baseserver.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: samples/ipc/baseserver.cpp
  3. // Purpose: IPC sample: console server
  4. // Author: Anders Larsen
  5. // Most of the code was stolen from: samples/ipc/server.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. // ----------------------------------------------------------------------------
  32. // local classes
  33. // ----------------------------------------------------------------------------
  34. // a simple connection class testing and logging various operations
  35. class MyConnection : public MyConnectionBase, public wxTimer
  36. {
  37. public:
  38. virtual bool Disconnect() { return wxConnection::Disconnect(); }
  39. virtual bool OnExecute(const wxString& topic,
  40. const void *data,
  41. size_t size,
  42. wxIPCFormat format);
  43. virtual const void *OnRequest(const wxString& topic,
  44. const wxString& item,
  45. size_t *size,
  46. wxIPCFormat format);
  47. virtual bool OnPoke(const wxString& topic,
  48. const wxString& item,
  49. const void *data,
  50. size_t size,
  51. wxIPCFormat format);
  52. virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
  53. virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
  54. virtual bool DoAdvise(const wxString& item,
  55. const void *data,
  56. size_t size,
  57. wxIPCFormat format);
  58. virtual bool OnDisconnect();
  59. virtual void Notify();
  60. private:
  61. wxString m_sAdvise;
  62. wxString m_sRequestDate;
  63. char m_achRequestBytes[3];
  64. };
  65. // a connection used for benchmarking some IPC operations by
  66. // tests/benchmarks/ipcclient.cpp
  67. class BenchConnection : public wxConnection
  68. {
  69. public:
  70. BenchConnection() { m_advise = false; }
  71. virtual bool OnPoke(const wxString& topic,
  72. const wxString& item,
  73. const void *data,
  74. size_t size,
  75. wxIPCFormat format);
  76. virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
  77. virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
  78. private:
  79. // return true if this is the supported topic+item combination, log an
  80. // error message otherwise
  81. bool IsSupportedTopicAndItem(const wxString& operation,
  82. const wxString& topic,
  83. const wxString& item) const;
  84. // the item which can be manipulated by the client via Poke() calls
  85. wxString m_item;
  86. // should we notify the client about changes to m_item?
  87. bool m_advise;
  88. wxDECLARE_NO_COPY_CLASS(BenchConnection);
  89. };
  90. // a simple server accepting connections to IPC_TOPIC and IPC_BENCHMARK_TOPIC
  91. class MyServer : public wxServer
  92. {
  93. public:
  94. MyServer();
  95. virtual ~MyServer();
  96. void Disconnect();
  97. bool IsConnected() { return m_connection != NULL; };
  98. virtual wxConnectionBase *OnAcceptConnection(const wxString& topic);
  99. private:
  100. wxConnection *m_connection;
  101. };
  102. // Define a new application
  103. class MyApp : public wxApp
  104. {
  105. public:
  106. virtual bool OnInit();
  107. protected:
  108. MyServer m_server;
  109. };
  110. DECLARE_APP(MyApp)
  111. // ============================================================================
  112. // implementation
  113. // ============================================================================
  114. IMPLEMENT_APP_CONSOLE(MyApp)
  115. // ----------------------------------------------------------------------------
  116. // MyApp
  117. // ----------------------------------------------------------------------------
  118. bool MyApp::OnInit()
  119. {
  120. if ( !wxApp::OnInit() )
  121. return false;
  122. delete wxLog::SetActiveTarget(new wxLogStderr);
  123. const char * const kind =
  124. #if wxUSE_DDE_FOR_IPC
  125. "DDE"
  126. #else
  127. "TCP"
  128. #endif
  129. ;
  130. // Create a new server
  131. if ( !m_server.Create(IPC_SERVICE) )
  132. {
  133. wxLogMessage("%s server failed to start on %s", kind, IPC_SERVICE);
  134. return false;
  135. }
  136. wxLogMessage("%s server started on %s", kind, IPC_SERVICE);
  137. return true;
  138. }
  139. // ----------------------------------------------------------------------------
  140. // MyServer
  141. // ----------------------------------------------------------------------------
  142. MyServer::MyServer()
  143. {
  144. m_connection = NULL;
  145. }
  146. MyServer::~MyServer()
  147. {
  148. Disconnect();
  149. }
  150. wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
  151. {
  152. wxLogMessage("OnAcceptConnection(\"%s\")", topic);
  153. if ( topic == IPC_TOPIC )
  154. {
  155. m_connection = new MyConnection;
  156. }
  157. else if ( topic == IPC_BENCHMARK_TOPIC )
  158. {
  159. m_connection = new BenchConnection;
  160. }
  161. else // unknown topic
  162. {
  163. wxLogMessage("Unknown topic");
  164. return NULL;
  165. }
  166. wxLogMessage("Connection accepted");
  167. return m_connection;
  168. }
  169. void MyServer::Disconnect()
  170. {
  171. if ( m_connection )
  172. {
  173. m_connection->Disconnect();
  174. wxDELETE(m_connection);
  175. wxLogMessage("Disconnected client");
  176. }
  177. }
  178. // ----------------------------------------------------------------------------
  179. // MyConnection
  180. // ----------------------------------------------------------------------------
  181. bool
  182. MyConnection::OnExecute(const wxString& topic,
  183. const void *data,
  184. size_t size,
  185. wxIPCFormat format)
  186. {
  187. Log("OnExecute", topic, "", data, size, format);
  188. return true;
  189. }
  190. bool
  191. MyConnection::OnPoke(const wxString& topic,
  192. const wxString& item,
  193. const void *data,
  194. size_t size,
  195. wxIPCFormat format)
  196. {
  197. Log("OnPoke", topic, item, data, size, format);
  198. return wxConnection::OnPoke(topic, item, data, size, format);
  199. }
  200. const void *
  201. MyConnection::OnRequest(const wxString& topic,
  202. const wxString& item,
  203. size_t *size,
  204. wxIPCFormat format)
  205. {
  206. const void *data;
  207. if (item == "Date")
  208. {
  209. m_sRequestDate = wxDateTime::Now().Format();
  210. data = m_sRequestDate.c_str();
  211. *size = wxNO_LEN;
  212. }
  213. else if (item == "Date+len")
  214. {
  215. m_sRequestDate = wxDateTime::Now().FormatTime() +
  216. " " + wxDateTime::Now().FormatDate();
  217. data = m_sRequestDate.c_str();
  218. *size = m_sRequestDate.Length() + 1;
  219. }
  220. else if (item == "bytes[3]")
  221. {
  222. data = m_achRequestBytes;
  223. m_achRequestBytes[0] = '1';
  224. m_achRequestBytes[1] = '2';
  225. m_achRequestBytes[2] = '3';
  226. *size = 3;
  227. }
  228. else
  229. {
  230. data = NULL;
  231. *size = 0;
  232. }
  233. Log("OnRequest", topic, item, data, *size, format);
  234. return data;
  235. }
  236. bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item)
  237. {
  238. wxLogMessage("OnStartAdvise(\"%s\",\"%s\")", topic, item);
  239. wxLogMessage("Returning true");
  240. m_sAdvise = item;
  241. Start(3000); // schedule our Notify() to be called in 3 seconds
  242. return true;
  243. }
  244. bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item)
  245. {
  246. wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item);
  247. wxLogMessage("Returning true");
  248. m_sAdvise.clear();
  249. Stop();
  250. return true;
  251. }
  252. void MyConnection::Notify()
  253. {
  254. if (!m_sAdvise.empty())
  255. {
  256. wxString s = wxDateTime::Now().Format();
  257. Advise(m_sAdvise, s);
  258. s = wxDateTime::Now().FormatTime() + " "
  259. + wxDateTime::Now().FormatDate();
  260. Advise(m_sAdvise, s.mb_str(), s.length() + 1);
  261. #if wxUSE_DDE_FOR_IPC
  262. wxLogMessage("DDE Advise type argument cannot be wxIPC_PRIVATE. "
  263. "The client will receive it as wxIPC_TEXT, "
  264. "and receive the correct no of bytes, "
  265. "but not print a correct log entry.");
  266. #endif // DDE
  267. char bytes[3];
  268. bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
  269. Advise(m_sAdvise, bytes, 3, wxIPC_PRIVATE);
  270. // this works, but the log treats it as a string now
  271. // m_connection->Advise(m_connection->m_sAdvise, bytes, 3, wxIPC_TEXT );
  272. }
  273. }
  274. bool MyConnection::DoAdvise(const wxString& item,
  275. const void *data,
  276. size_t size,
  277. wxIPCFormat format)
  278. {
  279. Log("Advise", "", item, data, size, format);
  280. return wxConnection::DoAdvise(item, data, size, format);
  281. }
  282. bool MyConnection::OnDisconnect()
  283. {
  284. wxLogMessage("OnDisconnect()");
  285. return true;
  286. }
  287. // ----------------------------------------------------------------------------
  288. // BenchConnection
  289. // ----------------------------------------------------------------------------
  290. bool BenchConnection::IsSupportedTopicAndItem(const wxString& operation,
  291. const wxString& topic,
  292. const wxString& item) const
  293. {
  294. if ( topic != IPC_BENCHMARK_TOPIC ||
  295. item != IPC_BENCHMARK_ITEM )
  296. {
  297. wxLogMessage("Unexpected %s(\"%s\", \"%s\") call.",
  298. operation, topic, item);
  299. return false;
  300. }
  301. return true;
  302. }
  303. bool BenchConnection::OnPoke(const wxString& topic,
  304. const wxString& item,
  305. const void *data,
  306. size_t size,
  307. wxIPCFormat format)
  308. {
  309. if ( !IsSupportedTopicAndItem("OnPoke", topic, item) )
  310. return false;
  311. if ( !IsTextFormat(format) )
  312. {
  313. wxLogMessage("Unexpected format %d in OnPoke().", format);
  314. return false;
  315. }
  316. m_item = GetTextFromData(data, size, format);
  317. if ( m_advise )
  318. {
  319. if ( !Advise(item, m_item) )
  320. {
  321. wxLogMessage("Failed to advise client about the change.");
  322. }
  323. }
  324. return true;
  325. }
  326. bool BenchConnection::OnStartAdvise(const wxString& topic, const wxString& item)
  327. {
  328. if ( !IsSupportedTopicAndItem("OnStartAdvise", topic, item) )
  329. return false;
  330. m_advise = true;
  331. return true;
  332. }
  333. bool BenchConnection::OnStopAdvise(const wxString& topic, const wxString& item)
  334. {
  335. if ( !IsSupportedTopicAndItem("OnStopAdvise", topic, item) )
  336. return false;
  337. m_advise = false;
  338. return true;
  339. }