baseclient.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. // Copyright: (c) 2007 Anders Larsen
  9. // Licence: wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11. // ============================================================================
  12. // declarations
  13. // ============================================================================
  14. // ----------------------------------------------------------------------------
  15. // headers
  16. // ----------------------------------------------------------------------------
  17. // For compilers that support precompilation, includes "wx.h".
  18. #include "wx/wxprec.h"
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22. #ifndef WX_PRECOMP
  23. #include "wx/wx.h"
  24. #endif
  25. // Settings common to both executables: determines whether
  26. // we're using TCP/IP or real DDE.
  27. #include "ipcsetup.h"
  28. #include "connection.h"
  29. #include "wx/timer.h"
  30. #include "wx/datetime.h"
  31. #include "wx/vector.h"
  32. class MyClient;
  33. // ----------------------------------------------------------------------------
  34. // classes
  35. // ----------------------------------------------------------------------------
  36. class MyApp : public wxApp
  37. {
  38. public:
  39. MyApp() { Connect(wxEVT_IDLE, wxIdleEventHandler(MyApp::OnIdle)); }
  40. virtual bool OnInit();
  41. virtual int OnExit();
  42. private:
  43. void OnIdle(wxIdleEvent& event);
  44. MyClient *m_client;
  45. };
  46. class MyConnection : public MyConnectionBase
  47. {
  48. public:
  49. virtual bool DoExecute(const void *data, size_t size, wxIPCFormat format);
  50. virtual const void *Request(const wxString& item, size_t *size = NULL, wxIPCFormat format = wxIPC_TEXT);
  51. virtual bool DoPoke(const wxString& item, const void* data, size_t size, wxIPCFormat format);
  52. virtual bool OnAdvise(const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format);
  53. virtual bool OnDisconnect();
  54. };
  55. class MyClient : public wxClient,
  56. private wxTimer
  57. {
  58. public:
  59. MyClient();
  60. virtual ~MyClient();
  61. bool Connect(const wxString& sHost, const wxString& sService, const wxString& sTopic);
  62. void Disconnect();
  63. wxConnectionBase *OnMakeConnection();
  64. bool IsConnected() { return m_connection != NULL; };
  65. virtual void Notify();
  66. void StartNextTestIfNecessary();
  67. private:
  68. void TestRequest();
  69. void TestPoke();
  70. void TestExecute();
  71. void TestStartAdvise();
  72. void TestStopAdvise();
  73. void TestDisconnect();
  74. MyConnection *m_connection;
  75. // the test functions to be executed by StartNextTestIfNecessary()
  76. typedef void (MyClient::*MyClientTestFunc)();
  77. wxVector<MyClientTestFunc> m_tests;
  78. // number of seconds since the start of the test
  79. int m_step;
  80. };
  81. // ============================================================================
  82. // implementation
  83. // ============================================================================
  84. IMPLEMENT_APP_CONSOLE(MyApp)
  85. // ----------------------------------------------------------------------------
  86. // MyApp
  87. // ----------------------------------------------------------------------------
  88. // The `main program' equivalent, creating the windows and returning the
  89. // main frame
  90. bool MyApp::OnInit()
  91. {
  92. if ( !wxApp::OnInit() )
  93. return false;
  94. // Create a new client
  95. m_client = new MyClient;
  96. bool retval = m_client->Connect("localhost", "4242", "IPC TEST");
  97. wxLogMessage("Client host=\"localhost\" port=\"4242\" topic=\"IPC TEST\" %s",
  98. retval ? "connected" : "failed to connect");
  99. return retval;
  100. }
  101. int MyApp::OnExit()
  102. {
  103. delete m_client;
  104. return 0;
  105. }
  106. void MyApp::OnIdle(wxIdleEvent& event)
  107. {
  108. if ( m_client )
  109. m_client->StartNextTestIfNecessary();
  110. event.Skip();
  111. }
  112. // ----------------------------------------------------------------------------
  113. // MyClient
  114. // ----------------------------------------------------------------------------
  115. MyClient::MyClient()
  116. : wxClient()
  117. {
  118. m_connection = NULL;
  119. m_step = 0;
  120. }
  121. bool
  122. MyClient::Connect(const wxString& sHost,
  123. const wxString& sService,
  124. const wxString& sTopic)
  125. {
  126. // suppress the log messages from MakeConnection()
  127. wxLogNull nolog;
  128. m_connection = (MyConnection *)MakeConnection(sHost, sService, sTopic);
  129. if ( !m_connection )
  130. return false;
  131. Start(1000);
  132. return true;
  133. }
  134. wxConnectionBase *MyClient::OnMakeConnection()
  135. {
  136. return new MyConnection;
  137. }
  138. void MyClient::Disconnect()
  139. {
  140. if (m_connection)
  141. {
  142. m_connection->Disconnect();
  143. wxDELETE(m_connection);
  144. wxLogMessage("Client disconnected from server");
  145. }
  146. wxGetApp().ExitMainLoop();
  147. }
  148. MyClient::~MyClient()
  149. {
  150. Disconnect();
  151. }
  152. void MyClient::Notify()
  153. {
  154. // we shouldn't call wxIPC methods from here directly as we may be called
  155. // from inside an IPC call when using TCP/IP as the sockets are used in
  156. // non-blocking code and so can dispatch events, including the timer ones,
  157. // while waiting for IO and so starting another IPC call would result in
  158. // fatal reentrancies -- instead, just set a flag and perform the test
  159. // indicated by it later from our idle event handler
  160. MyClientTestFunc testfunc = NULL;
  161. switch ( m_step++ )
  162. {
  163. case 0:
  164. testfunc = &MyClient::TestRequest;
  165. break;
  166. case 1:
  167. testfunc = &MyClient::TestPoke;
  168. break;
  169. case 2:
  170. testfunc = &MyClient::TestExecute;
  171. break;
  172. case 3:
  173. testfunc = &MyClient::TestStartAdvise;
  174. break;
  175. case 10:
  176. testfunc = &MyClient::TestStopAdvise;
  177. break;
  178. case 15:
  179. testfunc = &MyClient::TestDisconnect;
  180. // We don't need the timer any more, we're going to exit soon.
  181. Stop();
  182. break;
  183. default:
  184. // No need to wake up idle handling.
  185. return;
  186. }
  187. m_tests.push_back(testfunc);
  188. wxWakeUpIdle();
  189. }
  190. void MyClient::StartNextTestIfNecessary()
  191. {
  192. while ( !m_tests.empty() )
  193. {
  194. MyClientTestFunc testfunc = m_tests.front();
  195. m_tests.erase(m_tests.begin());
  196. (this->*testfunc)();
  197. }
  198. }
  199. void MyClient::TestRequest()
  200. {
  201. size_t size;
  202. m_connection->Request("Date");
  203. m_connection->Request("Date+len", &size);
  204. m_connection->Request("bytes[3]", &size, wxIPC_PRIVATE);
  205. }
  206. void MyClient::TestPoke()
  207. {
  208. wxString s = wxDateTime::Now().Format();
  209. m_connection->Poke("Date", s);
  210. s = wxDateTime::Now().FormatTime() + " " + wxDateTime::Now().FormatDate();
  211. m_connection->Poke("Date", (const char *)s.c_str(), s.length() + 1);
  212. char bytes[3];
  213. bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
  214. m_connection->Poke("bytes[3]", bytes, 3, wxIPC_PRIVATE);
  215. }
  216. void MyClient::TestExecute()
  217. {
  218. wxString s = "Date";
  219. m_connection->Execute(s);
  220. m_connection->Execute((const char *)s.c_str(), s.length() + 1);
  221. char bytes[3];
  222. bytes[0] = '1';
  223. bytes[1] = '2';
  224. bytes[2] = '3';
  225. m_connection->Execute(bytes, WXSIZEOF(bytes));
  226. }
  227. void MyClient::TestStartAdvise()
  228. {
  229. wxLogMessage("StartAdvise(\"something\")");
  230. m_connection->StartAdvise("something");
  231. }
  232. void MyClient::TestStopAdvise()
  233. {
  234. wxLogMessage("StopAdvise(\"something\")");
  235. m_connection->StopAdvise("something");
  236. }
  237. void MyClient::TestDisconnect()
  238. {
  239. Disconnect();
  240. }
  241. // ----------------------------------------------------------------------------
  242. // MyConnection
  243. // ----------------------------------------------------------------------------
  244. bool MyConnection::OnAdvise(const wxString& topic, const wxString& item, const void *data,
  245. size_t size, wxIPCFormat format)
  246. {
  247. Log("OnAdvise", topic, item, data, size, format);
  248. return true;
  249. }
  250. bool MyConnection::OnDisconnect()
  251. {
  252. wxLogMessage("OnDisconnect()");
  253. wxGetApp().ExitMainLoop();
  254. return true;
  255. }
  256. bool MyConnection::DoExecute(const void *data, size_t size, wxIPCFormat format)
  257. {
  258. Log("Execute", wxEmptyString, wxEmptyString, data, size, format);
  259. bool retval = wxConnection::DoExecute(data, size, format);
  260. if (!retval)
  261. {
  262. wxLogMessage("Execute failed!");
  263. }
  264. return retval;
  265. }
  266. const void *MyConnection::Request(const wxString& item, size_t *size, wxIPCFormat format)
  267. {
  268. const void *data = wxConnection::Request(item, size, format);
  269. Log("Request", wxEmptyString, item, data, size ? *size : wxNO_LEN, format);
  270. return data;
  271. }
  272. bool MyConnection::DoPoke(const wxString& item, const void *data, size_t size, wxIPCFormat format)
  273. {
  274. Log("Poke", wxEmptyString, item, data, size, format);
  275. return wxConnection::DoPoke(item, data, size, format);
  276. }