From 6d6ac5f2c308dabdfddd8e28b49311e6f76b6d0c Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Fri, 9 Sep 2011 15:50:55 +0000 Subject: [PATCH] Listen for and accept/close client connections in router code. --- src/ipxwrapper_stubs.txt | 2 + src/router.c | 96 +++++++++++++++++++++++++++++++++++++++- src/router.h | 36 ++++++++++++++- 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/src/ipxwrapper_stubs.txt b/src/ipxwrapper_stubs.txt index d5e2a6b..cd5bf2d 100644 --- a/src/ipxwrapper_stubs.txt +++ b/src/ipxwrapper_stubs.txt @@ -8,6 +8,8 @@ ntohl htons ntohs select +listen +accept WSACreateEvent WSAEventSelect WSACloseEvent diff --git a/src/router.c b/src/router.c index 1a858c6..80befa4 100644 --- a/src/router.c +++ b/src/router.c @@ -38,7 +38,8 @@ struct router_vars *router_init(BOOL global) { router->running = TRUE; router->interfaces = NULL; router->udp_sock = -1; - router->listner = -1; + router->listener = -1; + router->client_count = 0; router->wsa_event = WSA_INVALID_EVENT; router->crit_sec_init = FALSE; router->addrs = NULL; @@ -104,7 +105,37 @@ struct router_vars *router_init(BOOL global) { } if(global) { - /* TODO: Global (service) router support */ + if((router->listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + log_printf("Failed to create TCP socket: %s", w32_error(WSAGetLastError())); + + router_destroy(router); + return NULL; + } + + /* TODO: Use different port number for control socket? */ + + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if(bind(router->listener, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + log_printf("Failed to bind TCP socket: %s", w32_error(WSAGetLastError())); + + router_destroy(router); + return NULL; + } + + if(listen(router->listener, 8) == -1) { + log_printf("Failed to listen for connections: %s", w32_error(WSAGetLastError())); + + router_destroy(router); + return NULL; + } + + if(WSAEventSelect(router->listener, router->wsa_event, FD_ACCEPT) == -1) { + log_printf("WSAEventSelect error: %s", w32_error(WSAGetLastError())); + + router_destroy(router); + return NULL; + } } return router; @@ -113,6 +144,7 @@ struct router_vars *router_init(BOOL global) { /* Release all resources allocated by a router and free it */ void router_destroy(struct router_vars *router) { struct router_addr *addr = router->addrs; + int i; while(addr) { struct router_addr *del = addr; @@ -121,6 +153,14 @@ void router_destroy(struct router_vars *router) { free(del); } + for(i = 0; i < router->client_count; i++) { + closesocket(router->clients[i].sock); + } + + if(router->listener != -1) { + closesocket(router->listener); + } + free(router->recvbuf); if(router->udp_sock != -1) { @@ -159,6 +199,58 @@ DWORD router_main(void *arg) { LeaveCriticalSection(&(router->crit_sec)); + if(router->listener != -1) { + int newfd = accept(router->listener, NULL, NULL); + if(newfd != -1) { + if(router->client_count == MAX_ROUTER_CLIENTS) { + log_printf("Too many clients, dropping new connection!"); + goto DROP_NEWFD; + } + + if(WSAEventSelect(newfd, router->wsa_event, FD_READ | FD_CLOSE) == -1) { + log_printf("WSAEventSelect error: %s", w32_error(WSAGetLastError())); + goto DROP_NEWFD; + } + + router->clients[router->client_count].sock = newfd; + router->clients[router->client_count++].recvbuf_len = 0; + + if(0) { + DROP_NEWFD: + closesocket(newfd); + } + }else if(WSAGetLastError() != WSAEWOULDBLOCK) { + log_printf("Failed to accept client connection: %s", w32_error(WSAGetLastError())); + } + } + + int i; + for(i = 0; i < router->client_count; i++) { + char *bstart = ((char*)&(router->clients[i].recvbuf)) + router->clients[i].recvbuf_len; + int len = sizeof(struct router_call) - router->clients[i].recvbuf_len; + + if((len = recv(router->clients[i].sock, bstart, len, 0) == -1) || len == 0) { + if(WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAECONNRESET) { + continue; + } + + if(len == -1) { + log_printf("Error reading from client socket: %s", w32_error(WSAGetLastError())); + } + + closesocket(router->clients[i].sock); + memcpy(&(router->clients[i]), &(router->clients[--router->client_count]), sizeof(struct router_client)); + + continue; + } + + if((router->clients[i].recvbuf_len += len) == sizeof(struct router_call)) { + /* TODO: Handle call */ + + router->clients[i].recvbuf_len = 0; + } + } + struct sockaddr_in addr; int addrlen = sizeof(addr); diff --git a/src/router.h b/src/router.h index 0c838d2..eb62623 100644 --- a/src/router.h +++ b/src/router.h @@ -23,6 +23,30 @@ #include #include +#define MAX_ROUTER_CLIENTS 128 + +struct router_call { + enum { + rc_bind, + rc_unbind, + rc_port, + rc_filter, + rc_reuse + } call; + + SOCKET sock; + + struct sockaddr_ipx arg_addr; + int arg_int; +}; + +struct router_ret { + int err_code; /* ERROR_SUCCESS on success */ + + struct sockaddr_ipx ret_addr; + int ret_int; +}; + /* Represents a bound IPX address */ struct router_addr { struct sockaddr_ipx addr; @@ -36,13 +60,23 @@ struct router_addr { struct router_addr *next; }; +struct router_client { + SOCKET sock; + + struct router_call recvbuf; + int recvbuf_len; +}; + struct router_vars { BOOL running; struct ipx_interface *interfaces; SOCKET udp_sock; - SOCKET listner; + SOCKET listener; + + struct router_client clients[MAX_ROUTER_CLIENTS]; + int client_count; WSAEVENT wsa_event;