X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b61d8079f54ee9fd67bd2a1e42970bc30031e20a..124a5e3e6ab203dcbed670d586dc53a28e4c97a7:/samples/ipc/server.cpp diff --git a/samples/ipc/server.cpp b/samples/ipc/server.cpp index 562f9bb9f2..4bd26352a2 100644 --- a/samples/ipc/server.cpp +++ b/samples/ipc/server.cpp @@ -2,7 +2,7 @@ // Name: server.cpp // Purpose: IPC sample: server // Author: Julian Smart -// Modified by: +// Modified by: Jurgen Doornik // Created: 25/01/99 // RCS-ID: $Id$ // Copyright: (c) Julian Smart @@ -30,13 +30,15 @@ // Settings common to both executables: determines whether // we're using TCP/IP or real DDE. -#include "ddesetup.h" +#include "ipcsetup.h" -#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__) - #include "mondrian.xpm" +#if !defined(__WXMSW__) && !defined(__WXPM__) + #include "../sample.xpm" #endif #include "server.h" +#include "wx/textdlg.h" +#include "wx/datetime.h" // ---------------------------------------------------------------------------- // wxWin macros @@ -45,19 +47,14 @@ IMPLEMENT_APP(MyApp) BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU (SERVER_EXIT, MyFrame::OnExit) - EVT_LISTBOX(SERVER_LISTBOX, MyFrame::OnListBoxClick) -END_EVENT_TABLE() + EVT_CLOSE( MyFrame::OnClose ) -BEGIN_EVENT_TABLE(IPCDialogBox, wxDialog) - EVT_BUTTON(SERVER_QUIT_BUTTON, IPCDialogBox::OnQuit) + 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() -// ---------------------------------------------------------------------------- -// global variables -// ---------------------------------------------------------------------------- - -MyConnection *the_connection = NULL; // ============================================================================ // implementation @@ -69,185 +66,332 @@ MyConnection *the_connection = NULL; bool MyApp::OnInit() { - // Create the main frame window - (new MyFrame(NULL, _T("Server")))->Show(true); - - // service name (DDE classes) or port number (TCP/IP based classes) - wxString service = IPC_SERVICE; + if ( !wxApp::OnInit() ) + return false; - if (argc > 1) - service = argv[1]; - - // Create a new server - m_server = new MyServer; - m_server->Create(service); + // Create the main frame window + m_frame = new MyFrame(NULL, "Server"); + m_frame->Show(true); return true; } -int MyApp::OnExit() -{ - delete m_server; - - return 0; -} - // ---------------------------------------------------------------------------- // MyFrame // ---------------------------------------------------------------------------- // Define my frame constructor MyFrame::MyFrame(wxFrame *frame, const wxString& title) - : wxFrame(frame, wxID_ANY, title, wxDefaultPosition, wxSize(350, 250)) + : wxFrame(frame, wxID_ANY, title, wxDefaultPosition, wxSize(400, 300)) { #if wxUSE_STATUSBAR CreateStatusBar(); #endif // wxUSE_STATUSBAR - // Give it an icon - SetIcon(wxICON(mondrian)); + 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); - // Make a menubar - wxMenu *file_menu = new wxMenu; + btn = new wxButton(panel, ID_DISCONNECT, "&Disconnect Client"); + sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); + sizerCmds->AddSpacer(20); - file_menu->Append(SERVER_EXIT, _T("&Quit\tCtrl-Q")); + btn = new wxButton( panel, ID_ADVISE, "&Advise"); + sizerCmds->Add(btn, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); + sizerCmds->AddSpacer(20); - wxMenuBar *menu_bar = new wxMenuBar; + sizerMain->Add(sizerCmds, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); - menu_bar->Append(file_menu, _T("&File")); + wxStaticBoxSizer * const + sizerLog = new wxStaticBoxSizer(wxVERTICAL, panel, "Server &log"); - // Associate the menu bar with the frame - SetMenuBar(menu_bar); + wxTextCtrl * const textLog = new wxTextCtrl + ( + panel, + wxID_ANY, + "", + wxDefaultPosition, wxSize(500, 140), + wxTE_MULTILINE + ); + sizerLog->Add(textLog, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5); - // Make a listbox - wxListBox *list = new wxListBox(this, SERVER_LISTBOX); - list->Append(_T("Apple")); - list->Append(_T("Pear")); - list->Append(_T("Orange")); - list->Append(_T("Banana")); - list->Append(_T("Fruit")); + 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(); } -// Set the client process's listbox to this item -void MyFrame::OnListBoxClick(wxCommandEvent& WXUNUSED(event)) +void MyFrame::UpdateUI() { - wxListBox* listBox = (wxListBox*) FindWindow(SERVER_LISTBOX); - if (listBox) - { - wxString value = listBox->GetStringSelection(); + GetStart()->Enable(m_server == NULL); + GetServername()->Enable(m_server == NULL); + GetAdvise()->Enable(m_server && m_server->CanAdvise()); + GetDisconnect()->Enable(m_server && m_server->IsConnected()); +} - /* Because the_connection only holds one connection, in this sample only - one connection can receive advise messages */ - if (the_connection) - { - the_connection->Advise(IPC_ADVISE_NAME, (wxChar*)value.c_str()); - } +void MyFrame::OnClose(wxCloseEvent& event) +{ + if (m_server) + { + delete m_server; + m_server = NULL; } + event.Skip(); } -void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) +void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event)) { - Close(true); + // 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(); } -// ---------------------------------------------------------------------------- -// IPCDialogBox -// ---------------------------------------------------------------------------- +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); + } + } +} -IPCDialogBox::IPCDialogBox(wxWindow *parent, const wxString& title, - const wxPoint& pos, const wxSize& size, - MyConnection *connection) - : wxDialog(parent, wxID_ANY, title, pos, size) +void MyFrame::Disconnect() { - m_connection = connection; - (void)new wxButton(this, SERVER_QUIT_BUTTON, _T("Quit this connection"), - wxPoint(5, 5)); - Fit(); + m_server->Disconnect(); + UpdateUI(); } -IPCDialogBox::~IPCDialogBox( ) +void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event)) { - // wxWidgets exit code destroys dialog before destroying the connection in - // OnExit, so make sure connection won't try to delete the dialog later. - if (m_connection) - m_connection->dialog = NULL; + Disconnect(); } -void IPCDialogBox::OnQuit(wxCommandEvent& WXUNUSED(event)) +void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event)) { - m_connection->Disconnect(); - delete m_connection; + 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 ) - return new MyConnection(); + { + m_connection = new MyConnection(); + wxGetApp().GetFrame()->UpdateUI(); + wxLogMessage("Connection accepted"); + return m_connection; + } + //else: unknown topic - // 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 // ---------------------------------------------------------------------------- -MyConnection::MyConnection() - : wxConnection() +bool +MyConnection::OnExecute(const wxString& topic, + const void *data, + size_t size, + wxIPCFormat format) { - dialog = new IPCDialogBox(wxTheApp->GetTopWindow(), _T("Connection"), - wxDefaultPosition, wxDefaultSize, this); - dialog->Show(true); - the_connection = this; + Log("OnExecute", topic, "", data, size, format); + return true; } -MyConnection::~MyConnection() +bool +MyConnection::OnPoke(const wxString& topic, + const wxString& item, + const void *data, + size_t size, + wxIPCFormat format) { - if (the_connection) + 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) ) { - if (dialog) + const wxDateTime now = wxDateTime::Now(); + + if ( afterDate.empty() ) + { + s = now.Format(); + *size = wxNO_LEN; + } + else if ( afterDate == "+len" ) { - dialog->m_connection = NULL; - dialog->Destroy(); + s = now.FormatTime() + " " + now.FormatDate(); + *size = strlen(s.mb_str()) + 1; } - the_connection = NULL; } + 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::OnExecute(const wxString& WXUNUSED(topic), - wxChar *data, - int WXUNUSED(size), - wxIPCFormat WXUNUSED(format)) +bool MyConnection::OnStartAdvise(const wxString& topic, const wxString& item) { - wxLogStatus(wxT("Execute command: %s"), data); + wxLogMessage("OnStartAdvise(\"%s\", \"%s\")", topic, item); + wxLogMessage("Returning true"); + m_advise = item; + wxGetApp().GetFrame()->UpdateUI(); return true; } -bool MyConnection::OnPoke(const wxString& WXUNUSED(topic), - const wxString& item, - wxChar *data, - int WXUNUSED(size), - wxIPCFormat WXUNUSED(format)) +bool MyConnection::OnStopAdvise(const wxString& topic, const wxString& item) { - wxLogStatus(wxT("Poke command: %s = %s"), item.c_str(), data); + wxLogMessage("OnStopAdvise(\"%s\",\"%s\")", topic, item); + wxLogMessage("Returning true"); + m_advise.clear(); + wxGetApp().GetFrame()->UpdateUI(); return true; } -wxChar *MyConnection::OnRequest(const wxString& WXUNUSED(topic), - const wxString& WXUNUSED(item), - int * WXUNUSED(size), - wxIPCFormat WXUNUSED(format)) +bool +MyConnection::DoAdvise(const wxString& item, + const void *data, + size_t size, + wxIPCFormat format) { - return _T("Here, have your data, client!"); + Log("Advise", "", item, data, size, format); + return wxConnection::DoAdvise(item, data, size, format); } -bool MyConnection::OnStartAdvise(const wxString& WXUNUSED(topic), - const wxString& WXUNUSED(item)) +bool MyConnection::OnDisconnect() { + wxLogMessage("OnDisconnect()"); + wxGetApp().GetFrame()->Disconnect(); return true; } -