From 20e3875e35b8e4801ef22eb72de8508c0879d518 Mon Sep 17 00:00:00 2001 From: skotlex Date: Sun, 1 Apr 2007 16:25:34 +0000 Subject: - Modified waiting_disconnect on the login server to hold the timer id of the 'set offline' timer. - connect_client will no longer accept connections when their number is greater than FD_SETSIZE to prevent crashes on packet parsing. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@10110 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/common/socket.c | 6 ++++++ src/login/login.c | 50 ++++++++++++++++++++++++++++++-------------------- src/login_sql/login.c | 48 ++++++++++++++++++++++++++++-------------------- 3 files changed, 64 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/common/socket.c b/src/common/socket.c index d816767ae..4e001c512 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -248,6 +248,12 @@ int connect_client(int listen_fd) return -1; } + if ( fd >= FD_SETSIZE ) + { //More connections than we can handle! + ShowError("accept failed. Received socket #%d is greater than can we handle! Increase the value of FD_SETSIZE (%d) for your OS to fix this!\n", fd, FD_SETSIZE); + closesocket(fd); + return -1; + } setsocketopts(fd); set_nonblocking(fd, 1); diff --git a/src/login/login.c b/src/login/login.c index 1b5e96596..b6b2c6402 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -122,8 +122,8 @@ int auth_fifo_pos = 0; struct online_login_data { int account_id; + int waiting_disconnect; short char_server; - short waiting_disconnect; }; struct auth_dat { @@ -204,8 +204,10 @@ static void* create_online_user(DBKey key, va_list args) { p = aCalloc(1, sizeof(struct online_login_data)); p->account_id = key.i; p->char_server = -1; - return p; + return p; } +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); + //----------------------------------------------------- // Online User Database [Wizputer] //----------------------------------------------------- @@ -216,11 +218,13 @@ void add_online_user (int char_server, int account_id) { return; p = idb_ensure(online_db, account_id, create_online_user); p->char_server = char_server; - p->waiting_disconnect = 0; -} -int is_user_online (int account_id) { - return (idb_get(online_db, account_id) != NULL); + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } + void remove_online_user (int account_id) { if(!online_check) return; @@ -231,11 +235,14 @@ void remove_online_user (int account_id) { idb_remove(online_db,account_id); } -int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) { struct online_login_data *p; - if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect) + if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect == id) + { + p->waiting_disconnect = -1; remove_online_user(p->account_id); + } return 0; } @@ -1312,9 +1319,8 @@ int mmo_auth(struct mmo_account* account, int fd) WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = auth_dat[i].account_id; charif_sendallwos(-1, buf, 6); - if (!data->waiting_disconnect) - add_timer(gettick()+30000, waiting_disconnect_timer,auth_dat[i].account_id, 0); - data->waiting_disconnect = 1; + if (data->waiting_disconnect == -1) + data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer,auth_dat[i].account_id, 0); return 3; // Rejected } } @@ -1392,7 +1398,11 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap) { int server = va_arg(ap, int); if (server == -1) { p->char_server = -1; - p->waiting_disconnect = 0; + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } else if (p->char_server == server) p->char_server = -2; //Char server disconnected. return 0; @@ -1899,11 +1909,7 @@ int parse_fromchar(int fd) { case 0x272d: // Receive list of all online accounts. [Skotlex] if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; - if (!online_check) { - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; - } - { + if (online_check) { struct online_login_data *p; int aid; unsigned int users; @@ -1913,11 +1919,15 @@ int parse_fromchar(int fd) { aid = RFIFOL(fd,6+i*4); p = idb_ensure(online_db, aid, create_online_user); p->char_server = id; - p->waiting_disconnect = 0; + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; } + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; case 0x272e: //Request account_reg2 for a character. if (RFIFOREST(fd) < 10) return 0; diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 2d2e7af9f..0c4b77b61 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -125,8 +125,8 @@ int auth_fifo_pos = 0; struct online_login_data { int account_id; + int waiting_disconnect; short char_server; - short waiting_disconnect; }; //----------------------------------------------------- @@ -141,10 +141,12 @@ static void* create_online_user(DBKey key, va_list args) p = aCalloc(1, sizeof(struct online_login_data)); p->account_id = key.i; p->char_server = -1; + p->waiting_disconnect = -1; return p; } int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len); +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); //----------------------------------------------------- // Online User Database [Wizputer] @@ -157,12 +159,11 @@ void add_online_user(int char_server, int account_id) return; p = idb_ensure(online_db, account_id, create_online_user); p->char_server = char_server; - p->waiting_disconnect = 0; -} - -int is_user_online(int account_id) -{ - return (idb_get(online_db, account_id) != NULL); + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } void remove_online_user(int account_id) @@ -176,11 +177,14 @@ void remove_online_user(int account_id) idb_remove(online_db,account_id); } -int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) { struct online_login_data *p; - if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect) + if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect == id) + { + p->waiting_disconnect = -1; remove_online_user(id); + } return 0; } @@ -735,9 +739,8 @@ int mmo_auth(struct mmo_account* account, int fd) WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = atol(sql_row[0]); charif_sendallwos(-1, buf, 6); - if (!data->waiting_disconnect) - add_timer(gettick()+30000, waiting_disconnect_timer, atol(sql_row[0]), 0); - data->waiting_disconnect = 1; + if (data->waiting_disconnect == -1) + data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer, atol(sql_row[0]), 0); return 3; // Rejected } } @@ -768,7 +771,11 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap) int server = va_arg(ap, int); if (server == -1) { p->char_server = -1; - p->waiting_disconnect = 0; + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } else if (p->char_server == server) p->char_server = -2; //Char server disconnected. return 0; @@ -1222,11 +1229,7 @@ int parse_fromchar(int fd) case 0x272d: // Receive list of all online accounts. [Skotlex] if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) return 0; - if (!login_config.online_check) { - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; - } - { + if (login_config.online_check) { struct online_login_data *p; int aid, users; online_db->foreach(online_db,online_db_setoffline,id); //Set all chars from this char-server offline first @@ -1235,10 +1238,15 @@ int parse_fromchar(int fd) aid = RFIFOL(fd,6+i*4); p = idb_ensure(online_db, aid, create_online_user); p->char_server = id; + if (p->waiting_disconnect != -1) + { + delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + p->waiting_disconnect = -1; + } } - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; } + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; case 0x272e: //Request account_reg2 for a character. if (RFIFOREST(fd) < 10) return 0; -- cgit v1.2.3-60-g2f50