summaryrefslogblamecommitdiff
path: root/src/char_sql/inter.c
blob: 800beaf485489bcc4fd61e876289836016352cde (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                 

                                                                                 
 



                                           



                                
                            
                   


                         



                     

                    
 
                             




                                      
                              





                                       









                                                                 
  
 
                    









                                                                 

  




                                             
  
                                 



                                                          





































                                                                                                          


                                     
                                                             
 



























                                                                                    


             
                            
 


                                         





                                            




























































































                                                                      


                         
                              
 
















                                                                      

 
             
                                 
 














































                                                                                               

 


                                
 
             

 


                                                          









                                                                              


              












                                                    
 
 
                     
                                                
 







                                             

 
                                                  
 




                                                 


                                 
                                                    
 




















                                                          




                                                          




                                                             
 


                                                
 
             

 






















                                                                                                                                  




                                                          
                                  
 

                                                     

 
                            



































































                                                                                                                                  

 
                                



                                                    
 

                                                                                                                                                      
 





                                                                                                                                  
 
             

 
                                     
                               
 















                                                                          


                                   
                                      
 

                                                        

 
                                                          
                                
 


                              
                                    




                                                                            
                                  


































                                                                           


              
                                           
 










                                                     
 
//
// original code from athena
// SQL conversion by Jioh L. Jung
//

#include <string.h>
#include <stdlib.h>

#include "char.h"
#include "strlib.h"
#include "inter.h"
#include "int_party.h"
#include "int_guild.h"
#include "int_storage.h"
#include "int_pet.h"
#include "lock.h"

#define WISDATA_TTL		(60*1000)   // Wisデータの生存時間(60秒)
#define WISDELLIST_MAX	256     // Wisデータ削除リストの要素数

struct accreg
{
    int  account_id, reg_num;
    struct global_reg reg[ACCOUNT_REG_NUM];
};

static struct accreg *accreg_pt;

int  party_share_level = 10;
MYSQL mysql_handle;
MYSQL_RES *sql_res;
MYSQL_ROW sql_row;
int  sql_fields, sql_cnt;
char tmp_sql[65535];

MYSQL lmysql_handle;
char tmp_lsql[65535];
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";

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";

// sending packet list
int  inter_send_packet_length[] = {
    -1, -1, 27, 0, -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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

// recv. packet list
int  inter_recv_packet_length[] = {
    -1, -1, 7, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    6, -1, 0, 0, 0, 0, 0, 0, 10, -1, 0, 0, 0, 0, 0, 0,
    72, 6, 52, 14, 10, 29, 6, -1, 34, 0, 0, 0, 0, 0, 0, 0,
    -1, 6, -1, 0, 55, 19, 6, -1, 14, -1, -1, -1, 14, 19, 186, -1,
    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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

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;

//--------------------------------------------------------
// Save account_reg to sql (type=2)
int inter_accreg_tosql (int account_id, struct accreg *reg)
{

    int  j;
    char temp_str[32];
    if (account_id <= 0)
        return 0;
    reg->account_id = account_id;

    //`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);
    if (mysql_query (&mysql_handle, tmp_sql))
    {
        printf ("DB server Error (delete `global_reg_value`)- %s\n",
                mysql_error (&mysql_handle));
    }

    if (reg->reg_num <= 0)
        return 0;

    for (j = 0; j < reg->reg_num; j++)
    {
        if (reg->reg[j].str != NULL)
        {
            sprintf (tmp_sql,
                     "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES (2,'%d', '%s','%d')",
                     reg_db, reg->account_id, jstrescapecpy (temp_str,
                                                             reg->reg[j].str),
                     reg->reg[j].value);
            if (mysql_query (&mysql_handle, tmp_sql))
            {
                printf ("DB server Error (insert `global_reg_value`)- %s\n",
                        mysql_error (&mysql_handle));
            }
        }
    }
    return 0;
}

// Load account_reg from sql (type=2)
int inter_accreg_fromsql (int account_id, struct accreg *reg)
{
    int  j = 0;
    if (reg == NULL)
        return 0;
    memset (reg, 0, sizeof (struct accreg));
    reg->account_id = account_id;

    //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`)
    sprintf (tmp_sql,
             "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",
             reg_db, reg->account_id);
    if (mysql_query (&mysql_handle, tmp_sql))
    {
        printf ("DB server Error (select `global_reg_value`)- %s\n",
                mysql_error (&mysql_handle));
    }
    sql_res = mysql_store_result (&mysql_handle);

    if (sql_res)
    {
        for (j = 0; (sql_row = mysql_fetch_row (sql_res)); j++)
        {
            memcpy (reg->reg[j].str, sql_row[0], 32);
            reg->reg[j].value = atoi (sql_row[1]);
        }
        mysql_free_result (sql_res);
    }
    reg->reg_num = j;
    return 0;
}

// Initialize
int inter_accreg_sql_init ()
{
    CREATE (accreg_pt, struct accreg, 1);
    return 0;

}

/*==========================================
 * read config file
 *------------------------------------------
 */
int inter_config_read (const char *cfgName)
{
    printf ("start reading interserver configuration: %s\n", cfgName);
    int  i;
    char line[1024], w1[1024], w2[1024];
    FILE *fp;

    fp = fopen_ (cfgName, "r");
    if (fp == NULL)
    {
        printf ("file not found: %s\n", cfgName);
        return 1;
    }
    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);
            printf ("set char_server_ip : %s\n", w2);
        }
        else if (strcmpi (w1, "char_server_port") == 0)
        {
            char_server_port = atoi (w2);
            printf ("set char_server_port : %s\n", w2);
        }
        else if (strcmpi (w1, "char_server_id") == 0)
        {
            strcpy (char_server_id, w2);
            printf ("set char_server_id : %s\n", w2);
        }
        else if (strcmpi (w1, "char_server_pw") == 0)
        {
            strcpy (char_server_pw, w2);
            printf ("set char_server_pw : %s\n", w2);
        }
        else if (strcmpi (w1, "char_server_db") == 0)
        {
            strcpy (char_server_db, w2);
            printf ("set char_server_db : %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);
            printf ("set login_server_ip : %s\n", w2);
        }
        else if (strcmpi (w1, "login_server_port") == 0)
        {
            login_server_port = atoi (w2);
            printf ("set login_server_port : %s\n", w2);
        }
        else if (strcmpi (w1, "login_server_id") == 0)
        {
            strcpy (login_server_id, w2);
            printf ("set login_server_id : %s\n", w2);
        }
        else if (strcmpi (w1, "login_server_pw") == 0)
        {
            strcpy (login_server_pw, w2);
            printf ("set login_server_pw : %s\n", w2);
        }
        else if (strcmpi (w1, "login_server_db") == 0)
        {
            strcpy (login_server_db, w2);
            printf ("set login_server_db : %s\n", w2);
        }
        else if (strcmpi (w1, "party_share_level") == 0)
        {
            party_share_level = atoi (w2);
            if (party_share_level < 0)
                party_share_level = 0;
        }
        else if (strcmpi (w1, "import") == 0)
        {
            inter_config_read (w2);
        }
        else if (strcmpi (w1, "login_server_db") == 0)
        {
            strcpy (login_server_db, w2);
            printf ("set login_server_db : %s\n", w2);
        }
    }
    fclose_ (fp);

    printf ("success reading interserver configuration\n");

    return 0;
}

// Save interlog into sql
int inter_log (char *fmt, ...)
{
    char str[255];
    char temp_str[255];
    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))
    {
        printf ("DB server Error (insert `interlog`)- %s\n",
                mysql_error (&mysql_handle));
    }

    va_end (ap);
    return 0;
}

// initialize
int inter_init (const char *file)
{
    //int i;

    printf ("interserver initialize...\n");
    inter_config_read (file);

    //DB connection initialized
    mysql_init (&mysql_handle);
    printf ("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
        printf ("%s\n", mysql_error (&mysql_handle));
        exit (1);
    }
    else
    {
        printf ("Connect Success! (Character Server)\n");
    }

    mysql_init (&lmysql_handle);
    printf ("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
        printf ("%s\n", mysql_error (&lmysql_handle));
        exit (1);
    }
    else
    {
        printf ("Connect Success! (Login Server)");
    }
    wis_db = numdb_init ();
    inter_guild_sql_init ();
    inter_storage_sql_init ();
    inter_party_sql_init ();

    inter_pet_sql_init ();
    inter_accreg_sql_init ();

    //printf ("interserver timer initializing : %d sec...\n",autosave_interval);
    //i=add_timer_interval(gettick()+autosave_interval,inter_save_timer,0,0,autosave_interval);

    return 0;
}

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 char buf[len];

    WBUFW (buf, 0) = 0x3800;
    WBUFW (buf, 2) = len;
    memcpy (WBUFP (buf, 4), mes, len - 4);
    mapif_sendall (buf, len);
    printf ("\033[1;34m inter server: GM[len:%d] - '%s' \033[0m\n", len, mes);
    return 0;
}

// Wis sending
int mapif_wis_message (struct WisData *wd)
{
    unsigned char buf[56 + wd->len];

    WBUFW (buf, 0) = 0x3801;
    WBUFW (buf, 2) = 56 + wd->len;
    WBUFL (buf, 4) = wd->id;
    memcpy (WBUFP (buf, 8), wd->src, 24);
    memcpy (WBUFP (buf, 32), wd->dst, 24);
    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)];
    memcpy (WBUFP (buf, 0), src, WBUFW (src, 2));
    WBUFW (buf, 0) = 0x3804;
    mapif_sendallwos (fd, buf, WBUFW (buf, 2));
    return 0;
}

// Send the requested account_reg
int mapif_account_reg_reply (int fd, int account_id)
{
    struct accreg *reg = accreg_pt;
    inter_accreg_fromsql (account_id, reg);

    WFIFOW (fd, 0) = 0x3804;
    WFIFOL (fd, 4) = account_id;
    if (reg->reg_num == 0)
    {
        WFIFOW (fd, 2) = 8;
    }
    else
    {
        int  j, p;
        for (j = 0, p = 8; j < reg->reg_num; j++, p += 36)
        {
            memcpy (WFIFOP (fd, p), reg->reg[j].str, 32);
            WFIFOL (fd, p + 32) = reg->reg[j].value;
        }
        WFIFOW (fd, 2) = p;
    }
    WFIFOSET (fd, WFIFOW (fd, 2));
    return 0;
}

//--------------------------------------------------------

// Existence check of WISP data
int check_ttl_wisdata_sub (void *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 ()
{
    unsigned long tick = gettick ();
    int  i;

    do
    {
        wis_delnum = 0;
        numdb_foreach (wis_db, check_ttl_wisdata_sub, tick);
        for (i = 0; i < wis_delnum; i++)
        {
            struct WisData *wd = numdb_search (wis_db, wis_dellist[i]);
            printf ("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
            numdb_erase (wis_db, wd->id);
            free (wd);
        }
    }
    while (wis_delnum >= WISDELLIST_MAX);

    return 0;
}

//--------------------------------------------------------

// GM message sending
int mapif_parse_GMmessage (int fd)
{
    mapif_GMmessage (RFIFOP (fd, 4), RFIFOW (fd, 2));
    return 0;
}

// Wisp/page request to send
int mapif_parse_WisRequest (int fd)
{
    struct WisData *wd;
    static int wisid = 0;

    if (RFIFOW (fd, 2) - 52 >= sizeof (wd->msg))
    {
        printf ("inter: Wis message size too long.\n");
        return 0;
    }
    else if (RFIFOW (fd, 2) - 52 <= 0)
    {                           // normaly, impossible, but who knows...
        printf ("inter: Wis message doesn't exist.\n");
        return 0;
    }
    sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db,
             (int) RFIFOP (fd, 28));
    if (mysql_query (&mysql_handle, tmp_sql))
    {
        printf ("DB server Error - %s\n", mysql_error (&mysql_handle));
    }
    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), 24);
        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 (RFIFOP (fd, 28), 0, 24);
        strncpy (RFIFOP (fd, 28), sql_row[0], 24);
        // if source is destination, don't ask other servers.
        if (strcmp (RFIFOP (fd, 4), RFIFOP (fd, 28)) == 0)
        {
            unsigned char buf[27];
            WBUFW (buf, 0) = 0x3802;
            memcpy (WBUFP (buf, 2), RFIFOP (fd, 4), 24);
            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), 24);
            memcpy (wd->dst, RFIFOP (fd, 28), 24);
            memcpy (wd->msg, RFIFOP (fd, 52), wd->len);
            wd->tick = gettick ();
            numdb_insert (wis_db, wd->id, wd);
            mapif_wis_message (wd);
        }
    }

    return 0;
}

// Wisp/page transmission result
int mapif_parse_WisReply (int fd)
{
    int  id = RFIFOL (fd, 2), flag = RFIFOB (fd, 6);
    struct WisData *wd = numdb_search (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
        numdb_erase (wis_db, id);
        free (wd);
    }

    return 0;
}

// Save account_reg into sql (type=2)
int mapif_parse_AccReg (int fd)
{
    int  j, p;
    struct accreg *reg = accreg_pt;
    int  account_id = RFIFOL (fd, 4);
    memset (accreg_pt, 0, sizeof (struct accreg));

    for (j = 0, p = 8; j < ACCOUNT_REG_NUM && p < RFIFOW (fd, 2);
         j++, p += 36)
    {
        memcpy (reg->reg[j].str, RFIFOP (fd, p), 32);
        reg->reg[j].value = RFIFOL (fd, p + 32);
    }
    reg->reg_num = j;

    inter_accreg_tosql (account_id, reg);
    mapif_account_reg (fd, RFIFOP (fd, 0)); // Send confirm message to map
    return 0;
}

// Request the value of account_reg
int mapif_parse_AccRegRequest (int fd)
{
//  printf("mapif: accreg request\n");
    return mapif_account_reg_reply (fd, RFIFOL (fd, 2));
}

//--------------------------------------------------------
int inter_parse_frommap (int fd)
{
    int  cmd = RFIFOW (fd, 0);
    int  len = 0;

    // inter鯖管轄かを調べる
    if (cmd < 0x3000 || cmd >= 0x3000 + (sizeof (inter_recv_packet_length) /
                                         sizeof (inter_recv_packet_length
                                                 [0])))
        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 0x3004:
            mapif_parse_AccReg (fd);
            break;
        case 0x3005:
            mapif_parse_AccRegRequest (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;
            return 0;
    }
    RFIFOSKIP (fd, len);
    return 1;
}

// RFIFO check
int inter_check_length (int fd, int length)
{
    if (length == -1)
    {                           // v-len packet
        if (RFIFOREST (fd) < 4) // packet not yet
            return 0;
        length = RFIFOW (fd, 2);
    }

    if (RFIFOREST (fd) < length)    // packet not yet
        return 0;

    return length;
}