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
9 // Copyright: (c) 2007 Anders Larsen
10 // Licence: wxWindows licence
11 ///////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 // ----------------------------------------------------------------------------
19 // ----------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
32 // Settings common to both executables: determines whether
33 // we're using TCP/IP or real DDE.
36 #include "connection.h"
39 #include "wx/datetime.h"
40 #include "wx/vector.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 class MyApp
: public wxApp
51 MyApp() { Connect(wxEVT_IDLE
, wxIdleEventHandler(MyApp::OnIdle
)); }
53 virtual bool OnInit();
57 void OnIdle(wxIdleEvent
& event
);
62 class MyConnection
: public MyConnectionBase
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();
72 class MyClient
: public wxClient
,
79 bool Connect(const wxString
& sHost
, const wxString
& sService
, const wxString
& sTopic
);
81 wxConnectionBase
*OnMakeConnection();
82 bool IsConnected() { return m_connection
!= NULL
; };
84 virtual void Notify();
86 void StartNextTestIfNecessary();
92 void TestStartAdvise();
93 void TestStopAdvise();
94 void TestDisconnect();
97 MyConnection
*m_connection
;
99 // the test functions to be executed by StartNextTestIfNecessary()
100 typedef void (MyClient::*MyClientTestFunc
)();
101 wxVector
<MyClientTestFunc
> m_tests
;
103 // number of seconds since the start of the test
107 // ============================================================================
109 // ============================================================================
111 IMPLEMENT_APP_CONSOLE(MyApp
)
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
117 // The `main program' equivalent, creating the windows and returning the
121 if ( !wxApp::OnInit() )
124 // Create a new client
125 m_client
= new MyClient
;
126 bool retval
= m_client
->Connect("localhost", "4242", "IPC TEST");
128 wxLogMessage("Client host=\"localhost\" port=\"4242\" topic=\"IPC TEST\" %s",
129 retval
? "connected" : "failed to connect");
141 void MyApp::OnIdle(wxIdleEvent
& event
)
144 m_client
->StartNextTestIfNecessary();
149 // ----------------------------------------------------------------------------
151 // ----------------------------------------------------------------------------
161 MyClient::Connect(const wxString
& sHost
,
162 const wxString
& sService
,
163 const wxString
& sTopic
)
165 // suppress the log messages from MakeConnection()
168 m_connection
= (MyConnection
*)MakeConnection(sHost
, sService
, sTopic
);
177 wxConnectionBase
*MyClient::OnMakeConnection()
179 return new MyConnection
;
182 void MyClient::Disconnect()
186 m_connection
->Disconnect();
187 wxDELETE(m_connection
);
188 wxLogMessage("Client disconnected from server");
190 wxGetApp().ExitMainLoop();
193 MyClient::~MyClient()
198 void MyClient::Notify()
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
;
210 testfunc
= &MyClient::TestRequest
;
214 testfunc
= &MyClient::TestPoke
;
218 testfunc
= &MyClient::TestExecute
;
222 testfunc
= &MyClient::TestStartAdvise
;
226 testfunc
= &MyClient::TestStopAdvise
;
230 testfunc
= &MyClient::TestDisconnect
;
231 // We don't need the timer any more, we're going to exit soon.
236 // No need to wake up idle handling.
240 m_tests
.push_back(testfunc
);
245 void MyClient::StartNextTestIfNecessary()
247 while ( !m_tests
.empty() )
249 MyClientTestFunc testfunc
= m_tests
.front();
250 m_tests
.erase(m_tests
.begin());
255 void MyClient::TestRequest()
258 m_connection
->Request("Date");
259 m_connection
->Request("Date+len", &size
);
260 m_connection
->Request("bytes[3]", &size
, wxIPC_PRIVATE
);
263 void MyClient::TestPoke()
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);
270 bytes
[0] = '1'; bytes
[1] = '2'; bytes
[2] = '3';
271 m_connection
->Poke("bytes[3]", bytes
, 3, wxIPC_PRIVATE
);
274 void MyClient::TestExecute()
277 m_connection
->Execute(s
);
278 m_connection
->Execute((const char *)s
.c_str(), s
.length() + 1);
283 m_connection
->Execute(bytes
, WXSIZEOF(bytes
));
286 void MyClient::TestStartAdvise()
288 wxLogMessage("StartAdvise(\"something\")");
289 m_connection
->StartAdvise("something");
292 void MyClient::TestStopAdvise()
294 wxLogMessage("StopAdvise(\"something\")");
295 m_connection
->StopAdvise("something");
298 void MyClient::TestDisconnect()
303 // ----------------------------------------------------------------------------
305 // ----------------------------------------------------------------------------
307 bool MyConnection::OnAdvise(const wxString
& topic
, const wxString
& item
, const void *data
,
308 size_t size
, wxIPCFormat format
)
310 Log("OnAdvise", topic
, item
, data
, size
, format
);
314 bool MyConnection::OnDisconnect()
316 wxLogMessage("OnDisconnect()");
317 wxGetApp().ExitMainLoop();
321 bool MyConnection::DoExecute(const void *data
, size_t size
, wxIPCFormat format
)
323 Log("Execute", wxEmptyString
, wxEmptyString
, data
, size
, format
);
324 bool retval
= wxConnection::DoExecute(data
, size
, format
);
327 wxLogMessage("Execute failed!");
332 const void *MyConnection::Request(const wxString
& item
, size_t *size
, wxIPCFormat format
)
334 const void *data
= wxConnection::Request(item
, size
, format
);
335 Log("Request", wxEmptyString
, item
, data
, size
? *size
: wxNO_LEN
, format
);
339 bool MyConnection::DoPoke(const wxString
& item
, const void *data
, size_t size
, wxIPCFormat format
)
341 Log("Poke", wxEmptyString
, item
, data
, size
, format
);
342 return wxConnection::DoPoke(item
, data
, size
, format
);