diff options
-rw-r--r-- | Changelog-Trunk.txt | 4 | ||||
-rw-r--r-- | src/char/char.c | 76 | ||||
-rw-r--r-- | src/char_sql/char.c | 84 | ||||
-rw-r--r-- | src/map/chrif.c | 74 |
4 files changed, 224 insertions, 14 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index a0c012245..9d2dd0566 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,10 @@ 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. 2008/04/13 + * Quick&dirty reversal of the inter-server behaviour introduced in r3255/r3256: + - the behaviour enabled a desynch between the char-server and the map-server + - now the map-server asks the char-server to authenticate the auth info + (the char-server doesn't send the auth info immediatelly) * Changes to the configure script: [FlavioJS] - clarified how --with-zlib is used - added --enable-packetver to set the PACKETVER define (used often enough diff --git a/src/char/char.c b/src/char/char.c index 13da079ab..b35e46c9f 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -2838,12 +2838,16 @@ int parse_frommap(int fd) //Tell the new map server about this player using Kevin's new auth packet. [Skotlex] if (map_fd >= 0 && session[map_fd] && char_data) { //Send the map server the auth of this player. + struct auth_node* node; + //Update the "last map" as this is where the player must be spawned on the new map server. char_data->last_point.map = RFIFOW(fd,18); char_data->last_point.x = RFIFOW(fd,20); char_data->last_point.y = RFIFOW(fd,22); char_data->sex = RFIFOB(fd,30); +#if 0 + // the map-server must request it [FlavioJS] WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus); @@ -2853,6 +2857,18 @@ int parse_frommap(int fd) WFIFOL(map_fd,12) = (unsigned long)0; //TODO: expiration_time, how do I figure it out right now? memcpy(WFIFOP(map_fd,20), char_data, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); +#endif + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = RFIFOL(fd,2); + node->char_id = RFIFOL(fd,14); + node->login_id1 = RFIFOL(fd,6); + node->login_id2 = RFIFOL(fd,10); + node->sex = RFIFOB(fd,30); + node->expiration_time = 0; // FIXME + node->ip = ntohl(RFIFOL(fd,31)); + idb_put(auth_db, RFIFOL(fd,2), node); data = (struct online_char_data*)idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); data->char_id = char_data->char_id; @@ -3111,6 +3127,63 @@ int parse_frommap(int fd) RFIFOSKIP(fd,2); break; + case 0x2b26: // auth request from map-server + if (RFIFOREST(fd) < 19) + return 0; + + { + int account_id; + int char_id; + int login_id1; + char sex; + uint32 ip; + struct auth_node* node; + struct mmo_charstatus* cd; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + + node = (struct auth_node*)idb_get(auth_db, account_id); + cd = search_character(account_id, char_id); + if( node != NULL && cd != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex && + node->ip == ip ) + {// auth ok + WFIFOHEAD(fd,20 + sizeof(struct mmo_charstatus)); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = 20 + sizeof(struct mmo_charstatus); + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = login_id1; + WFIFOL(fd,12) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" + WFIFOL(fd,16) = node->login_id2; + memcpy(WFIFOP(fd,20), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + // only use the auth once and mark user online + idb_remove(auth_db, account_id); + set_char_online(id, account_id, char_id); + } + else + {// auth failed + WFIFOHEAD(fd,19); + WFIFOW(fd,0) = 0x2b27; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOL(fd,10) = login_id1; + WFIFOB(fd,14) = sex; + WFIFOL(fd,15) = htonl(ip); + WFIFOSET(fd,19); + } + } + break; + case 0x2736: // ip address update if (RFIFOREST(fd) < 6) return 0; server[id].ip = ntohl(RFIFOL(fd, 2)); @@ -3398,6 +3471,8 @@ int parse_char(int fd) ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch); +#if 0 + // The server must request it [FlavioJS] //Send auth ok to map server WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; @@ -3408,6 +3483,7 @@ int parse_char(int fd) WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time; memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); +#endif // create temporary auth entry CREATE(node, struct auth_node, 1); diff --git a/src/char_sql/char.c b/src/char_sql/char.c index ca1b74ce7..9afd6b59d 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -2532,17 +2532,21 @@ int parse_frommap(int fd) if (char_data == NULL) { //Really shouldn't happen. mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); - char_data = &char_dat; + char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); } //Tell the new map server about this player using Kevin's new auth packet. [Skotlex] if (map_fd >= 0 && session[map_fd] && char_data) { //Send the map server the auth of this player. + struct auth_node* node; + //Update the "last map" as this is where the player must be spawned on the new map server. char_data->last_point.map = RFIFOW(fd,18); char_data->last_point.x = RFIFOW(fd,20); char_data->last_point.y = RFIFOW(fd,22); char_data->sex = RFIFOB(fd,30); +#if 0 + // the map-server must request it [FlavioJS] WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus); @@ -2552,6 +2556,18 @@ int parse_frommap(int fd) WFIFOL(map_fd,12) = (unsigned long)0; //TODO: expiration_time, how do I figure it out right now? memcpy(WFIFOP(map_fd,20), char_data, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); +#endif + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = RFIFOL(fd,2); + node->char_id = RFIFOL(fd,14); + node->login_id1 = RFIFOL(fd,6); + node->login_id2 = RFIFOL(fd,10); + node->sex = RFIFOB(fd,30); + node->expiration_time = 0; // FIXME + node->ip = ntohl(RFIFOL(fd,31)); + idb_put(auth_db, RFIFOL(fd,2), node); data = (struct online_char_data*)idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); data->char_id = char_data->char_id; @@ -2852,6 +2868,69 @@ int parse_frommap(int fd) RFIFOSKIP(fd,2); break; + case 0x2b26: // auth request from map-server + if (RFIFOREST(fd) < 19) + return 0; + + { + int account_id; + int char_id; + int login_id1; + char sex; + uint32 ip; + struct auth_node* node; + struct mmo_charstatus* cd; + struct mmo_charstatus char_dat; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + + node = (struct auth_node*)idb_get(auth_db, account_id); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + if( cd == NULL ) + { //Really shouldn't happen. + mmo_char_fromsql(char_id, &char_dat, true); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); + } + if( node != NULL && cd != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex && + node->ip == ip ) + {// auth ok + WFIFOHEAD(fd,20 + sizeof(struct mmo_charstatus)); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = 20 + sizeof(struct mmo_charstatus); + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = login_id1; + WFIFOL(fd,12) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" + WFIFOL(fd,16) = node->login_id2; + memcpy(WFIFOP(fd,20), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + // only use the auth once and mark user online + idb_remove(auth_db, account_id); + set_char_online(id, account_id, char_id); + } + else + {// auth failed + WFIFOHEAD(fd,19); + WFIFOW(fd,0) = 0x2b27; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOL(fd,10) = login_id1; + WFIFOB(fd,14) = sex; + WFIFOL(fd,15) = htonl(ip); + WFIFOSET(fd,19); + } + } + break; + case 0x2736: // ip address update if (RFIFOREST(fd) < 6) return 0; server[id].ip = ntohl(RFIFOL(fd, 2)); @@ -3139,6 +3218,8 @@ int parse_char(int fd) WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] WFIFOSET(fd,28); +#if 0 + // The server must request it [FlavioJS] //Send auth ok to map server WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; @@ -3149,6 +3230,7 @@ int parse_char(int fd) WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time; memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); +#endif // create temporary auth entry CREATE(node, struct auth_node, 1); diff --git a/src/map/chrif.c b/src/map/chrif.c index c4fe9dd67..7fbff78e4 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -37,7 +37,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free 6,30,-1,-1,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f 11,10,10, 6,11,-1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, U->2b15, U->2b16, U->2b17 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f - -1,10, 8, 2, 2,14,-1,-1, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, F->2b26, F->2b27 + -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, F->2b26, F->2b27 }; //Used Packets: @@ -46,7 +46,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free //2afa: Outgoing, chrif_sendmap -> 'sending our maps' //2afb: Incoming, chrif_sendmapack -> 'Maps received successfully / or not ..' //2afc: Outgoing, chrif_scdata_request -> request sc_data for pc_authok'ed char. <- new command reuses previous one. -//2afd: Incoming, chrif_authok -> 'character selected, add to auth db' +//2afd: Incoming, chrif_authok -> 'client authentication ok' //2afe: Outgoing, send_usercount_tochar -> 'sends player count of this map server to charserver' //2aff: Outgoing, send_users_tochar -> 'sends all actual connected character ids to charserver' //2b00: Incoming, map_setusers -> 'set the actual usercount? PACKET.2B COUNT.L.. ?' (not sure) @@ -87,8 +87,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free //2b23: Outgoing, chrif_keepalive. charserver ping. //2b24: Incoming, chrif_keepalive_ack. charserver ping reply. //2b25: Incoming, chrif_deadopt -> 'Removes baby from Father ID and Mother ID' -//2b26: FREE -//2b27: FREE +//2b26: Outgoing, chrif_authreq -> 'client authentication request' +//2b27: Incoming, chrif_authfail -> 'client authentication failed' int chrif_connected = 0; int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex] @@ -384,7 +384,7 @@ int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) WFIFOL(char_fd,24) = htonl(ip); WFIFOW(char_fd,28) = htons(port); WFIFOB(char_fd,30) = sd->status.sex; - WFIFOL(char_fd,31) = 0; // sd's IP, not used anymore + WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr); WFIFOSET(char_fd,35); return 0; } @@ -517,6 +517,14 @@ void chrif_authreq(struct map_session_data *sd) if(!node) { //data from char server has not arrived yet. + WFIFOHEAD(char_fd,19); + WFIFOW(char_fd,0) = 0x2b26; + WFIFOL(char_fd,2) = sd->status.account_id; + WFIFOL(char_fd,6) = sd->status.char_id; + WFIFOL(char_fd,10) = sd->login_id1; + WFIFOB(char_fd,14) = sd->status.sex; + WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr); + WFIFOSET(char_fd,19); chrif_sd_to_auth(sd, ST_LOGIN); return; } @@ -550,10 +558,13 @@ void chrif_authreq(struct map_session_data *sd) //character selected, insert into auth db void chrif_authok(int fd) { + int account_id; + uint32 login_id1; + time_t expiration_time; + uint32 login_id2; + struct mmo_charstatus* status; + int char_id; struct auth_node *node; - int account_id = RFIFOL(fd, 4); - struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20); - int char_id = status->char_id; TBL_PC* sd; //Check if both servers agree on the struct's size @@ -563,6 +574,13 @@ void chrif_authok(int fd) return; } + account_id = RFIFOL(fd,4); + login_id1 = RFIFOL(fd,8); + expiration_time = (time_t)(int32)RFIFOL(fd,12); + login_id2 = RFIFOL(fd,16); + status = (struct mmo_charstatus*)RFIFOP(fd,20); + char_id = status->char_id; + //Check if we don't already have player data in our server //Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth. if ((sd = map_id2sd(account_id)) != NULL) @@ -578,9 +596,9 @@ void chrif_authok(int fd) if(node->char_dat == NULL && node->account_id == account_id && node->char_id == char_id && - node->login_id1 == RFIFOL(fd, 8)) + node->login_id1 == login_id1 ) { //Auth Ok - if (pc_authok(sd, RFIFOL(fd, 16), RFIFOL(fd, 12), status)) + if (pc_authok(sd, login_id2, expiration_time, status)) { chrif_char_online(sd); return; @@ -604,14 +622,43 @@ void chrif_authok(int fd) node->account_id=account_id; node->char_id=char_id; - node->login_id1=RFIFOL(fd, 8); - node->expiration_time=RFIFOL(fd, 12); - node->login_id2=RFIFOL(fd, 16); + node->login_id1=login_id1; + node->expiration_time=expiration_time; + node->login_id2=login_id2; memcpy(node->char_dat,status,sizeof(struct mmo_charstatus)); node->node_created=gettick(); idb_put(auth_db, account_id, node); } +// client authentication failed +void chrif_authfail(int fd) +{ + int account_id; + int char_id; + uint32 login_id1; + char sex; + uint32 ip; + struct auth_node* node; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + + node = chrif_search(account_id); + if( node != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex && + node->state == ST_LOGIN ) + {// found a match + clif_authfail_fd(node->fd, 0); + chrif_auth_delete(account_id, char_id, ST_LOGIN); + } +} + int auth_db_cleanup_sub(DBKey key,void *data,va_list ap) { struct auth_node *node=(struct auth_node*)data; @@ -1443,6 +1490,7 @@ int chrif_parse(int fd) case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; + case 0x2b27: chrif_authfail(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); |