1///////////////////////////////////////////////////////////////////////////// 2// Name: server.cpp 3// Purpose: IPC sample: server 4// Author: Julian Smart 5// Modified by: Jurgen Doornik 6// Created: 25/01/99 7// RCS-ID: $Id: server.cpp 36266 2005-11-27 14:03:36Z VZ $ 8// Copyright: (c) Julian Smart 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20// For compilers that support precompilation, includes "wx.h". 21#include "wx/wxprec.h" 22 23#ifdef __BORLANDC__ 24 #pragma hdrstop 25#endif 26 27#ifndef WX_PRECOMP 28 #include "wx/wx.h" 29#endif 30 31// Settings common to both executables: determines whether 32// we're using TCP/IP or real DDE. 33#include "ipcsetup.h" 34 35#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__) 36 #include "mondrian.xpm" 37#endif 38 39#include "server.h" 40#include "wx/textdlg.h" 41#include "wx/datetime.h" 42 43// ---------------------------------------------------------------------------- 44// wxWin macros 45// ---------------------------------------------------------------------------- 46 47IMPLEMENT_APP(MyApp) 48 49BEGIN_EVENT_TABLE(MyFrame, wxFrame) 50 EVT_MENU (wxID_EXIT, MyFrame::OnExit) 51 EVT_CLOSE( MyFrame::OnClose ) 52 EVT_BUTTON( ID_START, MyFrame::OnStart ) 53 EVT_CHOICE( ID_SERVERNAME, MyFrame::OnServerName ) 54 EVT_BUTTON( ID_DISCONNECT, MyFrame::OnDisconnect ) 55 EVT_BUTTON( ID_ADVISE, MyFrame::OnAdvise ) 56END_EVENT_TABLE() 57 58 59// ============================================================================ 60// implementation 61// ============================================================================ 62 63// ---------------------------------------------------------------------------- 64// MyApp 65// ---------------------------------------------------------------------------- 66 67bool MyApp::OnInit() 68{ 69 // Create the main frame window 70 m_frame = new MyFrame(NULL, _T("Server")); 71 m_frame->Show(true); 72 73 return true; 74} 75 76int MyApp::OnExit() 77{ 78 return 0; 79} 80 81// ---------------------------------------------------------------------------- 82// MyFrame 83// ---------------------------------------------------------------------------- 84 85// Define my frame constructor 86MyFrame::MyFrame(wxFrame *frame, const wxString& title) 87 : wxFrame(frame, wxID_ANY, title, wxDefaultPosition, wxSize(400, 300)) 88{ 89#if wxUSE_STATUSBAR 90 CreateStatusBar(); 91#endif // wxUSE_STATUSBAR 92 93 // Give it an icon 94 SetIcon(wxICON(mondrian)); 95 96 // Make a menubar 97 wxMenu *file_menu = new wxMenu; 98 99 file_menu->Append(wxID_EXIT, _T("&Quit\tCtrl-Q")); 100 101 wxMenuBar *menu_bar = new wxMenuBar; 102 103 menu_bar->Append(file_menu, _T("&File")); 104 105 // Associate the menu bar with the frame 106 SetMenuBar(menu_bar); 107 108 // set a dialog background 109 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); 110 111 // add the controls to the frame 112 wxBoxSizer *item0 = new wxBoxSizer( wxVERTICAL ); 113 114 wxBoxSizer *item1 = new wxBoxSizer( wxHORIZONTAL ); 115 116 wxFlexGridSizer *item2 = new wxFlexGridSizer( 2, 0, 0 ); 117 item2->AddGrowableCol( 1 ); 118 119 wxButton *item3 = new wxButton( this, ID_START, wxT("Start Server"), wxDefaultPosition, wxDefaultSize, 0 ); 120 item2->Add( item3, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 121 122 wxString strs4[] = 123 { 124 IPC_SERVICE, _T("...") 125 }; 126 wxChoice *item4 = new wxChoice( this, ID_SERVERNAME, wxDefaultPosition, wxSize(100,-1), 2, strs4, 0 ); 127 item2->Add( item4, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 128 129 wxButton *item5 = new wxButton( this, ID_DISCONNECT, wxT("Disconnect Client"), wxDefaultPosition, wxDefaultSize, 0 ); 130 item2->Add( item5, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 131 132 item2->Add( 20, 20, 0, wxALIGN_CENTER|wxALL, 5 ); 133 134 wxButton *item6 = new wxButton( this, ID_ADVISE, wxT("Advise"), wxDefaultPosition, wxDefaultSize, 0 ); 135 item2->Add( item6, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 136 137 item2->Add( 20, 20, 0, wxALIGN_CENTER|wxALL, 5 ); 138 139 item1->Add( item2, 1, wxALIGN_CENTER|wxALL, 5 ); 140 141 item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 142 143 wxStaticBox *item8 = new wxStaticBox( this, -1, wxT("Server log") ); 144 wxStaticBoxSizer *item7 = new wxStaticBoxSizer( item8, wxVERTICAL ); 145 146 wxTextCtrl *item9 = new wxTextCtrl( this, ID_LOG, wxT(""), wxDefaultPosition, wxSize(500,140), wxTE_MULTILINE ); 147 item7->Add( item9, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 148 149 item0->Add( item7, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 150 151 SetSizer( item0 ); 152 item0->SetSizeHints( this ); 153 154 // status 155 m_server = NULL; 156 GetServername()->SetSelection(0); 157 wxLogTextCtrl *logWindow = new wxLogTextCtrl(GetLog()); 158 delete wxLog::SetActiveTarget(logWindow); 159 wxLogMessage(_T("Click on Start to start the server")); 160 Enable(); 161} 162 163void MyFrame::Enable() 164{ 165 GetStart()->Enable(m_server == NULL); 166 GetServername()->Enable(m_server == NULL); 167 GetAdvise()->Enable(m_server && m_server->CanAdvise()); 168 GetDisconnect()->Enable(m_server && m_server->IsConnected()); 169} 170 171void MyFrame::OnClose(wxCloseEvent& event) 172{ 173 if (m_server) 174 { 175 delete m_server; 176 m_server = NULL; 177 } 178 event.Skip(); 179} 180 181void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) 182{ 183 Close(true); 184} 185 186void MyFrame::OnStart(wxCommandEvent& WXUNUSED(event)) 187{ 188 // Create a new server 189 m_server = new MyServer; 190 wxString servername = GetServername()->GetStringSelection(); 191 if (m_server->Create(servername)) 192 { 193 wxLogMessage(_T("Server %s started"), servername.c_str()); 194 #if wxUSE_DDE_FOR_IPC 195 wxLogMessage(_T("Server uses DDE")); 196 #else // !wxUSE_DDE_FOR_IPC 197 wxLogMessage(_T("Server uses TCP")); 198 #endif // wxUSE_DDE_FOR_IPC/!wxUSE_DDE_FOR_IPC 199 } 200 else 201 { 202 wxLogMessage(_T("Server %s failed to start"), servername.c_str()); 203 delete m_server; 204 m_server = NULL; 205 } 206 Enable(); 207} 208 209void MyFrame::OnServerName( wxCommandEvent& WXUNUSED(event) ) 210{ 211 if (GetServername()->GetStringSelection() == _T("...")) 212 { 213 wxString s = wxGetTextFromUser(_T("Specify the name of the server"), 214 _T("Server Name"), _(""), this); 215 if (!s.IsEmpty() && s != IPC_SERVICE) 216 { 217 GetServername()->Insert(s, 0); 218 GetServername()->SetSelection(0); 219 } 220 } 221} 222 223void MyFrame::Disconnect() 224{ 225 m_server->Disconnect(); 226 Enable(); 227} 228 229void MyFrame::OnDisconnect(wxCommandEvent& WXUNUSED(event)) 230{ 231 Disconnect(); 232} 233 234void MyFrame::OnAdvise(wxCommandEvent& WXUNUSED(event)) 235{ 236 m_server->Advise(); 237} 238 239// ---------------------------------------------------------------------------- 240// MyServer 241// ---------------------------------------------------------------------------- 242 243MyServer::MyServer() : wxServer() 244{ 245 m_connection = NULL; 246} 247 248MyServer::~MyServer() 249{ 250 Disconnect(); 251} 252 253wxConnectionBase *MyServer::OnAcceptConnection(const wxString& topic) 254{ 255 wxLogMessage(_T("OnAcceptConnection(\"%s\")"), topic.c_str()); 256 257 if ( topic == IPC_TOPIC ) 258 { 259 m_connection = new MyConnection(); 260 wxGetApp().GetFrame()->Enable(); 261 wxLogMessage(_T("Connection accepted")); 262 return m_connection; 263 } 264 // unknown topic 265 return NULL; 266} 267 268void MyServer::Disconnect() 269{ 270 if (m_connection) 271 { 272 m_connection->Disconnect(); 273 delete m_connection; 274 m_connection = NULL; 275 wxGetApp().GetFrame()->Enable(); 276 wxLogMessage(_T("Disconnected client")); 277 } 278} 279 280void MyServer::Advise() 281{ 282 if (CanAdvise()) 283 { 284 wxString s = wxDateTime::Now().Format(); 285 m_connection->Advise(m_connection->m_sAdvise, (wxChar *)s.c_str()); 286 s = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate(); 287 m_connection->Advise(m_connection->m_sAdvise, (wxChar *)s.c_str(), (s.Length() + 1) * sizeof(wxChar)); 288 289#if wxUSE_DDE_FOR_IPC 290 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.")); 291#endif 292 char bytes[3]; 293 bytes[0] = '1'; bytes[1] = '2'; bytes[2] = '3'; 294 m_connection->Advise(m_connection->m_sAdvise, (wxChar *)bytes, 3, wxIPC_PRIVATE); 295 // this works, but the log treats it as a string now 296// m_connection->Advise(m_connection->m_sAdvise, (wxChar *)bytes, 3, wxIPC_TEXT ); 297 } 298} 299 300// ---------------------------------------------------------------------------- 301// MyConnection 302// ---------------------------------------------------------------------------- 303 304MyConnection::MyConnection() 305 : wxConnection() 306{ 307} 308 309MyConnection::~MyConnection() 310{ 311} 312 313bool MyConnection::OnExecute(const wxString& topic, 314 wxChar *data, int size, wxIPCFormat format) 315{ 316 Log(_T("OnExecute"), topic, _T(""), data, size, format); 317 return true; 318} 319 320bool MyConnection::OnPoke(const wxString& topic, 321 const wxString& item, wxChar *data, int size, wxIPCFormat format) 322{ 323 Log(_T("OnPoke"), topic, item, data, size, format); 324 return wxConnection::OnPoke(topic, item, data, size, format); 325} 326 327wxChar *MyConnection::OnRequest(const wxString& topic, 328 const wxString& item, int * size, wxIPCFormat format) 329{ 330 wxChar *data; 331 if (item == _T("Date")) 332 { 333 m_sRequestDate = wxDateTime::Now().Format(); 334 data = (wxChar *)m_sRequestDate.c_str(); 335 *size = -1; 336 } 337 else if (item == _T("Date+len")) 338 { 339 m_sRequestDate = wxDateTime::Now().FormatTime() + _T(" ") + wxDateTime::Now().FormatDate(); 340 data = (wxChar *)m_sRequestDate.c_str(); 341 *size = (m_sRequestDate.Length() + 1) * sizeof(wxChar); 342 } 343 else if (item == _T("bytes[3]")) 344 { 345 data = (wxChar *)m_achRequestBytes; 346 m_achRequestBytes[0] = '1'; m_achRequestBytes[1] = '2'; m_achRequestBytes[2] = '3'; 347 *size = 3; 348 } 349 else 350 { 351 data = NULL; 352 *size = 0; 353 } 354 Log(_T("OnRequest"), topic, item, data, *size, format); 355 return data; 356} 357 358bool MyConnection::OnStartAdvise(const wxString& topic, 359 const wxString& item) 360{ 361 wxLogMessage(_T("OnStartAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str()); 362 wxLogMessage(_T("Returning true")); 363 m_sAdvise = item; 364 wxGetApp().GetFrame()->Enable(); 365 return true; 366} 367 368bool MyConnection::OnStopAdvise(const wxString& topic, 369 const wxString& item) 370{ 371 wxLogMessage(_T("OnStopAdvise(\"%s\",\"%s\")"), topic.c_str(), item.c_str()); 372 wxLogMessage(_T("Returning true")); 373 m_sAdvise.Empty(); 374 wxGetApp().GetFrame()->Enable(); 375 return true; 376} 377 378void MyConnection::Log(const wxString& command, const wxString& topic, 379 const wxString& item, wxChar *data, int size, wxIPCFormat format) 380{ 381 wxString s; 382 if (topic.IsEmpty() && item.IsEmpty()) 383 s.Printf(_T("%s("), command.c_str()); 384 else if (topic.IsEmpty()) 385 s.Printf(_T("%s(\"%s\","), command.c_str(), item.c_str()); 386 else if (item.IsEmpty()) 387 s.Printf(_T("%s(\"%s\","), command.c_str(), topic.c_str()); 388 else 389 s.Printf(_T("%s(\"%s\",\"%s\","), command.c_str(), topic.c_str(), item.c_str()); 390 391 if (format == wxIPC_TEXT || format == wxIPC_UNICODETEXT) 392 wxLogMessage(_T("%s\"%s\",%d)"), s.c_str(), data, size); 393 else if (format == wxIPC_PRIVATE) 394 { 395 if (size == 3) 396 { 397 char *bytes = (char *)data; 398 wxLogMessage(_T("%s'%c%c%c',%d)"), s.c_str(), bytes[0], bytes[1], bytes[2], size); 399 } 400 else 401 wxLogMessage(_T("%s...,%d)"), s.c_str(), size); 402 } 403 else if (format == wxIPC_INVALID) 404 wxLogMessage(_T("%s[invalid data],%d)"), s.c_str(), size); 405} 406 407bool MyConnection::Advise(const wxString& item, wxChar *data, int size, wxIPCFormat format) 408{ 409 Log(_T("Advise"), _T(""), item, data, size, format); 410 return wxConnection::Advise(item, data, size, format); 411} 412 413bool MyConnection::OnDisconnect() 414{ 415 wxLogMessage(_T("OnDisconnect()")); 416 wxGetApp().GetFrame()->Disconnect(); 417 return true; 418} 419