///////////////////////////////////////////////////////////////////////////// // Name: server.cpp // Purpose: Simple Soap Server // Author: Guy // Modified by: // Created: 21/08/2002 // Copyright: (c) 2002 Guy // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ========================================================================== // declarations // ========================================================================== // -------------------------------------------------------------------------- // headers // -------------------------------------------------------------------------- #include #include #include "wx/wfstream.h" #include #include #include "http.h" #include "soap.h" // -------------------------------------------------------------------------- // classes // -------------------------------------------------------------------------- // Define a new application type class SoapServerApp : public wxApp { wxEvtHandler* m_server; public: virtual bool OnInit(); virtual int OnExit(); }; enum { SERVER_ID = 1001, SOCKET_ID = 1002 }; class SoapServer : public wxEvtHandler { wxSocketServer* m_server; wxFileOutputStream* m_log; protected: int GetDefaultPort() const; void AppendText(const char* str); void ProcessSoapCommand(wxSocketBase *sock); public: bool Ok() const { return m_server->Ok(); } SoapServer(); ~SoapServer(); void OnServerEvent(wxSocketEvent& event); void OnSocketEvent(wxSocketEvent& event); DECLARE_EVENT_TABLE(); }; BEGIN_EVENT_TABLE(SoapServer, wxEvtHandler) EVT_SOCKET(SERVER_ID, SoapServer::OnServerEvent) EVT_SOCKET(SOCKET_ID, SoapServer::OnSocketEvent) END_EVENT_TABLE() void SoapServer::AppendText(const char* str) { *m_log << str << "\r\n"; } void SoapServer::ProcessSoapCommand(wxSocketBase *sock) { sock->SetFlags(wxSOCKET_NOWAIT); // Read the data wxChar buf[4096]; memset(buf, 0, sizeof(buf)); unsigned int len = sock->Read(buf, sizeof(buf)).LastCount(); AppendText(buf); wxString str; if (strncmp(buf, "POST", 4) == 0) { wxString strAnswer = SoapProcessMessage(buf, len); sock->Write(strAnswer, strAnswer.Length()); AppendText(strAnswer); } else if (strncmp(buf, "GET ", 4) == 0) { str = buf; HttpProcessMessage(str, sock, *m_log); } } void SoapServer::OnServerEvent(wxSocketEvent& event) { wxString s = "OnServerEvent: "; switch(event.GetSocketEvent()) { case wxSOCKET_CONNECTION : s.Append("wxSOCKET_CONNECTION"); break; default : s.Append("Unexpected event!"); break; } AppendText(s); // Accept new connection if there is one in the pending // connections queue, else exit. We use Accept(FALSE) for // non-blocking accept (although if we got here, there // should ALWAYS be a pending connection). wxSocketBase* sock = m_server->Accept(FALSE); if (sock) { AppendText("New client connection accepted"); } else { AppendText("Error: couldn't accept a new connection"); sock->Destroy(); return; } sock->SetEventHandler(*this, SOCKET_ID); sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); sock->Notify(TRUE); } void SoapServer::OnSocketEvent(wxSocketEvent& event) { wxString s = "OnSocketEvent: "; wxSocketBase *sock = event.GetSocket(); // First, print a message switch(event.GetSocketEvent()) { case wxSOCKET_INPUT : s.Append("wxSOCKET_INPUT\n"); break; case wxSOCKET_LOST : s.Append("wxSOCKET_LOST\n"); break; default : s.Append("Unexpected event !\n"); break; } AppendText(s); // Now we process the event switch(event.GetSocketEvent()) { case wxSOCKET_INPUT: { // We disable input events, so that the test doesn't trigger // wxSocketEvent again. sock->SetNotify(wxSOCKET_LOST_FLAG); ProcessSoapCommand(sock); // Enable input events again. sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG); break; } case wxSOCKET_LOST: { // Destroy() should be used instead of delete wherever possible, // due to the fact that wxSocket uses 'delayed events' (see the // documentation for wxPostEvent) and we don't want an event to // arrive to the event handler (the frame, here) after the socket // has been deleted. Also, we might be doing some other thing with // the socket at the same time; for example, we might be in the // middle of a test or something. Destroy() takes care of all // this for us. AppendText("Deleting socket."); sock->Destroy(); break; } default: ; } } int SoapServer::GetDefaultPort() const { int nPort = 3883; wxIniConfig ini("", "", "./campo.ini"); ini.SetPath("/Server"); const wxString str = ini.Read("Dictionary", ""); const int colon = str.Find(':'); if (colon > 0) nPort = atoi(str.Mid(colon+1)); return nPort; } SoapServer::SoapServer() { // Create the address - defaults to localhost:0 initially wxIPV4address addr; addr.Service(GetDefaultPort()); // Create the socket m_server = new wxSocketServer(addr); m_log = new wxFileOutputStream("soaplog.txt"); wxString str; // We use Ok() here to see if the server is really listening if (m_server->Ok()) { // Setup the event handler and subscribe to connection events m_server->SetEventHandler(*this, SERVER_ID); m_server->SetNotify(wxSOCKET_CONNECTION_FLAG); m_server->Notify(TRUE); str << "Server listening on port " << addr.Service(); } else { str << "Could not listen to port " << addr.Service(); } AppendText(str); } SoapServer::~SoapServer() { delete m_server; delete m_log; } IMPLEMENT_APP(SoapServerApp) bool SoapServerApp::OnInit() { m_server = new SoapServer; return TRUE; } int SoapServerApp::OnExit() { delete m_server; return wxApp::OnExit(); }