mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Use a hash table instead of a linked list for storing the IPX sockets.
This commit is contained in:
parent
920b5ee2c3
commit
2a06601f53
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
#include <uthash.h>
|
||||||
|
|
||||||
#include "addrtable.h"
|
#include "addrtable.h"
|
||||||
#include "ipxwrapper.h"
|
#include "ipxwrapper.h"
|
||||||
@ -176,9 +177,9 @@ bool addr_table_check(const struct sockaddr_ipx *addr, bool reuse)
|
|||||||
|
|
||||||
lock_sockets();
|
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))
|
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{
|
else{
|
||||||
lock_sockets();
|
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)
|
if((s->flags & IPX_BOUND) && ntohs(sock) == s->addr.sa_socket)
|
||||||
{
|
{
|
||||||
@ -253,8 +254,6 @@ uint16_t addr_table_auto_socket(void)
|
|||||||
s = sockets;
|
s = sockets;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = s->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_sockets();
|
unlock_sockets();
|
||||||
@ -367,8 +366,6 @@ void addr_table_update(void)
|
|||||||
|
|
||||||
addr_table_lock();
|
addr_table_lock();
|
||||||
|
|
||||||
ipx_socket *sock = sockets;
|
|
||||||
|
|
||||||
/* Remove any expired entries. */
|
/* Remove any expired entries. */
|
||||||
|
|
||||||
addr_table_entry_t *entry = addr_table_base;
|
addr_table_entry_t *entry = addr_table_base;
|
||||||
@ -393,7 +390,9 @@ void addr_table_update(void)
|
|||||||
|
|
||||||
/* This is really, really efficient. */
|
/* 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)
|
if(sock->flags & IPX_BOUND)
|
||||||
{
|
{
|
||||||
|
@ -113,37 +113,34 @@ BOOL WINAPI DllMain(HINSTANCE me, DWORD why, LPVOID res)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex and search the sockets list for an ipx_socket structure with
|
/* Lock the sockets table and search for one by file descriptor.
|
||||||
* the requested fd, if no matching fd is found, unlock the mutex
|
*
|
||||||
*
|
* Returns an ipx_socket pointer on success, unlocks the sockets table and
|
||||||
* TODO: Change this behaviour. It is almost as bad as the BKL.
|
* returns NULL if no match is found.
|
||||||
*/
|
*/
|
||||||
ipx_socket *get_socket(SOCKET fd) {
|
ipx_socket *get_socket(SOCKET sockfd)
|
||||||
|
{
|
||||||
lock_sockets();
|
lock_sockets();
|
||||||
|
|
||||||
ipx_socket *ptr = sockets;
|
ipx_socket *sock;
|
||||||
|
HASH_FIND_INT(sockets, &sockfd, sock);
|
||||||
|
|
||||||
while(ptr) {
|
if(!sock)
|
||||||
if(ptr->fd == fd) {
|
{
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr = ptr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!ptr) {
|
|
||||||
unlock_sockets();
|
unlock_sockets();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the mutex */
|
/* Lock the mutex */
|
||||||
void lock_sockets(void) {
|
void lock_sockets(void)
|
||||||
|
{
|
||||||
EnterCriticalSection(&sockets_cs);
|
EnterCriticalSection(&sockets_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the mutex */
|
/* Unlock the mutex */
|
||||||
void unlock_sockets(void) {
|
void unlock_sockets(void)
|
||||||
|
{
|
||||||
LeaveCriticalSection(&sockets_cs);
|
LeaveCriticalSection(&sockets_cs);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <wsipx.h>
|
#include <wsipx.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <uthash.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
@ -71,7 +72,7 @@ struct ipx_socket {
|
|||||||
/* Address used with connect call, only set when IPX_CONNECTED is */
|
/* Address used with connect call, only set when IPX_CONNECTED is */
|
||||||
struct sockaddr_ipx remote_addr;
|
struct sockaddr_ipx remote_addr;
|
||||||
|
|
||||||
ipx_socket *next;
|
UT_hash_handle hh;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipx_packet {
|
struct ipx_packet {
|
||||||
@ -92,7 +93,7 @@ struct ipx_packet {
|
|||||||
extern ipx_socket *sockets;
|
extern ipx_socket *sockets;
|
||||||
extern main_config_t main_config;
|
extern main_config_t main_config;
|
||||||
|
|
||||||
ipx_socket *get_socket(SOCKET fd);
|
ipx_socket *get_socket(SOCKET sockfd);
|
||||||
void lock_sockets(void);
|
void lock_sockets(void);
|
||||||
void unlock_sockets(void);
|
void unlock_sockets(void);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
#include <uthash.h>
|
||||||
|
|
||||||
#include "router.h"
|
#include "router.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -205,9 +206,9 @@ static bool handle_recv(int fd)
|
|||||||
|
|
||||||
lock_sockets();
|
lock_sockets();
|
||||||
|
|
||||||
ipx_socket *sock = sockets;
|
ipx_socket *sock, *tmp;
|
||||||
|
|
||||||
for(; sock; sock = sock->next)
|
HASH_ITER(hh, sockets, sock, tmp)
|
||||||
{
|
{
|
||||||
if(
|
if(
|
||||||
/* Socket is bound and not shutdown for recv. */
|
/* Socket is bound and not shutdown for recv. */
|
||||||
|
@ -154,19 +154,22 @@ INT WINAPI WSHEnumProtocols(LPINT protocols, LPWSTR ign, LPVOID buf, LPDWORD bsp
|
|||||||
return do_EnumProtocols(protocols, buf, bsptr, FALSE);
|
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);
|
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));
|
ipx_socket *nsock = malloc(sizeof(ipx_socket));
|
||||||
if(!nsock) {
|
if(!nsock)
|
||||||
|
{
|
||||||
WSASetLastError(ERROR_OUTOFMEMORY);
|
WSASetLastError(ERROR_OUTOFMEMORY);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsock->fd = r_socket(AF_INET, SOCK_DGRAM, 0);
|
if((nsock->fd = r_socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
if(nsock->fd == -1) {
|
{
|
||||||
log_printf(LOG_ERROR, "Creating fake socket failed: %s", w32_error(WSAGetLastError()));
|
log_printf(LOG_ERROR, "Cannot create UDP socket: %s", w32_error(WSAGetLastError()));
|
||||||
|
|
||||||
free(nsock);
|
free(nsock);
|
||||||
return -1;
|
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->flags = IPX_SEND | IPX_RECV | IPX_RECV_BCAST;
|
||||||
nsock->s_ptype = (protocol ? NSPROTO_IPX - protocol : 0);
|
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);
|
log_printf(LOG_INFO, "IPX socket created (fd = %d)", nsock->fd);
|
||||||
|
|
||||||
RETURN(nsock->fd);
|
lock_sockets();
|
||||||
}else{
|
HASH_ADD_INT(sockets, fd, nsock);
|
||||||
|
unlock_sockets();
|
||||||
|
|
||||||
|
return nsock->fd;
|
||||||
|
}
|
||||||
|
else{
|
||||||
return r_socket(af, type, protocol);
|
return r_socket(af, type, protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int WSAAPI closesocket(SOCKET fd) {
|
int WSAAPI closesocket(SOCKET sockfd)
|
||||||
int ret = r_closesocket(fd);
|
{
|
||||||
|
int ret = r_closesocket(sockfd);
|
||||||
|
|
||||||
ipx_socket *ptr = get_socket(fd);
|
ipx_socket *sock = get_socket(sockfd);
|
||||||
ipx_socket *pptr = sockets;
|
if(!sock)
|
||||||
|
{
|
||||||
if(!ptr) {
|
|
||||||
/* Not an IPX socket */
|
/* Not an IPX socket */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ret == SOCKET_ERROR) {
|
if(ret == SOCKET_ERROR)
|
||||||
log_printf(LOG_ERROR, "closesocket(%d) failed: %s", fd, w32_error(WSAGetLastError()));
|
{
|
||||||
|
log_printf(LOG_ERROR, "closesocket(%d): %s", sockfd, w32_error(WSAGetLastError()));
|
||||||
RETURN(SOCKET_ERROR);
|
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) {
|
HASH_DEL(sockets, sock);
|
||||||
sockets = ptr->next;
|
free(sock);
|
||||||
free(ptr);
|
|
||||||
}else{
|
|
||||||
while(ptr && pptr->next) {
|
|
||||||
if(ptr == pptr->next) {
|
|
||||||
pptr->next = ptr->next;
|
|
||||||
free(ptr);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pptr = pptr->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN(0);
|
unlock_sockets();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _complete_bind_address(struct sockaddr_ipx *addr)
|
static bool _complete_bind_address(struct sockaddr_ipx *addr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user