From e13ebc226f3f0ac937f880df270e30ad2aa5d450 Mon Sep 17 00:00:00 2001 From: ultramage Date: Wed, 25 Jul 2007 16:45:09 +0000 Subject: * Added support for character rename packet (only dummy code for now) * Added support for langtype-12 char deletion packet (tested, works) * Synchronized txt/sql charserver code a bit * Adjusted motd.txt to not crash new clients * Removed some dead code from the charserver (see r352) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@10909 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 6 ++ conf-tmpl/Changelog.txt | 3 + conf-tmpl/char_athena.conf | 9 +- conf-tmpl/motd.txt | 2 +- src/char/char.c | 180 ++++++++++++++++---------------------- src/char_sql/char.c | 210 +++++++++++++++++++++++---------------------- src/common/socket.c | 4 +- src/map/clif.c | 2 +- 8 files changed, 194 insertions(+), 222 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index b1930ae7c..9193c69fd 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,12 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/07/25 + * Added support for character rename packet (only dummy code for now) + * Added support for langtype-12 char deletion packet (tested, works) + * Synchronized txt/sql charserver code a bit + * Adjusted motd.txt to not crash new clients + * Removed some dead code from the charserver (see r352) 2007/07/24 * Fixes on Venom Splasher and the like (see topic:152975) [DracoRPG] - VS / Envenom / Throw Venom Knife poison chance raised to 10+4*lv % diff --git a/conf-tmpl/Changelog.txt b/conf-tmpl/Changelog.txt index 1f8870309..87f2a2ec9 100644 --- a/conf-tmpl/Changelog.txt +++ b/conf-tmpl/Changelog.txt @@ -1,5 +1,8 @@ Date Added +2007/07/25 + * Adjusted motd.txt to not crash new clients + * Removed backup_txt code since it's not needed anymore 2007/07/20 * Adjusted client.conf's packetver table (latest now uses new value) 2007/07/18 diff --git a/conf-tmpl/char_athena.conf b/conf-tmpl/char_athena.conf index 3948a84fa..200831220 100644 --- a/conf-tmpl/char_athena.conf +++ b/conf-tmpl/char_athena.conf @@ -110,13 +110,6 @@ save_log: yes // Character server flatfile database char_txt: save/athena.txt -// Choose to create or not backup file (yes/no, 0/1, etc...) -// default is 'no', because backup file take time for nothing. Actually, there is no problem on characters file creation and save. -backup_txt_flag: no - -// Character server flatfile database (backup, TXT only) -backup_txt: save/athena_backup.txt - // Friends list flatfile database friends_txt: save/friends.txt @@ -169,7 +162,7 @@ char_name_letters: abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678 // Character rename option. When set to yes, the server will send an extended // char-info packet, informing whether the character can be renamed or not. // NOTE: This functionality is not implemented. -// NOTE: This option is for compatibility with kRO sakray 2006-10-23 and above. +// NOTE: This option is for compatibility with kRO sakray 2006-10-23 and newer. // !Do not use it for any other type of client since it will crash them! char_rename: yes diff --git a/conf-tmpl/motd.txt b/conf-tmpl/motd.txt index 7e8c50575..b443cc434 100644 --- a/conf-tmpl/motd.txt +++ b/conf-tmpl/motd.txt @@ -1,2 +1,2 @@ // Internal default is limited to 128 lines. If you need more, you will need to modify the MOTD_LINE_SIZE definition in pc.c -Welcome to eAthena SVN Version! Enjoy! Please report any bugs you find in eAthena :). +Welcome to eAthena SVN Version! Enjoy! Please report any bugs you find. diff --git a/src/char/char.c b/src/char/char.c index ab4572af4..f584c8fdc 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -2,21 +2,21 @@ // For more information, see LICENCE in the main folder #include "../common/cbasetypes.h" -#include "../common/strlib.h" +#include "../common/db.h" +#include "../common/lock.h" +#include "../common/malloc.h" +#include "../common/mmo.h" #include "../common/core.h" #include "../common/socket.h" +#include "../common/strlib.h" +#include "../common/showmsg.h" #include "../common/timer.h" -#include "../common/mmo.h" -#include "../common/db.h" #include "../common/version.h" -#include "../common/lock.h" -#include "../common/showmsg.h" -#include "../common/malloc.h" #include "inter.h" -#include "int_pet.h" -#include "int_homun.h" #include "int_guild.h" +#include "int_homun.h" +#include "int_pet.h" #include "int_party.h" #include "int_storage.h" #ifdef ENABLE_SC_SAVING @@ -25,7 +25,6 @@ #include "char.h" #include - #ifdef WIN32 #include #else @@ -33,7 +32,6 @@ #include #include #endif - #include #include #include @@ -46,7 +44,15 @@ #define CHAR_CONF_NAME "conf/char_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" +char char_txt[1024] = "save/athena.txt"; +char friends_txt[1024] = "save/friends.txt"; +char char_log_filename[1024] = "log/char.log"; + +int save_log = 1; // show loading/saving messages + #ifndef TXT_SQL_CONVERT +char db_path[1024] = "db"; + struct mmo_map_server { uint32 ip; uint16 port; @@ -71,16 +77,20 @@ uint16 char_port = 6121; int char_maintenance = 0; int char_new = 1; int char_new_display = 0; + int email_creation = 0; // disabled by default -#endif -char char_txt[1024]="save/athena.txt"; -char backup_txt[1024]="save/backup.txt"; //By zanetheinsane -char friends_txt[1024]="save/friends.txt"; // davidsiaw -#ifndef TXT_SQL_CONVERT -char backup_txt_flag = 0; // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor] + +int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor] +int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] char unknown_char_name[1024] = "Unknown"; // Name to use when the requested name cannot be determined -char char_log_filename[1024] = "log/char.log"; -char db_path[1024]="db"; +#define TRIM_CHARS "\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] +char char_name_letters[1024] = ""; // list of letters/symbols authorised (or not) in a character name. by [Yor] +bool char_rename = true; + +int log_char = 1; // loggin char or not [devil] +int log_inter = 1; // loggin inter or not [devil] + +static int online_check = 1; //If one, it won't let players connect when their account is already registered online and will send the relevant map server a kick user request. [Skotlex] // Advanced subnet check [LuzZza] struct _subnet { @@ -89,19 +99,8 @@ struct _subnet { uint32 char_ip; uint32 map_ip; } subnet[16]; - int subnet_count = 0; -int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor] -int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] -//The following are characters that are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] -#define TRIM_CHARS "\032\t\x0A\x0D " -char char_name_letters[1024] = ""; // list of letters/symbols authorised (or not) in a character name. by [Yor] -bool char_rename = true; - -int log_char = 1; // loggin char or not [devil] -int log_inter = 1; // loggin inter or not [devil] - struct char_session_data{ int account_id, login_id1, login_id2, sex; int found_char[MAX_CHARS]; @@ -119,8 +118,6 @@ struct { } auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos = 0; -static int online_check = 1; //If one, it won't let players connect when their account is already registered online and will send the relevant map server a kick user request. [Skotlex] - int char_id_count = START_CHAR_NUM; struct character_data *char_dat; @@ -128,7 +125,6 @@ int char_num, char_max; int max_connect_user = 0; int gm_allow_level = 99; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; -int save_log = 1; int start_zeny = 500; int start_weapon = 1201; int start_armor = 2301; @@ -161,6 +157,7 @@ int online_gm_display_min_level = 20; // minimum GM level to display 'GM' when w //These are used to aid the map server in identifying valid clients. [Skotlex] static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID; +//Structure for holding in memory which characters are online on the map servers connected. struct online_char_data { int account_id; int char_id; @@ -1045,25 +1042,6 @@ void mmo_char_sync(void) lock_fclose(fp, char_txt, &lock); } - // Data save (backup) - if (backup_txt_flag) { // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor] - fp = lock_fopen(backup_txt, &lock); - if (fp == NULL) { - ShowWarning("Server can't not create backup of characters file.\n"); - char_log("WARNING: Server can't not create backup of characters file." RETCODE); - //aFree(id); // free up the memory before leaving -.- [Ajarn] - DELETE_BUFFER(id); - return; - } - for(i = 0; i < char_num; i++) { - // create only once the line, and save it in the 2 files (it's speeder than repeat twice the loop and create twice the line) - mmo_char_tostr(line, &char_dat[id[i]].status,char_dat[id[i]].global, char_dat[id[i]].global_num); // use of sorted index - fprintf(fp, "%s" RETCODE, line); - } - fprintf(fp, "%d\t%%newid%%" RETCODE, char_id_count); - lock_fclose(fp, backup_txt, &lock); - } - // Friends List data save (davidsiaw) f_fp = lock_fopen(friends_txt, &lock); for(i = 0; i < char_num; i++) { @@ -1663,7 +1641,7 @@ int count_users(void) /// Writes char data to the buffer in the format used by the client. /// Used in packets 0x6b (chars info) and 0x6d (new char info) /// Returns the size (106 or 108) -int mmo_char_tobuf(uint8* buf, struct mmo_charstatus *p) +int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p) { if( buf == NULL || p == NULL ) return 0; @@ -1673,14 +1651,11 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus *p) WBUFL(buf,8) = p->zeny; WBUFL(buf,12) = min(p->job_exp, LONG_MAX); WBUFL(buf,16) = p->job_level; - - WBUFL(buf,20) = 0;// probably opt1 - WBUFL(buf,24) = 0;// probably opt2 + WBUFL(buf,20) = 0; // probably opt1 + WBUFL(buf,24) = 0; // probably opt2 WBUFL(buf,28) = p->option; - WBUFL(buf,32) = p->karma; WBUFL(buf,36) = p->manner; - WBUFW(buf,40) = min(p->status_point, SHRT_MAX); WBUFW(buf,42) = min(p->hp, SHRT_MAX); WBUFW(buf,44) = min(p->max_hp, SHRT_MAX); @@ -1717,7 +1692,7 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus *p) //---------------------------------------- // Function to send characters to a player //---------------------------------------- -int mmo_char_send006b(int fd, struct char_session_data *sd) +int mmo_char_send006b(int fd, struct char_session_data* sd) { int i, j, found_num; @@ -1734,13 +1709,13 @@ int mmo_char_send006b(int fd, struct char_session_data *sd) for(i = found_num; i < MAX_CHARS; i++) sd->found_char[i] = -1; - j = 24;// offset + j = 24; // offset WFIFOHEAD(fd,j + found_num*108); // or 106(!) WFIFOW(fd,0) = 0x6b; - memset(WFIFOP(fd,4), 0, 20);// unknown bytes + memset(WFIFOP(fd,4), 0, 20); // unknown bytes for(i = 0; i < found_num; i++) j += mmo_char_tobuf(WFIFOP(fd,j), &char_dat[sd->found_char[i]].status); - WFIFOW(fd,2) = j;// packet len + WFIFOW(fd,2) = j; // packet len WFIFOSET(fd,j); return 0; @@ -3302,7 +3277,7 @@ int parse_char(int fd) char email[40]; unsigned short cmd; int map_fd; - struct char_session_data *sd; + struct char_session_data* sd; uint32 ipl = session[fd]->client_addr; sd = (struct char_session_data*)session[fd]->session_data; @@ -3324,32 +3299,17 @@ int parse_char(int fd) return 0; } - while(RFIFOREST(fd) >= 2) { - cmd = RFIFOW(fd,0); - // crc32のスキップ用 - if( sd==NULL && // 未ログインor管理パケット - RFIFOREST(fd)>=4 && // 最低バイト数制限 & 0x7530,0x7532管理パケ除去 - RFIFOREST(fd)<=21 && // 最大バイト数制限 & サーバーログイン除去 - cmd!=0x20b && // md5通知パケット除去 - (RFIFOREST(fd)<6 || RFIFOW(fd,4)==0x65) ){ // 次に何かパケットが来てるなら、接続でないとだめ - RFIFOSKIP(fd,4); - cmd = RFIFOW(fd,0); - ShowDebug("parse_char : %d crc32 skipped\n",fd); - if(RFIFOREST(fd)==0) - return 0; - } - -//For use in packets that depend on an sd being present [Skotlex] -#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL) { RFIFOSKIP(fd,rest); return 0; } } + while(RFIFOREST(fd) >= 2) + { + //For use in packets that depend on an sd being present [Skotlex] + #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL) { RFIFOSKIP(fd,rest); return 0; } } - switch(cmd) { - case 0x20b: //20040622暗号化ragexe対応 - if (RFIFOREST(fd) < 19) - return 0; - RFIFOSKIP(fd,19); - break; + cmd = RFIFOW(fd,0); + switch(cmd) + { - case 0x65: // 接続要求 + case 0x65: // request to connect + ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); if (RFIFOREST(fd) < 17) return 0; { @@ -3365,9 +3325,9 @@ int parse_char(int fd) ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", RFIFOL(fd,2), GM_value); else ShowInfo("Account Logged On; Account ID: %d.\n", RFIFOL(fd,2)); + CREATE(session[fd]->session_data, struct char_session_data, 1); sd = (struct char_session_data*)session[fd]->session_data; - session[fd]->session_data = sd; strncpy(sd->email, "no mail", 40); // put here a mail without '@' to refuse deletion if we don't receive the e-mail sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server) sd->account_id = RFIFOL(fd,2); @@ -3550,7 +3510,7 @@ int parse_char(int fd) case 0x67: // make new FIFOSD_CHECK(37); - + if(char_new == 0) //turn character creation on/off [Kevin] i = -2; else @@ -3590,13 +3550,15 @@ int parse_char(int fd) break; case 0x68: // delete char - FIFOSD_CHECK(46); + case 0x1fb: // 2004-04-19aSakexe+ langtype 12 char deletion packet + if (cmd == 0x68) FIFOSD_CHECK(46); + if (cmd == 0x1fb) FIFOSD_CHECK(56); { int cid = RFIFOL(fd,2); struct mmo_charstatus* cs = NULL; - ShowInfo(CL_RED" Request Char Deletion:"CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); memcpy(email, RFIFOP(fd,6), 40); - RFIFOSKIP(fd,46); + RFIFOSKIP(fd,RFIFOREST(fd)); // hack to make the other deletion packet work if (e_mail_check(email) == 0) strncpy(email, "a@a.com", 40); // default e-mail @@ -3692,6 +3654,19 @@ int parse_char(int fd) } break; + case 0x187: // R 0187 .l - client keep-alive packet (every 12 seconds) + if (RFIFOREST(fd) < 6) + return 0; + RFIFOSKIP(fd,6); + break; + + case 0x28d: // R 028d .l .l .24B - char rename request + if (RFIFOREST(fd) < 34) + return 0; + //not implemented + RFIFOSKIP(fd,34); + break; + case 0x2af8: // login as map-server if (RFIFOREST(fd) < 60) return 0; @@ -3738,13 +3713,7 @@ int parse_char(int fd) } break; - case 0x187: // R 0187 .l - client keep-alive packet (every 12 seconds) - if (RFIFOREST(fd) < 6) - return 0; - RFIFOSKIP(fd,6); - break; - - case 0x7530: // Athena info get + case 0x7530: // Athena info get { WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; @@ -3760,8 +3729,12 @@ int parse_char(int fd) return 0; } - case 0x7532: // disconnect(default also disconnect) - default: + case 0x7532: // disconnect request from login server + set_eof(fd); + return 0; + + default: // unknown packet received + ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); set_eof(fd); return 0; } @@ -4090,13 +4063,9 @@ int char_config_read(const char *cfgName) #endif } else if (strcmpi(w1, "char_txt") == 0) { strcpy(char_txt, w2); - } else if (strcmpi(w1, "backup_txt") == 0) { //By zanetheinsane - strcpy(backup_txt, w2); } else if (strcmpi(w1, "friends_txt") == 0) { //By davidsiaw strcpy(friends_txt, w2); #ifndef TXT_SQL_CONVERT - } else if (strcmpi(w1, "backup_txt_flag") == 0) { // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. By [Yor] - backup_txt_flag = config_switch(w2); } else if (strcmpi(w1, "max_connect_user") == 0) { max_connect_user = atoi(w2); if (max_connect_user < 0) @@ -4277,6 +4246,7 @@ int do_init(int argc, char **argv) mapindex_init(); //Needed here for the start-point reading. start_point.map = mapindex_name2id("new_zone01"); + char_config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]); char_lan_config_read((argc > 3) ? argv[3] : LAN_CONF_NAME); @@ -4349,9 +4319,7 @@ int do_init(int argc, char **argv) } char_fd = make_listen_bind(bind_ip, char_port); - char_log("The char-server is ready (Server is listening on the port %d)." RETCODE, char_port); - ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); return 0; diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 34883ca83..dd1935a6a 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -2,28 +2,26 @@ // For more information, see LICENCE in the main folder #include "../common/cbasetypes.h" -#include "../common/utils.h" -#include "../common/strlib.h" -#include "../common/showmsg.h" #include "../common/db.h" #include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/utils.h" -#include "itemdb.h" #include "inter.h" #include "int_guild.h" #include "int_homun.h" +#include "itemdb.h" #include "char.h" #include - #ifdef WIN32 #include #else #include -#include +#include #include #endif - #include #include #include @@ -33,13 +31,10 @@ #include // private declarations -#define CHAR_CONF_NAME "conf/char_athena.conf" +#define CHAR_CONF_NAME "conf/char_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" #define SQL_CONF_NAME "conf/inter_athena.conf" -#ifndef TXT_SQL_CONVERT -static struct dbt *char_db_; -#endif char char_db[256] = "char"; char scdata_db[256] = "sc_data"; char cart_db[256] = "cart_inventory"; @@ -61,10 +56,12 @@ char guild_storage_db[256] = "guild_storage"; char party_db[256] = "party"; char pet_db[256] = "pet"; char friend_db[256] = "friends"; -#ifdef TXT_SQL_CONVERT -int save_log = 0; //Have the logs be off by default when converting -#else -int save_log = 1; + +#ifndef TXT_SQL_CONVERT +static struct dbt *char_db_; + +char db_path[1024] = "db"; + int db_use_sqldbs; char login_db[256] = "login"; @@ -97,19 +94,30 @@ uint16 char_port = 6121; int char_maintenance = 0; int char_new = 1; int char_new_display = 0; + int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor] int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor] char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the requested name cannot be determined +#define TRIM_CHARS "\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] char char_name_letters[1024] = ""; // list of letters/symbols used to authorise or not a name of a character. by [Yor] -//The following are characters that are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] -#define TRIM_CHARS "\032\t\x0A\x0D " bool char_rename = true; + int char_per_account = 0; //Maximum charas per account (default unlimited) [Sirius] int char_del_level = 0; //From which level u can delete character [Lupus] int log_char = 1; // loggin char or not [devil] int log_inter = 1; // loggin inter or not [devil] +#ifdef TXT_SQL_CONVERT +int save_log = 0; //Have the logs be off by default when converting +#else +int save_log = 1; +#endif + +//These are used to aid the map server in identifying valid clients. [Skotlex] +static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID; +static int online_check = 1; //If one, it won't let players connect when their account is already registered online and will send the relevant map server a kick user request. [Skotlex] + // Advanced subnet check [LuzZza] struct _subnet { uint32 subnet; @@ -117,15 +125,8 @@ struct _subnet { uint32 char_ip; uint32 map_ip; } subnet[16]; - int subnet_count = 0; -char db_path[1024]="db"; - -//These are used to aid the map server in identifying valid clients. [Skotlex] -static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CHAR_ID; -static int online_check = 1; //If one, it won't let players connect when their account is already registered online and will send the relevant map server a kick user request. [Skotlex] - struct char_session_data{ int account_id, login_id1, login_id2, sex; int found_char[MAX_CHARS]; @@ -144,7 +145,7 @@ struct { int auth_fifo_pos = 0; struct mmo_charstatus char_dat; -int char_num,char_max; +int char_num, char_max; int max_connect_user = 0; int gm_allow_level = 99; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; @@ -168,7 +169,7 @@ struct fame_list taekwon_fame_list[MAX_FAME_LIST]; // other is char_id unsigned int save_flag = 0; -// start point (you can reset point on conf file) +// Initial position (it's possible to set it in conf file) struct point start_point = { 0, 53, 111 }; bool char_gm_read = false; @@ -1647,7 +1648,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd) j = 24; // offset - WFIFOHEAD(fd, j + found_num*108); + WFIFOHEAD(fd,j + found_num*108); // or 106(!) WFIFOW(fd,0) = 0x6b; memset(WFIFOP(fd,4), 0, 20); // unknown bytes for(i = 0; i < found_num; i++) @@ -3031,33 +3032,17 @@ int parse_char(int fd) return 0; } - while(RFIFOREST(fd) >= 2) { - cmd = RFIFOW(fd,0); - // crc32のスキップ用 - if( sd==NULL && // 未ログインor管理パケット - RFIFOREST(fd)>=4 && // 最低バイト数制限 & 0x7530,0x7532管理パケ除去 - RFIFOREST(fd)<=21 && // 最大バイト数制限 & サーバーログイン除去 - cmd!=0x20b && // md5通知パケット除去 - (RFIFOREST(fd)<6 || RFIFOW(fd,4)==0x65) ){ // 次に何かパケットが来てるなら、接続でないとだめ - RFIFOSKIP(fd,4); - cmd = RFIFOW(fd,0); - ShowDebug("parse_char : %d crc32 skipped\n",fd); - if(RFIFOREST(fd)==0) - return 0; - } + while(RFIFOREST(fd) >= 2) + { + //For use in packets that depend on an sd being present [Skotlex] + #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL) { RFIFOSKIP(fd,rest); return 0; } } -//For use in packets that depend on an sd being present [Skotlex] -#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL) { RFIFOSKIP(fd,rest); return 0; } } - - switch(cmd) { - case 0x20b: //20040622 encryption ragexe correspondence - if (RFIFOREST(fd) < 19) - return 0; - RFIFOSKIP(fd,19); - break; + cmd = RFIFOW(fd,0); + switch(cmd) + { case 0x65: // request to connect - ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOL(fd, 10)); + ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); if (RFIFOREST(fd) < 17) return 0; { @@ -3067,6 +3052,7 @@ int parse_char(int fd) RFIFOSKIP(fd,17); break; } + CREATE(session[fd]->session_data, struct char_session_data, 1); sd = (struct char_session_data*)session[fd]->session_data; sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server) @@ -3224,7 +3210,7 @@ int parse_char(int fd) //Send NEW auth packet [Kevin] if ((map_fd = server_fd[i]) < 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; memset(&server[i], 0, sizeof(struct mmo_map_server)); @@ -3235,18 +3221,17 @@ int parse_char(int fd) WFIFOSET(fd,3); break; } - { //Send auth ok to map server - WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); - WFIFOW(map_fd,0) = 0x2afd; - WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus); - WFIFOL(map_fd,4) = auth_fifo[auth_fifo_pos].account_id; - WFIFOL(map_fd,8) = auth_fifo[auth_fifo_pos].login_id1; - WFIFOL(map_fd,16) = auth_fifo[auth_fifo_pos].login_id2; - WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].connect_until_time; - memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus)); - WFIFOSET(map_fd, WFIFOW(map_fd,2)); - } - + //Send auth ok to map server + WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); + WFIFOW(map_fd,0) = 0x2afd; + WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus); + WFIFOL(map_fd,4) = auth_fifo[auth_fifo_pos].account_id; + WFIFOL(map_fd,8) = auth_fifo[auth_fifo_pos].login_id1; + WFIFOL(map_fd,16) = auth_fifo[auth_fifo_pos].login_id2; + WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].connect_until_time; + memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus)); + WFIFOSET(map_fd, WFIFOW(map_fd,2)); + set_char_online(i, auth_fifo[auth_fifo_pos].char_id, auth_fifo[auth_fifo_pos].account_id); auth_fifo_pos++; break; @@ -3293,13 +3278,15 @@ int parse_char(int fd) break; case 0x68: // delete char - FIFOSD_CHECK(46); + case 0x1fb: // 2004-04-19aSakexe+ langtype 12 char deletion packet + if (cmd == 0x68) FIFOSD_CHECK(46); + if (cmd == 0x1fb) FIFOSD_CHECK(56); { int cid = RFIFOL(fd,2); - WFIFOHEAD(fd,46); - ShowInfo(CL_RED" Request Char Deletion:"CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); memcpy(email, RFIFOP(fd,6), 40); - RFIFOSKIP(fd,46); + RFIFOSKIP(fd,RFIFOREST(fd)); // hack to make the other deletion packet work // Check if e-mail is correct if(strcmpi(email, sd->email) && //email does not matches and @@ -3307,9 +3294,10 @@ int parse_char(int fd) strcmp("a@a.com", sd->email) || //it is not default email, or (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default )) { //Fail - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; // 00 = Incorrect Email address - WFIFOSET(fd, 3); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; // 00 = Incorrect Email address + WFIFOSET(fd,3); break; } @@ -3322,6 +3310,7 @@ int parse_char(int fd) } } if (i == MAX_CHARS) { // Such a character does not exist in the account + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x70; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); @@ -3351,9 +3340,10 @@ int parse_char(int fd) //can't delete the char //either SQL error or can't delete by some CONFIG conditions //del fail - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); break; } if (char_pid != 0) @@ -3365,65 +3355,72 @@ int parse_char(int fd) } } /* Char successfully deleted.*/ + WFIFOHEAD(fd,2); WFIFOW(fd,0) = 0x6f; WFIFOSET(fd,2); } break; + case 0x187: // R 0187 .l - client keep-alive packet (every 12 seconds) + if (RFIFOREST(fd) < 6) + return 0; + RFIFOSKIP(fd,6); + break; + + case 0x28d: // R 028d .l .l .24B - char rename request + if (RFIFOREST(fd) < 34) + return 0; + //not implemented + RFIFOSKIP(fd,34); + break; + case 0x2af8: // login as map-server if (RFIFOREST(fd) < 60) return 0; { - char *l_user = RFIFOP(fd,2); - char *l_pass = RFIFOP(fd,26); - WFIFOHEAD(fd,4+5*GM_num); + char* l_user = RFIFOP(fd,2); + char* l_pass = RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - WFIFOW(fd,0) = 0x2af9; for(i = 0; i < MAX_MAP_SERVERS; i++) { if (server_fd[i] <= 0) break; } - if (i == MAX_MAP_SERVERS || - strcmp(l_user, userid) || - strcmp(l_pass, passwd)) { + if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; WFIFOB(fd,2) = 3; WFIFOSET(fd,3); - RFIFOSKIP(fd,60); } else { - int len; + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); + session[fd]->func_parse = parse_frommap; server_fd[i] = fd; - server[i].ip = ntohl(RFIFOL(fd, 54)); - server[i].port = ntohs(RFIFOW(fd, 58)); + server[i].ip = ntohl(RFIFOL(fd,54)); + server[i].port = ntohs(RFIFOW(fd,58)); server[i].users = 0; memset(server[i].map, 0, sizeof(server[i].map)); - RFIFOSKIP(fd,60); realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); char_mapif_init(fd); // send gm acccounts level to map-servers - len = 4; + WFIFOHEAD(fd,4+5*GM_num); WFIFOW(fd,0) = 0x2b15; for(i = 0; i < GM_num; i++) { - WFIFOL(fd,len) = gm_account[i].account_id; - WFIFOB(fd,len+4) = (unsigned char)gm_account[i].level; - len += 5; + WFIFOL(fd,4+5*i) = gm_account[i].account_id; + WFIFOB(fd,4+5*i+4) = (unsigned char)gm_account[i].level; } - WFIFOW(fd,2) = len; - WFIFOSET(fd,len); + WFIFOW(fd,2) = 4+5*GM_num; + WFIFOSET(fd,WFIFOW(fd,2)); } + + RFIFOSKIP(fd,60); } break; - case 0x187: // Alive? - if (RFIFOREST(fd) < 6) - return 0; - RFIFOSKIP(fd, 6); - break; - - case 0x7530: // Athena info get + case 0x7530: // Athena info get { WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; @@ -3439,12 +3436,17 @@ int parse_char(int fd) return 0; } - case 0x7532: // disconnect(default also disconnect) - default: + case 0x7532: // disconnect request from login server + set_eof(fd); + return 0; + + default: // unknown packet received + ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); set_eof(fd); return 0; } } + RFIFOFLUSH(fd); return 0; } @@ -4075,9 +4077,6 @@ int do_init(int argc, char **argv) } } - ShowInfo("open port %d.....\n",char_port); - char_fd = make_listen_bind(bind_ip, char_port); - add_timer_func_list(check_connect_login_server, "check_connect_login_server"); add_timer_func_list(send_users_tologin, "send_users_tologin"); add_timer_func_list(send_accounts_tologin, "send_accounts_tologin"); @@ -4128,6 +4127,9 @@ int do_init(int argc, char **argv) } ShowInfo("End of char server initilization function.\n"); + + ShowInfo("open port %d.....\n",char_port); + char_fd = make_listen_bind(bind_ip, char_port); ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); return 0; } diff --git a/src/common/socket.c b/src/common/socket.c index 87740ed65..221a0289b 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -1153,9 +1153,9 @@ uint32 str2ip(const char* ip_str) // Reorders bytes from network to little endian (Windows). // Neccessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls. -uint16 ntows(uint16 neshort) +uint16 ntows(uint16 netshort) { - return ((neshort & 0xFF) << 8) | ((neshort & 0xFF00) >> 8); + return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8); } #ifdef SEND_SHORTLIST diff --git a/src/map/clif.c b/src/map/clif.c index df5e16532..1ff295eac 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -7929,7 +7929,7 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd) (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04 (packet_ver > 9 && (battle_config.packet_ver_flag & 1<<(packet_ver-9)) == 0)) // version not allowed {// packet version rejected - ShowInfo("Rejected connection attempt, wrong packet version (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"', Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%s"CL_RESET"').\n", account_id, char_id, packet_ver, ip2str(session[fd]->client_addr, NULL)); + ShowInfo("Rejected connection attempt, forbidden packet version (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"', Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%s"CL_RESET"').\n", account_id, char_id, packet_ver, ip2str(session[fd]->client_addr, NULL)); WFIFOHEAD(fd,packet_len(0x6a)); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = 5; // Your Game's EXE file is not the latest version -- cgit v1.2.3-60-g2f50