X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/22a9029e2306865655c8f9f36383929fc6381ea9..27a5c702772a3a2617a1431d121f773747ecc9cc:/src/common/sckipc.cpp diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp index 50dcb26fef..0f1173baa6 100644 --- a/src/common/sckipc.cpp +++ b/src/common/sckipc.cpp @@ -53,20 +53,22 @@ namespace { -// Message codes +// Message codes (don't change them to avoid breaking the existing code using +// wxIPC protocol!) enum IPCCode { - IPC_EXECUTE = 1, - IPC_REQUEST, - IPC_POKE, - IPC_ADVISE_START, - IPC_ADVISE_REQUEST, - IPC_ADVISE, - IPC_ADVISE_STOP, - IPC_REQUEST_REPLY, - IPC_FAIL, - IPC_CONNECT, - IPC_DISCONNECT + IPC_EXECUTE = 1, + IPC_REQUEST = 2, + IPC_POKE = 3, + IPC_ADVISE_START = 4, + IPC_ADVISE_REQUEST = 5, + IPC_ADVISE = 6, + IPC_ADVISE_STOP = 7, + IPC_REQUEST_REPLY = 8, + IPC_FAIL = 9, + IPC_CONNECT = 10, + IPC_DISCONNECT = 11, + IPC_MAX }; } // anonymous namespace @@ -90,7 +92,7 @@ GetAddressFromName(const wxString& serverName, #if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__) // under Unix, if the server name looks like a path, create a AF_UNIX // socket instead of AF_INET one - if ( serverName.Find(_T('/')) != wxNOT_FOUND ) + if ( serverName.Find(wxT('/')) != wxNOT_FOUND ) { wxUNIXaddress *addr = new wxUNIXaddress; addr->Filename(serverName); @@ -117,13 +119,16 @@ GetAddressFromName(const wxString& serverName, class wxTCPEventHandler : public wxEvtHandler { public: - wxTCPEventHandler() : wxEvtHandler() {} + wxTCPEventHandler() : wxEvtHandler() { } void Client_OnRequest(wxSocketEvent& event); void Server_OnRequest(wxSocketEvent& event); +private: + void HandleDisconnect(wxTCPConnection *connection); + DECLARE_EVENT_TABLE() - DECLARE_NO_COPY_CLASS(wxTCPEventHandler) + wxDECLARE_NO_COPY_CLASS(wxTCPEventHandler); }; enum @@ -132,7 +137,38 @@ enum _SERVER_ONREQUEST_ID }; -static wxTCPEventHandler *gs_handler = NULL; +// -------------------------------------------------------------------------- +// wxTCPEventHandlerModule (private class) +// -------------------------------------------------------------------------- + +class wxTCPEventHandlerModule : public wxModule +{ +public: + wxTCPEventHandlerModule() : wxModule() { } + + // get the global wxTCPEventHandler creating it if necessary + static wxTCPEventHandler& GetHandler() + { + if ( !ms_handler ) + ms_handler = new wxTCPEventHandler; + + return *ms_handler; + } + + // as ms_handler is initialized on demand, don't do anything in OnInit() + virtual bool OnInit() { return true; } + virtual void OnExit() { wxDELETE(ms_handler); } + +private: + static wxTCPEventHandler *ms_handler; + + DECLARE_DYNAMIC_CLASS(wxTCPEventHandlerModule) + wxDECLARE_NO_COPY_CLASS(wxTCPEventHandlerModule); +}; + +IMPLEMENT_DYNAMIC_CLASS(wxTCPEventHandlerModule, wxModule) + +wxTCPEventHandler *wxTCPEventHandlerModule::ms_handler = NULL; // -------------------------------------------------------------------------- // wxIPCSocketStreams @@ -150,11 +186,11 @@ public: // ctor initializes all the streams on top of the given socket // // note that we use a bigger than default buffer size which matches the - // typical Ethernet MTU + // typical Ethernet MTU (minus TCP header overhead) wxIPCSocketStreams(wxSocketBase& sock) : m_socketStream(sock), #ifdef USE_BUFFER - m_bufferedOut(m_socketStream, 1500), + m_bufferedOut(m_socketStream, 1448), #else m_bufferedOut(m_socketStream), #endif @@ -248,7 +284,7 @@ private: wxDataInputStream m_dataIn; wxDataOutputStream m_dataOut; - DECLARE_NO_COPY_CLASS(wxIPCSocketStreams) + wxDECLARE_NO_COPY_CLASS(wxIPCSocketStreams); }; namespace @@ -305,7 +341,7 @@ public: private: wxIPCSocketStreams& m_streams; - DECLARE_NO_COPY_CLASS(IPCOutput) + wxDECLARE_NO_COPY_CLASS(IPCOutput); }; } // anonymous namespace @@ -368,7 +404,8 @@ wxConnectionBase *wxTCPClient::MakeConnection(const wxString& host, connection->m_topic = topic; connection->m_sock = client; connection->m_streams = streams; - client->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID); + client->SetEventHandler(wxTCPEventHandlerModule::GetHandler(), + _CLIENT_ONREQUEST_ID); client->SetClientData(connection); client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); client->Notify(true); @@ -469,7 +506,8 @@ bool wxTCPServer::Create(const wxString& serverName) return false; } - m_server->SetEventHandler(*gs_handler, _SERVER_ONREQUEST_ID); + m_server->SetEventHandler(wxTCPEventHandlerModule::GetHandler(), + _SERVER_ONREQUEST_ID); m_server->SetClientData(this); m_server->SetNotify(wxSOCKET_CONNECTION_FLAG); m_server->Notify(true); @@ -490,7 +528,7 @@ wxTCPServer::~wxTCPServer() { if ( remove(m_filename.fn_str()) != 0 ) { - wxLogDebug(_T("Stale AF_UNIX file '%s' left."), m_filename.c_str()); + wxLogDebug(wxT("Stale AF_UNIX file '%s' left."), m_filename.c_str()); } } #endif // __UNIX_LIKE__ @@ -576,11 +614,15 @@ const void *wxTCPConnection::Request(const wxString& item, IPCOutput(m_streams).Write(IPC_REQUEST, item, format); - int ret = m_streams->Read8(); - if ( ret == IPC_FAIL ) + const int ret = m_streams->Read8(); + if ( ret != IPC_REQUEST_REPLY ) return NULL; - return m_streams->ReadData(this, size); + // ReadData() needs a non-NULL size pointer but the client code can call us + // with NULL pointer (this makes sense if it knows that it always works + // with NUL-terminated strings) + size_t sizeFallback; + return m_streams->ReadData(this, size ? size : &sizeFallback); } bool wxTCPConnection::DoPoke(const wxString& item, @@ -605,11 +647,9 @@ bool wxTCPConnection::StartAdvise(const wxString& item) IPCOutput(m_streams).Write(IPC_ADVISE_START, item); - int ret = m_streams->Read8(); - if (ret != IPC_FAIL) - return true; - else - return false; + const int ret = m_streams->Read8(); + + return ret == IPC_ADVISE_START; } bool wxTCPConnection::StopAdvise (const wxString& item) @@ -619,12 +659,9 @@ bool wxTCPConnection::StopAdvise (const wxString& item) IPCOutput(m_streams).Write(IPC_ADVISE_STOP, item); - int ret = m_streams->Read8(); + const int ret = m_streams->Read8(); - if (ret != IPC_FAIL) - return true; - else - return false; + return ret == IPC_ADVISE_STOP; } // Calls that SERVER can make @@ -652,25 +689,38 @@ BEGIN_EVENT_TABLE(wxTCPEventHandler, wxEvtHandler) EVT_SOCKET(_SERVER_ONREQUEST_ID, wxTCPEventHandler::Server_OnRequest) END_EVENT_TABLE() +void wxTCPEventHandler::HandleDisconnect(wxTCPConnection *connection) +{ + // connection was closed (either gracefully or not): destroy everything + connection->m_sock->Notify(false); + connection->m_sock->Close(); + + // don't leave references to this soon-to-be-dangling connection in the + // socket as it won't be destroyed immediately as its destruction will be + // delayed in case there are more events pending for it + connection->m_sock->SetClientData(NULL); + + connection->SetConnected(false); + connection->OnDisconnect(); +} + void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) { wxSocketBase *sock = event.GetSocket(); if (!sock) - return ; + return; wxSocketNotify evt = event.GetSocketEvent(); - wxTCPConnection *connection = (wxTCPConnection *)(sock->GetClientData()); + wxTCPConnection * const + connection = static_cast(sock->GetClientData()); // This socket is being deleted; skip this event if (!connection) return; - // We lost the connection: destroy everything - if (evt == wxSOCKET_LOST) + if ( evt == wxSOCKET_LOST ) { - sock->Notify(false); - sock->Close(); - connection->OnDisconnect(); + HandleDisconnect(connection); return; } @@ -680,17 +730,21 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) const wxString topic = connection->m_topic; wxString item; + bool error = false; + const int msg = streams->Read8(); switch ( msg ) { case IPC_EXECUTE: { wxIPCFormat format; - size_t size; + size_t size wxDUMMY_INITIALIZE(0); void * const data = streams->ReadFormatData(connection, &format, &size); - - connection->OnExecute(topic, data, size, format); + if ( data ) + connection->OnExecute(topic, data, size, format); + else + error = true; } break; @@ -699,11 +753,14 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) item = streams->ReadString(); wxIPCFormat format; - size_t size; + size_t size wxDUMMY_INITIALIZE(0); void * const data = streams->ReadFormatData(connection, &format, &size); - connection->OnAdvise(topic, item, data, size, format); + if ( data ) + connection->OnAdvise(topic, item, data, size, format); + else + error = true; } break; @@ -732,10 +789,13 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) item = streams->ReadString(); wxIPCFormat format = (wxIPCFormat)streams->Read8(); - size_t size; + size_t size wxDUMMY_INITIALIZE(0); void * const data = streams->ReadData(connection, &size); - connection->OnPoke(topic, item, data, size, format); + if ( data ) + connection->OnPoke(topic, item, data, size, format); + else + error = true; } break; @@ -781,24 +841,29 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) break; case IPC_DISCONNECT: - sock->Notify(false); - sock->Close(); - connection->SetConnected(false); - connection->OnDisconnect(); + HandleDisconnect(connection); + break; + + case IPC_FAIL: + wxLogDebug("Unexpected IPC_FAIL received"); + error = true; break; default: wxLogDebug("Unknown message code %d received.", msg); - IPCOutput(streams).Write8(IPC_FAIL); + error = true; break; } + + if ( error ) + IPCOutput(streams).Write8(IPC_FAIL); } void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) { wxSocketServer *server = (wxSocketServer *) event.GetSocket(); if (!server) - return ; + return; wxTCPServer *ipcserv = (wxTCPServer *) server->GetClientData(); // This socket is being deleted; skip this event @@ -811,7 +876,7 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) // Accept the connection, getting a new socket wxSocketBase *sock = server->Accept(); if (!sock) - return ; + return; if (!sock->Ok()) { sock->Destroy(); @@ -841,7 +906,8 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) new_connection->m_sock = sock; new_connection->m_streams = streams; new_connection->m_topic = topic; - sock->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID); + sock->SetEventHandler(wxTCPEventHandlerModule::GetHandler(), + _CLIENT_ONREQUEST_ID); sock->SetClientData(new_connection); sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); sock->Notify(true); @@ -863,19 +929,4 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) sock->Destroy(); } -// -------------------------------------------------------------------------- -// wxTCPEventHandlerModule (private class) -// -------------------------------------------------------------------------- - -class wxTCPEventHandlerModule: public wxModule -{ -public: - virtual bool OnInit() { gs_handler = new wxTCPEventHandler; return true; } - virtual void OnExit() { wxDELETE(gs_handler); } - - DECLARE_DYNAMIC_CLASS(wxTCPEventHandlerModule) -}; - -IMPLEMENT_DYNAMIC_CLASS(wxTCPEventHandlerModule, wxModule) - #endif // wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS