forked from KolibriOS/kolibrios
192 lines
3.5 KiB
C
192 lines
3.5 KiB
C
|
|
||
|
#include "pipe/p_compiler.h"
|
||
|
#include "util/u_network.h"
|
||
|
#include "util/u_debug.h"
|
||
|
|
||
|
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
||
|
# include <winsock2.h>
|
||
|
# include <windows.h>
|
||
|
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \
|
||
|
defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_SOLARIS)
|
||
|
# include <sys/socket.h>
|
||
|
# include <netinet/in.h>
|
||
|
# include <unistd.h>
|
||
|
# include <fcntl.h>
|
||
|
# include <netdb.h>
|
||
|
#else
|
||
|
# warning "No socket implementation"
|
||
|
#endif
|
||
|
|
||
|
boolean
|
||
|
u_socket_init()
|
||
|
{
|
||
|
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
||
|
WORD wVersionRequested;
|
||
|
WSADATA wsaData;
|
||
|
int err;
|
||
|
|
||
|
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
|
||
|
wVersionRequested = MAKEWORD(1, 1);
|
||
|
|
||
|
err = WSAStartup(wVersionRequested, &wsaData);
|
||
|
if (err != 0) {
|
||
|
debug_printf("WSAStartup failed with error: %d\n", err);
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
#elif defined(PIPE_HAVE_SOCKETS)
|
||
|
return TRUE;
|
||
|
#else
|
||
|
return FALSE;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void
|
||
|
u_socket_stop()
|
||
|
{
|
||
|
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
||
|
WSACleanup();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void
|
||
|
u_socket_close(int s)
|
||
|
{
|
||
|
if (s < 0)
|
||
|
return;
|
||
|
|
||
|
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
|
||
|
|| defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
|
||
|
shutdown(s, SHUT_RDWR);
|
||
|
close(s);
|
||
|
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
||
|
shutdown(s, SD_BOTH);
|
||
|
closesocket(s);
|
||
|
#else
|
||
|
assert(0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int u_socket_accept(int s)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
return accept(s, NULL, NULL);
|
||
|
#else
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
u_socket_send(int s, void *data, size_t size)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
return send(s, data, size, 0);
|
||
|
#else
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
u_socket_peek(int s, void *data, size_t size)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
return recv(s, data, size, MSG_PEEK);
|
||
|
#else
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
u_socket_recv(int s, void *data, size_t size)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
return recv(s, data, size, 0);
|
||
|
#else
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
u_socket_connect(const char *hostname, uint16_t port)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
int s;
|
||
|
struct sockaddr_in sa;
|
||
|
struct hostent *host = NULL;
|
||
|
|
||
|
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||
|
host = gethostbyname(hostname);
|
||
|
if (!host)
|
||
|
return -1;
|
||
|
|
||
|
memcpy((char *)&sa.sin_addr,host->h_addr_list[0],host->h_length);
|
||
|
sa.sin_family= host->h_addrtype;
|
||
|
sa.sin_port = htons(port);
|
||
|
|
||
|
s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP);
|
||
|
if (s < 0)
|
||
|
return -1;
|
||
|
|
||
|
if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) {
|
||
|
u_socket_close(s);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return s;
|
||
|
#else
|
||
|
assert(0);
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
int
|
||
|
u_socket_listen_on_port(uint16_t portnum)
|
||
|
{
|
||
|
#if defined(PIPE_HAVE_SOCKETS)
|
||
|
int s;
|
||
|
struct sockaddr_in sa;
|
||
|
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||
|
|
||
|
sa.sin_family = AF_INET;
|
||
|
sa.sin_port = htons(portnum);
|
||
|
|
||
|
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||
|
if (s < 0)
|
||
|
return -1;
|
||
|
|
||
|
if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) {
|
||
|
u_socket_close(s);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
listen(s, 0);
|
||
|
|
||
|
return s;
|
||
|
#else
|
||
|
assert(0);
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void
|
||
|
u_socket_block(int s, boolean block)
|
||
|
{
|
||
|
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
|
||
|
|| defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
|
||
|
int old = fcntl(s, F_GETFL, 0);
|
||
|
if (old == -1)
|
||
|
return;
|
||
|
|
||
|
/* TODO obey block */
|
||
|
if (block)
|
||
|
fcntl(s, F_SETFL, old & ~O_NONBLOCK);
|
||
|
else
|
||
|
fcntl(s, F_SETFL, old | O_NONBLOCK);
|
||
|
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
|
||
|
u_long iMode = block ? 0 : 1;
|
||
|
ioctlsocket(s, FIONBIO, &iMode);
|
||
|
#else
|
||
|
assert(0);
|
||
|
#endif
|
||
|
}
|