X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e5b502f3a610d5d72b0fb6ca4b9cf9034d0d271b..19abad600cbfe9f0f7af81f127f36b89a80c569e:/src/common/sckipc.cpp diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp index f577b046f3..9fdd8343ef 100644 --- a/src/common/sckipc.cpp +++ b/src/common/sckipc.cpp @@ -1,16 +1,17 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: sckipc.cpp +// Name: src/common/sckipc.cpp // Purpose: Interprocess communication implementation (wxSocket version) // Author: Julian Smart // Modified by: Guilhem Lavaux (big rewrite) May 1997, 1998 // Guillermo Rodriguez (updated for wxSocket v2) Jan 2000 // (callbacks deprecated) Mar 2000 +// Vadim Zeitlin (added support for Unix sockets) Apr 2002 // Created: 1993 // RCS-ID: $Id$ // Copyright: (c) Julian Smart 1993 // (c) Guilhem Lavaux 1997, 1998 // (c) 2000 Guillermo Rodriguez -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ========================================================================== @@ -21,35 +22,28 @@ // headers // -------------------------------------------------------------------------- -#ifdef __GNUG__ -#pragma implementation "sckipc.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif +#if wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS + +#include "wx/sckipc.h" + #ifndef WX_PRECOMP -#include "wx/defs.h" + #include "wx/log.h" + #include "wx/event.h" + #include "wx/module.h" #endif -#if wxUSE_SOCKETS && wxUSE_IPC - #include #include +#include #include "wx/socket.h" -#include "wx/sckipc.h" -#include "wx/module.h" -#include "wx/event.h" -#include "wx/log.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif // -------------------------------------------------------------------------- // macros and constants @@ -74,9 +68,46 @@ enum }; #endif - // All sockets will be created with the following flags -#define SCKIPC_FLAGS (wxSOCKET_WAITALL) +#define SCKIPC_FLAGS (wxSOCKET_WAITALL|wxSOCKET_REUSEADDR) + +// headers needed for umask() +#ifdef __UNIX_LIKE__ + #include + #include +#endif // __UNIX_LIKE__ + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// get the address object for the given server name, the caller must delete it +static wxSockAddress * +GetAddressFromName(const wxString& serverName, const wxString& host = wxEmptyString) +{ + // we always use INET sockets under non-Unix systems +#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 ) + { + wxUNIXaddress *addr = new wxUNIXaddress; + addr->Filename(serverName); + + return addr; + } +#endif // Unix/!Unix + { + wxIPV4address *addr = new wxIPV4address; + addr->Service(serverName); + if ( !host.empty() ) + { + addr->Hostname(host); + } + + return addr; + } +} // -------------------------------------------------------------------------- // wxTCPEventHandler stuff (private class) @@ -85,12 +116,13 @@ enum class wxTCPEventHandler : public wxEvtHandler { public: - wxTCPEventHandler() : wxEvtHandler() {}; + wxTCPEventHandler() : wxEvtHandler() {} void Client_OnRequest(wxSocketEvent& event); void Server_OnRequest(wxSocketEvent& event); DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxTCPEventHandler) }; enum @@ -129,26 +161,29 @@ bool wxTCPClient::ValidHost(const wxString& host) } wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, - const wxString& server_name, + const wxString& serverName, const wxString& topic) { + wxSockAddress *addr = GetAddressFromName(serverName, host); + if ( !addr ) + return NULL; + wxSocketClient *client = new wxSocketClient(SCKIPC_FLAGS); wxSocketStream *stream = new wxSocketStream(*client); wxDataInputStream *data_is = new wxDataInputStream(*stream); wxDataOutputStream *data_os = new wxDataOutputStream(*stream); - wxIPV4address addr; - addr.Service(server_name); - addr.Hostname(host); + bool ok = client->Connect(*addr); + delete addr; - if (client->Connect(addr)) + if ( ok ) { unsigned char msg; - + // Send topic name, and enquire whether this has succeeded data_os->Write8(IPC_CONNECT); data_os->WriteString(topic); - + msg = data_is->Read8(); // OK! Confirmation. @@ -168,7 +203,7 @@ wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, client->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID); client->SetClientData(connection); client->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); - client->Notify(TRUE); + client->Notify(true); return connection; } else @@ -200,28 +235,96 @@ wxConnectionBase *wxTCPClient::OnMakeConnection() wxTCPServer::wxTCPServer () : wxServerBase() { + m_server = NULL; } -bool wxTCPServer::Create(const wxString& server_name) +bool wxTCPServer::Create(const wxString& serverName) { - wxSocketServer *server; + // Destroy previous server, if any + if (m_server) + { + m_server->SetClientData(NULL); + m_server->Destroy(); + m_server = NULL; + } - // wxIPV4address defaults to INADDR_ANY:0 - wxIPV4address addr; - addr.Service(server_name); + wxSockAddress *addr = GetAddressFromName(serverName); + if ( !addr ) + return false; + +#ifdef __UNIX_LIKE__ + mode_t umaskOld; + if ( addr->Type() == wxSockAddress::UNIX ) + { + // ensure that the file doesn't exist as otherwise calling socket() would + // fail + int rc = remove(serverName.fn_str()); + if ( rc < 0 && errno != ENOENT ) + { + delete addr; + + return false; + } + + // also set the umask to prevent the others from reading our file + umaskOld = umask(077); + } + else + { + // unused anyhow but shut down the compiler warnings + umaskOld = 0; + } +#endif // __UNIX_LIKE__ + + // Create a socket listening on the specified port + m_server = new wxSocketServer(*addr, SCKIPC_FLAGS); + +#ifdef __UNIX_LIKE__ + if ( addr->Type() == wxSockAddress::UNIX ) + { + // restore the umask + umask(umaskOld); + + // save the file name to remove it later + m_filename = serverName; + } +#endif // __UNIX_LIKE__ - // Create a socket listening on specified port - server = new wxSocketServer(addr, SCKIPC_FLAGS); - server->SetEventHandler(*gs_handler, _SERVER_ONREQUEST_ID); - server->SetClientData(this); - server->SetNotify(wxSOCKET_CONNECTION_FLAG); - server->Notify(TRUE); + delete addr; - return TRUE; + if (!m_server->Ok()) + { + m_server->Destroy(); + m_server = NULL; + + return false; + } + + m_server->SetEventHandler(*gs_handler, _SERVER_ONREQUEST_ID); + m_server->SetClientData(this); + m_server->SetNotify(wxSOCKET_CONNECTION_FLAG); + m_server->Notify(true); + + return true; } wxTCPServer::~wxTCPServer() { + if (m_server) + { + m_server->SetClientData(NULL); + m_server->Destroy(); + } + +#ifdef __UNIX_LIKE__ + if ( !m_filename.empty() ) + { + if ( remove(m_filename.fn_str()) != 0 ) + { + wxLogDebug(_T("Stale AF_UNIX file '%s' left."), m_filename.c_str()); + } + } +#endif // __UNIX_LIKE__ } wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) ) @@ -241,21 +344,29 @@ wxTCPConnection::wxTCPConnection () : wxConnectionBase() m_codeco = NULL; } -wxTCPConnection::wxTCPConnection(char * WXUNUSED(buffer), int WXUNUSED(size)) +wxTCPConnection::wxTCPConnection(void *buffer, size_t size) + : wxConnectionBase(buffer, size) { + m_sock = NULL; + m_sockstrm = NULL; + m_codeci = NULL; + m_codeco = NULL; } wxTCPConnection::~wxTCPConnection () { - wxDELETE(m_codeci); - wxDELETE(m_codeco); - wxDELETE(m_sockstrm); + Disconnect(); if (m_sock) { m_sock->SetClientData(NULL); m_sock->Destroy(); } + + /* Delete after destroy */ + wxDELETE(m_codeci); + wxDELETE(m_codeco); + wxDELETE(m_sockstrm); } void wxTCPConnection::Compress(bool WXUNUSED(on)) @@ -266,33 +377,38 @@ void wxTCPConnection::Compress(bool WXUNUSED(on)) // Calls that CLIENT can make. bool wxTCPConnection::Disconnect () { + if ( !GetConnected() ) + return true; // Send the the disconnect message to the peer. m_codeco->Write8(IPC_DISCONNECT); - m_sock->Notify(FALSE); - m_sock->Close(); - return TRUE; + if ( m_sock ) + { + m_sock->Notify(false); + m_sock->Close(); + } + + SetConnected(false); + + return true; } -bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format) +bool wxTCPConnection::DoExecute(const void *data, size_t size, wxIPCFormat format) { if (!m_sock->IsConnected()) - return FALSE; + return false; // Prepare EXECUTE message m_codeco->Write8(IPC_EXECUTE); m_codeco->Write8(format); - if (size < 0) - size = strlen(data) + 1; // includes final NUL - m_codeco->Write32(size); m_sockstrm->Write(data, size); - return TRUE; + return true; } -char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat format) +const void *wxTCPConnection::Request (const wxString& item, size_t *size, wxIPCFormat format) { if (!m_sock->IsConnected()) return NULL; @@ -309,11 +425,11 @@ char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat for return NULL; else { - size_t s; - char *data = NULL; + size_t s = m_codeci->Read32(); - s = m_codeci->Read32(); - data = new char[s]; + void *data = GetBufferAtLeast( s ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in wxTCPConnection::Request") ); m_sockstrm->Read(data, s); if (size) @@ -322,22 +438,19 @@ char *wxTCPConnection::Request (const wxString& item, int *size, wxIPCFormat for } } -bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCFormat format) +bool wxTCPConnection::DoPoke (const wxString& item, const void *data, size_t size, wxIPCFormat format) { if (!m_sock->IsConnected()) - return FALSE; + return false; m_codeco->Write8(IPC_POKE); m_codeco->WriteString(item); m_codeco->Write8(format); - if (size < 0) - size = strlen(data) + 1; // includes final NUL - m_codeco->Write32(size); m_sockstrm->Write(data, size); - return TRUE; + return true; } bool wxTCPConnection::StartAdvise (const wxString& item) @@ -345,7 +458,7 @@ bool wxTCPConnection::StartAdvise (const wxString& item) int ret; if (!m_sock->IsConnected()) - return FALSE; + return false; m_codeco->Write8(IPC_ADVISE_START); m_codeco->WriteString(item); @@ -353,9 +466,9 @@ bool wxTCPConnection::StartAdvise (const wxString& item) ret = m_codeci->Read8(); if (ret != IPC_FAIL) - return TRUE; + return true; else - return FALSE; + return false; } bool wxTCPConnection::StopAdvise (const wxString& item) @@ -363,7 +476,7 @@ bool wxTCPConnection::StopAdvise (const wxString& item) int msg; if (!m_sock->IsConnected()) - return FALSE; + return false; m_codeco->Write8(IPC_ADVISE_STOP); m_codeco->WriteString(item); @@ -371,29 +484,26 @@ bool wxTCPConnection::StopAdvise (const wxString& item) msg = m_codeci->Read8(); if (msg != IPC_FAIL) - return TRUE; + return true; else - return FALSE; + return false; } // Calls that SERVER can make -bool wxTCPConnection::Advise (const wxString& item, - wxChar *data, int size, wxIPCFormat format) +bool wxTCPConnection::DoAdvise (const wxString& item, + const void *data, size_t size, wxIPCFormat format) { if (!m_sock->IsConnected()) - return FALSE; + return false; m_codeco->Write8(IPC_ADVISE); m_codeco->WriteString(item); m_codeco->Write8(format); - if (size < 0) - size = strlen(data) + 1; // includes final NUL - m_codeco->Write32(size); m_sockstrm->Write(data, size); - return TRUE; + return true; } // -------------------------------------------------------------------------- @@ -408,16 +518,18 @@ END_EVENT_TABLE() void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) { wxSocketBase *sock = event.GetSocket(); + if (!sock) { /* No socket, no glory */ + return ; + } wxSocketNotify evt = event.GetSocketEvent(); - wxTCPConnection *connection = (wxTCPConnection *)(event.GetClientData()); + wxTCPConnection *connection = (wxTCPConnection *)(sock->GetClientData()); // This socket is being deleted; skip this event if (!connection) return; - int msg = 0; wxDataInputStream *codeci; - wxDataOutputStream *codeco; + wxDataOutputStream *codeco; wxSocketStream *sockstrm; wxString topic_name = connection->m_topic; wxString item; @@ -425,7 +537,7 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) // We lost the connection: destroy everything if (evt == wxSOCKET_LOST) { - sock->Notify(FALSE); + sock->Notify(false); sock->Close(); connection->OnDisconnect(); return; @@ -435,41 +547,40 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) codeci = connection->m_codeci; codeco = connection->m_codeco; sockstrm = connection->m_sockstrm; - msg = codeci->Read8(); + int msg = codeci->Read8(); switch (msg) { case IPC_EXECUTE: { - char *data; - size_t size; + void *data; + size_t size; wxIPCFormat format; - + format = (wxIPCFormat)codeci->Read8(); size = codeci->Read32(); - data = new char[size]; + + data = connection->GetBufferAtLeast( size ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") ); sockstrm->Read(data, size); connection->OnExecute (topic_name, data, size, format); - delete [] data; break; } case IPC_ADVISE: { - char *data; - size_t size; - wxIPCFormat format; - item = codeci->ReadString(); - format = (wxIPCFormat)codeci->Read8(); - size = codeci->Read32(); - data = new char[size]; + wxIPCFormat format = (wxIPCFormat)codeci->Read8(); + size_t size = codeci->Read32(); + void *data = connection->GetBufferAtLeast( size ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") ); sockstrm->Read(data, size); - + connection->OnAdvise (topic_name, item, data, size, format); - delete [] data; break; } case IPC_ADVISE_START: @@ -498,19 +609,15 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) } case IPC_POKE: { - wxIPCFormat format; - size_t size; - wxChar *data; - item = codeci->ReadString(); - format = (wxIPCFormat)codeci->Read8(); - size = codeci->Read32(); - data = new wxChar[size]; + wxIPCFormat format = (wxIPCFormat)codeci->Read8(); + size_t size = codeci->Read32(); + void *data = connection->GetBufferAtLeast( size ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in wxTCPEventHandler::Client_OnRequest") ); sockstrm->Read(data, size); - - connection->OnPoke (topic_name, item, data, size, format); - delete [] data; + connection->OnPoke (topic_name, item, data, size, format); break; } @@ -521,15 +628,28 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) item = codeci->ReadString(); format = (wxIPCFormat)codeci->Read8(); - int user_size = -1; - char *user_data = connection->OnRequest (topic_name, item, &user_size, format); + size_t user_size = wxNO_LEN; + const void *user_data = connection->OnRequest (topic_name, item, &user_size, format); if (user_data) { codeco->Write8(IPC_REQUEST_REPLY); - if (user_size == -1) - user_size = strlen(user_data) + 1; // includes final NUL + if (user_size == wxNO_LEN) + { + switch (format) + { + case wxIPC_TEXT: + case wxIPC_UTF8TEXT: + user_size = strlen((const char *)user_data) + 1; // includes final NUL + break; + case wxIPC_UNICODETEXT: + user_size = (wcslen((const wchar_t *)user_data) + 1) * sizeof(wchar_t); // includes final NUL + break; + default: + user_size = 0; + } + } codeco->Write32(user_size); sockstrm->Write(user_data, user_size); @@ -541,8 +661,9 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) } case IPC_DISCONNECT: { - sock->Notify(FALSE); + sock->Notify(false); sock->Close(); + connection->SetConnected(false); connection->OnDisconnect(); break; } @@ -555,7 +676,10 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) { wxSocketServer *server = (wxSocketServer *) event.GetSocket(); - wxTCPServer *ipcserv = (wxTCPServer *) event.GetClientData(); + if (!server) { /* No server, Then exit */ + return ; + } + wxTCPServer *ipcserv = (wxTCPServer *) server->GetClientData(); // This socket is being deleted; skip this event if (!ipcserv) @@ -566,6 +690,9 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) // Accept the connection, getting a new socket wxSocketBase *sock = server->Accept(); + if (!sock) { /* No socket, no glory */ + return ; + } if (!sock->Ok()) { sock->Destroy(); @@ -594,14 +721,14 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) // Acknowledge success codeco->Write8(IPC_CONNECT); new_connection->m_topic = topic_name; - new_connection->m_sock = sock; + new_connection->m_sock = sock; new_connection->m_sockstrm = stream; new_connection->m_codeci = codeci; new_connection->m_codeco = codeco; sock->SetEventHandler(*gs_handler, _CLIENT_ONREQUEST_ID); sock->SetClientData(new_connection); sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG); - sock->Notify(TRUE); + sock->Notify(true); return; } else @@ -625,12 +752,12 @@ void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) // wxTCPEventHandlerModule (private class) // -------------------------------------------------------------------------- -class WXDLLEXPORT wxTCPEventHandlerModule: public wxModule +class wxTCPEventHandlerModule: public wxModule { DECLARE_DYNAMIC_CLASS(wxTCPEventHandlerModule) public: - bool OnInit() { gs_handler = new wxTCPEventHandler(); return TRUE; } + bool OnInit() { gs_handler = new wxTCPEventHandler(); return true; } void OnExit() { wxDELETE(gs_handler); } }; @@ -638,4 +765,4 @@ IMPLEMENT_DYNAMIC_CLASS(wxTCPEventHandlerModule, wxModule) #endif - // wxUSE_SOCKETS && wxUSE_IPC + // wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS