extern int irc_send_pong(t_connection * conn, char const * params) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN]; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if ((1+strlen(server_get_hostname())+1+4+1+strlen(server_get_hostname())+((params)?(2+strlen(params)):(0))+2+1) > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"max message length exceeded"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } if (params) sprintf(data,":%s PONG %s :%s\r\n",server_get_hostname(),server_get_hostname(),params); else sprintf(data,":%s PONG %s\r\n",server_get_hostname(),server_get_hostname()); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); packet_set_size(p,0); packet_append_data(p,data,strlen(data)); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; }
extern int send_d2cs_gameinforeq(t_connection * c) { t_packet * packet; t_game * game; t_realm * realm; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn"); return -1; } if (!(game = conn_get_game(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL game"); return -1; } if (!(realm = conn_get_realm(c))) { eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL realm"); return -1; } if ((packet=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(packet,sizeof(t_bnetd_d2cs_gameinforeq)); packet_set_type(packet,BNETD_D2CS_GAMEINFOREQ); bn_int_set(&packet->u.bnetd_d2cs_gameinforeq.h.seqno,0); packet_append_string(packet,game_get_name(game)); conn_push_outqueue(realm_get_conn(realm),packet); packet_del_ref(packet); } return 0; }
extern int irc_send_ping(t_connection * conn) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN]; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } if((conn_get_wol(conn) == 1)) return 0; conn_set_ircping(conn,get_ticks()); if (conn_get_state(conn)==conn_state_bot_username) sprintf(data,"PING :%u\r\n",conn_get_ircping(conn)); /* Undernet doesn't reveal the servername yet ... neither do we */ else if ((6+strlen(server_get_hostname())+2+1)<=MAX_IRC_MESSAGE_LEN) sprintf(data,"PING :%s\r\n",server_get_hostname()); else eventlog(eventlog_level_error,__FUNCTION__,"maximum message length exceeded"); eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); packet_set_size(p,0); packet_append_data(p,data,strlen(data)); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; }
static int on_d2cs_authreply(t_connection * c, t_packet const * packet) { t_packet * rpacket; unsigned int version; unsigned int try_version; unsigned int reply; char const * realmname; t_realm * realm; if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_authreply)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size"); return -1; } if (!(realmname=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_authreply),REALM_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad realmname"); return -1; } if (!(realm=realmlist_find_realm(realmname))) { realm=realmlist_find_realm_by_ip(conn_get_addr(c)); /* should not fail - checked in handle_init_packet() handle_init.c */ eventlog(eventlog_level_warn,__FUNCTION__, "warn: realm name mismatch %s %s", realm_get_name(realm), realmname); if (!(prefs_allow_d2cs_setname())) { /* fail if allow_d2cs_setname = false */ eventlog(eventlog_level_error,__FUNCTION__, "d2cs not allowed to set realm name"); return -1; } if (realm_get_active(realm)) { /* fail if realm already active */ eventlog(eventlog_level_error,__FUNCTION__, "cannot set realm name to %s (realm already active)",realmname); return -1; } realm_set_name(realm,realmname); } version=prefs_get_d2cs_version(); try_version=bn_int_get(packet->u.d2cs_bnetd_authreply.version); if (version && version != try_version) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs version mismatch 0x%X - 0x%X", try_version,version); reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION; } else { reply=BNETD_D2CS_AUTHREPLY_SUCCEED; } if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) { eventlog(eventlog_level_info,__FUNCTION__,"d2cs %s authed", addr_num_to_ip_str(conn_get_addr(c))); conn_set_state(c,conn_state_loggedin); realm_active(realm,c); } else { eventlog(eventlog_level_error,__FUNCTION__,"failed to auth d2cs %s", addr_num_to_ip_str(conn_get_addr(c))); } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply)); packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_authreply.h.seqno,1); bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } 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); }
extern int irc_send_cmd2(t_connection * conn, char const * prefix, char const * command, char const * postfix, char const * comment) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN+1]; int len; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!prefix) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL prefix"); return -1; } if (!command) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command"); return -1; } if (!postfix) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL postfix"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } if (comment) { len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+2+strlen(comment)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s :%s\r\n",prefix,command,postfix,comment); } else { len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s\r\n",prefix,command,postfix); } packet_set_size(p,0); packet_append_data(p,data,len); // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; }
extern int irc_send_cmd(t_connection * conn, char const * command, char const * params) { t_packet * p; char data[MAX_IRC_MESSAGE_LEN+1]; int len; char const * ircname = server_get_hostname(); char const * nick; if (!conn) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!command) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL command"); return -1; } if (!(p = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create packet"); return -1; } nick = conn_get_loggeduser(conn); if (!nick) nick = ""; /* snprintf isn't portable -> check message length first */ if (params) { len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+strlen(params)+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s %s\r\n",ircname,command,nick,params); } else { len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+2; if (len > MAX_IRC_MESSAGE_LEN) { eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len); return -1; } else sprintf(data,":%s %s %s\r\n",ircname,command,nick); } packet_set_size(p,0); packet_append_data(p,data,len); // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data); conn_push_outqueue(conn,p); packet_del_ref(p); return 0; }
static int on_bnetd_accountloginreply(t_connection * c, t_packet * packet) { unsigned int seqno; t_sq * sq; t_packet * opacket, * rpacket; t_connection * client; int result, reply; char const * account; t_elem * elem; if (!packet || !c) return -1; seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return -1; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&elem); return -1; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno); sq_destroy(sq,&elem); return -1; } result=bn_int_get(packet->u.bnetd_d2cs_accountloginreply.reply); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { reply=D2CS_CLIENT_LOGINREPLY_SUCCEED; account=packet_get_str_const(opacket,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN); d2cs_conn_set_account(client,account); d2cs_conn_set_state(client,conn_state_authed); eventlog(eventlog_level_info,__FUNCTION__,"account %s authed",account); } else { eventlog(eventlog_level_warn,__FUNCTION__,"client %d login request was rejected by bnetd",sq_get_clientid(sq)); reply=D2CS_CLIENT_LOGINREPLY_BADPASS; } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_loginreply)); packet_set_type(rpacket,D2CS_CLIENT_LOGINREPLY); bn_int_set(&rpacket->u.d2cs_client_loginreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } sq_destroy(sq,&elem); return 0; }
extern int handle_d2cs_init(t_connection * c) { t_packet * packet; if ((packet=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq)); packet_set_type(packet,BNETD_D2CS_AUTHREQ); bn_int_set(&packet->u.bnetd_d2cs_authreq.h.seqno,1); bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c)); conn_push_outqueue(c,packet); packet_del_ref(packet); } eventlog(eventlog_level_info,__FUNCTION__,"sent init packet to d2cs (sessionnum=%d)", conn_get_sessionnum(c)); return 0; }
static int on_bnetd_authreq(t_connection * c, t_packet * packet) { t_packet * rpacket; unsigned int sessionnum; sessionnum=bn_int_get(packet->u.bnetd_d2cs_authreq.sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"received bnetd sessionnum %d",sessionnum); if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_d2cs_bnetd_authreply)); packet_set_type(rpacket,D2CS_BNETD_AUTHREPLY); bn_int_set(&rpacket->u.d2cs_bnetd_authreply.h.seqno,1); bn_int_set(&rpacket->u.d2cs_bnetd_authreply.version,D2CS_VERSION_NUMBER); packet_append_string(rpacket,prefs_get_realmname()); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; }
static int on_client_loginreq(t_connection * c, t_packet * packet) { t_packet * bnpacket; char const * account; t_sq * sq; unsigned int sessionnum; if (!(account=packet_get_str_const(packet,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (!bnetd_conn()) { eventlog(eventlog_level_warn,__FUNCTION__,"d2cs is offline with bnetd, login request will be rejected"); return -1; } sessionnum=bn_int_get(packet->u.client_d2cs_loginreq.sessionnum); conn_set_bnetd_sessionnum(c,sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"got client (*%s) login request sessionnum=0x%X",account,sessionnum); if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) { packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_accountloginreq)); packet_set_type(bnpacket,D2CS_BNETD_ACCOUNTLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.seqno, bn_int_get(packet->u.client_d2cs_loginreq.seqno)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionkey, bn_int_get(packet->u.client_d2cs_loginreq.sessionkey)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionnum,sessionnum); memcpy(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash, packet->u.client_d2cs_loginreq.secret_hash, sizeof(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash)); packet_append_string(bnpacket,account); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; }
static int _client_anongame_cancel(t_connection * c) { t_packet * rpacket; t_connection * tc[ANONGAME_MAX_GAMECOUNT / 2]; // [quetzal] 20020809 - added a_count, so we dont refer to already destroyed anongame t_anongame *a = conn_get_anongame(c); int a_count, i; eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME CANCEL packet", conn_get_socket(c)); if (!a) return -1; a_count = anongame_get_count(a); // anongame_unqueue(c, anongame_get_queue(a)); // -- already doing unqueue in conn_destroy_anongame for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++) tc[i] = anongame_get_tc(a, i); for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++) { if (tc[i] == NULL) continue; conn_set_routeconn(tc[i], NULL); conn_destroy_anongame(tc[i]); } if (!(rpacket = packet_create(packet_class_bnet))) return -1; packet_set_size(rpacket, sizeof(t_server_findanongame_playgame_cancel)); packet_set_type(rpacket, SERVER_FINDANONGAME_PLAYGAME_CANCEL); bn_byte_set(&rpacket->u.server_findanongame_playgame_cancel.cancel, SERVER_FINDANONGAME_CANCEL); bn_int_set(&rpacket->u.server_findanongame_playgame_cancel.count, a_count); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); return 0; }
int on_bnetd_gameinforeq(t_connection * c, t_packet * packet) { t_packet * rpacket; t_game * game; char const * gamename; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(gamename = packet_get_str_const(packet,sizeof(t_bnetd_d2cs_gameinforeq),MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename"); return -1; } if (!(game = d2cs_gamelist_find_game(gamename))) { eventlog(eventlog_level_error,__FUNCTION__,"request for unknown game \"%s\"",gamename); return -1; } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket, sizeof(t_d2cs_bnetd_gameinforeply)); packet_set_type(rpacket, D2CS_BNETD_GAMEINFOREPLY); bn_int_set(&rpacket->u.d2cs_bnetd_gameinforeply.h.seqno,0); packet_append_string(rpacket, gamename); bn_byte_set(&rpacket->u.d2cs_bnetd_gameinforeply.difficulty, game_get_gameflag_difficulty(game)); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; }
extern int handle_bot_packet(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_raw) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } { char const * const linestr=packet_get_str_const(packet,0,MAX_MESSAGE_LEN); if (packet_get_size(packet)<2) /* empty line */ return 0; if (!linestr) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] line too long",conn_get_socket(c)); return 0; } switch (conn_get_state(c)) { case conn_state_connected: conn_add_flags(c,MF_PLUG); conn_set_clienttag(c,CLIENTTAG_BNCHATBOT_UINT); { char const * temp=linestr; if (temp[0]=='\004') /* FIXME: no echo, ignore for now (we always do no echo) */ temp = &temp[1]; if (temp[0]=='\0') /* empty line */ { conn_set_state(c,conn_state_bot_username); /* don't look for ^D or reset tag and flags */ break; } conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,temp)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),temp); { char const * const msg="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,conn_get_loggeduser(c)); #endif packet_append_ntstring(rpacket,msg); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } break; case conn_state_bot_username: conn_set_state(c,conn_state_bot_password); if (conn_set_loggeduser(c,linestr)<0) eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),linestr); { char const * const temp="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } #if 1 /* don't echo */ packet_append_ntstring(rpacket,linestr); #endif packet_append_ntstring(rpacket,temp); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } break; case conn_state_bot_password: { char const * const tempa="\r\nLogin failed.\r\n\r\nUsername: "******"\r\nAccount has no bot access.\r\n\r\nUsername: "******"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (connlist_find_connection_by_accountname(loggeduser)) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (already logged in)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (!(account = accountlist_find_account(loggeduser))) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (bad account)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if ((oldstrhash1 = account_get_pass(account))) { if (hash_set_str(&oldpasshash1,oldstrhash1)<0) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (corrupted passhash1?)",conn_get_socket(c),loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } testpass = xstrdup(linestr); { unsigned int i; for (i=0; i<strlen(testpass); i++) if (isupper((int)testpass[i])) testpass[i] = tolower((int)testpass[i]); } if (bnet_hash(&trypasshash1,strlen(testpass),testpass)<0) /* FIXME: force to lowercase */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (unable to hash password)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); xfree((void *)testpass); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } xfree((void *)testpass); if (hash_eq(trypasshash1,oldpasshash1)!=1) { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (wrong password)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempa); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } if (account_get_auth_botlogin(account)!=1) /* default to false */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (no bot access)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempb); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } else if (account_get_auth_lock(account)==1) /* default to false */ { eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (this account is locked)",conn_get_socket(c), loggeduser); conn_set_state(c,conn_state_bot_username); if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); break; } packet_append_ntstring(rpacket,tempb); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); break; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (correct password)",conn_get_socket(c), loggeduser); } else { eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (no password)",conn_get_socket(c), loggeduser); } if (!(rpacket = packet_create(packet_class_raw))) /* if we got this far, let them log in even if this fails */ eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c)); else { packet_append_ntstring(rpacket,"\r\n"); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } bnetd_log(loggeduser, addr_num_to_ip_str(conn_get_addr(c)), "BOT", "LOGIN", NULL, 1, 0); conn_login(c,account,loggeduser); message_send_text(c,message_type_uniqueid,c,loggeduser); if (conn_set_channel(c,CHANNEL_NAME_CHAT)<0) conn_set_channel(c,CHANNEL_NAME_BANNED); /* should not fail */ } break; case conn_state_loggedin: { t_channel const * channel; conn_set_idletime(c); if ((channel = conn_get_channel(c))) channel_message_log(channel,c,1,linestr); /* we don't log game commands currently */ if (linestr[0]=='/') handle_command(c,linestr); else if (channel && !conn_quota_exceeded(c,linestr)) channel_message_send(channel,message_type_talk,c,linestr); /* else discard */ } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown bot connection state %d",conn_get_socket(c),(int)conn_get_state(c)); } } return 0; }
static int on_bnetd_charloginreply(t_connection * c, t_packet * packet) { unsigned int seqno; t_sq * sq; t_connection * client; t_packet * opacket, * rpacket; int result, reply, type; char const * charname; t_elem * elem; if (!packet || !c) return -1; seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno); if (!(sq=sqlist_find_sq(seqno))) { eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno); return -1; } if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) { eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq)); sq_destroy(sq,&elem); return -1; } if (!(opacket=sq_get_packet(sq))) { eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno); sq_destroy(sq,&elem); return -1; } type=packet_get_type(opacket); result=bn_int_get(packet->u.bnetd_d2cs_charloginreply.reply); if (type==CLIENT_D2CS_CREATECHARREQ) { charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { if (conn_check_multilogin(client,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; } else { reply= D2CS_CLIENT_CREATECHARREPLY_SUCCEED; eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname); d2cs_conn_set_charname(client,charname); d2cs_conn_set_state(client,conn_state_char_authed); } } else { reply = D2CS_CLIENT_CREATECHARREPLY_FAILED; eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_createcharreply)); packet_set_type(rpacket,D2CS_CLIENT_CREATECHARREPLY); bn_int_set(&rpacket->u.d2cs_client_createcharreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } } else if (type==CLIENT_D2CS_CHARLOGINREQ) { charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_charloginreq),MAX_CHARNAME_LEN); if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) { if (conn_check_multilogin(client,charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname); reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; } else { reply = D2CS_CLIENT_CHARLOGINREPLY_SUCCEED; eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname); d2cs_conn_set_charname(client,charname); d2cs_conn_set_state(client,conn_state_char_authed); } } else { reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED; eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_charloginreply)); packet_set_type(rpacket,D2CS_CLIENT_CHARLOGINREPLY); bn_int_set(&rpacket->u.d2cs_client_charloginreply.reply,reply); conn_push_outqueue(client,rpacket); packet_del_ref(rpacket); } } else { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d",type); sq_destroy(sq,&elem); return -1; } sq_destroy(sq,&elem); return 0; }
static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet) { unsigned int sessionkey; unsigned int sessionnum; unsigned int salt; char const * account; char const * tname; t_connection * client; int reply; t_packet * rpacket; struct { bn_int salt; bn_int sessionkey; bn_int sessionnum; bn_int secret; bn_int passhash[5]; } temp; t_hash secret_hash; char const * pass_str; t_hash passhash; t_hash try_hash; if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_accountloginreq)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size"); return -1; } if (!(account=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_accountloginreq),USER_NAME_MAX))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long account name"); return -1; } sessionkey=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionkey); sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum); salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno); if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) { eventlog(eventlog_level_error,__FUNCTION__,"sessionnum %d not found",sessionnum); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (sessionkey!=conn_get_sessionkey(client)) { eventlog(eventlog_level_error,__FUNCTION__,"sessionkey %d not match",sessionkey); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (!(tname=conn_get_username(client))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL username"); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else if (strcasecmp(account,tname)) { eventlog(eventlog_level_error,__FUNCTION__,"username %s not match",account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else { bn_int_set(&temp.salt,salt); bn_int_set(&temp.sessionkey,sessionkey); bn_int_set(&temp.sessionnum,sessionnum); bn_int_set(&temp.secret,conn_get_secret(client)); pass_str=account_get_pass(conn_get_account(client)); if (hash_set_str(&passhash,pass_str)<0) { reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } else { hash_to_bnhash((t_hash const *)&passhash,temp.passhash); bnet_hash(&secret_hash,sizeof(temp),&temp); bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash); if (hash_eq(try_hash,secret_hash)==1) { eventlog(eventlog_level_debug,__FUNCTION__,"user %s loggedin on d2cs", account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED; } else { eventlog(eventlog_level_error,__FUNCTION__,"user %s hash not match", account); reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED; } } } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply)); packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno, bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno)); bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0; }
static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet) { t_connection * client; char const * charname; char const * portrait; char const * clienttag; char * temp; unsigned int sessionnum; t_realm * realm; char const * realmname; unsigned int pos, reply; t_packet * rpacket; if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_charloginreq)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size"); return -1; } sessionnum=bn_int_get(packet->u.d2cs_bnetd_charloginreq.sessionnum); pos=sizeof(t_d2cs_bnetd_charloginreq); if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } pos+=strlen(charname)+1; if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character portrait"); return -1; } if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) { eventlog(eventlog_level_error,__FUNCTION__,"user %d not found",sessionnum); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else if (!(clienttag=clienttag_uint_to_str(conn_get_clienttag(client)))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL clienttag"); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else if (!(realm=conn_get_realm(client))) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm"); reply = BNETD_D2CS_CHARLOGINREPLY_FAILED; } else { char revtag[8]; realmname = realm_get_name(realm); temp=xmalloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+ strlen(portrait)+1); reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED; strcpy(revtag,clienttag); strreverse(revtag); sprintf(temp,"%4s%s,%s,%s",revtag,realmname,charname,portrait); conn_set_charname(client,charname); conn_set_realminfo(client,temp); xfree(temp); eventlog(eventlog_level_debug,__FUNCTION__, "loaded portrait for character %s",charname); } if ((rpacket=packet_create(packet_class_d2cs_bnetd))) { packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply)); packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY); bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno, bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno)); bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } 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; }
extern int handle_file_packet(t_connection * c, t_packet const * const packet) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } /* REMOVED BY UNDYING SOULZZ 4/3/02 */ /* if (packet_get_class(packet)!=packet_class_file) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } */ switch (conn_get_state(c)) { case conn_state_connected: switch (packet_get_type(packet)) { case CLIENT_FILE_REQ: { char const * rawname; if (!(rawname = packet_get_str_const(packet,sizeof(t_client_file_req),MAX_FILENAME_STR))) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad FILE_REQ (missing or too long filename)",conn_get_socket(c)); return -1; } file_send(c,rawname, bn_int_get(packet->u.client_file_req.adid), bn_int_get(packet->u.client_file_req.extensiontag), bn_int_get(packet->u.client_file_req.startoffset), 1); } break; case CLIENT_FILE_REQ2: { t_packet * rpacket = NULL; if((rpacket = packet_create(packet_class_raw))) { packet_set_size(rpacket,sizeof(t_server_file_unknown1)); bn_int_set( &rpacket->u.server_file_unknown1.unknown, 0xdeadbeef ); conn_push_outqueue(c, rpacket ); packet_del_ref( rpacket ); } conn_set_state(c, conn_state_pending_raw); break; } default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); break; } break; case conn_state_pending_raw: switch (packet_get_type(packet)) { case CLIENT_FILE_REQ3: { char rawname[MAX_FILENAME_STR]; psock_recv( conn_get_socket(c), rawname, MAX_FILENAME_STR, 0 ); file_send(c, rawname, 0, 0, 0, 1); } break; default: eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); break; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file connection state %d",conn_get_socket(c),(int)conn_get_state(c)); } return 0; }
static int _client_anongame_infos(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (bn_int_get(packet->u.client_findanongame_inforeq.count) > 1) { /* reply with 0 entries found */ int temp = 0; 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_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, 0); packet_append_data(rpacket, &temp, 1); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } else { int i; int client_tag; int server_tag_count = 0; int client_tag_unk; int server_tag_unk; bn_int temp; char noitems; char * tmpdata; int tmplen; t_clienttag clienttag = conn_get_clienttag(c); char last_packet = 0x00; char other_packet = 0x01; char langstr[5]; t_gamelang gamelang = conn_get_gamelang(c); bn_int_tag_get((bn_int const *)&gamelang, langstr, 5); /* Send seperate packet for each item requested * sending all at once overloaded w3xp * [Omega] */ for (i = 0; i < bn_byte_get(packet->u.client_findanongame_inforeq.noitems); i++){ noitems = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } /* Starting the packet stuff */ packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, 1); std::memcpy(&temp, (packet_get_data_const(packet, 10 + (i * 8), 4)), sizeof(int)); client_tag = bn_int_get(temp); std::memcpy(&temp, packet_get_data_const(packet, 14 + (i * 8), 4), sizeof(int)); client_tag_unk = bn_int_get(temp); switch (client_tag){ case CLIENT_FINDANONGAME_INFOTAG_URL: bn_int_set((bn_int*)&server_tag_unk, 0xBF1F1047); packet_append_data(rpacket, "LRU\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); // FIXME: Maybe need do do some checks to avoid prefs empty strings. tmpdata = anongame_infos_data_get_url(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_URL", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_MAP: bn_int_set((bn_int*)&server_tag_unk, 0x70E2E0D5); packet_append_data(rpacket, "PAM\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_map(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_MAP", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_TYPE: bn_int_set((bn_int*)&server_tag_unk, 0x7C87DEEE); packet_append_data(rpacket, "EPYT", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_type(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_TYPE", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_DESC: bn_int_set((bn_int*)&server_tag_unk, 0xA4F0A22F); packet_append_data(rpacket, "CSED", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_desc(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_DESC", client_tag_unk); noitems++; server_tag_count++; break; case CLIENT_FINDANONGAME_INFOTAG_LADR: bn_int_set((bn_int*)&server_tag_unk, 0x3BADE25A); packet_append_data(rpacket, "RDAL", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_ladr(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_LADR", client_tag_unk); break; default: eventlog(eventlog_level_debug, __FUNCTION__, "unrec client_tag request tagid=(0x%01x) tag=(0x%04x)", i, client_tag); } //Adding a last padding null-byte if (server_tag_count == bn_byte_get(packet->u.client_findanongame_inforeq.noitems)) packet_append_data(rpacket, &last_packet, 1); /* only last packet in group gets 0x00 */ else packet_append_data(rpacket, &other_packet, 1); /* the rest get 0x01 */ //Go,go,go bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, noitems); 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; }
/* Send a file. If the file doesn't exist we still need to respond * to the file request. This will set filelen to 0 and send the server * reply message and the client will be happy and not hang. */ extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header) { char const * filename; t_packet * rpacket; std::FILE * fp; unsigned int filelen; int nbytes; if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!rawname) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname"); return -1; } if (!(rpacket = packet_create(packet_class_file))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create file packet"); return -1; } packet_set_size(rpacket,sizeof(t_server_file_reply)); packet_set_type(rpacket,SERVER_FILE_REPLY); if ((filename = file_get_info(rawname,&filelen,&rpacket->u.server_file_reply.timestamp))) { if (!(fp = std::fopen(filename,"rb"))) { /* FIXME: check for lower-case version of filename */ eventlog(eventlog_level_error,__FUNCTION__, "stat() succeeded yet could not open file \"%s\" for reading (std::fopen: %s)", filename, std::strerror(errno)); filelen = 0; } xfree((void *)filename); /* avoid warning */ } else { fp = NULL; filelen = 0; bn_long_set_a_b(&rpacket->u.server_file_reply.timestamp,0,0); } if (fp) { if (startoffset<filelen) { std::fseek(fp,startoffset,SEEK_SET); } else { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] startoffset is beyond end of file (%u>%u)",conn_get_socket(c),startoffset,filelen); /* Keep the real filesize. Battle.net does it the same way ... */ std::fclose(fp); fp = NULL; } } if (need_header) { /* send the header from the server with the rawname and length. */ bn_int_set(&rpacket->u.server_file_reply.filelen,filelen); bn_int_set(&rpacket->u.server_file_reply.adid,adid); bn_int_set(&rpacket->u.server_file_reply.extensiontag,etag); /* rpacket->u.server_file_reply.timestamp is set above */ packet_append_string(rpacket,rawname); conn_push_outqueue(c,rpacket); } packet_del_ref(rpacket); /* Now send the data. Since it may be longer than a packet; we use * the raw packet class. */ if (!fp) { eventlog(eventlog_level_warn,__FUNCTION__,"[%d] sending no data for file \"%s\"",conn_get_socket(c),rawname); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"[%d] sending file \"%s\" of length %d",conn_get_socket(c),rawname,filelen); for (;;) { if (!(rpacket = packet_create(packet_class_raw))) { eventlog(eventlog_level_error,__FUNCTION__,"could not create raw packet"); if (std::fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (std::fclose: %s)",rawname,std::strerror(errno)); return -1; } if ((nbytes = std::fread(packet_get_raw_data_build(rpacket,0),1,MAX_PACKET_SIZE,fp))<(int)MAX_PACKET_SIZE) { if (nbytes>0) /* send out last portion */ { packet_set_size(rpacket,nbytes); conn_push_outqueue(c,rpacket); } packet_del_ref(rpacket); if (std::ferror(fp)) eventlog(eventlog_level_error,__FUNCTION__,"read failed before EOF on file \"%s\" (std::fread: %s)",rawname,std::strerror(errno)); break; } packet_set_size(rpacket,nbytes); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } if (std::fclose(fp)<0) eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (std::fclose: %s)",rawname,std::strerror(errno)); 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; }
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; }