소스 검색

- 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://svn.code.sf.net/p/rathena/svn/trunk@10110 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 18 년 전
부모
커밋
258746a5f9
3개의 변경된 파일64개의 추가작업 그리고 40개의 파일을 삭제
  1. 6 0
      src/common/socket.c
  2. 30 20
      src/login/login.c
  3. 28 20
      src/login_sql/login.c

+ 6 - 0
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);
 

+ 30 - 20
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;

+ 28 - 20
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;