// Created: 2007-11-08
// RCS-ID: $Id$
// Copyright: (c) 2007 Anders Larsen
-// License: wxWindows licence
+// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// we're using TCP/IP or real DDE.
#include "ipcsetup.h"
+#include "connection.h"
+
#include "wx/timer.h"
#include "wx/datetime.h"
// ----------------------------------------------------------------------------
-// wxWin macros
+// local classes
// ----------------------------------------------------------------------------
-// Define a new application
-class MyServer;
-class MyConnection;
-
-class MyApp : public wxApp
+// a simple connection class testing and logging various operations
+class MyConnection : public MyConnectionBase, public wxTimer
{
public:
- virtual bool OnInit();
- virtual int OnExit();
+ 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();
-protected:
- MyServer *m_server;
-};
+private:
+ wxString m_sAdvise;
-DECLARE_APP(MyApp)
+ wxString m_sRequestDate;
+ char m_achRequestBytes[3];
+};
-class MyConnection : public wxConnection, public wxTimer
+// a connection used for benchmarking some IPC operations by
+// tests/benchmarks/ipcclient.cpp
+class BenchConnection : public wxConnection
{
public:
- MyConnection();
- virtual ~MyConnection();
+ BenchConnection() { m_advise = false; }
- 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 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();
-protected:
- void Log(const wxString& command, const wxString& topic, const wxString& item, const void *data, size_t size, wxIPCFormat format);
+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;
-public:
- wxString m_sAdvise;
+ // the item which can be manipulated by the client via Poke() calls
+ wxString m_item;
-protected:
- wxString m_sRequestDate;
- char m_achRequestBytes[3];
+ // should we notify the client about changes to m_item?
+ bool m_advise;
+
+ wxDECLARE_NO_COPY_CLASS(BenchConnection);
};
-class MyServer: public wxServer
+// 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; };
- MyConnection *GetConnection() { return m_connection; };
- wxConnectionBase *OnAcceptConnection(const wxString& topic);
+
+ virtual wxConnectionBase *OnAcceptConnection(const wxString& topic);
+
+private:
+ wxConnection *m_connection;
+};
+
+// Define a new application
+class MyApp : public wxApp
+{
+public:
+ virtual bool OnInit();
protected:
- MyConnection *m_connection;
+ MyServer m_server;
};
+DECLARE_APP(MyApp)
+
// ============================================================================
// implementation
// ============================================================================
-IMPLEMENT_APP(MyApp)
+IMPLEMENT_APP_CONSOLE(MyApp)
// ----------------------------------------------------------------------------
// MyApp
delete wxLog::SetActiveTarget(new wxLogStderr);
- // Create a new server
- m_server = new MyServer;
- if (m_server->Create("4242"))
- {
- wxLogMessage(_T("Server 4242 started"));
+ const char * const kind =
#if wxUSE_DDE_FOR_IPC
- wxLogMessage(_T("Server uses DDE"));
-#else // !wxUSE_DDE_FOR_IPC
- wxLogMessage(_T("Server uses TCP"));
-#endif // wxUSE_DDE_FOR_IPC/!wxUSE_DDE_FOR_IPC
- return true;
- }
- else
+ "DDE"
+#else
+ "TCP"
+#endif
+ ;
+
+ // Create a new server
+ if ( !m_server.Create(IPC_SERVICE) )
{
- wxLogMessage(_T("Server 4242 failed to start"));
- delete m_server;
+ wxLogMessage("%s server failed to start on %s", kind, IPC_SERVICE);
return false;
}
-}
-int MyApp::OnExit()
-{
- return 0;
+ wxLogMessage("%s server started on %s", kind, IPC_SERVICE);
+ return true;
}
// ----------------------------------------------------------------------------
wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic)
{
- wxLogMessage(_T("OnAcceptConnection(\"%s\")"), topic.c_str());
+ wxLogMessage("OnAcceptConnection(\"%s\")", topic);
if ( topic == IPC_TOPIC )
{
m_connection = new MyConnection;
- wxLogMessage(_T("Connection accepted"));
- return m_connection;
}
- // unknown topic
- return NULL;
+ 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)
+ if ( m_connection )
{
m_connection->Disconnect();
- delete m_connection;
- m_connection = NULL;
- wxLogMessage(_T("Disconnected client"));
+ wxDELETE(m_connection);
+ wxLogMessage("Disconnected client");
}
}
// MyConnection
// ----------------------------------------------------------------------------
-MyConnection::MyConnection()
+bool
+MyConnection::OnExecute(const wxString& topic,
+ const void *data,
+ size_t size,
+ wxIPCFormat format)
{
-}
-
-MyConnection::~MyConnection()
-{
-}
-
-bool MyConnection::OnExecute(const wxString& topic,
- const void *data, size_t size, wxIPCFormat format)
-{
- Log(_T("OnExecute"), topic, _T(""), data, size, 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)
+bool
+MyConnection::OnPoke(const wxString& topic,
+ const wxString& item,
+ const void *data,
+ size_t size,
+ wxIPCFormat format)
{
- Log(_T("OnPoke"), topic, item, data, size, 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 *
+MyConnection::OnRequest(const wxString& topic,
+ const wxString& item,
+ size_t *size,
+ wxIPCFormat format)
{
const void *data;
- if (item == _T("Date"))
+ if (item == "Date")
{
m_sRequestDate = wxDateTime::Now().Format();
data = m_sRequestDate.c_str();
*size = wxNO_LEN;
}
- else if (item == _T("Date+len"))
+ else if (item == "Date+len")
{
- m_sRequestDate = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
+ m_sRequestDate = wxDateTime::Now().FormatTime() +
+ " " + wxDateTime::Now().FormatDate();
data = m_sRequestDate.c_str();
*size = m_sRequestDate.Length() + 1;
}
- else if (item == _T("bytes[3]"))
+ else if (item == "bytes[3]")
{
data = m_achRequestBytes;
- m_achRequestBytes[0] = '1'; m_achRequestBytes[1] = '2'; m_achRequestBytes[2] = '3';
+ m_achRequestBytes[0] = '1';
+ m_achRequestBytes[1] = '2';
+ m_achRequestBytes[2] = '3';
*size = 3;
}
else
data = NULL;
*size = 0;
}
- Log(_T("OnRequest"), topic, item, data, *size, format);
+ Log("OnRequest", topic, item, data, *size, format);
return data;
}
-bool MyConnection::OnStartAdvise(const wxString& topic,
- const wxString& item)
+bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item)
{
- wxLogMessage(_T("OnStartAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str());
- wxLogMessage(_T("Returning true"));
+ wxLogMessage("OnStartAdvise(\"%s\",\"%s\")", topic, item);
+ wxLogMessage("Returning true");
m_sAdvise = item;
- Start(3000, false);
+ Start(3000); // schedule our Notify() to be called in 3 seconds
return true;
}
-bool MyConnection::OnStopAdvise(const wxString& topic,
- const wxString& item)
+bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item)
{
- wxLogMessage(_T("OnStopAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str());
- wxLogMessage(_T("Returning true"));
- m_sAdvise.Empty();
+ wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item);
+ wxLogMessage("Returning true");
+ m_sAdvise.clear();
Stop();
return true;
}
void MyConnection::Notify()
{
- if (!m_sAdvise.IsEmpty())
+ if (!m_sAdvise.empty())
{
wxString s = wxDateTime::Now().Format();
Advise(m_sAdvise, s);
- s = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
- Advise(m_sAdvise, (const char *)s.c_str(), s.Length() + 1);
+ s = wxDateTime::Now().FormatTime() + " "
+ + wxDateTime::Now().FormatDate();
+ Advise(m_sAdvise, s.mb_str(), s.length() + 1);
#if wxUSE_DDE_FOR_IPC
- wxLogMessage(_T("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
+ 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);
}
}
-void MyConnection::Log(const wxString& command, const wxString& topic,
- const wxString& item, const void *data, size_t size, wxIPCFormat format)
+bool MyConnection::DoAdvise(const wxString& item,
+ const void *data,
+ size_t size,
+ wxIPCFormat format)
{
- wxString s;
- if (topic.IsEmpty() && item.IsEmpty())
- s.Printf(_T("%s("), command.c_str());
- else if (topic.IsEmpty())
- s.Printf(_T("%s(\"%s\","), command.c_str(), item.c_str());
- else if (item.IsEmpty())
- s.Printf(_T("%s(\"%s\","), command.c_str(), topic.c_str());
- else
- s.Printf(_T("%s(\"%s\",\"%s\","), command.c_str(), topic.c_str(), item.c_str());
+ Log("Advise", "", item, data, size, format);
+ return wxConnection::DoAdvise(item, data, size, format);
+}
- switch (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 )
{
- case wxIPC_TEXT:
- case wxIPC_UTF8TEXT:
-#if !wxUSE_UNICODE || wxUSE_UNICODE_UTF8
- wxLogMessage(_T("%s\"%s\",%d)"), s.c_str(), data, size);
-#else
- wxLogMessage(_T("%s\"%s\",%d)"), s.c_str(), wxConvUTF8.cMB2WC((const char*)data), size);
-#endif
- break;
- case wxIPC_PRIVATE:
- if (size == 3)
+ 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) )
{
- char *bytes = (char *)data;
- wxLogMessage(_T("%s'%c%c%c',%d)"), s.c_str(), bytes[0], bytes[1], bytes[2], size);
+ wxLogMessage("Failed to advise client about the change.");
}
- else
- wxLogMessage(_T("%s...,%d)"), s.c_str(), size);
- break;
- case wxIPC_INVALID:
- wxLogMessage(_T("%s[invalid data],%d)"), s.c_str(), size);
- break;
- default:
- wxLogMessage(_T("%s[unknown data],%d)"), s.c_str(), size);
- break;
}
+
+ return true;
}
-bool MyConnection::DoAdvise(const wxString& item, const void *data, size_t size, wxIPCFormat format)
+bool BenchConnection::OnStartAdvise(const wxString& topic, const wxString& item)
{
- Log(_T("Advise"), _T(""), item, data, size, format);
- return wxConnection::DoAdvise(item, data, size, format);
+ if ( !IsSupportedTopicAndItem("OnStartAdvise", topic, item) )
+ return false;
+
+ m_advise = true;
+
+ return true;
}
-bool MyConnection::OnDisconnect()
+bool BenchConnection::OnStopAdvise(const wxString& topic, const wxString& item)
{
- wxLogMessage(_T("OnDisconnect()"));
+ if ( !IsSupportedTopicAndItem("OnStopAdvise", topic, item) )
+ return false;
+
+ m_advise = false;
+
return true;
}
+