inter.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. // original code from athena
  4. // SQL conversion by Jioh L. Jung
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "char.h"
  9. #include "../common/malloc.h"
  10. #include "../common/strlib.h"
  11. #include "../common/showmsg.h"
  12. #include "inter.h"
  13. #include "int_party.h"
  14. #include "int_guild.h"
  15. #include "int_storage.h"
  16. #include "int_pet.h"
  17. #include "int_homun.h" //albator
  18. #define WISDATA_TTL (60*1000) // Wisデータの生存時間(60秒)
  19. #define WISDELLIST_MAX 256 // Wisデータ削除リストの要素数
  20. MYSQL mysql_handle;
  21. MYSQL_RES* sql_res ;
  22. MYSQL_ROW sql_row ;
  23. int sql_fields, sql_cnt;
  24. char tmp_sql[65535];
  25. MYSQL lmysql_handle;
  26. MYSQL_RES* lsql_res ;
  27. MYSQL_ROW lsql_row ;
  28. int char_server_port = 3306;
  29. char char_server_ip[32] = "127.0.0.1";
  30. char char_server_id[32] = "ragnarok";
  31. char char_server_pw[32] = "ragnarok";
  32. char char_server_db[32] = "ragnarok";
  33. char default_codepage[32] = ""; //Feature by irmin.
  34. int login_server_port = 3306;
  35. char login_server_ip[32] = "127.0.0.1";
  36. char login_server_id[32] = "ragnarok";
  37. char login_server_pw[32] = "ragnarok";
  38. char login_server_db[32] = "ragnarok";
  39. #ifndef TXT_SQL_CONVERT
  40. static struct accreg *accreg_pt;
  41. unsigned int party_share_level = 10;
  42. char main_chat_nick[16] = "Main";
  43. // sending packet list
  44. // 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]
  45. int inter_send_packet_length[]={
  46. -1,-1,27,-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  47. -1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0,
  48. 35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0,
  49. 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1,
  50. 9, 9,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  51. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  52. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  53. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  54. 11,-1, 7, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  55. };
  56. // recv. packet list
  57. int inter_recv_packet_length[]={
  58. -1,-1, 7,-1, -1,13,36, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f
  59. 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f
  60. -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
  61. -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
  62. 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  63. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  64. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  65. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  66. 48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3080-0x308f
  67. -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x3090 - 0x309f Homunculus packets [albator]
  68. };
  69. struct WisData {
  70. int id, fd, count, len;
  71. unsigned long tick;
  72. unsigned char src[24], dst[24], msg[512];
  73. };
  74. static struct dbt * wis_db = NULL;
  75. static int wis_dellist[WISDELLIST_MAX], wis_delnum;
  76. int inter_sql_test (void);
  77. #endif //TXT_SQL_CONVERT
  78. //--------------------------------------------------------
  79. // Save registry to sql
  80. int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type){
  81. int j;
  82. char temp_str[64]; //Needs be twice the source to ensure it fits [Skotlex]
  83. char temp_str2[512];
  84. if (account_id<=0) return 0;
  85. reg->account_id=account_id;
  86. reg->char_id = char_id;
  87. switch (type) {
  88. case 3: //Char Reg
  89. //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
  90. sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id);
  91. break;
  92. case 2: //Account Reg
  93. //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
  94. sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id);
  95. break;
  96. case 1: //Account2 Reg
  97. ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
  98. return 0;
  99. default:
  100. ShowError("inter_accreg_tosql: Invalid type %d\n", type);
  101. return 0;
  102. }
  103. if(mysql_query(&mysql_handle, tmp_sql) ) {
  104. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  105. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  106. }
  107. if (reg->reg_num<=0) return 0;
  108. for(j=0;j<reg->reg_num;j++){
  109. if(reg->reg[j].str != NULL){
  110. sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d','%s','%s')",
  111. reg_db, type, type!=3?reg->account_id:0, type==3?reg->char_id:0,
  112. jstrescapecpy(temp_str,reg->reg[j].str), jstrescapecpy(temp_str2,reg->reg[j].value));
  113. if(mysql_query(&mysql_handle, tmp_sql) ) {
  114. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  115. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  116. }
  117. }
  118. }
  119. return 1;
  120. }
  121. #ifndef TXT_SQL_CONVERT
  122. // Load account_reg from sql (type=2)
  123. int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int type)
  124. {
  125. int j=0;
  126. if (reg==NULL) return 0;
  127. memset(reg, 0, sizeof(struct accreg));
  128. reg->account_id=account_id;
  129. reg->char_id=char_id;
  130. //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
  131. switch (type) {
  132. case 3: //char reg
  133. sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, reg->char_id);
  134. break;
  135. case 2: //account reg
  136. sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id);
  137. break;
  138. case 1: //account2 reg
  139. ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
  140. return 0;
  141. }
  142. if(mysql_query(&mysql_handle, tmp_sql) ) {
  143. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  144. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  145. }
  146. sql_res = mysql_store_result(&mysql_handle);
  147. if (sql_res) {
  148. for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){
  149. strcpy(reg->reg[j].str, sql_row[0]);
  150. strcpy(reg->reg[j].value, sql_row[1]);
  151. }
  152. mysql_free_result(sql_res);
  153. }
  154. reg->reg_num=j;
  155. return 1;
  156. }
  157. // Initialize
  158. int inter_accreg_sql_init(void)
  159. {
  160. CREATE(accreg_pt, struct accreg, 1);
  161. return 0;
  162. }
  163. #endif //TXT_SQL_CONVERT
  164. /*==========================================
  165. * read config file
  166. *------------------------------------------
  167. */
  168. static int inter_config_read(const char *cfgName) {
  169. int i;
  170. char line[1024], w1[1024], w2[1024];
  171. FILE *fp;
  172. fp=fopen(cfgName,"r");
  173. if(fp==NULL){
  174. ShowError("file not found: %s\n", cfgName);
  175. return 1;
  176. }
  177. ShowInfo("reading file %s...\n",cfgName);
  178. while(fgets(line, 1020, fp)){
  179. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  180. if(i!=2)
  181. continue;
  182. if(strcmpi(w1,"char_server_ip")==0){
  183. strcpy(char_server_ip, w2);
  184. ShowStatus ("set char_server_ip : %s\n",w2);
  185. }
  186. else if(strcmpi(w1,"char_server_port")==0){
  187. char_server_port=atoi(w2);
  188. ShowStatus ("set char_server_port : %s\n",w2);
  189. }
  190. else if(strcmpi(w1,"char_server_id")==0){
  191. strcpy(char_server_id, w2);
  192. ShowStatus ("set char_server_id : %s\n",w2);
  193. }
  194. else if(strcmpi(w1,"char_server_pw")==0){
  195. strcpy(char_server_pw, w2);
  196. ShowStatus ("set char_server_pw : %s\n",w2);
  197. }
  198. else if(strcmpi(w1,"char_server_db")==0){
  199. strcpy(char_server_db, w2);
  200. ShowStatus ("set char_server_db : %s\n",w2);
  201. }
  202. else if(strcmpi(w1,"default_codepage")==0){
  203. strcpy(default_codepage, w2);
  204. ShowStatus ("set default_codepage : %s\n",w2);
  205. }
  206. //Logins information to be read from the inter_athena.conf
  207. //for character deletion (checks email in the loginDB)
  208. else if(strcmpi(w1,"login_server_ip")==0){
  209. strcpy(login_server_ip, w2);
  210. ShowStatus ("set login_server_ip : %s\n",w2);
  211. }
  212. else if(strcmpi(w1,"login_server_port")==0){
  213. login_server_port=atoi(w2);
  214. ShowStatus ("set login_server_port : %s\n",w2);
  215. }
  216. else if(strcmpi(w1,"login_server_id")==0){
  217. strcpy(login_server_id, w2);
  218. ShowStatus ("set login_server_id : %s\n",w2);
  219. }
  220. else if(strcmpi(w1,"login_server_pw")==0){
  221. strcpy(login_server_pw, w2);
  222. ShowStatus ("set login_server_pw : %s\n",w2);
  223. }
  224. else if(strcmpi(w1,"login_server_db")==0){
  225. strcpy(login_server_db, w2);
  226. ShowStatus ("set login_server_db : %s\n",w2);
  227. }
  228. #ifndef TXT_SQL_CONVERT
  229. else if(strcmpi(w1,"party_share_level")==0){
  230. party_share_level=(unsigned int)atof(w2);
  231. }
  232. else if(strcmpi(w1,"log_inter")==0){
  233. log_inter = atoi(w2);
  234. }
  235. else if(strcmpi(w1, "main_chat_nick")==0){ // Main chat nick [LuzZza]
  236. strcpy(main_chat_nick, w2); //
  237. }
  238. #endif //TXT_SQL_CONVERT
  239. else if(strcmpi(w1,"import")==0){
  240. inter_config_read(w2);
  241. }
  242. }
  243. fclose(fp);
  244. ShowInfo ("done reading %s.\n", cfgName);
  245. return 0;
  246. }
  247. #ifndef TXT_SQL_CONVERT
  248. // Save interlog into sql
  249. int inter_log(char *fmt,...)
  250. {
  251. char str[255];
  252. char temp_str[510]; //Needs be twice as long as str[] //Skotlex
  253. va_list ap;
  254. va_start(ap,fmt);
  255. vsprintf(str,fmt,ap);
  256. sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str));
  257. if(mysql_query(&mysql_handle, tmp_sql) ) {
  258. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  259. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  260. }
  261. va_end(ap);
  262. return 0;
  263. }
  264. /*=============================================
  265. * Does a mysql_ping to all connection handles
  266. *---------------------------------------------*/
  267. int inter_sql_ping(int tid, unsigned int tick, int id, int data)
  268. {
  269. ShowInfo("Pinging SQL server to keep connection alive...\n");
  270. mysql_ping(&mysql_handle);
  271. if(char_gm_read)
  272. mysql_ping(&lmysql_handle);
  273. return 0;
  274. }
  275. int sql_ping_init(void)
  276. {
  277. int connection_timeout, connection_ping_interval;
  278. // set a default value first
  279. connection_timeout = 28800; // 8 hours
  280. // ask the mysql server for the timeout value
  281. if (!mysql_query(&mysql_handle, "SHOW VARIABLES LIKE 'wait_timeout'")
  282. && (sql_res = mysql_store_result(&mysql_handle)) != NULL) {
  283. sql_row = mysql_fetch_row(sql_res);
  284. if (sql_row)
  285. connection_timeout = atoi(sql_row[1]);
  286. if (connection_timeout < 60)
  287. connection_timeout = 60;
  288. mysql_free_result(sql_res);
  289. }
  290. // establish keepalive
  291. connection_ping_interval = connection_timeout - 30; // 30-second reserve
  292. add_timer_func_list(inter_sql_ping, "inter_sql_ping");
  293. add_timer_interval(gettick() + connection_ping_interval*1000, inter_sql_ping, 0, 0, connection_ping_interval*1000);
  294. return 0;
  295. }
  296. #endif //TXT_SQL_CONVERT
  297. // initialize
  298. int inter_init_sql(const char *file)
  299. {
  300. //int i;
  301. ShowInfo ("interserver initialize...\n");
  302. inter_config_read(file);
  303. //DB connection initialized
  304. mysql_init(&mysql_handle);
  305. ShowInfo("Connect Character DB server.... (Character Server)\n");
  306. if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw,
  307. char_server_db ,char_server_port, (char *)NULL, 0)) {
  308. //pointer check
  309. ShowFatalError("%s\n",mysql_error(&mysql_handle));
  310. exit(1);
  311. }
  312. #ifndef TXT_SQL_CONVERT
  313. else if (inter_sql_test()) {
  314. ShowStatus("Connect Success! (Character Server)\n");
  315. }
  316. if(char_gm_read) {
  317. mysql_init(&lmysql_handle);
  318. ShowInfo("Connect Character DB server.... (login server)\n");
  319. if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
  320. login_server_db ,login_server_port, (char *)NULL, 0)) {
  321. //pointer check
  322. ShowFatalError("%s\n",mysql_error(&lmysql_handle));
  323. exit(1);
  324. }else {
  325. ShowStatus ("Connect Success! (Login Server)\n");
  326. }
  327. }
  328. #endif //TXT_SQL_CONVERT
  329. if(strlen(default_codepage) > 0 ) {
  330. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  331. if (mysql_query(&mysql_handle, tmp_sql)) {
  332. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  333. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  334. }
  335. #ifndef TXT_SQL_CONVERT
  336. if(char_gm_read)
  337. if (mysql_query(&lmysql_handle, tmp_sql)) {
  338. ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle));
  339. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  340. }
  341. #endif //TXT_SQL_CONVERT
  342. }
  343. #ifndef TXT_SQL_CONVERT
  344. wis_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
  345. inter_guild_sql_init();
  346. inter_storage_sql_init();
  347. inter_party_sql_init();
  348. inter_pet_sql_init();
  349. inter_homunculus_sql_init(); // albator
  350. inter_accreg_sql_init();
  351. sql_ping_init();
  352. #endif //TXT_SQL_CONVERT
  353. return 0;
  354. }
  355. #ifndef TXT_SQL_CONVERT
  356. int inter_sql_test (void)
  357. {
  358. const char fields[][24] = {
  359. "father", // version 1363
  360. "fame", // version 1491
  361. };
  362. char buf[1024] = "";
  363. int i;
  364. sprintf(tmp_sql, "EXPLAIN `%s`",char_db);
  365. if (mysql_query(&mysql_handle, tmp_sql)) {
  366. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  367. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  368. }
  369. sql_res = mysql_store_result(&mysql_handle);
  370. // store DB fields
  371. if (sql_res) {
  372. while((sql_row = mysql_fetch_row(sql_res))) {
  373. strcat (buf, sql_row[0]);
  374. strcat (buf, " ");
  375. }
  376. }
  377. // check DB strings
  378. for (i = 0; i < (int)(sizeof(fields) / sizeof(fields[0])); i++) {
  379. if(!strstr(buf, fields[i])) {
  380. ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db);
  381. exit(1);
  382. }
  383. }
  384. mysql_free_result(sql_res);
  385. return 1;
  386. }
  387. // finalize
  388. void inter_final(void) {
  389. wis_db->destroy(wis_db, NULL);
  390. inter_guild_sql_final();
  391. inter_storage_sql_final();
  392. inter_party_sql_final();
  393. inter_pet_sql_final();
  394. inter_homunculus_sql_final(); //[orn]
  395. if (accreg_pt) aFree(accreg_pt);
  396. return;
  397. }
  398. int inter_mapif_init(int fd) {
  399. inter_guild_mapif_init(fd);
  400. return 0;
  401. }
  402. //--------------------------------------------------------
  403. // GM message sending
  404. int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) {
  405. unsigned char buf[2048];
  406. if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
  407. WBUFW(buf, 0) = 0x3800;
  408. WBUFW(buf, 2) = len;
  409. WBUFL(buf, 4) = color;
  410. memcpy(WBUFP(buf, 8), mes, len-8);
  411. mapif_sendallwos(sfd, buf, len);
  412. return 0;
  413. }
  414. // Wis sending
  415. int mapif_wis_message(struct WisData *wd) {
  416. unsigned char buf[2048];
  417. if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
  418. WBUFW(buf, 0) = 0x3801;
  419. WBUFW(buf, 2) = 56 +wd->len;
  420. WBUFL(buf, 4) = wd->id;
  421. memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
  422. memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH);
  423. memcpy(WBUFP(buf,56), wd->msg, wd->len);
  424. wd->count = mapif_sendall(buf,WBUFW(buf,2));
  425. return 0;
  426. }
  427. // Wis sending result
  428. int mapif_wis_end(struct WisData *wd,int flag)
  429. {
  430. unsigned char buf[27];
  431. WBUFW(buf, 0)=0x3802;
  432. memcpy(WBUFP(buf, 2),wd->src,24);
  433. WBUFB(buf,26)=flag;
  434. mapif_send(wd->fd,buf,27);
  435. // printf("inter server wis_end %d\n",flag);
  436. return 0;
  437. }
  438. int mapif_account_reg(int fd,unsigned char *src)
  439. {
  440. // unsigned char buf[WBUFW(src,2)]; <- Hey, can this really be done? [Skotlex]
  441. unsigned char *buf = aCalloc(1,WBUFW(src,2)); // [Lance] - Skot... Dynamic allocation is better :D
  442. memcpy(WBUFP(buf,0),src,WBUFW(src,2));
  443. WBUFW(buf, 0)=0x3804;
  444. mapif_sendallwos(fd, buf, WBUFW(buf,2));
  445. aFree(buf);
  446. return 0;
  447. }
  448. // Send the requested account_reg
  449. int mapif_account_reg_reply(int fd,int account_id,int char_id, int type)
  450. {
  451. struct accreg *reg=accreg_pt;
  452. WFIFOHEAD(fd, 13 + 5000);
  453. inter_accreg_fromsql(account_id,char_id,reg,type);
  454. WFIFOW(fd,0)=0x3804;
  455. WFIFOL(fd,4)=account_id;
  456. WFIFOL(fd,8)=char_id;
  457. WFIFOB(fd,12)=type;
  458. if(reg->reg_num==0){
  459. WFIFOW(fd,2)=13;
  460. }else{
  461. int i,p;
  462. for (p=13,i = 0; i < reg->reg_num && p < 5000; i++) {
  463. p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place.
  464. p+= sprintf(WFIFOP(fd,p), "%s", reg->reg[i].value)+1;
  465. }
  466. WFIFOW(fd,2)=p;
  467. if (p>= 5000)
  468. ShowWarning("Too many acc regs for %d:%d, not all values were loaded.\n", account_id, char_id);
  469. }
  470. WFIFOSET(fd,WFIFOW(fd,2));
  471. return 0;
  472. }
  473. int mapif_send_gmaccounts()
  474. {
  475. int i, len = 4;
  476. unsigned char buf[32000];
  477. // forward the gm accounts to the map server
  478. len = 4;
  479. WBUFW(buf,0) = 0x2b15;
  480. for(i = 0; i < GM_num; i++) {
  481. WBUFL(buf, len) = gm_account[i].account_id;
  482. WBUFB(buf, len+4) = (unsigned char)gm_account[i].level;
  483. len += 5;
  484. }
  485. WBUFW(buf, 2) = len;
  486. mapif_sendall(buf, len);
  487. return 0;
  488. }
  489. //Sends to map server the current max Account/Char id [Skotlex]
  490. void mapif_send_maxid(int account_id, int char_id)
  491. {
  492. unsigned char buf[12];
  493. WBUFW(buf,0) = 0x2b07;
  494. WBUFL(buf,2) = account_id;
  495. WBUFL(buf,6) = char_id;
  496. mapif_sendall(buf, 10);
  497. }
  498. //Request to kick char from a certain map server. [Skotlex]
  499. int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
  500. {
  501. if (fd >= 0)
  502. {
  503. WFIFOHEAD(fd,7);
  504. WFIFOW(fd,0) = 0x2b1f;
  505. WFIFOL(fd,2) = account_id;
  506. WFIFOB(fd,6) = reason;
  507. WFIFOSET(fd,7);
  508. return 0;
  509. }
  510. return -1;
  511. }
  512. //--------------------------------------------------------
  513. // Existence check of WISP data
  514. int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap) {
  515. unsigned long tick;
  516. struct WisData *wd = (struct WisData *)data;
  517. tick = va_arg(ap, unsigned long);
  518. if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
  519. wis_dellist[wis_delnum++] = wd->id;
  520. return 0;
  521. }
  522. int check_ttl_wisdata(void) {
  523. unsigned long tick = gettick();
  524. int i;
  525. do {
  526. wis_delnum = 0;
  527. wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
  528. for(i = 0; i < wis_delnum; i++) {
  529. struct WisData *wd = idb_get(wis_db, wis_dellist[i]);
  530. ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
  531. // removed. not send information after a timeout. Just no answer for the player
  532. //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  533. idb_remove(wis_db, wd->id);
  534. }
  535. } while(wis_delnum >= WISDELLIST_MAX);
  536. return 0;
  537. }
  538. //--------------------------------------------------------
  539. // GM message sending
  540. int mapif_parse_GMmessage(int fd)
  541. {
  542. RFIFOHEAD(fd);
  543. mapif_GMmessage(RFIFOP(fd, 8), RFIFOW(fd, 2), RFIFOL(fd, 4), fd);
  544. return 0;
  545. }
  546. // Wisp/page request to send
  547. int mapif_parse_WisRequest(int fd) {
  548. struct WisData* wd;
  549. static int wisid = 0;
  550. char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex]
  551. RFIFOHEAD(fd);
  552. if ( fd <= 0 ) {return 0;} // check if we have a valid fd
  553. if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
  554. ShowWarning("inter: Wis message size too long.\n");
  555. return 0;
  556. } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
  557. ShowError("inter: Wis message doesn't exist.\n");
  558. return 0;
  559. }
  560. memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
  561. name[NAME_LENGTH-1]= '\0';
  562. sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'",
  563. char_db, jstrescapecpy(t_name, name));
  564. if(mysql_query(&mysql_handle, tmp_sql) ) {
  565. ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
  566. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  567. }
  568. sql_res = mysql_store_result(&mysql_handle);
  569. // search if character exists before to ask all map-servers
  570. if (!(sql_row = mysql_fetch_row(sql_res))) {
  571. unsigned char buf[27];
  572. WBUFW(buf, 0) = 0x3802;
  573. memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
  574. WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  575. mapif_send(fd, buf, 27);
  576. // Character exists. So, ask all map-servers
  577. } else {
  578. // to be sure of the correct name, rewrite it
  579. memset(name, 0, NAME_LENGTH);
  580. strncpy(name, sql_row[0], NAME_LENGTH);
  581. // if source is destination, don't ask other servers.
  582. if (strcmp((char*)RFIFOP(fd,4),name) == 0) {
  583. unsigned char buf[27];
  584. WBUFW(buf, 0) = 0x3802;
  585. memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
  586. WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  587. mapif_send(fd, buf, 27);
  588. } else {
  589. CREATE(wd, struct WisData, 1);
  590. // Whether the failure of previous wisp/page transmission (timeout)
  591. check_ttl_wisdata();
  592. wd->id = ++wisid;
  593. wd->fd = fd;
  594. wd->len= RFIFOW(fd,2)-52;
  595. memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH);
  596. memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH);
  597. memcpy(wd->msg, RFIFOP(fd,52), wd->len);
  598. wd->tick = gettick();
  599. idb_put(wis_db, wd->id, wd);
  600. mapif_wis_message(wd);
  601. }
  602. }
  603. //Freeing ... O.o
  604. if(sql_res){
  605. mysql_free_result(sql_res);
  606. }
  607. return 0;
  608. }
  609. // Wisp/page transmission result
  610. int mapif_parse_WisReply(int fd) {
  611. int id, flag;
  612. struct WisData *wd;
  613. RFIFOHEAD(fd);
  614. id = RFIFOL(fd,2);
  615. flag = RFIFOB(fd,6);
  616. wd = idb_get(wis_db, id);
  617. if (wd == NULL)
  618. return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
  619. if ((--wd->count) <= 0 || flag != 1) {
  620. mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  621. idb_remove(wis_db, id);
  622. }
  623. return 0;
  624. }
  625. // Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
  626. int mapif_parse_WisToGM(int fd) {
  627. unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
  628. RFIFOHEAD(fd);
  629. ShowDebug("Sent packet back!\n");
  630. memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
  631. WBUFW(buf, 0) = 0x3803;
  632. mapif_sendall(buf, RFIFOW(fd,2));
  633. return 0;
  634. }
  635. // Save account_reg into sql (type=2)
  636. int mapif_parse_Registry(int fd)
  637. {
  638. int j,p,len, max;
  639. struct accreg *reg=accreg_pt;
  640. RFIFOHEAD(fd);
  641. memset(accreg_pt,0,sizeof(struct accreg));
  642. switch (RFIFOB(fd, 12)) {
  643. case 3: //Character registry
  644. max = GLOBAL_REG_NUM;
  645. break;
  646. case 2: //Account Registry
  647. max = ACCOUNT_REG_NUM;
  648. break;
  649. case 1: //Account2 registry, must be sent over to login server.
  650. return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4);
  651. default:
  652. return 1;
  653. }
  654. for(j=0,p=13;j<max && p<RFIFOW(fd,2);j++){
  655. sscanf(RFIFOP(fd,p), "%31c%n",reg->reg[j].str,&len);
  656. reg->reg[j].str[len]='\0';
  657. p +=len+1; //+1 to skip the '\0' between strings.
  658. sscanf(RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len);
  659. reg->reg[j].value[len]='\0';
  660. p +=len+1;
  661. }
  662. reg->reg_num=j;
  663. inter_accreg_tosql(RFIFOL(fd,4),RFIFOL(fd,8),reg, RFIFOB(fd,12));
  664. mapif_account_reg(fd,RFIFOP(fd,0)); // Send updated accounts to other map servers.
  665. return 0;
  666. }
  667. // Request the value of all registries.
  668. int mapif_parse_RegistryRequest(int fd)
  669. {
  670. RFIFOHEAD(fd);
  671. //Load Char Registry
  672. if (RFIFOB(fd,12))
  673. mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3);
  674. //Load Account Registry
  675. if (RFIFOB(fd,11))
  676. mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2);
  677. //Ask Login Server for Account2 values.
  678. if (RFIFOB(fd,10))
  679. request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6)-2);
  680. return 1;
  681. }
  682. static void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, char *name){
  683. WFIFOHEAD(fd, NAME_LENGTH+13);
  684. WFIFOW(fd, 0) =0x3806;
  685. WFIFOL(fd, 2) =account_id;
  686. WFIFOL(fd, 6) =char_id;
  687. WFIFOB(fd,10) =type;
  688. WFIFOB(fd,11) =flag;
  689. memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
  690. WFIFOSET(fd, NAME_LENGTH+13);
  691. }
  692. int mapif_parse_NameChangeRequest(int fd)
  693. {
  694. int account_id, char_id, type;
  695. char* name;
  696. int i;
  697. RFIFOHEAD(fd);
  698. account_id = RFIFOL(fd, 2);
  699. char_id = RFIFOL(fd, 6);
  700. type = RFIFOB(fd, 10);
  701. name = RFIFOP(fd, 11);
  702. // Check Authorised letters/symbols in the name
  703. if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  704. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  705. if (strchr(char_name_letters, name[i]) == NULL) {
  706. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  707. return 0;
  708. }
  709. } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  710. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  711. if (strchr(char_name_letters, name[i]) != NULL) {
  712. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  713. return 0;
  714. }
  715. }
  716. //TODO: type holds the type of object to rename.
  717. //If it were a player, it needs to have the guild information and db information
  718. //updated here, because changing it on the map won't make it be saved [Skotlex]
  719. //name allowed.
  720. mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
  721. return 0;
  722. }
  723. //--------------------------------------------------------
  724. int inter_parse_frommap(int fd)
  725. {
  726. int cmd;
  727. int len=0;
  728. RFIFOHEAD(fd);
  729. cmd=RFIFOW(fd,0);
  730. // inter鯖管轄かを調べる
  731. if(cmd < 0x3000 || cmd >= 0x3000 + (sizeof(inter_recv_packet_length)/
  732. sizeof(inter_recv_packet_length[0]) ) )
  733. return 0;
  734. 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]
  735. return 0;
  736. // パケット長を調べる
  737. if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
  738. return 2;
  739. switch(cmd){
  740. case 0x3000: mapif_parse_GMmessage(fd); break;
  741. case 0x3001: mapif_parse_WisRequest(fd); break;
  742. case 0x3002: mapif_parse_WisReply(fd); break;
  743. case 0x3003: mapif_parse_WisToGM(fd); break;
  744. case 0x3004: mapif_parse_Registry(fd); break;
  745. case 0x3005: mapif_parse_RegistryRequest(fd); break;
  746. case 0x3006: mapif_parse_NameChangeRequest(fd); break;
  747. default:
  748. if(inter_party_parse_frommap(fd))
  749. break;
  750. if(inter_guild_parse_frommap(fd))
  751. break;
  752. if(inter_storage_parse_frommap(fd))
  753. break;
  754. if(inter_pet_parse_frommap(fd))
  755. break;
  756. if(inter_homunculus_parse_frommap(fd)) //albator
  757. break;
  758. return 0;
  759. }
  760. RFIFOSKIP(fd, len);
  761. return 1;
  762. }
  763. // RFIFO check
  764. int inter_check_length(int fd, int length)
  765. {
  766. RFIFOHEAD(fd);
  767. if(length==-1){ // v-len packet
  768. if(RFIFOREST(fd)<4) // packet not yet
  769. return 0;
  770. length = RFIFOW(fd, 2);
  771. }
  772. if((int)RFIFOREST(fd) < length) // packet not yet
  773. return 0;
  774. return length;
  775. }
  776. #endif //TXT_SQL_CONVERT