///////////////////////////////////////////////////////////////////////////// // Name: server.cpp // Purpose: IPC sample: server // Author: Julian Smart // Modified by: Jurgen Doornik // Created: 25/01/99 // RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: 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" #if !defined(__WXMSW__) && !defined(__WXPM__) #include "../sample.xpm" #endif #include "server.h" #include "wx/textdlg.h" #include "wx/datetime.h" // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- IMPLEMENT_APP(MyApp) BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_CLOSE( MyFrame::OnClose ) EVT_BUTTON( ID_START, MyFrame::OnStart ) EVT_CHOICE( ID_SERVERNAME, MyFrame::OnServerName ) EVT_BUTTON( ID_DISCONNECT, MyFrame::OnDisconnect ) EVT_BUTTON( ID_ADVISE, MyFrame::OnAdvise ) END_EVENT_TABLE() // ============================================================================ // implementation // ============================================================================ // ---------------------------------------------------------------------------- // MyApp // ---------------------------------------------------------------------------- bool MyApp::OnInit() { if ( !wxApp::OnInit() ) return false; // Create the main frame window m_frame = new MyFrame(NULL, "Server"); m_frame->Show(true); return true; } // ---------------------------------------------------------------------------- // MyFrame // ---------------------------------------------------------------------------- // Define my frame constructor MyFrame::MyFrame(wxFrame *frame, const wxString& title) : wxFrame(frame, wxID_ANY, title, wxDefaultPosition, wxSize(400, 300)) { #if wxUSE_STATUSBAR CreateStatusBar(); #endif // wxUSE_STATUSBAR SetIcon(wxICON(sample)); m_server = NULL; wxPanel * const panel = new wxPanel(this); wxBoxSizer * const sizerMain = new wxBoxSizer( wxVERTICAL ); wxFlexGridSizer * const sizerCmds = new wxFlexGridSizer( 2, 0, 0 ); sizerCmds->AddGrowableCol( 1 ); wxButton *btn; btn = new wxButton(panel, ID_START, "&Start Server"); sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); const wxString choices[] = { IPC_SERVICE, "..." }; wxChoice * const choice = new wxChoice ( panel, ID_SERVERNAME, wxDefaultPosition, wxSize(100, -1), WXSIZEOF(choices), choices ); sizerCmds->Add(choice, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); btn = new wxButton(panel, ID_DISCONNECT, "&Disconnect Client"); sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); sizerCmds->AddSpacer(20); btn = new wxButton( panel, ID_ADVISE, "&Advise"); sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); sizerCmds->AddSpacer(20); sizerMain->Add(sizerCmds, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); wxStaticBoxSizer * const sizerLog = new wxStaticBoxSizer(wxVERTICAL, panel, "Server &log"); wxTextCtrl * const textLog = new wxTextCtrl ( panel, wxID_ANY, "", wxDefaultPosition, wxSize(500, 140), wxTE_MULTILINE ); sizerLog->Add(textLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); sizerMain->Add(sizerLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); panel->SetSizer(sizerMain); sizerMain->SetSizeHints(panel); SetClientSize(panel->GetSize()); GetServername()->SetSelection(0); wxLogTextCtrl *logWindow = new wxLogTextCtrl(textLog); delete wxLog::SetActiveTarget(logWindow); wxLogMessage("Click on Start to start the server"); UpdateUI(); } void MyFrame::UpdateUI() { GetStart()->Enable(m_server == NULL); GetServername()->Enable(m_server == NULL); GetAdvise()->Enable(m_server && m_server->CanAdvise()); GetDisconnect()->Enable(m_server && m_server->IsConnected()); } void MyFrame::OnClose(wxCloseEvent& event) { if (m_server) { delete m_server; m_server = NULL; } event.Skip(); } void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event)) { // Create a new server m_server = new MyServer; wxString servername = GetServername()->GetStringSelection(); if (m_server->Create(servername)) { wxLogMessage("Server %s started", servername); #if wxUSE_DDE_FOR_IPC wxLogMessage("Server uses DDE"); #else // !wxUSE_DDE_FOR_IPC wxLogMessage("Server uses TCP"); #endif // wxUSE_DDE_FOR_IPC/!wxUSE_DDE_FOR_IPC } else { wxLogMessage("Server %s failed to start", servername); delete m_server; m_server = NULL; } UpdateUI(); } void MyFrame::OnServerName( wxCommandEvent& WXUNUSED(event) ) { if ( GetServername()->GetStringSelection() == "..." ) { wxString s = wxGetTextFromUser ( "Specify the name of the server", "Server Name", "", this ); if ( !s.empty() && s != IPC_SERVICE ) { GetServername()->Insert(s, 0); GetServername()->SetSelection(0); } } } void MyFrame::Disconnect() { m_server->Disconnect(); UpdateUI(); } void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event)) { Disconnect(); } void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event)) { m_server->Advise(); } // ---------------------------------------------------------------------------- // MyServer // ---------------------------------------------------------------------------- MyServer::MyServer() : wxServer() { m_connection = NULL; } MyServer::~MyServer() { Disconnect(); } wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic) { wxLogMessage("OnAcceptConnection(\"%s\")", topic); if ( topic == IPC_TOPIC ) { m_connection = new MyConnection(); wxGetApp().GetFrame()->UpdateUI(); wxLogMessage("Connection accepted"); return m_connection; } //else: unknown topic wxLogMessage("Unknown topic, connection refused"); return NULL; } void MyServer::Disconnect() { if ( m_connection ) { delete m_connection; m_connection = NULL; wxGetApp().GetFrame()->UpdateUI(); wxLogMessage("Disconnected client"); } } void MyServer::Advise() { if ( CanAdvise() ) { const wxDateTime now = wxDateTime::Now(); m_connection->Advise(m_connection->m_advise, now.Format()); const wxString s = now.FormatTime() + " " + now.FormatDate(); m_connection->Advise(m_connection->m_advise, s.mb_str(), wxNO_LEN); #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 char bytes[3] = { '1', '2', '3' }; m_connection->Advise(m_connection->m_advise, bytes, 3, wxIPC_PRIVATE); } } // ---------------------------------------------------------------------------- // 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) { *size = 0; wxString s, afterDate; if ( item.StartsWith("Date", &afterDate) ) { const wxDateTime now = wxDateTime::Now(); if ( afterDate.empty() ) { s = now.Format(); *size = wxNO_LEN; } else if ( afterDate == "+len" ) { s = now.FormatTime() + " " + now.FormatDate(); *size = strlen(s.mb_str()) + 1; } } else if ( item == "bytes[3]" ) { s = "123"; *size = 3; } if ( !*size ) { wxLogMessage("Unknown request for \"%s\"", item); return NULL; } // store the data pointer to which we return in a member variable to ensure // that the pointer remains valid even after we return m_requestData = s.mb_str(); const void * const data = m_requestData; 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_advise = item; wxGetApp().GetFrame()->UpdateUI(); return true; } bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item) { wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item); wxLogMessage("Returning true"); m_advise.clear(); wxGetApp().GetFrame()->UpdateUI(); return true; } 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()"); wxGetApp().GetFrame()->Disconnect(); return true; }