Rebake.
[wxWidgets.git] / samples / ipc / baseserver.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: samples/ipc/baseserver.cpp
3 // Purpose: IPC sample: console server
4 // Author: Anders Larsen
5 // Most of the code was stolen from: samples/ipc/server.cpp
6 // (c) Julian Smart, Jurgen Doornik
7 // Created: 2007-11-08
8 // RCS-ID: $Id$
9 // Copyright: (c) 2007 Anders Larsen
10 // License: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #ifndef WX_PRECOMP
29 #include "wx/wx.h"
30 #endif
31
32 // Settings common to both executables: determines whether
33 // we're using TCP/IP or real DDE.
34 #include "ipcsetup.h"
35
36 #include "connection.h"
37
38 #include "wx/timer.h"
39 #include "wx/datetime.h"
40
41 // ----------------------------------------------------------------------------
42 // local classes
43 // ----------------------------------------------------------------------------
44
45 // a simple connection class testing and logging various operations
46 class MyConnection : public MyConnectionBase, public wxTimer
47 {
48 public:
49 virtual bool Disconnect() { return wxConnection::Disconnect(); }
50 virtual bool OnExecute(const wxString& topic,
51 const void *data,
52 size_t size,
53 wxIPCFormat format);
54 virtual const void *OnRequest(const wxString& topic,
55 const wxString& item,
56 size_t *size,
57 wxIPCFormat format);
58 virtual bool OnPoke(const wxString& topic,
59 const wxString& item,
60 const void *data,
61 size_t size,
62 wxIPCFormat format);
63 virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
64 virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
65 virtual bool DoAdvise(const wxString& item,
66 const void *data,
67 size_t size,
68 wxIPCFormat format);
69 virtual bool OnDisconnect();
70 virtual void Notify();
71
72 private:
73 wxString m_sAdvise;
74
75 wxString m_sRequestDate;
76 char m_achRequestBytes[3];
77 };
78
79 // a connection used for benchmarking some IPC operations by
80 // tests/benchmarks/ipcclient.cpp
81 class BenchConnection : public wxConnection
82 {
83 public:
84 BenchConnection() { m_advise = false; }
85
86 virtual bool OnPoke(const wxString& topic,
87 const wxString& item,
88 const void *data,
89 size_t size,
90 wxIPCFormat format);
91 virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
92 virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
93
94 private:
95 // return true if this is the supported topic+item combination, log an
96 // error message otherwise
97 bool IsSupportedTopicAndItem(const wxString& operation,
98 const wxString& topic,
99 const wxString& item) const;
100
101 // the item which can be manipulated by the client via Poke() calls
102 wxString m_item;
103
104 // should we notify the client about changes to m_item?
105 bool m_advise;
106
107 wxDECLARE_NO_COPY_CLASS(BenchConnection);
108 };
109
110 // a simple server accepting connections to IPC_TOPIC and IPC_BENCHMARK_TOPIC
111 class MyServer : public wxServer
112 {
113 public:
114 MyServer();
115 virtual ~MyServer();
116 void Disconnect();
117 bool IsConnected() { return m_connection != NULL; };
118
119 virtual wxConnectionBase *OnAcceptConnection(const wxString& topic);
120
121 private:
122 wxConnection *m_connection;
123 };
124
125 // Define a new application
126 class MyApp : public wxApp
127 {
128 public:
129 virtual bool OnInit();
130
131 protected:
132 MyServer m_server;
133 };
134
135 DECLARE_APP(MyApp)
136
137 // ============================================================================
138 // implementation
139 // ============================================================================
140
141 IMPLEMENT_APP_CONSOLE(MyApp)
142
143 // ----------------------------------------------------------------------------
144 // MyApp
145 // ----------------------------------------------------------------------------
146
147 bool MyApp::OnInit()
148 {
149 if ( !wxApp::OnInit() )
150 return false;
151
152 delete wxLog::SetActiveTarget(new wxLogStderr);
153
154 const char * const kind =
155 #if wxUSE_DDE_FOR_IPC
156 "DDE"
157 #else
158 "TCP"
159 #endif
160 ;
161
162 // Create a new server
163 if ( !m_server.Create(IPC_SERVICE) )
164 {
165 wxLogMessage("%s server failed to start on %s", kind, IPC_SERVICE);
166 return false;
167 }
168
169 wxLogMessage("%s server started on %s", kind, IPC_SERVICE);
170 return true;
171 }
172
173 // ----------------------------------------------------------------------------
174 // MyServer
175 // ----------------------------------------------------------------------------
176
177 MyServer::MyServer()
178 {
179 m_connection = NULL;
180 }
181
182 MyServer::~MyServer()
183 {
184 Disconnect();
185 }
186
187 wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
188 {
189 wxLogMessage("OnAcceptConnection(\"%s\")", topic);
190
191 if ( topic == IPC_TOPIC )
192 {
193 m_connection = new MyConnection;
194 }
195 else if ( topic == IPC_BENCHMARK_TOPIC )
196 {
197 m_connection = new BenchConnection;
198 }
199 else // unknown topic
200 {
201 wxLogMessage("Unknown topic");
202 return NULL;
203 }
204
205 wxLogMessage("Connection accepted");
206 return m_connection;
207 }
208
209 void MyServer::Disconnect()
210 {
211 if ( m_connection )
212 {
213 m_connection->Disconnect();
214 delete m_connection;
215 m_connection = NULL;
216 wxLogMessage("Disconnected client");
217 }
218 }
219
220 // ----------------------------------------------------------------------------
221 // MyConnection
222 // ----------------------------------------------------------------------------
223
224 bool
225 MyConnection::OnExecute(const wxString& topic,
226 const void *data,
227 size_t size,
228 wxIPCFormat format)
229 {
230 Log("OnExecute", topic, "", data, size, format);
231 return true;
232 }
233
234 bool
235 MyConnection::OnPoke(const wxString& topic,
236 const wxString& item,
237 const void *data,
238 size_t size,
239 wxIPCFormat format)
240 {
241 Log("OnPoke", topic, item, data, size, format);
242 return wxConnection::OnPoke(topic, item, data, size, format);
243 }
244
245 const void *
246 MyConnection::OnRequest(const wxString& topic,
247 const wxString& item,
248 size_t *size,
249 wxIPCFormat format)
250 {
251 const void *data;
252 if (item == "Date")
253 {
254 m_sRequestDate = wxDateTime::Now().Format();
255 data = m_sRequestDate.c_str();
256 *size = wxNO_LEN;
257 }
258 else if (item == "Date+len")
259 {
260 m_sRequestDate = wxDateTime::Now().FormatTime() +
261 " " + wxDateTime::Now().FormatDate();
262 data = m_sRequestDate.c_str();
263 *size = m_sRequestDate.Length() + 1;
264 }
265 else if (item == "bytes[3]")
266 {
267 data = m_achRequestBytes;
268 m_achRequestBytes[0] = '1';
269 m_achRequestBytes[1] = '2';
270 m_achRequestBytes[2] = '3';
271 *size = 3;
272 }
273 else
274 {
275 data = NULL;
276 *size = 0;
277 }
278 Log("OnRequest", topic, item, data, *size, format);
279 return data;
280 }
281
282 bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item)
283 {
284 wxLogMessage("OnStartAdvise(\"%s\",\"%s\")", topic, item);
285 wxLogMessage("Returning true");
286 m_sAdvise = item;
287 Start(3000); // schedule our Notify() to be called in 3 seconds
288 return true;
289 }
290
291 bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item)
292 {
293 wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item);
294 wxLogMessage("Returning true");
295 m_sAdvise.clear();
296 Stop();
297 return true;
298 }
299
300 void MyConnection::Notify()
301 {
302 if (!m_sAdvise.empty())
303 {
304 wxString s = wxDateTime::Now().Format();
305 Advise(m_sAdvise, s);
306 s = wxDateTime::Now().FormatTime() + " "
307 + wxDateTime::Now().FormatDate();
308 Advise(m_sAdvise, s.mb_str(), s.length() + 1);
309
310 #if wxUSE_DDE_FOR_IPC
311 wxLogMessage("DDE Advise type argument cannot be wxIPC_PRIVATE. "
312 "The client will receive it as wxIPC_TEXT, "
313 "and receive the correct no of bytes, "
314 "but not print a correct log entry.");
315 #endif // DDE
316
317 char bytes[3];
318 bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
319 Advise(m_sAdvise, bytes, 3, wxIPC_PRIVATE);
320 // this works, but the log treats it as a string now
321 // m_connection->Advise(m_connection->m_sAdvise, bytes, 3, wxIPC_TEXT );
322 }
323 }
324
325 bool MyConnection::DoAdvise(const wxString& item,
326 const void *data,
327 size_t size,
328 wxIPCFormat format)
329 {
330 Log("Advise", "", item, data, size, format);
331 return wxConnection::DoAdvise(item, data, size, format);
332 }
333
334 bool MyConnection::OnDisconnect()
335 {
336 wxLogMessage("OnDisconnect()");
337 return true;
338 }
339
340 // ----------------------------------------------------------------------------
341 // BenchConnection
342 // ----------------------------------------------------------------------------
343
344 bool BenchConnection::IsSupportedTopicAndItem(const wxString& operation,
345 const wxString& topic,
346 const wxString& item) const
347 {
348 if ( topic != IPC_BENCHMARK_TOPIC ||
349 item != IPC_BENCHMARK_ITEM )
350 {
351 wxLogMessage("Unexpected %s(\"%s\", \"%s\") call.",
352 operation, topic, item);
353 return false;
354 }
355
356 return true;
357 }
358
359 bool BenchConnection::OnPoke(const wxString& topic,
360 const wxString& item,
361 const void *data,
362 size_t size,
363 wxIPCFormat format)
364 {
365 if ( !IsSupportedTopicAndItem("OnPoke", topic, item) )
366 return false;
367
368 if ( !IsTextFormat(format) )
369 {
370 wxLogMessage("Unexpected format %d in OnPoke().", format);
371 return false;
372 }
373
374 m_item = GetTextFromData(data, size, format);
375
376 if ( m_advise )
377 {
378 if ( !Advise(item, m_item) )
379 {
380 wxLogMessage("Failed to advise client about the change.");
381 }
382 }
383
384 return true;
385 }
386
387 bool BenchConnection::OnStartAdvise(const wxString& topic, const wxString& item)
388 {
389 if ( !IsSupportedTopicAndItem("OnStartAdvise", topic, item) )
390 return false;
391
392 m_advise = true;
393
394 return true;
395 }
396
397 bool BenchConnection::OnStopAdvise(const wxString& topic, const wxString& item)
398 {
399 if ( !IsSupportedTopicAndItem("OnStopAdvise", topic, item) )
400 return false;
401
402 m_advise = false;
403
404 return true;
405 }
406