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 + -
显示快捷键?