From 0dbfd66d0b35352a0f60e7190b72815052b3d2d4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 12 Apr 2002 15:13:53 +0000 Subject: [PATCH] implemented IPC using Unix domain sockets git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15114 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/tipc.tex | 10 +++- include/wx/sckipc.h | 5 ++ src/common/sckipc.cpp | 126 ++++++++++++++++++++++++++++++++++------- 4 files changed, 119 insertions(+), 23 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index ce40ad753b..4fd6357921 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -131,6 +131,7 @@ Unix (Base/GUI): - wxWindows may be built using BSD and Solaris (and possibly other) make programs and not only GNU make +- wxTCP-based IPC classes now support communicating over Unix domain sockets All (GUI): diff --git a/docs/latex/wx/tipc.tex b/docs/latex/wx/tipc.tex index 9ae5159e15..d2c74699d7 100644 --- a/docs/latex/wx/tipc.tex +++ b/docs/latex/wx/tipc.tex @@ -48,8 +48,14 @@ element of some messages. To create a connection (a conversation in Windows parlance), the client application sends the message MakeConnection to the client object, with a string service name to identify the server and a topic name to identify the topic for the -duration of the connection. Under Unix, the service name must contain an -integer port identifier. +duration of the connection. Under Unix, the service name may be either an +integer port identifier in which case an Internet domain socket will be used +for the communications or a valid file name (which shouldn't exist and will be +deleted afterwards) in which case a Unix domain socket is created. + +{\bf SECURITY NOTE:} Using Internet domain sockets if extremely insecure for +IPC as there is absolutely no access control for them, use Unix domain sockets +whenever possible! The server then responds and either vetoes the connection or allows it. If allowed, a connection object is created which persists until the diff --git a/include/wx/sckipc.h b/include/wx/sckipc.h index 743da0ab9f..47f506184f 100644 --- a/include/wx/sckipc.h +++ b/include/wx/sckipc.h @@ -122,6 +122,11 @@ public: protected: wxSocketServer *m_server; + +#ifdef __UNIX_LIKE__ + // the name of the file associated to the Unix domain socket, may be empty + wxString m_filename; +#endif // __UNIX_LIKE__ }; class wxTCPClient: public wxClientBase diff --git a/src/common/sckipc.cpp b/src/common/sckipc.cpp index 3fea37e1ec..c3ad40ca7f 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 && 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 +#ifdef __UNIX_LIKE__ + // 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,11 +171,14 @@ 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; + + bool ok = client->Connect(*addr); + delete addr; - if (client->Connect(addr)) + if ( ok ) { unsigned char msg; @@ -213,12 +250,49 @@ bool wxTCPServer::Create(const wxString& serverName) m_server = NULL; } - // wxIPV4address defaults to INADDR_ANY:0 - wxIPV4address addr; - addr.Service(serverName); + 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); + 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); + 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()) { @@ -238,11 +312,21 @@ bool wxTCPServer::Create(const wxString& serverName) wxTCPServer::~wxTCPServer() { - if (m_server) - { - m_server->SetClientData(NULL); - m_server->Destroy(); - } + if (m_server) + { + m_server->SetClientData(NULL); + m_server->Destroy(); + } + +#ifdef __UNIX_LIKE__ + if ( !m_filename.empty() ) + { + if ( !remove(m_filename) ) + { + wxLogDebug(_T("Stale AF_UNIX file '%s' left."), m_filename.c_str()); + } + } +#endif // __UNIX_LIKE__ } wxConnectionBase *wxTCPServer::OnAcceptConnection( const wxString& WXUNUSED(topic) ) -- 2.45.2