diff --git a/src/addrtable.c b/src/addrtable.c index c6f7040..c405154 100644 --- a/src/addrtable.c +++ b/src/addrtable.c @@ -21,6 +21,7 @@ #include #include +#include #include "addrtable.h" #include "ipxwrapper.h" @@ -176,9 +177,9 @@ bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse) lock_sockets(); - ipx_socket *s = sockets; + ipx_socket *s, *tmp; - for(; s; s = s->next) + HASH_ITER(hh, sockets, s, tmp) { if(memcmp(&(s->addr), addr, sizeof(struct sockaddr_ipx)) == 0 && (!(s->flags & IPX_REUSE) || !reuse)) { @@ -236,9 +237,9 @@ uint16_t addr_table_auto_socket(void) else{ lock_sockets(); - ipx_socket *s = sockets; + ipx_socket *s, *tmp; - while(s) + HASH_ITER(hh, sockets, s, tmp) { if((s->flags & IPX_BOUND) && ntohs(sock) == s->addr.sa_socket) { @@ -253,8 +254,6 @@ uint16_t addr_table_auto_socket(void) s = sockets; continue; } - - s = s->next; } unlock_sockets(); @@ -367,8 +366,6 @@ void addr_table_update(void) addr_table_lock(); - ipx_socket *sock = sockets; - /* Remove any expired entries. */ addr_table_entry_t *entry = addr_table_base; @@ -393,7 +390,9 @@ void addr_table_update(void) /* This is really, really efficient. */ - for(; sock; sock = sock->next) + ipx_socket *sock, *tmp; + + HASH_ITER(hh, sockets, sock, tmp) { if(sock->flags & IPX_BOUND) { diff --git a/src/ipxwrapper.c b/src/ipxwrapper.c index 55c34f1..3e5a438 100644 --- a/src/ipxwrapper.c +++ b/src/ipxwrapper.c @@ -113,37 +113,34 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res) return TRUE; } -/* Lock the mutex and search the sockets list for an ipx_socket structure with - * the requested fd, if no matching fd is found, unlock the mutex - * - * TODO: Change this behaviour. It is almost as bad as the BKL. +/* Lock the sockets table and search for one by file descriptor. + * + * Returns an ipx_socket pointer on success, unlocks the sockets table and + * returns NULL if no match is found. */ -ipx_socket *get_socket(SOCKET fd) { +ipx_socket *get_socket(SOCKET sockfd) +{ lock_sockets(); - ipx_socket *ptr = sockets; + ipx_socket *sock; + HASH_FIND_INT(sockets, &sockfd, sock); - while(ptr) { - if(ptr->fd == fd) { - break; - } - - ptr = ptr->next; - } - - if(!ptr) { + if(!sock) + { unlock_sockets(); } - return ptr; + return sock; } /* Lock the mutex */ -void lock_sockets(void) { +void lock_sockets(void) +{ EnterCriticalSection(&sockets_cs); } /* Unlock the mutex */ -void unlock_sockets(void) { +void unlock_sockets(void) +{ LeaveCriticalSection(&sockets_cs); } diff --git a/src/ipxwrapper.h b/src/ipxwrapper.h index 3412e3f..31c1602 100644 --- a/src/ipxwrapper.h +++ b/src/ipxwrapper.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "config.h" #include "router.h" @@ -71,7 +72,7 @@ struct ipx_socket { /* Address used with connect call, only set when IPX_CONNECTED is */ struct sockaddr_ipx remote_addr; - ipx_socket *next; + UT_hash_handle hh; }; struct ipx_packet { @@ -92,7 +93,7 @@ struct ipx_packet { extern ipx_socket *sockets; extern main_config_t main_config; -ipx_socket *get_socket(SOCKET fd); +ipx_socket *get_socket(SOCKET sockfd); void lock_sockets(void); void unlock_sockets(void); diff --git a/src/router.c b/src/router.c index f404d68..728c137 100644 --- a/src/router.c +++ b/src/router.c @@ -17,6 +17,7 @@ #include #include +#include #include "router.h" #include "common.h" @@ -205,9 +206,9 @@ static bool handle_recv(int fd) lock_sockets(); - ipx_socket *sock = sockets; + ipx_socket *sock, *tmp; - for(; sock; sock = sock->next) + HASH_ITER(hh, sockets, sock, tmp) { if( /* Socket is bound and not shutdown for recv. */ diff --git a/src/winsock.c b/src/winsock.c index c490746..7d2d9f0 100644 --- a/src/winsock.c +++ b/src/winsock.c @@ -154,19 +154,22 @@ INT WINAPI WSHEnumProtocols(LPINT protocols, LPWSTR ign, LPVOID buf, LPDWORD bsp return do_EnumProtocols(protocols, buf, bsptr, FALSE); } -SOCKET WSAAPI socket(int af, int type, int protocol) { +SOCKET WSAAPI socket(int af, int type, int protocol) +{ log_printf(LOG_DEBUG, "socket(%d, %d, %d)", af, type, protocol); - if(af == AF_IPX) { + if(af == AF_IPX) + { ipx_socket *nsock = malloc(sizeof(ipx_socket)); - if(!nsock) { + if(!nsock) + { WSASetLastError(ERROR_OUTOFMEMORY); return -1; } - nsock->fd = r_socket(AF_INET, SOCK_DGRAM, 0); - if(nsock->fd == -1) { - log_printf(LOG_ERROR, "Creating fake socket failed: %s", w32_error(WSAGetLastError())); + if((nsock->fd = r_socket(AF_INET, SOCK_DGRAM, 0)) == -1) + { + log_printf(LOG_ERROR, "Cannot create UDP socket: %s", w32_error(WSAGetLastError())); free(nsock); return -1; @@ -175,59 +178,49 @@ SOCKET WSAAPI socket(int af, int type, int protocol) { nsock->flags = IPX_SEND | IPX_RECV | IPX_RECV_BCAST; nsock->s_ptype = (protocol ? NSPROTO_IPX - protocol : 0); - lock_sockets(); - - nsock->next = sockets; - sockets = nsock; - log_printf(LOG_INFO, "IPX socket created (fd = %d)", nsock->fd); - RETURN(nsock->fd); - }else{ + lock_sockets(); + HASH_ADD_INT(sockets, fd, nsock); + unlock_sockets(); + + return nsock->fd; + } + else{ return r_socket(af, type, protocol); } } -int WSAAPI closesocket(SOCKET fd) { - int ret = r_closesocket(fd); +int WSAAPI closesocket(SOCKET sockfd) +{ + int ret = r_closesocket(sockfd); - ipx_socket *ptr = get_socket(fd); - ipx_socket *pptr = sockets; - - if(!ptr) { + ipx_socket *sock = get_socket(sockfd); + if(!sock) + { /* Not an IPX socket */ return ret; } - if(ret == SOCKET_ERROR) { - log_printf(LOG_ERROR, "closesocket(%d) failed: %s", fd, w32_error(WSAGetLastError())); + if(ret == SOCKET_ERROR) + { + log_printf(LOG_ERROR, "closesocket(%d): %s", sockfd, w32_error(WSAGetLastError())); RETURN(SOCKET_ERROR); } - log_printf(LOG_INFO, "IPX socket closed (fd = %d)", fd); + log_printf(LOG_INFO, "IPX socket closed (fd = %d)", sockfd); - if(ptr->flags & IPX_BOUND) + if(sock->flags & IPX_BOUND) { - addr_table_remove(ptr->port); + addr_table_remove(sock->port); } - if(ptr == sockets) { - sockets = ptr->next; - free(ptr); - }else{ - while(ptr && pptr->next) { - if(ptr == pptr->next) { - pptr->next = ptr->next; - free(ptr); - - break; - } - - pptr = pptr->next; - } - } + HASH_DEL(sockets, sock); + free(sock); - RETURN(0); + unlock_sockets(); + + return 0; } static bool _complete_bind_address(struct sockaddr_ipx *addr)