Pārlūkot izejas kodu

* TXT/SQL login server code synchronization
- exported several core structures to login.h
- split off ladmin communication code from the TXT login server
- removed all occurences of login_log(); a unified function should be added when SQL's loginlog_db logging code gets synced with TXT
- removed conf setting login_log_filename
- fixed ladmin getting timeouts since the ping system was changed
- removed login/char server_fd[] arrays, added server[].fd instead

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11826 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 gadi atpakaļ
vecāks
revīzija
ea5212c5a8

+ 8 - 0
Changelog-Trunk.txt

@@ -4,6 +4,14 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2007/11/27
+	* removed login/char server_fd[] arrays, added server[].fd instead
+	* TXT/SQL login server code synchronization [ultramage]
+	- exported several core structures to login.h
+	- split off ladmin communication code from the TXT login server
+	- removed all occurences of login_log(); a unified function should be
+	  added when SQL's loginlog_db logging code gets synced with TXT
+	- removed conf setting login_log_filename
+	- fixed ladmin getting timeouts since the ping system was changed
 	* Moved basic max HP/SP calculation to before parsing equipment, fixes
 	  negative absolute HP/SP bonuses not working.
 	* Corrected the online_data_cleanup routine setting offline characters that

+ 2 - 5
conf/login_athena.conf

@@ -34,8 +34,8 @@ stdout_with_ansisequence: no
 //Example: "console_silent: 7" Hides information, status and notice messages (1+2+4)
 console_silent: 0
 
-// Whether remote administration is enabled or disabled (1 for enabled, 0 for disabled)
-admin_state: 0
+// Whether remote administration is enabled or disabled
+admin_state: no
 
 // Administrative password, used by ladmin (perl software) to connect remotely to server.
 // NOTICE: If you enable remote administration, you should change its value for security
@@ -88,9 +88,6 @@ gm_account_filename: conf/GM_account.txt
 // (in seconds; default: 15; value: 0 (disabled), or 2 or more)
 gm_account_filename_check_timer: 15
 
-// Log Filename. All operations received by the server are logged in this file.
-login_log_filename: log/login.log
-
 // To log the login server?
 // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans.
 log_login: yes

+ 27 - 35
src/char/char.c

@@ -57,12 +57,12 @@ int save_log = 1;	// show loading/saving messages
 char db_path[1024] = "db";
 
 struct mmo_map_server {
+	int fd;
 	uint32 ip;
 	uint16 port;
 	int users;
 	unsigned short map[MAX_MAP_PER_SERVER];
 } server[MAX_MAP_SERVERS];
-int server_fd[MAX_MAP_SERVERS];
 
 int login_fd, char_fd;
 char userid[24];
@@ -290,7 +290,7 @@ int search_character_online(int aid, int cid)
 	if(character &&
 		character->char_id == cid &&
 		character->server > -1) 
-		return server_fd[character->server];
+		return server[character->server].fd;
 	return -1;
 }
 static void * create_online_char_data(DBKey key, va_list args)
@@ -335,7 +335,7 @@ void set_char_online(int map_id, int char_id, int account_id)
 		if (char_id != 99)
 			ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n",
 				character->account_id, character->char_id, character->server, map_id, account_id, char_id);
-		mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 	}
 
 	character->char_id = (char_id==99)?-1:char_id;
@@ -402,15 +402,14 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap)
 static int char_db_kickoffline(DBKey key, void* data, va_list ap)
 {
 	struct online_char_data* character = (struct online_char_data*)data;
-	int server = va_arg(ap, int);
+	int server_id = va_arg(ap, int);
 
-	if (server > -1 && character->server != server)
+	if (server_id > -1 && character->server != server_id)
 		return 0;
 
 	//Kick out any connected characters, and set them offline as appropiate.
 	if (character->server > -1)
-		mapif_disconnectplayer(server_fd[character->server],
-			character->account_id, character->char_id, 1);
+		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
 	else if (character->waiting_disconnect == -1)
 		set_char_offline(character->char_id, character->account_id);
 	else return 0;
@@ -1375,7 +1374,7 @@ static int create_online_files_sub(DBKey key, void* data, va_list va)
 	}
 	
 	j = character->server;
-	if (server_fd[j] < 0) {
+	if (server[j].fd < 0) {
 		server[j].users = 0;
 		return -1;
 	}
@@ -1670,7 +1669,7 @@ int count_users(void)
 
 	users = 0;
 	for(i = 0; i < MAX_MAP_SERVERS; i++)
-		if (server_fd[i] >= 0)
+		if (server[i].fd >= 0)
 			users += server[i].users;
 
 	return users;
@@ -1915,7 +1914,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 	{	// check if character is not online already. [Skotlex]
 		if (character->server > -1)
 		{	//Character already online. KICK KICK KICK
-			mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+			mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 			if (character->waiting_disconnect == -1)
 				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
@@ -1991,7 +1990,7 @@ int parse_fromlogin(int fd)
 				send_accounts_tologin(-1, gettick(), 0, 0);
 
 				// if no map-server already connected, display a message...
-				ARR_FIND( 0, MAX_MAP_SERVERS, i, server_fd[i] > 0 && server[i].map[0] );
+				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
 				if( i == MAX_MAP_SERVERS )
 					ShowStatus("Awaiting maps from map-server.\n");
 			}
@@ -2150,9 +2149,7 @@ int parse_fromlogin(int fd)
 			else
 			{
 				// at least 1 map-server
-				for(i = 0; i < MAX_MAP_SERVERS; i++)
-					if (server_fd[i] >= 0)
-						break;
+				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd >= 0 );
 				if (i == MAX_MAP_SERVERS)
 					char_log("'ladmin': Receiving a message for broadcast, but no map-server is online.\n");
 				else {
@@ -2328,7 +2325,7 @@ int parse_fromlogin(int fd)
 			{	//Kick out this player.
 				if (character->server > -1)
 				{	//Kick it from the map server it is on.
-					mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 					if (character->waiting_disconnect == -1)
 						character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
 				} else { //Manual kick from char server.
@@ -2605,9 +2602,7 @@ int parse_frommap(int fd)
 	int i, j;
 	int id;
 
-	for(id = 0; id < MAX_MAP_SERVERS; id++)
-		if (server_fd[id] == fd)
-			break;
+	ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
 	if(id == MAX_MAP_SERVERS)
 		set_eof(fd);
 	if(session[fd]->eof) {
@@ -2626,7 +2621,7 @@ int parse_frommap(int fd)
 				WBUFW(buf,2) = j * 4 + 10;
 				mapif_sendallwos(fd, buf, WBUFW(buf,2));
 			}
-			server_fd[id] = -1;
+			server[id].fd = -1;
 			online_char_db->foreach(online_char_db,char_db_setoffline,i); //Tag relevant chars as 'in disconnected' server.
 		}
 		do_close(fd);
@@ -2696,7 +2691,7 @@ int parse_frommap(int fd)
 			}
 			// Transmitting the maps of the other map-servers to the new map-server
 			for(x = 0; x < MAX_MAP_SERVERS; x++) {
-				if (server_fd[x] > 0 && x != id) {
+				if (server[x].fd > 0 && x != id) {
 					WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
 					WFIFOW(fd,0) = 0x2b04;
 					WFIFOL(fd,4) = htonl(server[x].ip);
@@ -2768,7 +2763,7 @@ int parse_frommap(int fd)
 				{
 					ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
 						character->account_id, character->char_id, character->server, id, aid, cid);
-					mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 				}
 				character->char_id = cid;
 				character->server = id;
@@ -2833,7 +2828,7 @@ int parse_frommap(int fd)
 			name = RFIFOW(fd,18);
 			map_id = search_mapserver(name, ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
 			if (map_id >= 0)
-				map_fd = server_fd[map_id];
+				map_fd = server[map_id].fd;
 			for(i = 0; i < char_num; i++) {
 			if (char_dat[i].status.account_id == RFIFOL(fd,2) &&
 			    char_dat[i].status.char_id == RFIFOL(fd,14))
@@ -3180,7 +3175,7 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port)
 	
 	for(i = 0; i < MAX_MAP_SERVERS; i++)
 	{
-		if (server_fd[i] > 0
+		if (server[i].fd > 0
 		&& (ip == (uint32)-1 || server[i].ip == ip)
 		&& (port == (uint16)-1 || server[i].port == port))
 		{
@@ -3355,7 +3350,7 @@ int parse_char(int fd)
 			if (i < 0) {
 				unsigned short j;
 				//First check that there's actually a map server online.
-				ARR_FIND( 0, MAX_MAP_SERVERS, j, server_fd[j] >= 0 && server[j].map[0] );
+				ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] );
 				if (j == MAX_MAP_SERVERS) {
 					ShowInfo("Connection Closed. No map servers available.\n");
 					WFIFOHEAD(fd,3);
@@ -3421,10 +3416,10 @@ int parse_char(int fd)
 			auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
 
 			//Send NEW auth packet [Kevin]
-			if ((map_fd = server_fd[i]) < 1 || session[map_fd] == NULL)
+			if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
 			{
 				ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
-				server_fd[i] = -1;
+				server[i].fd = -1;
 				memset(&server[i], 0, sizeof(struct mmo_map_server));
 				//Send server closed.
 				WFIFOHEAD(fd,3);
@@ -3626,10 +3621,7 @@ int parse_char(int fd)
 			char* l_pass = RFIFOP(fd,26);
 			l_user[23] = '\0';
 			l_pass[23] = '\0';
-			for(i = 0; i < MAX_MAP_SERVERS; i++) {
-				if (server_fd[i] <= 0)
-					break;
-			}
+			ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
 			if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2af9;
@@ -3641,7 +3633,7 @@ int parse_char(int fd)
 				WFIFOB(fd,2) = 0;
 				WFIFOSET(fd,3);
 
-				server_fd[i] = fd;
+				server[i].fd = fd;
 				server[i].ip = ntohl(RFIFOL(fd,54));
 				server[i].port = ntohs(RFIFOW(fd,58));
 				server[i].users = 0;
@@ -3736,7 +3728,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
 	c = 0;
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		int fd;
-		if ((fd = server_fd[i]) > 0) {
+		if ((fd = server[i].fd) > 0) {
 			WFIFOHEAD(fd,len);
 			memcpy(WFIFOP(fd,0), buf, len);
 			WFIFOSET(fd,len);
@@ -3755,7 +3747,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
 	c = 0;
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		int fd;
-		if ((fd = server_fd[i]) > 0 && fd != sfd) {
+		if ((fd = server[i].fd) > 0 && fd != sfd) {
 			WFIFOHEAD(fd,len);
 			memcpy(WFIFOP(fd,0), buf, len);
 			WFIFOSET(fd,len);
@@ -3772,7 +3764,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
 
 	if (fd >= 0) {
 		for(i = 0; i < MAX_MAP_SERVERS; i++) {
-			if (fd == server_fd[i]) {
+			if (fd == server[i].fd) {
 				WFIFOHEAD(fd,len);
 				memcpy(WFIFOP(fd,0), buf, len);
 				WFIFOSET(fd,len);
@@ -4229,7 +4221,7 @@ int do_init(int argc, char **argv)
 
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		memset(&server[i], 0, sizeof(struct mmo_map_server));
-		server_fd[i] = -1;
+		server[i].fd = -1;
 	}
 
 	//Read map indexes

+ 1 - 1
src/char/int_homun.c

@@ -103,7 +103,7 @@ int inter_homun_fromstr(char *str,struct s_homunculus *p)
 			p->hskill[i].id = tmp_int[0];
 			p->hskill[i].lv = tmp_int[1];
 		} else
-			ShowError("Read Homun: Unsupported Skill ID %d for homunculus (Homun ID=%d\n)", tmp_int[0], p->hom_id);
+			ShowError("Read Homun: Unsupported Skill ID %d for homunculus (Homun ID=%d)\n", tmp_int[0], p->hom_id);
 		next += len;
 		if (str[next] == ' ')
 			next++;

+ 25 - 31
src/char_sql/char.c

@@ -77,12 +77,12 @@ char login_db_level[32] = "level";
 int lowest_gm_level = 1;
 
 struct mmo_map_server {
+	int fd;
 	uint32 ip;
 	uint16 port;
 	int users;
 	unsigned short map[MAX_MAP_PER_SERVER];
 } server[MAX_MAP_SERVERS];
-int server_fd[MAX_MAP_SERVERS];
 
 int login_fd, char_fd;
 char userid[24];
@@ -239,7 +239,7 @@ void set_char_online(int map_id, int char_id, int account_id)
 		if (char_id != 99)
 			ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n",
 				character->account_id, character->char_id, character->server, map_id, account_id, char_id);
-		mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 	}
 
 	character->char_id = (char_id==99)?-1:char_id;
@@ -329,15 +329,14 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap)
 static int char_db_kickoffline(DBKey key, void* data, va_list ap)
 {
 	struct online_char_data* character = (struct online_char_data*)data;
-	int server = va_arg(ap, int);
+	int server_id = va_arg(ap, int);
 
-	if (server > -1 && character->server != server)
+	if (server_id > -1 && character->server != server_id)
 		return 0;
 
 	//Kick out any connected characters, and set them offline as appropiate.
 	if (character->server > -1)
-		mapif_disconnectplayer(server_fd[character->server],
-			character->account_id, character->char_id, 1);
+		mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
 	else if (character->waiting_disconnect == -1)
 		set_char_offline(character->char_id, character->account_id);
 	else return 0;
@@ -1423,7 +1422,7 @@ int count_users(void)
 	if (login_fd > 0 && session[login_fd]){
 		users = 0;
 		for(i = 0; i < MAX_MAP_SERVERS; i++) {
-			if (server_fd[i] > 0) {
+			if (server[i].fd > 0) {
 				users += server[i].users;
 			}
 		}
@@ -1584,7 +1583,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
 	{	// check if character is not online already. [Skotlex]
 		if (character->server > -1)
 		{	//Character already online. KICK KICK KICK
-			mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+			mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 			if (character->waiting_disconnect == -1)
 				character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
 			WFIFOW(fd,0) = 0x81;
@@ -1660,7 +1659,7 @@ int parse_fromlogin(int fd)
 				send_accounts_tologin(-1, gettick(), 0, 0);
 			
 				// if no map-server already connected, display a message...
-				ARR_FIND( 0, MAX_MAP_SERVERS, i, server_fd[i] > 0 && server[i].map[0] );
+				ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
 				if( i == MAX_MAP_SERVERS )
 					ShowStatus("Awaiting maps from map-server.\n");
 			}
@@ -1892,7 +1891,7 @@ int parse_fromlogin(int fd)
 			{	//Kick out this player.
 				if( character->server != -1 )
 				{	//Kick it from the map server it is on.
-					mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 					if (character->waiting_disconnect == -1)
 						character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
 				}
@@ -2124,9 +2123,7 @@ int parse_frommap(int fd)
 		return 0;
 	}
 
-	for(id = 0; id < MAX_MAP_SERVERS; id++)
-		if (server_fd[id] == fd)
-			break;
+	ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
 	if(id == MAX_MAP_SERVERS)
 		set_eof(fd);
 	if(session[fd]->eof) {
@@ -2146,9 +2143,9 @@ int parse_frommap(int fd)
 				mapif_sendallwos(fd, buf, WBUFW(buf,2));
 			}
 			memset(&server[id], 0, sizeof(struct mmo_map_server));
-			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]) )
+			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) )
 				Sql_ShowDebug(sql_handle);
-			server_fd[id] = -1;
+			server[id].fd = -1;
 			online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
 		}
 		do_close(fd);
@@ -2215,7 +2212,7 @@ int parse_frommap(int fd)
 			}
 			// Transmitting the maps of the other map-servers to the new map-server
 			for(x = 0; x < MAX_MAP_SERVERS; x++) {
-				if (server_fd[x] > 0 && x != id) {
+				if (server[x].fd > 0 && x != id) {
 					WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
 					WFIFOW(fd,0) = 0x2b04;
 					WFIFOL(fd,4) = htonl(server[x].ip);
@@ -2315,7 +2312,7 @@ int parse_frommap(int fd)
 				{
 					ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n",
 						character->account_id, character->char_id, character->server, id, aid, cid);
-					mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2);
+					mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2);
 				}
 				character->server = id;
 				character->char_id = cid;
@@ -2397,7 +2394,7 @@ int parse_frommap(int fd)
 
 			map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
 			if (map_id >= 0)
-				map_fd = server_fd[map_id];
+				map_fd = server[map_id].fd;
 			//Char should just had been saved before this packet, so this should be safe. [Skotlex]
 			char_data = uidb_get(char_db_,RFIFOL(fd,14));
 			if (char_data == NULL) 
@@ -2754,7 +2751,7 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port)
 	
 	for(i = 0; i < MAX_MAP_SERVERS; i++)
 	{
-		if (server_fd[i] > 0
+		if (server[i].fd > 0
 		&& (ip == (uint32)-1 || server[i].ip == ip)
 		&& (port == (uint16)-1 || server[i].port == port))
 		{
@@ -2930,7 +2927,7 @@ int parse_char(int fd)
 			if (i < 0) {
 				unsigned short j;
 				//First check that there's actually a map server online.
-				ARR_FIND( 0, MAX_MAP_SERVERS, j, server_fd[j] >= 0 && server[j].map[0] );
+				ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] );
 				if (j == MAX_MAP_SERVERS) {
 					ShowInfo("Connection Closed. No map servers available.\n");
 					WFIFOHEAD(fd,3);
@@ -2994,10 +2991,10 @@ int parse_char(int fd)
 			auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
 
 			//Send NEW auth packet [Kevin]
-			if ((map_fd = server_fd[i]) < 1 || session[map_fd] == NULL)
+			if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
 			{
 				ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
-				server_fd[i] = -1;
+				server[i].fd = -1;
 				memset(&server[i], 0, sizeof(struct mmo_map_server));
 				//Send server closed.
 				WFIFOHEAD(fd,3);
@@ -3174,10 +3171,7 @@ int parse_char(int fd)
 			char* l_pass = RFIFOP(fd,26);
 			l_user[23] = '\0';
 			l_pass[23] = '\0';
-			for(i = 0; i < MAX_MAP_SERVERS; i++) {
-				if (server_fd[i] <= 0)
-					break;
-			}
+			ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
 			if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2af9;
@@ -3189,7 +3183,7 @@ int parse_char(int fd)
 				WFIFOB(fd,2) = 0;
 				WFIFOSET(fd,3);
 
-				server_fd[i] = fd;
+				server[i].fd = fd;
 				server[i].ip = ntohl(RFIFOL(fd,54));
 				server[i].port = ntohs(RFIFOW(fd,58));
 				server[i].users = 0;
@@ -3284,7 +3278,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
 	c = 0;
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		int fd;
-		if ((fd = server_fd[i]) > 0) {
+		if ((fd = server[i].fd) > 0) {
 			WFIFOHEAD(fd,len);
 			memcpy(WFIFOP(fd,0), buf, len);
 			WFIFOSET(fd,len);
@@ -3302,7 +3296,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
 	c = 0;
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		int fd;
-		if ((fd = server_fd[i]) > 0 && fd != sfd) {
+		if ((fd = server[i].fd) > 0 && fd != sfd) {
 			WFIFOHEAD(fd,len);
 			memcpy(WFIFOP(fd,0), buf, len);
 			WFIFOSET(fd,len);
@@ -3318,7 +3312,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
 	int i;
 
 	if (fd >= 0) {
-		ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server_fd[i] );
+		ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd );
 		if( i < MAX_MAP_SERVERS )
 		{
 			WFIFOHEAD(fd,len);
@@ -3835,7 +3829,7 @@ int do_init(int argc, char **argv)
 
 	for(i = 0; i < MAX_MAP_SERVERS; i++) {
 		memset(&server[i], 0, sizeof(struct mmo_map_server));
-		server_fd[i] = -1;
+		server[i].fd = -1;
 	}
 
 	//Read map indexes

+ 22 - 6
src/ladmin/ladmin.c

@@ -4087,37 +4087,37 @@ int parse_fromlogin(int fd)
 					if (defaultlanguage == 'F')
 						ShowMessage(" Statut: 0 [Compte Ok]\n");
 					else
-						ShowMessage(" Statut: 0 [Account OK]\n");
+						ShowMessage(" State: 0 [Account OK]\n");
 					break;
 				case 1:
 					ShowMessage(" Statut: 1 [Unregistered ID]\n");
 					break;
 				case 2:
-					ShowMessage(" Statut: 2 [Incorrect Password]\n");
+					ShowMessage(" State: 2 [Incorrect Password]\n");
 					break;
 				case 3:
 					ShowMessage(" Statut: 3 [This ID is expired]\n");
 					break;
 				case 4:
-					ShowMessage(" Statut: 4 [Rejected from Server]\n");
+					ShowMessage(" State: 4 [Rejected from Server]\n");
 					break;
 				case 5:
 					ShowMessage(" Statut: 5 [You have been blocked by the GM Team]\n");
 					break;
 				case 6:
-					ShowMessage(" Statut: 6 [Your Game's EXE file is not the latest version]\n");
+					ShowMessage(" State: 6 [Your Game's EXE file is not the latest version]\n");
 					break;
 				case 7:
 					ShowMessage(" Statut: 7 [You are Prohibited to log in until %s]\n", error_message);
 					break;
 				case 8:
-					ShowMessage(" Statut: 8 [Server is jammed due to over populated]\n");
+					ShowMessage(" State: 8 [Server is jammed due to over populated]\n");
 					break;
 				case 9:
 					ShowMessage(" Statut: 9 [No MSG]\n");
 					break;
 				default: // 100
-					ShowMessage(" Statut: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36));
+					ShowMessage(" State: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36));
 					break;
 				}
 				if (defaultlanguage == 'F') {
@@ -4232,6 +4232,18 @@ int Connect_login_server(void)
 	return 0;
 }
 
+// sends a ping packet to login server (will receive pong 0x2718)
+int ping_login_server(int tid, unsigned int tick, int id, int data)
+{
+	if (login_fd > 0 && session[login_fd] != NULL)
+	{
+		WFIFOHEAD(login_fd,2);
+		WFIFOW(login_fd,0) = 0x2719;
+		WFIFOSET(login_fd,2);
+	}
+	return 0;
+}
+
 //-----------------------------------
 // Reading general configuration file
 //-----------------------------------
@@ -4380,6 +4392,10 @@ int do_init(int argc, char **argv)
 
 	Connect_login_server();
 
+	// keep the char-login connection alive
+	add_timer_func_list(ping_login_server, "ping_login_server");
+	add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
+
 	// minimalist core doesn't have sockets parsing,
 	// so we have to do this ourselves
 	while (runflag) {

+ 1 - 1
src/login/Makefile.in

@@ -10,7 +10,7 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h
 	../common/grfio.h ../common/mapindex.h \
 	../common/ers.h ../common/md5calc.h
 
-LOGIN_OBJ = obj/login.o
+LOGIN_OBJ = obj/login.o obj/admin.o
 LOGIN_H = login.h
 
 @SET_MAKE@

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 244 - 390
src/login/login.c


+ 61 - 1
src/login/login.h

@@ -4,7 +4,7 @@
 #ifndef _LOGIN_H_
 #define _LOGIN_H_
 
-#include "../common/mmo.h"
+#include "../common/mmo.h" // NAME_LENGTH
 
 #define LOGIN_CONF_NAME "conf/login_athena.conf"
 #define LAN_CONF_NAME "conf/subnet_athena.conf"
@@ -24,10 +24,12 @@ struct mmo_account {
 	long char_id;
 	char lastlogin[24];
 	char sex;
+	//uint8 level;
 };
 
 struct mmo_char_server {
 	char name[20];
+	int fd;
 	uint32 ip;
 	uint16 port;
 	uint16 users;		// user count on this server
@@ -35,4 +37,62 @@ struct mmo_char_server {
 	uint16 new_;		// allows creating new chars?
 };
 
+extern struct Login_Config {
+
+	uint32 login_ip;								// the address to bind to
+	uint16 login_port;								// the port to bind to
+	unsigned int ip_sync_interval;					// interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
+	bool log_login;									// whether to log login server actions or not
+	char date_format[32];							// date format used in messages
+	bool console;									// console input system enabled?
+	bool new_account_flag;							// autoregistration via _M/_F ?
+//	bool case_sensitive;							// are logins case sensitive ?
+	bool use_md5_passwds;							// work with password hashes instead of plaintext passwords?
+//	bool login_gm_read;								// should the login server handle info about gm accounts?
+	int min_level_to_connect;						// minimum level of player/GM (0: player, 1-99: GM) to connect
+	bool online_check;								// reject incoming players that are already registered as online ?
+	bool check_client_version;						// check the clientversion set in the clientinfo ?
+	int client_version_to_connect;					// the client version needed to connect (if checking is enabled)
+
+//	bool ipban;										// perform IP blocking (via contents of `ipbanlist`) ?
+//	bool dynamic_pass_failure_ban;					// automatic IP blocking due to failed login attemps ?
+//	unsigned int dynamic_pass_failure_ban_interval;	// how far to scan the loginlog for password failures
+//	unsigned int dynamic_pass_failure_ban_limit;	// number of failures needed to trigger the ipban
+//	unsigned int dynamic_pass_failure_ban_duration;	// duration of the ipban
+	bool use_dnsbl;									// dns blacklist blocking ?
+	char dnsbl_servs[1024];							// comma-separated list of dnsbl servers
+
+} login_config;
+
+// TXT-specific account database
+// holds info about all existing accounts (entire contents of account.txt)
+extern struct auth_data {
+	int account_id;
+	uint8 sex; // 0, 1, 2
+	char userid[24];
+	char pass[32+1]; // 23+1 for normal, 32+1 for md5-ed passwords
+	char lastlogin[24];
+	int logincount;
+	uint32 state; // packet 0x006a value + 1 (0: compte OK)
+	char email[40]; // e-mail (by default: a@a.com)
+	char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
+	time_t ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
+	time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+	char last_ip[16]; // save of last IP of connection
+	char memo[255]; // a memo field
+	int account_reg2_num;
+	struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
+} *auth_dat;
+
+// stores auth information of incoming clients
+// used during charserver auth validation process
+#define AUTH_FIFO_SIZE 256
+extern struct _auth_fifo {
+	int account_id;
+	uint32 login_id1, login_id2;
+	uint32 ip;
+	uint8 sex;
+	bool delflag;
+} auth_fifo[AUTH_FIFO_SIZE];
+
 #endif /* _LOGIN_H_ */

+ 112 - 138
src/login_sql/login.c

@@ -20,36 +20,10 @@
 #include <string.h>
 #include <sys/stat.h> // for stat/lstat/fstat
 
-struct Login_Config {
-
-	uint32 login_ip;								// the address to bind to
-	uint16 login_port;								// the port to bind to
-	unsigned int ip_sync_interval;					// interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
-	bool log_login;									// whether to log login server actions or not
-	char date_format[32];							// date format used in messages
-	bool console;									// console input system enabled?
-	bool new_account_flag;							// autoregistration via _M/_F ?
-	bool case_sensitive;							// are logins case sensitive ?
-	bool use_md5_passwds;							// work with password hashes instead of plaintext passwords?
-	bool login_gm_read;								// should the login server handle info about gm accounts?
-	int min_level_to_connect;						// minimum level of player/GM (0: player, 1-99: GM) to connect
-	bool online_check;								// reject incoming players that are already registered as online ?
-	bool check_client_version;						// check the clientversion set in the clientinfo ?
-	int client_version_to_connect;					// the client version needed to connect (if checking is enabled)
-
-	bool ipban;										// perform IP blocking (via contents of `ipbanlist`) ?
-	bool dynamic_pass_failure_ban;					// automatic IP blocking due to failed login attemps ?
-	unsigned int dynamic_pass_failure_ban_interval;	// how far to scan the loginlog for password failures
-	unsigned int dynamic_pass_failure_ban_limit;	// number of failures needed to trigger the ipban
-	unsigned int dynamic_pass_failure_ban_duration;	// duration of the ipban
-	bool use_dnsbl;									// dns blacklist blocking ?
-	char dnsbl_servs[1024];							// comma-separated list of dnsbl servers
-	
-} login_config;
+struct Login_Config login_config;
 
 int login_fd; // login server socket
 #define MAX_SERVERS 30
-int server_fd[MAX_SERVERS]; // char server sockets
 struct mmo_char_server server[MAX_SERVERS]; // char server data
 
 // Advanced subnet check [LuzZza]
@@ -98,25 +72,22 @@ struct login_session_data {
 	char md5key[20];
 };
 
-#define AUTH_FIFO_SIZE 256
-struct _auth_fifo {
-	int account_id;
-	uint32 login_id1, login_id2;
-	uint32 ip;
-	uint8 sex;
-	bool delflag;
-} auth_fifo[AUTH_FIFO_SIZE];
+// auth information of incoming clients
+struct _auth_fifo auth_fifo[AUTH_FIFO_SIZE];
 int auth_fifo_pos = 0;
 
+//-----------------------------------------------------
+// Online User Database [Wizputer]
+//-----------------------------------------------------
+
 struct online_login_data {
 	int account_id;
 	int waiting_disconnect;
 	int char_server;
 };
 
-//-----------------------------------------------------
-
 static DBMap* online_db; // int account_id -> struct online_login_data*
+static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data);
 
 static void* create_online_user(DBKey key, va_list args)
 {
@@ -128,13 +99,6 @@ static void* create_online_user(DBKey key, va_list args)
 	return p;
 }
 
-int charif_sendallwos(int sfd, uint8* buf, size_t len);
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data);
-
-//-----------------------------------------------------
-// Online User Database [Wizputer]
-//-----------------------------------------------------
-
 void add_online_user(int char_server, int account_id)
 {
 	struct online_login_data* p;
@@ -172,13 +136,26 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data
 	return 0;
 }
 
-static int sync_ip_addresses(int tid, unsigned int tick, int id, int data)
+//--------------------------------------------------------------------
+// Packet send to all char-servers, except one (wos: without our self)
+//--------------------------------------------------------------------
+int charif_sendallwos(int sfd, uint8* buf, size_t len)
 {
-	uint8 buf[2];
-	ShowInfo("IP Sync in progress...\n");
-	WBUFW(buf,0) = 0x2735;
-	charif_sendallwos(-1, buf, 2);
-	return 0;
+	int i, c;
+
+	for( i = 0, c = 0; i < MAX_SERVERS; ++i )
+	{
+		int fd = server[i].fd;
+		if( session_isValid(fd) && fd != sfd )
+		{
+			WFIFOHEAD(fd,len);
+			memcpy(WFIFOP(fd,0), buf, len);
+			WFIFOSET(fd,len);
+			++c;
+		}
+	}
+
+	return c;
 }
 
 //-----------------------------------------------------
@@ -331,7 +308,7 @@ void mmo_db_close(void)
 
 	for( i = 0; i < MAX_SERVERS; ++i )
 	{
-		fd = server_fd[i];
+		fd = server[i].fd;
 		if( session_isValid(fd) )
 		{// Clean only data related to servers we are connected to. [Skotlex]
 			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index` = '%d'", i) )
@@ -346,30 +323,18 @@ void mmo_db_close(void)
 		do_close(login_fd);
 }
 
-
-//--------------------------------------------------------------------
-// Packet send to all char-servers, except one (wos: without our self)
-//--------------------------------------------------------------------
-int charif_sendallwos(int sfd, uint8* buf, size_t len)
+//-----------------------------------------------------
+// periodic ip address synchronization
+//-----------------------------------------------------
+static int sync_ip_addresses(int tid, unsigned int tick, int id, int data)
 {
-	int i, c;
-
-	for( i = 0, c = 0; i < MAX_SERVERS; ++i )
-	{
-		int fd = server_fd[i];
-		if( session_isValid(fd) && fd != sfd )
-		{
-			WFIFOHEAD(fd,len);
-			memcpy(WFIFOP(fd,0), buf, len);
-			WFIFOSET(fd,len);
-			++c;
-		}
-	}
-
-	return c;
+	uint8 buf[2];
+	ShowInfo("IP Sync in progress...\n");
+	WBUFW(buf,0) = 0x2735;
+	charif_sendallwos(-1, buf, 2);
+	return 0;
 }
 
-
 //-----------------------------------------------------
 // encrypted/unencrypted password check
 //-----------------------------------------------------
@@ -645,7 +610,7 @@ int parse_fromchar(int fd)
 	char ip[16];
 	ip2str(ipl, ip);
 
-	ARR_FIND( 0, MAX_SERVERS, id, server_fd[id] == fd );
+	ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd );
 	if( id == MAX_SERVERS )
 	{// not a char server
 		set_eof(fd);
@@ -656,7 +621,7 @@ int parse_fromchar(int fd)
 	if( session[fd]->eof )
 	{
 		ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
-		server_fd[id] = -1;
+		server[id].fd = -1;
 		memset(&server[id], 0, sizeof(struct mmo_char_server));
 		online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
 		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index`='%d'", id) )
@@ -673,6 +638,7 @@ int parse_fromchar(int fd)
 		{
 
 		case 0x2709: // request from map-server via char-server to reload GM accounts
+			ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip);
 			if( login_config.log_login )
 			{
 				if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name) )
@@ -689,21 +655,18 @@ int parse_fromchar(int fd)
 				return 0;
 		{
 			int account_id = RFIFOL(fd,2);
-			for( i = 0; i < AUTH_FIFO_SIZE; ++i )
-			{
-				if( auth_fifo[i].account_id == RFIFOL(fd,2) &&
-				    auth_fifo[i].login_id1  == RFIFOL(fd,6) &&
-				    auth_fifo[i].login_id2  == RFIFOL(fd,10) &&
-				    auth_fifo[i].sex        == RFIFOB(fd,14) &&
-				    auth_fifo[i].ip         == ntohl(RFIFOL(fd,15)) &&
-				    !auth_fifo[i].delflag)
-				{
-					auth_fifo[i].delflag = 1;
-					break;
-				}
-			}
-
-			if( i != AUTH_FIFO_SIZE && account_id > 0 )
+			ARR_FIND( 0, AUTH_FIFO_SIZE, i, 
+				auth_fifo[i].account_id == RFIFOL(fd,2) &&
+				auth_fifo[i].login_id1  == RFIFOL(fd,6) &&
+				auth_fifo[i].login_id2  == RFIFOL(fd,10) &&
+				auth_fifo[i].sex        == RFIFOB(fd,14) &&
+				auth_fifo[i].ip         == ntohl(RFIFOL(fd,15)) &&
+				!auth_fifo[i].delflag );
+
+			if( i < AUTH_FIFO_SIZE )
+				auth_fifo[i].delflag = 1;
+
+			if( i < AUTH_FIFO_SIZE && account_id > 0 )
 			{// send ack 
 				uint32 connect_until_time;
 				char email[40];
@@ -737,7 +700,8 @@ int parse_fromchar(int fd)
 				WFIFOSET(fd,51);
 			}
 			else
-			{// authentification not found
+			{// authentication not found
+				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
 				WFIFOHEAD(fd,51);
 				WFIFOW(fd,0) = 0x2713;
 				WFIFOL(fd,2) = account_id;
@@ -752,7 +716,7 @@ int parse_fromchar(int fd)
 		break;
 
 		case 0x2714:
-			if (RFIFOREST(fd) < 6)
+			if( RFIFOREST(fd) < 6 )
 				return 0;
 
 			// how many users on world? (update)
@@ -906,9 +870,8 @@ int parse_fromchar(int fd)
 			if (RFIFOREST(fd) < 10)
 				return 0;
 		{
-			int account_id, state;
-			account_id = RFIFOL(fd,2);
-			state = RFIFOL(fd,6);
+			int account_id = RFIFOL(fd,2);
+			int state = RFIFOL(fd,6);
 			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
 				Sql_ShowDebug(sql_handle);
 			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@@ -990,7 +953,7 @@ int parse_fromchar(int fd)
 		break;
 
 		case 0x2727: // Change of sex (sex is reversed)
-			if (RFIFOREST(fd) < 6)
+			if( RFIFOREST(fd) < 6 )
 				return 0;
 		{
 			int account_id;
@@ -1099,14 +1062,14 @@ int parse_fromchar(int fd)
 		}
 
 		case 0x272b:    // Set account_id to online [Wizputer]
-			if (RFIFOREST(fd) < 6)
+			if( RFIFOREST(fd) < 6 )
 				return 0;
 			add_online_user(id, RFIFOL(fd,2));
 			RFIFOSKIP(fd,6);
 		break;
 
 		case 0x272c:   // Set account_id to offline [Wizputer]
-			if (RFIFOREST(fd) < 6)
+			if( RFIFOREST(fd) < 6 )
 				return 0;
 			remove_online_user(RFIFOL(fd,2));
 			RFIFOSKIP(fd,6);
@@ -1179,7 +1142,7 @@ int parse_fromchar(int fd)
 		break;
 
 		case 0x2736: // WAN IP update from char-server
-			if (RFIFOREST(fd) < 6)
+			if( RFIFOREST(fd) < 6 )
 				return 0;
 			server[id].ip = ntohl(RFIFOL(fd,2));
 			ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
@@ -1256,14 +1219,14 @@ int parse_login(int fd)
 	uint32 ipl = session[fd]->client_addr;
 	char ip[16];
 
-	ip2str(ipl, ip);
-
 	if( session[fd]->eof )
 	{
 		do_close(fd);
 		return 0;
 	}
 
+	ip2str(ipl, ip);
+
 	while( RFIFOREST(fd) >= 2 )
 	{
 		uint16 command = RFIFOW(fd,0);
@@ -1287,11 +1250,12 @@ int parse_login(int fd)
 		case 0x0277:		// New login packet (kRO 2006-04-24aSakexe langtype 0)
 		case 0x02b0:		// New login packet (kRO 2007-05-14aSakexe langtype 0)
 		{
-			size_t packet_len = RFIFOREST(fd);
+			size_t packet_len = RFIFOREST(fd); // assume no other packet was sent
 
 			// Perform ip-ban check
 			if( login_config.ipban && login_ip_ban_check(ipl) )
 			{
+				ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
 				WFIFOHEAD(fd,23);
 				WFIFOW(fd,0) = 0x6a;
 				WFIFOB(fd,2) = 3; // 3 = Rejected from Server
@@ -1326,6 +1290,7 @@ int parse_login(int fd)
 			{	// auth success
 				if( login_config.min_level_to_connect > account.level )
 				{
+					ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", login_config.min_level_to_connect, account.userid, account.level, ip);
 					WFIFOHEAD(fd,3);
 					WFIFOW(fd,0) = 0x81;
 					WFIFOB(fd,2) = 1; // 01 = Server closed
@@ -1333,32 +1298,24 @@ int parse_login(int fd)
 				}
 				else
 				{
-					uint8 server_num = 0;
+					uint8 server_num, n;
+					uint32 subnet_char_ip;
 
-					if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, esc_userid) )
-						Sql_ShowDebug(sql_handle);
-					if( account.level )
-						ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid);
-					else
-						ShowStatus("Connection of the account '%s' accepted.\n", account.userid);
-
-					WFIFOHEAD(fd,47+32*MAX_SERVERS);
+					server_num = 0;
 					for( i = 0; i < MAX_SERVERS; ++i )
-					{
-						if( session_isValid(server_fd[i]) )
-						{
-							// Advanced subnet check [LuzZza]
-							uint32 subnet_char_ip = lan_subnetcheck(ipl);
-							WFIFOL(fd,47+server_num*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
-							WFIFOW(fd,47+server_num*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
-							memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20);
-							WFIFOW(fd,47+server_num*32+26) = server[i].users;
-							WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
-							WFIFOW(fd,47+server_num*32+30) = server[i].new_;
+						if( session_isValid(server[i].fd) )
 							server_num++;
-						}
-					}
-					if (server_num > 0) { // if at least 1 char-server
+
+					if( server_num > 0 )
+					{// if at least 1 char-server
+						if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, esc_userid) )
+							Sql_ShowDebug(sql_handle);
+						if( account.level )
+							ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid);
+						else
+							ShowStatus("Connection of the account '%s' accepted.\n", account.userid);
+
+						WFIFOHEAD(fd,47+32*server_num);
 						WFIFOW(fd,0) = 0x69;
 						WFIFOW(fd,2) = 47+32*server_num;
 						WFIFOL(fd,4) = account.login_id1;
@@ -1366,8 +1323,24 @@ int parse_login(int fd)
 						WFIFOL(fd,12) = account.login_id2;
 						WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
 						//memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used)
+						WFIFOW(fd,44) = 0; // unknown
 						WFIFOB(fd,46) = account.sex;
+						for( i = 0, n = 0; i < MAX_SERVERS; ++i )
+						{
+							if( !session_isValid(server[i].fd) )
+								continue;
+
+							subnet_char_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
+							WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
+							WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
+							memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20);
+							WFIFOW(fd,47+n*32+26) = server[i].users;
+							WFIFOW(fd,47+n*32+28) = server[i].maintenance;
+							WFIFOW(fd,47+n*32+30) = server[i].new_;
+							n++;
+						}
 						WFIFOSET(fd,47+32*server_num);
+
 						if (auth_fifo_pos >= AUTH_FIFO_SIZE)
 							auth_fifo_pos = 0;
 						auth_fifo[auth_fifo_pos].account_id = account.account_id;
@@ -1377,7 +1350,11 @@ int parse_login(int fd)
 						auth_fifo[auth_fifo_pos].delflag = 0;
 						auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
 						auth_fifo_pos++;
-					} else { // if no char-server, don't send void list of servers, just disconnect the player with proper message
+					}
+					else
+					{// if no char-server, don't send void list of servers, just disconnect the player with proper message
+						ShowStatus("Connection refused: there is no char-server online (account: %s, ip: %s).\n", account.userid, ip);
+						WFIFOHEAD(fd,3);
 						WFIFOW(fd,0) = 0x81;
 						WFIFOB(fd,2) = 1; // 01 = Server closed
 						WFIFOSET(fd,3);
@@ -1445,7 +1422,9 @@ int parse_login(int fd)
 				WFIFOHEAD(fd,23);
 				WFIFOW(fd,0) = 0x6a;
 				WFIFOB(fd,2) = (uint8)result;
-				if( result == 6 )
+				if( result != 6 )
+					memset(WFIFOP(fd,3), '\0', 20);
+				else
 				{// 6 = Your are Prohibited to log in until %s
 					if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'", login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) )
 						Sql_ShowDebug(sql_handle);
@@ -1461,8 +1440,6 @@ int parse_login(int fd)
 						strftime((char*)WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time));
 					}
 				}
-				else
-					memset(WFIFOP(fd,3), '\0', 20);
 				WFIFOSET(fd,23);
 			}
 
@@ -1526,7 +1503,7 @@ int parse_login(int fd)
 				Sql_ShowDebug(sql_handle);
 
 			result = mmo_auth(&account, fd);
-			if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 )
+			if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 )
 			{
 				ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name);
 				memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
@@ -1536,7 +1513,7 @@ int parse_login(int fd)
 				server[account.account_id].users = 0;
 				server[account.account_id].maintenance = RFIFOW(fd,82);
 				server[account.account_id].new_ = RFIFOW(fd,84);
-				server_fd[account.account_id] = fd;
+				server[account.account_id].fd = fd;
 
 				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x2711;
@@ -1560,14 +1537,12 @@ int parse_login(int fd)
 				WFIFOB(fd,2) = 3;
 				WFIFOSET(fd,3);
 			}
-
+		}
 			RFIFOSKIP(fd,86);
 			return 0;
-		}
 
 		case 0x7530:	// Server version information request
-		{
-			ShowInfo ("Athena version check...\n");
+			ShowStatus("Sending server version information to ip: %s\n", ip);
 			WFIFOHEAD(fd,10);
 			WFIFOW(fd,0) = 0x7531;
 			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
@@ -1580,7 +1555,6 @@ int parse_login(int fd)
 			WFIFOSET(fd,10);
 
 			RFIFOSKIP(fd,2);
-		}
 		break;
 
 		case 0x7532:	// Request to end connection
@@ -1589,7 +1563,7 @@ int parse_login(int fd)
 		break;
 
 		default:
-			ShowStatus("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0));
+			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
 			set_eof(fd);
 			return 0;
 		}
@@ -1618,7 +1592,7 @@ int parse_console(char* buf)
 		strcmpi("end", command) == 0 )
 		runflag = 0;
 	else
-	if( strcmpi("alive", command) == 0 || 
+	if( strcmpi("alive", command) == 0 ||
 		strcmpi("status", command) == 0 )
 		ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
 	else
@@ -1931,7 +1905,7 @@ int do_init(int argc, char** argv)
 		auth_fifo[i].delflag = 1;
 
 	for( i = 0; i < MAX_SERVERS; i++ )
-		server_fd[i] = -1;
+		server[i].fd = -1;
 
 	// Online user database init
 	online_db = idb_alloc(DB_OPT_RELEASE_DATA);

+ 42 - 1
src/login_sql/login.h

@@ -4,6 +4,8 @@
 #ifndef _LOGIN_SQL_H_
 #define _LOGIN_SQL_H_
 
+#include "../common/mmo.h" // NAME_LENGTH
+
 #define LOGIN_CONF_NAME	"conf/login_athena.conf"
 #define SQL_CONF_NAME "conf/inter_athena.conf"
 #define LAN_CONF_NAME "conf/subnet_athena.conf"
@@ -18,9 +20,9 @@ struct mmo_account {
 	int passwdenc;
 	
 	int account_id;
-	int char_id;
 	long login_id1;
 	long login_id2;
+	int char_id;
 	char lastlogin[24];
 	int sex;
 	uint8 level;
@@ -28,6 +30,7 @@ struct mmo_account {
 
 struct mmo_char_server {
 	char name[20];
+	int fd;
 	uint32 ip;
 	uint16 port;
 	int users;
@@ -35,4 +38,42 @@ struct mmo_char_server {
 	int new_;
 };
 
+extern struct Login_Config {
+
+	uint32 login_ip;								// the address to bind to
+	uint16 login_port;								// the port to bind to
+	unsigned int ip_sync_interval;					// interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
+	bool log_login;									// whether to log login server actions or not
+	char date_format[32];							// date format used in messages
+	bool console;									// console input system enabled?
+	bool new_account_flag;							// autoregistration via _M/_F ?
+	bool case_sensitive;							// are logins case sensitive ?
+	bool use_md5_passwds;							// work with password hashes instead of plaintext passwords?
+	bool login_gm_read;								// should the login server handle info about gm accounts?
+	int min_level_to_connect;						// minimum level of player/GM (0: player, 1-99: GM) to connect
+	bool online_check;								// reject incoming players that are already registered as online ?
+	bool check_client_version;						// check the clientversion set in the clientinfo ?
+	int client_version_to_connect;					// the client version needed to connect (if checking is enabled)
+
+	bool ipban;										// perform IP blocking (via contents of `ipbanlist`) ?
+	bool dynamic_pass_failure_ban;					// automatic IP blocking due to failed login attemps ?
+	unsigned int dynamic_pass_failure_ban_interval;	// how far to scan the loginlog for password failures
+	unsigned int dynamic_pass_failure_ban_limit;	// number of failures needed to trigger the ipban
+	unsigned int dynamic_pass_failure_ban_duration;	// duration of the ipban
+	bool use_dnsbl;									// dns blacklist blocking ?
+	char dnsbl_servs[1024];							// comma-separated list of dnsbl servers
+
+} login_config;
+
+// stores auth information of incoming clients
+// used during charserver auth validation process
+#define AUTH_FIFO_SIZE 256
+extern struct _auth_fifo {
+	int account_id;
+	uint32 login_id1, login_id2;
+	uint32 ip;
+	uint8 sex;
+	bool delflag;
+} auth_fifo[AUTH_FIFO_SIZE];
+
 #endif /* _LOGIN_SQL_H_ */

+ 1 - 1
src/map/clif.h

@@ -30,7 +30,7 @@ struct guild;
 // v8 - 2007-05-21aSakexe+ - 0x283
 // v9 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c
 #ifndef PACKETVER
-	#define PACKETVER	8
+	#define PACKETVER	7
 #endif
 
 // packet DB

+ 1 - 1
src/map/script.c

@@ -11610,7 +11610,7 @@ BUILDIN_FUNC(query_sql)
 	num_cols = Sql_NumColumns(mmysql_handle);
 	if( num_vars < num_cols )
 	{
-		ShowWarning("script:query_sql: Too many columns, discarting last %u columns.\n", (unsigned int)(num_cols-num_vars));
+		ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars));
 		script_reportsrc(st);
 	}
 	else if( num_vars > num_cols )

+ 4 - 0
vcproj-6/login-server_txt.dsp

@@ -187,6 +187,10 @@ SOURCE=..\src\common\version.h
 # PROP Default_Filter ""
 # Begin Source File
 
+SOURCE=..\src\login\admin.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\login\login.c
 # End Source File
 # Begin Source File

+ 3 - 0
vcproj-7.1/login-server_txt.vcproj

@@ -147,6 +147,9 @@
 		<Filter
 			Name="login_txt"
 			Filter="">
+			<File
+				RelativePath="..\src\login\admin.c">
+			</File>
 			<File
 				RelativePath="..\src\login\login.c">
 			</File>

+ 4 - 0
vcproj-8/login-server_txt.vcproj

@@ -203,6 +203,10 @@
 		<Filter
 			Name="login_txt"
 			>
+			<File
+				RelativePath="..\src\login\admin.c"
+				>
+			</File>
 			<File
 				RelativePath="..\src\login\login.c"
 				>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels