// 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
#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 <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#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
};
#endif
-
// All sockets will be created with the following flags
#define SCKIPC_FLAGS (wxSOCKET_WAITALL)
+// headers needed for umask()
+#ifdef __UNIX_LIKE__
+ #include <sys/types.h>
+ #include <sys/stat.h>
+#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)
// --------------------------------------------------------------------------
}
wxConnectionBase *wxTCPClient::MakeConnection (const wxString& host,
- const wxString& server_name,
+ const wxString& serverName,
const wxString& topic)
{
wxSocketClient *client = new wxSocketClient(SCKIPC_FLAGS);
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.
wxConnectionBase *wxTCPClient::OnMakeConnection()
{
- return new wxTCPConnection;
+ return new wxTCPConnection();
}
// --------------------------------------------------------------------------
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);
+ if ( rc < 0 && errno != ENOENT )
+ {
+ delete 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);
+ // 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) )
wxDELETE(m_codeco);
wxDELETE(m_sockstrm);
- if (m_sock) m_sock->Destroy();
+ if (m_sock)
+ {
+ m_sock->SetClientData(NULL);
+ m_sock->Destroy();
+ }
}
void wxTCPConnection::Compress(bool WXUNUSED(on))
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);
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);
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);
{
wxSocketBase *sock = event.GetSocket();
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;
- // The socket handler signals us that we lost the connection: destroy all.
+ // We lost the connection: destroy everything
if (evt == wxSOCKET_LOST)
{
sock->Notify(FALSE);
case IPC_EXECUTE:
{
char *data;
- size_t size;
+ size_t size;
wxIPCFormat format;
-
+
format = (wxIPCFormat)codeci->Read8();
size = codeci->Read32();
data = new char[size];
size = codeci->Read32();
data = new char[size];
sockstrm->Read(data, size);
-
+
connection->OnAdvise (topic_name, item, data, size, format);
delete [] data;
size = codeci->Read32();
data = new wxChar[size];
sockstrm->Read(data, size);
-
+
connection->OnPoke (topic_name, item, data, size, format);
delete [] data;
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)
+ return;
if (event.GetSocketEvent() != wxSOCKET_CONNECTION)
return;
// 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;