Преглед изворни кода

* Optimized login-server some more [Wizputer]

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@503 54d463be-8e91-2dee-dedb-b68131a5f0ec
wizputer пре 20 година
родитељ
комит
1b9d601b96
5 измењених фајлова са 177 додато и 278 уклоњено
  1. 3 0
      Changelog.txt
  2. 44 65
      src/login_sql/char_int.c
  3. 92 122
      src/login_sql/login.c
  4. 2 1
      src/login_sql/login.h
  5. 36 90
      src/login_sql/login_int.c

+ 3 - 0
Changelog.txt

@@ -1,4 +1,7 @@
 Date	Added
+12/07
+	* Optimized login-server some more [Wizputer]
+
 12/05
 	* Added src/webserver, eAthena Web Server (Second Edition), not finished [MC Cameri]
 	* some cleanup of char_sql [MouseJstr]

+ 44 - 65
src/login_sql/char_int.c

@@ -15,7 +15,7 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
 	int fd;
 
 	c = 0;
-	for(i = 0; i < MAX_SERVERS; i++) {
+	for(i = 0; i < MAX_SERVERS && i < servers_connected; i++) {
 		if ((fd = server_fd[i]) > 0 && fd != sfd) {
 			memcpy(WFIFOP(fd,0), buf, len);
 			WFIFOSET(fd,len);
@@ -32,7 +32,7 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
 int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) {
 	int i;
 
-	for(i = 0; i < MAX_SERVERS; i++) {
+	for(i = 0; i < MAX_SERVERS && i < servers_connected; i++) {
 		if (server_fd[i] >= 0) {// if char-server is online
 //			printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
 			if (server_freezeflag[i]-- < 1) {// Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
@@ -77,21 +77,21 @@ void send_account_reg(int fd) {
 
 		sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id);
 		sql_query(tmpsql,"send_account_reg");
-		sql_res = mysql_store_result(&mysql_handle) ;
 		
-        if (sql_res) {
-			sql_row = mysql_fetch_row(sql_res);
-			connect_until_time = atol(sql_row[1]);
-			strcpy(email, sql_row[0]);
+		
+        if ((sql_res = mysql_store_result(&mysql_handle))) {
+			if((sql_row = mysql_fetch_row(sql_res))) {
+			    connect_until_time = atol(sql_row[1]);
+			    strcpy(email, sql_row[0]);
+			}    
 		}
 		mysql_free_result(sql_res);
 		
 		if (account_id > 0) {
 			sprintf(tmpsql, "SELECT `str`,`value` FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d'",account_id);
 			sql_query(tmpsql,"send_account_reg");
-			sql_res = mysql_store_result(&mysql_handle) ;
 			
-            if (sql_res) {
+            if ((sql_res = mysql_store_result(&mysql_handle))) {
 				WFIFOW(fd,0) = 0x2729;
 				WFIFOL(fd,4) = account_id;
 				for(p = 8; (sql_row = mysql_fetch_row(sql_res));p+=36){
@@ -150,12 +150,12 @@ void email_time_request(int fd, int id) {
 	
 	sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id);
 	sql_query(tmpsql,"email_time_request");
-	
-	sql_res = mysql_store_result(&mysql_handle) ;
-	if (sql_res) {
-		sql_row = mysql_fetch_row(sql_res);
-		connect_until_time = atol(sql_row[1]);
-		strcpy(email, sql_row[0]);
+
+	if ((sql_res = mysql_store_result(&mysql_handle))) {
+		if((sql_row = mysql_fetch_row(sql_res))) {
+		    connect_until_time = atol(sql_row[1]);
+		    strcpy(email, sql_row[0]);
+		}    
 	}
 	mysql_free_result(sql_res);
 	
@@ -201,18 +201,18 @@ void change_account_email(int fd, int id, char ip[16]) {
 		sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc);
 		sql_query(tmpsql,"change_account_email");
 
-		sql_res = mysql_store_result(&mysql_handle);
-		if (sql_res) {
-			sql_row = mysql_fetch_row(sql_res);	//row fetching
-
-			if (strcmpi(sql_row[1], actual_email) == 0) {
-				sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc);
-				sql_query(tmpsql,"change_account_email");
-				#ifdef DEBUG
-				printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE,
- 				       server[id].name, acc, sql_row[0], actual_email, ip);
-                #endif
-			}
+		if ((sql_res = mysql_store_result(&mysql_handle))) {
+			if((sql_row = mysql_fetch_row(sql_res))) {	//row fetching
+			    if (strcmpi(sql_row[1], actual_email) == 0) {
+				    sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc);
+				    sql_query(tmpsql,"change_account_email");
+				    
+                    #ifdef DEBUG
+                    printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE,
+                            server[id].name, acc, sql_row[0], actual_email, ip);
+                    #endif
+                }
+            }    
 		}
 				
     }
@@ -229,18 +229,17 @@ void status_change_request(int fd) {
 	sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc);
 	sql_query(tmpsql,"status_change_request");
 	
-	sql_res = mysql_store_result(&mysql_handle);
-	if (sql_res) {
-		sql_row = mysql_fetch_row(sql_res); // row fetching
-
-		if (atoi(sql_row[0]) != status && status != 0) {
-			unsigned char buf[16];
-			WBUFW(buf,0) = 0x2731;
-			WBUFL(buf,2) = acc;
-			WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
-			WBUFL(buf,7) = status; // status or final date of a banishment
-			charif_sendallwos(-1, buf, 11);
-		}
+	if ((sql_res = mysql_store_result(&mysql_handle))) {
+		if((sql_row = mysql_fetch_row(sql_res))) { // row fetching
+		    if (atoi(sql_row[0]) != status && status != 0) {
+		        unsigned char buf[16];
+		        WBUFW(buf,0) = 0x2731;
+		        WBUFL(buf,2) = acc;
+		        WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
+		        WBUFL(buf,7) = status; // status or final date of a banishment
+		        charif_sendallwos(-1, buf, 11);
+            }
+        }    
 			
 		sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, status,login_db_account_id,acc);
 		sql_query(tmpsql,"status_change_request");
@@ -259,10 +258,7 @@ void ban_request(int fd) {
 	sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
 	sql_query(tmpsql,"ban_request");
 	
-	sql_res = mysql_store_result(&mysql_handle);
-	if (sql_res) {
-		sql_row = mysql_fetch_row(sql_res); // row fetching
-
+	if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) {
 		tmptime = atol(sql_row[0]);
 
 		if (tmptime == 0 || tmptime < time(NULL))
@@ -315,11 +311,7 @@ void change_sex(int fd) {
 	sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
     sql_query(tmpsql,"change_sex");
         
-    sql_res = mysql_store_result(&mysql_handle) ;
-        
-    if (sql_res) {
-		sql_row = mysql_fetch_row(sql_res);	//row fetching
-	
+    if ((sql_res = mysql_store_result(&mysql_handle)) && (sql_row = mysql_fetch_row(sql_res))) {
         if (strcmpi(sql_row[0], "M") == 0)
             sex = 1;
         else
@@ -351,10 +343,7 @@ void save_account_reg(int fd){
 			memcpy(str,RFIFOP(fd,p),32);
 			value=RFIFOL(fd,p+32);
 			
-            sprintf(tmpsql,"DELETE FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d' AND `str`='%s';",acc,jstrescapecpy(temp_str,str));
-			sql_query(tmpsql,"save_account_reg");
-			
-            sprintf(tmpsql,"INSERT INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');",  acc, jstrescapecpy(temp_str,str), value);
+            sprintf(tmpsql,"REPLACE INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');",  acc, jstrescapecpy(temp_str,str), value);
 			sql_query(tmpsql,"save_account_reg");
 		}
 
@@ -377,19 +366,8 @@ void save_account_reg(int fd){
 void unban_request(int fd) {
 	int acc = RFIFOL(fd,2);
 				
-    sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
+    sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d' AND `state`='6'", login_db,login_db_account_id,acc);
     sql_query(tmpsql,"unban_request");
-    
-    sql_res = mysql_store_result(&mysql_handle) ;
-
-    if (sql_res) {
-        sql_row = mysql_fetch_row(sql_res);	//row fetching
-
-        if (atol(sql_row[0]) != 0) {
-            sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc);
-            sql_query(tmpsql,"unban_request");
-		}
-	}
 
 	RFIFOSKIP(fd,6);
 }
@@ -405,7 +383,7 @@ int parse_fromchar(int fd){
 
 	sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
 
-	for(id = 0; id < MAX_SERVERS; id++)
+	for(id = 0; id < MAX_SERVERS && id < servers_connected; id++)
 		if (server_fd[id] == fd)
 			break;
 
@@ -417,6 +395,7 @@ int parse_fromchar(int fd){
 			printf("Char-server '%s' has disconnected.\n", server[id].name);
 			server_fd[id] = -1;
 			memset(&server[id], 0, sizeof(struct mmo_char_server));
+			servers_connected--;
 			// server delete
 			sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id);
     		sql_query(tmpsql,"parse_fromchar");

+ 92 - 122
src/login_sql/login.c

@@ -54,6 +54,7 @@ int subnetmaski[4];
 // Char-server data
 struct mmo_char_server server[MAX_SERVERS];
 int server_fd[MAX_SERVERS];
+unsigned char servers_connected = 0;
 
 // Anti-freeze Data
 int server_freezeflag[MAX_SERVERS];
@@ -115,6 +116,9 @@ int console = 0;
 // Online User DB
 struct dbt *online_db;
 
+// GM Database
+struct dbt *gm_db;
+
 //-----------------------------------------------------
 // Online User Database [Wizputer]
 //-----------------------------------------------------
@@ -136,7 +140,10 @@ int is_user_online(int account_id) {
 	p = numdb_search(online_db, account_id);
 	if (p == NULL)
 		return 0;
-	printf("Acccount %d\n",*p);
+	
+	#ifdef DEBUG
+	printf("Acccount [%d] Online\n",*p);
+	#endif
 	return 1;
 }
 
@@ -168,32 +175,39 @@ void sql_query(char* query,char function[32]) {
 }
 
 //-----------------------------------------------------
-// check user level
+// check user level [Wizputer]
 //-----------------------------------------------------
 
-int isGM(int account_id) {
-	int level=0;
-
-	sprintf(tmpsql,"SELECT `%s` FROM `%s` WHERE `%s`='%d'", login_db_level, login_db, login_db_account_id, account_id);
-	sql_query(tmpsql,"isGM");
-	sql_res = mysql_store_result(&mysql_handle);
-	if (sql_res) {
-		sql_row = mysql_fetch_row(sql_res);
-		level = atoi(sql_row[0]);
-		if (level > 99)
-			level = 99;
-	}
-
-	if (level == 0) {
+unsigned char isGM(int account_id) {
+    unsigned char *level;
+    
+   	level = numdb_search(gm_db, account_id);
+	if (level == NULL)
 		return 0;
-		//not GM
-	}
 
-	mysql_free_result(sql_res);
-
-	return level;
+	return *level;
 }
 
+void read_GMs(void) {
+    unsigned char *level;
+    level = malloc(sizeof(unsigned char));
+    
+    sprintf(tmpsql,"SELECT `%s`,`%s` FROM `%s` WHERE `%s` > 0", login_db_account_id, login_db_level, login_db,login_db_level);
+    sql_query(tmpsql,"read_GMs");
+    
+    if ((sql_res = mysql_store_result(&mysql_handle))) {
+        while((sql_row = mysql_fetch_row(sql_res))) {
+            if( (*level = atoi(sql_row[1])) > 99 )
+                *level = 99;
+
+            numdb_insert(gm_db, atoi(sql_row[0]), level);
+        }
+    }
+    
+    mysql_free_result(sql_res);
+}    
+    
+
 //---------------------------------------------------
 // E-mail check: return 0 (not correct) or 1 (valid).
 //---------------------------------------------------
@@ -257,8 +271,12 @@ int mmo_auth_sqldb_init(void) {
 	} else {
 		printf("Connected to MySQL Server\n");
 	}
+	
+	//delete all server status
+	sprintf(tmpsql,"TRUNCATE TABLE `sstatus`");
+	sql_query(tmpsql,"mmo_db_close");
 
-	sprintf(tmpsql, "INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver', '100','login server started')", loginlog_db);
+	sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver', '100','login server started')", loginlog_db);
 	sql_query(tmpsql,"mmo_auth_sqldb_init");
 
 	return 0;
@@ -271,11 +289,11 @@ void mmo_db_close(void) {
 	int i, fd;
 
 	//set log.
-	sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver','100', 'login server shutdown')", loginlog_db);
+	sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver','100', 'login server shutdown')", loginlog_db);
 	sql_query(tmpsql,"mmo_db_close");
 
 	//delete all server status
-	sprintf(tmpsql,"DELETE FROM `sstatus`");
+	sprintf(tmpsql,"TRUNCATE TABLE `sstatus`");
 	sql_query(tmpsql,"mmo_db_close");
 
 	mysql_close(&mysql_handle);
@@ -344,36 +362,53 @@ int mmo_auth( struct mmo_account* account , int fd){
 		#endif
 		return 0;
 	}
-	// Documented by CLOWNISIUS || LLRO || Gunstar lead this one with me
-	// IF changed to diferent returns~ you get diferent responses from your msgstringtable.txt
-	//Ireturn 2  == line 9
-	//Ireturn 5  == line 311
-	//Ireturn 6  == line 450
-	//Ireturn 7  == line 440
-	//Ireturn 8  == line 682
-	//Ireturn 9  == line 704
-	//Ireturn 10 == line 705
-	//Ireturn 11 == line 706
-	//Ireturn 12 == line 707
-	//Ireturn 13 == line 708
-	//Ireturn 14 == line 709
-	//Ireturn 15 == line 710
-	//Ireturn -1 == line 010
-	// Check status
 
 	account->ban_until_time = atol(sql_row[8]);
 	state = atoi(sql_row[9]);
 
-	if (state == -3) {
-		//id is banned
-		mysql_free_result(sql_res);
-		return -3;
-	} else if (state == -2) { //dynamic ban
-		//id is banned
-		mysql_free_result(sql_res);
-		//add IP list.
-		return -2;
+	if (state) {
+		switch(state) { // packet 0x006a value + 1
+		case 1:   // 0 = Unregistered ID
+		case 2:   // 1 = Incorrect Password
+		case 3:   // 2 = This ID is expired
+		case 4:   // 3 = Rejected from Server
+		case 5:   // 4 = You have been blocked by the GM Team
+		case 6:   // 5 = Your Game's EXE file is not the latest version
+		case 8:   // 7 = Server is jammed due to over populated
+		case 9:   // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
+		case 100: // 99 = This ID has been totally erased
+		    #ifdef DEBUG
+			printf("Auth Error #%d\n", state);
+			#endif
+			mysql_free_result(sql_res);
+			return state;
+			break;
+		case 7:   // 6 = Your are Prohibited to log in until %s
+		    strftime(tmpstr, 20, date_format, localtime(&account->ban_until_time));
+		    tmpstr[19] = '\0';
+		    if (account->ban_until_time > time(NULL)) { // always banned
+		        mysql_free_result(sql_res);  
+		        return 7;
+            } else { // ban is finished
+			    // reset the ban time
+			    sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0',`state`='0' WHERE BINARY `%s`='%s'", login_db, login_db_userid, t_uid);
+			    sql_query(tmpsql,"mmo_auth");
+		    }
+		    break;
+		default:
+			return 100; // 99 = ID has been totally erased
+			break;
+		}
 	}
+	
+	if (atol(sql_row[6]) != 0 && atol(sql_row[6]) < time(NULL)) {
+		return 2; // 2 = This ID is expired
+	}
+
+    if ( is_user_online(atol(sql_row[0])) ) {
+        printf("User [%s] is already online - Rejected.\n",sql_row[1]);
+	    return 3; // Rejected
+    }
 
 	if (use_md5_passwds) {
 		MD5_String(account->passwd,user_password);
@@ -448,85 +483,13 @@ int mmo_auth( struct mmo_account* account , int fd){
 			#endif
 #endif
 		}
-		return 1;
+		return 2;
 	}
 
 	#ifdef DEBUG
 	printf("Auth ok: Time: [%s] Username: [%s]\n" RETCODE, tmpstr, account->userid);
 	#endif
 
-	if (state) {
-		switch(state) { // packet 0x006a value + 1
-		case 1:   // 0 = Unregistered ID
-		case 2:   // 1 = Incorrect Password
-		case 3:   // 2 = This ID is expired
-		case 4:   // 3 = Rejected from Server
-		case 5:   // 4 = You have been blocked by the GM Team
-		case 6:   // 5 = Your Game's EXE file is not the latest version
-		case 8:   // 7 = Server is jammed due to over populated
-		case 9:   // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
-		case 100: // 99 = This ID has been totally erased
-			printf("Auth Error #%d\n", state);
-			return state;
-			break;
-		case 7:   // 6 = Your are Prohibited to log in until %s
-		    strftime(tmpstr, 20, date_format, localtime(&account->ban_until_time));
-		    tmpstr[19] = '\0';
-		    if (account->ban_until_time > time(NULL)) { // always banned
-		        return 7;
-            } else { // ban is finished
-			    // reset the ban time
-			    sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0',`state`='0' WHERE BINARY `%s`='%s'", login_db, login_db_userid, t_uid);
-			    sql_query(tmpsql,"mmo_auth");
-		    }
-		    break;
-		default:
-			return 100; // 99 = ID has been totally erased
-			break;
-		}
-	}
-
-/*
-// do not remove this section. this is meant for future, and current forums usage
-// as a login manager and CP for login server. [CLOWNISIUS]
-	if (atoi(sql_row[10]) == 1) {
-		return 4;
-	}
-
-	if (atoi(sql_row[10]) >= 5) {
-		switch(atoi(sql_row[10])) {
-		case 5:
-			return 5;
-			break;
-		case 6:
-			return 7;
-			break;
-		case 7:
-			return 9;
-			break;
-		case 8:
-			return 10;
-			break;
-		case 9:
-			return 11;
-			break;
-		default:
-			return 10;
-			break;
-		}
-	}
-*/
-
-
-	if (atol(sql_row[6]) != 0 && atol(sql_row[6]) < time(NULL)) {
-		return 2; // 2 = This ID is expired
-	}
-
-    if ( is_user_online(atol(sql_row[0])) ) {
-        printf("User [%s] is already online - Rejected.\n",sql_row[1]);
-	    return 3; // Rejected
-    }
-        
 	account->account_id = atoi(sql_row[0]);
 	account->login_id1 = rand();
 	account->login_id2 = rand();
@@ -968,6 +931,13 @@ int do_init(int argc,char **argv){
     free(online_db);
 	online_db = numdb_init();
 	
+	// GM database init
+    free(gm_db);
+	gm_db = numdb_init();
+	
+	// Read GMs from table
+	read_GMs();
+	
 	printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port);
 
 	return 0;

+ 2 - 1
src/login_sql/login.h

@@ -114,6 +114,7 @@ extern int subnetmaski[4];
 // Char-server data
 extern struct mmo_char_server server[MAX_SERVERS];
 extern int server_fd[MAX_SERVERS];
+extern unsigned char servers_connected;
 
 // Anti-freeze Data
 extern int server_freezeflag[MAX_SERVERS];
@@ -150,7 +151,7 @@ void add_online_user(int);
 int is_user_online(int);
 void remove_online_user(int);
 int mmo_auth( struct mmo_account*, int);
-int isGM(int);
+unsigned char isGM(int);
 int lan_ip_check(unsigned char *);
 
 

+ 36 - 90
src/login_sql/login_int.c

@@ -31,14 +31,14 @@ void client_request_login(int fd,unsigned char *p ) {
 
 	jstrescapecpy(t_uid,RFIFOP(fd, 6));
 	if(result==-1){
-	    int gm_level = isGM(account.account_id);
-        if (min_level_to_connect > gm_level) {
+	    unsigned char gm_level = isGM(account.account_id);
+        if (min_level_to_connect > gm_level || !servers_connected) {
 			WFIFOW(fd,0) = 0x81;
 			WFIFOL(fd,2) = 1; // 01 = Server closed
 			WFIFOSET(fd,3);
 	    } else {
             if (p[0] != 127) {
-                sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid);
+                sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid);
                 sql_query(tmpsql,"client_request_login");
             }
 
@@ -52,12 +52,12 @@ void client_request_login(int fd,unsigned char *p ) {
 				#endif
 			}
    			
-            for(i = 0; i < MAX_SERVERS; i++) {
-				if (server_fd[i] >= 0) {
-					//Lan check added by Kashy
-					if (lan_ip_check(p))
-						WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip);
-					else
+		    for(i = 0; i < MAX_SERVERS || server_num < servers_connected ; i++)
+		        if (server_fd[i] >= 0) {
+		            //Lan check added by Kashy
+		            if (lan_ip_check(p))
+					    WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip);
+	                else
                         WFIFOL(fd,47+server_num*32) = server[i].ip;
 
                     WFIFOW(fd,47+server_num*32+4) = server[i].port;
@@ -66,11 +66,8 @@ void client_request_login(int fd,unsigned char *p ) {
                     WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
                     WFIFOW(fd,47+server_num*32+30) = server[i].new;
                     server_num++;
-                }
-            }
+                }   
             
-            // if at least 1 char-server
-            if (server_num > 0) {
                 WFIFOW(fd,0)=0x69;
                 WFIFOW(fd,2)=47+32*server_num;
                 WFIFOL(fd,4)=account.login_id1;
@@ -91,74 +88,26 @@ void client_request_login(int fd,unsigned char *p ) {
                 auth_fifo[auth_fifo_pos].delflag=0;
                 auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
                 auth_fifo_pos++;
-            } else {
-                WFIFOW(fd,0) = 0x81;
-                WFIFOL(fd,2) = 1; // 01 = Server closed
-                WFIFOSET(fd,3);
-            }
         }
     } else {
-		char error[64];
-		char tmp_sql[65535];
+		char error[32];
 		
-        sprintf(tmp_sql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %%s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result);
-		switch((result)) {
-		
-        case -3:  //-3 = Account Banned
-			sprintf(tmpsql,tmp_sql,"Account banned.");
-			sprintf(error,"Account banned.");
-		break;
-		case -2:  //-2 = Dynamic Ban
-			sprintf(tmpsql,tmp_sql,"dynamic ban (ip and account).");
-			sprintf(error,"dynamic ban (ip and account).");
-		break;
-		case 1:   // 0 = Unregistered ID
-			sprintf(tmpsql,tmp_sql,"Unregisterd ID.");
-			sprintf(error,"Unregisterd ID.");
-		break;
-		case 2:   // 1 = Incorrect Password
-			sprintf(tmpsql,tmp_sql,"Incorrect Password.");
-			sprintf(error,"Incorrect Password.");
-		break;
-		case 3:   // 2 = This ID is expired
-			sprintf(tmpsql,tmp_sql,"Account Expired.");
-			sprintf(error,"Account Expired.");
-		break;
-		case 4:   // 3 = Rejected from Server
-			sprintf(tmpsql,tmp_sql,"Rejected from server.");
-			sprintf(error,"Rejected from server.");
-		break;
-		case 5:   // 4 = You have been blocked by the GM Team
-			sprintf(tmpsql,tmp_sql,"Blocked by GM.");
-			sprintf(error,"Blocked by GM.");
-		break;
-		case 6:   // 5 = Your Game's EXE file is not the latest version
-			sprintf(tmpsql,tmp_sql,"Not latest game EXE.");
-			sprintf(error,"Not latest game EXE.");
-		break;
-		case 7:   // 6 = Your are Prohibited to log in until %s
-			sprintf(tmpsql,tmp_sql,"Banned.");
-			sprintf(error,"Banned.");
-		break;
-		case 8:   // 7 = Server is jammed due to over populated
-			sprintf(tmpsql,tmp_sql,"Server Over-population.");
-			sprintf(error,"Server Over-population.");
-		break;
-		case 9:   // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
-			sprintf(tmpsql,tmp_sql," ");
-			sprintf(error," ");
-		break;
-		case 100: // 99 = This ID has been totally erased
-			sprintf(tmpsql,tmp_sql,"Account gone.");
-			sprintf(error,"Account gone.");
-		break;
-		default:
-			sprintf(tmpsql,tmp_sql,"Uknown Error.");
-			sprintf(error,"Uknown Error.");
-		break;
-		}
-
+		sprintf(tmpsql,"SELECT `error` FROM `errors` WHERE `result`='%d'",result);
 		sql_query(tmpsql,"client_request_login");
+		
+		if ((sql_res = mysql_store_result(&mysql_handle))) {
+                if ((sql_row = mysql_fetch_row(sql_res))) {
+                    sprintf(error,sql_row[0]);
+                } else {
+                    sprintf(error,"No Error!");
+                }
+        }        
+		
+        
+        sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result, error);
+        
+        		
+        sql_query(tmpsql,"client_request_login");
 
 		if ((result == 1) && (dynamic_pass_failure_ban != 0)){	// failed password
 			sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%d.%d.%d.%d' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
@@ -177,12 +126,8 @@ void client_request_login(int fd,unsigned char *p ) {
 			
 			mysql_free_result(sql_res);
 			
-		} else if (result == -2) {	//dynamic banned - add ip to ban list.
-			sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() +  INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid);
-			sql_query(tmpsql,"client_request_login");
-			result = -3;
 		}
-
+		
 		//cannot connect login failed
 		memset(WFIFOP(fd,0),'\0',23);
 		WFIFOW(fd,0)=0x6a;
@@ -226,7 +171,7 @@ void char_request_login(int fd, unsigned char *p) {
    	char t_uid[32];  
 	int result;
 	
-	sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58));
+	sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58));
 	sql_query(tmpsql,"char_request_login");
 	
 	#ifdef DEBUG
@@ -261,12 +206,9 @@ void char_request_login(int fd, unsigned char *p) {
 		if(anti_freeze_enable)
 			server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
 
-		sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%ld'", account.account_id);
-		sql_query(tmpsql,"char_request_login");
-
 		jstrescapecpy(t_uid,server[account.account_id].name);
 		
-		sprintf(tmpsql,"INSERT DELAYED INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')",
+		sprintf(tmpsql,"REPLACE DELAYED INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')",
 				account.account_id, server[account.account_id].name,0);
 		sql_query(tmpsql,"char_request_login");
 		
@@ -275,6 +217,8 @@ void char_request_login(int fd, unsigned char *p) {
 		WFIFOSET(fd,3);
 		session[fd]->func_parse=parse_fromchar;
 		realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);
+		
+		servers_connected++;
 	} else {
 		WFIFOW(fd, 0) =0x2711;
 		WFIFOB(fd, 2)=3;
@@ -328,7 +272,7 @@ int parse_login(int fd) {
                     // ip ban ok.
                     printf ("packet from banned ip : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]);
                 
-                    sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]);
+                    sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]);
                     sql_query(tmpsql,"parse_login");
                 
                     #ifdef DEBUG
@@ -350,9 +294,11 @@ int parse_login(int fd) {
     
 	if (session[fd]->eof) {
 	    int i;
-		for(i = 0; i < MAX_SERVERS; i++)
-			if (server_fd[i] == fd)
+		for(i = 0; i < MAX_SERVERS && i < servers_connected; i++)
+			if (server_fd[i] == fd) {
 				server_fd[i] = -1;
+				servers_connected--;
+			}			
 		close(fd);
 		delete_session(fd);
 		return 0;