📄 handle_d2gs.c
字号:
/* * Copyright (C) 2000,2001 Onlyer (onlyer@263.net) * * 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"#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H# include <malloc.h># endif#endif#ifdef HAVE_SYS_TYPES_H# include <sys/types.h> /* needed to include netinet/in.h */#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#include "compat/socket.h"#ifdef HAVE_NETINET_IN_H# include <netinet/in.h>#endif#include "compat/netinet_in.h"#ifdef HAVE_ARPA_INET_H# include <arpa/inet.h> /* FIXME: probably not needed... do some systems put types in here or something? */#endif#include "compat/psock.h"#include "d2gs.h"#include "handle_d2gs.h"#include "serverqueue.h"#include "game.h"#include "connection.h"#include "prefs.h"#include "d2cs_d2gs_protocol.h"#include "common/trans.h"#include "common/addr.h"#include "common/eventlog.h"#include "common/queue.h"#include "common/bn_type.h"#include "common/packet.h"#include "common/xalloc.h"#include "common/setup_after.h"DECLARE_PACKET_HANDLER(on_d2gs_authreply)DECLARE_PACKET_HANDLER(on_d2gs_setgsinfo)DECLARE_PACKET_HANDLER(on_d2gs_echoreply)DECLARE_PACKET_HANDLER(on_d2gs_creategamereply)DECLARE_PACKET_HANDLER(on_d2gs_joingamereply)DECLARE_PACKET_HANDLER(on_d2gs_updategameinfo)DECLARE_PACKET_HANDLER(on_d2gs_closegame)static t_packet_handle_table d2gs_packet_handle_table[]={/* 0x00 */ { 0, conn_state_none, NULL },/* 0x01 */ { 0, conn_state_none, NULL },/* 0x02 */ { 0, conn_state_none, NULL },/* 0x03 */ { 0, conn_state_none, NULL },/* 0x04 */ { 0, conn_state_none, NULL },/* 0x05 */ { 0, conn_state_none, NULL },/* 0x06 */ { 0, conn_state_none, NULL },/* 0x07 */ { 0, conn_state_none, NULL },/* 0x08 */ { 0, conn_state_none, NULL },/* 0x09 */ { 0, conn_state_none, NULL },/* 0x0a */ { 0, conn_state_none, NULL },/* 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 },/* FIXME: shouldn't these three be at 0x10-0x12? (But I'm pretty sure I preserved the padding) *//* 0x11 */ { sizeof(t_d2gs_d2cs_authreply), conn_state_connected, on_d2gs_authreply },/* 0x12 */ { sizeof(t_d2gs_d2cs_setgsinfo), conn_state_authed, on_d2gs_setgsinfo },/* 0x13 */ { sizeof(t_d2gs_d2cs_echoreply), conn_state_any, on_d2gs_echoreply },/* 0x14 */ { 0, conn_state_none, NULL },/* 0x15 */ { 0, conn_state_none, NULL },/* 0x16 */ { 0, conn_state_none, NULL },/* 0x17 */ { 0, conn_state_none, NULL },/* 0x18 */ { 0, conn_state_none, NULL },/* 0x19 */ { 0, conn_state_none, NULL },/* 0x1a */ { 0, conn_state_none, NULL },/* 0x1b */ { 0, conn_state_none, NULL },/* 0x1c */ { 0, conn_state_none, NULL },/* 0x1d */ { 0, conn_state_none, NULL },/* 0x1e */ { 0, conn_state_none, NULL },/* 0x1f */ { 0, conn_state_none, NULL },/* 0x20 */ { sizeof(t_d2gs_d2cs_creategamereply),conn_state_authed, on_d2gs_creategamereply },/* 0x21 */ { sizeof(t_d2gs_d2cs_joingamereply), conn_state_authed, on_d2gs_joingamereply },/* 0x22 */ { sizeof(t_d2gs_d2cs_updategameinfo), conn_state_authed, on_d2gs_updategameinfo },/* 0x23 */ { sizeof(t_d2gs_d2cs_closegame), conn_state_authed, on_d2gs_closegame },};static void d2gs_send_init_info(t_d2gs * gs, t_connection * c){ t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2gs))) { packet_set_size(rpacket,sizeof(t_d2cs_d2gs_setinitinfo)); packet_set_type(rpacket,D2CS_D2GS_SETINITINFO); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.time, time(NULL)); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.gs_id, d2gs_get_id(gs)); bn_int_set(&rpacket->u.d2cs_d2gs_setinitinfo.ac_version, 0);// packet_append_string(rpacket,prefs_get_d2gs_ac_checksum()); packet_append_string(rpacket,"bogus_ac_checksum");// packet_append_string(rpacket,prefs_get_d2gs_ac_string()); packet_append_string(rpacket,"bogus_ac_string"); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return;}static void d2gs_send_server_conffile(t_d2gs *gs, t_connection *c){ t_packet *rpacket; FILE *fp; char buff[256]; int rno; struct stat sfile; /* open d2gs server config file */ fp = fopen(prefs_get_d2gsconffile(), "rb"); if (!fp) goto err; /* get file size */ if (fstat(fileno(fp),&sfile)) { eventlog(eventlog_level_debug,__FUNCTION__,"failed fstat()"); goto err_fp; } rpacket = packet_create(packet_class_d2cs); packet_set_size(rpacket,sizeof(t_d2cs_d2gs_setconffile)); packet_set_type(rpacket,D2CS_D2GS_SETCONFFILE); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.size, sfile.st_size); bn_int_set(&rpacket->u.d2cs_d2gs_setconffile.reserved1, time(NULL)); while((rno = fread(buff,1,sizeof(buff),fp)) > 0) { if (packet_append_data(rpacket,buff,rno) < 0) { /* file too big */ eventlog(eventlog_level_debug,__FUNCTION__,"conffile too big for a single packet"); goto err_packet; } } conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); fclose(fp); return;err_packet: packet_del_ref(rpacket);err_fp: fclose(fp);err: return;}static int on_d2gs_authreply(t_connection * c, t_packet * packet){ t_d2gs * gs; t_packet * rpacket; unsigned int reply; unsigned int try_checksum, checksum; unsigned int version, conf_version; unsigned int randnum, signlen; unsigned char *sign; if (!(gs=d2gslist_find_gs(conn_get_d2gs_id(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d not found",conn_get_d2gs_id(c)); return -1; } version=bn_int_get(packet->u.d2gs_d2cs_authreply.version); try_checksum=bn_int_get(packet->u.d2gs_d2cs_authreply.checksum); checksum=d2gs_calc_checksum(c); conf_version = prefs_get_d2gs_version(); randnum = bn_int_get(packet->u.d2gs_d2cs_authreply.randnum); signlen = bn_int_get(packet->u.d2gs_d2cs_authreply.signlen); sign = packet->u.d2gs_d2cs_authreply.sign; if (conf_version && conf_version != version) { eventlog(eventlog_level_warn,__FUNCTION__,"game server %d version mismatch 0x%X - 0x%X",conn_get_d2gs_id(c), version,conf_version); } if (conf_version && !MAJOR_VERSION_EQUAL(version, conf_version, D2GS_MAJOR_VERSION_MASK)) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d major version mismatch 0x%X - 0x%X",conn_get_d2gs_id(c), version,conf_version); reply=D2CS_D2GS_AUTHREPLY_BAD_VERSION; } else if (prefs_get_d2gs_checksum() && try_checksum != checksum) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d checksum mismach 0x%X - 0x%X",conn_get_d2gs_id(c),try_checksum,checksum); reply=D2CS_D2GS_AUTHREPLY_BAD_CHECKSUM;// } else if (license_verify_reply(c, randnum, sign, signlen)) {// eventlog(eventlog_level_error,__FUNCTION__,"game server %d signal mismach", conn_get_d2gs_id(c));// reply=D2CS_D2GS_AUTHREPLY_BAD_CHECKSUM; } else { reply=D2CS_D2GS_AUTHREPLY_SUCCEED; } if (reply==D2CS_D2GS_AUTHREPLY_SUCCEED) { eventlog(eventlog_level_info,__FUNCTION__,"game server %s authed",addr_num_to_ip_str(d2cs_conn_get_addr(c))); d2cs_conn_set_state(c,conn_state_authed); d2gs_send_server_conffile(gs, c); d2gs_send_init_info(gs, c); d2gs_active(gs,c); } else { eventlog(eventlog_level_error,__FUNCTION__,"game server %s failed to auth",addr_num_to_ip_str(d2cs_conn_get_addr(c))); /* d2cs_conn_set_state(c,conn_state_destroy); */ } if ((rpacket=packet_create(packet_class_d2gs))) { packet_set_size(rpacket,sizeof(t_d2cs_d2gs_authreply)); packet_set_type(rpacket,D2CS_D2GS_AUTHREPLY); bn_int_set(&rpacket->u.d2cs_d2gs_authreply.h.seqno,0); bn_int_set(&rpacket->u.d2cs_d2gs_authreply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } return 0;}static int on_d2gs_setgsinfo(t_connection * c, t_packet * packet){ t_d2gs * gs; t_packet * rpacket; unsigned int maxgame, prev_maxgame; unsigned int currgame, gameflag; if (!(gs=d2gslist_find_gs(conn_get_d2gs_id(c)))) { eventlog(eventlog_level_error,__FUNCTION__,"game server %d not found",conn_get_d2gs_id(c)); return -1; } maxgame=bn_int_get(packet->u.d2gs_d2cs_setgsinfo.maxgame); gameflag=bn_int_get(packet->u.d2gs_d2cs_setgsinfo.gameflag);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -