diff --git a/src/inet.c b/src/inet.c index 60106f2..b7f3ae5 100644 --- a/src/inet.c +++ b/src/inet.c @@ -19,10 +19,6 @@ static int inet_global_tohostname(lua_State *L); static void inet_pushresolved(lua_State *L, struct hostent *hp); -#ifdef INET_ATON -static int inet_aton(const char *cp, struct in_addr *inp); -#endif - static luaL_reg func[] = { { "toip", inet_global_toip }, { "tohostname", inet_global_tohostname }, @@ -196,9 +192,11 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp) * Returns * NULL in case of success, error message otherwise \*-------------------------------------------------------------------------*/ -const char *inet_tryconnect(p_sock ps, const char *address, ushort port) +const char *inet_tryconnect(p_sock ps, const char *address, + unsigned short port) { struct sockaddr_in remote; + const char *err; memset(&remote, 0, sizeof(remote)); remote.sin_family = AF_INET; remote.sin_port = htons(port); @@ -213,7 +211,7 @@ const char *inet_tryconnect(p_sock ps, const char *address, ushort port) } } else remote.sin_family = AF_UNSPEC; sock_setblocking(ps); - const char *err = sock_connect(ps, (SA *) &remote, sizeof(remote)); + err = sock_connect(ps, (SA *) &remote, sizeof(remote)); if (err) { sock_destroy(ps); *ps = SOCK_INVALID; @@ -233,10 +231,11 @@ const char *inet_tryconnect(p_sock ps, const char *address, ushort port) * Returns * NULL in case of success, error message otherwise \*-------------------------------------------------------------------------*/ -const char *inet_trybind(p_sock ps, const char *address, ushort port, +const char *inet_trybind(p_sock ps, const char *address, unsigned short port, int backlog) { struct sockaddr_in local; + const char *err; memset(&local, 0, sizeof(local)); /* address is either wildcard or a valid ip address */ local.sin_addr.s_addr = htonl(INADDR_ANY); @@ -251,7 +250,7 @@ const char *inet_trybind(p_sock ps, const char *address, ushort port, memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); } sock_setblocking(ps); - const char *err = sock_bind(ps, (SA *) &local, sizeof(local)); + err = sock_bind(ps, (SA *) &local, sizeof(local)); if (err) { sock_destroy(ps); *ps = SOCK_INVALID; @@ -279,8 +278,8 @@ const char *inet_trycreate(p_sock ps, int type) * Some systems do not provide this so that we provide our own. It's not * marvelously fast, but it works just fine. \*-------------------------------------------------------------------------*/ -#ifdef COMPAT_INETATON -static int inet_aton(const char *cp, struct in_addr *inp) +#ifdef INET_ATON +int inet_aton(const char *cp, struct in_addr *inp) { unsigned int a = 0, b = 0, c = 0, d = 0; int n = 0, r; diff --git a/src/inet.h b/src/inet.h index b8d8f19..60be9e4 100644 --- a/src/inet.h +++ b/src/inet.h @@ -23,4 +23,8 @@ const char *inet_trycreate(p_sock ps, int type); int inet_meth_getpeername(lua_State *L, p_sock ps); int inet_meth_getsockname(lua_State *L, p_sock ps); +#ifdef INET_ATON +int inet_aton(const char *cp, struct in_addr *inp); +#endif + #endif /* INET_H_ */ diff --git a/src/tcp.c b/src/tcp.c index 74857c9..dc7683d 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -154,7 +154,7 @@ static int meth_connect(lua_State *L) { p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); const char *address = luaL_checkstring(L, 2); - unsigned short port = (ushort) luaL_checknumber(L, 3); + unsigned short port = (unsigned short) luaL_checknumber(L, 3); const char *err = inet_tryconnect(&tcp->sock, address, port); if (err) { lua_pushnil(L); @@ -174,7 +174,7 @@ static int meth_bind(lua_State *L) { p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); const char *address = luaL_checkstring(L, 2); - unsigned short port = (ushort) luaL_checknumber(L, 3); + unsigned short port = (unsigned short) luaL_checknumber(L, 3); int backlog = (int) luaL_optnumber(L, 4, 1); const char *err = inet_trybind(&tcp->sock, address, port, backlog); if (err) { @@ -227,12 +227,13 @@ static int meth_accept(lua_State *L) \*-------------------------------------------------------------------------*/ int global_create(lua_State *L) { + const char *err; /* allocate tcp object */ p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); /* set its type as master object */ aux_setclass(L, "tcp{master}", -1); /* try to allocate a system socket */ - const char *err = inet_trycreate(&tcp->sock, SOCK_STREAM); + err = inet_trycreate(&tcp->sock, SOCK_STREAM); if (err) { /* get rid of object on stack and push error */ lua_pop(L, 1); lua_pushnil(L); diff --git a/src/udp.c b/src/udp.c index bcf515b..79831e7 100644 --- a/src/udp.c +++ b/src/udp.c @@ -104,7 +104,7 @@ static int meth_sendto(lua_State *L) size_t count, sent = 0; const char *data = luaL_checklstring(L, 2, &count); const char *ip = luaL_checkstring(L, 3); - ushort port = (ushort) luaL_checknumber(L, 4); + unsigned short port = (unsigned short) luaL_checknumber(L, 4); p_tm tm = &udp->tm; struct sockaddr_in addr; int err; @@ -220,7 +220,8 @@ static int meth_setpeername(lua_State *L) const char *address = luaL_checkstring(L, 2); int connecting = strcmp(address, "*"); unsigned short port = connecting ? - (ushort) luaL_checknumber(L, 3) : (ushort) luaL_optnumber(L, 3, 0); + (unsigned short) luaL_checknumber(L, 3) : + (unsigned short) luaL_optnumber(L, 3, 0); const char *err = inet_tryconnect(&udp->sock, address, port); if (err) { lua_pushnil(L); @@ -251,7 +252,7 @@ static int meth_setsockname(lua_State *L) { p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1); const char *address = luaL_checkstring(L, 2); - unsigned short port = (ushort) luaL_checknumber(L, 3); + unsigned short port = (unsigned short) luaL_checknumber(L, 3); const char *err = inet_trybind(&udp->sock, address, port, -1); if (err) { lua_pushnil(L); @@ -270,12 +271,13 @@ static int meth_setsockname(lua_State *L) \*-------------------------------------------------------------------------*/ int global_create(lua_State *L) { + const char *err; /* allocate udp object */ p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); /* set its type as master object */ aux_setclass(L, "udp{unconnected}", -1); /* try to allocate a system socket */ - const char *err = inet_trycreate(&udp->sock, SOCK_DGRAM); + err = inet_trycreate(&udp->sock, SOCK_DGRAM); if (err) { /* get rid of object on stack and push error */ lua_pop(L, 1); diff --git a/src/usocket.h b/src/usocket.h index 9e4b75a..034ae74 100644 --- a/src/usocket.h +++ b/src/usocket.h @@ -3,8 +3,8 @@ * * RCS ID: $Id$ \*=========================================================================*/ -#ifndef UNIX_H -#define UNIX_H +#ifndef USOCKET_H +#define USOCKET_H /*=========================================================================*\ * BSD include files @@ -41,4 +41,4 @@ typedef t_sock *p_sock; #define SOCK_INVALID (-1) -#endif /* UNIX_H */ +#endif /* USOCKET_H */ diff --git a/src/wsocket.c b/src/wsocket.c new file mode 100644 index 0000000..56e65ec --- /dev/null +++ b/src/wsocket.c @@ -0,0 +1,261 @@ +#include + +#include "socket.h" + +int sock_open(void) +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD(2, 0); + err = WSAStartup(wVersionRequested, &wsaData ); + if (err != 0) return 0; + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { + WSACleanup(); + return 0; + } + return 1; +} + +void sock_destroy(p_sock ps) +{ + closesocket(*ps); +} + +const char *sock_create(p_sock ps, int domain, int type, int protocol) +{ + t_sock sock = socket(domain, type, protocol); + if (sock == SOCK_INVALID) return sock_createstrerror(); + *ps = sock; + sock_setnonblocking(ps); + sock_setreuseaddr(ps); + return NULL; +} + +const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) +{ + if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); + else return NULL; +} + +const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) +{ + if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); + else return NULL; +} + +void sock_listen(p_sock ps, int backlog) +{ + listen(*ps, backlog); +} + +int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, + int timeout) +{ + t_sock sock = *ps; + struct timeval tv; + SA dummy_addr; + socklen_t dummy_len; + fd_set fds; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(&fds); + FD_SET(sock, &fds); + if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) + return IO_TIMEOUT; + if (!addr) addr = &dummy_addr; + if (!addr_len) addr_len = &dummy_len; + *pa = accept(sock, addr, addr_len); + if (*pa == SOCK_INVALID) return IO_ERROR; + else return IO_DONE; +} + +int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, + int timeout) +{ + t_sock sock = *ps; + struct timeval tv; + fd_set fds; + ssize_t put = 0; + int err; + int ret; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(&fds); + FD_SET(sock, &fds); + ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); + if (ret > 0) { + put = send(sock, data, count, 0); + if (put <= 0) { + /* a bug in WinSock forces us to do a busy wait until we manage + ** to write, because select returns immediately even though it + ** should have blocked us until we could write... */ + if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; + else err = IO_CLOSED; + *sent = 0; + } else { + *sent = put; + err = IO_DONE; + } + return err; + } else { + *sent = 0; + return IO_TIMEOUT; + } +} + +int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, + SA *addr, socklen_t addr_len, int timeout) +{ + t_sock sock = *ps; + struct timeval tv; + fd_set fds; + ssize_t put = 0; + int err; + int ret; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(&fds); + FD_SET(sock, &fds); + ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); + if (ret > 0) { + put = sendto(sock, data, count, 0, addr, addr_len); + if (put <= 0) { + /* a bug in WinSock forces us to do a busy wait until we manage + ** to write, because select returns immediately even though it + ** should have blocked us until we could write... */ + if (WSAGetLastError() == WSAEWOULDBLOCK) err = IO_DONE; + else err = IO_CLOSED; + *sent = 0; + } else { + *sent = put; + err = IO_DONE; + } + return err; + } else { + *sent = 0; + return IO_TIMEOUT; + } +} + +int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) +{ + t_sock sock = *ps; + struct timeval tv; + fd_set fds; + int ret; + ssize_t taken = 0; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(&fds); + FD_SET(sock, &fds); + ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); + if (ret > 0) { + taken = recv(sock, data, count, 0); + if (taken <= 0) { + *got = 0; + return IO_CLOSED; + } else { + *got = taken; + return IO_DONE; + } + } else { + *got = 0; + return IO_TIMEOUT; + } +} + +int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, + SA *addr, socklen_t *addr_len, int timeout) +{ + t_sock sock = *ps; + struct timeval tv; + fd_set fds; + int ret; + ssize_t taken = 0; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + FD_ZERO(&fds); + FD_SET(sock, &fds); + ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); + if (ret > 0) { + taken = recvfrom(sock, data, count, 0, addr, addr_len); + if (taken <= 0) { + *got = 0; + return IO_CLOSED; + } else { + *got = taken; + return IO_DONE; + } + } else { + *got = 0; + return IO_TIMEOUT; + } +} + +const char *sock_hoststrerror(void) +{ + switch (WSAGetLastError()) { + case HOST_NOT_FOUND: return "host not found"; + case NO_ADDRESS: return "unable to resolve host name"; + case NO_RECOVERY: return "name server error"; + case TRY_AGAIN: return "name server unavailable, try again later."; + default: return "unknown error"; + } +} + +const char *sock_createstrerror(void) +{ + switch (WSAGetLastError()) { + case WSANOTINITIALISED: return "not initialized"; + case WSAENETDOWN: return "network is down"; + case WSAEMFILE: return "descriptor table is full"; + case WSAENOBUFS: return "insufficient buffer space"; + default: return "unknown error"; + } +} + +const char *sock_bindstrerror(void) +{ + switch (WSAGetLastError()) { + case WSANOTINITIALISED: return "not initialized"; + case WSAENETDOWN: return "network is down"; + case WSAEADDRINUSE: return "address already in use"; + case WSAEINVAL: return "socket already bound"; + case WSAENOBUFS: return "too many connections"; + case WSAEFAULT: return "invalid address"; + case WSAENOTSOCK: return "not a socket descriptor"; + default: return "unknown error"; + } +} + +const char *sock_connectstrerror(void) +{ + switch (WSAGetLastError()) { + case WSANOTINITIALISED: return "not initialized"; + case WSAENETDOWN: return "network is down"; + case WSAEADDRINUSE: return "address already in use"; + case WSAEADDRNOTAVAIL: return "address unavailable"; + case WSAECONNREFUSED: return "connection refused"; + case WSAENETUNREACH: return "network is unreachable"; + default: return "unknown error"; + } +} + +void sock_setreuseaddr(p_sock ps) +{ + int val = 1; + setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); +} + +void sock_setblocking(p_sock ps) +{ + u_long argp = 0; + ioctlsocket(*ps, FIONBIO, &argp); +} + +void sock_setnonblocking(p_sock ps) +{ + u_long argp = 1; + ioctlsocket(*ps, FIONBIO, &argp); +} diff --git a/src/wsocket.h b/src/wsocket.h new file mode 100644 index 0000000..ceecae7 --- /dev/null +++ b/src/wsocket.h @@ -0,0 +1,22 @@ +/*=========================================================================*\ +* Socket compatibilization module for Win32 +* +* RCS ID: $Id$ +\*=========================================================================*/ +#ifndef WSOCKET_H +#define WSOCKET_H + +/*=========================================================================*\ +* WinSock2 include files +\*=========================================================================*/ +#include +#include + +typedef int socklen_t; +typedef int ssize_t; +typedef SOCKET t_sock; +typedef t_sock *p_sock; + +#define SOCK_INVALID (INVALID_SOCKET) + +#endif /* WSOCKET_H */