git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56360 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ///////////////////////////////////////////////////////////////////////////////
 | |
| // Name:        samples/ipc/baseserver.cpp
 | |
| // Purpose:     IPC sample: console server
 | |
| // Author:      Anders Larsen
 | |
| //              Most of the code was stolen from: samples/ipc/server.cpp
 | |
| //              (c) Julian Smart, Jurgen Doornik
 | |
| // Created:     2007-11-08
 | |
| // RCS-ID:      $Id$
 | |
| // Copyright:   (c) 2007 Anders Larsen
 | |
| // License:     wxWindows licence
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| // ============================================================================
 | |
| // declarations
 | |
| // ============================================================================
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // headers
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| // For compilers that support precompilation, includes "wx.h".
 | |
| #include "wx/wxprec.h"
 | |
| 
 | |
| #ifdef __BORLANDC__
 | |
|     #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #ifndef WX_PRECOMP
 | |
|     #include "wx/wx.h"
 | |
| #endif
 | |
| 
 | |
| // Settings common to both executables: determines whether
 | |
| // we're using TCP/IP or real DDE.
 | |
| #include "ipcsetup.h"
 | |
| 
 | |
| #include "connection.h"
 | |
| 
 | |
| #include "wx/timer.h"
 | |
| #include "wx/datetime.h"
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // local classes
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| // a simple connection class testing and logging various operations
 | |
| class MyConnection : public MyConnectionBase, public wxTimer
 | |
| {
 | |
| public:
 | |
|     virtual bool Disconnect() { return wxConnection::Disconnect(); }
 | |
|     virtual bool OnExecute(const wxString& topic,
 | |
|                            const void *data,
 | |
|                            size_t size,
 | |
|                            wxIPCFormat format);
 | |
|     virtual const void *OnRequest(const wxString& topic,
 | |
|                                   const wxString& item,
 | |
|                                   size_t *size,
 | |
|                                   wxIPCFormat format);
 | |
|     virtual bool OnPoke(const wxString& topic,
 | |
|                         const wxString& item,
 | |
|                         const void *data,
 | |
|                         size_t size,
 | |
|                         wxIPCFormat format);
 | |
|     virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
 | |
|     virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
 | |
|     virtual bool DoAdvise(const wxString& item,
 | |
|                           const void *data,
 | |
|                           size_t size,
 | |
|                           wxIPCFormat format);
 | |
|     virtual bool OnDisconnect();
 | |
|     virtual void Notify();
 | |
| 
 | |
| private:
 | |
|     wxString        m_sAdvise;
 | |
| 
 | |
|     wxString        m_sRequestDate;
 | |
|     char            m_achRequestBytes[3];
 | |
| };
 | |
| 
 | |
| // a connection used for benchmarking some IPC operations by
 | |
| // tests/benchmarks/ipcclient.cpp
 | |
| class BenchConnection : public wxConnection
 | |
| {
 | |
| public:
 | |
|     BenchConnection() { m_advise = false; }
 | |
| 
 | |
|     virtual bool OnPoke(const wxString& topic,
 | |
|                         const wxString& item,
 | |
|                         const void *data,
 | |
|                         size_t size,
 | |
|                         wxIPCFormat format);
 | |
|     virtual bool OnStartAdvise(const wxString& topic, const wxString& item);
 | |
|     virtual bool OnStopAdvise(const wxString& topic, const wxString& item);
 | |
| 
 | |
| private:
 | |
|     // return true if this is the supported topic+item combination, log an
 | |
|     // error message otherwise
 | |
|     bool IsSupportedTopicAndItem(const wxString& operation,
 | |
|                                  const wxString& topic,
 | |
|                                  const wxString& item) const;
 | |
| 
 | |
|     // the item which can be manipulated by the client via Poke() calls
 | |
|     wxString m_item;
 | |
| 
 | |
|     // should we notify the client about changes to m_item?
 | |
|     bool m_advise;
 | |
| 
 | |
|     DECLARE_NO_COPY_CLASS(BenchConnection)
 | |
| };
 | |
| 
 | |
| // a simple server accepting connections to IPC_TOPIC and IPC_BENCHMARK_TOPIC
 | |
| class MyServer : public wxServer
 | |
| {
 | |
| public:
 | |
|     MyServer();
 | |
|     virtual ~MyServer();
 | |
|     void Disconnect();
 | |
|     bool IsConnected() { return m_connection != NULL; };
 | |
| 
 | |
|     virtual wxConnectionBase *OnAcceptConnection(const wxString& topic);
 | |
| 
 | |
| private:
 | |
|     wxConnection *m_connection;
 | |
| };
 | |
| 
 | |
| // Define a new application
 | |
| class MyApp : public wxApp
 | |
| {
 | |
| public:
 | |
|     virtual bool OnInit();
 | |
| 
 | |
| protected:
 | |
|     MyServer m_server;
 | |
| };
 | |
| 
 | |
| DECLARE_APP(MyApp)
 | |
| 
 | |
| // ============================================================================
 | |
| // implementation
 | |
| // ============================================================================
 | |
| 
 | |
| IMPLEMENT_APP_CONSOLE(MyApp)
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // MyApp
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| bool MyApp::OnInit()
 | |
| {
 | |
|     if ( !wxApp::OnInit() )
 | |
|         return false;
 | |
| 
 | |
|     delete wxLog::SetActiveTarget(new wxLogStderr);
 | |
| 
 | |
|     const char * const kind =
 | |
| #if wxUSE_DDE_FOR_IPC
 | |
|                  "DDE"
 | |
| #else
 | |
|                  "TCP"
 | |
| #endif
 | |
|                  ;
 | |
| 
 | |
|     // Create a new server
 | |
|     if ( !m_server.Create(IPC_SERVICE) )
 | |
|     {
 | |
|         wxLogMessage("%s server failed to start on %s", kind, IPC_SERVICE);
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     wxLogMessage("%s server started on %s", kind, IPC_SERVICE);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // MyServer
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| MyServer::MyServer()
 | |
| {
 | |
|     m_connection = NULL;
 | |
| }
 | |
| 
 | |
| MyServer::~MyServer()
 | |
| {
 | |
|     Disconnect();
 | |
| }
 | |
| 
 | |
| wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
 | |
| {
 | |
|     wxLogMessage("OnAcceptConnection(\"%s\")", topic);
 | |
| 
 | |
|     if ( topic == IPC_TOPIC )
 | |
|     {
 | |
|         m_connection = new MyConnection;
 | |
|     }
 | |
|     else if ( topic == IPC_BENCHMARK_TOPIC )
 | |
|     {
 | |
|         m_connection = new BenchConnection;
 | |
|     }
 | |
|     else // unknown topic
 | |
|     {
 | |
|         wxLogMessage("Unknown topic");
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     wxLogMessage("Connection accepted");
 | |
|     return m_connection;
 | |
| }
 | |
| 
 | |
| void MyServer::Disconnect()
 | |
| {
 | |
|     if ( m_connection )
 | |
|     {
 | |
|         m_connection->Disconnect();
 | |
|         delete m_connection;
 | |
|         m_connection = NULL;
 | |
|         wxLogMessage("Disconnected client");
 | |
|     }
 | |
| }
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // MyConnection
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| bool
 | |
| MyConnection::OnExecute(const wxString& topic,
 | |
|                         const void *data,
 | |
|                         size_t size,
 | |
|                         wxIPCFormat format)
 | |
| {
 | |
|     Log("OnExecute", topic, "", data, size, format);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool
 | |
| MyConnection::OnPoke(const wxString& topic,
 | |
|                      const wxString& item,
 | |
|                      const void *data,
 | |
|                      size_t size,
 | |
|                      wxIPCFormat format)
 | |
| {
 | |
|     Log("OnPoke", topic, item, data, size, format);
 | |
|     return wxConnection::OnPoke(topic, item, data, size, format);
 | |
| }
 | |
| 
 | |
| const void *
 | |
| MyConnection::OnRequest(const wxString& topic,
 | |
|                         const wxString& item,
 | |
|                         size_t *size,
 | |
|                         wxIPCFormat format)
 | |
| {
 | |
|     const void *data;
 | |
|     if (item == "Date")
 | |
|     {
 | |
|         m_sRequestDate = wxDateTime::Now().Format();
 | |
|         data = m_sRequestDate.c_str();
 | |
|         *size = wxNO_LEN;
 | |
|     }
 | |
|     else if (item == "Date+len")
 | |
|     {
 | |
|         m_sRequestDate = wxDateTime::Now().FormatTime() +
 | |
|                             " " + wxDateTime::Now().FormatDate();
 | |
|         data = m_sRequestDate.c_str();
 | |
|         *size = m_sRequestDate.Length() + 1;
 | |
|     }
 | |
|     else if (item == "bytes[3]")
 | |
|     {
 | |
|         data = m_achRequestBytes;
 | |
|         m_achRequestBytes[0] = '1';
 | |
|         m_achRequestBytes[1] = '2';
 | |
|         m_achRequestBytes[2] = '3';
 | |
|         *size = 3;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         data = NULL;
 | |
|         *size = 0;
 | |
|     }
 | |
|     Log("OnRequest", topic, item, data, *size, format);
 | |
|     return data;
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item)
 | |
| {
 | |
|     wxLogMessage("OnStartAdvise(\"%s\",\"%s\")", topic, item);
 | |
|     wxLogMessage("Returning true");
 | |
|     m_sAdvise = item;
 | |
|     Start(3000); // schedule our Notify() to be called in 3 seconds
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item)
 | |
| {
 | |
|     wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item);
 | |
|     wxLogMessage("Returning true");
 | |
|     m_sAdvise.clear();
 | |
|     Stop();
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void MyConnection::Notify()
 | |
| {
 | |
|     if (!m_sAdvise.empty())
 | |
|     {
 | |
|         wxString s = wxDateTime::Now().Format();
 | |
|         Advise(m_sAdvise, s);
 | |
|         s = wxDateTime::Now().FormatTime() + " "
 | |
|                 + wxDateTime::Now().FormatDate();
 | |
|         Advise(m_sAdvise, s.mb_str(), s.length() + 1);
 | |
| 
 | |
| #if wxUSE_DDE_FOR_IPC
 | |
|         wxLogMessage("DDE Advise type argument cannot be wxIPC_PRIVATE. "
 | |
|                      "The client will receive it as wxIPC_TEXT, "
 | |
|                      "and receive the correct no of bytes, "
 | |
|                      "but not print a correct log entry.");
 | |
| #endif // DDE
 | |
| 
 | |
|         char bytes[3];
 | |
|         bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
 | |
|         Advise(m_sAdvise, bytes, 3, wxIPC_PRIVATE);
 | |
|         // this works, but the log treats it as a string now
 | |
| //        m_connection->Advise(m_connection->m_sAdvise, bytes, 3, wxIPC_TEXT );
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool MyConnection::DoAdvise(const wxString& item,
 | |
|                             const void *data,
 | |
|                             size_t size,
 | |
|                             wxIPCFormat format)
 | |
| {
 | |
|     Log("Advise", "", item, data, size, format);
 | |
|     return wxConnection::DoAdvise(item, data, size, format);
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnDisconnect()
 | |
| {
 | |
|     wxLogMessage("OnDisconnect()");
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // BenchConnection
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| bool BenchConnection::IsSupportedTopicAndItem(const wxString& operation,
 | |
|                                               const wxString& topic,
 | |
|                                               const wxString& item) const
 | |
| {
 | |
|     if ( topic != IPC_BENCHMARK_TOPIC ||
 | |
|             item != IPC_BENCHMARK_ITEM )
 | |
|     {
 | |
|         wxLogMessage("Unexpected %s(\"%s\", \"%s\") call.",
 | |
|                      operation, topic, item);
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool BenchConnection::OnPoke(const wxString& topic,
 | |
|                              const wxString& item,
 | |
|                              const void *data,
 | |
|                              size_t size,
 | |
|                              wxIPCFormat format)
 | |
| {
 | |
|     if ( !IsSupportedTopicAndItem("OnPoke", topic, item) )
 | |
|         return false;
 | |
| 
 | |
|     if ( !IsTextFormat(format) )
 | |
|     {
 | |
|         wxLogMessage("Unexpected format %d in OnPoke().", format);
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     m_item = GetTextFromData(data, size, format);
 | |
| 
 | |
|     if ( m_advise )
 | |
|     {
 | |
|         if ( !Advise(item, m_item) )
 | |
|             wxLogMessage("Failed to advise client about the change.");
 | |
|     }
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool BenchConnection::OnStartAdvise(const wxString& topic, const wxString& item)
 | |
| {
 | |
|     if ( !IsSupportedTopicAndItem("OnStartAdvise", topic, item) )
 | |
|         return false;
 | |
| 
 | |
|     m_advise = true;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool BenchConnection::OnStopAdvise(const wxString& topic, const wxString& item)
 | |
| {
 | |
|     if ( !IsSupportedTopicAndItem("OnStopAdvise", topic, item) )
 | |
|         return false;
 | |
| 
 | |
|     m_advise = false;
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 |