added console IPC sample (part of patch 1833150)
[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 "wx/timer.h"
37 #include "wx/datetime.h"
38
39 // ----------------------------------------------------------------------------
40 // wxWin macros
41 // ----------------------------------------------------------------------------
42
43 // Define a new application
44 class MyServer;
45 class MyConnection;
46
47 class MyApp : public wxApp
48 {
49 public:
50 virtual bool OnInit();
51 virtual int OnExit();
52
53 protected:
54 MyServer *m_server;
55 };
56
57 DECLARE_APP(MyApp)
58
59 class MyConnection : public wxConnection, public wxTimer
60 {
61 public:
62 MyConnection();
63 virtual ~MyConnection();
64
65 virtual bool Disconnect() { return wxConnection::Disconnect(); }
66 virtual bool OnExecute(const wxString& topic, const void *data, size_t size, wxIPCFormat format);
67 virtual const void *OnRequest(const wxString& topic, const wxString& item, size_t *size, wxIPCFormat format);
68 virtual bool OnPoke(const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format);
69 virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
70 virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
71 virtual bool DoAdvise(const wxString& item, const void *data, size_t size, wxIPCFormat format);
72 virtual bool OnDisconnect();
73 virtual void Notify();
74
75 protected:
76 void Log(const wxString& command, const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format);
77
78 public:
79 wxString m_sAdvise;
80
81 protected:
82 wxString m_sRequestDate;
83 char m_achRequestBytes[3];
84 };
85
86 class MyServer: public wxServer
87 {
88 public:
89 MyServer();
90 virtual ~MyServer();
91 void Disconnect();
92 bool IsConnected() { return m_connection != NULL; };
93 MyConnection *GetConnection() { return m_connection; };
94 wxConnectionBase *OnAcceptConnection(const wxString& topic);
95
96 protected:
97 MyConnection *m_connection;
98 };
99
100 // ============================================================================
101 // implementation
102 // ============================================================================
103
104 IMPLEMENT_APP(MyApp)
105
106 // ----------------------------------------------------------------------------
107 // MyApp
108 // ----------------------------------------------------------------------------
109
110 bool MyApp::OnInit()
111 {
112 if ( !wxApp::OnInit() )
113 return false;
114
115 delete wxLog::SetActiveTarget(new wxLogStderr);
116
117 // Create a new server
118 m_server = new MyServer;
119 if (m_server->Create("4242"))
120 {
121 wxLogMessage(_T("Server 4242 started"));
122 #if wxUSE_DDE_FOR_IPC
123 wxLogMessage(_T("Server uses DDE"));
124 #else // !wxUSE_DDE_FOR_IPC
125 wxLogMessage(_T("Server uses TCP"));
126 #endif // wxUSE_DDE_FOR_IPC/!wxUSE_DDE_FOR_IPC
127 return true;
128 }
129 else
130 {
131 wxLogMessage(_T("Server 4242 failed to start"));
132 delete m_server;
133 return false;
134 }
135 }
136
137 int MyApp::OnExit()
138 {
139 return 0;
140 }
141
142 // ----------------------------------------------------------------------------
143 // MyServer
144 // ----------------------------------------------------------------------------
145
146 MyServer::MyServer()
147 {
148 m_connection = NULL;
149 }
150
151 MyServer::~MyServer()
152 {
153 Disconnect();
154 }
155
156 wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
157 {
158 wxLogMessage(_T("OnAcceptConnection(\"%s\")"), topic.c_str());
159
160 if ( topic == IPC_TOPIC )
161 {
162 m_connection = new MyConnection;
163 wxLogMessage(_T("Connection accepted"));
164 return m_connection;
165 }
166 // unknown topic
167 return NULL;
168 }
169
170 void MyServer::Disconnect()
171 {
172 if (m_connection)
173 {
174 m_connection->Disconnect();
175 delete m_connection;
176 m_connection = NULL;
177 wxLogMessage(_T("Disconnected client"));
178 }
179 }
180
181 // ----------------------------------------------------------------------------
182 // MyConnection
183 // ----------------------------------------------------------------------------
184
185 MyConnection::MyConnection()
186 {
187 }
188
189 MyConnection::~MyConnection()
190 {
191 }
192
193 bool MyConnection::OnExecute(const wxString& topic,
194 const void *data, size_t size, wxIPCFormat format)
195 {
196 Log(_T("OnExecute"), topic, _T(""), data, size, format);
197 return true;
198 }
199
200 bool MyConnection::OnPoke(const wxString& topic,
201 const wxString& item, const void *data, size_t size, wxIPCFormat format)
202 {
203 Log(_T("OnPoke"), topic, item, data, size, format);
204 return wxConnection::OnPoke(topic, item, data, size, format);
205 }
206
207 const void *MyConnection::OnRequest(const wxString& topic,
208 const wxString& item, size_t *size, wxIPCFormat format)
209 {
210 const void *data;
211 if (item == _T("Date"))
212 {
213 m_sRequestDate = wxDateTime::Now().Format();
214 data = m_sRequestDate.c_str();
215 *size = wxNO_LEN;
216 }
217 else if (item == _T("Date+len"))
218 {
219 m_sRequestDate = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
220 data = m_sRequestDate.c_str();
221 *size = m_sRequestDate.Length() + 1;
222 }
223 else if (item == _T("bytes[3]"))
224 {
225 data = m_achRequestBytes;
226 m_achRequestBytes[0] = '1'; m_achRequestBytes[1] = '2'; m_achRequestBytes[2] = '3';
227 *size = 3;
228 }
229 else
230 {
231 data = NULL;
232 *size = 0;
233 }
234 Log(_T("OnRequest"), topic, item, data, *size, format);
235 return data;
236 }
237
238 bool MyConnection::OnStartAdvise(const wxString& topic,
239 const wxString& item)
240 {
241 wxLogMessage(_T("OnStartAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str());
242 wxLogMessage(_T("Returning true"));
243 m_sAdvise = item;
244 Start(3000, false);
245 return true;
246 }
247
248 bool MyConnection::OnStopAdvise(const wxString& topic,
249 const wxString& item)
250 {
251 wxLogMessage(_T("OnStopAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str());
252 wxLogMessage(_T("Returning true"));
253 m_sAdvise.Empty();
254 Stop();
255 return true;
256 }
257
258 void MyConnection::Notify()
259 {
260 if (!m_sAdvise.IsEmpty())
261 {
262 wxString s = wxDateTime::Now().Format();
263 Advise(m_sAdvise, s);
264 s = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
265 Advise(m_sAdvise, (const char *)s.c_str(), s.Length() + 1);
266
267 #if wxUSE_DDE_FOR_IPC
268 wxLogMessage(_T("DDE Advise type argument cannot be wxIPC_PRIVATE. The client will receive it as wxIPC_TEXT, and receive the correct no of bytes, but not print a correct log entry."));
269 #endif
270 char bytes[3];
271 bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
272 Advise(m_sAdvise, bytes, 3, wxIPC_PRIVATE);
273 // this works, but the log treats it as a string now
274 // m_connection->Advise(m_connection->m_sAdvise, bytes, 3, wxIPC_TEXT );
275 }
276 }
277
278 void MyConnection::Log(const wxString& command, const wxString& topic,
279 const wxString& item, const void *data, size_t size, wxIPCFormat format)
280 {
281 wxString s;
282 if (topic.IsEmpty() && item.IsEmpty())
283 s.Printf(_T("%s("), command.c_str());
284 else if (topic.IsEmpty())
285 s.Printf(_T("%s(\"%s\","), command.c_str(), item.c_str());
286 else if (item.IsEmpty())
287 s.Printf(_T("%s(\"%s\","), command.c_str(), topic.c_str());
288 else
289 s.Printf(_T("%s(\"%s\",\"%s\","), command.c_str(), topic.c_str(), item.c_str());
290
291 switch (format)
292 {
293 case wxIPC_TEXT:
294 case wxIPC_UTF8TEXT:
295 #if !wxUSE_UNICODE || wxUSE_UNICODE_UTF8
296 wxLogMessage(_T("%s\"%s\",%d)"), s.c_str(), data, size);
297 #else
298 wxLogMessage(_T("%s\"%s\",%d)"), s.c_str(), wxConvUTF8.cMB2WC((const char*)data), size);
299 #endif
300 break;
301 case wxIPC_PRIVATE:
302 if (size == 3)
303 {
304 char *bytes = (char *)data;
305 wxLogMessage(_T("%s'%c%c%c',%d)"), s.c_str(), bytes[0], bytes[1], bytes[2], size);
306 }
307 else
308 wxLogMessage(_T("%s...,%d)"), s.c_str(), size);
309 break;
310 case wxIPC_INVALID:
311 wxLogMessage(_T("%s[invalid data],%d)"), s.c_str(), size);
312 break;
313 default:
314 wxLogMessage(_T("%s[unknown data],%d)"), s.c_str(), size);
315 break;
316 }
317 }
318
319 bool MyConnection::DoAdvise(const wxString& item, const void *data, size_t size, wxIPCFormat format)
320 {
321 Log(_T("Advise"), _T(""), item, data, size, format);
322 return wxConnection::DoAdvise(item, data, size, format);
323 }
324
325 bool MyConnection::OnDisconnect()
326 {
327 wxLogMessage(_T("OnDisconnect()"));
328 return true;
329 }