X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/45a50a2e8ff5d066f96fcd40ce687c420d92b0e9..e1efca652844273c3e8d32c7e5f442b87e455ca7:/samples/sockets/baseserver.cpp diff --git a/samples/sockets/baseserver.cpp b/samples/sockets/baseserver.cpp index cf879de292..ac856e80a2 100644 --- a/samples/sockets/baseserver.cpp +++ b/samples/sockets/baseserver.cpp @@ -6,7 +6,7 @@ // Created: 27.06.2005 // RCS-ID: $Id$ // Copyright: (c) 2005 Lukasz Michalski -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -26,68 +26,39 @@ #include "wx/timer.h" #include "wx/thread.h" -wxChar* GetSocketErrorMsg(int pSockError) +const char *GetSocketErrorMsg(int pSockError) { switch(pSockError) { case wxSOCKET_NOERROR: - return wxT("wxSOCKET_NOERROR"); - break; + return "wxSOCKET_NOERROR"; + case wxSOCKET_INVOP: - return wxT("wxSOCKET_INVOP"); - break; + return "wxSOCKET_INVOP"; + case wxSOCKET_IOERR: - return wxT("wxSOCKET_IOERR"); - break; + return "wxSOCKET_IOERR"; + case wxSOCKET_INVADDR: - return wxT("wxSOCKET_INVADDR"); - break; + return "wxSOCKET_INVADDR"; + case wxSOCKET_NOHOST: - return wxT("wxSOCKET_NOHOST"); - break; + return "wxSOCKET_NOHOST"; + case wxSOCKET_INVPORT: - return wxT("wxSOCKET_INVPORT"); - break; + return "wxSOCKET_INVPORT"; + case wxSOCKET_WOULDBLOCK: - return wxT("wxSOCKET_WOULDBLOCK"); - break; + return "wxSOCKET_WOULDBLOCK"; + case wxSOCKET_TIMEDOUT: - return wxT("wxSOCKET_TIMEDOUT"); - break; - case wxSOCKET_MEMERR: - return wxT("wxSOCKET_MEMERR"); - break; - default: - return wxT("Unknown"); - break; - } -} + return "wxSOCKET_TIMEDOUT"; -//log output types for LogWorker helper function -typedef enum -{ - LOG_MESSAGE, - LOG_ERROR, - LOG_VERBOSE -} logWorker_t; + case wxSOCKET_MEMERR: + return "wxSOCKET_MEMERR"; -//outputs log message with IP and TCP port number prepended -void -LogWorker(const wxIPV4address& pAddr, const wxString& pMessage, logWorker_t pType = LOG_VERBOSE) -{ - wxString msg(wxString::Format(wxT("%s:%d "),pAddr.IPAddress().c_str(),pAddr.Service())); - msg += pMessage; - switch (pType) - { - case LOG_VERBOSE: - wxLogVerbose(msg); - break; - case LOG_MESSAGE: - wxLogMessage(msg); - break; - case LOG_ERROR: - wxLogError(msg); - break; + default: + return "Unknown"; } } @@ -96,7 +67,8 @@ LogWorker(const wxIPV4address& pAddr, const wxString& pMessage, logWorker_t pTyp const wxEventType wxEVT_WORKER = wxNewEventType(); #define EVT_WORKER(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_WORKER, -1, -1, (wxObjectEventFunction) (wxEventFunction) (WorkerEventFunction) & func, (wxObject *) NULL ), -class WorkerEvent : public wxEvent { +class WorkerEvent : public wxEvent +{ public: WorkerEvent(void* pSender) { @@ -129,7 +101,7 @@ WX_DECLARE_LIST(EventWorker, EList); //and list of two type worker classes that serve clients class Server : public wxApp { - DECLARE_EVENT_TABLE(); + DECLARE_EVENT_TABLE() public: Server() : m_maxConnections(-1) {} ~Server() {} @@ -177,29 +149,42 @@ private: DECLARE_APP(Server); +// just some common things shared between ThreadWorker and EventWorker +class WorkerBase +{ +protected: + // outputs log message with IP and TCP port number prepended + void LogWorker(const wxString& msg, wxLogLevel level = wxLOG_Info) + { + wxLogGeneric(level, + "%s:%d %s", m_peer.IPAddress(), m_peer.Service(), msg); + } + + wxIPV4address m_peer; +}; + //thread based worker reads signature and all data first from connected client //and resends data to client after reading -class ThreadWorker : public wxThread +class ThreadWorker : public wxThread, private WorkerBase { public: ThreadWorker(wxSocketBase* pSocket); virtual ExitCode Entry(); + private: wxSocketBase* m_socket; - wxIPV4address m_peer; }; //event based worker reads signature and creates buffer for incoming data. //When part of data arrives this worker resends it as soon as possible. -class EventWorker : public wxEvtHandler +class EventWorker : public wxEvtHandler, private WorkerBase { - DECLARE_EVENT_TABLE(); public: EventWorker(wxSocketBase* pSock); - ~EventWorker(); + virtual ~EventWorker(); + private: wxSocketBase* m_socket; - wxIPV4address m_peer; unsigned char m_signature[2]; char* m_inbuf; @@ -212,6 +197,8 @@ private: void OnSocketEvent(wxSocketEvent& pEvent); void DoWrite(); void DoRead(); + + DECLARE_EVENT_TABLE() }; /******************* Implementation ******************/ @@ -226,10 +213,12 @@ void Server::OnInitCmdLine(wxCmdLineParser& pParser) { wxApp::OnInitCmdLine(pParser); - pParser.AddSwitch(wxT("t"),wxT("threads"),_("Use thread based workers only")); - pParser.AddSwitch(wxT("e"),wxT("events"),_("Use event based workers only")); - pParser.AddOption(wxT("m"),wxT("max"),_("Exit after connections"),wxCMD_LINE_VAL_NUMBER,wxCMD_LINE_PARAM_OPTIONAL); - pParser.AddOption(wxT("p"),wxT("port"),_("listen on given port (default 3000)"),wxCMD_LINE_VAL_NUMBER,wxCMD_LINE_PARAM_OPTIONAL); + pParser.AddSwitch("t","threads","Use thread based workers only"); + pParser.AddSwitch("e","events","Use event based workers only"); + pParser.AddOption("m","max","Exit after connections", + wxCMD_LINE_VAL_NUMBER); + pParser.AddOption("p","port","listen on given port (default 3000)", + wxCMD_LINE_VAL_NUMBER); } void @@ -239,25 +228,37 @@ Server::DumpStatistics() switch(m_workMode) { case EVENTS: - mode = _("Event based workers"); + mode = "Event based workers"; break; case THREADS: - mode = _("Thread based workers"); + mode = "Thread based workers"; break; case MIXED: - mode = _("Event and thread based workers"); + mode = "Event and thread based workers"; break; } - wxLogMessage(wxString::Format(wxT("Server mode: %s"),mode.c_str())); - wxLogMessage(wxString::Format(wxT("\t\t\t\tThreads\tEvents\tTotal"))); - wxLogMessage(wxString::Format(wxT("Workers created:\t\t%d\t%d\t%d"),m_threadWorkersCreated,m_eventWorkersCreated,m_threadWorkersCreated+m_eventWorkersCreated)); - wxLogMessage(wxString::Format(wxT("Max concurrent workers:\t%d\t%d\t%d"),m_maxThreadWorkers,m_maxEventWorkers,m_maxThreadWorkers+m_maxEventWorkers)); - wxLogMessage(wxString::Format(wxT("Workers failed:\t\t%d\t%d\t%d"),m_threadWorkersFailed,m_eventWorkersFailed,m_threadWorkersFailed+m_eventWorkersFailed)); - wxLogMessage(wxString::Format(wxT("Workers done:\t\t%d\t%d\t%d"),m_threadWorkersDone,m_eventWorkersDone,m_threadWorkersDone+m_eventWorkersDone)); + wxLogMessage("Server mode: %s",mode); + wxLogMessage("\t\t\t\tThreads\tEvents\tTotal"); + wxLogMessage("Workers created:\t\t%d\t%d\t%d", + m_threadWorkersCreated, + m_eventWorkersCreated, + m_threadWorkersCreated + m_eventWorkersCreated); + wxLogMessage("Max concurrent workers:\t%d\t%d\t%d", + m_maxThreadWorkers, + m_maxEventWorkers, + m_maxThreadWorkers + m_maxEventWorkers); + wxLogMessage("Workers failed:\t\t%d\t%d\t%d", + m_threadWorkersFailed, + m_eventWorkersFailed, + m_threadWorkersFailed + m_eventWorkersFailed); + wxLogMessage("Workers done:\t\t%d\t%d\t%d", + m_threadWorkersDone, + m_eventWorkersDone, + m_threadWorkersDone + m_eventWorkersDone); if ((int)(m_threadWorkersDone+m_eventWorkersDone) == m_maxConnections) { - wxLogMessage(wxT("%d connection(s) served, exiting"),m_maxConnections); + wxLogMessage("%d connection(s) served, exiting",m_maxConnections); ExitMainLoop(); } } @@ -266,29 +267,29 @@ Server::DumpStatistics() bool Server::OnCmdLineParsed(wxCmdLineParser& pParser) { - if (pParser.Found(_("verbose"))) + if (pParser.Found("verbose")) { - wxLog::AddTraceMask(wxT("wxSocket")); - wxLog::AddTraceMask(wxT("epolldispatcher")); - wxLog::AddTraceMask(wxT("selectdispatcher")); - wxLog::AddTraceMask(wxT("thread")); - wxLog::AddTraceMask(wxT("events")); - wxLog::AddTraceMask(wxT("timer")); + wxLog::AddTraceMask("wxSocket"); + wxLog::AddTraceMask("epolldispatcher"); + wxLog::AddTraceMask("selectdispatcher"); + wxLog::AddTraceMask("thread"); + wxLog::AddTraceMask("events"); + wxLog::AddTraceMask("timer"); } - if (pParser.Found(wxT("m"),&m_maxConnections)) + if (pParser.Found("m",&m_maxConnections)) { - wxLogMessage(wxT("%d connection(s) to exit"),m_maxConnections); + wxLogMessage("%d connection(s) to exit",m_maxConnections); } - if (pParser.Found(wxT("p"),&m_port)) + if (pParser.Found("p",&m_port)) { - wxLogMessage(wxT("%d connection(s) to exit"),m_maxConnections); + wxLogMessage("%d connection(s) to exit",m_maxConnections); } - if (pParser.Found(wxT("t"))) + if (pParser.Found("t")) m_workMode = THREADS; - else if (pParser.Found(wxT("e"))) + else if (pParser.Found("e")) m_workMode = EVENTS; else m_workMode = MIXED; @@ -314,9 +315,9 @@ bool Server::OnInit() m_listeningSocket->SetEventHandler(*this); m_listeningSocket->SetNotify(wxSOCKET_CONNECTION_FLAG); m_listeningSocket->Notify(true); - if (!m_listeningSocket->Ok()) + if (!m_listeningSocket->IsOk()) { - wxLogError(wxT("Cannot bind listening socket")); + wxLogError("Cannot bind listening socket"); return false; } @@ -330,19 +331,25 @@ bool Server::OnInit() m_eventWorkersFailed = 0; m_maxEventWorkers = 0; - wxLogMessage(wxT("Server listening at port %d, waiting for connections"), m_port); + wxLogMessage("Server listening at port %d, waiting for connections", m_port); return true; } int Server::OnExit() { - for(TList::compatibility_iterator it = m_threadWorkers.GetFirst(); it ; it = it->GetNext()) { + for ( TList::compatibility_iterator it = m_threadWorkers.GetFirst(); + it; + it = it->GetNext() ) + { it->GetData()->Wait(); delete it->GetData(); } - for(EList::compatibility_iterator it2 = m_eventWorkers.GetFirst(); it2 ; it2->GetNext()) { + for ( EList::compatibility_iterator it2 = m_eventWorkers.GetFirst(); + it2; + it2->GetNext() ) + { delete it2->GetData(); } @@ -357,10 +364,10 @@ void Server::OnSocketEvent(wxSocketEvent& pEvent) switch(pEvent.GetSocketEvent()) { case wxSOCKET_INPUT: - wxLogError(wxT("Unexpected wxSOCKET_INPUT in wxSocketServer")); - break; + wxLogError("Unexpected wxSOCKET_INPUT in wxSocketServer"); + break; case wxSOCKET_OUTPUT: - wxLogError(wxT("Unexpected wxSOCKET_OUTPUT in wxSocketServer")); + wxLogError("Unexpected wxSOCKET_OUTPUT in wxSocketServer"); break; case wxSOCKET_CONNECTION: { @@ -368,9 +375,9 @@ void Server::OnSocketEvent(wxSocketEvent& pEvent) wxIPV4address addr; if (!sock->GetPeer(addr)) { - wxLogError(wxT("Server: cannot get peer info")); + wxLogError("Server: cannot get peer info"); } else { - wxLogMessage(wxT("Got connection from %s:%d"),addr.IPAddress().c_str(), addr.Service()); + wxLogMessage("Got connection from %s:%d",addr.IPAddress().c_str(), addr.Service()); } bool createThread; @@ -392,7 +399,7 @@ void Server::OnSocketEvent(wxSocketEvent& pEvent) } else { - wxLogError(wxT("Server: cannot create next thread (current threads: %d"), m_threadWorkers.size()); + wxLogError("Server: cannot create next thread (current threads: %d", m_threadWorkers.size()); }; } else @@ -406,19 +413,20 @@ void Server::OnSocketEvent(wxSocketEvent& pEvent) } break; case wxSOCKET_LOST: - wxLogError(wxT("Unexpected wxSOCKET_LOST in wxSocketServer")); + wxLogError("Unexpected wxSOCKET_LOST in wxSocketServer"); break; } } void Server::OnWorkerEvent(WorkerEvent& pEvent) { - //wxLogMessage(wxT("Got worker event")); + //wxLogMessage("Got worker event"); for(TList::compatibility_iterator it = m_threadWorkers.GetFirst(); it ; it = it->GetNext()) { if (it->GetData() == pEvent.m_sender) { - wxLogVerbose(wxT("Deleting thread worker (%d left)"),m_threadWorkers.GetCount()); + wxLogVerbose("Deleting thread worker (%d left)", + m_threadWorkers.GetCount()); it->GetData()->Wait(); delete it->GetData(); m_threadWorkers.DeleteNode(it); @@ -433,7 +441,8 @@ void Server::OnWorkerEvent(WorkerEvent& pEvent) { if (it2->GetData() == pEvent.m_sender) { - wxLogVerbose(wxT("Deleting event worker (%d left)"),m_eventWorkers.GetCount()); + wxLogVerbose("Deleting event worker (%d left)", + m_eventWorkers.GetCount()); delete it2->GetData(); m_eventWorkers.DeleteNode(it2); if (!pEvent.m_workerFailed) @@ -478,26 +487,26 @@ wxThread::ExitCode ThreadWorker::Entry() WorkerEvent e(this); if (!m_socket->IsConnected()) { - LogWorker(m_peer,wxT("ThreadWorker: not connected"),LOG_ERROR); + LogWorker("ThreadWorker: not connected",wxLOG_Error); return 0; } int to_process = -1; if (m_socket->IsConnected()) { unsigned char signature[2]; - LogWorker(m_peer,wxT("ThreadWorker: reading for data")); + LogWorker("ThreadWorker: reading for data"); to_process = 2; do { m_socket->Read(&signature,to_process); if (m_socket->Error()) { - LogWorker(m_peer,wxT("ThreadWorker: Read error"),LOG_ERROR); + LogWorker("ThreadWorker: Read error",wxLOG_Error); wxGetApp().AddPendingEvent(e); return 0; } to_process -= m_socket->LastCount(); - LogWorker(m_peer,wxString::Format(wxT("to_process: %d"),to_process)); + LogWorker(wxString::Format("to_process: %d",to_process)); } while (!m_socket->Error() && to_process != 0); @@ -510,29 +519,29 @@ wxThread::ExitCode ThreadWorker::Entry() if (signature[0] == 0xCE) { - LogWorker(m_peer,_("This server does not support test2 from GUI client"),LOG_ERROR); + LogWorker("This server does not support test2 from GUI client",wxLOG_Error); e.m_workerFailed = true; e.m_exit = true; return 0; } int size = signature[1] * (signature[0] == 0xBE ? 1 : 1024); char* buf = new char[size]; - LogWorker(m_peer,wxString::Format(wxT("Message signature: chunks: %d, kilobytes: %d, size: %d (bytes)"),signature[0],signature[1],size)); + LogWorker(wxString::Format("Message signature: chunks: %d, kilobytes: %d, size: %d (bytes)",signature[0],signature[1],size)); to_process = size; - LogWorker(m_peer,wxString::Format(wxT("ThreadWorker: reading %d bytes of data"),to_process)); + LogWorker(wxString::Format("ThreadWorker: reading %d bytes of data",to_process)); do { m_socket->Read(buf,to_process); if (m_socket->Error()) { - LogWorker(m_peer,wxT("ThreadWorker: Read error"),LOG_ERROR); + LogWorker("ThreadWorker: Read error",wxLOG_Error); wxGetApp().AddPendingEvent(e); return 0; } to_process -= m_socket->LastCount(); - LogWorker(m_peer,wxString::Format(wxT("ThreadWorker: %d bytes readed, %d todo"),m_socket->LastCount(),to_process)); + LogWorker(wxString::Format("ThreadWorker: %d bytes readed, %d todo",m_socket->LastCount(),to_process)); } while(!m_socket->Error() && to_process != 0); @@ -542,17 +551,18 @@ wxThread::ExitCode ThreadWorker::Entry() do { m_socket->Write(buf,to_process); - if (m_socket->Error()) { - LogWorker(m_peer,wxT("ThreadWorker: Write error"),LOG_ERROR); + if (m_socket->Error()) + { + LogWorker("ThreadWorker: Write error",wxLOG_Error); break; - } + } to_process -= m_socket->LastCount(); - LogWorker(m_peer,wxString::Format(wxT("ThreadWorker: %d bytes written, %d todo"),m_socket->LastCount(),to_process)); + LogWorker(wxString::Format("ThreadWorker: %d bytes written, %d todo",m_socket->LastCount(),to_process)); } while(!m_socket->Error() && to_process != 0); } - LogWorker(m_peer,wxT("ThreadWorker: done")); + LogWorker("ThreadWorker: done"); e.m_workerFailed = to_process != 0; m_socket->Destroy(); wxGetApp().AddPendingEvent(e); @@ -573,37 +583,40 @@ EventWorker::EventWorker(wxSocketBase* pSock) m_socket->GetPeer(m_peer); } -EventWorker::~EventWorker() { +EventWorker::~EventWorker() +{ m_socket->Destroy(); delete [] m_inbuf; delete [] m_outbuf; } void -EventWorker::DoRead() +EventWorker::DoRead() { if (m_inbuf == NULL) { //read message header do { - m_socket->Read(m_signature,2 - m_infill); - if (m_socket->Error()) { + m_socket->Read(m_signature + m_infill, 2 - m_infill); + if (m_socket->Error()) + { if (m_socket->LastError() != wxSOCKET_WOULDBLOCK) { - LogWorker(m_peer,wxString::Format(wxT("Read error (%d): %s"),m_socket->LastError(),GetSocketErrorMsg(m_socket->LastError())),LOG_ERROR); + LogWorker(wxString::Format("Read error (%d): %s",m_socket->LastError(),GetSocketErrorMsg(m_socket->LastError())),wxLOG_Error); m_socket->Close(); } } else { m_infill += m_socket->LastCount(); - if (m_infill == 2) { + if (m_infill == 2) + { unsigned char chunks = m_signature[1]; unsigned char type = m_signature[0]; if (type == 0xCE) { - LogWorker(m_peer,_("This server does not support test2 from GUI client"),LOG_ERROR); + LogWorker("This server does not support test2 from GUI client",wxLOG_Error); m_written = -1; //wxSOCKET_LOST will interpret this as failure m_socket->Close(); } @@ -615,11 +628,12 @@ EventWorker::DoRead() m_infill = 0; m_outfill = 0; m_written = 0; - LogWorker(m_peer,wxString::Format(wxT("Message signature: len: %d, type: %s, size: %d (bytes)"),chunks,type == 0xBE ? wxT("b") : wxT("kB"),m_size)); + LogWorker(wxString::Format("Message signature: len: %d, type: %s, size: %d (bytes)",chunks,type == 0xBE ? "b" : "kB",m_size)); break; - } else + } + else { - LogWorker(m_peer,wxString::Format(wxT("Unknown test type %x"),type)); + LogWorker(wxString::Format("Unknown test type %x",type)); m_socket->Close(); } } @@ -631,25 +645,24 @@ EventWorker::DoRead() if (m_inbuf == NULL) return; //read message data - do { - if (m_size == m_infill) { + do + { + if (m_size == m_infill) + { m_signature[0] = m_signature[1] = 0x0; - delete [] m_inbuf; - m_inbuf = NULL; + wxDELETEA(m_inbuf); m_infill = 0; return; } m_socket->Read(m_inbuf + m_infill,m_size - m_infill); - if (m_socket->Error()) { + if (m_socket->Error()) + { if (m_socket->LastError() != wxSOCKET_WOULDBLOCK) { - LogWorker( - m_peer, - wxString::Format(wxT("Read error (%d): %s"), - m_socket->LastError(), - GetSocketErrorMsg(m_socket->LastError()) - ), - LOG_ERROR); + LogWorker(wxString::Format("Read error (%d): %s", + m_socket->LastError(), + GetSocketErrorMsg(m_socket->LastError())), + wxLOG_Error); m_socket->Close(); } @@ -671,34 +684,38 @@ void EventWorker::OnSocketEvent(wxSocketEvent& pEvent) { case wxSOCKET_INPUT: DoRead(); - break; + break; + case wxSOCKET_OUTPUT: - if (m_inbuf != NULL) + if ( m_outbuf ) DoWrite(); - break; + break; + case wxSOCKET_CONNECTION: - LogWorker(m_peer,wxString::Format(wxT("Unexpected wxSOCKET_CONNECTION in EventWorker")),LOG_ERROR); - break; + LogWorker("Unexpected wxSOCKET_CONNECTION in EventWorker", wxLOG_Error); + break; + case wxSOCKET_LOST: - { - LogWorker(m_peer,wxString::Format(wxT("Connection lost"))); - WorkerEvent e(this); - e.m_workerFailed = m_written != m_size; - wxGetApp().AddPendingEvent(e); - } - break; + { + LogWorker("Connection lost"); + WorkerEvent e(this); + e.m_workerFailed = m_written != m_size; + wxGetApp().AddPendingEvent(e); + } + break; } } -void EventWorker::DoWrite() { - do { +void EventWorker::DoWrite() +{ + do + { if (m_written == m_size) { - delete [] m_outbuf; - m_outbuf = NULL; - m_outfill = 0; - LogWorker(m_peer,wxString::Format(wxT("All data written"))); - return; + wxDELETEA(m_outbuf); + m_outfill = 0; + LogWorker( "All data written"); + return; } if (m_outfill - m_written == 0) { @@ -709,18 +726,18 @@ void EventWorker::DoWrite() { { if (m_socket->LastError() != wxSOCKET_WOULDBLOCK) { - LogWorker(m_peer, - wxString::Format(wxT("Write error (%d): %s"), + LogWorker( + wxString::Format("Write error (%d): %s", m_socket->LastError(), GetSocketErrorMsg(m_socket->LastError()) ) - ,LOG_ERROR + ,wxLOG_Error ); m_socket->Close(); } else { - LogWorker(m_peer,wxString::Format(wxT("Write would block, waiting for OUTPUT event"))); + LogWorker("Write would block, waiting for OUTPUT event"); } } else @@ -728,11 +745,12 @@ void EventWorker::DoWrite() { memmove(m_outbuf,m_outbuf+m_socket->LastCount(),m_outfill-m_socket->LastCount()); m_written += m_socket->LastCount(); } - LogWorker(m_peer,wxString::Format(wxT("Written %d of %d bytes, todo %d"),m_socket->LastCount(),m_size,m_size - m_written)); + LogWorker(wxString::Format("Written %d of %d bytes, todo %d", + m_socket->LastCount(),m_size,m_size - m_written)); } while (!m_socket->Error()); } BEGIN_EVENT_TABLE(EventWorker,wxEvtHandler) - EVT_SOCKET(wxID_ANY,EventWorker::OnSocketEvent) + EVT_SOCKET(wxID_ANY,EventWorker::OnSocketEvent) END_EVENT_TABLE()