1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

Listen for and accept/close client connections in router code.

This commit is contained in:
Daniel Collins 2011-09-09 15:50:55 +00:00
parent 8928ae23cc
commit 6d6ac5f2c3
3 changed files with 131 additions and 3 deletions

View File

@ -8,6 +8,8 @@ ntohl
htons
ntohs
select
listen
accept
WSACreateEvent
WSAEventSelect
WSACloseEvent

View File

@ -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);

View File

@ -23,6 +23,30 @@
#include <wsipx.h>
#include <stdint.h>
#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;