static int d2charsave_init(void * buffer,char const * charname,unsigned char classs,unsigned short status) { ASSERT(buffer,-1); ASSERT(charname,-1); bn_byte_set((bn_byte *)((char *)buffer+D2CHARSAVE_CLASS_OFFSET), classs); bn_short_set((bn_short *)((char *)buffer+D2CHARSAVE_STATUS_OFFSET),status); strncpy((char *)buffer+D2CHARSAVE_CHARNAME_OFFSET,charname,MAX_CHARNAME_LEN); return 0; }
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 d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname, unsigned char classs, unsigned short status) { unsigned int i; time_t now; now=time(NULL); bn_int_set(&chardata->header.magicword,D2CHARINFO_MAGICWORD); bn_int_set(&chardata->header.version,D2CHARINFO_VERSION); bn_int_set(&chardata->header.create_time,now); bn_int_set(&chardata->header.last_time,now); bn_int_set(&chardata->header.total_play_time,0); memset(chardata->header.charname, 0,MAX_CHARNAME_LEN); strncpy(chardata->header.charname,charname,MAX_CHARNAME_LEN); memset(chardata->header.account, 0,MAX_ACCTNAME_LEN); strncpy(chardata->header.account,account,MAX_ACCTNAME_LEN); memset(chardata->header.realmname, 0,MAX_REALMNAME_LEN); strncpy(chardata->header.realmname,prefs_get_realmname(),MAX_REALMNAME_LEN); bn_int_set(&chardata->header.checksum,0); for (i=0; i<NELEMS(chardata->header.reserved); i++) { bn_int_set(&chardata->header.reserved[i],0); } bn_int_set(&chardata->summary.charlevel,1); bn_int_set(&chardata->summary.experience,0); bn_int_set(&chardata->summary.charclass,classs); bn_int_set(&chardata->summary.charstatus,status); memset(chardata->portrait.gfx,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.gfx)); memset(chardata->portrait.color,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.color)); memset(chardata->portrait.u2,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.u2)); memset(chardata->portrait.u1,D2CHARINFO_PORTRAIT_MASK,sizeof(chardata->portrait.u1)); memset(chardata->pad,0,sizeof(chardata->pad)); bn_short_set(&chardata->portrait.header,D2CHARINFO_PORTRAIT_HEADER); bn_byte_set(&chardata->portrait.status,status|D2CHARINFO_PORTRAIT_MASK); bn_byte_set(&chardata->portrait.classs,classs+1); bn_byte_set(&chardata->portrait.level,1); if (charstatus_get_ladder(status)) bn_byte_set(&chardata->portrait.ladder, 1); else bn_byte_set(&chardata->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); bn_byte_set(&chardata->portrait.end,'\0'); memset(chardata->pad,0,sizeof(chardata->pad)); return 0; }
/* tournament notice disabled at this time, but responce is sent to cleint */ static int _client_anongame_tournament(t_connection * c, t_packet const * const packet) { t_packet * rpacket; t_account * account = conn_get_account(c); t_clienttag clienttag = conn_get_clienttag(c); unsigned int start_prelim = tournament_get_start_preliminary(); unsigned int end_signup = tournament_get_end_signup(); unsigned int end_prelim = tournament_get_end_preliminary(); unsigned int start_r1 = tournament_get_start_round_1(); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_anongame_tournament_reply)); packet_set_type(rpacket, SERVER_FINDANONGAME_TOURNAMENT_REPLY); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.option, 7); bn_int_set(&rpacket->u.server_anongame_tournament_reply.count, bn_int_get(packet->u.client_anongame_tournament_request.count)); if (!start_prelim || (end_signup <= now && tournament_user_signed_up(account) < 0) || tournament_check_client(clienttag) < 0) { /* No Tournament Notice */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_prelim >= now) { /* Tournament Notice */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 1); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_prelim)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_prelim - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x00); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_signup >= now) { /* Tournament Signup Notice - Play Game Active */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_signup)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_signup - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (end_prelim >= now) { /* Tournament Prelim Period - Play Game Active */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 3); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_prelim)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_prelim - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (start_r1 >= now && (tournament_get_game_in_progress())) { /* Prelim Period Over - Shows user stats (not all prelim games finished) */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 4); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */ bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); /* 00 00 */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if (!(tournament_get_in_finals_status(account))) { /* Prelim Period Over - user did not make finals - Shows user stats */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 5); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } /* cycle through [type-6] & [type-7] packets * * use [type-6] to show client "eliminated" or "continue" * timestamp , countdown & round number (of next round) must be set if clinet continues * * use [type-7] to make cleint wait for 44FF packet option 1 to start game (A guess, not tested) * * not sure if there is overall winner packet sent at end of last final round */ // UNDONE: next two conditions never executed else if ((0)) { /* User in finals - Shows user stats and start of next round*/ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 6); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1)); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0x0000); /* 00 00 */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 4); /* round number */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); /* 0 = continue , 1= eliminated */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of rounds in finals */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } else if ((0)) { /* user waiting for match to be made */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 7); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0); bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0); bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 1); /* round number */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of finals */ bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0); bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0); } conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; }
/* Open portrait in Warcraft 3 user profile */ static int _client_anongame_get_icon(t_connection * c, t_packet const * const packet) { t_packet * rpacket; //BlacKDicK 04/20/2003 Need some huge re-work on this. { struct { char icon_code[4]; unsigned int portrait_code; char race; bn_short required_wins; char client_enabled; } tempicon; //FIXME: Add those to the prefs and also merge them on accoun_wrap; // FIXED BY DJP 07/16/2003 FOR 110 CHANGE ( TOURNEY & RACE WINS ) + Table_witdh short icon_req_race_wins; short icon_req_tourney_wins; int race[] = { W3_RACE_RANDOM, W3_RACE_HUMANS, W3_RACE_ORCS, W3_RACE_UNDEAD, W3_RACE_NIGHTELVES, W3_RACE_DEMONS }; char race_char[6] = { 'R', 'H', 'O', 'U', 'N', 'D' }; char icon_pos[5] = { '2', '3', '4', '5', '6', }; char table_width = 6; char table_height = 5; int i, j; char rico; unsigned int rlvl, rwins; t_clienttag clienttag; t_account * acc; char user_icon[5]; char const * uicon; clienttag = conn_get_clienttag(c); acc = conn_get_account(c); /* WAR3 uses a different table size, might change if blizzard add tournament support to RoC */ if (clienttag == CLIENTTAG_WARCRAFT3_UINT) { table_width = 5; table_height = 4; } eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME Get Icons packet", conn_get_socket(c)); if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_iconreply)); packet_set_type(rpacket, SERVER_FINDANONGAME_ICONREPLY); bn_int_set(&rpacket->u.server_findanongame_iconreply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_iconreply.option, CLIENT_FINDANONGAME_GET_ICON); if (prefs_get_custom_icons() == 1) { // get current custom icon t_icon_info * icon; if (icon = customicons_get_icon_by_account(acc, clienttag)) std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, icon->icon_code, 4); } else if ((uicon = account_get_user_icon(acc, clienttag))) { std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, uicon, 4); } else { account_get_raceicon(acc, &rico, &rlvl, &rwins, clienttag); std::sprintf(user_icon, "%1d%c3W", rlvl, rico); std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, user_icon, 4); } bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_width, table_width); bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_size, table_width*table_height); for (j = 0; j < table_height; j++){ icon_req_race_wins = anongame_infos_get_ICON_REQ(j + 1, clienttag); for (i = 0; i < table_width; i++){ tempicon.race = i; tempicon.icon_code[0] = icon_pos[j]; tempicon.icon_code[1] = race_char[i]; tempicon.icon_code[2] = '3'; tempicon.icon_code[3] = 'W'; tempicon.portrait_code = (account_icon_to_profile_icon(tempicon.icon_code, acc, clienttag)); if (i <= 4){ //Building the icon for the races bn_short_set(&tempicon.required_wins, icon_req_race_wins); if (account_get_racewins(acc, race[i], clienttag) >= icon_req_race_wins) { if (prefs_get_custom_icons() == 1) tempicon.client_enabled = 0; else tempicon.client_enabled = 1; } else{ tempicon.client_enabled = 0; } } else{ //Building the icon for the tourney icon_req_tourney_wins = anongame_infos_get_ICON_REQ_TOURNEY(j + 1); bn_short_set(&tempicon.required_wins, icon_req_tourney_wins); if (account_get_racewins(acc, race[i], clienttag) >= icon_req_tourney_wins) { if (prefs_get_custom_icons() == 1) tempicon.client_enabled = 0; else tempicon.client_enabled = 1; } else{ tempicon.client_enabled = 0; } } packet_append_data(rpacket, &tempicon, sizeof(tempicon)); } } //Go,go,go conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } return 0; }
extern int packet_set_type(t_packet * packet, unsigned int type) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } switch (packet->pclass) { case packet_class_init: if (type!=CLIENT_INITCONN) { eventlog(eventlog_level_error,__FUNCTION__,"init packet type 0x%08x is not valid",type); return -1; } return 0; 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 -1; } if (type>MAX_NORMAL_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.bnet.h.type,(unsigned short)type); return 0; 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 -1; } if (type>MAX_FILE_TYPE) { eventlog(eventlog_level_error,__FUNCTION__,"file packet type 0x%08x is too large",type); return -1; } bn_short_set(&packet->u.file.h.type,(unsigned short)type); return 0; 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 -1; } bn_int_set(&packet->u.udp.h.type,type); return 0; 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 -1; } bn_byte_set(&packet->u.d2game.h.type,type); return 0; 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 -1; } bn_short_set(&packet->u.d2cs_d2gs.h.type,type); return 0; case packet_class_d2cs_bnetd: if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs_bnetd packet is shorter than header (len=%u)",packet_get_size(packet)); return -1; } bn_short_set(&packet->u.d2cs_bnetd.h.type,type); return 0; 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 -1; } bn_byte_set(&packet->u.d2cs_client.h.type,type); return 0; 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 -1; } bn_short_set(&packet->u.w3route.h.type,(unsigned short)type); return 0; case packet_class_wolgameres: eventlog(eventlog_level_error,__FUNCTION__,"can not set packet type for wol gameres packet"); return 0; case packet_class_raw: eventlog(eventlog_level_error,__FUNCTION__,"can not set packet type for raw packet"); return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return -1; } }
extern int packet_set_size(t_packet * packet, unsigned int size) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return -1; } if (size>MAX_PACKET_SIZE) { eventlog(eventlog_level_error,__FUNCTION__,"got bad size %u",size); return -1; } switch (packet->pclass) { case packet_class_init: if (size!=0 && size!=sizeof(t_client_initconn)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for init packet",size); return -1; } packet->len = size; return 0; case packet_class_bnet: if (size!=0 && size<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for bnet packet",size); return -1; } bn_short_set(&packet->u.bnet.h.size,size); return 0; case packet_class_file: if (size!=0 && size<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for file packet",size); return -1; } bn_short_set(&packet->u.file.h.size,size); return 0; case packet_class_udp: if (size!=0 && size<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for udp packet",size); return -1; } packet->len = size; return 0; case packet_class_raw: packet->len = size; return 0; case packet_class_d2game: packet->len = size; /* FIXME: does header not contain the size? */ return 0; case packet_class_d2cs: bn_short_set(&packet->u.d2cs_client.h.size,size); return 0; case packet_class_d2gs: bn_short_set(&packet->u.d2cs_d2gs.h.size,size); return 0; case packet_class_d2cs_bnetd: bn_short_set(&packet->u.d2cs_bnetd.h.size,size); return 0; case packet_class_w3route: if (size!=0 && size<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"invalid size %u for w3route packet",size); return -1; } bn_short_set(&packet->u.w3route.h.size,size); return 0; case packet_class_wolgameres: /* PELISH: useless - there is no server packet for wolgameres */ packet->len = size; return 0; default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return -1; } }
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; }
extern int d2ladder_saveladder(void) { t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE]; t_d2ladderfile_header fileheader; std::FILE * fdladder; int start; unsigned int i,j, number; t_d2ladder * d2ladder; t_d2ladderfile_ladderinfo * ldata; char * XMLfilename; std::FILE * XMLfile; /* if(!d2ladder_change_count) { eventlog(eventlog_level_debug,__FUNCTION__,"ladder data unchanged, skip saving"); return 0; } */ start=sizeof(fileheader)+sizeof(lhead); for(i=0;i<D2LADDER_MAXTYPE;i++) { d2ladder=d2ladderlist_find_type(i); bn_int_set(&lhead[i].type,d2ladder->type); bn_int_set(&lhead[i].offset,start); bn_int_set(&lhead[i].number,d2ladder->len); start+=d2ladder->len*sizeof(*ldata); } if (!d2ladder_ladder_file) return -1; if (!d2ladder_backup_file) return -1; if(d2ladder_checksum_check()==1) { eventlog(eventlog_level_info,__FUNCTION__,"backup ladder file"); if (p_rename(d2ladder_ladder_file,d2ladder_backup_file)==-1) { eventlog(eventlog_level_warn,__FUNCTION__,"error std::rename %s to %s", d2ladder_ladder_file, d2ladder_backup_file); } } fdladder=std::fopen(d2ladder_ladder_file,"wb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file); return -1; } // aaron: add extra output for XML ladder here ---> if (d2dbs_prefs_get_XML_output_ladder()) { XMLfilename = (char*)xmalloc(std::strlen(d2dbs_prefs_get_ladder_dir())+1+std::strlen(XMLname)+1); std::sprintf(XMLfilename,"%s/%s",d2dbs_prefs_get_ladder_dir(),XMLname); if (!(XMLfile = std::fopen(XMLfilename,"w"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open XML ladder file for output"); } else { d2ladder_print_XML(XMLfile); std::fclose(XMLfile); xfree(XMLfilename); } } // <--- bn_int_set(&fileheader.maxtype,d2ladder_maxtype); bn_int_set(&fileheader.checksum,0); std::fwrite(&fileheader,1,sizeof(fileheader),fdladder); std::fwrite(lhead,1,sizeof(lhead),fdladder); for(i=0;i<d2ladder_maxtype;i++) { number=bn_int_get(lhead[i].number); if(number<=0) continue; d2ladder=d2ladderlist_find_type(i); ldata=(t_d2ladderfile_ladderinfo*)xmalloc(number * sizeof(*ldata)); std::memset(ldata,0,number * sizeof(*ldata)); for (j=0; j< number; j++) { bn_int_set(&ldata[j].experience,d2ladder->info[j].experience); bn_short_set(&ldata[j].status, d2ladder->info[j].status); bn_byte_set(&ldata[j].level, d2ladder->info[j].level); bn_byte_set(&ldata[j].chclass, d2ladder->info[j].chclass); std::strncpy(ldata[j].charname,d2ladder->info[j].charname,sizeof(ldata[j].charname)); } std::fwrite(ldata,1,number*sizeof(*ldata),fdladder); xfree(ldata); } std::fclose(fdladder); d2ladder_checksum_set(); eventlog(eventlog_level_info,__FUNCTION__,"ladder file saved (%d changes)",d2ladder_change_count); d2ladder_change_count=0; return 0; }
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; }