static int dbs_packet_charlock(t_d2dbs_connection * conn) { char CharName[MAX_CHARNAME_LEN]; char AccountName[MAX_USERNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_char_lock * charlock; char * readpos; readpos = conn->ReadBuf; charlock = (t_d2gs_d2dbs_char_lock*)readpos; readpos += sizeof(*charlock); std::strncpy(AccountName, readpos, MAX_USERNAME_LEN); if (AccountName[MAX_USERNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max account name length exceeded"); return -1; } readpos += std::strlen(AccountName) + 1; std::strncpy(CharName, readpos, MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max char name length exceeded"); return -1; } readpos += std::strlen(CharName) + 1; std::strncpy(RealmName, readpos, MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max realm name length exceeded"); return -1; } readpos += std::strlen(RealmName) + 1; if (readpos != conn->ReadBuf + bn_short_get(charlock->h.size)) { eventlog(eventlog_level_error, __FUNCTION__, "request packet size error"); return -1; } if (bn_int_get(charlock->lockstatus)) { if (cl_lock_char((unsigned char*)CharName, (unsigned char*)RealmName, conn->serverid) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to lock character %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); } else { eventlog(eventlog_level_info, __FUNCTION__, "lock character %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); } } else { if (cl_unlock_char((unsigned char*)CharName, (unsigned char*)RealmName, conn->serverid) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to unlock character %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); } else { eventlog(eventlog_level_info, __FUNCTION__, "unlock character %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); } } return 1; }
static int on_client_gameinforeq(t_connection * c, t_packet * packet) { t_game_charinfo * info; t_packet * rpacket; char const * gamename; t_game * game; unsigned int seqno, n; if (!(gamename=packet_get_str_const(packet,sizeof(t_client_d2cs_gameinforeq),MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } if (!(game=d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"game %s not found",gamename); return 0; } seqno=bn_short_get(packet->u.client_d2cs_gameinforeq.seqno); if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gameinforeply)); packet_set_type(rpacket,D2CS_CLIENT_GAMEINFOREPLY); bn_short_set(&rpacket->u.d2cs_client_gameinforeply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.gameflag,game_get_gameflag(game)); bn_int_set(&rpacket->u.d2cs_client_gameinforeply.etime,std::time(NULL)-d2cs_game_get_create_time(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.charlevel,game_get_charlevel(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.leveldiff,game_get_leveldiff(game)); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.maxchar,game_get_maxchar(game)); packet_append_string(rpacket, game_get_desc(game) ? game_get_desc(game) : NULL); n=0; BEGIN_LIST_TRAVERSE_DATA_CONST(game_get_charlist(game),info,t_game_charinfo) { if (!info->charname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname in game %s char list",gamename); continue; } packet_append_string(rpacket,info->charname); bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.chclass[n],info->chclass); /* GUI is limited to a max level of 255 */ if (info->level < 255) { bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n],info->level); } else { bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n], 255); } n++; } END_LIST_TRAVERSE_DATA_CONST() bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.currchar,n); if (n!=game_get_currchar(game)) { eventlog(eventlog_level_error,__FUNCTION__,"game %s character list corrupted",gamename); } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); }
static int dbs_packet_updateladder(t_d2dbs_connection * conn) { char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_update_ladder * updateladder; char * readpos; t_d2ladder_info charladderinfo; readpos = conn->ReadBuf; updateladder = (t_d2gs_d2dbs_update_ladder *)readpos; readpos += sizeof(*updateladder); std::strncpy(CharName, readpos, MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max char name length exceeded"); return -1; } readpos += std::strlen(CharName) + 1; std::strncpy(RealmName, readpos, MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max realm name length exceeded"); return -1; } readpos += std::strlen(RealmName) + 1; if (readpos != conn->ReadBuf + bn_short_get(updateladder->h.size)) { eventlog(eventlog_level_error, __FUNCTION__, "request packet size error"); return -1; } std::strcpy(charladderinfo.charname, CharName); charladderinfo.experience = bn_int_get(updateladder->charexplow); charladderinfo.level = bn_int_get(updateladder->charlevel); charladderinfo.status = bn_short_get(updateladder->charstatus); charladderinfo.chclass = bn_short_get(updateladder->charclass); eventlog(eventlog_level_info, __FUNCTION__, "update ladder for %s@%s for gs %s(%d)", CharName, RealmName, conn->serverip, conn->serverid); d2ladder_update(&charladderinfo); return 1; }
static int d2ladder_append_ladder(unsigned int type, t_d2ladderfile_ladderinfo * info) { t_d2cs_client_ladderinfo * ladderinfo; unsigned short ladderstatus; unsigned short status; unsigned char class; if (!info) { log_error("got NULL info"); return -1; } if (type > max_ladder_type) { log_error("ladder type %d exceed max ladder type %d",type,max_ladder_type); return -1; } if (!ladder_data[type].info) { log_error("ladder data info not initialized"); return -1; } if (ladder_data[type].curr_len >= ladder_data[type].len) { log_error("ladder data overflow %d > %d", ladder_data[type].curr_len, ladder_data[type].len); return -1; } status = bn_short_get(info->status); class = bn_byte_get(info->class); ladderstatus = (status & LADDERSTATUS_FLAG_DIFFICULTY); if (charstatus_get_hardcore(status)) { ladderstatus |= LADDERSTATUS_FLAG_HARDCORE; if (charstatus_get_dead(status)) { ladderstatus |= LADDERSTATUS_FLAG_DEAD; } } if (charstatus_get_expansion(status)) { ladderstatus |= LADDERSTATUS_FLAG_EXPANSION; ladderstatus |= min(class,D2CHAR_EXP_CLASS_MAX); } else {
/* size of the _complete_ packet, not the amount currently received or sent */ extern unsigned int packet_get_size(t_packet const * packet) { unsigned int size; if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } switch (packet->pclass) { case packet_class_init: size = sizeof(t_client_initconn); break; case packet_class_bnet: size = (unsigned int)bn_short_get(packet->u.bnet.h.size); break; case packet_class_file: size = (unsigned int)bn_short_get(packet->u.file.h.size); break; case packet_class_udp: size = packet->len; break; case packet_class_raw: size = packet->len; break; case packet_class_d2game: size = packet->len; /* FIXME: does header not contain the size? */ break; case packet_class_d2gs: size = (unsigned int)bn_short_get(packet->u.d2cs_d2gs.h.size); break; case packet_class_d2cs_bnetd: size = (unsigned int)bn_short_get(packet->u.d2cs_bnetd.h.size); break; case packet_class_d2cs: size = (unsigned int)bn_short_get(packet->u.d2cs_client.h.size); break; case packet_class_w3route: size = (unsigned int)bn_short_get(packet->u.w3route.h.size); break; case packet_class_wolgameres: /* PELISH: We check and return size explicitly in this case, because we need to check MAX_WOL_GAMERES_PACKET_SIZE */ { size = (unsigned int)bn_short_nget(packet->u.wolgameres.h.size); if (size == 0) /* RNGD sends size on rngd_size */ size = (unsigned int)bn_short_nget(packet->u.wolgameres.h.rngd_size); // if (size>MAX_WOL_GAMERES_PACKET_SIZE) { /* PELISH: Fix for bug but also disable WOL gameres */ if (size>MAX_PACKET_SIZE) { // eventlog(eventlog_level_error,__FUNCTION__,"packet has bad size %u",size); return 0; } } return size; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return 0; } if (size>MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"packet has bad size %u",size); return 0; } return size; }
extern char const * packet_get_type_str(t_packet const * packet, t_packet_dir dir) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return "unknown"; } switch (dir) { case packet_dir_from_client: switch (packet->pclass) { case packet_class_init: return "CLIENT_INITCONN"; case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case CLIENT_COMPINFO1: return "CLIENT_COMPINFO1"; case CLIENT_COMPINFO2: return "CLIENT_COMPINFO2"; case CLIENT_COUNTRYINFO1: return "CLIENT_COUNTRYINFO1"; case CLIENT_COUNTRYINFO_109: return "CLIENT_COUNTRYINFO_109"; case CLIENT_CREATEACCTREQ1: return "CLIENT_CREATEACCTREQ1"; case CLIENT_UNKNOWN_2B: return "CLIENT_UNKNOWN_2B"; case CLIENT_PROGIDENT: return "CLIENT_PROGIDENT"; case CLIENT_AUTHREQ1: return "CLIENT_AUTHREQ1"; case CLIENT_AUTHREQ_109: return "CLIENT_AUTHREQ_109"; case CLIENT_REGSNOOPREPLY: return "CLIENT_REGSNOOPREPLY"; case CLIENT_ICONREQ: return "CLIENT_ICONREQ"; case CLIENT_LADDERSEARCHREQ: return "CLIENT_LADDERSEARCHREQ"; case CLIENT_CDKEY: return "CLIENT_CDKEY"; case CLIENT_CDKEY2: return "CLIENT_CDKEY2"; case CLIENT_CDKEY3: return "CLIENT_CDKEY3"; case CLIENT_REALMLISTREQ: return "CLIENT_REALMLISTREQ"; case CLIENT_REALMLISTREQ_110: return "CLIENT_REALMLISTREQ_110"; case CLIENT_PROFILEREQ: return "CLIENT_PROFILEREQ"; case CLIENT_UNKNOWN_37: return "CLIENT_UNKNOWN_37"; case CLIENT_UNKNOWN_39: return "CLIENT_UNKNOWN_39"; case CLIENT_LOGINREQ2: return "CLIENT_LOGINREQ2"; case CLIENT_MOTD_W3: return "CLIENT_MOTD_W3"; case CLIENT_LOGINREQ_W3: return "CLIENT_LOGINREQ_W3"; case CLIENT_LOGONPROOFREQ: return "CLIENT_LOGONPROOFREQ"; case CLIENT_CREATEACCOUNT_W3: return "CLIENT_CREATEACCOUNT_W3"; case CLIENT_PASSCHANGEREQ: return "CLIENT_PASSCHANGEREQ"; case CLIENT_PASSCHANGEPROOFREQ: return "CLIENT_PASSCHANGEPROOFREQ"; case CLIENT_CHANGEGAMEPORT: return "CLIENT_CHANGEGAMEPORT"; case CLIENT_CREATEACCTREQ2: return "CLIENT_CREATEACCTREQ2"; case CLIENT_UDPOK: return "CLIENT_UDPOK"; case CLIENT_FILEINFOREQ: return "CLIENT_FILEINFOREQ"; case CLIENT_STATSREQ: return "CLIENT_STATSREQ"; case CLIENT_LOGINREQ1: return "CLIENT_LOGINREQ1"; case CLIENT_CHANGEPASSREQ: return "CLIENT_CHANGEPASSREQ"; case CLIENT_PLAYERINFOREQ: return "CLIENT_PLAYERINFOREQ"; case CLIENT_PROGIDENT2: return "CLIENT_PROGIDENT2"; case CLIENT_JOINCHANNEL: return "CLIENT_JOINCHANNEL"; case CLIENT_MESSAGE: return "CLIENT_MESSAGE"; case CLIENT_GAMELISTREQ: return "CLIENT_GAMELISTREQ"; case CLIENT_STARTGAME1: return "CLIENT_STARTGAME1"; case CLIENT_UNKNOWN_1B: return "CLIENT_UNKNOWN_1B"; case CLIENT_STARTGAME3: return "CLIENT_STARTGAME3"; case CLIENT_STARTGAME4: return "CLIENT_STARTGAME4"; case CLIENT_CLOSEGAME: return "CLIENT_CLOSEGAME"; case CLIENT_CLOSEGAME2: return "CLIENT_CLOSEGAME2"; case CLIENT_LEAVECHANNEL: return "CLIENT_LEAVECHANNEL"; case CLIENT_MAPAUTHREQ1: return "CLIENT_MAPAUTHREQ1"; case CLIENT_MAPAUTHREQ2: return "CLIENT_MAPAUTHREQ2"; case CLIENT_ADREQ: return "CLIENT_ADREQ"; case CLIENT_ADACK: return "CLIENT_ADACK"; case CLIENT_ADCLICK: return "CLIENT_ADCLICK"; case CLIENT_ADCLICK2: return "CLIENT_ADCLICK2"; case CLIENT_UNKNOWN_17: return "CLIENT_UNKNOWN_17"; case CLIENT_UNKNOWN_24: return "CLIENT_UNKNOWN_24"; case CLIENT_LADDERREQ: return "CLIENT_LADDERREQ"; case CLIENT_ECHOREPLY: return "CLIENT_ECHOREPLY"; case CLIENT_PINGREQ: return "CLIENT_PINGREQ"; case CLIENT_GAME_REPORT: return "CLIENT_GAME_REPORT"; case CLIENT_JOIN_GAME: return "CLIENT_JOIN_GAME"; case CLIENT_STATSUPDATE: return "CLIENT_STATSUPDATE"; case CLIENT_REALMJOINREQ_109: return "CLIENT_REALMJOINREQ_109"; case CLIENT_CHANGECLIENT: return "CLIENT_CHANGECLIENT"; case CLIENT_SETEMAILREPLY: return "CLIENT_SETEMAILREPLY"; case CLIENT_GETPASSWORDREQ: return "CLIENT_GETPASSWORDREQ"; case CLIENT_CHANGEEMAILREQ: return "CLIENT_CHANGEEMAILREQ"; case CLIENT_CRASHDUMP: return "CLIENT_CRASHDUMP"; case CLIENT_FINDANONGAME: return "CLIENT_FINDANONGAME"; case CLIENT_ARRANGEDTEAM_FRIENDSCREEN: return "CLIENT_ARRANGEDTEAM_FRIENDSCREEN"; case CLIENT_ARRANGEDTEAM_INVITE_FRIEND: return "CLIENT_ARRANGEDTEAM_INVITE_FRIEND"; case CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE: return "CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE"; case CLIENT_FRIENDSLISTREQ: return "CLIENT_FRIENDSLISTREQ"; case CLIENT_FRIENDINFOREQ: return "CLIENT_FRIENDINFOREQ"; case CLIENT_CLANINFOREQ: return "CLIENT_CLANINFOREQ"; case CLIENT_CLAN_CREATEREQ: return "CLIENT_CLAN_CREATEREQ"; case CLIENT_CLAN_CREATEINVITEREQ: return "CLIENT_CLAN_CREATEINVITEREQ"; case CLIENT_CLAN_CREATEINVITEREPLY: return "CLIENT_CLAN_CREATEINVITEREPLY"; case CLIENT_CLAN_DISBANDREQ: return "CLIENT_CLAN_DISBANDREQ"; case CLIENT_CLAN_MEMBERNEWCHIEFREQ: return "CLIENT_CLAN_MEMBERNEWCHIEFREQ"; case CLIENT_CLAN_INVITEREQ: return "CLIENT_CLAN_INVITEREQ"; case CLIENT_CLANMEMBER_REMOVE_REQ: return "CLIENT_CLANMEMBER_REMOVE_REQ"; case CLIENT_CLAN_INVITEREPLY: return "CLIENT_CLAN_INVITEREPLY"; case CLIENT_CLANMEMBER_RANKUPDATE_REQ: return "CLIENT_CLANMEMBER_RANKUPDATE_REQ"; case CLIENT_CLAN_MOTDCHG: return "CLIENT_CLAN_MOTDCHG"; case CLIENT_CLAN_MOTDREQ: return "CLIENT_CLAN_MOTDREQ"; case CLIENT_CLANMEMBERLIST_REQ: return "CLIENT_CLANMEMBERLIST_REQ"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.file.h.type)) { case CLIENT_FILE_REQ: return "CLIENT_FILE_REQ"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_int_get(packet->u.udp.h.type)) { case SERVER_UDPTEST: /* we get these if we send stuff to ourself */ return "SERVER_UDPTEST"; case CLIENT_UDPPING: return "CLIENT_UDPPING"; case CLIENT_SESSIONADDR1: return "CLIENT_SESSIONADDR1"; case CLIENT_SESSIONADDR2: return "CLIENT_SESSIONADDR2"; } return "unknown"; case packet_class_raw: return "CLIENT_RAW"; case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_byte_get(packet->u.d2game.h.type)) { default: return "CLIENT_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case CLIENT_W3ROUTE_REQ: return "CLIENT_W3ROUTE_REQ"; case CLIENT_W3ROUTE_LOADINGDONE: return "CLIENT_W3ROUTE_LOADINGDONE"; case CLIENT_W3ROUTE_ABORT: return "CLIENT_W3ROUTE_ABORT"; case CLIENT_W3ROUTE_CONNECTED: return "CLIENT_W3ROUTE_CONNECTED"; case CLIENT_W3ROUTE_ECHOREPLY: return "CLIENT_W3ROUTE_ECHOREPLY"; case CLIENT_W3ROUTE_GAMERESULT: return "CLIENT_W3ROUTE_GAMERESULT"; case CLIENT_W3ROUTE_GAMERESULT_W3XP: return "CLIENT_W3ROUTE_GAMERESULT_W3XP"; } return "unknown"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return "unknown"; case packet_dir_from_server: switch (packet->pclass) { case packet_class_init: return "unknown"; case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case SERVER_COMPREPLY: return "SERVER_COMPREPLY"; case SERVER_SESSIONKEY1: return "SERVER_SESSIONKEY1"; case SERVER_SESSIONKEY2: return "SERVER_SESSIONKEY2"; case SERVER_CREATEACCTREPLY1: return "SERVER_CREATEACCTREPLY1"; case SERVER_AUTHREQ1: return "SERVER_AUTHREQ1"; case SERVER_AUTHREQ_109: return "SERVER_AUTHREQ_109"; case SERVER_AUTHREPLY1: return "SERVER_AUTHREPLY1"; case SERVER_AUTHREPLY_109: return "SERVER_AUTHREPLY_109"; case SERVER_REGSNOOPREQ: return "SERVER_REGSNOOPREQ"; case SERVER_ICONREPLY: return "SERVER_ICONREPLY"; case SERVER_LADDERSEARCHREPLY: return "SERVER_LADDERSEARCHREPLY"; case SERVER_CDKEYREPLY: return "SERVER_CDKEYREPLY"; case SERVER_CDKEYREPLY2: return "SERVER_CDKEYREPLY2"; case SERVER_CDKEYREPLY3: return "SERVER_CDKEYREPLY3"; case SERVER_REALMLISTREPLY: return "SERVER_REALMLISTREPLY"; case SERVER_REALMLISTREPLY_110: return "SERVER_REALMLISTREPLY_110"; case SERVER_PROFILEREPLY: return "SERVER_PROFILEREPLY"; case SERVER_UNKNOWN_37: return "SERVER_UNKNOWN_37"; case SERVER_MOTD_W3: return "SERVER_MOTD_W3"; case SERVER_LOGINREPLY_W3: return "SERVER_LOGINREPLY_W3"; case SERVER_LOGONPROOFREPLY: return "SERVER_LOGONPROOFREPLY"; case SERVER_CREATEACCOUNT_W3: return "SERVER_CREATEACCOUNT_W3"; case SERVER_PASSCHANGEREPLY: return "SERVER_PASSCHANGEREPLY"; case SERVER_PASSCHANGEPROOFREPLY: return "SERVER_PASSCHANGEPROOFREPLY"; case SERVER_LOGINREPLY2: return "SERVER_LOGINREPLY2"; case SERVER_CREATEACCTREPLY2: return "SERVER_CREATEACCTREPLY2"; case SERVER_FILEINFOREPLY: return "SERVER_FILEINFOREPLY"; case SERVER_STATSREPLY: return "SERVER_STATSREPLY"; case SERVER_LOGINREPLY1: return "SERVER_LOGINREPLY1"; case SERVER_CHANGEPASSACK: return "SERVER_CHANGEPASSACK"; case SERVER_PLAYERINFOREPLY: return "SERVER_PLAYERINFOREPLY"; case SERVER_CHANNELLIST: return "SERVER_CHANNELLIST"; case SERVER_SERVERLIST: return "SERVER_SERVERLIST"; case SERVER_MESSAGE: return "SERVER_MESSAGE"; case SERVER_GAMELISTREPLY: return "SERVER_GAMELISTREPLY"; case SERVER_STARTGAME1_ACK: return "SERVER_STARTGAME1_ACK"; case SERVER_STARTGAME3_ACK: return "SERVER_STARTGAME3_ACK"; case SERVER_STARTGAME4_ACK: return "SERVER_STARTGAME4_ACK"; case SERVER_MAPAUTHREPLY1: return "SERVER_MAPAUTHREPLY1"; case SERVER_MAPAUTHREPLY2: return "SERVER_MAPAUTHREPLY2"; case SERVER_ADREPLY: return "SERVER_ADREPLY"; case SERVER_ADCLICKREPLY2: return "SERVER_ADCLICKREPLY2"; case SERVER_LADDERREPLY: return "SERVER_LADDERREPLY"; case SERVER_ECHOREQ: return "SERVER_ECHOREQ"; case SERVER_PINGREPLY: return "SERVER_PINGREPLY"; case SERVER_REALMJOINREPLY_109: return "SERVER_REALMJOINREPLY_109"; case SERVER_SETEMAILREQ: return "SERVER_SETEMAILREQ"; case SERVER_FINDANONGAME: return "SERVER_FINDANONGAME"; case SERVER_ARRANGEDTEAM_FRIENDSCREEN: return "SERVER_ARRANGEDTEAM_FRIENDSCREEN"; case SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK: return "SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK"; case SERVER_ARRANGEDTEAM_SEND_INVITE: return "SERVER_ARRANGEDTEAM_SEND_INVITE"; case SERVER_ARRANGEDTEAM_MEMBER_DECLINE: return "SERVER_ARRANGEDTEAM_MEMBER_DECLINE"; case SERVER_FRIENDSLISTREPLY: return "SERVER_FRIENDSLISTREPLY"; case SERVER_FRIENDINFOREPLY: return "SERVER_FRIENDINFOREPLY"; case SERVER_FRIENDADD_ACK: return "SERVER_FRIENDADD_ACK"; case SERVER_FRIENDDEL_ACK: return "SERVER_FRIENDDEL_ACK"; case SERVER_FRIENDMOVE_ACK: return "SERVER_FRIENDMOVE_ACK"; case SERVER_CLANINFOREPLY: return "SERVER_CLANINFO_REPLY"; case SERVER_CLAN_CREATEREPLY: return "SERVER_CLAN_CREATEREPLY"; case SERVER_CLAN_CREATEINVITEREPLY: return "SERVER_CLAN_CREATEINVITEREPLY"; case SERVER_CLAN_CREATEINVITEREQ: return "SERVER_CLAN_CREATEINVITEREQ"; case SERVER_CLAN_DISBANDREPLY: return "SERVER_CLAN_DISBANDREPLY"; case SERVER_CLAN_MEMBERNEWCHIEFREPLY: return "SERVER_CLAN_MEMBERNEWCHIEFREPLY"; case SERVER_CLAN_CLANACK: return "SERVER_CLAN_CLANACK"; case SERVER_CLANQUITNOTIFY: return "SERVER_CLANQUITNOTIFY"; case SERVER_CLAN_INVITEREPLY: return "SERVER_CLAN_INVITEREPLY"; case SERVER_CLANMEMBER_REMOVE_REPLY: return "SERVER_CLANMEMBER_REMOVE_REPLY"; case SERVER_CLAN_INVITEREQ: return "SERVER_CLAN_INVITEREQ"; case SERVER_CLANMEMBER_RANKUPDATE_REPLY: return "SERVER_CLANMEMBER_RANKUPDATE_REPLY"; case SERVER_CLAN_MOTDREPLY: return "SERVER_CLAN_MOTDREPLY"; case SERVER_CLANMEMBERLIST_REPLY: return "SERVER_CLANMEMBERLIST_REPLY"; case SERVER_CLANMEMBER_REMOVED_NOTIFY: return "SERVER_CLANMEMBER_REMOVED_NOTIFY"; case SERVER_CLANMEMBERUPDATE: return "SERVER_CLANMEMBERUPDATE"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.file.h.type)) { case SERVER_FILE_REPLY: return "SERVER_FILE_REPLY"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_int_get(packet->u.udp.h.type)) { case SERVER_UDPTEST: return "SERVER_UDPTEST"; } return "unknown"; case packet_class_raw: return "SERVER_RAW"; case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_byte_get(packet->u.d2game.h.type)) { default: return "SERVER_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case SERVER_W3ROUTE_READY: return "SERVER_W3ROUTE_READY"; case SERVER_W3ROUTE_LOADINGACK: return "SERVER_W3ROUTE_LOADINGACK"; case SERVER_W3ROUTE_ECHOREQ: return "SERVER_W3ROUTE_ECHOREQ"; case SERVER_W3ROUTE_ACK: return "SERVER_W3ROUTE_ACK"; case SERVER_W3ROUTE_PLAYERINFO: return "SERVER_W3ROUTE_PLAYERINFO"; case SERVER_W3ROUTE_LEVELINFO: return "SERVER_W3ROUTE_LEVELINFO"; case SERVER_W3ROUTE_STARTGAME1: return "SERVER_W3ROUTE_STARTGAME1"; case SERVER_W3ROUTE_STARTGAME2: return "SERVER_W3ROUTE_STARTGAME2"; } return "unknown"; case packet_class_wolgameres: return "CLIENT_WOLGAMERES"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"got unknown direction %d",(int)dir); return "unknown"; }
extern unsigned int packet_get_type(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } switch (packet->pclass) { case packet_class_init: return CLIENT_INITCONN; /* all init packets are of this type */ case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return (unsigned int)bn_short_get(packet->u.bnet.h.type); case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"file packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return (unsigned int)bn_short_get(packet->u.file.h.type); case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"udp packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_int_get(packet->u.udp.h.type); case packet_class_raw: return 0; /* raw packets don't have a type, but don't warn because the packet dump tries anyway */ case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2game packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_byte_get(packet->u.d2game.h.type); case packet_class_d2gs: if (packet_get_size(packet)<sizeof(t_d2cs_d2gs_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2gs packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.d2cs_d2gs.h.type); case packet_class_d2cs_bnetd: if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs_bnetd packet shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.d2cs_d2gs.h.type); case packet_class_d2cs: if (packet_get_size(packet)<sizeof(t_d2cs_client_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_byte_get(packet->u.d2cs_client.h.type); case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"w3route packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.w3route.h.type); case packet_class_wolgameres: return 0; /* wolgameres packets don't have a type */ default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return 0; } }
static int on_client_gamelistreq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; unsigned int count; unsigned int seqno; std::time_t now; unsigned int maxlifetime; t_elem const * start_elem; t_elem const * elem; seqno=bn_short_get(packet->u.client_d2cs_gamelistreq.seqno); /* if (seqno%2) return 0; */ count=0; now=std::time(NULL); maxlifetime=prefs_get_game_maxlifetime(); elem=start_elem=gamelist_get_curr_elem(); if (!elem) elem=list_get_first_const(d2cs_gamelist()); else elem=elem_get_next_const(d2cs_gamelist(),elem); for (; elem != start_elem; elem=elem_get_next_const(d2cs_gamelist(),elem)) { if (!elem) { elem=list_get_first_const(d2cs_gamelist()); if (elem == start_elem) break; } if (!(game=(t_game*)elem_get_data(elem))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL game"); break; } if (maxlifetime && (now-game->create_time>maxlifetime)) continue; if (!game_get_currchar(game)) continue; if (!prefs_allow_gamelist_showall()) { if (conn_get_charinfo_difficulty(c)!=game_get_gameflag_difficulty(game)) continue; } if (prefs_hide_pass_games()) if (d2cs_game_get_pass(game)) continue; if (d2cs_try_joingame(c,game,"")!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) continue; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,d2cs_game_get_id(game)); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,game_get_currchar(game)); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,game_get_gameflag(game)); packet_append_string(rpacket,d2cs_game_get_name(game)); packet_append_string(rpacket,game_get_desc(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); count++; if (prefs_get_maxgamelist() && count>=prefs_get_maxgamelist()) break; } } gamelist_set_curr_elem(elem); if (count) { if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply)); packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY); bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,0); bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,0); bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,0); packet_append_string(rpacket,""); packet_append_string(rpacket,""); packet_append_string(rpacket,""); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } return 0; }
static int on_client_joingamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * charname; char const * account; t_game * game; t_d2gs * gs; int reply; unsigned int pos; unsigned int seqno; gs = NULL; pos=sizeof(t_client_d2cs_joingamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=std::strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } if (!(charname=d2cs_conn_get_charname(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing character name for connection"); return -1; } if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection"); return -1; } if (conn_check_multilogin(c,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); return -1; } if (!(game=d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_info,__FUNCTION__,"game %s not found",gamename); reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else if (!(gs=game_get_d2gs(game))) { eventlog(eventlog_level_error,__FUNCTION__,"missing game server for game %s",gamename); reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST; } else { reply=d2cs_try_joingame(c,game,gamepass); } seqno=bn_short_get(packet->u.client_d2cs_joingamereq.seqno); if (reply!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_joingamereply)); packet_set_type(rpacket,D2CS_CLIENT_JOINGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_joingamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_joingamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.addr,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,0); bn_int_set(&rpacket->u.d2cs_client_joingamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_joingamereq)); packet_set_type(gspacket,D2CS_D2GS_JOINGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.h.seqno,sq_get_seqno(sq)); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.gameid, game_get_d2gs_gameid(game)); sq_set_gametoken(sq,d2gs_make_token(gs)); bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.token,sq_get_gametoken(sq)); packet_append_string(gspacket,charname); packet_append_string(gspacket,account); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request join game %s for character %s on gs %d",gamename, charname,d2gs_get_id(gs)); } } return 0; }
static int on_client_creategamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * gamedesc; t_game * game; t_d2gs * gs; t_gq * gq; unsigned int tempflag,gameflag; unsigned int leveldiff, maxchar, difficulty, expansion, hardcore, ladder; unsigned int seqno, reply; unsigned int pos; t_elem * elem; pos=sizeof(t_client_d2cs_creategamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=std::strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } pos+=std::strlen(gamepass)+1; if (!(gamedesc=packet_get_str_const(packet,pos,MAX_GAMEDESC_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game desc"); return -1; } tempflag=bn_int_get(packet->u.client_d2cs_creategamereq.gameflag); leveldiff=bn_byte_get(packet->u.client_d2cs_creategamereq.leveldiff); maxchar=bn_byte_get(packet->u.client_d2cs_creategamereq.maxchar); difficulty=gameflag_get_difficulty(tempflag); if (difficulty > conn_get_charinfo_difficulty(c)) { eventlog(eventlog_level_error,__FUNCTION__,"game difficulty exceed character limit %d %d",difficulty, conn_get_charinfo_difficulty(c)); return 0; } expansion=conn_get_charinfo_expansion(c); hardcore=conn_get_charinfo_hardcore(c); ladder=conn_get_charinfo_ladder(c); gameflag=gameflag_create(ladder,expansion,hardcore,difficulty); gs = NULL; game = NULL; gq=conn_get_gamequeue(c); if (d2cs_gamelist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in gamelist",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!gq && gqlist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in game queue",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!(gs=d2gslist_choose_server())) { if (gq) { eventlog(eventlog_level_error,__FUNCTION__,"client %d is already in game queue",d2cs_conn_get_sessionnum(c)); conn_set_gamequeue(c,NULL); gq_destroy(gq,&elem); return 0; } else if ((gq=gq_create(d2cs_conn_get_sessionnum(c), packet, gamename))) { conn_set_gamequeue(c,gq); d2cs_send_client_creategamewait(c,gqlist_get_length()); return 0; } reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (hardcore && conn_get_charinfo_dead(c)) { reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (!(game=d2cs_game_create(gamename,gamepass,gamedesc,gameflag))) { reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else { reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED; game_set_d2gs(game,gs); d2gs_add_gamenum(gs, 1); game_set_gameflag_ladder(game,ladder); game_set_gameflag_expansion(game,expansion); game_set_created(game,0); game_set_leveldiff(game,leveldiff); game_set_charlevel(game,conn_get_charinfo_level(c)); game_set_maxchar(game,maxchar); game_set_gameflag_difficulty(game,difficulty); game_set_gameflag_hardcore(game,hardcore); } seqno=bn_short_get(packet->u.client_d2cs_creategamereq.seqno); if (reply!=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply)); packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_creategamereq)); packet_set_type(gspacket,D2CS_D2GS_CREATEGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_creategamereq.h.seqno,sq_get_seqno(sq)); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.difficulty,difficulty); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.hardcore,hardcore); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.expansion,expansion); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.ladder,ladder); packet_append_string(gspacket,gamename); packet_append_string(gspacket,gamepass); packet_append_string(gspacket,gamedesc); packet_append_string(gspacket,d2cs_conn_get_account(c)); packet_append_string(gspacket,d2cs_conn_get_charname(c)); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request create game %s on gs %d",gamename,d2gs_get_id(gs)); } } return 0; }
int d2ladder_readladder(void) { t_d2ladder * d2ladder; t_d2ladderfile_header fileheader; std::FILE * fdladder; t_d2ladderfile_ladderindex * lhead; t_d2ladderfile_ladderinfo * ldata; t_d2ladder_info * info; t_d2ladder_info temp; long leftsize,blocksize; unsigned int laddertype; unsigned int tempmaxtype; int readlen; unsigned int i, number; if (!d2ladder_ladder_file) return -1; fdladder=std::fopen(d2ladder_ladder_file,"rb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"canot open ladder file"); return -1; } std::fseek(fdladder,0,SEEK_END); leftsize=std::ftell(fdladder); std::rewind(fdladder); blocksize=sizeof(fileheader) ; if (leftsize<blocksize) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); std::fclose(fdladder); return -1; } readlen=std::fread(&fileheader,1,sizeof(fileheader),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); std::fclose(fdladder); return -1; } tempmaxtype=bn_int_get(fileheader.maxtype); leftsize-=blocksize; if(tempmaxtype>D2LADDER_MAXTYPE) { eventlog(eventlog_level_error,__FUNCTION__,"ladder type > D2LADDER_MAXTYPE error"); std::fclose(fdladder); return -1; } d2ladder_maxtype=tempmaxtype; blocksize=d2ladder_maxtype*sizeof(*lhead); if (leftsize < blocksize ) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); std::fclose(fdladder); return -1; } lhead=(t_d2ladderfile_ladderindex*)xmalloc(blocksize); readlen=std::fread(lhead,1,d2ladder_maxtype*sizeof(*lhead),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); xfree(lhead); std::fclose(fdladder); return -1; } leftsize-=blocksize; blocksize=0; for(i=0;i<d2ladder_maxtype;i++) { blocksize+=bn_int_get(lhead[i].number)*sizeof(*ldata); } if (leftsize < blocksize ) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); xfree(lhead); std::fclose(fdladder); return -1; } for(laddertype=0;laddertype<d2ladder_maxtype;laddertype++) { number= bn_int_get(lhead[laddertype].number); if(number<=0) continue; d2ladder=d2ladderlist_find_type(laddertype); if (!d2ladder) { eventlog(eventlog_level_error,__FUNCTION__,"could not find ladder type %d",laddertype); continue; } ldata=(t_d2ladderfile_ladderinfo*)xmalloc(number*sizeof(*ldata)); info=(t_d2ladder_info*)xmalloc(number * sizeof(*info)); std::memset(info,0,number * sizeof(*info)); std::fseek(fdladder,bn_int_get(lhead[laddertype].offset),SEEK_SET); readlen=std::fread(ldata,1,number*sizeof(*ldata),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); xfree(ldata); xfree(info); continue; } d2ladder->info=info; d2ladder->len=number; for (i=0; i< number; i++) { if (!ldata[i].charname[0]) continue; temp.experience=bn_int_get(ldata[i].experience); temp.status=bn_short_get(ldata[i].status); temp.level=bn_byte_get(ldata[i].level); temp.chclass=bn_byte_get(ldata[i].chclass); std::strncpy(temp.charname,ldata[i].charname,sizeof(info[i].charname)); if (d2ladder_update_info_and_pos(d2ladder,&temp, d2ladder_find_char_all(d2ladder,&temp), d2ladder_find_pos(d2ladder,&temp))==1) { d2ladder_change_count++; } } xfree(ldata); } leftsize-=blocksize; xfree(lhead); std::fclose(fdladder); return 0; }
/* return value: 1 : process one or more packet 0 : not get a whole packet,do nothing -1 : error */ extern int dbs_packet_handle(t_d2dbs_connection* conn) { unsigned short readlen, writelen; t_d2dbs_d2gs_header * readhead; int retval; if (conn->stats == 0) { if (conn->nCharsInReadBuffer < (signed)sizeof(t_d2gs_d2dbs_connect)) { return 0; } conn->stats = 1; conn->type = conn->ReadBuf[0]; if (conn->type == CONNECT_CLASS_D2GS_TO_D2DBS) { if (dbs_verify_ipaddr(d2dbs_prefs_get_d2gs_list(), conn) < 0) { eventlog(eventlog_level_error, __FUNCTION__, "d2gs connection from unknown ip address"); return -1; } readlen = 1; writelen = 0; eventlog(eventlog_level_info, __FUNCTION__, "set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd); eventlog_step(prefs_get_logfile_gs(), eventlog_level_info, __FUNCTION__, "set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd); } else { eventlog(eventlog_level_error, __FUNCTION__, "unknown connection type"); return -1; } conn->nCharsInReadBuffer -= readlen; std::memmove(conn->ReadBuf, conn->ReadBuf + readlen, conn->nCharsInReadBuffer); } else if (conn->stats == 1) { if (conn->type == CONNECT_CLASS_D2GS_TO_D2DBS) { while (conn->nCharsInReadBuffer >= (signed)sizeof(*readhead)) { readhead = (t_d2dbs_d2gs_header *)conn->ReadBuf; readlen = bn_short_get(readhead->size); if (conn->nCharsInReadBuffer < readlen) break; switch (bn_short_get(readhead->type)) { case D2GS_D2DBS_SAVE_DATA_REQUEST: retval = dbs_packet_savedata(conn); break; case D2GS_D2DBS_GET_DATA_REQUEST: retval = dbs_packet_getdata(conn); break; case D2GS_D2DBS_UPDATE_LADDER: retval = dbs_packet_updateladder(conn); break; case D2GS_D2DBS_CHAR_LOCK: retval = dbs_packet_charlock(conn); break; case D2GS_D2DBS_ECHOREPLY: retval = dbs_packet_echoreply(conn); break; default: eventlog(eventlog_level_error, __FUNCTION__, "unknown request type %d", \ bn_short_get(readhead->type)); retval = -1; } if (retval != 1) return retval; conn->nCharsInReadBuffer -= readlen; std::memmove(conn->ReadBuf, conn->ReadBuf + readlen, conn->nCharsInReadBuffer); } } else { eventlog(eventlog_level_error, __FUNCTION__, "unknown connection type %d", conn->type); return -1; } } else { eventlog(eventlog_level_error, __FUNCTION__, "unknown connection stats"); return -1; } return 1; }
static int dbs_packet_getdata(t_d2dbs_connection * conn) { unsigned short writelen; unsigned short datatype; unsigned short datalen; unsigned int result; char AccountName[MAX_USERNAME_LEN]; char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_get_data_request * getcom; t_d2dbs_d2gs_get_data_reply * getret; char * readpos; char * writepos; char databuf[kBufferSize]; t_d2charinfo_file charinfo; unsigned short charinfolen; unsigned int gsid; readpos = conn->ReadBuf; getcom = (t_d2gs_d2dbs_get_data_request *)readpos; datatype = bn_short_get(getcom->datatype); readpos += sizeof(*getcom); std::strncpy(AccountName, readpos, MAX_USERNAME_LEN); if (AccountName[MAX_USERNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max account name length exceeded"); return -1; } readpos += std::strlen(AccountName) + 1; std::strncpy(CharName, readpos, MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max char name length exceeded"); return -1; } readpos += std::strlen(CharName) + 1; std::strncpy(RealmName, readpos, MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max realm name length exceeded"); return -1; } readpos += std::strlen(RealmName) + 1; if (readpos != conn->ReadBuf + bn_short_get(getcom->h.size)) { eventlog(eventlog_level_error, __FUNCTION__, "request packet size error"); return -1; } writepos = conn->WriteBuf + conn->nCharsInWriteBuffer; getret = (t_d2dbs_d2gs_get_data_reply *)writepos; datalen = 0; if (datatype == D2GS_DATA_CHARSAVE) { if (cl_query_charlock_status((unsigned char*)CharName, (unsigned char*)RealmName, &gsid) != 0) { eventlog(eventlog_level_warn, __FUNCTION__, "char %s(*%s)@%s is already locked on gs %u", CharName, AccountName, RealmName, gsid); result = D2DBS_GET_DATA_CHARLOCKED; } else if (cl_lock_char((unsigned char*)CharName, (unsigned char*)RealmName, conn->serverid) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to lock char %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); result = D2DBS_GET_DATA_CHARLOCKED; } else { eventlog(eventlog_level_info, __FUNCTION__, "lock char %s(*%s)@%s for gs %s(%d)", CharName, AccountName, RealmName, conn->serverip, conn->serverid); datalen = dbs_packet_getdata_charsave(conn, AccountName, CharName, databuf, kBufferSize); if (datalen > 0) { result = D2DBS_GET_DATA_SUCCESS; charinfolen = dbs_packet_getdata_charinfo(conn, AccountName, CharName, (char *)&charinfo, sizeof(charinfo)); if (charinfolen > 0) { result = D2DBS_GET_DATA_SUCCESS; } else { result = D2DBS_GET_DATA_FAILED; if (cl_unlock_char((unsigned char*)CharName, (unsigned char*)RealmName, gsid) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "failed to unlock char %s(*%s)@%s for gs %s(%d)", CharName, \ AccountName, RealmName, conn->serverip, conn->serverid); } else { eventlog(eventlog_level_info, __FUNCTION__, "unlock char %s(*%s)@%s for gs %s(%d)", CharName, \ AccountName, RealmName, conn->serverip, conn->serverid); } } } else { datalen = 0; result = D2DBS_GET_DATA_FAILED; if (cl_unlock_char((unsigned char*)CharName, (unsigned char*)RealmName, gsid) != 0) { eventlog(eventlog_level_error, __FUNCTION__, "faled to unlock char %s(*%s)@%s for gs %s(%d)", CharName, \ AccountName, RealmName, conn->serverip, conn->serverid); } else { eventlog(eventlog_level_info, __FUNCTION__, "unlock char %s(*%s)@%s for gs %s(%d)", CharName, \ AccountName, RealmName, conn->serverip, conn->serverid); } } } if (result == D2DBS_GET_DATA_SUCCESS) { bn_int_set(&getret->charcreatetime, bn_int_get(charinfo.header.create_time)); /* FIXME: this should be rewritten to support string formatted std::time */ if (bn_int_get(charinfo.header.create_time) >= prefs_get_ladderinit_time()) { bn_int_set(&getret->allowladder, 1); } else { bn_int_set(&getret->allowladder, 0); } } else { bn_int_set(&getret->charcreatetime, 0); bn_int_set(&getret->allowladder, 0); } } else if (datatype == D2GS_DATA_PORTRAIT) { datalen = dbs_packet_getdata_charinfo(conn, AccountName, CharName, databuf, kBufferSize); if (datalen > 0) result = D2DBS_GET_DATA_SUCCESS; else { datalen = 0; result = D2DBS_GET_DATA_FAILED; } } else { eventlog(eventlog_level_error, __FUNCTION__, "unknown data type %d", datatype); return -1; } writelen = datalen + sizeof(*getret) + std::strlen(CharName) + 1; if (writelen > kBufferSize - conn->nCharsInWriteBuffer) return 0; bn_short_set(&getret->h.type, D2DBS_D2GS_GET_DATA_REPLY); bn_short_set(&getret->h.size, writelen); bn_int_set(&getret->h.seqno, bn_int_get(getcom->h.seqno)); bn_short_set(&getret->datatype, bn_short_get(getcom->datatype)); bn_int_set(&getret->result, result); bn_short_set(&getret->datalen, datalen); writepos += sizeof(*getret); std::strncpy(writepos, CharName, MAX_CHARNAME_LEN); writepos += std::strlen(CharName) + 1; if (datalen) std::memcpy(writepos, databuf, datalen); conn->nCharsInWriteBuffer += writelen; return 1; }
static int dbs_packet_savedata(t_d2dbs_connection * conn) { unsigned short writelen; unsigned short datatype; unsigned short datalen; unsigned int result; char AccountName[MAX_USERNAME_LEN]; char CharName[MAX_CHARNAME_LEN]; char RealmName[MAX_REALMNAME_LEN]; t_d2gs_d2dbs_save_data_request * savecom; t_d2dbs_d2gs_save_data_reply * saveret; char * readpos; unsigned char * writepos; readpos = conn->ReadBuf; savecom = (t_d2gs_d2dbs_save_data_request *)readpos; datatype = bn_short_get(savecom->datatype); datalen = bn_short_get(savecom->datalen); readpos += sizeof(*savecom); std::strncpy(AccountName, readpos, MAX_USERNAME_LEN); if (AccountName[MAX_USERNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max acccount name length exceeded"); return -1; } readpos += std::strlen(AccountName) + 1; std::strncpy(CharName, readpos, MAX_CHARNAME_LEN); if (CharName[MAX_CHARNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max char name length exceeded"); return -1; } readpos += std::strlen(CharName) + 1; std::strncpy(RealmName, readpos, MAX_REALMNAME_LEN); if (RealmName[MAX_REALMNAME_LEN - 1] != 0) { eventlog(eventlog_level_error, __FUNCTION__, "max realm name length exceeded"); return -1; } readpos += std::strlen(RealmName) + 1; if (readpos + datalen != conn->ReadBuf + bn_short_get(savecom->h.size)) { eventlog(eventlog_level_error, __FUNCTION__, "request packet size error"); return -1; } if (datatype == D2GS_DATA_CHARSAVE) { if (dbs_packet_savedata_charsave(conn, AccountName, CharName, readpos, datalen) > 0 && dbs_packet_fix_charinfo(conn, AccountName, CharName, readpos)) { result = D2DBS_SAVE_DATA_SUCCESS; } else { datalen = 0; result = D2DBS_SAVE_DATA_FAILED; } } else if (datatype == D2GS_DATA_PORTRAIT) { /* if level is > 255 , sets level to 255 */ dbs_packet_set_charinfo_level(CharName, readpos); if (dbs_packet_savedata_charinfo(conn, AccountName, CharName, readpos, datalen) > 0) { result = D2DBS_SAVE_DATA_SUCCESS; } else { datalen = 0; result = D2DBS_SAVE_DATA_FAILED; } } else { eventlog(eventlog_level_error, __FUNCTION__, "unknown data type %d", datatype); return -1; } writelen = sizeof(*saveret) + std::strlen(CharName) + 1; if (writelen > kBufferSize - conn->nCharsInWriteBuffer) return 0; writepos = (unsigned char*)(conn->WriteBuf + conn->nCharsInWriteBuffer); saveret = (t_d2dbs_d2gs_save_data_reply *)writepos; bn_short_set(&saveret->h.type, D2DBS_D2GS_SAVE_DATA_REPLY); bn_short_set(&saveret->h.size, writelen); bn_int_set(&saveret->h.seqno, bn_int_get(savecom->h.seqno)); bn_short_set(&saveret->datatype, bn_short_get(savecom->datatype)); bn_int_set(&saveret->result, result); writepos += sizeof(*saveret); std::strncpy((char*)writepos, CharName, MAX_CHARNAME_LEN); conn->nCharsInWriteBuffer += writelen; return 1; }