X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/70d26c3f4ffb24d50457d405c9595fd23f9e5b7c..14619f10b0bdb630206607abd0ce0319d45e095a:/samples/ipc/server.cpp diff --git a/samples/ipc/server.cpp b/samples/ipc/server.cpp index 3dfb36562f..47b2d62ee6 100644 --- a/samples/ipc/server.cpp +++ b/samples/ipc/server.cpp @@ -1,198 +1,391 @@ ///////////////////////////////////////////////////////////////////////////// // Name: server.cpp -// Purpose: DDE sample: server +// Purpose: IPC sample: server // Author: Julian Smart -// Modified by: +// 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 + #pragma hdrstop #endif #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/wx.h" #endif // Settings common to both executables: determines whether // we're using TCP/IP or real DDE. +#include "ipcsetup.h" -#include "ddesetup.h" - -#if defined(__WXGTK__) || defined(__WXMOTIF__) -#include "mondrian.xpm" +#ifndef wxHAS_IMAGES_IN_RESOURCES + #include "../sample.xpm" #endif #include "server.h" +#include "wx/textdlg.h" +#include "wx/datetime.h" -MyFrame *frame = NULL; +// ---------------------------------------------------------------------------- +// wxWin macros +// ---------------------------------------------------------------------------- IMPLEMENT_APP(MyApp) -char ipc_buffer[4000]; -MyConnection *the_connection = NULL; -MyServer *my_server ; +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() { - // Create the main frame window - frame = new MyFrame(NULL, "Server", wxDefaultPosition, wxSize(400, 500)); + 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; - frame->CreateStatusBar(); + wxPanel * const panel = new wxPanel(this); - // Give it an icon - frame->SetIcon(wxICON(mondrian)); + wxBoxSizer * const sizerMain = new wxBoxSizer( wxVERTICAL ); - // Make a menubar - wxMenu *file_menu = new wxMenu; + wxFlexGridSizer * const sizerCmds = new wxFlexGridSizer( 2, 0, 0 ); + sizerCmds->AddGrowableCol( 1 ); - file_menu->Append(SERVER_QUIT, "&Exit"); + wxButton *btn; - wxMenuBar *menu_bar = new wxMenuBar; + btn = new wxButton(panel, ID_START, "&Start Server"); + sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); - menu_bar->Append(file_menu, "&File"); + 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); - // Associate the menu bar with the frame - frame->SetMenuBar(menu_bar); + btn = new wxButton(panel, ID_DISCONNECT, "&Disconnect Client"); + sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); + sizerCmds->AddSpacer(20); - // Make a panel - frame->panel = new wxPanel(frame, 0, 0, 400, 250); - wxListBox *list = new wxListBox(frame->panel, SERVER_LISTBOX, - wxPoint(5, 5), wxSize(150, 120)); - list->Append("Apple"); - list->Append("Pear"); - list->Append("Orange"); - list->Append("Banana"); - list->Append("Fruit"); + btn = new wxButton( panel, ID_ADVISE, "&Advise"); + sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); + sizerCmds->AddSpacer(20); - frame->panel->Fit(); - frame->Fit(); + sizerMain->Add(sizerCmds, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); - wxString server_name = "4242"; - if (argc > 1) - server_name = argv[1]; + wxStaticBoxSizer * const + sizerLog = new wxStaticBoxSizer(wxVERTICAL, panel, "Server &log"); - // Create a new server - my_server = new MyServer; - my_server->Create(server_name); - frame->Show(TRUE); + wxTextCtrl * const textLog = new wxTextCtrl + ( + panel, + wxID_ANY, + "", + wxDefaultPosition, wxSize(500, 140), + wxTE_MULTILINE + ); + sizerLog->Add(textLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); - return TRUE; + 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(); } -BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(SERVER_QUIT, MyFrame::OnExit) - EVT_CLOSE(MyFrame::OnCloseWindow) - EVT_LISTBOX(SERVER_LISTBOX, MyFrame::OnListBoxClick) -END_EVENT_TABLE() +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()); +} -// Define my frame constructor -MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size): - wxFrame(frame, -1, title, pos, size) +void MyFrame::OnClose(wxCloseEvent& event) { - panel = NULL; + wxDELETE(m_server); + event.Skip(); } -void MyFrame::OnExit(wxCommandEvent& event) +void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event)) { - if (my_server) - delete my_server; - this->Destroy(); + // 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); + wxDELETE(m_server); + } + UpdateUI(); } -// Set the client process's listbox to this item -void MyFrame::OnListBoxClick(wxCommandEvent& event) +void MyFrame::OnServerName( wxCommandEvent& WXUNUSED(event) ) { - wxListBox* listBox = (wxListBox*) panel->FindWindow(SERVER_LISTBOX); - if (listBox) + if ( GetServername()->GetStringSelection() == "..." ) { - wxString value = listBox->GetStringSelection(); - if (the_connection) + wxString s = wxGetTextFromUser + ( + "Specify the name of the server", + "Server Name", + "", + this + ); + + if ( !s.empty() && s != IPC_SERVICE ) { - the_connection->Advise("Item", (char*) (const char*) value); + GetServername()->Insert(s, 0); + GetServername()->SetSelection(0); } } } -void MyFrame::OnCloseWindow(wxCloseEvent& event) +void MyFrame::Disconnect() { - if (my_server) - delete my_server; - this->Destroy(); + m_server->Disconnect(); + UpdateUI(); } -BEGIN_EVENT_TABLE(IPCDialogBox, wxDialog) - EVT_BUTTON(SERVER_QUIT_BUTTON, IPCDialogBox::OnQuit) -END_EVENT_TABLE() +void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event)) +{ + Disconnect(); +} + +void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event)) +{ + m_server->Advise(); +} + +// ---------------------------------------------------------------------------- +// MyServer +// ---------------------------------------------------------------------------- -IPCDialogBox::IPCDialogBox(wxFrame *parent, const wxString& title, - const wxPoint& pos, const wxSize& size, MyConnection *the_connection): - wxDialog(parent, -1, title, pos, size) +MyServer::MyServer() : wxServer() { - connection = the_connection; - (void)new wxButton(this, SERVER_QUIT_BUTTON, "Quit this connection", wxPoint(5, 5)); - Fit(); + m_connection = NULL; } -void IPCDialogBox::OnQuit(wxCommandEvent& event) +MyServer::~MyServer() { - connection->Disconnect(); - delete connection; + Disconnect(); } wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic) { - if (strcmp(topic, "STDIO") != 0 && strcmp(topic, "IPC TEST") == 0) - return new MyConnection(ipc_buffer, 4000); - else + 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; } -MyConnection::MyConnection(char *buf, int size):wxConnection(buf, size) +void MyServer::Disconnect() { - dialog = new IPCDialogBox(frame, "Connection", wxPoint(100, 100), wxSize(500, 500), this); - dialog->Show(TRUE); - the_connection = this; + if ( m_connection ) + { + wxDELETE(m_connection); + wxGetApp().GetFrame()->UpdateUI(); + wxLogMessage("Disconnected client"); + } } -MyConnection::~MyConnection(void) +void MyServer::Advise() { - if (the_connection) - { - dialog->Destroy(); - the_connection = NULL; - } + 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); + } } -bool MyConnection::OnExecute(const wxString& topic, char *data, int size, wxIPCFormat format) +// ---------------------------------------------------------------------------- +// MyConnection +// ---------------------------------------------------------------------------- + +bool +MyConnection::OnExecute(const wxString& topic, + const void *data, + size_t size, + wxIPCFormat format) { - char buf[300]; - sprintf(buf, "Execute command: %s", data); - frame->SetStatusText(buf); - return TRUE; + Log("OnExecute", topic, "", data, size, format); + return true; } -bool MyConnection::OnPoke(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format) +bool +MyConnection::OnPoke(const wxString& topic, + const wxString& item, + const void *data, + size_t size, + wxIPCFormat format) { - char buf[300]; - sprintf(buf, "Poke command: %s", data); - frame->SetStatusText(buf); - return TRUE; + Log("OnPoke", topic, item, data, size, format); + return wxConnection::OnPoke(topic, item, data, size, format); } -char *MyConnection::OnRequest(const wxString& topic, const wxString& item, int *size, wxIPCFormat format) +const void * +MyConnection::OnRequest(const wxString& topic, + const wxString& item, + size_t *size, + wxIPCFormat format) { - return "Here, have your data, client!"; + *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) { - return TRUE; + 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; +}