X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f0500b3ee1255cc71624bc58b83d0d954b2d45e..f90566f5c386e6e5d80deecad9052ec53a0394ba:/src/common/sckipc.cpp diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp index 16406abe08..822f96397e 100644 --- a/src/common/sckipc.cpp +++ b/src/common/sckipc.cpp @@ -5,6 +5,7 @@ // 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 @@ -33,23 +34,19 @@ #endif #ifndef WX_PRECOMP -#include "wx/defs.h" +#include "wx/log.h" #endif -#if wxUSE_SOCKETS && wxUSE_IPC +#if wxUSE_SOCKETS && wxUSE_IPC && wxUSE_STREAMS #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,10 +71,47 @@ enum }; #endif - // All sockets will be created with the following flags #define SCKIPC_FLAGS (wxSOCKET_WAITALL) +// 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 = _T("")) +{ + // we always use INET sockets under non-Unix systems +#if defined(__UNIX__) && !defined(__WXMAC__) + // 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) // -------------------------------------------------------------------------- @@ -129,7 +163,7 @@ bool wxTCPClient::ValidHost(const wxString& host) } wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, - const wxString& server_name, + const wxString& serverName, const wxString& topic) { wxSocketClient *client = new wxSocketClient(SCKIPC_FLAGS); @@ -137,18 +171,21 @@ wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host, wxDataInputStream *data_is = new wxDataInputStream(*stream); wxDataOutputStream *data_os = new wxDataOutputStream(*stream); - wxIPV4address addr; - addr.Service(server_name); - addr.Hostname(host); + wxSockAddress *addr = GetAddressFromName(serverName, host); + if ( !addr ) + return NULL; - if (client->Connect(addr)) + bool ok = client->Connect(*addr); + delete 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. @@ -200,28 +237,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; - // 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); +#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); + 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__ + + delete addr; + + 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) != 0 ) + { + wxLogDebug(_T("Stale AF_UNIX file '%s' left."), m_filename.c_str()); + } + } +#endif // __UNIX_LIKE__ } wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) ) @@ -284,7 +389,7 @@ bool wxTCPConnection::Execute(const wxChar *data, int size, wxIPCFormat format) m_codeco->Write8(format); if (size < 0) - size = strlen(data) + 1; // includes final NUL + size = wxStrlen(data) + 1; // includes final NUL m_codeco->Write32(size); m_sockstrm->Write(data, size); @@ -332,7 +437,7 @@ bool wxTCPConnection::Poke (const wxString& item, wxChar *data, int size, wxIPCF m_codeco->Write8(format); if (size < 0) - size = strlen(data) + 1; // includes final NUL + size = wxStrlen(data) + 1; // includes final NUL m_codeco->Write32(size); m_sockstrm->Write(data, size); @@ -388,7 +493,7 @@ bool wxTCPConnection::Advise (const wxString& item, m_codeco->Write8(format); if (size < 0) - size = strlen(data) + 1; // includes final NUL + size = wxStrlen(data) + 1; // includes final NUL m_codeco->Write32(size); m_sockstrm->Write(data, size); @@ -417,7 +522,7 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) int msg = 0; wxDataInputStream *codeci; - wxDataOutputStream *codeco; + wxDataOutputStream *codeco; wxSocketStream *sockstrm; wxString topic_name = connection->m_topic; wxString item; @@ -442,9 +547,9 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) case IPC_EXECUTE: { char *data; - size_t size; + size_t size; wxIPCFormat format; - + format = (wxIPCFormat)codeci->Read8(); size = codeci->Read32(); data = new char[size]; @@ -466,7 +571,7 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) size = codeci->Read32(); data = new char[size]; sockstrm->Read(data, size); - + connection->OnAdvise (topic_name, item, data, size, format); delete [] data; @@ -507,7 +612,7 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) size = codeci->Read32(); data = new wxChar[size]; sockstrm->Read(data, size); - + connection->OnPoke (topic_name, item, data, size, format); delete [] data; @@ -555,7 +660,7 @@ void wxTCPEventHandler::Client_OnRequest(wxSocketEvent &event) void wxTCPEventHandler::Server_OnRequest(wxSocketEvent &event) { wxSocketServer *server = (wxSocketServer *) event.GetSocket(); - wxTCPServer *ipcserv = (wxTCPServer *) event.GetClientData(); + wxTCPServer *ipcserv = (wxTCPServer *) server->GetClientData(); // This socket is being deleted; skip this event if (!ipcserv) @@ -594,7 +699,7 @@ 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;