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

📄 connection.c

📁 打魔兽战网的都知道他是什么
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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"#include <ctype.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"#include "compat/strdup.h"#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_TYPES_H# include <sys/types.h>#endif#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#include "compat/psock.h"#ifdef HAVE_NETINET_IN_H# include <netinet/in.h>#endif#include "compat/netinet_in.h"#ifdef HAVE_LIMITS_H# include <limits.h>#endif#include "compat/char_bit.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_ASSERT_H# include <assert.h>#endif#include "compat/psock.h"#include "compat/strcasecmp.h"#include "connection.h"#include "game.h"#include "gamequeue.h"#include "prefs.h"#include "d2gs.h"#include "net.h"#include "s2s.h"#include "handle_d2gs.h"#include "handle_d2cs.h"#include "handle_init.h"#include "handle_bnetd.h"#include "d2charfile.h"#include "common/fdwatch.h"#include "common/addr.h"#include "common/introtate.h"#include "common/network.h"#include "common/packet.h"#include "common/hashtable.h"#include "common/queue.h"#include "common/eventlog.h"#include "common/xalloc.h"#include "common/setup_after.h"static t_hashtable 	* connlist_head=NULL;static t_hashtable	* conn_charname_list_head=NULL;static t_list		* connlist_dead=NULL;static unsigned int	total_connection=0;static int conn_handle_connecting(t_connection * c);static t_packet * conn_create_packet(t_connection * c);static int conn_handle_packet(t_connection * c, t_packet * packet);static int conn_handle_read(t_connection * c);static int conn_handle_write(t_connection * c);static unsigned int conn_charname_hash(char const * charname);static unsigned int conn_sessionnum_hash(unsigned int sessionnum);static unsigned int conn_sessionnum_hash(unsigned int sessionnum){	return sessionnum;}static unsigned int conn_charname_hash(char const * charname){	unsigned int hash;	unsigned int i, len, pos;	unsigned int ch;	ASSERT(charname,0);	len=strlen(charname);	for (hash=0, i=0, pos=0; i<len; i++) {		if (isascii((int)charname[i])) {			ch=(unsigned int)(unsigned char)tolower((int)charname[i]);		} else {			ch=(unsigned int)(unsigned char)charname[i];		}		hash ^= ROTL(ch,pos,sizeof(unsigned int) * CHAR_BIT);		pos += CHAR_BIT-1;	}	return hash;}extern t_hashtable * d2cs_connlist(void){	return connlist_head;}extern int d2cs_connlist_create(void){	if (!(connlist_head=hashtable_create(200))) return -1;	if (!(conn_charname_list_head=hashtable_create(200))) return -1;	return 0;}extern int d2cs_connlist_destroy(void){	t_connection 	* c;	t_elem		* curr;	        if (connlist_dead) {                d2cs_connlist_reap();                if (list_destroy(connlist_dead))                        eventlog(eventlog_level_error,__FUNCTION__,"error destroy conndead list");                connlist_dead = NULL;        }	BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)	{		d2cs_conn_destroy(c,&curr);	}	END_HASHTABLE_TRAVERSE_DATA()	if (hashtable_destroy(connlist_head)<0) {		eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection list");		return -1;	}	connlist_head=NULL;	if (hashtable_destroy(conn_charname_list_head)<0) {		eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection charname list");		return -1;	}	conn_charname_list_head=NULL;	return 0;}extern int d2cs_connlist_reap(void){	t_connection 	* c;		if (!connlist_dead) return 0;	BEGIN_LIST_TRAVERSE_DATA(connlist_dead, c)	{		d2cs_conn_destroy(c,&curr_elem_);	}	END_LIST_TRAVERSE_DATA()	return 0;}extern int conn_check_multilogin(t_connection const * c,char const * charname){	t_connection * conn;	ASSERT(charname,-1);	if (!prefs_check_multilogin()) return 0;	if (gamelist_find_character(charname)) {		return -1;	}	conn=d2cs_connlist_find_connection_by_charname(charname);	if (conn && conn!=c) {		return -1;	}	return 0;}extern t_connection * d2cs_connlist_find_connection_by_sessionnum(unsigned int sessionnum){	t_connection 	* c;	t_entry		* curr;	unsigned int	hash;	hash=conn_sessionnum_hash(sessionnum);	HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)	{		if (!(c=entry_get_data(curr))) {			eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");		} else if (c->sessionnum==sessionnum) {			hashtable_entry_release(curr);			return c;		}	}	return NULL;}extern t_connection * d2cs_connlist_find_connection_by_charname(char const * charname){	t_entry		* curr;	t_connection 	* c;	unsigned int	hash;	hash=conn_charname_hash(charname);	HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)	{		if (!(c=entry_get_data(curr))) {			eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");		} else {			if (!c->charname) continue;			if (!strcmp_charname(c->charname,charname)) {				hashtable_entry_release(curr);				return c;			}		}	}	return NULL;}static t_packet * conn_create_packet(t_connection * c){	t_packet	* packet;	switch (c->class) {		CASE(conn_class_init, packet=packet_create(packet_class_init));		CASE(conn_class_d2cs, packet=packet_create(packet_class_d2cs));		CASE(conn_class_d2gs, packet=packet_create(packet_class_d2gs));		CASE(conn_class_bnetd, packet=packet_create(packet_class_d2cs_bnetd));		default:			eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);			return NULL;	}	if (!packet) {		eventlog(eventlog_level_error,__FUNCTION__,"error create packet");		return NULL;	}	d2cs_conn_set_in_queue(c,packet);	return packet;}static int conn_handle_connecting(t_connection * c){	int	retval;	if (net_check_connected(c->sock)<0) {		eventlog(eventlog_level_warn,__FUNCTION__,"can not connect to %s",addr_num_to_addr_str(c->addr, c->port));		return -1;	}	eventlog(eventlog_level_info,__FUNCTION__,"connected to %s",addr_num_to_addr_str(c->addr, c->port));	c->state=conn_state_init;        /* this is a kind of hack to not update fd but updating breaks kqueue         * and the clean fix would require a cache a userland copy of the kernel	 * kqueue fds, considering that it also doesnt brake anything else should do	 * for the moment 	fdwatch_update_fd(c->sock, fdwatch_type_read); */	switch (c->class) {		case conn_class_bnetd:			retval=handle_bnetd_init(c);			break;		default:			eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);			return -1;	}	return retval;}static int conn_handle_packet(t_connection * c, t_packet * packet){	int	retval;	switch (c->class) {		CASE (conn_class_init, retval=d2cs_handle_init_packet(c,packet));		CASE (conn_class_d2cs, retval=d2cs_handle_d2cs_packet(c,packet));		CASE (conn_class_d2gs, retval=handle_d2gs_packet(c,packet));		CASE (conn_class_bnetd, retval=handle_bnetd_packet(c,packet));		default:			eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d (close connection)",c->class);			retval=-1;			break;	}	return retval;}static int conn_handle_read(t_connection * c){	t_packet	* packet;	int		retval;	packet = d2cs_conn_get_in_queue(c);	if (!packet) {		packet = conn_create_packet(c);		if (!packet) return -1;		c->insize=0;	}	switch (net_recv_packet(c->sock,packet,&c->insize)) {		case -1:			retval=-1;			break;		case 0:			retval=0;			break;		case 1:			c->insize=0;			d2cs_conn_set_in_queue(c,NULL);			retval=conn_handle_packet(c,packet);			packet_del_ref(packet);			break;		default:			retval=0;			break;	}	return retval;}static int conn_handle_write(t_connection * c){	t_packet	* packet;	int		retval;	if (c->state==conn_state_connecting) {		return conn_handle_connecting(c);	}	if (!(packet=conn_peek_outqueue(c))) return 0;	switch (net_send_packet(c->sock, packet, &c->outsize)) {		case -1:			retval=-1;			break;		case 0:			retval=0;			break;		case 1:			c->outsize=0;			packet=conn_pull_outqueue(c);			packet_del_ref(packet);			retval=0;			break;		default:			retval = -1;	}	return retval;}extern int conn_handle_socket(t_connection * c){	time_t	now;	ASSERT(c,-1);	now=time(NULL);	if (c->socket_flag & SOCKET_FLAG_READ) {		if (conn_handle_read(c)<0) return -1;		c->last_active=now;	}	if (c->socket_flag & SOCKET_FLAG_WRITE) {		if (conn_handle_write(c)<0) return -1;		c->last_active=now;	}	c->socket_flag=0;	return 0;}extern int connlist_check_timeout(void){	t_connection	* c;	time_t		now;	now=time(NULL);	BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)	{		switch (c->class) {			case conn_class_d2cs:				if (prefs_get_idletime() && (now - c->last_active > prefs_get_idletime())) {					eventlog(eventlog_level_info,__FUNCTION__,"client %d idled too long time, destroy it",c->sessionnum);					d2cs_conn_set_state(c,conn_state_destroy);				}				break;			case conn_class_d2gs:				if (prefs_get_s2s_idletime() && now - c->last_active > prefs_get_s2s_idletime()) {					eventlog(eventlog_level_info,__FUNCTION__,"server %d timed out",c->sessionnum);					d2cs_conn_set_state(c,conn_state_destroy);				}				break;			case conn_class_bnetd:				break;			default:				break;		}	}	END_HASHTABLE_TRAVERSE_DATA()

⌨️ 快捷键说明

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