⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 d2gs.c

📁 打魔兽战网的都知道他是什么
💻 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 HAVE_STDDEF_H# include <stddef.h>#else# ifndef NULL#  define NULL ((void *)0)# endif#endif#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H#  include <malloc.h># endif#endif#ifdef HAVE_STRING_H# include <string.h>#else# ifdef HAVE_STRINGS_H#  include <strings.h># endif#endif#include "compat/strsep.h"#include "compat/char_bit.h"#ifdef HAVE_SYS_TYPES_H# include <sys/types.h> /* needed to include netinet/in.h */#endif#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#include "compat/socket.h"#ifdef HAVE_SYS_PARAM_H# include <sys/param.h>#endif#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#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include "compat/psock.h"#include "d2gs.h"#include "game.h"#include "net.h"#include "bit.h"#include "prefs.h"#include "connection.h"#include "common/introtate.h"#include "common/addr.h"#include "common/list.h"#include "common/eventlog.h"#include "common/xalloc.h"#include "common/setup_after.h"static t_list		* d2gslist_head=NULL;static unsigned int	d2gs_id=0;static unsigned int	total_d2gs=0;extern t_list *	d2gslist(void){	return d2gslist_head;}extern int d2gslist_create(void){	d2gslist_head=list_create();	return d2gslist_reload(prefs_get_d2gs_list());}extern int d2gslist_reload(char const * gslist){	t_addrlist	* gsaddrs;	t_d2gs		* gs;	if (!d2gslist_head) return -1;	BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)	{		BIT_CLR_FLAG(gs->flag, D2GS_FLAG_VALID);	}	END_LIST_TRAVERSE_DATA()	gsaddrs = addrlist_create(gslist, INADDR_ANY, 0);	if (gsaddrs) {	    t_elem const *acurr;	    t_addr * curr_laddr;	    LIST_TRAVERSE_CONST(gsaddrs, acurr)	    {		curr_laddr = (t_addr*)elem_get_data(acurr);		if (!curr_laddr) {		    eventlog(eventlog_level_error, __FUNCTION__, "found NULL value in gslist");		    continue;		}		if (!(gs=d2gslist_find_gs_by_ip(addr_get_ip(curr_laddr))))		    gs = d2gs_create(addr_num_to_ip_str(addr_get_ip(curr_laddr)));		if (gs) BIT_SET_FLAG(gs->flag, D2GS_FLAG_VALID);	    }	    addrlist_destroy(gsaddrs);	}	BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)	{		if (!BIT_TST_FLAG(gs->flag, D2GS_FLAG_VALID)) {			d2gs_destroy(gs,&curr_elem_);		}	}	END_LIST_TRAVERSE_DATA()	return 0;}extern int d2gslist_destroy(void){	t_d2gs	* gs;	BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)	{		d2gs_destroy(gs,(t_elem **)&curr_elem_);	}	END_LIST_TRAVERSE_DATA_CONST()	d2cs_connlist_reap();	if (list_destroy(d2gslist_head)<0) {		eventlog(eventlog_level_error,__FUNCTION__,"error destroy d2gs list");		return -1;	}	d2gslist_head=NULL;	return 0;}extern t_d2gs * d2gslist_find_gs_by_ip(unsigned int ip){	t_d2gs	* gs;	BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)	{		if (gs->ip==ip) return gs;	}	END_LIST_TRAVERSE_DATA_CONST()	return NULL;}extern t_d2gs * d2gslist_find_gs(unsigned int id){	t_d2gs	* gs;	BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)	{		if (gs->id==id) return gs;	}	END_LIST_TRAVERSE_DATA_CONST()	return NULL;}extern t_d2gs * d2gs_create(char const * ipaddr){	t_d2gs 	* gs;	unsigned int	ip;	ASSERT(ipaddr,NULL);	if ((ip=net_inet_addr(ipaddr))==~0U) {		eventlog(eventlog_level_error,__FUNCTION__,"got bad ip address %s",ipaddr);		return NULL;	}	if (d2gslist_find_gs_by_ip(ntohl(ip))) {		eventlog(eventlog_level_error,__FUNCTION__,"game server %s already in list",ipaddr);		return NULL;	}	gs=xmalloc(sizeof(t_d2gs));	gs->ip=ntohl(ip);	gs->id=++d2gs_id;	gs->active=0;	gs->token=0;	gs->state=d2gs_state_none;	gs->gamenum=0;	gs->maxgame=0;	gs->connection=NULL;	if (list_append_data(d2gslist_head,gs)<0) {		eventlog(eventlog_level_error,__FUNCTION__,"error add gs to list");		xfree(gs);		return NULL;	}	eventlog(eventlog_level_info,__FUNCTION__,"added game server %s (id: %d) to list",ipaddr,gs->id);	return gs;}extern int d2gs_destroy(t_d2gs * gs, t_elem ** curr){	ASSERT(gs,-1);	if (list_remove_data(d2gslist_head,gs,curr)<0) {		eventlog(eventlog_level_error,__FUNCTION__,"error remove gs from list");		return -1;	}	if (gs->active && gs->connection) {		d2cs_conn_set_state(gs->connection, conn_state_destroy);		d2gs_deactive(gs, gs->connection);	}	eventlog(eventlog_level_info,__FUNCTION__,"removed game server %s (id: %d) from list",addr_num_to_ip_str(gs->ip),gs->id);	xfree(gs);	return 0;}extern t_d2gs * d2gslist_get_server_by_id(unsigned int id){	t_d2gs	* gs;	BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)	{		if (gs->id==id) return gs;	}	END_LIST_TRAVERSE_DATA_CONST()	return NULL;}	  extern t_d2gs * d2gslist_choose_server(void){	t_d2gs			* gs;	t_d2gs			* ogs;	unsigned int		percent;	unsigned int		min_percent=100;	ogs=NULL;	BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)	{		if (!gs->active) continue;		if (!gs->connection) continue;		if (gs->state!=d2gs_state_authed) continue;		if (!gs->maxgame) continue;		if (gs->gamenum>=gs->maxgame) continue;		percent=100*gs->gamenum/gs->maxgame;		if (percent<min_percent) {			min_percent=percent;			ogs=gs;		}	}	END_LIST_TRAVERSE_DATA_CONST()	return ogs;}extern int d2gs_set_state(t_d2gs * gs, t_d2gs_state state){	ASSERT(gs,-1);	gs->state=state;	return 0;}extern t_d2gs_state d2gs_get_state(t_d2gs const * gs){	ASSERT(gs,d2gs_state_none);	return gs->state;}extern int d2gs_add_gamenum(t_d2gs * gs, int number){	ASSERT(gs,-1);	gs->gamenum += number;	return 0;}extern unsigned int d2gs_get_gamenum(t_d2gs const * gs){	ASSERT(gs,0);	return gs->gamenum;}extern int d2gs_set_maxgame(t_d2gs * gs,unsigned int maxgame){	ASSERT(gs,-1);	gs->maxgame=maxgame;	return 0;}extern unsigned int d2gs_get_maxgame(t_d2gs const * gs){	ASSERT(gs,0);	return gs->maxgame;}extern unsigned int d2gs_get_id(t_d2gs const * gs){	ASSERT(gs,0);	return gs->id;}extern unsigned int d2gs_get_ip(t_d2gs const * gs){	ASSERT(gs,0);	return gs->ip;}extern unsigned int d2gs_get_token(t_d2gs const * gs){	return gs->token;}extern unsigned int d2gs_make_token(t_d2gs * gs){	return ((unsigned int)rand())^((++(gs->token))+((unsigned int)time(NULL)));}extern t_connection * d2gs_get_connection(t_d2gs const * gs){	ASSERT(gs,NULL);	return gs->connection;}extern int d2gs_active(t_d2gs * gs, t_connection * c){	ASSERT(gs,-1);	ASSERT(c,-1);	if (gs->active && gs->connection) {		eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is already actived, deactive previous connection first",gs->id);		d2gs_deactive(gs, gs->connection);	}	total_d2gs++;	eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) actived (%d total)",addr_num_to_addr_str(d2cs_conn_get_addr(c),		d2cs_conn_get_port(c)),gs->id,total_d2gs);	gs->state=d2gs_state_authed;	gs->connection=c;	gs->active=1;	gs->gamenum=0;	gs->maxgame=0;	return 0;}extern int d2gs_deactive(t_d2gs * gs, t_connection * c){	t_game * game;	ASSERT(gs,-1);	if (!gs->active || !gs->connection) {		eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is not actived yet", gs->id);		return -1;	}	if (gs->connection != c) {		eventlog(eventlog_level_debug,__FUNCTION__,"game server %d connection mismatch,ignore it", gs->id);		return 0;	}	total_d2gs--;	eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) deactived (%d left)",addr_num_to_addr_str(d2cs_conn_get_addr(gs->connection),d2cs_conn_get_port(gs->connection)),gs->id,total_d2gs);	gs->state=d2gs_state_none;	gs->connection=NULL;	gs->active=0;	gs->maxgame=0;	eventlog(eventlog_level_info,__FUNCTION__,"destroying all games on game server %d",gs->id);	BEGIN_LIST_TRAVERSE_DATA(d2cs_gamelist(),game)	{		if (game_get_d2gs(game)==gs) game_destroy(game,&curr_elem_);	}	END_LIST_TRAVERSE_DATA()	if (gs->gamenum!=0) {		eventlog(eventlog_level_error,__FUNCTION__,"game server %d deactived but still with games left",gs->id);	}	gs->gamenum=0;	return 0;}extern unsigned int d2gs_calc_checksum(t_connection * c){	unsigned int	sessionnum, checksum, port, addr;	unsigned int	i, len, ch;	char const	* realmname;	char const	* password;	ASSERT(c,0);	sessionnum=d2cs_conn_get_sessionnum(c);	checksum=prefs_get_d2gs_checksum();	port=d2cs_conn_get_port(c);	addr=d2cs_conn_get_addr(c);	realmname=prefs_get_realmname();	password=prefs_get_d2gs_password();	len=strlen(realmname);	for (i=0; i<len ; i++) {		ch = (unsigned int)(unsigned char) realmname[i];		checksum ^= ROTL(sessionnum,i, sizeof(unsigned int) * CHAR_BIT);		checksum ^= ROTL(port , ch, sizeof(unsigned int) * CHAR_BIT);	}	len=strlen(password);	for (i=0; i<len ; i++) {		ch = (unsigned int)(unsigned char) password[i];		checksum ^= ROTL(sessionnum,i, sizeof(unsigned int) * CHAR_BIT);		checksum ^= ROTL(port , ch, sizeof(unsigned int) * CHAR_BIT);	}	checksum ^= addr;	return checksum;}extern int d2gs_keepalive(void){	t_packet	* packet;	t_d2gs *	gs;	if (!(packet=packet_create(packet_class_d2gs))) {		eventlog(eventlog_level_error,__FUNCTION__,"error creating packet");		return -1;	}	packet_set_size(packet,sizeof(t_d2cs_d2gs_echoreq));	packet_set_type(packet,D2CS_D2GS_ECHOREQ);        /* FIXME: sequence number not set */        bn_int_set(&packet->u.d2cs_d2gs.h.seqno,0);       		BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)	{		if (gs->active && gs->connection) {			conn_push_outqueue(gs->connection,packet);		}	}	END_LIST_TRAVERSE_DATA()	packet_del_ref(packet);	return 0;}extern int d2gs_restart_all_gs(void){	t_packet        * packet;	t_d2gs          * gs;		if (!(packet=packet_create(packet_class_d2gs))) {    		eventlog(eventlog_level_error, __FUNCTION__, "error creating packet");    		return -1;        }        packet_set_size(packet,sizeof(t_d2cs_d2gs_control));        packet_set_type(packet,D2CS_D2GS_CONTROL);        /* FIXME: sequence number not set */        bn_int_set(&packet->u.d2cs_d2gs.h.seqno,0);        		        bn_int_set(&packet->u.d2cs_d2gs_control.cmd, D2CS_D2GS_CONTROL_CMD_RESTART);        bn_int_set(&packet->u.d2cs_d2gs_control.value, prefs_get_d2gs_restart_delay());	        BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)        {    		if (gs->connection) {            	    conn_push_outqueue(gs->connection,packet);                }        }	        END_LIST_TRAVERSE_DATA()        packet_del_ref(packet);        return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -