📄 handle_d2cs.c
字号:
/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * Copyright (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "common/setup_before.h"#include "setup.h"#include <stdio.h>#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H# include <strings.h># endif# ifdef HAVE_MEMORY_H# include <memory.h># endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H# include <malloc.h># endif#endif#include "compat/memcpy.h"#ifdef TIME_WITH_SYS_TIME# include <time.h># include <sys/time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#endif#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#ifdef HAVE_NETINET_IN_H# include <netinet/in.h>#endif#include "compat/socket.h"#include "compat/netinet_in.h"#ifdef HAVE_ARPA_INET_H# include <arpa/inet.h>#endif#include "compat/inet_ntoa.h"#include "compat/pdir.h"#include "compat/mkdir.h"#include "d2charfile.h"#include "connection.h"#include "game.h"#include "bnetd.h"#include "d2cs_protocol.h"#include "d2cs_bnetd_protocol.h"#include "handle_d2cs.h"#include "d2ladder.h"#include "gamequeue.h"#include "serverqueue.h"#include "prefs.h"#include "common/bn_type.h"#include "common/queue.h"#include "common/packet.h"#include "common/eventlog.h"#include "d2charlist.h"#include "common/elist.h"#include "common/xalloc.h"#include "common/setup_after.h"static int d2cs_send_client_ladder(t_connection * c, unsigned char type, unsigned short from);static unsigned int d2cs_try_joingame(t_connection const * c, t_game const * game, char const * gamepass);DECLARE_PACKET_HANDLER(on_client_loginreq)DECLARE_PACKET_HANDLER(on_client_createcharreq)DECLARE_PACKET_HANDLER(on_client_creategamereq)DECLARE_PACKET_HANDLER(on_client_joingamereq)DECLARE_PACKET_HANDLER(on_client_gamelistreq)DECLARE_PACKET_HANDLER(on_client_gameinforeq)DECLARE_PACKET_HANDLER(on_client_charloginreq)DECLARE_PACKET_HANDLER(on_client_deletecharreq)DECLARE_PACKET_HANDLER(on_client_ladderreq)DECLARE_PACKET_HANDLER(on_client_motdreq)DECLARE_PACKET_HANDLER(on_client_cancelcreategame)DECLARE_PACKET_HANDLER(on_client_charladderreq)DECLARE_PACKET_HANDLER(on_client_charlistreq)DECLARE_PACKET_HANDLER(on_client_charlistreq_110)DECLARE_PACKET_HANDLER(on_client_convertcharreq)static t_packet_handle_table d2cs_packet_handle_table[]={/* 0x00 */ { 0, conn_state_none, NULL },/* 0x01 */ { sizeof(t_client_d2cs_loginreq), conn_state_connected, on_client_loginreq },/* 0x02 */ { sizeof(t_client_d2cs_createcharreq), conn_state_authed|conn_state_char_authed, on_client_createcharreq },/* 0x03 */ { sizeof(t_client_d2cs_creategamereq), conn_state_char_authed, on_client_creategamereq },/* 0x04 */ { sizeof(t_client_d2cs_joingamereq), conn_state_char_authed, on_client_joingamereq },/* 0x05 */ { sizeof(t_client_d2cs_gamelistreq), conn_state_char_authed, on_client_gamelistreq },/* 0x06 */ { sizeof(t_client_d2cs_gameinforeq), conn_state_char_authed, on_client_gameinforeq },/* 0x07 */ { sizeof(t_client_d2cs_charloginreq), conn_state_authed|conn_state_char_authed, on_client_charloginreq },/* 0x08 */ { 0, conn_state_none, NULL },/* 0x09 */ { 0, conn_state_none, NULL },/* 0x0a */ { sizeof(t_client_d2cs_deletecharreq), conn_state_authed|conn_state_char_authed, on_client_deletecharreq },/* 0x0b */ { 0, conn_state_none, NULL },/* 0x0c */ { 0, conn_state_none, NULL },/* 0x0d */ { 0, conn_state_none, NULL },/* 0x0e */ { 0, conn_state_none, NULL },/* 0x0f */ { 0, conn_state_none, NULL },/* 0x10 */ { 0, conn_state_none, NULL },/* 0x11 */ { sizeof(t_client_d2cs_ladderreq), conn_state_char_authed, on_client_ladderreq },/* 0x12 */ { sizeof(t_client_d2cs_motdreq), conn_state_char_authed, on_client_motdreq },/* 0x13 */ { sizeof(t_client_d2cs_cancelcreategame),conn_state_char_authed, on_client_cancelcreategame},/* 0x14 */ { 0, conn_state_none, NULL },/* 0x15 */ { 0, conn_state_none, NULL },/* 0x16 */ { sizeof(t_client_d2cs_charladderreq), conn_state_char_authed, on_client_charladderreq },/* 0x17 */ { sizeof(t_client_d2cs_charlistreq), conn_state_authed|conn_state_char_authed, on_client_charlistreq },/* 0x18 */ { sizeof(t_client_d2cs_convertcharreq), conn_state_authed|conn_state_char_authed, on_client_convertcharreq },/* 0x19 */ { sizeof(t_client_d2cs_charlistreq_110), conn_state_authed|conn_state_char_authed, on_client_charlistreq_110 }};extern int d2cs_handle_d2cs_packet(t_connection * c, t_packet * packet){ return conn_process_packet(c,packet,d2cs_packet_handle_table,NELEMS(d2cs_packet_handle_table));}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 on_client_createcharreq(t_connection * c, t_packet * packet){ t_packet * rpacket, * bnpacket; char const * charname; char const * account; char * path; t_pdir * dir; t_sq * sq; unsigned int reply; unsigned short status, class; t_d2charinfo_file data; if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name"); return -1; } if (!(account=d2cs_conn_get_account(c))) { eventlog(eventlog_level_error,__FUNCTION__,"missing account for character %s",charname); return -1; } class=bn_short_get(packet->u.client_d2cs_createcharreq.class); status=bn_short_get(packet->u.client_d2cs_createcharreq.status); path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1); d2char_get_infodir_name(path,account); if (!(dir=p_opendir(path))) { eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account); p_mkdir(path,S_IRWXU); } else p_closedir(dir); xfree(path); if (d2char_create(account,charname,class,status)<0) { eventlog(eventlog_level_warn,__FUNCTION__,"error create character %s for account %s",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_ALREADY_EXIST; } else if (d2charinfo_load(account,charname,&data)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for character %s(*%s)",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_FAILED; } else { eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) created",charname,account); reply=D2CS_CLIENT_CREATECHARREPLY_SUCCEED; conn_set_charinfo(c,&data.summary); 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_charloginreq)); packet_set_type(bnpacket,D2CS_BNETD_CHARLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.sessionnum, conn_get_bnetd_sessionnum(c)); packet_append_string(bnpacket,charname); packet_append_string(bnpacket,(char const *)&data.portrait); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; } 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(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+=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+=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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -