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
8 // Copyright: (c) 2007 Anders Larsen
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 // Settings common to both executables: determines whether
32 // we're using TCP/IP or real DDE.
35 #include "connection.h"
38 #include "wx/datetime.h"
39 #include "wx/vector.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 class MyApp
: public wxApp
50 MyApp() { Connect(wxEVT_IDLE
, wxIdleEventHandler(MyApp::OnIdle
)); }
52 virtual bool OnInit();
56 void OnIdle(wxIdleEvent
& event
);
61 class MyConnection
: public MyConnectionBase
64 virtual bool DoExecute(const void *data
, size_t size
, wxIPCFormat format
);
65 virtual const void *Request(const wxString
& item
, size_t *size
= NULL
, wxIPCFormat format
= wxIPC_TEXT
);
66 virtual bool DoPoke(const wxString
& item
, const void* data
, size_t size
, wxIPCFormat format
);
67 virtual bool OnAdvise(const wxString
& topic
, const wxString
& item
, const void *data
, size_t size
, wxIPCFormat format
);
68 virtual bool OnDisconnect();
71 class MyClient
: public wxClient
,
78 bool Connect(const wxString
& sHost
, const wxString
& sService
, const wxString
& sTopic
);
80 wxConnectionBase
*OnMakeConnection();
81 bool IsConnected() { return m_connection
!= NULL
; };
83 virtual void Notify();
85 void StartNextTestIfNecessary();
91 void TestStartAdvise();
92 void TestStopAdvise();
93 void TestDisconnect();
96 MyConnection
*m_connection
;
98 // the test functions to be executed by StartNextTestIfNecessary()
99 typedef void (MyClient::*MyClientTestFunc
)();
100 wxVector
<MyClientTestFunc
> m_tests
;
102 // number of seconds since the start of the test
106 // ============================================================================
108 // ============================================================================
110 IMPLEMENT_APP_CONSOLE(MyApp
)
112 // ----------------------------------------------------------------------------
114 // ----------------------------------------------------------------------------
116 // The `main program' equivalent, creating the windows and returning the
120 if ( !wxApp::OnInit() )
123 // Create a new client
124 m_client
= new MyClient
;
125 bool retval
= m_client
->Connect("localhost", "4242", "IPC TEST");
127 wxLogMessage("Client host=\"localhost\" port=\"4242\" topic=\"IPC TEST\" %s",
128 retval
? "connected" : "failed to connect");
140 void MyApp::OnIdle(wxIdleEvent
& event
)
143 m_client
->StartNextTestIfNecessary();
148 // ----------------------------------------------------------------------------
150 // ----------------------------------------------------------------------------
160 MyClient::Connect(const wxString
& sHost
,
161 const wxString
& sService
,
162 const wxString
& sTopic
)
164 // suppress the log messages from MakeConnection()
167 m_connection
= (MyConnection
*)MakeConnection(sHost
, sService
, sTopic
);
176 wxConnectionBase
*MyClient::OnMakeConnection()
178 return new MyConnection
;
181 void MyClient::Disconnect()
185 m_connection
->Disconnect();
186 wxDELETE(m_connection
);
187 wxLogMessage("Client disconnected from server");
189 wxGetApp().ExitMainLoop();
192 MyClient::~MyClient()
197 void MyClient::Notify()
199 // we shouldn't call wxIPC methods from here directly as we may be called
200 // from inside an IPC call when using TCP/IP as the sockets are used in
201 // non-blocking code and so can dispatch events, including the timer ones,
202 // while waiting for IO and so starting another IPC call would result in
203 // fatal reentrancies -- instead, just set a flag and perform the test
204 // indicated by it later from our idle event handler
205 MyClientTestFunc testfunc
= NULL
;
209 testfunc
= &MyClient::TestRequest
;
213 testfunc
= &MyClient::TestPoke
;
217 testfunc
= &MyClient::TestExecute
;
221 testfunc
= &MyClient::TestStartAdvise
;
225 testfunc
= &MyClient::TestStopAdvise
;
229 testfunc
= &MyClient::TestDisconnect
;
230 // We don't need the timer any more, we're going to exit soon.
235 // No need to wake up idle handling.
239 m_tests
.push_back(testfunc
);
244 void MyClient::StartNextTestIfNecessary()
246 while ( !m_tests
.empty() )
248 MyClientTestFunc testfunc
= m_tests
.front();
249 m_tests
.erase(m_tests
.begin());
254 void MyClient::TestRequest()
257 m_connection
->Request("Date");
258 m_connection
->Request("Date+len", &size
);
259 m_connection
->Request("bytes[3]", &size
, wxIPC_PRIVATE
);
262 void MyClient::TestPoke()
264 wxString s
= wxDateTime::Now().Format();
265 m_connection
->Poke("Date", s
);
266 s
= wxDateTime::Now().FormatTime() + " " + wxDateTime::Now().FormatDate();
267 m_connection
->Poke("Date", (const char *)s
.c_str(), s
.length() + 1);
269 bytes
[0] = '1'; bytes
[1] = '2'; bytes
[2] = '3';
270 m_connection
->Poke("bytes[3]", bytes
, 3, wxIPC_PRIVATE
);
273 void MyClient::TestExecute()
276 m_connection
->Execute(s
);
277 m_connection
->Execute((const char *)s
.c_str(), s
.length() + 1);
282 m_connection
->Execute(bytes
, WXSIZEOF(bytes
));
285 void MyClient::TestStartAdvise()
287 wxLogMessage("StartAdvise(\"something\")");
288 m_connection
->StartAdvise("something");
291 void MyClient::TestStopAdvise()
293 wxLogMessage("StopAdvise(\"something\")");
294 m_connection
->StopAdvise("something");
297 void MyClient::TestDisconnect()
302 // ----------------------------------------------------------------------------
304 // ----------------------------------------------------------------------------
306 bool MyConnection::OnAdvise(const wxString
& topic
, const wxString
& item
, const void *data
,
307 size_t size
, wxIPCFormat format
)
309 Log("OnAdvise", topic
, item
, data
, size
, format
);
313 bool MyConnection::OnDisconnect()
315 wxLogMessage("OnDisconnect()");
316 wxGetApp().ExitMainLoop();
320 bool MyConnection::DoExecute(const void *data
, size_t size
, wxIPCFormat format
)
322 Log("Execute", wxEmptyString
, wxEmptyString
, data
, size
, format
);
323 bool retval
= wxConnection::DoExecute(data
, size
, format
);
326 wxLogMessage("Execute failed!");
331 const void *MyConnection::Request(const wxString
& item
, size_t *size
, wxIPCFormat format
)
333 const void *data
= wxConnection::Request(item
, size
, format
);
334 Log("Request", wxEmptyString
, item
, data
, size
? *size
: wxNO_LEN
, format
);
338 bool MyConnection::DoPoke(const wxString
& item
, const void *data
, size_t size
, wxIPCFormat format
)
340 Log("Poke", wxEmptyString
, item
, data
, size
, format
);
341 return wxConnection::DoPoke(item
, data
, size
, format
);