]>
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 | |
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 | ||
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(); | |
187 | delete m_connection; | |
188 | m_connection = NULL; | |
05b93327 | 189 | wxLogMessage("Client disconnected from server"); |
ebe887ed VZ |
190 | } |
191 | wxGetApp().ExitMainLoop(); | |
192 | } | |
193 | ||
194 | MyClient::~MyClient() | |
195 | { | |
196 | Disconnect(); | |
197 | } | |
198 | ||
199 | void MyClient::Notify() | |
200 | { | |
05b93327 VZ |
201 | // we shouldn't call wxIPC methods from here directly as we may be called |
202 | // from inside an IPC call when using TCP/IP as the sockets are used in | |
203 | // non-blocking code and so can dispatch events, including the timer ones, | |
204 | // while waiting for IO and so starting another IPC call would result in | |
205 | // fatal reentrancies -- instead, just set a flag and perform the test | |
206 | // indicated by it later from our idle event handler | |
207 | MyClientTestFunc testfunc = NULL; | |
208 | switch ( m_step++ ) | |
ebe887ed VZ |
209 | { |
210 | case 0: | |
05b93327 | 211 | testfunc = &MyClient::TestRequest; |
ebe887ed | 212 | break; |
05b93327 | 213 | |
ebe887ed | 214 | case 1: |
05b93327 | 215 | testfunc = &MyClient::TestPoke; |
ebe887ed | 216 | break; |
05b93327 | 217 | |
ebe887ed | 218 | case 2: |
05b93327 | 219 | testfunc = &MyClient::TestExecute; |
ebe887ed | 220 | break; |
05b93327 | 221 | |
ebe887ed | 222 | case 3: |
05b93327 | 223 | testfunc = &MyClient::TestStartAdvise; |
ebe887ed | 224 | break; |
05b93327 | 225 | |
ebe887ed | 226 | case 10: |
05b93327 | 227 | testfunc = &MyClient::TestStopAdvise; |
ebe887ed | 228 | break; |
05b93327 | 229 | |
ebe887ed | 230 | case 15: |
05b93327 | 231 | testfunc = &MyClient::TestDisconnect; |
ebe887ed VZ |
232 | break; |
233 | } | |
05b93327 VZ |
234 | |
235 | if ( testfunc ) | |
236 | m_tests.push_back(testfunc); | |
237 | ||
238 | wxWakeUpIdle(); | |
239 | } | |
240 | ||
241 | void MyClient::StartNextTestIfNecessary() | |
242 | { | |
243 | if ( !m_tests.empty() ) | |
244 | { | |
245 | MyClientTestFunc testfunc = m_tests.front(); | |
246 | m_tests.erase(m_tests.begin()); | |
247 | (this->*testfunc)(); | |
248 | } | |
249 | } | |
250 | ||
251 | void MyClient::TestRequest() | |
252 | { | |
253 | size_t size; | |
254 | m_connection->Request("Date"); | |
255 | m_connection->Request("Date+len", &size); | |
256 | m_connection->Request("bytes[3]", &size, wxIPC_PRIVATE); | |
257 | } | |
258 | ||
259 | void MyClient::TestPoke() | |
260 | { | |
261 | wxString s = wxDateTime::Now().Format(); | |
262 | m_connection->Poke("Date", s); | |
263 | s = wxDateTime::Now().FormatTime() + " " + wxDateTime::Now().FormatDate(); | |
264 | m_connection->Poke("Date", (const char *)s.c_str(), s.length() + 1); | |
265 | char bytes[3]; | |
266 | bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3'; | |
267 | m_connection->Poke("bytes[3]", bytes, 3, wxIPC_PRIVATE); | |
268 | } | |
269 | ||
270 | void MyClient::TestExecute() | |
271 | { | |
272 | wxString s = "Date"; | |
273 | m_connection->Execute(s); | |
274 | m_connection->Execute((const char *)s.c_str(), s.length() + 1); | |
275 | char bytes[3]; | |
276 | bytes[0] = '1'; | |
277 | bytes[1] = '2'; | |
278 | bytes[2] = '3'; | |
279 | m_connection->Execute(bytes, WXSIZEOF(bytes)); | |
280 | } | |
281 | ||
282 | void MyClient::TestStartAdvise() | |
283 | { | |
284 | wxLogMessage("StartAdvise(\"something\")"); | |
285 | m_connection->StartAdvise("something"); | |
286 | } | |
287 | ||
288 | void MyClient::TestStopAdvise() | |
289 | { | |
290 | wxLogMessage("StopAdvise(\"something\")"); | |
291 | m_connection->StopAdvise("something"); | |
292 | } | |
293 | ||
294 | void MyClient::TestDisconnect() | |
295 | { | |
296 | Disconnect(); | |
ebe887ed VZ |
297 | } |
298 | ||
299 | // ---------------------------------------------------------------------------- | |
300 | // MyConnection | |
301 | // ---------------------------------------------------------------------------- | |
302 | ||
ebe887ed VZ |
303 | bool MyConnection::OnAdvise(const wxString& topic, const wxString& item, const void *data, |
304 | size_t size, wxIPCFormat format) | |
305 | { | |
05b93327 | 306 | Log("OnAdvise", topic, item, data, size, format); |
ebe887ed VZ |
307 | return true; |
308 | } | |
309 | ||
310 | bool MyConnection::OnDisconnect() | |
311 | { | |
05b93327 | 312 | wxLogMessage("OnDisconnect()"); |
ebe887ed VZ |
313 | wxGetApp().ExitMainLoop(); |
314 | return true; | |
315 | } | |
316 | ||
317 | bool MyConnection::DoExecute(const void *data, size_t size, wxIPCFormat format) | |
318 | { | |
05b93327 | 319 | Log("Execute", wxEmptyString, wxEmptyString, data, size, format); |
ebe887ed VZ |
320 | bool retval = wxConnection::DoExecute(data, size, format); |
321 | if (!retval) | |
43b2d5e7 | 322 | { |
05b93327 | 323 | wxLogMessage("Execute failed!"); |
43b2d5e7 | 324 | } |
ebe887ed VZ |
325 | return retval; |
326 | } | |
327 | ||
328 | const void *MyConnection::Request(const wxString& item, size_t *size, wxIPCFormat format) | |
329 | { | |
330 | const void *data = wxConnection::Request(item, size, format); | |
05b93327 | 331 | Log("Request", wxEmptyString, item, data, size ? *size : wxNO_LEN, format); |
ebe887ed VZ |
332 | return data; |
333 | } | |
334 | ||
335 | bool MyConnection::DoPoke(const wxString& item, const void *data, size_t size, wxIPCFormat format) | |
336 | { | |
05b93327 | 337 | Log("Poke", wxEmptyString, item, data, size, format); |
ebe887ed VZ |
338 | return wxConnection::DoPoke(item, data, size, format); |
339 | } |