root/src/char_sql/inter.c @ 11

Revision 1, 24.1 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/mmo.h"
5#include "../common/db.h"
6#include "../common/malloc.h"
7#include "../common/strlib.h"
8#include "../common/showmsg.h"
9#include "../common/socket.h"
10#include "../common/timer.h"
11#include "char.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"
18#include "int_mail.h"
19#include "int_auction.h"
20#include "int_quest.h"
21
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25
26#define WISDATA_TTL (60*1000)   // Wisƒf[ƒ^‚̐¶‘¶ŽžŠÔ(60•b)
27#define WISDELLIST_MAX 256                      // Wisƒf[ƒ^íœƒŠƒXƒg‚Ì—v‘f”
28
29
30Sql* sql_handle = NULL;
31Sql* lsql_handle = NULL;
32
33int char_server_port = 3306;
34char char_server_ip[32] = "127.0.0.1";
35char char_server_id[32] = "ragnarok";
36char char_server_pw[32] = "ragnarok";
37char char_server_db[32] = "ragnarok";
38char default_codepage[32] = ""; //Feature by irmin.
39
40int login_server_port = 3306;
41char login_server_ip[32] = "127.0.0.1";
42char login_server_id[32] = "ragnarok";
43char login_server_pw[32] = "ragnarok";
44char login_server_db[32] = "ragnarok";
45
46#ifndef TXT_SQL_CONVERT
47
48static struct accreg *accreg_pt;
49unsigned int party_share_level = 10;
50char main_chat_nick[16] = "Main";
51
52// recv. packet list
53int inter_recv_packet_length[] = {
54        -1,-1, 7,-1, -1,13,36, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3000-
55         6,-1, 0, 0,  0, 0, 0, 0, 10,-1, 0, 0,  0, 0,  0, 0,    // 3010-
56        -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0,  0, 0,  0, 0,    // 3020-
57        -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1,    // 3030-
58         5, 9, 0, 0,  0, 0, 0, 0,  7, 6,10,10, 10,-1,  0, 0,    // 3040-
59        -1,-1,10,10,  0,-1, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3050-  Auction System [Zephyrus]
60         6,-1,10, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3060-  Quest system [Kevin]
61         0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3070-
62        48,14,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3080-
63        -1,10,-1, 6,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,    // 3090-  Homunculus packets [albator]
64};
65
66struct WisData {
67        int id, fd, count, len;
68        unsigned long tick;
69        unsigned char src[24], dst[24], msg[512];
70};
71static DBMap* wis_db = NULL; // int wis_id -> struct WisData*
72static int wis_dellist[WISDELLIST_MAX], wis_delnum;
73
74int inter_sql_test (void);
75
76#endif //TXT_SQL_CONVERT
77//--------------------------------------------------------
78// Save registry to sql
79int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type)
80{
81        struct global_reg* r;
82        SqlStmt* stmt;
83        int i;
84
85        if( account_id <= 0 )
86                return 0;
87        reg->account_id = account_id;
88        reg->char_id = char_id;
89
90        //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
91        switch( type )
92        {
93        case 3: //Char Reg
94                if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) )
95                        Sql_ShowDebug(sql_handle);
96                account_id = 0;
97                break;
98        case 2: //Account Reg
99                if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) )
100                        Sql_ShowDebug(sql_handle);
101                char_id = 0;
102                break;
103        case 1: //Account2 Reg
104                ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
105                return 0;
106        default:
107                ShowError("inter_accreg_tosql: Invalid type %d\n", type);
108                return 0;
109        }
110
111        if( reg->reg_num <= 0 )
112                return 0;
113
114        stmt = SqlStmt_Malloc(sql_handle);
115        if( SQL_ERROR == SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d',?,?)", reg_db, type, account_id, char_id) )
116                SqlStmt_ShowDebug(stmt);
117        for( i = 0; i < reg->reg_num; ++i )
118        {
119                r = &reg->reg[i];
120                if( r->str[0] != '\0' && r->value != '\0' )
121                {
122                        // str
123                        SqlStmt_BindParam(stmt, 0, SQLDT_STRING, r->str, strnlen(r->str, sizeof(r->str)));
124                        // value
125                        SqlStmt_BindParam(stmt, 1, SQLDT_STRING, r->value, strnlen(r->value, sizeof(r->value)));
126
127                        if( SQL_ERROR == SqlStmt_Execute(stmt) )
128                                SqlStmt_ShowDebug(stmt);
129                }
130        }
131        SqlStmt_Free(stmt);
132        return 1;
133}
134#ifndef TXT_SQL_CONVERT
135
136// Load account_reg from sql (type=2)
137int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int type)
138{
139        struct global_reg* r;
140        char* data;
141        size_t len;
142        int i;
143
144        if( reg == NULL)
145                return 0;
146
147        memset(reg, 0, sizeof(struct accreg));
148        reg->account_id = account_id;
149        reg->char_id = char_id;
150
151        //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
152        switch( type )
153        {
154        case 3: //char reg
155                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) )
156                        Sql_ShowDebug(sql_handle);
157                break;
158        case 2: //account reg
159                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) )
160                        Sql_ShowDebug(sql_handle);
161                break;
162        case 1: //account2 reg
163                ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
164                return 0;
165        default:
166                ShowError("inter_accreg_fromsql: Invalid type %d\n", type);
167                return 0;
168        }
169        for( i = 0; i < MAX_REG_NUM && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
170        {
171                r = &reg->reg[i];
172                // str
173                Sql_GetData(sql_handle, 0, &data, &len);
174                memcpy(r->str, data, min(len, sizeof(r->str)));
175                // value
176                Sql_GetData(sql_handle, 1, &data, &len);
177                memcpy(r->value, data, min(len, sizeof(r->value)));
178        }
179        reg->reg_num = i;
180        Sql_FreeResult(sql_handle);
181        return 1;
182}
183
184// Initialize
185int inter_accreg_sql_init(void)
186{
187        CREATE(accreg_pt, struct accreg, 1);
188        return 0;
189
190}
191#endif //TXT_SQL_CONVERT
192
193/*==========================================
194 * read config file
195 *------------------------------------------*/
196static int inter_config_read(const char* cfgName)
197{
198        int i;
199        char line[1024], w1[1024], w2[1024];
200        FILE* fp;
201
202        fp = fopen(cfgName, "r");
203        if(fp == NULL) {
204                ShowError("file not found: %s\n", cfgName);
205                return 1;
206        }
207
208        ShowInfo("reading file %s...\n", cfgName);
209
210        while(fgets(line, sizeof(line), fp))
211        {
212                i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2);
213                if(i != 2)
214                        continue;
215
216                if(!strcmpi(w1,"char_server_ip")) {
217                        strcpy(char_server_ip,w2);
218                        ShowStatus ("set char_server_ip : %s\n", w2);
219                } else
220                if(!strcmpi(w1,"char_server_port")) {
221                        char_server_port = atoi(w2);
222                        ShowStatus ("set char_server_port : %s\n", w2);
223                } else
224                if(!strcmpi(w1,"char_server_id")) {
225                        strcpy(char_server_id,w2);
226                        ShowStatus ("set char_server_id : %s\n", w2);
227                } else
228                if(!strcmpi(w1,"char_server_pw")) {
229                        strcpy(char_server_pw,w2);
230                        ShowStatus ("set char_server_pw : %s\n", w2);
231                } else
232                if(!strcmpi(w1,"char_server_db")) {
233                        strcpy(char_server_db,w2);
234                        ShowStatus ("set char_server_db : %s\n", w2);
235                } else
236                if(!strcmpi(w1,"default_codepage")) {
237                        strcpy(default_codepage,w2);
238                        ShowStatus ("set default_codepage : %s\n", w2);
239                }
240                //Logins information to be read from the inter_athena.conf
241                //for character deletion (checks email in the loginDB)
242                else
243                if(!strcmpi(w1,"login_server_ip")) {
244                        strcpy(login_server_ip, w2);
245                        ShowStatus ("set login_server_ip : %s\n", w2);
246                } else
247                if(!strcmpi(w1,"login_server_port")) {
248                        login_server_port = atoi(w2);
249                        ShowStatus ("set login_server_port : %s\n", w2);
250                } else
251                if(!strcmpi(w1,"login_server_id")) {
252                        strcpy(login_server_id, w2);
253                        ShowStatus ("set login_server_id : %s\n", w2);
254                } else
255                if(!strcmpi(w1,"login_server_pw")) {
256                        strcpy(login_server_pw, w2);
257                        ShowStatus ("set login_server_pw : %s\n", w2);
258                } else
259                if(!strcmpi(w1,"login_server_db")) {
260                        strcpy(login_server_db, w2);
261                        ShowStatus ("set login_server_db : %s\n", w2);
262                }
263#ifndef TXT_SQL_CONVERT
264                else if(!strcmpi(w1,"party_share_level"))
265                        party_share_level = atoi(w2);
266                else if(!strcmpi(w1,"log_inter"))
267                        log_inter = atoi(w2);
268                else if(!strcmpi(w1,"main_chat_nick"))
269                        strcpy(main_chat_nick, w2);
270#endif //TXT_SQL_CONVERT
271                else if(!strcmpi(w1,"import"))
272                        inter_config_read(w2);
273        }
274        fclose(fp);
275
276        ShowInfo ("done reading %s.\n", cfgName);
277
278        return 0;
279}
280#ifndef TXT_SQL_CONVERT
281
282// Save interlog into sql
283int inter_log(char* fmt, ...)
284{
285        char str[255];
286        char esc_str[sizeof(str)*2+1];// escaped str
287        va_list ap;
288
289        va_start(ap,fmt);
290        vsnprintf(str, sizeof(str), fmt, ap);
291        va_end(ap);
292
293        Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str)));
294        if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(),  '%s')", interlog_db, esc_str) )
295                Sql_ShowDebug(sql_handle);
296
297        return 0;
298}
299
300/*=============================================
301 * Does a mysql_ping to all connection handles
302 *---------------------------------------------*/
303int inter_sql_ping(int tid, unsigned int tick, int id, intptr data) 
304{
305        ShowInfo("Pinging SQL server to keep connection alive...\n");
306        Sql_Ping(sql_handle);
307        if( char_gm_read )
308                Sql_Ping(lsql_handle);
309        return 0;
310}
311
312
313int sql_ping_init(void)
314{
315        uint32 connection_timeout, connection_ping_interval;
316
317        // set a default value first
318        connection_timeout = 28800; // 8 hours
319
320        // ask the mysql server for the timeout value
321        if( SQL_SUCCESS == Sql_GetTimeout(sql_handle, &connection_timeout) && connection_timeout < 60 )
322                connection_timeout = 60;
323
324        // establish keepalive
325        connection_ping_interval = connection_timeout - 30; // 30-second reserve
326        add_timer_func_list(inter_sql_ping, "inter_sql_ping");
327        add_timer_interval(gettick() + connection_ping_interval*1000, inter_sql_ping, 0, 0, connection_ping_interval*1000);
328
329        return 0;
330}
331
332#endif //TXT_SQL_CONVERT
333
334// initialize
335int inter_init_sql(const char *file)
336{
337        //int i;
338
339        ShowInfo ("interserver initialize...\n");
340        inter_config_read(file);
341
342        //DB connection initialized
343        sql_handle = Sql_Malloc();
344        ShowInfo("Connect Character DB server.... (Character Server)\n");
345        if( SQL_ERROR == Sql_Connect(sql_handle, char_server_id, char_server_pw, char_server_ip, (uint16)char_server_port, char_server_db) )
346        {
347                Sql_ShowDebug(sql_handle);
348                Sql_Free(sql_handle);
349                exit(EXIT_FAILURE);
350        }
351#ifndef TXT_SQL_CONVERT
352        else if (inter_sql_test()) {
353                ShowStatus("Connect Success! (Character Server)\n");
354        }
355
356        if(char_gm_read) {
357                lsql_handle = Sql_Malloc();
358                ShowInfo("Connect Character DB server.... (login server)\n");
359                if( SQL_ERROR == Sql_Connect(lsql_handle, login_server_id, login_server_pw, login_server_ip, (uint16)login_server_port, login_server_db) )
360                {
361                        Sql_ShowDebug(lsql_handle);
362                        Sql_Free(lsql_handle);
363                        Sql_Free(sql_handle);
364                        exit(EXIT_FAILURE);
365                }
366                else
367                {
368                        ShowStatus ("Connect Success! (Login Server)\n");
369                }
370        }
371#endif //TXT_SQL_CONVERT
372        if( *default_codepage ) {
373                if( SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) )
374                        Sql_ShowDebug(sql_handle);
375#ifndef TXT_SQL_CONVERT
376                if( char_gm_read && SQL_ERROR == Sql_SetEncoding(lsql_handle, default_codepage) )
377                        Sql_ShowDebug(lsql_handle);
378#endif //TXT_SQL_CONVERT
379        }
380
381#ifndef TXT_SQL_CONVERT
382        wis_db = idb_alloc(DB_OPT_RELEASE_DATA);
383        inter_guild_sql_init();
384        inter_storage_sql_init();
385        inter_party_sql_init();
386        inter_pet_sql_init();
387        inter_homunculus_sql_init(); // albator
388        inter_accreg_sql_init();
389        inter_mail_sql_init();
390        inter_auction_sql_init();
391
392        sql_ping_init();
393#endif //TXT_SQL_CONVERT
394        return 0;
395}
396#ifndef TXT_SQL_CONVERT
397
398int inter_sql_test (void)
399{
400        const char fields[][24] = {
401                "father",       // version 1363
402                "fame",         // version 1491
403        };     
404        char buf[1024] = "";
405        char* p;
406        size_t len;
407        int i;
408
409        if( SQL_ERROR == Sql_GetColumnNames(sql_handle, char_db, buf, sizeof(buf), '\n') )
410                Sql_ShowDebug(sql_handle);
411
412        // check DB strings
413        for( i = 0; i < ARRAYLENGTH(fields); ++i )
414        {
415                len = strlen(fields[i]);
416                p = strstr(buf, fields[i]);
417                while( p != NULL && p[len] != '\n' )
418                        p = strstr(p, fields[i]);
419                if( p == NULL )
420                {
421                        ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db);
422                        if( lsql_handle )
423                                Sql_Free(lsql_handle);
424                        Sql_Free(sql_handle);
425                        exit(EXIT_FAILURE);
426                }
427        }
428
429        return 1;
430}
431
432// finalize
433void inter_final(void)
434{
435        wis_db->destroy(wis_db, NULL);
436
437        inter_guild_sql_final();
438        inter_storage_sql_final();
439        inter_party_sql_final();
440        inter_pet_sql_final();
441        inter_homunculus_sql_final();   //[orn]
442        inter_mail_sql_final();
443        inter_auction_sql_final();
444       
445        if (accreg_pt) aFree(accreg_pt);
446        return;
447}
448
449int inter_mapif_init(int fd)
450{
451        inter_guild_mapif_init(fd);
452
453        return 0;
454}
455
456
457//--------------------------------------------------------
458
459// GM message sending
460int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd)
461{
462        unsigned char buf[2048];
463
464        if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
465        WBUFW(buf,0) = 0x3800;
466        WBUFW(buf,2) = len;
467        WBUFL(buf,4) = color;
468        memcpy(WBUFP(buf,8), mes, len - 8);
469        mapif_sendallwos(sfd, buf, len);
470        return 0;
471}
472
473// Wis sending
474int mapif_wis_message(struct WisData *wd)
475{
476        unsigned char buf[2048];
477        if (wd->len > 2047-56) wd->len = 2047-56; //Force it to fit to avoid crashes. [Skotlex]
478
479        WBUFW(buf, 0) = 0x3801;
480        WBUFW(buf, 2) = 56 +wd->len;
481        WBUFL(buf, 4) = wd->id;
482        memcpy(WBUFP(buf, 8), wd->src, NAME_LENGTH);
483        memcpy(WBUFP(buf,32), wd->dst, NAME_LENGTH);
484        memcpy(WBUFP(buf,56), wd->msg, wd->len);
485        wd->count = mapif_sendall(buf,WBUFW(buf,2));
486
487        return 0;
488}
489
490// Wis sending result
491int mapif_wis_end(struct WisData *wd, int flag)
492{
493        unsigned char buf[27];
494
495        WBUFW(buf, 0)=0x3802;
496        memcpy(WBUFP(buf, 2),wd->src,24);
497        WBUFB(buf,26)=flag;
498        mapif_send(wd->fd,buf,27);
499        return 0;
500}
501
502// Account registry transfer to map-server
503static void mapif_account_reg(int fd, unsigned char *src)
504{
505        WBUFW(src,0)=0x3804; //NOTE: writing to RFIFO
506        mapif_sendallwos(fd, src, WBUFW(src,2));
507}
508
509// Send the requested account_reg
510int mapif_account_reg_reply(int fd,int account_id,int char_id, int type)
511{
512        struct accreg *reg=accreg_pt;
513        WFIFOHEAD(fd, 13 + 5000);
514        inter_accreg_fromsql(account_id,char_id,reg,type);
515       
516        WFIFOW(fd,0)=0x3804;
517        WFIFOL(fd,4)=account_id;
518        WFIFOL(fd,8)=char_id;
519        WFIFOB(fd,12)=type;
520        if(reg->reg_num==0){
521                WFIFOW(fd,2)=13;
522        }else{
523                int i,p;
524                for (p=13,i = 0; i < reg->reg_num && p < 5000; i++) {
525                        p+= sprintf((char*)WFIFOP(fd,p), "%s", reg->reg[i].str)+1; //We add 1 to consider the '\0' in place.
526                        p+= sprintf((char*)WFIFOP(fd,p), "%s", reg->reg[i].value)+1;
527                }
528                WFIFOW(fd,2)=p;
529                if (p>= 5000)
530                        ShowWarning("Too many acc regs for %d:%d, not all values were loaded.\n", account_id, char_id);
531        }
532        WFIFOSET(fd,WFIFOW(fd,2));
533        return 0;
534}
535
536int mapif_send_gmaccounts()
537{
538        int i, len = 4;
539        unsigned char buf[32000];
540
541        // forward the gm accounts to the map server
542        len = 4;
543        WBUFW(buf,0) = 0x2b15;
544                               
545        for(i = 0; i < GM_num; i++) {
546                WBUFL(buf,len) = gm_account[i].account_id;
547                WBUFB(buf,len+4) = (uint8)gm_account[i].level;
548                len += 5;
549        }
550        WBUFW(buf,2) = len;
551        mapif_sendall(buf, len);
552
553        return 0;
554}
555
556//Request to kick char from a certain map server. [Skotlex]
557int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
558{
559        if (fd >= 0)
560        {
561                WFIFOHEAD(fd,7);
562                WFIFOW(fd,0) = 0x2b1f;
563                WFIFOL(fd,2) = account_id;
564                WFIFOB(fd,6) = reason;
565                WFIFOSET(fd,7);
566                return 0;
567        }
568        return -1;
569}
570
571//--------------------------------------------------------
572
573// Existence check of WISP data
574int check_ttl_wisdata_sub(DBKey key, void *data, va_list ap)
575{
576        unsigned long tick;
577        struct WisData *wd = (struct WisData *)data;
578        tick = va_arg(ap, unsigned long);
579
580        if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX)
581                wis_dellist[wis_delnum++] = wd->id;
582
583        return 0;
584}
585
586int check_ttl_wisdata(void)
587{
588        unsigned long tick = gettick();
589        int i;
590
591        do {
592                wis_delnum = 0;
593                wis_db->foreach(wis_db, check_ttl_wisdata_sub, tick);
594                for(i = 0; i < wis_delnum; i++) {
595                        struct WisData *wd = (struct WisData*)idb_get(wis_db, wis_dellist[i]);
596                        ShowWarning("inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst);
597                        // removed. not send information after a timeout. Just no answer for the player
598                        //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
599                        idb_remove(wis_db, wd->id);
600                }
601        } while(wis_delnum >= WISDELLIST_MAX);
602
603        return 0;
604}
605
606//--------------------------------------------------------
607
608// GM message sending
609int mapif_parse_GMmessage(int fd)
610{
611        mapif_GMmessage(RFIFOP(fd,8), RFIFOW(fd,2), RFIFOL(fd,4), fd);
612        return 0;
613}
614
615
616// Wisp/page request to send
617int mapif_parse_WisRequest(int fd)
618{
619        struct WisData* wd;
620        static int wisid = 0;
621        char name[NAME_LENGTH];
622        char esc_name[NAME_LENGTH*2+1];// escaped name
623        char* data;
624        size_t len;
625
626
627        if ( fd <= 0 ) {return 0;} // check if we have a valid fd
628
629        if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
630                ShowWarning("inter: Wis message size too long.\n");
631                return 0;
632        } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
633                ShowError("inter: Wis message doesn't exist.\n");
634                return 0;
635        }
636       
637        safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
638
639        Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
640        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) )
641                Sql_ShowDebug(sql_handle);
642
643        // search if character exists before to ask all map-servers
644        if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
645        {
646                unsigned char buf[27];
647                WBUFW(buf, 0) = 0x3802;
648                memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
649                WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
650                mapif_send(fd, buf, 27);
651        }
652        else
653        {// Character exists. So, ask all map-servers
654                // to be sure of the correct name, rewrite it
655                Sql_GetData(sql_handle, 0, &data, &len);
656                memset(name, 0, NAME_LENGTH);
657                memcpy(name, data, min(len, NAME_LENGTH));
658                // if source is destination, don't ask other servers.
659                if( strncmp((const char*)RFIFOP(fd,4), name, NAME_LENGTH) == 0 )
660                {
661                        uint8 buf[27];
662                        WBUFW(buf, 0) = 0x3802;
663                        memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
664                        WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
665                        mapif_send(fd, buf, 27);
666                }
667                else
668                {
669
670                        CREATE(wd, struct WisData, 1);
671
672                        // Whether the failure of previous wisp/page transmission (timeout)
673                        check_ttl_wisdata();
674
675                        wd->id = ++wisid;
676                        wd->fd = fd;
677                        wd->len= RFIFOW(fd,2)-52;
678                        memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH);
679                        memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH);
680                        memcpy(wd->msg, RFIFOP(fd,52), wd->len);
681                        wd->tick = gettick();
682                        idb_put(wis_db, wd->id, wd);
683                        mapif_wis_message(wd);
684                }
685        }
686
687        Sql_FreeResult(sql_handle);
688        return 0;
689}
690
691
692// Wisp/page transmission result
693int mapif_parse_WisReply(int fd)
694{
695        int id, flag;
696        struct WisData *wd;
697
698        id = RFIFOL(fd,2);
699        flag = RFIFOB(fd,6);
700        wd = (struct WisData*)idb_get(wis_db, id);
701        if (wd == NULL)
702                return 0;       // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
703
704        if ((--wd->count) <= 0 || flag != 1) {
705                mapif_wis_end(wd, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
706                idb_remove(wis_db, id);
707        }
708
709        return 0;
710}
711
712// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
713int mapif_parse_WisToGM(int fd)
714{
715        unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
716       
717        ShowDebug("Sent packet back!\n");
718        memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
719        WBUFW(buf, 0) = 0x3803;
720        mapif_sendall(buf, RFIFOW(fd,2));
721
722        return 0;
723}
724
725// Save account_reg into sql (type=2)
726int mapif_parse_Registry(int fd)
727{
728        int j,p,len, max;
729        struct accreg *reg=accreg_pt;
730       
731        memset(accreg_pt,0,sizeof(struct accreg));
732        switch (RFIFOB(fd, 12)) {
733        case 3: //Character registry
734                max = GLOBAL_REG_NUM;
735        break;
736        case 2: //Account Registry
737                max = ACCOUNT_REG_NUM;
738        break;
739        case 1: //Account2 registry, must be sent over to login server.
740                return save_accreg2(RFIFOP(fd,4), RFIFOW(fd,2)-4);
741        default:
742                return 1;
743        }
744        for(j=0,p=13;j<max && p<RFIFOW(fd,2);j++){
745                sscanf((char*)RFIFOP(fd,p), "%31c%n",reg->reg[j].str,&len);
746                reg->reg[j].str[len]='\0';
747                p +=len+1; //+1 to skip the '\0' between strings.
748                sscanf((char*)RFIFOP(fd,p), "%255c%n",reg->reg[j].value,&len);
749                reg->reg[j].value[len]='\0';
750                p +=len+1;
751        }
752        reg->reg_num=j;
753
754        inter_accreg_tosql(RFIFOL(fd,4),RFIFOL(fd,8),reg, RFIFOB(fd,12));
755        mapif_account_reg(fd,RFIFOP(fd,0));     // Send updated accounts to other map servers.
756        return 0;
757}
758
759// Request the value of all registries.
760int mapif_parse_RegistryRequest(int fd)
761{
762        //Load Char Registry
763        if (RFIFOB(fd,12)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3);
764        //Load Account Registry
765        if (RFIFOB(fd,11)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2);
766        //Ask Login Server for Account2 values.
767        if (RFIFOB(fd,10)) request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6));
768        return 1;
769}
770
771static void mapif_namechange_ack(int fd, int account_id, int char_id, int type, int flag, char *name)
772{
773        WFIFOHEAD(fd, NAME_LENGTH+13);
774        WFIFOW(fd, 0) = 0x3806;
775        WFIFOL(fd, 2) = account_id;
776        WFIFOL(fd, 6) = char_id;
777        WFIFOB(fd,10) = type;
778        WFIFOB(fd,11) = flag;
779        memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
780        WFIFOSET(fd, NAME_LENGTH+13);
781}
782
783int mapif_parse_NameChangeRequest(int fd)
784{
785        int account_id, char_id, type;
786        char* name;
787        int i;
788
789        account_id = RFIFOL(fd,2);
790        char_id = RFIFOL(fd,6);
791        type = RFIFOB(fd,10);
792        name = (char*)RFIFOP(fd,11);
793
794        // Check Authorised letters/symbols in the name
795        if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
796                for (i = 0; i < NAME_LENGTH && name[i]; i++)
797                if (strchr(char_name_letters, name[i]) == NULL) {
798                        mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
799                        return 0;
800                }
801        } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
802                for (i = 0; i < NAME_LENGTH && name[i]; i++)
803                if (strchr(char_name_letters, name[i]) != NULL) {
804                        mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
805                        return 0;
806                }
807        }
808        //TODO: type holds the type of object to rename.
809        //If it were a player, it needs to have the guild information and db information
810        //updated here, because changing it on the map won't make it be saved [Skotlex]
811
812        //name allowed.
813        mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
814        return 0;
815}
816
817//--------------------------------------------------------
818int inter_parse_frommap(int fd)
819{
820        int cmd;
821        int len = 0;
822        cmd = RFIFOW(fd,0);
823        // interŽIŠÇŠ‚©‚𒲂ׂé
824        if(cmd < 0x3000 || cmd >= 0x3000 + ARRAYLENGTH(inter_recv_packet_length) || inter_recv_packet_length[cmd - 0x3000] == 0)
825                return 0;
826
827        // ƒpƒPƒbƒg’·‚𒲂ׂé
828        if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
829                return 2;
830
831        switch(cmd) {
832        case 0x3000: mapif_parse_GMmessage(fd); break;
833        case 0x3001: mapif_parse_WisRequest(fd); break;
834        case 0x3002: mapif_parse_WisReply(fd); break;
835        case 0x3003: mapif_parse_WisToGM(fd); break;
836        case 0x3004: mapif_parse_Registry(fd); break;
837        case 0x3005: mapif_parse_RegistryRequest(fd); break;
838        case 0x3006: mapif_parse_NameChangeRequest(fd); break;
839        default:
840                if(  inter_party_parse_frommap(fd)
841                  || inter_guild_parse_frommap(fd)
842                  || inter_storage_parse_frommap(fd)
843                  || inter_pet_parse_frommap(fd)
844                  || inter_homunculus_parse_frommap(fd)
845                  || inter_mail_parse_frommap(fd)
846                  || inter_auction_parse_frommap(fd)
847                  || inter_quest_parse_frommap(fd)
848                   )
849                        break;
850                else
851                        return 0;
852        }
853
854        RFIFOSKIP(fd, len);
855        return 1;
856}
857
858// RFIFO check
859int inter_check_length(int fd, int length)
860{
861        if(length == -1) {      // v-len packet
862                if(RFIFOREST(fd) < 4)   // packet not yet
863                        return 0;
864                length = RFIFOW(fd, 2);
865        }
866
867        if((int)RFIFOREST(fd) < length) // packet not yet
868                return 0;
869
870        return length;
871}
872#endif //TXT_SQL_CONVERT
Note: See TracBrowser for help on using the browser.