wxWidgets/samples/ipc/baseserver.cpp

402 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
// Copyright: (c) 2007 Anders Larsen
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#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() wxOVERRIDE { return wxConnection::Disconnect(); }
virtual bool OnExecute(const wxString& topic,
const void *data,
size_t size,
wxIPCFormat format) wxOVERRIDE;
virtual const void *OnRequest(const wxString& topic,
const wxString& item,
size_t *size,
wxIPCFormat format) wxOVERRIDE;
virtual bool OnPoke(const wxString& topic,
const wxString& item,
const void *data,
size_t size,
wxIPCFormat format) wxOVERRIDE;
virtual bool OnStartAdvise(const wxString& topic, const wxString& item) wxOVERRIDE;
virtual bool OnStopAdvise(const wxString& topic, const wxString& item) wxOVERRIDE;
virtual bool DoAdvise(const wxString& item,
const void *data,
size_t size,
wxIPCFormat format) wxOVERRIDE;
virtual bool OnDisconnect() wxOVERRIDE;
virtual void Notify() wxOVERRIDE;
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) wxOVERRIDE;
virtual bool OnStartAdvise(const wxString& topic, const wxString& item) wxOVERRIDE;
virtual bool OnStopAdvise(const wxString& topic, const wxString& item) wxOVERRIDE;
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;
wxDECLARE_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) wxOVERRIDE;
private:
wxConnection *m_connection;
};
// Define a new application
class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
protected:
MyServer m_server;
};
wxDECLARE_APP(MyApp);
// ============================================================================
// implementation
// ============================================================================
wxIMPLEMENT_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();
wxDELETE(m_connection);
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;
}