]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/ipc/server.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / samples / ipc / server.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: server.cpp
3// Purpose: IPC sample: server
4// Author: Julian Smart
5// Modified by: Jurgen Doornik
6// Created: 25/01/99
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/wx.h"
28#endif
29
30// Settings common to both executables: determines whether
31// we're using TCP/IP or real DDE.
32#include "ipcsetup.h"
33
34#ifndef wxHAS_IMAGES_IN_RESOURCES
35 #include "../sample.xpm"
36#endif
37
38#include "server.h"
39#include "wx/textdlg.h"
40#include "wx/datetime.h"
41
42// ----------------------------------------------------------------------------
43// wxWin macros
44// ----------------------------------------------------------------------------
45
46IMPLEMENT_APP(MyApp)
47
48BEGIN_EVENT_TABLE(MyFrame, wxFrame)
49 EVT_CLOSE( MyFrame::OnClose )
50
51 EVT_BUTTON( ID_START, MyFrame::OnStart )
52 EVT_CHOICE( ID_SERVERNAME, MyFrame::OnServerName )
53 EVT_BUTTON( ID_DISCONNECT, MyFrame::OnDisconnect )
54 EVT_BUTTON( ID_ADVISE, MyFrame::OnAdvise )
55END_EVENT_TABLE()
56
57
58// ============================================================================
59// implementation
60// ============================================================================
61
62// ----------------------------------------------------------------------------
63// MyApp
64// ----------------------------------------------------------------------------
65
66bool MyApp::OnInit()
67{
68 if ( !wxApp::OnInit() )
69 return false;
70
71 // Create the main frame window
72 m_frame = new MyFrame(NULL, "Server");
73 m_frame->Show(true);
74
75 return true;
76}
77
78// ----------------------------------------------------------------------------
79// MyFrame
80// ----------------------------------------------------------------------------
81
82// Define my frame constructor
83MyFrame::MyFrame(wxFrame *frame, const wxString& title)
84 : wxFrame(frame, wxID_ANY, title, wxDefaultPosition, wxSize(400, 300))
85{
86#if wxUSE_STATUSBAR
87 CreateStatusBar();
88#endif // wxUSE_STATUSBAR
89
90 SetIcon(wxICON(sample));
91
92 m_server = NULL;
93
94 wxPanel * const panel = new wxPanel(this);
95
96 wxBoxSizer * const sizerMain = new wxBoxSizer( wxVERTICAL );
97
98 wxFlexGridSizer * const sizerCmds = new wxFlexGridSizer( 2, 0, 0 );
99 sizerCmds->AddGrowableCol( 1 );
100
101 wxButton *btn;
102
103 btn = new wxButton(panel, ID_START, "&Start Server");
104 sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
105
106 const wxString choices[] = { IPC_SERVICE, "..." };
107 wxChoice * const choice = new wxChoice
108 (
109 panel,
110 ID_SERVERNAME,
111 wxDefaultPosition, wxSize(100, -1),
112 WXSIZEOF(choices), choices
113 );
114 sizerCmds->Add(choice, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
115
116 btn = new wxButton(panel, ID_DISCONNECT, "&Disconnect Client");
117 sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
118 sizerCmds->AddSpacer(20);
119
120 btn = new wxButton( panel, ID_ADVISE, "&Advise");
121 sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
122 sizerCmds->AddSpacer(20);
123
124 sizerMain->Add(sizerCmds, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
125
126 wxStaticBoxSizer * const
127 sizerLog = new wxStaticBoxSizer(wxVERTICAL, panel, "Server &log");
128
129 wxTextCtrl * const textLog = new wxTextCtrl
130 (
131 panel,
132 wxID_ANY,
133 "",
134 wxDefaultPosition, wxSize(500, 140),
135 wxTE_MULTILINE
136 );
137 sizerLog->Add(textLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
138
139 sizerMain->Add(sizerLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
140
141 panel->SetSizer(sizerMain);
142 sizerMain->SetSizeHints(panel);
143 SetClientSize(panel->GetSize());
144
145 GetServername()->SetSelection(0);
146 wxLogTextCtrl *logWindow = new wxLogTextCtrl(textLog);
147 delete wxLog::SetActiveTarget(logWindow);
148 wxLogMessage("Click on Start to start the server");
149 UpdateUI();
150}
151
152void MyFrame::UpdateUI()
153{
154 GetStart()->Enable(m_server == NULL);
155 GetServername()->Enable(m_server == NULL);
156 GetAdvise()->Enable(m_server && m_server->CanAdvise());
157 GetDisconnect()->Enable(m_server && m_server->IsConnected());
158}
159
160void MyFrame::OnClose(wxCloseEvent& event)
161{
162 wxDELETE(m_server);
163 event.Skip();
164}
165
166void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event))
167{
168 // Create a new server
169 m_server = new MyServer;
170 wxString servername = GetServername()->GetStringSelection();
171 if (m_server->Create(servername))
172 {
173 wxLogMessage("Server %s started", servername);
174 #if wxUSE_DDE_FOR_IPC
175 wxLogMessage("Server uses DDE");
176 #else // !wxUSE_DDE_FOR_IPC
177 wxLogMessage("Server uses TCP");
178 #endif // wxUSE_DDE_FOR_IPC/!wxUSE_DDE_FOR_IPC
179 }
180 else
181 {
182 wxLogMessage("Server %s failed to start", servername);
183 wxDELETE(m_server);
184 }
185 UpdateUI();
186}
187
188void MyFrame::OnServerName( wxCommandEvent& WXUNUSED(event) )
189{
190 if ( GetServername()->GetStringSelection() == "..." )
191 {
192 wxString s = wxGetTextFromUser
193 (
194 "Specify the name of the server",
195 "Server Name",
196 "",
197 this
198 );
199
200 if ( !s.empty() && s != IPC_SERVICE )
201 {
202 GetServername()->Insert(s, 0);
203 GetServername()->SetSelection(0);
204 }
205 }
206}
207
208void MyFrame::Disconnect()
209{
210 m_server->Disconnect();
211 UpdateUI();
212}
213
214void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event))
215{
216 Disconnect();
217}
218
219void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event))
220{
221 m_server->Advise();
222}
223
224// ----------------------------------------------------------------------------
225// MyServer
226// ----------------------------------------------------------------------------
227
228MyServer::MyServer() : wxServer()
229{
230 m_connection = NULL;
231}
232
233MyServer::~MyServer()
234{
235 Disconnect();
236}
237
238wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
239{
240 wxLogMessage("OnAcceptConnection(\"%s\")", topic);
241
242 if ( topic == IPC_TOPIC )
243 {
244 m_connection = new MyConnection();
245 wxGetApp().GetFrame()->UpdateUI();
246 wxLogMessage("Connection accepted");
247 return m_connection;
248 }
249 //else: unknown topic
250
251 wxLogMessage("Unknown topic, connection refused");
252 return NULL;
253}
254
255void MyServer::Disconnect()
256{
257 if ( m_connection )
258 {
259 wxDELETE(m_connection);
260 wxGetApp().GetFrame()->UpdateUI();
261 wxLogMessage("Disconnected client");
262 }
263}
264
265void MyServer::Advise()
266{
267 if ( CanAdvise() )
268 {
269 const wxDateTime now = wxDateTime::Now();
270
271 m_connection->Advise(m_connection->m_advise, now.Format());
272
273 const wxString s = now.FormatTime() + " " + now.FormatDate();
274 m_connection->Advise(m_connection->m_advise, s.mb_str(), wxNO_LEN);
275
276#if wxUSE_DDE_FOR_IPC
277 wxLogMessage("DDE Advise type argument cannot be wxIPC_PRIVATE. "
278 "The client will receive it as wxIPC_TEXT, "
279 " and receive the correct no of bytes, "
280 "but not print a correct log entry.");
281#endif
282 char bytes[3] = { '1', '2', '3' };
283 m_connection->Advise(m_connection->m_advise, bytes, 3, wxIPC_PRIVATE);
284 }
285}
286
287// ----------------------------------------------------------------------------
288// MyConnection
289// ----------------------------------------------------------------------------
290
291bool
292MyConnection::OnExecute(const wxString& topic,
293 const void *data,
294 size_t size,
295 wxIPCFormat format)
296{
297 Log("OnExecute", topic, "", data, size, format);
298 return true;
299}
300
301bool
302MyConnection::OnPoke(const wxString& topic,
303 const wxString& item,
304 const void *data,
305 size_t size,
306 wxIPCFormat format)
307{
308 Log("OnPoke", topic, item, data, size, format);
309 return wxConnection::OnPoke(topic, item, data, size, format);
310}
311
312const void *
313MyConnection::OnRequest(const wxString& topic,
314 const wxString& item,
315 size_t *size,
316 wxIPCFormat format)
317{
318 *size = 0;
319
320 wxString s,
321 afterDate;
322 if ( item.StartsWith("Date", &afterDate) )
323 {
324 const wxDateTime now = wxDateTime::Now();
325
326 if ( afterDate.empty() )
327 {
328 s = now.Format();
329 *size = wxNO_LEN;
330 }
331 else if ( afterDate == "+len" )
332 {
333 s = now.FormatTime() + " " + now.FormatDate();
334 *size = strlen(s.mb_str()) + 1;
335 }
336 }
337 else if ( item == "bytes[3]" )
338 {
339 s = "123";
340 *size = 3;
341 }
342
343 if ( !*size )
344 {
345 wxLogMessage("Unknown request for \"%s\"", item);
346 return NULL;
347 }
348
349 // store the data pointer to which we return in a member variable to ensure
350 // that the pointer remains valid even after we return
351 m_requestData = s.mb_str();
352 const void * const data = m_requestData;
353 Log("OnRequest", topic, item, data, *size, format);
354 return data;
355}
356
357bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item)
358{
359 wxLogMessage("OnStartAdvise(\"%s\", \"%s\")", topic, item);
360 wxLogMessage("Returning true");
361 m_advise = item;
362 wxGetApp().GetFrame()->UpdateUI();
363 return true;
364}
365
366bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item)
367{
368 wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item);
369 wxLogMessage("Returning true");
370 m_advise.clear();
371 wxGetApp().GetFrame()->UpdateUI();
372 return true;
373}
374
375bool
376MyConnection::DoAdvise(const wxString& item,
377 const void *data,
378 size_t size,
379 wxIPCFormat format)
380{
381 Log("Advise", "", item, data, size, format);
382 return wxConnection::DoAdvise(item, data, size, format);
383}
384
385bool MyConnection::OnDisconnect()
386{
387 wxLogMessage("OnDisconnect()");
388 wxGetApp().GetFrame()->Disconnect();
389 return true;
390}