git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49281 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			434 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /////////////////////////////////////////////////////////////////////////////
 | |
| // 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(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
 | |
|     #include "mondrian.xpm"
 | |
| #endif
 | |
| 
 | |
| #include "server.h"
 | |
| #include "wx/textdlg.h"
 | |
| #include "wx/datetime.h"
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // wxWin macros
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| IMPLEMENT_APP(MyApp)
 | |
| 
 | |
| BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 | |
|     EVT_MENU   (wxID_EXIT,         MyFrame::OnExit)
 | |
|     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, _T("Server"));
 | |
|     m_frame->Show(true);
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| int MyApp::OnExit()
 | |
| {
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // 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
 | |
| 
 | |
|     // Give it an icon
 | |
|     SetIcon(wxICON(mondrian));
 | |
| 
 | |
|     // Make a menubar
 | |
|     wxMenu *file_menu = new wxMenu;
 | |
| 
 | |
|     file_menu->Append(wxID_EXIT, _T("&Quit\tCtrl-Q"));
 | |
| 
 | |
|     wxMenuBar *menu_bar = new wxMenuBar;
 | |
| 
 | |
|     menu_bar->Append(file_menu, _T("&File"));
 | |
| 
 | |
|     // Associate the menu bar with the frame
 | |
|     SetMenuBar(menu_bar);
 | |
| 
 | |
|     // set a dialog background
 | |
|     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
 | |
| 
 | |
|     // add the controls to the frame
 | |
|     wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL );
 | |
| 
 | |
|     wxBoxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
 | |
| 
 | |
|     wxFlexGridSizer *item2 = new wxFlexGridSizer( 2, 0, 0 );
 | |
|     item2->AddGrowableCol( 1 );
 | |
| 
 | |
|     wxButton *item3 = new wxButton( this, ID_START, wxT("Start Server"), wxDefaultPosition, wxDefaultSize, 0 );
 | |
|     item2->Add( item3, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     wxString strs4[] = 
 | |
|     {
 | |
|         IPC_SERVICE, _T("...")
 | |
|     };
 | |
|     wxChoice *item4 = new wxChoice( this, ID_SERVERNAME, wxDefaultPosition, wxSize(100,-1), 2, strs4, 0 );
 | |
|     item2->Add( item4, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     wxButton *item5 = new wxButton( this, ID_DISCONNECT, wxT("Disconnect Client"), wxDefaultPosition, wxDefaultSize, 0 );
 | |
|     item2->Add( item5, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     item2->Add( 20, 20, 0, wxALIGN_CENTER|wxALL, 5 );
 | |
| 
 | |
|     wxButton *item6 = new wxButton( this, ID_ADVISE, wxT("Advise"), wxDefaultPosition, wxDefaultSize, 0 );
 | |
|     item2->Add( item6, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     item2->Add( 20, 20, 0, wxALIGN_CENTER|wxALL, 5 );
 | |
| 
 | |
|     item1->Add( item2, 1, wxALIGN_CENTER|wxALL, 5 );
 | |
| 
 | |
|     item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     wxStaticBox *item8 = new wxStaticBox( this, -1, wxT("Server log") );
 | |
|     wxStaticBoxSizer *item7 = new wxStaticBoxSizer( item8, wxVERTICAL );
 | |
| 
 | |
|     wxTextCtrl *item9 = new wxTextCtrl( this, ID_LOG, wxT(""), wxDefaultPosition, wxSize(500,140), wxTE_MULTILINE );
 | |
|     item7->Add( item9, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     item0->Add( item7, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
 | |
| 
 | |
|     SetSizer( item0 );
 | |
|     item0->SetSizeHints( this );
 | |
| 
 | |
|     // status
 | |
|     m_server = NULL;
 | |
|     GetServername()->SetSelection(0);
 | |
|     wxLogTextCtrl *logWindow = new wxLogTextCtrl(GetLog());
 | |
|     delete wxLog::SetActiveTarget(logWindow);
 | |
|     wxLogMessage(_T("Click on Start to start the server"));
 | |
|     Enable();
 | |
| }
 | |
| 
 | |
| void MyFrame::Enable()
 | |
| {
 | |
|     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::OnExit(wxCommandEvent& WXUNUSED(event))
 | |
| {
 | |
|     Close(true);
 | |
| }
 | |
| 
 | |
| void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event))
 | |
| {
 | |
|     // Create a new server
 | |
|     m_server = new MyServer;
 | |
|     wxString servername = GetServername()->GetStringSelection();
 | |
|     if (m_server->Create(servername))
 | |
|     {
 | |
|         wxLogMessage(_T("Server %s started"), servername.c_str());
 | |
|   #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
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         wxLogMessage(_T("Server %s failed to start"), servername.c_str());
 | |
|         delete m_server;
 | |
|         m_server = NULL;
 | |
|     }
 | |
|     Enable();
 | |
| }
 | |
| 
 | |
| void MyFrame::OnServerName( wxCommandEvent& WXUNUSED(event) )
 | |
| {
 | |
|     if (GetServername()->GetStringSelection() == _T("..."))
 | |
|     {
 | |
|         wxString s = wxGetTextFromUser(_T("Specify the name of the server"),
 | |
|             _T("Server Name"), _(""), this);
 | |
|         if (!s.IsEmpty() && s != IPC_SERVICE)
 | |
|         {
 | |
|             GetServername()->Insert(s, 0);
 | |
|             GetServername()->SetSelection(0);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void MyFrame::Disconnect()
 | |
| {
 | |
|     m_server->Disconnect();
 | |
|     Enable();
 | |
| }
 | |
| 
 | |
| 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(_T("OnAcceptConnection(\"%s\")"), topic.c_str());
 | |
| 
 | |
|     if ( topic == IPC_TOPIC )
 | |
|     {
 | |
|         m_connection = new MyConnection();
 | |
|         wxGetApp().GetFrame()->Enable();
 | |
|         wxLogMessage(_T("Connection accepted"));
 | |
|         return m_connection;
 | |
|     }
 | |
|     // unknown topic
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| void MyServer::Disconnect()
 | |
| {
 | |
|     if (m_connection)
 | |
|     {
 | |
|         m_connection->Disconnect();
 | |
|         delete m_connection;
 | |
|         m_connection = NULL;
 | |
|         wxGetApp().GetFrame()->Enable();
 | |
|         wxLogMessage(_T("Disconnected client"));
 | |
|     }
 | |
| }
 | |
| 
 | |
| void MyServer::Advise()
 | |
| {
 | |
|     if (CanAdvise())
 | |
|     {
 | |
|         wxString s = wxDateTime::Now().Format();
 | |
|         m_connection->Advise(m_connection->m_sAdvise, s);
 | |
|         s = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
 | |
|         m_connection->Advise(m_connection->m_sAdvise, (const char *)s.c_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
 | |
|         char bytes[3];
 | |
|         bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3';
 | |
|         m_connection->Advise(m_connection->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 );
 | |
|     }
 | |
| }
 | |
| 
 | |
| // ----------------------------------------------------------------------------
 | |
| // MyConnection
 | |
| // ----------------------------------------------------------------------------
 | |
| 
 | |
| MyConnection::MyConnection()
 | |
|             : wxConnection()
 | |
| {
 | |
| }
 | |
| 
 | |
| MyConnection::~MyConnection()
 | |
| {
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnExecute(const wxString& topic,
 | |
|     const void *data, size_t size, wxIPCFormat format)
 | |
| {
 | |
|     Log(_T("OnExecute"), topic, _T(""), data, size, format);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| 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);
 | |
|     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 == _T("Date"))
 | |
|     {
 | |
|         m_sRequestDate = wxDateTime::Now().Format();
 | |
|         data = m_sRequestDate.c_str();
 | |
|         *size = wxNO_LEN;
 | |
|     }    
 | |
|     else if (item == _T("Date+len"))
 | |
|     {
 | |
|         m_sRequestDate = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate();
 | |
|         data = m_sRequestDate.c_str();
 | |
|         *size = m_sRequestDate.Length() + 1;
 | |
|     }    
 | |
|     else if (item == _T("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(_T("OnRequest"), topic, item, data, *size, format);
 | |
|     return data;
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnStartAdvise(const wxString& topic,
 | |
|                                  const wxString& item)
 | |
| {
 | |
|     wxLogMessage(_T("OnStartAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str());
 | |
|     wxLogMessage(_T("Returning true"));
 | |
|     m_sAdvise = item;
 | |
|     wxGetApp().GetFrame()->Enable();
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| 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();
 | |
|     wxGetApp().GetFrame()->Enable();
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void MyConnection::Log(const wxString& command, const wxString& topic,
 | |
|     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());
 | |
| 
 | |
|     switch (format)
 | |
|     {
 | |
|       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)
 | |
|         {
 | |
|             char *bytes = (char *)data;
 | |
|             wxLogMessage(_T("%s'%c%c%c',%d)"), s.c_str(), bytes[0], bytes[1], bytes[2], size);
 | |
|         }
 | |
|         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;
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool MyConnection::DoAdvise(const wxString& item, const void *data, size_t size, wxIPCFormat format)
 | |
| {
 | |
|     Log(_T("Advise"), _T(""), item, data, size, format);
 | |
|     return wxConnection::DoAdvise(item, data, size, format);
 | |
| }
 | |
| 
 | |
| bool MyConnection::OnDisconnect()
 | |
| {
 | |
|     wxLogMessage(_T("OnDisconnect()"));
 | |
|     wxGetApp().GetFrame()->Disconnect();
 | |
|     return true;
 | |
| }
 |