From 288490094a7fe9167747dc78d416940759a31197 Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Tue, 5 Dec 2006 13:23:07 +0000 Subject: - Massive EOL normalization & 'svn:eol-style native' flag setting for all txt/conf/h/c files. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9410 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char_sql/inter.c | 1644 +++++++++++++++++++++++++------------------------- 1 file changed, 822 insertions(+), 822 deletions(-) (limited to 'src/char_sql/inter.c') diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index 5ce452717..64983cfc6 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -1,822 +1,822 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -// original code from athena -// SQL conversion by Jioh L. Jung - -#include -#include - -#include "char.h" -#include "../common/strlib.h" -#include "../common/showmsg.h" -#include "inter.h" -#include "int_party.h" -#include "int_guild.h" -#include "int_storage.h" -#include "int_pet.h" -#include "int_homun.h" //albator - -#define WISDATA_TTL (60*1000) // Wisデータの生存時間(60秒) -#define WISDELLIST_MAX 256 // Wisデータ削除リストの要素数 - - -MYSQL mysql_handle; -MYSQL_RES* sql_res ; -MYSQL_ROW sql_row ; -int sql_fields, sql_cnt; -char tmp_sql[65535]; - -MYSQL lmysql_handle; -MYSQL_RES* lsql_res ; -MYSQL_ROW lsql_row ; - -int char_server_port = 3306; -char char_server_ip[32] = "127.0.0.1"; -char char_server_id[32] = "ragnarok"; -char char_server_pw[32] = "ragnarok"; -char char_server_db[32] = "ragnarok"; -char default_codepage[32] = ""; //Feature by irmin. - -int login_server_port = 3306; -char login_server_ip[32] = "127.0.0.1"; -char login_server_id[32] = "ragnarok"; -char login_server_pw[32] = "ragnarok"; -char login_server_db[32] = "ragnarok"; - -#ifndef TXT_SQL_CONVERT - -static struct accreg *accreg_pt; -unsigned int party_share_level = 10; -char main_chat_nick[16] = "Main"; - -// sending packet list -// NOTE: This variable ain't used at all! And it's confusing.. where do I add that the length of packet 0x2b07 is 10? x.x [Skotlex] -int inter_send_packet_length[]={ - -1,-1,27,-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, - 35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, - 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, - 9, 9,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 11,-1, 7, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -// recv. packet list -int inter_recv_packet_length[]={ - -1,-1, 7,-1, -1,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f - 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f - -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f - -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f - 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48,14,-1, 6, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f - -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator] -}; - -struct WisData { - int id, fd, count,len; - unsigned long tick; - unsigned char src[24], dst[24], msg[512]; -}; -static struct dbt * wis_db = NULL; -static int wis_dellist[WISDELLIST_MAX], wis_delnum; - -int inter_sql_test (void); - -#endif //TXT_SQL_CONVERT -//-------------------------------------------------------- -// Save registry to sql -int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type){ - - int j; - char temp_str[64]; //Needs be twice the source to ensure it fits [Skotlex] - char temp_str2[512]; - if (account_id<=0) return 0; - reg->account_id=account_id; - reg->char_id = char_id; - - switch (type) { - case 3: //Char Reg - //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); - break; - case 2: //Account Reg - //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id); - break; - case 1: //Account2 Reg - ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); - return 0; - default: - ShowError("inter_accreg_tosql: Invalid type %d\n", type); - return 0; - - } - 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 (reg->reg_num<=0) return 0; - - for(j=0;jreg_num;j++){ - if(reg->reg[j].str != NULL){ - sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d','%s','%s')", - reg_db, type, type!=3?reg->account_id:0, type==3?reg->char_id:0, - jstrescapecpy(temp_str,reg->reg[j].str), jstrescapecpy(temp_str2,reg->reg[j].value)); - 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; -} -#ifndef TXT_SQL_CONVERT - -// Load account_reg from sql (type=2) -int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int type) -{ - int j=0; - if (reg==NULL) return 0; - memset(reg, 0, sizeof(struct accreg)); - reg->account_id=account_id; - reg->char_id=char_id; - - //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - switch (type) { - case 3: //char reg - sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, reg->char_id); - break; - case 2: //account reg - sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id); - break; - case 1: //account2 reg - ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); - return 0; - } - 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); - } - sql_res = mysql_store_result(&mysql_handle); - - if (sql_res) { - for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){ - strcpy(reg->reg[j].str, sql_row[0]); - strcpy(reg->reg[j].value, sql_row[1]); - } - mysql_free_result(sql_res); - } - reg->reg_num=j; - return 1; -} - -// Initialize -int inter_accreg_sql_init(void) -{ - CREATE(accreg_pt, struct accreg, 1); - return 0; - -} -#endif //TXT_SQL_CONVERT - -/*========================================== - * read config file - *------------------------------------------ - */ -static int inter_config_read(const char *cfgName) { - int i; - char line[1024], w1[1024], w2[1024]; - FILE *fp; - - fp=fopen(cfgName,"r"); - if(fp==NULL){ - ShowError("file not found: %s\n", cfgName); - return 1; - } - - ShowInfo("reading file %s...\n",cfgName); - - while(fgets(line, 1020, fp)){ - i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); - if(i!=2) - continue; - - if(strcmpi(w1,"char_server_ip")==0){ - strcpy(char_server_ip, w2); - ShowStatus ("set char_server_ip : %s\n",w2); - } - else if(strcmpi(w1,"char_server_port")==0){ - char_server_port=atoi(w2); - ShowStatus ("set char_server_port : %s\n",w2); - } - else if(strcmpi(w1,"char_server_id")==0){ - strcpy(char_server_id, w2); - ShowStatus ("set char_server_id : %s\n",w2); - } - else if(strcmpi(w1,"char_server_pw")==0){ - strcpy(char_server_pw, w2); - ShowStatus ("set char_server_pw : %s\n",w2); - } - else if(strcmpi(w1,"char_server_db")==0){ - strcpy(char_server_db, w2); - ShowStatus ("set char_server_db : %s\n",w2); - } - else if(strcmpi(w1,"default_codepage")==0){ - strcpy(default_codepage, w2); - ShowStatus ("set default_codepage : %s\n",w2); - } - //Logins information to be read from the inter_athena.conf - //for character deletion (checks email in the loginDB) - else if(strcmpi(w1,"login_server_ip")==0){ - strcpy(login_server_ip, w2); - ShowStatus ("set login_server_ip : %s\n",w2); - } - else if(strcmpi(w1,"login_server_port")==0){ - login_server_port=atoi(w2); - ShowStatus ("set login_server_port : %s\n",w2); - } - else if(strcmpi(w1,"login_server_id")==0){ - strcpy(login_server_id, w2); - ShowStatus ("set login_server_id : %s\n",w2); - } - else if(strcmpi(w1,"login_server_pw")==0){ - strcpy(login_server_pw, w2); - ShowStatus ("set login_server_pw : %s\n",w2); - } - else if(strcmpi(w1,"login_server_db")==0){ - strcpy(login_server_db, w2); - ShowStatus ("set login_server_db : %s\n",w2); - } -#ifndef TXT_SQL_CONVERT - else if(strcmpi(w1,"party_share_level")==0){ - party_share_level=(unsigned int)atof(w2); - } - else if(strcmpi(w1,"log_inter")==0){ - log_inter = atoi(w2); - } - else if(strcmpi(w1, "main_chat_nick")==0){ // Main chat nick [LuzZza] - strcpy(main_chat_nick, w2); // - } -#endif //TXT_SQL_CONVERT - else if(strcmpi(w1,"import")==0){ - inter_config_read(w2); - } - } - fclose(fp); - - ShowInfo ("done reading %s.\n", cfgName); - - return 0; -} -#ifndef TXT_SQL_CONVERT - -// Save interlog into sql -int inter_log(char *fmt,...) -{ - char str[255]; - char temp_str[510]; //Needs be twice as long as str[] //Skotlex - va_list ap; - va_start(ap,fmt); - - vsprintf(str,fmt,ap); - sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str)); - 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); - } - - va_end(ap); - return 0; -} - -/*====================================================== - * Does a mysql_ping to all connection handles. [Skotlex] - *------------------------------------------------------ - */ -int inter_sql_ping(int tid, unsigned int tick, int id, int data) -{ - ShowInfo("Pinging SQL server to keep connection alive...\n"); - mysql_ping(&mysql_handle); - if(char_gm_read) - mysql_ping(&lmysql_handle); - return 0; -} -#endif //TXT_SQL_CONVERT - -// initialize -int inter_init_sql(const char *file) -{ - //int i; - - ShowInfo ("interserver initialize...\n"); - inter_config_read(file); - - //DB connection initialized - mysql_init(&mysql_handle); - ShowInfo("Connect Character DB server.... (Character Server)\n"); - if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, - char_server_db ,char_server_port, (char *)NULL, 0)) { - //pointer check - ShowFatalError("%s\n",mysql_error(&mysql_handle)); - exit(1); - } -#ifndef TXT_SQL_CONVERT - else if (inter_sql_test()) { - ShowStatus("Connect Success! (Character Server)\n"); - } - - if(char_gm_read) { - mysql_init(&lmysql_handle); - ShowInfo("Connect Character DB server.... (login server)\n"); - if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, - login_server_db ,login_server_port, (char *)NULL, 0)) { - //pointer check - ShowFatalError("%s\n",mysql_error(&lmysql_handle)); - exit(1); - }else { - ShowStatus ("Connect Success! (Login Server)\n"); - } - } -#endif //TXT_SQL_CONVERT - if(strlen(default_codepage) > 0 ) { - sprintf( tmp_sql, "SET NAMES %s", default_codepage ); - 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); - } -#ifndef TXT_SQL_CONVERT - if(char_gm_read) - if (mysql_query(&lmysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } -#endif //TXT_SQL_CONVERT - } - -#ifndef TXT_SQL_CONVERT - wis_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); - inter_guild_sql_init(); - inter_storage_sql_init(); - inter_party_sql_init(); - inter_pet_sql_init(); - inter_homunculus_sql_init(); // albator - inter_accreg_sql_init(); - - if (connection_ping_interval) { - add_timer_func_list(inter_sql_ping, "inter_sql_ping"); - add_timer_interval(gettick()+connection_ping_interval*60*60*1000, - inter_sql_ping, 0, 0, connection_ping_interval*60*60*1000); - } -#endif //TXT_SQL_CONVERT - return 0; -} -#ifndef TXT_SQL_CONVERT - -int inter_sql_test (void) -{ - const char fields[][24] = { - "father", // version 1363 - "fame", // version 1491 - }; - char buf[1024] = ""; - int i; - - sprintf(tmp_sql, "EXPLAIN `%s`",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); - } - sql_res = mysql_store_result(&mysql_handle); - // store DB fields - if (sql_res) { - while((sql_row = mysql_fetch_row(sql_res))) { - strcat (buf, sql_row[0]); - strcat (buf, " "); - } - } - - // check DB strings - for (i = 0; i < (int)(sizeof(fields) / sizeof(fields[0])); i++) { - if(!strstr(buf, fields[i])) { - ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db); - exit(1); - } - } - - mysql_free_result(sql_res); - - return 1; -} - -// finalize -void inter_final(void) { - wis_db->destroy(wis_db, NULL); - - inter_guild_sql_final(); - inter_storage_sql_final(); - inter_party_sql_final(); - inter_pet_sql_final(); - inter_homunculus_sql_final(); //[orn] - - if (accreg_pt) aFree(accreg_pt); - return; -} - -int inter_mapif_init(int fd) { - inter_guild_mapif_init(fd); - - return 0; -} - - -//-------------------------------------------------------- - -// GM message sending -int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) { - unsigned char buf[2048]; - - if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex] - WBUFW(buf, 0) = 0x3800; - WBUFW(buf, 2) = len; - WBUFL(buf, 4) = color; - memcpy(WBUFP(buf, 8), mes, len-8); - mapif_sendallwos(sfd, buf, len); - return 0; -} - -// Wis sending -int mapif_wis_message(struct WisData *wd) { - unsigned char buf[2048]; - if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex] - - WBUFW(buf, 0) = 0x3801; - WBUFW(buf, 2) = 56 +wd->len; - WBUFL(buf, 4) = wd->id; - memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH); - memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH); - memcpy(WBUFP(buf,56), wd->msg, wd->len); - wd->count = mapif_sendall(buf,WBUFW(buf,2)); - - return 0; -} -// Wis sending result -int mapif_wis_end(struct WisData *wd,int flag) -{ - unsigned char buf[27]; - - WBUFW(buf, 0)=0x3802; - memcpy(WBUFP(buf, 2),wd->src,24); - WBUFB(buf,26)=flag; - mapif_send(wd->fd,buf,27); -// printf("inter server wis_end %d\n",flag); - return 0; -} - -int mapif_account_reg(int fd,unsigned char *src) -{ -// unsigned char buf[WBUFW(src,2)]; <- Hey, can this really be done? [Skotlex] - unsigned char *buf = aCalloc(1,WBUFW(src,2)); // [Lance] - Skot... Dynamic allocation is better :D - memcpy(WBUFP(buf,0),src,WBUFW(src,2)); - WBUFW(buf, 0)=0x3804; - mapif_sendallwos(fd, buf, WBUFW(buf,2)); - aFree(buf); - return 0; -} - -// Send the requested account_reg -int mapif_account_reg_reply(int fd,int account_id,int char_id, int type) -{ - struct accreg *reg=accreg_pt; - WFIFOHEAD(fd, 13 + 5000); - inter_accreg_fromsql(account_id,char_id,reg,type); - - WFIFOW(fd,0)=0x3804; - WFIFOL(fd,4)=account_id; - WFIFOL(fd,8)=char_id; - WFIFOB(fd,12)=type; - if(reg->reg_num==0){ - WFIFOW(fd,2)=13; - }else{ - int i,p; - for (p=13,i = 0; i < reg->reg_num && p < 5000; i++) { - p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place. - p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].value)+1; - } - WFIFOW(fd,2)=p; - if (p>= 5000) - ShowWarning("Too many acc regs for %d:%d, not all values were loaded.\n", account_id, char_id); - } - WFIFOSET(fd,WFIFOW(fd,2)); - return 0; -} - -int mapif_send_gmaccounts() -{ - int i, len = 4; - unsigned char buf[32000]; - - // forward the gm accounts to the map server - len = 4; - WBUFW(buf,0) = 0x2b15; - - for(i = 0; i < GM_num; i++) { - WBUFL(buf, len) = gm_account[i].account_id; - WBUFB(buf, len+4) = (unsigned char)gm_account[i].level; - len += 5; - } - WBUFW(buf, 2) = len; - mapif_sendall(buf, len); - - return 0; -} - -//Sends to map server the current max Account/Char id [Skotlex] -void mapif_send_maxid(int account_id, int char_id) -{ - unsigned char buf[12]; - - WBUFW(buf,0) = 0x2b07; - WBUFL(buf,2) = account_id; - WBUFL(buf,6) = char_id; - mapif_sendall(buf, 10); -} - -//Request to kick char from a certain map server. [Skotlex] -int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason) -{ - if (fd >= 0) - { - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b1f; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = reason; - WFIFOSET(fd,7); - return 0; - } - return -1; -} - -//-------------------------------------------------------- - -// Existence check of WISP data -int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap) { - unsigned long tick; - struct WisData *wd = (struct WisData *)data; - tick = va_arg(ap, unsigned long); - - if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX) - wis_dellist[wis_delnum++] = wd->id; - - return 0; -} - -int check_ttl_wisdata(void) { - unsigned long tick = gettick(); - int i; - - do { - wis_delnum = 0; - wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick); - for(i = 0; i < wis_delnum; i++) { - struct WisData *wd = idb_get(wis_db, wis_dellist[i]); - ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst); - // removed. not send information after a timeout. Just no answer for the player - //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - idb_remove(wis_db, wd->id); - } - } while(wis_delnum >= WISDELLIST_MAX); - - return 0; -} - -//-------------------------------------------------------- - -// GM message sending -int mapif_parse_GMmessage(int fd) -{ - RFIFOHEAD(fd); - mapif_GMmessage(RFIFOP(fd, 8), RFIFOW(fd, 2), RFIFOL(fd, 4), fd); - return 0; -} - - -// Wisp/page request to send -int mapif_parse_WisRequest(int fd) { - struct WisData* wd; - static int wisid = 0; - char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex] - RFIFOHEAD(fd); - if ( fd <= 0 ) {return 0;} // check if we have a valid fd - - if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { - ShowWarning("inter: Wis message size too long.\n"); - return 0; - } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... - ShowError("inter: Wis message doesn't exist.\n"); - return 0; - } - memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] - name[NAME_LENGTH-1]= '\0'; - - sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'", - char_db, jstrescapecpy(t_name, name)); - 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); - } - sql_res = mysql_store_result(&mysql_handle); - - // search if character exists before to ask all map-servers - if (!(sql_row = mysql_fetch_row(sql_res))) { - unsigned char buf[27]; - WBUFW(buf, 0) = 0x3802; - memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); - WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(fd, buf, 27); - // Character exists. So, ask all map-servers - } else { - // to be sure of the correct name, rewrite it - memset(name, 0, NAME_LENGTH); - strncpy(name, sql_row[0], NAME_LENGTH); - // if source is destination, don't ask other servers. - if (strcmp((char*)RFIFOP(fd,4),name) == 0) { - unsigned char buf[27]; - WBUFW(buf, 0) = 0x3802; - memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); - WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - mapif_send(fd, buf, 27); - } else { - - CREATE(wd, struct WisData, 1); - - // Whether the failure of previous wisp/page transmission (timeout) - check_ttl_wisdata(); - - wd->id = ++wisid; - wd->fd = fd; - wd->len= RFIFOW(fd,2)-52; - memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); - memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); - memcpy(wd->msg, RFIFOP(fd,52), wd->len); - wd->tick = gettick(); - idb_put(wis_db, wd->id, wd); - mapif_wis_message(wd); - } - } - - //Freeing ... O.o - if(sql_res){ - mysql_free_result(sql_res); - } - - return 0; -} - - -// Wisp/page transmission result -int mapif_parse_WisReply(int fd) { - int id, flag; - struct WisData *wd; - RFIFOHEAD(fd); - id = RFIFOL(fd,2); - flag = RFIFOB(fd,6); - wd = idb_get(wis_db, id); - if (wd == NULL) - return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server - - if ((--wd->count) <= 0 || flag != 1) { - mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - idb_remove(wis_db, id); - } - - return 0; -} - -// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers) -int mapif_parse_WisToGM(int fd) { - unsigned char buf[2048]; // 0x3003/0x3803 .w .24B .w .?B - RFIFOHEAD(fd); - ShowDebug("Sent packet back!\n"); - memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); - WBUFW(buf, 0) = 0x3803; - mapif_sendall(buf, RFIFOW(fd,2)); - - return 0; -} - -// Save account_reg into sql (type=2) -int mapif_parse_Registry(int fd) -{ - int j,p,len, max; - struct accreg *reg=accreg_pt; - RFIFOHEAD(fd); - memset(accreg_pt,0,sizeof(struct accreg)); - switch (RFIFOB(fd, 12)) { - case 3: //Character registry - max = GLOBAL_REG_NUM; - break; - case 2: //Account Registry - max = ACCOUNT_REG_NUM; - break; - case 1: //Account2 registry, must be sent over to login server. - return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4); - default: - return 1; - } - for(j=0,p=13;jreg[j].str,&len); - reg->reg[j].str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf(RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len); - reg->reg[j].value[len]='\0'; - p +=len+1; - } - reg->reg_num=j; - - inter_accreg_tosql(RFIFOL(fd,4),RFIFOL(fd,8),reg, RFIFOB(fd,12)); - mapif_account_reg(fd,RFIFOP(fd,0)); // Send updated accounts to other map servers. - return 0; -} - -// Request the value of all registries. -int mapif_parse_RegistryRequest(int fd) -{ - RFIFOHEAD(fd); - //Load Char Registry - if (RFIFOB(fd,12)) - mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3); - //Load Account Registry - if (RFIFOB(fd,11)) - mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2); - //Ask Login Server for Account2 values. - if (RFIFOB(fd,10)) - request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)-2); - return 1; -} - -//-------------------------------------------------------- -int inter_parse_frommap(int fd) -{ - int cmd; - int len=0; - RFIFOHEAD(fd); - cmd=RFIFOW(fd,0); - // inter鯖管轄かを調べ - if(cmd < 0x3000 || cmd >= 0x3000 + (sizeof(inter_recv_packet_length)/ - sizeof(inter_recv_packet_length[0]) ) ) - return 0; - - if (inter_recv_packet_length[cmd-0x3000] == 0) //This is necessary, because otherwise we return 2 and the char server will just hang waiting for packets! [Skotlex] - return 0; - - // パケット長を調べる - if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0) - return 2; - - switch(cmd){ - case 0x3000: mapif_parse_GMmessage(fd); break; - case 0x3001: mapif_parse_WisRequest(fd); break; - case 0x3002: mapif_parse_WisReply(fd); break; - case 0x3003: mapif_parse_WisToGM(fd); break; - case 0x3004: mapif_parse_Registry(fd); break; - case 0x3005: mapif_parse_RegistryRequest(fd); break; - default: - if(inter_party_parse_frommap(fd)) - break; - if(inter_guild_parse_frommap(fd)) - break; - if(inter_storage_parse_frommap(fd)) - break; - if(inter_pet_parse_frommap(fd)) - break; - if(inter_homunculus_parse_frommap(fd)) //albator - break; - return 0; - } - - RFIFOSKIP(fd, len); - return 1; -} - -// RFIFO check -int inter_check_length(int fd, int length) -{ - RFIFOHEAD(fd); - if(length==-1){ // v-len packet - if(RFIFOREST(fd)<4) // packet not yet - return 0; - length = RFIFOW(fd, 2); - } - - if((int)RFIFOREST(fd) < length) // packet not yet - return 0; - - return length; -} -#endif //TXT_SQL_CONVERT +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +// original code from athena +// SQL conversion by Jioh L. Jung + +#include +#include + +#include "char.h" +#include "../common/strlib.h" +#include "../common/showmsg.h" +#include "inter.h" +#include "int_party.h" +#include "int_guild.h" +#include "int_storage.h" +#include "int_pet.h" +#include "int_homun.h" //albator + +#define WISDATA_TTL (60*1000) // Wisデータの生存時間(60秒) +#define WISDELLIST_MAX 256 // Wisデータ削除リストの要素数 + + +MYSQL mysql_handle; +MYSQL_RES* sql_res ; +MYSQL_ROW sql_row ; +int sql_fields, sql_cnt; +char tmp_sql[65535]; + +MYSQL lmysql_handle; +MYSQL_RES* lsql_res ; +MYSQL_ROW lsql_row ; + +int char_server_port = 3306; +char char_server_ip[32] = "127.0.0.1"; +char char_server_id[32] = "ragnarok"; +char char_server_pw[32] = "ragnarok"; +char char_server_db[32] = "ragnarok"; +char default_codepage[32] = ""; //Feature by irmin. + +int login_server_port = 3306; +char login_server_ip[32] = "127.0.0.1"; +char login_server_id[32] = "ragnarok"; +char login_server_pw[32] = "ragnarok"; +char login_server_db[32] = "ragnarok"; + +#ifndef TXT_SQL_CONVERT + +static struct accreg *accreg_pt; +unsigned int party_share_level = 10; +char main_chat_nick[16] = "Main"; + +// sending packet list +// NOTE: This variable ain't used at all! And it's confusing.. where do I add that the length of packet 0x2b07 is 10? x.x [Skotlex] +int inter_send_packet_length[]={ + -1,-1,27,-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, + 35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, + 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, + 9, 9,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11,-1, 7, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +// recv. packet list +int inter_recv_packet_length[]={ + -1,-1, 7,-1, -1,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f + 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f + -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f + -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f + 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48,14,-1, 6, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f + -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator] +}; + +struct WisData { + int id, fd, count,len; + unsigned long tick; + unsigned char src[24], dst[24], msg[512]; +}; +static struct dbt * wis_db = NULL; +static int wis_dellist[WISDELLIST_MAX], wis_delnum; + +int inter_sql_test (void); + +#endif //TXT_SQL_CONVERT +//-------------------------------------------------------- +// Save registry to sql +int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type){ + + int j; + char temp_str[64]; //Needs be twice the source to ensure it fits [Skotlex] + char temp_str2[512]; + if (account_id<=0) return 0; + reg->account_id=account_id; + reg->char_id = char_id; + + switch (type) { + case 3: //Char Reg + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); + break; + case 2: //Account Reg + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id); + break; + case 1: //Account2 Reg + ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); + return 0; + default: + ShowError("inter_accreg_tosql: Invalid type %d\n", type); + return 0; + + } + 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 (reg->reg_num<=0) return 0; + + for(j=0;jreg_num;j++){ + if(reg->reg[j].str != NULL){ + sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d','%s','%s')", + reg_db, type, type!=3?reg->account_id:0, type==3?reg->char_id:0, + jstrescapecpy(temp_str,reg->reg[j].str), jstrescapecpy(temp_str2,reg->reg[j].value)); + 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; +} +#ifndef TXT_SQL_CONVERT + +// Load account_reg from sql (type=2) +int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int type) +{ + int j=0; + if (reg==NULL) return 0; + memset(reg, 0, sizeof(struct accreg)); + reg->account_id=account_id; + reg->char_id=char_id; + + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) + switch (type) { + case 3: //char reg + sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, reg->char_id); + break; + case 2: //account reg + sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id); + break; + case 1: //account2 reg + ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); + return 0; + } + 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); + } + sql_res = mysql_store_result(&mysql_handle); + + if (sql_res) { + for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){ + strcpy(reg->reg[j].str, sql_row[0]); + strcpy(reg->reg[j].value, sql_row[1]); + } + mysql_free_result(sql_res); + } + reg->reg_num=j; + return 1; +} + +// Initialize +int inter_accreg_sql_init(void) +{ + CREATE(accreg_pt, struct accreg, 1); + return 0; + +} +#endif //TXT_SQL_CONVERT + +/*========================================== + * read config file + *------------------------------------------ + */ +static int inter_config_read(const char *cfgName) { + int i; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("file not found: %s\n", cfgName); + return 1; + } + + ShowInfo("reading file %s...\n",cfgName); + + while(fgets(line, 1020, fp)){ + i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); + if(i!=2) + continue; + + if(strcmpi(w1,"char_server_ip")==0){ + strcpy(char_server_ip, w2); + ShowStatus ("set char_server_ip : %s\n",w2); + } + else if(strcmpi(w1,"char_server_port")==0){ + char_server_port=atoi(w2); + ShowStatus ("set char_server_port : %s\n",w2); + } + else if(strcmpi(w1,"char_server_id")==0){ + strcpy(char_server_id, w2); + ShowStatus ("set char_server_id : %s\n",w2); + } + else if(strcmpi(w1,"char_server_pw")==0){ + strcpy(char_server_pw, w2); + ShowStatus ("set char_server_pw : %s\n",w2); + } + else if(strcmpi(w1,"char_server_db")==0){ + strcpy(char_server_db, w2); + ShowStatus ("set char_server_db : %s\n",w2); + } + else if(strcmpi(w1,"default_codepage")==0){ + strcpy(default_codepage, w2); + ShowStatus ("set default_codepage : %s\n",w2); + } + //Logins information to be read from the inter_athena.conf + //for character deletion (checks email in the loginDB) + else if(strcmpi(w1,"login_server_ip")==0){ + strcpy(login_server_ip, w2); + ShowStatus ("set login_server_ip : %s\n",w2); + } + else if(strcmpi(w1,"login_server_port")==0){ + login_server_port=atoi(w2); + ShowStatus ("set login_server_port : %s\n",w2); + } + else if(strcmpi(w1,"login_server_id")==0){ + strcpy(login_server_id, w2); + ShowStatus ("set login_server_id : %s\n",w2); + } + else if(strcmpi(w1,"login_server_pw")==0){ + strcpy(login_server_pw, w2); + ShowStatus ("set login_server_pw : %s\n",w2); + } + else if(strcmpi(w1,"login_server_db")==0){ + strcpy(login_server_db, w2); + ShowStatus ("set login_server_db : %s\n",w2); + } +#ifndef TXT_SQL_CONVERT + else if(strcmpi(w1,"party_share_level")==0){ + party_share_level=(unsigned int)atof(w2); + } + else if(strcmpi(w1,"log_inter")==0){ + log_inter = atoi(w2); + } + else if(strcmpi(w1, "main_chat_nick")==0){ // Main chat nick [LuzZza] + strcpy(main_chat_nick, w2); // + } +#endif //TXT_SQL_CONVERT + else if(strcmpi(w1,"import")==0){ + inter_config_read(w2); + } + } + fclose(fp); + + ShowInfo ("done reading %s.\n", cfgName); + + return 0; +} +#ifndef TXT_SQL_CONVERT + +// Save interlog into sql +int inter_log(char *fmt,...) +{ + char str[255]; + char temp_str[510]; //Needs be twice as long as str[] //Skotlex + va_list ap; + va_start(ap,fmt); + + vsprintf(str,fmt,ap); + sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str)); + 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); + } + + va_end(ap); + return 0; +} + +/*====================================================== + * Does a mysql_ping to all connection handles. [Skotlex] + *------------------------------------------------------ + */ +int inter_sql_ping(int tid, unsigned int tick, int id, int data) +{ + ShowInfo("Pinging SQL server to keep connection alive...\n"); + mysql_ping(&mysql_handle); + if(char_gm_read) + mysql_ping(&lmysql_handle); + return 0; +} +#endif //TXT_SQL_CONVERT + +// initialize +int inter_init_sql(const char *file) +{ + //int i; + + ShowInfo ("interserver initialize...\n"); + inter_config_read(file); + + //DB connection initialized + mysql_init(&mysql_handle); + ShowInfo("Connect Character DB server.... (Character Server)\n"); + if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, + char_server_db ,char_server_port, (char *)NULL, 0)) { + //pointer check + ShowFatalError("%s\n",mysql_error(&mysql_handle)); + exit(1); + } +#ifndef TXT_SQL_CONVERT + else if (inter_sql_test()) { + ShowStatus("Connect Success! (Character Server)\n"); + } + + if(char_gm_read) { + mysql_init(&lmysql_handle); + ShowInfo("Connect Character DB server.... (login server)\n"); + if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, + login_server_db ,login_server_port, (char *)NULL, 0)) { + //pointer check + ShowFatalError("%s\n",mysql_error(&lmysql_handle)); + exit(1); + }else { + ShowStatus ("Connect Success! (Login Server)\n"); + } + } +#endif //TXT_SQL_CONVERT + if(strlen(default_codepage) > 0 ) { + sprintf( tmp_sql, "SET NAMES %s", default_codepage ); + 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); + } +#ifndef TXT_SQL_CONVERT + if(char_gm_read) + if (mysql_query(&lmysql_handle, tmp_sql)) { + ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } +#endif //TXT_SQL_CONVERT + } + +#ifndef TXT_SQL_CONVERT + wis_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); + inter_guild_sql_init(); + inter_storage_sql_init(); + inter_party_sql_init(); + inter_pet_sql_init(); + inter_homunculus_sql_init(); // albator + inter_accreg_sql_init(); + + if (connection_ping_interval) { + add_timer_func_list(inter_sql_ping, "inter_sql_ping"); + add_timer_interval(gettick()+connection_ping_interval*60*60*1000, + inter_sql_ping, 0, 0, connection_ping_interval*60*60*1000); + } +#endif //TXT_SQL_CONVERT + return 0; +} +#ifndef TXT_SQL_CONVERT + +int inter_sql_test (void) +{ + const char fields[][24] = { + "father", // version 1363 + "fame", // version 1491 + }; + char buf[1024] = ""; + int i; + + sprintf(tmp_sql, "EXPLAIN `%s`",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); + } + sql_res = mysql_store_result(&mysql_handle); + // store DB fields + if (sql_res) { + while((sql_row = mysql_fetch_row(sql_res))) { + strcat (buf, sql_row[0]); + strcat (buf, " "); + } + } + + // check DB strings + for (i = 0; i < (int)(sizeof(fields) / sizeof(fields[0])); i++) { + if(!strstr(buf, fields[i])) { + ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db); + exit(1); + } + } + + mysql_free_result(sql_res); + + return 1; +} + +// finalize +void inter_final(void) { + wis_db->destroy(wis_db, NULL); + + inter_guild_sql_final(); + inter_storage_sql_final(); + inter_party_sql_final(); + inter_pet_sql_final(); + inter_homunculus_sql_final(); //[orn] + + if (accreg_pt) aFree(accreg_pt); + return; +} + +int inter_mapif_init(int fd) { + inter_guild_mapif_init(fd); + + return 0; +} + + +//-------------------------------------------------------- + +// GM message sending +int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) { + unsigned char buf[2048]; + + if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex] + WBUFW(buf, 0) = 0x3800; + WBUFW(buf, 2) = len; + WBUFL(buf, 4) = color; + memcpy(WBUFP(buf, 8), mes, len-8); + mapif_sendallwos(sfd, buf, len); + return 0; +} + +// Wis sending +int mapif_wis_message(struct WisData *wd) { + unsigned char buf[2048]; + if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex] + + WBUFW(buf, 0) = 0x3801; + WBUFW(buf, 2) = 56 +wd->len; + WBUFL(buf, 4) = wd->id; + memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH); + memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH); + memcpy(WBUFP(buf,56), wd->msg, wd->len); + wd->count = mapif_sendall(buf,WBUFW(buf,2)); + + return 0; +} +// Wis sending result +int mapif_wis_end(struct WisData *wd,int flag) +{ + unsigned char buf[27]; + + WBUFW(buf, 0)=0x3802; + memcpy(WBUFP(buf, 2),wd->src,24); + WBUFB(buf,26)=flag; + mapif_send(wd->fd,buf,27); +// printf("inter server wis_end %d\n",flag); + return 0; +} + +int mapif_account_reg(int fd,unsigned char *src) +{ +// unsigned char buf[WBUFW(src,2)]; <- Hey, can this really be done? [Skotlex] + unsigned char *buf = aCalloc(1,WBUFW(src,2)); // [Lance] - Skot... Dynamic allocation is better :D + memcpy(WBUFP(buf,0),src,WBUFW(src,2)); + WBUFW(buf, 0)=0x3804; + mapif_sendallwos(fd, buf, WBUFW(buf,2)); + aFree(buf); + return 0; +} + +// Send the requested account_reg +int mapif_account_reg_reply(int fd,int account_id,int char_id, int type) +{ + struct accreg *reg=accreg_pt; + WFIFOHEAD(fd, 13 + 5000); + inter_accreg_fromsql(account_id,char_id,reg,type); + + WFIFOW(fd,0)=0x3804; + WFIFOL(fd,4)=account_id; + WFIFOL(fd,8)=char_id; + WFIFOB(fd,12)=type; + if(reg->reg_num==0){ + WFIFOW(fd,2)=13; + }else{ + int i,p; + for (p=13,i = 0; i < reg->reg_num && p < 5000; i++) { + p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place. + p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].value)+1; + } + WFIFOW(fd,2)=p; + if (p>= 5000) + ShowWarning("Too many acc regs for %d:%d, not all values were loaded.\n", account_id, char_id); + } + WFIFOSET(fd,WFIFOW(fd,2)); + return 0; +} + +int mapif_send_gmaccounts() +{ + int i, len = 4; + unsigned char buf[32000]; + + // forward the gm accounts to the map server + len = 4; + WBUFW(buf,0) = 0x2b15; + + for(i = 0; i < GM_num; i++) { + WBUFL(buf, len) = gm_account[i].account_id; + WBUFB(buf, len+4) = (unsigned char)gm_account[i].level; + len += 5; + } + WBUFW(buf, 2) = len; + mapif_sendall(buf, len); + + return 0; +} + +//Sends to map server the current max Account/Char id [Skotlex] +void mapif_send_maxid(int account_id, int char_id) +{ + unsigned char buf[12]; + + WBUFW(buf,0) = 0x2b07; + WBUFL(buf,2) = account_id; + WBUFL(buf,6) = char_id; + mapif_sendall(buf, 10); +} + +//Request to kick char from a certain map server. [Skotlex] +int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason) +{ + if (fd >= 0) + { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b1f; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = reason; + WFIFOSET(fd,7); + return 0; + } + return -1; +} + +//-------------------------------------------------------- + +// Existence check of WISP data +int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap) { + unsigned long tick; + struct WisData *wd = (struct WisData *)data; + tick = va_arg(ap, unsigned long); + + if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX) + wis_dellist[wis_delnum++] = wd->id; + + return 0; +} + +int check_ttl_wisdata(void) { + unsigned long tick = gettick(); + int i; + + do { + wis_delnum = 0; + wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick); + for(i = 0; i < wis_delnum; i++) { + struct WisData *wd = idb_get(wis_db, wis_dellist[i]); + ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst); + // removed. not send information after a timeout. Just no answer for the player + //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + idb_remove(wis_db, wd->id); + } + } while(wis_delnum >= WISDELLIST_MAX); + + return 0; +} + +//-------------------------------------------------------- + +// GM message sending +int mapif_parse_GMmessage(int fd) +{ + RFIFOHEAD(fd); + mapif_GMmessage(RFIFOP(fd, 8), RFIFOW(fd, 2), RFIFOL(fd, 4), fd); + return 0; +} + + +// Wisp/page request to send +int mapif_parse_WisRequest(int fd) { + struct WisData* wd; + static int wisid = 0; + char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex] + RFIFOHEAD(fd); + if ( fd <= 0 ) {return 0;} // check if we have a valid fd + + if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { + ShowWarning("inter: Wis message size too long.\n"); + return 0; + } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... + ShowError("inter: Wis message doesn't exist.\n"); + return 0; + } + memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] + name[NAME_LENGTH-1]= '\0'; + + sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'", + char_db, jstrescapecpy(t_name, name)); + 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); + } + sql_res = mysql_store_result(&mysql_handle); + + // search if character exists before to ask all map-servers + if (!(sql_row = mysql_fetch_row(sql_res))) { + unsigned char buf[27]; + WBUFW(buf, 0) = 0x3802; + memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); + WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + mapif_send(fd, buf, 27); + // Character exists. So, ask all map-servers + } else { + // to be sure of the correct name, rewrite it + memset(name, 0, NAME_LENGTH); + strncpy(name, sql_row[0], NAME_LENGTH); + // if source is destination, don't ask other servers. + if (strcmp((char*)RFIFOP(fd,4),name) == 0) { + unsigned char buf[27]; + WBUFW(buf, 0) = 0x3802; + memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); + WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + mapif_send(fd, buf, 27); + } else { + + CREATE(wd, struct WisData, 1); + + // Whether the failure of previous wisp/page transmission (timeout) + check_ttl_wisdata(); + + wd->id = ++wisid; + wd->fd = fd; + wd->len= RFIFOW(fd,2)-52; + memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); + memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); + memcpy(wd->msg, RFIFOP(fd,52), wd->len); + wd->tick = gettick(); + idb_put(wis_db, wd->id, wd); + mapif_wis_message(wd); + } + } + + //Freeing ... O.o + if(sql_res){ + mysql_free_result(sql_res); + } + + return 0; +} + + +// Wisp/page transmission result +int mapif_parse_WisReply(int fd) { + int id, flag; + struct WisData *wd; + RFIFOHEAD(fd); + id = RFIFOL(fd,2); + flag = RFIFOB(fd,6); + wd = idb_get(wis_db, id); + if (wd == NULL) + return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server + + if ((--wd->count) <= 0 || flag != 1) { + mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + idb_remove(wis_db, id); + } + + return 0; +} + +// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers) +int mapif_parse_WisToGM(int fd) { + unsigned char buf[2048]; // 0x3003/0x3803 .w .24B .w .?B + RFIFOHEAD(fd); + ShowDebug("Sent packet back!\n"); + memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); + WBUFW(buf, 0) = 0x3803; + mapif_sendall(buf, RFIFOW(fd,2)); + + return 0; +} + +// Save account_reg into sql (type=2) +int mapif_parse_Registry(int fd) +{ + int j,p,len, max; + struct accreg *reg=accreg_pt; + RFIFOHEAD(fd); + memset(accreg_pt,0,sizeof(struct accreg)); + switch (RFIFOB(fd, 12)) { + case 3: //Character registry + max = GLOBAL_REG_NUM; + break; + case 2: //Account Registry + max = ACCOUNT_REG_NUM; + break; + case 1: //Account2 registry, must be sent over to login server. + return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4); + default: + return 1; + } + for(j=0,p=13;jreg[j].str,&len); + reg->reg[j].str[len]='\0'; + p +=len+1; //+1 to skip the '\0' between strings. + sscanf(RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len); + reg->reg[j].value[len]='\0'; + p +=len+1; + } + reg->reg_num=j; + + inter_accreg_tosql(RFIFOL(fd,4),RFIFOL(fd,8),reg, RFIFOB(fd,12)); + mapif_account_reg(fd,RFIFOP(fd,0)); // Send updated accounts to other map servers. + return 0; +} + +// Request the value of all registries. +int mapif_parse_RegistryRequest(int fd) +{ + RFIFOHEAD(fd); + //Load Char Registry + if (RFIFOB(fd,12)) + mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3); + //Load Account Registry + if (RFIFOB(fd,11)) + mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2); + //Ask Login Server for Account2 values. + if (RFIFOB(fd,10)) + request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)-2); + return 1; +} + +//-------------------------------------------------------- +int inter_parse_frommap(int fd) +{ + int cmd; + int len=0; + RFIFOHEAD(fd); + cmd=RFIFOW(fd,0); + // inter鯖管轄かを調べ + if(cmd < 0x3000 || cmd >= 0x3000 + (sizeof(inter_recv_packet_length)/ + sizeof(inter_recv_packet_length[0]) ) ) + return 0; + + if (inter_recv_packet_length[cmd-0x3000] == 0) //This is necessary, because otherwise we return 2 and the char server will just hang waiting for packets! [Skotlex] + return 0; + + // パケット長を調べる + if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0) + return 2; + + switch(cmd){ + case 0x3000: mapif_parse_GMmessage(fd); break; + case 0x3001: mapif_parse_WisRequest(fd); break; + case 0x3002: mapif_parse_WisReply(fd); break; + case 0x3003: mapif_parse_WisToGM(fd); break; + case 0x3004: mapif_parse_Registry(fd); break; + case 0x3005: mapif_parse_RegistryRequest(fd); break; + default: + if(inter_party_parse_frommap(fd)) + break; + if(inter_guild_parse_frommap(fd)) + break; + if(inter_storage_parse_frommap(fd)) + break; + if(inter_pet_parse_frommap(fd)) + break; + if(inter_homunculus_parse_frommap(fd)) //albator + break; + return 0; + } + + RFIFOSKIP(fd, len); + return 1; +} + +// RFIFO check +int inter_check_length(int fd, int length) +{ + RFIFOHEAD(fd); + if(length==-1){ // v-len packet + if(RFIFOREST(fd)<4) // packet not yet + return 0; + length = RFIFOW(fd, 2); + } + + if((int)RFIFOREST(fd) < length) // packet not yet + return 0; + + return length; +} +#endif //TXT_SQL_CONVERT -- cgit v1.2.3-70-g09d2