X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=blobdiff_plain;f=src%2FQServer.c;h=ef382c98d46cfb945f95c9174df9bc134c9983d2;hp=a9e36faa7b21d907ff6b70cf36dd69ed4964af06;hb=HEAD;hpb=689da1db7e2517c187ce76c6c553e20d630a7f36 diff --git a/src/QServer.c b/src/QServer.c index a9e36fa..ef382c9 100644 --- a/src/QServer.c +++ b/src/QServer.c @@ -1,4 +1,4 @@ -/* QServer.c - NeonServ v5.4 +/* QServer.c - NeonServ v5.6 * Copyright (C) 2011-2012 Philipp Kreil (pk910) * * This program is free software: you can redistribute it and/or modify @@ -24,6 +24,8 @@ #include "WHOHandler.h" #include "ConfigParser.h" #include "bots.h" +#include "IOHandler.h" +#include "tools.h" #ifdef WIN32 typedef uint32_t socklen_t; @@ -32,52 +34,55 @@ typedef uint32_t socklen_t; #define QSERVER_TIMEOUT 30 #define QSERVER_MAXCLIENTS 100 -#define QSERVER_FLAG_DISCONNECT 0x01 -#define QSERVER_FLAG_AUTHED 0x02 -#define QSERVER_FLAG_IN_USE 0x04 +#define QSERVER_FLAG_AUTHED 0x01 +#define QSERVER_FLAG_IN_USE 0x02 struct QServerClient { - int sock; + struct IODescriptor *iofd; unsigned int flags; - time_t lastmsg; - char buffer[MAXLEN]; - int bufferpos; int references; struct QServerClient *next; }; -static int server_sockfd = 0; +static struct IODescriptor *server_iofd = NULL; struct QServerClient *qserver_clients = NULL; static int qserver_clientcount = 0; +static IOHANDLER_CALLBACK(qserver_callback); + void qserver_init() { if(get_int_field("QServer.enabled")) { - server_sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (server_sockfd < 0) - return; - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - int portno = get_int_field("QServer.port"); - if(!portno) - portno = 7499; - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = INADDR_ANY; - serv_addr.sin_port = htons(portno); - if (bind(server_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) - return; - listen(server_sockfd,5); + char *host = get_string_field("QServer.host"); + if(!host) + host = "0.0.0.0"; + int port = get_int_field("QServer.port"); + if(!port) + port = 7499; + server_iofd = iohandler_listen(host, port, qserver_callback); } } +void qserver_free() { + if(!server_iofd) + return; + struct QServerClient *client, *next; + for (client = qserver_clients; client; client = next) { + next = client->next; + if(client->iofd) + iohandler_close(client->iofd); + free(client); + } + qserver_clients = NULL; + qserver_clientcount = 0; + iohandler_close(server_iofd); + server_iofd = NULL; +} + static int qserver_write(struct QServerClient *client, char* msg, int len) { - if (!(client && !(client->flags & QSERVER_FLAG_DISCONNECT))) return 0; + if (!client || !client->iofd) return 0; if(!len) len = strlen(msg); - #ifdef WIN32 - send(client->sock, msg, len, 0); - #else - write(client->sock, msg, len); - #endif + iohandler_send(client->iofd, msg, len); return 1; } @@ -85,7 +90,7 @@ static void qserver_put(struct QServerClient *client, const char *text, ...) { va_list arg_list; char sendBuf[MAXLEN]; int pos; - if (!(client && !(client->flags & QSERVER_FLAG_DISCONNECT))) return; + if (!client || !client->iofd) return; sendBuf[0] = '\0'; va_start(arg_list, text); pos = vsnprintf(sendBuf, MAXLEN - 2, text, arg_list); @@ -96,6 +101,13 @@ static void qserver_put(struct QServerClient *client, const char *text, ...) { qserver_write(client, sendBuf, pos+1); } +static void qserver_update_lastmsg(struct QServerClient *client) { + struct timeval timeout; + gettimeofday(&timeout, NULL); + timeout.tv_sec += QSERVER_TIMEOUT; + iohandler_set_timeout(client->iofd, &timeout); +} + static void qserver_parse_A(struct QServerClient *client, char **argv, int argc) { if(client->flags & QSERVER_FLAG_AUTHED) { qserver_put(client, "E :Already Authed"); @@ -110,7 +122,7 @@ static void qserver_parse_A(struct QServerClient *client, char **argv, int argc) return; } client->flags |= QSERVER_FLAG_AUTHED; - client->lastmsg = time(0); + qserver_update_lastmsg(client); qserver_put(client, "A :Logged in"); } @@ -119,7 +131,7 @@ static void qserver_parse_A(struct QServerClient *client, char **argv, int argc) qserver_put(client, "E :Not Authed");\ return;\ }\ - client->lastmsg = time(0);\ + qserver_update_lastmsg(client);\ } static void qserver_parse_U(struct QServerClient *client, char **argv, int argc); @@ -128,7 +140,7 @@ static void qserver_parse_AC(struct QServerClient *client, char **argv, int argc static void qserver_parse_ACU(struct QServerClient *client, char **argv, int argc); static void qserver_parse_R(struct QServerClient *client, char **argv, int argc); -static void qserver_parse(struct QServerClient *client, char *line, int len) { +static void qserver_parse(struct QServerClient *client, char *line) { int argc = 0; char *argv[MAXNUMPARAMS]; while(*line) { @@ -162,115 +174,59 @@ static void qserver_parse(struct QServerClient *client, char *line, int len) { qserver_put(client, "E :Unknown Command"); } -void qserver_loop() { - if(!get_int_field("QServer.enabled")) +static void qserver_accept(int sockfd) { + struct IODescriptor *client_iofd = iohandler_add(sockfd, IOTYPE_CLIENT, NULL, qserver_callback); + client_iofd->state = IO_CONNECTED; + iohandler_update(client_iofd); + if(qserver_clientcount >= QSERVER_MAXCLIENTS) { + iohandler_printf(client_iofd, "E :Maximum QServer Connections reached"); + iohandler_close(client_iofd); return; - struct timeval tv; + } + struct QServerClient *client = malloc(sizeof(*client)); + client->iofd = client_iofd; + client->references = 0; + client->next = qserver_clients; + qserver_clients = client; + qserver_clientcount++; +} + +static void qserver_cleanup() { struct QServerClient *client, *next, *prev = NULL; - int ret; - time_t now = time(0); - fd_set fds; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&fds); - ret = server_sockfd; - FD_SET(server_sockfd, &fds); for (client = qserver_clients; client; client = next) { next = client->next; - if((client->flags & (QSERVER_FLAG_DISCONNECT | QSERVER_FLAG_IN_USE)) == QSERVER_FLAG_DISCONNECT) { - close(client->sock); + if(client->iofd == NULL && !(client->flags & QSERVER_FLAG_IN_USE)) { if(prev) prev->next = client->next; else qserver_clients = client->next; qserver_clientcount--; free(client); - continue; - } - prev = client; - if(client->flags & QSERVER_FLAG_DISCONNECT) continue; - if(now - client->lastmsg > QSERVER_TIMEOUT) { - qserver_put(client, "E :Timeout"); - client->flags |= QSERVER_FLAG_DISCONNECT; - continue; - } - FD_SET(client->sock, &fds); - if(client->sock > ret) - ret = client->sock; - } - ret = select(ret + 1, &fds, NULL, NULL, &tv); - if(ret == 0) { - return; - } - if(FD_ISSET(server_sockfd, &fds)) { - //new connection - struct sockaddr_in cli_addr; - #ifdef WIN32 - int clilen; - #else - socklen_t clilen; - #endif - client = malloc(sizeof(*client)); - clilen = sizeof(cli_addr); - client->sock = accept(server_sockfd, (struct sockaddr *) &cli_addr, &clilen); - client->flags = 0; - if(qserver_clientcount >= QSERVER_MAXCLIENTS) { - qserver_put(client, "E :Maximum QServer Connections reached"); - close(client->sock); - free(client); - } else { - client->lastmsg = now; - client->bufferpos = 0; - client->references = 0; - client->next = qserver_clients; - qserver_clients = client; - qserver_clientcount++; - } - } - int bytes, i; - char buffer[MAXLEN]; - for (client = qserver_clients; client; client = next) { - next = client->next; - if(FD_ISSET(client->sock, &fds)) { - #ifdef WIN32 - bytes = recv(client->sock, buffer, sizeof(buffer), 0); - #else - bytes = read(client->sock, buffer, sizeof(buffer)); - #endif - if(bytes <= 0) { - client->flags |= QSERVER_FLAG_DISCONNECT; - continue; - } - for(i = 0; i < bytes; i++) { - if(client->bufferpos == MAXLEN-1) { - //buffer overflow - qserver_put(client, "E :Buffer Overflow"); - client->flags |= QSERVER_FLAG_DISCONNECT; - break; - } - if(buffer[i] == '\r') continue; - else if(buffer[i] == '\n') { - client->buffer[client->bufferpos] = '\0'; - qserver_parse(client, client->buffer, client->bufferpos); - client->bufferpos = 0; - } else { - client->buffer[client->bufferpos++] = buffer[i]; - } - } } } } -void qserver_free() { - struct QServerClient *client, *next; - for (client = qserver_clients; client; client = next) { - next = client->next; - close(client->sock); - free(client); +static IOHANDLER_CALLBACK(qserver_callback) { + struct QServerClient *client = event->iofd->data; + switch(event->type) { + case IOEVENT_TIMEOUT: + qserver_put(client, "E :Timeout"); + client->iofd = NULL; + break; + case IOEVENT_RECV: + qserver_parse(client, event->data.recv_str); + break; + case IOEVENT_CLOSED: + iohandler_close(client->iofd); + client->iofd = NULL; + break; + case IOEVENT_ACCEPT: + qserver_accept(event->data.accept_fd); + break; + default: + break; } - qserver_clients = NULL; - qserver_clientcount = 0; - close(server_sockfd); + qserver_cleanup(); } /*