summaryrefslogtreecommitdiff
path: root/src/char_sql/char.c
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-07-10 19:41:25 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-07-10 19:41:25 +0000
commit85bdc1dc6c13036984310f39428c82968ecffba7 (patch)
tree88e0e06f9b7bfa6bcd30b75c6e8f5335b26267c1 /src/char_sql/char.c
parent1a26dbddc283e94bdfb684a71b0d9db471e18b3b (diff)
downloadhercules-85bdc1dc6c13036984310f39428c82968ecffba7.tar.gz
hercules-85bdc1dc6c13036984310f39428c82968ecffba7.tar.bz2
hercules-85bdc1dc6c13036984310f39428c82968ecffba7.tar.xz
hercules-85bdc1dc6c13036984310f39428c82968ecffba7.zip
- Added login-char packet 0x2737. Sets all characters offline (login-server side).
- Cleaned up char server "set all offline" implementation to remove only characters from the map-server from which the packet was invoked. It will also now correctly kick/set-character offline from the map-server if they are connected. - Cleaned up the char-sql reconnect code. It no longer sets everyone to offline. - Removed setting "kick_on_disconnect", servers will no longer kick characters out when there's a disconnection. Instead, it'll use the most logical approach: Set characters into a "lost" state when there's a disconnection, on reconnect, resent the list of online-characters, do a sync, and let the difference be characters to be removed. Also, the map-server won't release character data until it's saved and the ack returns from the char-server to prevent data loss (all this data is resent on reconnect for saving anyway). git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@7600 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/char_sql/char.c')
-rw-r--r--src/char_sql/char.c212
1 files changed, 76 insertions, 136 deletions
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 98b6534c3..a6e707f2e 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -290,38 +290,55 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap) {
return 0;
}
-void set_all_offline(void) {
- MYSQL_RES* sql_res2; //Needed because it is used inside inter_guild_CharOffline; [Skotlex]
- int char_id;
- sprintf(tmp_sql, "SELECT `account_id`, `char_id`, `guild_id` FROM `%s` WHERE `online`='1'",char_db);
- if (mysql_query(&mysql_handle, tmp_sql)) {
+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);
+ if (server > -1 && character->server != server)
+ 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);
+ else if (!character->waiting_disconnect)
+ set_char_offline(character->char_id, character->account_id);
+ else return 0;
+ return 1;
+}
+
+void set_all_offline(int id) {
+ if (id < 0)
+ ShowNotice("Sending all users offline.\n");
+ else
+ ShowNotice("Sending users of map-server %d offline.\n",id);
+ online_char_db->foreach(online_char_db,char_db_kickoffline,id);
+
+ if (id >= 0 || login_fd <= 0 || session[login_fd]->eof)
+ return;
+ //Tell login-server to also mark all our characters as offline.
+ WFIFOHEAD(login_fd, 2);
+ WFIFOW(login_fd,0) = 0x2737;
+ WFIFOSET(login_fd,2);
+}
+
+void set_all_offline_sql(void) {
+ //Set all players to 'OFFLINE'
+ sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", char_db);
+ if(mysql_query(&mysql_handle, tmp_sql)){
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
}
- ShowNotice("Sending all users offline.\n");
- sql_res2 = mysql_store_result(&mysql_handle);
- if (sql_res2) {
- while((sql_row = mysql_fetch_row(sql_res2))) {
- char_id = atoi(sql_row[1]);
- inter_guild_CharOffline(char_id, atoi(sql_row[2]));
-
- if ( login_fd > 0 ) {
- ShowInfo("send user offline: %d\n",char_id);
- WFIFOW(login_fd,0) = 0x272c;
- WFIFOL(login_fd,2) = char_id;
- WFIFOSET(login_fd,6);
- }
- }
- mysql_free_result(sql_res2);
- }
-
- sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db);
- if (mysql_query(&mysql_handle, tmp_sql)) {
+ sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", guild_member_db);
+ if(mysql_query(&mysql_handle, tmp_sql)){
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
}
- online_char_db->foreach(online_char_db,char_db_setoffline,-1);
+ sprintf(tmp_sql, "UPDATE `%s` SET `connect_member` = '0'", guild_db);
+ if(mysql_query(&mysql_handle, tmp_sql)){
+ ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
+ ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
}
+
//----------------------------------------------------------------------
// Determine if an account (id) is a GM account
// and returns its level (or 0 if it isn't a GM account or if not found)
@@ -1812,13 +1829,8 @@ int parse_tologin(int fd) {
//exit(1); //fixed for server shutdown.
}else {
ShowStatus("Connected to login-server (connection #%d).\n", fd);
-// Don't set them offline as there's no packet to tell the map server
-// to kick everyone out. Also, a disconnection from the login server is
-// NOT something serious to the data integrity as a char-map disconnect
-// is. [Skotlex]
-// if (kick_on_disconnect)
-// set_all_offline();
-// However, on reconnect, DO send our connected accounts to login.
+
+ //Send online accounts to login server.
send_accounts_tologin(-1, gettick(), 0, 0);
// if no map-server already connected, display a message...
@@ -2453,8 +2465,7 @@ int parse_frommap(int fd) {
ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
id, j, p[0], p[1], p[2], p[3], server[id].port);
ShowStatus("Map-server %d loading complete.\n", id);
- if (kick_on_disconnect)
- set_all_offline();
+
if (max_account_id != DEFAULT_MAX_ACCOUNT_ID || max_char_id != DEFAULT_MAX_CHAR_ID)
mapif_send_maxid(max_account_id, max_char_id); //Send the current max ids to the server to keep in sync [Skotlex]
}
@@ -2951,8 +2962,7 @@ int parse_frommap(int fd) {
break;
// Reset all chars to offline [Wizputer]
case 0x2b18:
- ShowNotice("Map server [%d] requested to set all characters offline.\n", id);
- set_all_offline();
+ set_all_offline(id);
RFIFOSKIP(fd,2);
break;
// Character set online [Wizputer]
@@ -3751,112 +3761,41 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, int data) {
WFIFOL(login_fd,4) = users;
online_char_db->foreach(online_char_db, send_accounts_tologin_sub, &i, users);
WFIFOW(login_fd,2) = 8+ i*4;
- if (i > 0)
- WFIFOSET(login_fd,WFIFOW(login_fd,2));
+ WFIFOSET(login_fd,WFIFOW(login_fd,2));
}
return 0;
}
int check_connect_login_server(int tid, unsigned int tick, int id, int data) {
- if (login_fd <= 0 || session[login_fd] == NULL) {
- struct char_session_data *sd;
- int i, cc;
- unsigned char buf[16];
-
- ShowInfo("Attempt to connect to login-server...\n");
- login_fd = make_connection(login_ip, login_port);
- if (login_fd == -1)
- { //Try again later. [Skotlex]
- login_fd = 0;
- return 0;
- }
- session[login_fd]->func_parse = parse_tologin;
- realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
- WFIFOW(login_fd,0) = 0x2710;
- memcpy(WFIFOP(login_fd,2), userid, 24);
- memcpy(WFIFOP(login_fd,26), passwd, 24);
- WFIFOL(login_fd,50) = 0;
- WFIFOL(login_fd,54) = char_ip;
- WFIFOL(login_fd,58) = char_port;
- memset(WFIFOP(login_fd,60), 0, 20);
- memcpy(WFIFOP(login_fd,60), server_name, strlen(server_name) < 20 ? strlen(server_name) : 20);
- WFIFOW(login_fd,80) = 0;
- WFIFOW(login_fd,82) = char_maintenance;
-
- WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin]
-
- WFIFOSET(login_fd,86);
-
- if (!kick_on_disconnect)
- return 0; //Do not perform on-connect cleanup duties.
-
- //(re)connected to login-server,
- //now wi'll look in sql which player's are ON and set them OFF
- //AND send to all mapservers (if we have one / ..) to kick the players
- //so the bug is fixed, if'ure using more than one charservers (worlds)
- //that the player'S got reejected from server after a 'world' crash^^
- //2b1f AID.L B1
-
- sprintf(tmp_sql, "SELECT `account_id`, `online` FROM `%s` WHERE `online` = '1'", char_db);
- if(mysql_query(&mysql_handle, tmp_sql)){
- ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- return -1;
- }
-
- sql_res = mysql_store_result(&mysql_handle);
- if(sql_res){
- cc = (int)mysql_num_rows(sql_res);
- ShowStatus("Setting %d Players offline\n", cc);
- while((sql_row = mysql_fetch_row(sql_res))){
- //sql_row[0] == AID
- //tell the loginserver
- WFIFOW(login_fd, 0) = 0x272c; //set off
- WFIFOL(login_fd, 2) = atoi(sql_row[0]); //AID
- WFIFOSET(login_fd, 6);
-
- //tell map to 'kick' the player (incase of 'on' ..)
- WBUFW(buf, 0) = 0x2b1f;
- WBUFL(buf, 2) = atoi(sql_row[0]);
- WBUFB(buf, 6) = 1;
- mapif_sendall(buf, 7);
-
- //kick the player if he's on charselect
- for(i = 0; i < fd_max; i++){
- if(session[i] && (sd = (struct char_session_data*)session[i]->session_data)){
- if(sd->account_id == atoi(sql_row[0])){
- session[i]->eof = 1;
- break;
- }
- }
- }
-
- }
- mysql_free_result(sql_res);
- }else{
- ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- return -1;
- }
+ struct char_session_data *sd;
+ int i, cc;
+ unsigned char buf[16];
- //Now Update all players to 'OFFLINE'
- sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", char_db);
- if(mysql_query(&mysql_handle, tmp_sql)){
- ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- }
- sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", guild_member_db);
- if(mysql_query(&mysql_handle, tmp_sql)){
- ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- }
- sprintf(tmp_sql, "UPDATE `%s` SET `connect_member` = '0'", guild_db);
- if(mysql_query(&mysql_handle, tmp_sql)){
- ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
- ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- }
+ if (login_fd > 0 || session[login_fd] != NULL)
+ return 0;
+ ShowInfo("Attempt to connect to login-server...\n");
+ login_fd = make_connection(login_ip, login_port);
+ if (login_fd == -1)
+ { //Try again later. [Skotlex]
+ login_fd = 0;
+ return 0;
}
+ session[login_fd]->func_parse = parse_tologin;
+ realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+ WFIFOW(login_fd,0) = 0x2710;
+ memcpy(WFIFOP(login_fd,2), userid, 24);
+ memcpy(WFIFOP(login_fd,26), passwd, 24);
+ WFIFOL(login_fd,50) = 0;
+ WFIFOL(login_fd,54) = char_ip;
+ WFIFOL(login_fd,58) = char_port;
+ memcpy(WFIFOP(login_fd,60), server_name, 20);
+ WFIFOW(login_fd,80) = 0;
+ WFIFOW(login_fd,82) = char_maintenance;
+
+ WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin]
+
+ WFIFOSET(login_fd,86);
return 0;
}
@@ -3951,7 +3890,8 @@ void do_final(void) {
//check SQL save progress.
//wait until save char complete
- set_all_offline();
+ set_all_offline(-1);
+ set_all_offline_sql();
inter_final();
@@ -4107,7 +4047,7 @@ int char_config_read(const char *cfgName) {
} else if (strcmpi(w1, "passwd") == 0) {
strncpy(passwd, w2, 24);
} else if (strcmpi(w1, "server_name") == 0) {
- memcpy(server_name, w2, sizeof(server_name));
+ strncpy(server_name, w2, 20)
server_name[sizeof(server_name) - 1] = '\0';
ShowStatus("%s server has been initialized\n", w2);
} else if (strcmpi(w1, "wisp_server_name") == 0) {