Skip to content

Commit

Permalink
Fixed LocalSocket (Unix socket) and support on recent Windows (opt AS…
Browse files Browse the repository at this point in the history
…L_SOCKET_LOCAL)
  • Loading branch information
aslze committed Jun 4, 2024
1 parent 39960a8 commit 74f2e8f
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 30 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12...3.5)

project(asl)

set(ASL_VERSION 1.11.10)
set(ASL_VERSION 1.11.11)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
Expand Down Expand Up @@ -38,7 +38,7 @@ option(ASL_BUILD_SHARED "Build shared library" ${ASL_BUILD_SHARED_HINT})
option(ASL_IPV6 "Expect also IPv6 when looking up DNS names")
option(ASL_SAMPLES "Build samples")
option(ASL_TESTS "Build tests")

option(ASL_SOCKET_LOCAL "Support Unix sockets on Windows")

if(ASL_TLS)
if(TARGET MbedTLS::mbedtls)
Expand Down
6 changes: 2 additions & 4 deletions doc/doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,10 @@ socket.connect(host, 80);
socket << String(0, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", *path, *host);
String response;
char buffer[1001];
while(true)
while(socket.connected())
{
if(!socket.waitInput())
if(!socket.waitData())
continue;
if(socket.disconnected())
break;
int n = socket.read(buffer, min(socket.available(), 1000));
if(n <= 0)
break;
Expand Down
2 changes: 1 addition & 1 deletion doc/doxy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = _WIN32 ASL_EXP_THREADING ASL_TLS ASL_API ASL_HAVE_INITLIST ASL_HAVE_INITLIST2 DOXYGEN_SHOULD_SKIP_THIS _MSC_VER=1800 ASL_EXPLICIT=explicit ASL_DEPRECATED= ASL_PRINTF_W1=
PREDEFINED = _WIN32 ASL_EXP_THREADING ASL_TLS ASL_API ASL_HAVE_INITLIST ASL_HAVE_INITLIST2 DOXYGEN_SHOULD_SKIP_THIS _MSC_VER=1800 ASL_EXPLICIT=explicit ASL_DEPRECATED= ASL_PRINTF_W1= ASL_SOCKET_LOCAL
EXPAND_AS_DEFINED = YES
SKIP_FUNCTION_MACROS = NO

Expand Down
36 changes: 31 additions & 5 deletions include/asl/Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ ASL_SMART_CLASS(Socket, SmartObject)
};

/**
A Socket is a communication socket for TCP protocol.
A communication socket for the TCP/IP protocol.
\ingroup Sockets
*/
class ASL_API Socket : public SmartObject
Expand Down Expand Up @@ -174,6 +174,11 @@ class ASL_API Socket : public SmartObject
*/
bool disconnected() { return _()->disconnected(); }

/**
Checks if the connection is open.
*/
bool connected() { return !disconnected(); }

/**
Binds this socket to the given IP address and port number.
*/
Expand Down Expand Up @@ -369,7 +374,7 @@ ASL_SMART_CLASS(PacketSocket, Socket)
};

/**
A PacketSocket is a communication socket for UDP protocol.
A communication socket for UDP/IP protocol.
\ingroup Sockets
A listening side binds to a port and receives packets. The readFrom() functions also
Expand Down Expand Up @@ -434,18 +439,39 @@ class ASL_API PacketSocket : public Socket
}
};

#if !defined(_WIN32) || defined(ASL_SOCKETLOCAL)
#if !defined(_WIN32) || defined(ASL_SOCKET_LOCAL)

ASL_SMART_CLASS(LocalSocket, Socket)
{
ASL_SMART_INNER_DEF(LocalSocket);
LocalSocket_();
LocalSocket_(int fd);
~LocalSocket_();
String _pathname;
bool bind(const String& name);
Socket_* accept();
};

/**
A Local or Unix socket for inter-process communication within a machine.
Works similar to a TCP socket but it is bound to a local path in the file system.
Used to be Unix/Linux-only but is also supported on recent Windows 10+ versions (need to
enable CMAKE_SOCKET_LOCAL on Windows)
```
LocalSocket server;
server.bind("/dir/comm.sock");
server.listen();
LocalSocket client = server.accept();
...
LocalSocket client;
client.connect("/dir/comm.sock");
client << "Hello\n";
```
\ingroup Sockets
*/
class ASL_API LocalSocket : public Socket
{
public:
Expand All @@ -465,7 +491,7 @@ ASL_SMART_CLASS(MulticastSocket, PacketSocket)
};

/**
A MulticastSocket is a communication socket for multicast UDP protocol.
A communication socket for multicast UDP/IP protocol.
A socket can send packets to a multicast group and port, and another socket can join the group
so it receives packets sent to it.
Expand Down
4 changes: 2 additions & 2 deletions include/asl/SocketServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct SockServerThread;
struct SockClientThread;

/**
This is a reusable TCP socket server that listens to incoming connections and answers them concurrently (default) or sequentially.
This is a reusable TCP or Unix socket server that listens to incoming connections and answers them concurrently (default) or sequentially.
To make an actual server, derive a class from it and implement the virtual function `serve()`. That function will be called
whenever a new connection arrives.
Expand Down Expand Up @@ -46,7 +46,7 @@ For long-running connections, the recommended way of dealing with possible disco
~~~
void serve(Socket client)
{
while (!client.disconnected())
while (client.connected())
{
if (!client.waitData())
continue;
Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ if( ASL_USE_LOCAL8BIT )
list(APPEND ASL_DEFS ASL_ANSI)
endif()

if(ASL_SOCKET_LOCAL)
list(APPEND ASL_DEFS ASL_SOCKET_LOCAL)
endif()

if(POLICY CMP0022)
cmake_policy(SET CMP0022 NEW)
endif()
Expand Down
51 changes: 35 additions & 16 deletions src/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" with /permissive-
#include <winsock2.h>
#include <ws2tcpip.h>
#ifdef ASL_SOCKETLOCAL
#ifdef ASL_SOCKET_LOCAL
#include <afunix.h>
#endif
#include <windows.h>
Expand All @@ -20,6 +20,9 @@ struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#ifndef ASL_SOCKET_LOCAL
#define ASL_SOCKET_LOCAL
#endif
#endif

#include <string.h>
Expand Down Expand Up @@ -139,7 +142,7 @@ inline int sockfamily(InetAddress::Type t)
{
case InetAddress::IPv4: return AF_INET;
case InetAddress::IPv6: return AF_INET6;
#if !defined(_WIN32) || defined(ASL_SOCKETLOCAL)
#ifdef ASL_SOCKET_LOCAL
case InetAddress::LOCAL: return AF_UNIX;
#endif
default:;
Expand All @@ -155,7 +158,7 @@ InetAddress::InetAddress(InetAddress::Type t)
{
case IPv4: n = sizeof(sockaddr_in); break;
case IPv6: n = sizeof(sockaddr_in6); break;
#if !defined(_WIN32) || defined(ASL_SOCKETLOCAL)
#ifdef ASL_SOCKET_LOCAL
case LOCAL: n = sizeof(sockaddr_un); break;
#endif
default: ;
Expand Down Expand Up @@ -210,7 +213,7 @@ String InetAddress::host() const
byte* ip = (byte*)&addr->sin_addr;
return String::f("%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
}
#if !defined(_WIN32) || defined(ASL_SOCKETLOCAL)
#ifdef ASL_SOCKET_LOCAL
else if (_type == LOCAL)
{
sockaddr_un* addr = (sockaddr_un*)ptr();
Expand Down Expand Up @@ -347,7 +350,7 @@ HostPort parseHostPort(const String& u)
}
else {
int i = u.lastIndexOf(':');
if (i > 0) {
if (i > 1) {
hostend = i;
portstart = i + 1;
}
Expand All @@ -366,13 +369,14 @@ bool InetAddress::set(const String& host)
thehost = '[' + host + ']';

HostPort hp = parseHostPort(thehost);
if(!hp.port.ok() && hp.host.contains('/'))
if (!hp.port.ok() && (hp.host.contains('/') || hp.host.contains('\\')))
{
#ifndef _WIN32
#ifdef ASL_SOCKET_LOCAL
resize(sizeof(sockaddr_un));
sockaddr_un* a=(sockaddr_un*)ptr();
a->sun_family=AF_UNIX;
strcpy(a->sun_path, host.substring(0, min(107, host.length())));
memcpy(a->sun_path, *host, min((int)sizeof(a->sun_path), host.length() + 1));
a->sun_path[sizeof(a->sun_path) - 1] = '\0';
_type = LOCAL;
return true;
#endif
Expand All @@ -382,7 +386,6 @@ bool InetAddress::set(const String& host)

// Socket


Socket_::Socket_()
{
#ifdef _WIN32
Expand All @@ -398,6 +401,10 @@ Socket_::Socket_()

Socket_::Socket_(int fd)
{
#ifdef _WIN32
if (!g_wsaStarted)
startWSA();
#endif
_handle = fd;
_family = InetAddress::IPv4;
_error = 0;
Expand Down Expand Up @@ -640,7 +647,7 @@ void Socket_::skip(int n)

bool Socket_::disconnected()
{
return _error != 0 || (waitInput(0) && available() <= 0);
return _handle < 0 || _error != 0 || (waitInput(0) && available() <= 0);
}

bool Socket_::waitInput(double t)
Expand Down Expand Up @@ -719,7 +726,7 @@ void PacketSocket_::sendTo(const InetAddress& to, const void* data, int n)
sendto(_handle, (const char*)data, n, 0, (sockaddr*)to.ptr(), to.length());
}

#if !defined(_WIN32) || defined(ASL_SOCKETLOCAL)
#ifdef ASL_SOCKET_LOCAL

// LocalSocket (UNIX)

Expand All @@ -737,28 +744,40 @@ LocalSocket_::LocalSocket_(int fd) : Socket_(fd)

LocalSocket_::~LocalSocket_()
{
if(_pathname)
String path = localAddress().toString();
if (path)
{
close();
unlink(_pathname);
#ifdef _WIN32
DeleteFileW(path);
#else
unlink(path);
#endif
}
}

bool LocalSocket_::bind(const String& name)
{
_pathname=name;
#ifdef _WIN32
DeleteFileW(name);
#else
unlink(name);
#endif
init();
setOption(SOL_SOCKET, SO_REUSEADDR, 1);
InetAddress here(name);
if(::bind(_handle, (sockaddr*)here.ptr(), here.length()))
if (::bind(_handle, (sockaddr*)here.ptr(), sizeof(sockaddr_un)))
{
verbose_print("Can't bind to %s\n", *name);
return false;
}
return true;
}

Socket_* LocalSocket_::accept()
{
return new LocalSocket_((int)::accept(_handle, (sockaddr*)0, (socklen_t*)0));
}

#endif

}
Expand Down

0 comments on commit 74f2e8f

Please sign in to comment.