]>
Commit | Line | Data |
---|---|---|
ebe887ed VZ |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: samples/ipc/baseclient.cpp | |
3 | // Purpose: IPC sample: console client | |
4 | // Author: Anders Larsen | |
5 | // Most of the code was stolen from: samples/ipc/client.cpp | |
6 | // (c) Julian Smart, Jurgen Doornik | |
7 | // Created: 2007-11-08 | |
8 | // RCS-ID: $Id$ | |
9 | // Copyright: (c) 2007 Anders Larsen | |
526954c5 | 10 | // Licence: wxWindows licence |
ebe887ed VZ |
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 | ||
521d3436 VZ |
36 | #include "connection.h" |
37 | ||
ebe887ed VZ |
38 | #include "wx/timer.h" |
39 | #include "wx/datetime.h" | |
05b93327 VZ |
40 | #include "wx/vector.h" |
41 | ||
42 | class MyClient; | |
ebe887ed VZ |
43 | |
44 | // ---------------------------------------------------------------------------- | |
05b93327 | 45 | // classes |
ebe887ed VZ |
46 | // ---------------------------------------------------------------------------- |
47 | ||
05b93327 | 48 | class MyApp : public wxApp |
ebe887ed VZ |
49 | { |
50 | public: | |
05b93327 VZ |
51 | MyApp() { Connect(wxEVT_IDLE, wxIdleEventHandler(MyApp::OnIdle)); } |
52 | ||
ebe887ed VZ |
53 | virtual bool OnInit(); |
54 | virtual int OnExit(); | |
55 | ||
05b93327 VZ |
56 | private: |
57 | void OnIdle(wxIdleEvent& event); | |
58 | ||
59 | MyClient *m_client; | |
ebe887ed VZ |
60 | }; |
61 | ||
521d3436 | 62 | class MyConnection : public MyConnectionBase |
ebe887ed VZ |
63 | { |
64 | public: | |
ebe887ed VZ |
65 | virtual bool DoExecute(const void *data, size_t size, wxIPCFormat format); |
66 | virtual const void *Request(const wxString& item, size_t *size = NULL, wxIPCFormat format = wxIPC_TEXT); | |
67 | virtual bool DoPoke(const wxString& item, const void* data, size_t size, wxIPCFormat format); | |
68 | virtual bool OnAdvise(const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format); | |
69 | virtual bool OnDisconnect(); | |
ebe887ed VZ |
70 | }; |
71 | ||
05b93327 VZ |
72 | class MyClient : public wxClient, |
73 | private wxTimer | |
ebe887ed VZ |
74 | { |
75 | public: | |
76 | MyClient(); | |
77 | virtual ~MyClient(); | |
05b93327 | 78 | |
ebe887ed VZ |
79 | bool Connect(const wxString& sHost, const wxString& sService, const wxString& sTopic); |
80 | void Disconnect(); | |
81 | wxConnectionBase *OnMakeConnection(); | |
82 | bool IsConnected() { return m_connection != NULL; }; | |
05b93327 | 83 | |
ebe887ed VZ |
84 | virtual void Notify(); |
85 | ||
05b93327 VZ |
86 | void StartNextTestIfNecessary(); |
87 | ||
88 | private: | |
89 | void TestRequest(); | |
90 | void TestPoke(); | |
91 | void TestExecute(); | |
92 | void TestStartAdvise(); | |
93 | void TestStopAdvise(); | |
94 | void TestDisconnect(); | |
95 | ||
96 | ||
97 | MyConnection *m_connection; | |
98 | ||
99 | // the test functions to be executed by StartNextTestIfNecessary() | |
100 | typedef void (MyClient::*MyClientTestFunc)(); | |
101 | wxVector<MyClientTestFunc> m_tests; | |
102 | ||
103 | // number of seconds since the start of the test | |
104 | int m_step; | |
ebe887ed VZ |
105 | }; |
106 | ||
107 | // ============================================================================ | |
108 | // implementation | |
109 | // ============================================================================ | |
110 | ||
2e334012 | 111 | IMPLEMENT_APP_CONSOLE(MyApp) |
ebe887ed VZ |
112 | |
113 | // ---------------------------------------------------------------------------- | |
114 | // MyApp | |
115 | // ---------------------------------------------------------------------------- | |
116 | ||
117 | // The `main program' equivalent, creating the windows and returning the | |
118 | // main frame | |
119 | bool MyApp::OnInit() | |
120 | { | |
121 | if ( !wxApp::OnInit() ) | |
122 | return false; | |
123 | ||
ebe887ed VZ |
124 | // Create a new client |
125 | m_client = new MyClient; | |
126 | bool retval = m_client->Connect("localhost", "4242", "IPC TEST"); | |
127 | ||
05b93327 VZ |
128 | wxLogMessage("Client host=\"localhost\" port=\"4242\" topic=\"IPC TEST\" %s", |
129 | retval ? "connected" : "failed to connect"); | |
ebe887ed VZ |
130 | |
131 | return retval; | |
132 | } | |
133 | ||
134 | int MyApp::OnExit() | |
135 | { | |
136 | delete m_client; | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
05b93327 VZ |
141 | void MyApp::OnIdle(wxIdleEvent& event) |
142 | { | |
143 | if ( m_client ) | |
144 | m_client->StartNextTestIfNecessary(); | |
145 | ||
146 | event.Skip(); | |
147 | } | |
148 | ||
ebe887ed VZ |
149 | // ---------------------------------------------------------------------------- |
150 | // MyClient | |
151 | // ---------------------------------------------------------------------------- | |
152 | ||
05b93327 VZ |
153 | MyClient::MyClient() |
154 | : wxClient() | |
ebe887ed VZ |
155 | { |
156 | m_connection = NULL; | |
157 | m_step = 0; | |
158 | } | |
159 | ||
05b93327 VZ |
160 | bool |
161 | MyClient::Connect(const wxString& sHost, | |
162 | const wxString& sService, | |
163 | const wxString& sTopic) | |
ebe887ed VZ |
164 | { |
165 | // suppress the log messages from MakeConnection() | |
166 | wxLogNull nolog; | |
167 | ||
168 | m_connection = (MyConnection *)MakeConnection(sHost, sService, sTopic); | |
05b93327 VZ |
169 | if ( !m_connection ) |
170 | return false; | |
171 | ||
172 | Start(1000); | |
173 | ||
174 | return true; | |
ebe887ed VZ |
175 | } |
176 | ||
177 | wxConnectionBase *MyClient::OnMakeConnection() | |
178 | { | |
179 | return new MyConnection; | |
180 | } | |
181 | ||
182 | void MyClient::Disconnect() | |
183 | { | |
184 | if (m_connection) | |
185 | { | |
186 | m_connection->Disconnect(); | |
5276b0a5 | 187 | wxDELETE(m_connection); |
05b93327 | 188 | wxLogMessage("Client disconnected from server"); |
ebe887ed VZ |
189 | } |
190 | wxGetApp().ExitMainLoop(); | |
191 | } | |
192 | ||
193 | MyClient::~MyClient() | |
194 | { | |
195 | Disconnect(); | |
196 | } | |
197 | ||
198 | void MyClient::Notify() | |
199 | { | |
05b93327 VZ |
200 | // we shouldn't call wxIPC methods from here directly as we may be called |
201 | // from inside an IPC call when using TCP/IP as the sockets are used in | |
202 | // non-blocking code and so can dispatch events, including the timer ones, | |
203 | // while waiting for IO and so starting another IPC call would result in | |
204 | // fatal reentrancies -- instead, just set a flag and perform the test | |
205 | // indicated by it later from our idle event handler | |
206 | MyClientTestFunc testfunc = NULL; | |
207 | switch ( m_step++ ) | |
ebe887ed VZ |
208 | { |
209 | case 0: | |
05b93327 | 210 | testfunc = &MyClient::TestRequest; |
ebe887ed | 211 | break; |
05b93327 | 212 | |
ebe887ed | 213 | case 1: |
05b93327 | 214 | testfunc = &MyClient::TestPoke; |
ebe887ed | 215 | break; |
05b93327 | 216 | |
ebe887ed | 217 | case 2: |
05b93327 | 218 | testfunc = &MyClient::TestExecute; |
ebe887ed | 219 | break; |
05b93327 | 220 | |
ebe887ed | 221 | case 3: |
05b93327 | 222 | testfunc = &MyClient::TestStartAdvise; |
ebe887ed | 223 | break; |
05b93327 | 224 | |
ebe887ed | 225 | case 10: |
05b93327 | 226 | testfunc = &MyClient::TestStopAdvise; |
ebe887ed | 227 | break; |
05b93327 | 228 | |
ebe887ed | 229 | case 15: |
05b93327 | 230 | testfunc = &MyClient::TestDisconnect; |
67eca664 VZ |
231 | // We don't need the timer any more, we're going to exit soon. |
232 | Stop(); | |
ebe887ed | 233 | break; |
67eca664 VZ |
234 | |
235 | default: | |
236 | // No need to wake up idle handling. | |
237 | return; | |
ebe887ed | 238 | } |
05b93327 | 239 | |
67eca664 | 240 | m_tests.push_back(testfunc); |
05b93327 VZ |
241 | |
242 | wxWakeUpIdle(); | |
243 | } | |
244 | ||
245 | void MyClient::StartNextTestIfNecessary() | |
246 | { | |
67eca664 | 247 | while ( !m_tests.empty() ) |
05b93327 VZ |
248 | { |
249 | MyClientTestFunc testfunc = m_tests.front(); | |
250 | m_tests.erase(m_tests.begin()); | |
251 | (this->*testfunc)(); | |
252 | } | |
253 | } | |
254 | ||
255 | void MyClient::TestRequest() | |
256 | { | |
257 | size_t size; | |
258 | m_connection->Request("Date"); | |
259 | m_connection->Request("Date+len", &size); | |
260 | m_connection->Request("bytes[3]", &size, wxIPC_PRIVATE); | |
261 | } | |
262 | ||
263 | void MyClient::TestPoke() | |
264 | { | |
265 | wxString s = wxDateTime::Now().Format(); | |
266 | m_connection->Poke("Date", s); | |
267 | s = wxDateTime::Now().FormatTime() + " " + wxDateTime::Now().FormatDate(); | |
268 | m_connection->Poke("Date", (const char *)s.c_str(), s.length() + 1); | |
269 | char bytes[3]; | |
270 | bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3'; | |
271 | m_connection->Poke("bytes[3]", bytes, 3, wxIPC_PRIVATE); | |
272 | } | |
273 | ||
274 | void MyClient::TestExecute() | |
275 | { | |
276 | wxString s = "Date"; | |
277 | m_connection->Execute(s); | |
278 | m_connection->Execute((const char *)s.c_str(), s.length() + 1); | |
279 | char bytes[3]; | |
280 | bytes[0] = '1'; | |
281 | bytes[1] = '2'; | |
282 | bytes[2] = '3'; | |
283 | m_connection->Execute(bytes, WXSIZEOF(bytes)); | |
284 | } | |
285 | ||
286 | void MyClient::TestStartAdvise() | |
287 | { | |
288 | wxLogMessage("StartAdvise(\"something\")"); | |
289 | m_connection->StartAdvise("something"); | |
290 | } | |
291 | ||
292 | void MyClient::TestStopAdvise() | |
293 | { | |
294 | wxLogMessage("StopAdvise(\"something\")"); | |
295 | m_connection->StopAdvise("something"); | |
296 | } | |
297 | ||
298 | void MyClient::TestDisconnect() | |
299 | { | |
300 | Disconnect(); | |
ebe887ed VZ |
301 | } |
302 | ||
303 | // ---------------------------------------------------------------------------- | |
304 | // MyConnection | |
305 | // ---------------------------------------------------------------------------- | |
306 | ||
ebe887ed VZ |
307 | bool MyConnection::OnAdvise(const wxString& topic, const wxString& item, const void *data, |
308 | size_t size, wxIPCFormat format) | |
309 | { | |
05b93327 | 310 | Log("OnAdvise", topic, item, data, size, format); |
ebe887ed VZ |
311 | return true; |
312 | } | |
313 | ||
314 | bool MyConnection::OnDisconnect() | |
315 | { | |
05b93327 | 316 | wxLogMessage("OnDisconnect()"); |
ebe887ed VZ |
317 | wxGetApp().ExitMainLoop(); |
318 | return true; | |
319 | } | |
320 | ||
321 | bool MyConnection::DoExecute(const void *data, size_t size, wxIPCFormat format) | |
322 | { | |
05b93327 | 323 | Log("Execute", wxEmptyString, wxEmptyString, data, size, format); |
ebe887ed VZ |
324 | bool retval = wxConnection::DoExecute(data, size, format); |
325 | if (!retval) | |
43b2d5e7 | 326 | { |
05b93327 | 327 | wxLogMessage("Execute failed!"); |
43b2d5e7 | 328 | } |
ebe887ed VZ |
329 | return retval; |
330 | } | |
331 | ||
332 | const void *MyConnection::Request(const wxString& item, size_t *size, wxIPCFormat format) | |
333 | { | |
334 | const void *data = wxConnection::Request(item, size, format); | |
05b93327 | 335 | Log("Request", wxEmptyString, item, data, size ? *size : wxNO_LEN, format); |
ebe887ed VZ |
336 | return data; |
337 | } | |
338 | ||
339 | bool MyConnection::DoPoke(const wxString& item, const void *data, size_t size, wxIPCFormat format) | |
340 | { | |
05b93327 | 341 | Log("Poke", wxEmptyString, item, data, size, format); |
ebe887ed VZ |
342 | return wxConnection::DoPoke(item, data, size, format); |
343 | } |