]> git.saurik.com Git - wxWidgets.git/blob - samples/ipc/server.cpp
prevent infinite loop if gtk_menu_popup() fails, fixes #15387
[wxWidgets.git] / samples / ipc / server.cpp
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
46 IMPLEMENT_APP(MyApp)
47
48 BEGIN_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 )
55 END_EVENT_TABLE()
56
57
58 // ============================================================================
59 // implementation
60 // ============================================================================
61
62 // ----------------------------------------------------------------------------
63 // MyApp
64 // ----------------------------------------------------------------------------
65
66 bool 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
83 MyFrame::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
152 void 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
160 void MyFrame::OnClose(wxCloseEvent& event)
161 {
162 wxDELETE(m_server);
163 event.Skip();
164 }
165
166 void 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
188 void 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
208 void MyFrame::Disconnect()
209 {
210 m_server->Disconnect();
211 UpdateUI();
212 }
213
214 void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event))
215 {
216 Disconnect();
217 }
218
219 void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event))
220 {
221 m_server->Advise();
222 }
223
224 // ----------------------------------------------------------------------------
225 // MyServer
226 // ----------------------------------------------------------------------------
227
228 MyServer::MyServer() : wxServer()
229 {
230 m_connection = NULL;
231 }
232
233 MyServer::~MyServer()
234 {
235 Disconnect();
236 }
237
238 wxConnectionBase *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
255 void MyServer::Disconnect()
256 {
257 if ( m_connection )
258 {
259 wxDELETE(m_connection);
260 wxGetApp().GetFrame()->UpdateUI();
261 wxLogMessage("Disconnected client");
262 }
263 }
264
265 void 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
291 bool
292 MyConnection::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
301 bool
302 MyConnection::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
312 const void *
313 MyConnection::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
357 bool 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
366 bool 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
375 bool
376 MyConnection::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
385 bool MyConnection::OnDisconnect()
386 {
387 wxLogMessage("OnDisconnect()");
388 wxGetApp().GetFrame()->Disconnect();
389 return true;
390 }