dbspacket.c

来自「打魔兽战网的都知道他是什么」· C语言 代码 · 共 924 行 · 第 1/2 页

C
924
字号
/* * Copyright (C) 2001		sousou	(liupeng.cs@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#include <stdio.h>#ifdef STDC_HEADERS# include <stdlib.h>#else# ifdef HAVE_MALLOC_H#  include <malloc.h># endif#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#endif#ifdef HAVE_FCNTL_H# include <fcntl.h>#else# ifdef HAVE_SYS_FILE_H#  include <sys/file.h># endif#endif#include "compat/statmacros.h"#include "compat/mkdir.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#include "compat/memcpy.h"#include "compat/memmove.h"#include "compat/strdup.h"#include "compat/strsep.h"#include <errno.h>#include "compat/strerror.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_SYS_TYPES_H# include <sys/types.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>#endif#include "compat/inet_ntoa.h"#include "compat/psock.h"#include "compat/access.h"#include "compat/rename.h"#include "dbserver.h"#include "dbspacket.h"#include "d2ladder.h"#include "charlock.h"#include "prefs.h"#include "common/bn_type.h"#include "common/d2char_checksum.h"#include "common/xstring.h"#include "d2cs/d2cs_d2gs_character.h"#include "common/list.h"#include "common/eventlog.h"#include "common/addr.h"#include "common/xalloc.h"#include "common/setup_after.h"static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen);static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen);static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize);static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize);static unsigned int dbs_packet_echoreply(t_d2dbs_connection* conn);static unsigned int dbs_packet_getdata(t_d2dbs_connection* conn);static unsigned int dbs_packet_savedata(t_d2dbs_connection* conn);static unsigned int dbs_packet_charlock(t_d2dbs_connection* conn);static unsigned int dbs_packet_updateladder(t_d2dbs_connection* conn);static int dbs_verify_ipaddr(char const * addrlist,t_d2dbs_connection * c);static int dbs_packet_fix_charinfo(t_d2dbs_connection * conn,char * AccountName,char * CharName,char * charsave);static void dbs_packet_set_charinfo_level(char * CharName,char * charinfo);static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn, char * AccountName,char * CharName,char * data,unsigned int datalen){	char filename[MAX_PATH];	char savefile[MAX_PATH];	char bakfile[MAX_PATH];	unsigned short curlen,readlen,leftlen,writelen;	FILE * fd;	int checksum_header;	int checksum_calc;		strtolower(AccountName);	strtolower(CharName);	//check if checksum is ok	checksum_header = bn_int_get(&data[D2CHARSAVE_CHECKSUM_OFFSET]);	checksum_calc   = d2charsave_checksum(data,datalen,D2CHARSAVE_CHECKSUM_OFFSET);	if (checksum_header != checksum_calc)	{	  eventlog(eventlog_level_error,__FUNCTION__,"received (%x) and calculated(%x) checksum do not match - discarding charsave",checksum_header, checksum_calc);	  return 0;	}	sprintf(filename,"%s/.%s.tmp",d2dbs_prefs_get_charsave_dir(),CharName);	fd = fopen(filename, "wb");	if (!fd) {		eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);		return 0;	}	curlen=0;	leftlen=datalen;	while(curlen<datalen) {		if (leftlen>2000) writelen=2000;		else writelen=leftlen;		readlen=fwrite(data+curlen,1,writelen,fd);		if (readlen<=0) {			fclose(fd);			eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno));			return 0;		}		curlen+=readlen;		leftlen-=readlen;	}	fclose(fd);	sprintf(bakfile,"%s/%s",prefs_get_charsave_bak_dir(),CharName);	sprintf(savefile,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName);	if (p_rename(savefile, bakfile)==-1) {		eventlog(eventlog_level_warn,__FUNCTION__,"error rename %s to %s", savefile, bakfile);	}	if (p_rename(filename, savefile)==-1) {		eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile);		return 0;	}	eventlog(eventlog_level_info,__FUNCTION__,"saved charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);	return datalen;}static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen){	char savefile[MAX_PATH];	char bakfile[MAX_PATH];	char filepath[MAX_PATH];	char filename[MAX_PATH];	FILE * fd;	unsigned short curlen,readlen,leftlen,writelen;	struct stat statbuf;		strtolower(AccountName);	strtolower(CharName);	sprintf(filepath,"%s/%s",prefs_get_charinfo_bak_dir(),AccountName);	if (stat(filepath,&statbuf)==-1) {		p_mkdir(filepath,S_IRWXU|S_IRWXG|S_IRWXO );		eventlog(eventlog_level_info,__FUNCTION__,"created charinfo directory: %s",filepath);	}	sprintf(filename,"%s/%s/.%s.tmp",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);	fd = fopen(filename, "wb");	if (!fd) {		eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);		return 0;	}	curlen=0;	leftlen=datalen;	while(curlen<datalen) {		if (leftlen>2000) writelen=2000;		else writelen=leftlen;		readlen=fwrite(data+curlen,1,writelen,fd);		if (readlen<=0) {			fclose(fd);			eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno));			return 0;		}		curlen+=readlen;		leftlen-=readlen;	}	fclose(fd);	sprintf(bakfile,"%s/%s/%s",prefs_get_charinfo_bak_dir(),AccountName,CharName);	sprintf(savefile,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);	if (p_rename(savefile, bakfile)==-1) {		eventlog(eventlog_level_info,__FUNCTION__,"error rename %s to %s", savefile, bakfile);	}	if (p_rename(filename, savefile)==-1) {		eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile);		return 0;	}	eventlog(eventlog_level_info,__FUNCTION__,"saved charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);	return datalen;}static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize){	char filename[MAX_PATH];	char filename_d2closed[MAX_PATH];	FILE * fd;	unsigned short curlen,readlen,leftlen,writelen;	long filesize;		strtolower(AccountName);	strtolower(CharName);		sprintf(filename,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName);	sprintf(filename_d2closed,"%s/%s.d2s",d2dbs_prefs_get_charsave_dir(),CharName);	if ((access(filename, F_OK) < 0) && (access(filename_d2closed, F_OK) == 0))	{		rename(filename_d2closed, filename);	}	fd = fopen(filename, "rb");	if (!fd) {		eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);		return 0;	}	fseek(fd,0,SEEK_END);	filesize=ftell(fd);	rewind(fd);	if (filesize==-1) {		fclose(fd);		eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed");		return 0;	}	if ((signed)bufsize < filesize) {		fclose(fd);		eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer");		return 0;	}	curlen=0;	leftlen=filesize;	while(curlen < filesize) {		if (leftlen>2000) writelen=2000;		else writelen=leftlen;		readlen=fread(data+curlen,1,writelen,fd);		if (readlen<=0) {			fclose(fd);			eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno));			return 0;		}		leftlen-=readlen;		curlen+=readlen;	}	fclose(fd);	eventlog(eventlog_level_info,__FUNCTION__,"loaded charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);	return filesize;}static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize){	char filename[MAX_PATH];	FILE * fd;	unsigned short curlen,readlen,leftlen,writelen;	long filesize;		strtolower(AccountName);	strtolower(CharName);	sprintf(filename,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);	fd = fopen(filename, "rb");	if (!fd) {		eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);		return 0;	}	fseek(fd,0,SEEK_END);	filesize=ftell(fd);	rewind(fd);	if (filesize==-1) {		fclose(fd);		eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed");		return 0;	}	if ((signed)bufsize < filesize) {		fclose(fd);		eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer");		return 0;	}	curlen=0;	leftlen=filesize;	while(curlen < filesize) {		if (leftlen>2000)			writelen=2000;		else			writelen=leftlen;		readlen=fread(data+curlen,1,writelen,fd);	    if (readlen<=0)		{			fclose(fd);			eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno));			return 0;		}		leftlen-=readlen;		curlen+=readlen;	}	fclose(fd);	eventlog(eventlog_level_info,__FUNCTION__,"loaded charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);	return filesize;}static unsigned int dbs_packet_savedata(t_d2dbs_connection * conn){	unsigned short writelen;	unsigned short      datatype;	unsigned short      datalen; 	unsigned int        result; 	char AccountName[MAX_ACCTNAME_LEN];	char CharName[MAX_CHARNAME_LEN];	char RealmName[MAX_REALMNAME_LEN];	t_d2gs_d2dbs_save_data_request	* savecom; 	t_d2dbs_d2gs_save_data_reply	* saveret; 	char * readpos;	unsigned char * writepos;		readpos=conn->ReadBuf;	savecom=(t_d2gs_d2dbs_save_data_request	*)readpos;	datatype=bn_short_get(savecom->datatype);	datalen=bn_short_get(savecom->datalen);	readpos+=sizeof(*savecom);	strncpy(AccountName,readpos,MAX_ACCTNAME_LEN);	if (AccountName[MAX_ACCTNAME_LEN-1]!=0)	{	    eventlog(eventlog_level_error,__FUNCTION__,"max acccount name length exceeded");	    return -1;	}	readpos+=strlen(AccountName)+1;	strncpy(CharName,readpos,MAX_CHARNAME_LEN);	if (CharName[MAX_CHARNAME_LEN-1]!=0)	{	    eventlog(eventlog_level_error,__FUNCTION__,"max char name length exceeded");	    return -1;	}	readpos+=strlen(CharName)+1;	strncpy(RealmName,readpos,MAX_REALMNAME_LEN);	if (RealmName[MAX_REALMNAME_LEN-1]!=0)	{	    eventlog(eventlog_level_error,__FUNCTION__,"max realm name length exceeded");	    return -1;	}	readpos+=strlen(RealmName)+1;	if (readpos+datalen!=conn->ReadBuf+bn_short_get(savecom->h.size)) {		eventlog(eventlog_level_error,__FUNCTION__,"request packet size error");		return -1;	}	if (datatype==D2GS_DATA_CHARSAVE) {		if (dbs_packet_savedata_charsave(conn,AccountName,CharName,readpos,datalen)>0 &&		    dbs_packet_fix_charinfo(conn,AccountName,CharName,readpos)) {			result=D2DBS_SAVE_DATA_SUCCESS;		} else {			datalen=0;			result=D2DBS_SAVE_DATA_FAILED    ;		}	} else if (datatype==D2GS_DATA_PORTRAIT) {		/* if level is > 255 , sets level to 255 */		dbs_packet_set_charinfo_level(CharName,readpos);		if (dbs_packet_savedata_charinfo(conn,AccountName,CharName,readpos,datalen)>0) {			result=D2DBS_SAVE_DATA_SUCCESS;		} else {			datalen=0;			result=D2DBS_SAVE_DATA_FAILED;		}	} else {		eventlog(eventlog_level_error,__FUNCTION__,"unknown data type %d",datatype);		return -1;	}	writelen=sizeof(*saveret)+strlen(CharName)+1;	if (writelen > kBufferSize-conn->nCharsInWriteBuffer) return 0;	writepos=conn->WriteBuf+conn->nCharsInWriteBuffer;	saveret=(t_d2dbs_d2gs_save_data_reply *)writepos;	bn_short_set(&saveret->h.type, D2DBS_D2GS_SAVE_DATA_REPLY);	bn_short_set(&saveret->h.size,writelen);	bn_int_set(&saveret->h.seqno,bn_int_get(savecom->h.seqno));	bn_short_set(&saveret->datatype,bn_short_get(savecom->datatype));	bn_int_set(&saveret->result,result);	writepos+=sizeof(*saveret);	strncpy(writepos,CharName,MAX_CHARNAME_LEN);	conn->nCharsInWriteBuffer += writelen;	return 1;}static unsigned int dbs_packet_echoreply(t_d2dbs_connection * conn){	conn->last_active=time(NULL);	return 1;}static unsigned int dbs_packet_getdata(t_d2dbs_connection * conn){	unsigned short	writelen;	unsigned short	datatype;	unsigned short	datalen; 	unsigned int	result; 	char		AccountName[MAX_ACCTNAME_LEN];	char		CharName[MAX_CHARNAME_LEN];	char		RealmName[MAX_REALMNAME_LEN];	t_d2gs_d2dbs_get_data_request	* getcom; 	t_d2dbs_d2gs_get_data_reply	* getret; 	char		* readpos;	char		* writepos;	char		databuf[kBufferSize ];	t_d2charinfo_file charinfo;	unsigned short	charinfolen;	unsigned int	gsid;	readpos=conn->ReadBuf;	getcom=(t_d2gs_d2dbs_get_data_request *)readpos;	datatype=bn_short_get(getcom->datatype);		readpos+=sizeof(*getcom);	strncpy(AccountName,readpos,MAX_ACCTNAME_LEN);	if (AccountName[MAX_ACCTNAME_LEN-1]!=0)	{

⌨️ 快捷键说明

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