Unified BSD socket source, for WIN32 and POSIX.

This commit is contained in:
carlo-bramini 2017-11-25 14:50:52 +01:00
parent 4178bbdb72
commit f26258cd1f
2 changed files with 81 additions and 208 deletions

View file

@ -32,7 +32,12 @@
/* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket.
* Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */
#define WIN32_SOCKET_FLAG 0x40000000
#ifdef _WIN32
#define FLUID_SOCKET_FLAG 0x40000000
#else
#define FLUID_SOCKET_FLAG 0x00000000
#define SOCKET_ERROR -1
#endif
/* SCHED_FIFO priority for high priority timer threads */
#define FLUID_SYS_TIMER_HIGH_PRIO_LEVEL 10
@ -854,14 +859,14 @@ fluid_istream_gets (fluid_istream_t in, char* buf, int len)
if (n == -1) return -1;
#else
/* Handle read differently depending on if its a socket or file descriptor */
if (!(in & WIN32_SOCKET_FLAG))
if (!(in & FLUID_SOCKET_FLAG))
{
n = read(in, &c, 1);
if (n == -1) return -1;
}
else
{
n = recv(in & ~WIN32_SOCKET_FLAG, &c, 1, 0);
n = recv(in & ~FLUID_SOCKET_FLAG, &c, 1, 0);
if (n == SOCKET_ERROR) return -1;
}
#endif
@ -923,11 +928,11 @@ fluid_ostream_printf (fluid_ostream_t out, char* format, ...)
int retval;
/* Handle write differently depending on if its a socket or file descriptor */
if (!(out & WIN32_SOCKET_FLAG))
if (!(out & FLUID_SOCKET_FLAG))
return write(out, buf, strlen (buf));
/* Socket */
retval = send (out & ~WIN32_SOCKET_FLAG, buf, strlen (buf), 0);
retval = send (out & ~FLUID_SOCKET_FLAG, buf, strlen (buf), 0);
return retval != SOCKET_ERROR ? retval : -1;
}
@ -939,191 +944,55 @@ int fluid_server_socket_join(fluid_server_socket_t *server_socket)
return fluid_thread_join (server_socket->thread);
}
int fluid_socket_init(void)
{
#ifdef _WIN32
WSADATA wsaData;
int res = WSAStartup(MAKEWORD(2,2), &wsaData);
#ifndef WIN32 // Not win32?
if (res != 0) {
FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", res);
return FLUID_FAILED;
}
#endif
#define SOCKET_ERROR -1
return FLUID_OK;
}
void fluid_socket_cleanup(void)
{
#ifdef _WIN32
WSACleanup();
#endif
}
int fluid_socket_get_error(void)
{
#ifdef _WIN32
return (int)WSAGetLastError();
#else
return errno;
#endif
}
fluid_istream_t fluid_socket_get_istream (fluid_socket_t sock)
{
return sock;
return sock | FLUID_SOCKET_FLAG;
}
fluid_ostream_t fluid_socket_get_ostream (fluid_socket_t sock)
{
return sock;
}
void fluid_socket_close(fluid_socket_t sock)
{
if (sock != INVALID_SOCKET)
close (sock);
}
static fluid_thread_return_t
fluid_server_socket_run (void *data)
{
fluid_server_socket_t *server_socket = (fluid_server_socket_t *)data;
fluid_socket_t client_socket;
#ifdef IPV6_SUPPORT
struct sockaddr_in6 addr;
char straddr[INET6_ADDRSTRLEN];
#else
struct sockaddr_in addr;
char straddr[INET_ADDRSTRLEN];
#endif
socklen_t addrlen = sizeof (addr);
int retval;
FLUID_MEMSET((char *)&addr, 0, sizeof(addr));
FLUID_LOG (FLUID_DBG, "Server listening for connections");
while (server_socket->cont)
{
client_socket = accept (server_socket->socket, (struct sockaddr *)&addr, &addrlen);
FLUID_LOG (FLUID_DBG, "New client connection");
if (client_socket == INVALID_SOCKET)
{
if (server_socket->cont)
FLUID_LOG(FLUID_ERR, "Failed to accept connection");
server_socket->cont = 0;
return FLUID_THREAD_RETURN_VALUE;
} else {
#ifdef HAVE_INETNTOP
#ifdef IPV6_SUPPORT
inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
#else
inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
#endif
#endif
#ifdef HAVE_INETNTOP
retval = server_socket->func (server_socket->data, client_socket,
straddr);
#else
retval = server_socket->func (server_socket->data, client_socket,
inet_ntoa (addr.sin_addr));
#endif
if (retval != 0)
fluid_socket_close(client_socket);
}
}
FLUID_LOG(FLUID_DBG, "Server closing");
return FLUID_THREAD_RETURN_VALUE;
}
fluid_server_socket_t*
new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
{
fluid_server_socket_t* server_socket;
#ifdef IPV6_SUPPORT
struct sockaddr_in6 addr;
#else
struct sockaddr_in addr;
#endif
fluid_socket_t sock;
g_return_val_if_fail (func != NULL, NULL);
#ifdef IPV6_SUPPORT
sock = socket(AF_INET6, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
FLUID_LOG(FLUID_ERR, "Failed to create server socket");
return NULL;
}
FLUID_MEMSET((char *)&addr, 0, sizeof(struct sockaddr_in6));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(port);
#else
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
FLUID_LOG(FLUID_ERR, "Failed to create server socket");
return NULL;
}
FLUID_MEMSET((char *)&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
#endif
if (bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
FLUID_LOG(FLUID_ERR, "Failed to bind server socket");
fluid_socket_close(sock);
return NULL;
}
if (listen(sock, 10) == SOCKET_ERROR) {
FLUID_LOG(FLUID_ERR, "Failed listen on server socket");
fluid_socket_close(sock);
return NULL;
}
server_socket = FLUID_NEW(fluid_server_socket_t);
if (server_socket == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
fluid_socket_close(sock);
return NULL;
}
server_socket->socket = sock;
server_socket->func = func;
server_socket->data = data;
server_socket->cont = 1;
server_socket->thread = new_fluid_thread("server", fluid_server_socket_run, server_socket,
0, FALSE);
if (server_socket->thread == NULL) {
FLUID_FREE(server_socket);
fluid_socket_close(sock);
return NULL;
}
return server_socket;
}
void delete_fluid_server_socket(fluid_server_socket_t* server_socket)
{
fluid_return_if_fail(server_socket != NULL);
server_socket->cont = 0;
if (server_socket->socket != INVALID_SOCKET) {
fluid_socket_close(server_socket->socket);
}
if (server_socket->thread) {
delete_fluid_thread(server_socket->thread);
}
FLUID_FREE(server_socket);
}
#else // Win32 is "special"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
fluid_istream_t fluid_socket_get_istream (fluid_socket_t sock)
{
return sock | WIN32_SOCKET_FLAG;
}
fluid_ostream_t fluid_socket_get_ostream (fluid_socket_t sock)
{
return sock | WIN32_SOCKET_FLAG;
return sock | FLUID_SOCKET_FLAG;
}
void fluid_socket_close (fluid_socket_t sock)
{
if (sock != INVALID_SOCKET)
closesocket (sock);
#ifdef _WIN32
closesocket(sock);
#else
close(sock);
#endif
}
static fluid_thread_return_t fluid_server_socket_run (void *data)
@ -1132,13 +1001,18 @@ static fluid_thread_return_t fluid_server_socket_run (void *data)
fluid_socket_t client_socket;
#ifdef IPV6_SUPPORT
struct sockaddr_in6 addr;
char straddr[INET6_ADDRSTRLEN];
#else
struct sockaddr_in addr;
#endif
#ifdef HAVE_INETNTOP
#ifdef IPV6_SUPPORT
char straddr[INET6_ADDRSTRLEN];
#else
char straddr[INET_ADDRSTRLEN];
#endif
#endif
#endif /* HAVE_INETNTOP */
#endif /* IPV6_SUPPORT */
socklen_t addrlen = sizeof (addr);
int r;
FLUID_MEMSET((char *)&addr, 0, sizeof(addr));
@ -1154,7 +1028,7 @@ static fluid_thread_return_t fluid_server_socket_run (void *data)
if (client_socket == INVALID_SOCKET)
{
if (server_socket->cont)
FLUID_LOG (FLUID_ERR, "Failed to accept connection: %ld", WSAGetLastError ());
FLUID_LOG (FLUID_ERR, "Failed to accept connection: %ld", fluid_socket_get_error());
server_socket->cont = 0;
return FLUID_THREAD_RETURN_VALUE;
@ -1162,13 +1036,13 @@ static fluid_thread_return_t fluid_server_socket_run (void *data)
else
{
#ifdef HAVE_INETNTOP
#ifdef IPV6_SUPPORT
inet_ntop(AF_INET6, &addr.sin6_addr, straddr, sizeof(straddr));
#else
inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr));
#endif
#endif
#ifdef HAVE_INETNTOP
r = server_socket->func (server_socket->data, client_socket,
straddr);
#else
@ -1182,7 +1056,7 @@ static fluid_thread_return_t fluid_server_socket_run (void *data)
FLUID_LOG (FLUID_DBG, "Server closing");
return FLUID_THREAD_RETURN_VALUE;
return FLUID_THREAD_RETURN_VALUE;
}
fluid_server_socket_t*
@ -1196,29 +1070,25 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
#endif
fluid_socket_t sock;
WSADATA wsaData;
int retval;
g_return_val_if_fail (func != NULL, NULL);
fluid_return_val_if_fail (func != NULL, NULL);
// Win32 requires initialization of winsock
retval = WSAStartup (MAKEWORD (2,2), &wsaData);
if (retval != 0)
if (fluid_socket_init() != FLUID_OK)
{
FLUID_LOG(FLUID_ERR, "Server socket creation error: WSAStartup failed: %d", retval);
return NULL;
}
#ifdef IPV6_SUPPORT
sock = socket (AF_INET6, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", WSAGetLastError ());
WSACleanup ();
FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error());
fluid_socket_cleanup();
return NULL;
}
FLUID_MEMSET(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons (port);
addr.sin6_port = htons ((uint16_t)port);
addr.sin6_addr = in6addr_any;
#else
@ -1226,30 +1096,30 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
if (sock == INVALID_SOCKET)
{
FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", WSAGetLastError ());
WSACleanup ();
FLUID_LOG (FLUID_ERR, "Failed to create server socket: %ld", fluid_socket_get_error());
fluid_socket_cleanup();
return NULL;
}
FLUID_MEMSET(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_port = htons ((uint16_t)port);
addr.sin_addr.s_addr = htonl (INADDR_ANY);
#endif
retval = bind (sock, (struct sockaddr *)&addr, sizeof (addr));
if (retval == SOCKET_ERROR)
if (bind(sock, (const struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR)
{
FLUID_LOG (FLUID_ERR, "Failed to bind server socket: %ld", WSAGetLastError ());
FLUID_LOG (FLUID_ERR, "Failed to bind server socket: %ld", fluid_socket_get_error());
fluid_socket_close (sock);
WSACleanup ();
fluid_socket_cleanup();
return NULL;
}
if (listen (sock, SOMAXCONN) == SOCKET_ERROR)
{
FLUID_LOG (FLUID_ERR, "Failed to listen on server socket: %ld", WSAGetLastError ());
FLUID_LOG (FLUID_ERR, "Failed to listen on server socket: %ld", fluid_socket_get_error());
fluid_socket_close (sock);
WSACleanup ();
fluid_socket_cleanup();
return NULL;
}
@ -1259,7 +1129,7 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
{
FLUID_LOG (FLUID_ERR, "Out of memory");
fluid_socket_close (sock);
WSACleanup ();
fluid_socket_cleanup();
return NULL;
}
@ -1274,7 +1144,7 @@ new_fluid_server_socket(int port, fluid_server_func_t func, void* data)
{
FLUID_FREE (server_socket);
fluid_socket_close (sock);
WSACleanup ();
fluid_socket_cleanup();
return NULL;
}
@ -1295,7 +1165,6 @@ void delete_fluid_server_socket(fluid_server_socket_t *server_socket)
FLUID_FREE (server_socket);
WSACleanup (); // Should be called the same number of times as WSAStartup
// Should be called the same number of times as fluid_socket_init()
fluid_socket_cleanup();
}
#endif

View file

@ -355,6 +355,10 @@ void fluid_socket_close(fluid_socket_t sock);
fluid_istream_t fluid_socket_get_istream(fluid_socket_t sock);
fluid_ostream_t fluid_socket_get_ostream(fluid_socket_t sock);
int fluid_socket_init(void);
void fluid_socket_cleanup(void);
int fluid_socket_get_error(void);
/* Profiling */