/[LeafOK_CVS]/pvpgn-1.7.4/src/d2dbs/dbspacket.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/d2dbs/dbspacket.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
CVS Tags: pvpgn_1-7-4-0_MIL
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 sysadm 1.1 /*
2     * Copyright (C) 2001 sousou (liupeng.cs@263.net)
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the Free Software
16     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17     */
18     #include "common/setup_before.h"
19     #include "setup.h"
20    
21     #ifdef HAVE_STDDEF_H
22     # include <stddef.h>
23     #else
24     # ifndef NULL
25     # define NULL ((void *)0)
26     # endif
27     #endif
28     #include <stdio.h>
29     #ifdef STDC_HEADERS
30     # include <stdlib.h>
31     #else
32     # ifdef HAVE_MALLOC_H
33     # include <malloc.h>
34     # endif
35     #endif
36     #ifdef HAVE_UNISTD_H
37     # include <unistd.h>
38     #endif
39     #ifdef HAVE_SYS_STAT_H
40     # include <sys/stat.h>
41     #endif
42     #ifdef HAVE_FCNTL_H
43     # include <fcntl.h>
44     #else
45     # ifdef HAVE_SYS_FILE_H
46     # include <sys/file.h>
47     # endif
48     #endif
49     #include "compat/statmacros.h"
50     #include "compat/mkdir.h"
51     #ifdef HAVE_STRING_H
52     # include <string.h>
53     #else
54     # ifdef HAVE_STRINGS_H
55     # include <strings.h>
56     # endif
57     # ifdef HAVE_MEMORY_H
58     # include <memory.h>
59     # endif
60     #endif
61     #include "compat/memcpy.h"
62     #include "compat/memmove.h"
63     #include "compat/strdup.h"
64     #include "compat/strsep.h"
65     #include <errno.h>
66     #include "compat/strerror.h"
67     #ifdef TIME_WITH_SYS_TIME
68     # include <time.h>
69     # include <sys/time.h>
70     #else
71     # ifdef HAVE_SYS_TIME_H
72     # include <sys/time.h>
73     # else
74     # include <time.h>
75     # endif
76     #endif
77     #ifdef HAVE_SYS_TYPES_H
78     # include <sys/types.h>
79     #endif
80     #ifdef HAVE_SYS_SOCKET_H
81     # include <sys/socket.h>
82     #endif
83     #include "compat/socket.h"
84     #ifdef HAVE_SYS_PARAM_H
85     # include <sys/param.h>
86     #endif
87     #ifdef HAVE_NETINET_IN_H
88     # include <netinet/in.h>
89     #endif
90     #include "compat/netinet_in.h"
91     #ifdef HAVE_ARPA_INET_H
92     # include <arpa/inet.h>
93     #endif
94     #include "compat/inet_ntoa.h"
95     #include "compat/psock.h"
96     #include "compat/access.h"
97     #include "compat/rename.h"
98     #include "dbserver.h"
99     #include "dbspacket.h"
100     #include "d2ladder.h"
101     #include "charlock.h"
102     #include "prefs.h"
103     #include "common/bn_type.h"
104     #include "common/d2char_checksum.h"
105     #include "d2cs/xstring.h"
106     #include "d2cs/d2cs_d2gs_character.h"
107     #include "common/list.h"
108     #include "common/eventlog.h"
109     #include "common/addr.h"
110     #include "common/xalloc.h"
111     #include "common/setup_after.h"
112    
113     static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen);
114     static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen);
115     static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize);
116     static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize);
117     static unsigned int dbs_packet_echoreply(t_d2dbs_connection* conn);
118     static unsigned int dbs_packet_getdata(t_d2dbs_connection* conn);
119     static unsigned int dbs_packet_savedata(t_d2dbs_connection* conn);
120     static unsigned int dbs_packet_charlock(t_d2dbs_connection* conn);
121     static unsigned int dbs_packet_updateladder(t_d2dbs_connection* conn);
122     static int dbs_verify_ipaddr(char const * addrlist,t_d2dbs_connection * c);
123    
124     static int dbs_packet_fix_charinfo(t_d2dbs_connection * conn,char * AccountName,char * CharName,char * charsave);
125     static void dbs_packet_set_charinfo_level(char * CharName,char * charinfo);
126    
127     static unsigned int dbs_packet_savedata_charsave(t_d2dbs_connection* conn, char * AccountName,char * CharName,char * data,unsigned int datalen)
128     {
129     char filename[MAX_PATH];
130     char savefile[MAX_PATH];
131     char bakfile[MAX_PATH];
132     unsigned short curlen,readlen,leftlen,writelen;
133     FILE * fd;
134     int checksum_header;
135     int checksum_calc;
136    
137     strtolower(AccountName);
138     strtolower(CharName);
139    
140     //check if checksum is ok
141     checksum_header = bn_int_get(&data[D2CHARSAVE_CHECKSUM_OFFSET]);
142     checksum_calc = d2charsave_checksum(data,datalen,D2CHARSAVE_CHECKSUM_OFFSET);
143    
144     if (checksum_header != checksum_calc)
145     {
146     eventlog(eventlog_level_error,__FUNCTION__,"received (%x) and calculated(%x) checksum do not match - discarding charsave",checksum_header, checksum_calc);
147     return 0;
148     }
149    
150    
151     sprintf(filename,"%s/.%s.tmp",d2dbs_prefs_get_charsave_dir(),CharName);
152     fd = fopen(filename, "wb");
153     if (!fd) {
154     eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);
155     return 0;
156     }
157     curlen=0;
158     leftlen=datalen;
159     while(curlen<datalen) {
160     if (leftlen>2000) writelen=2000;
161     else writelen=leftlen;
162     readlen=fwrite(data+curlen,1,writelen,fd);
163     if (readlen<=0) {
164     fclose(fd);
165     eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno));
166     return 0;
167     }
168     curlen+=readlen;
169     leftlen-=readlen;
170     }
171     fclose(fd);
172    
173     sprintf(bakfile,"%s/%s",prefs_get_charsave_bak_dir(),CharName);
174     sprintf(savefile,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName);
175     if (p_rename(savefile, bakfile)==-1) {
176     eventlog(eventlog_level_warn,__FUNCTION__,"error rename %s to %s", savefile, bakfile);
177     }
178     if (p_rename(filename, savefile)==-1) {
179     eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile);
180     return 0;
181     }
182     eventlog(eventlog_level_info,__FUNCTION__,"saved charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);
183     return datalen;
184     }
185    
186     static unsigned int dbs_packet_savedata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int datalen)
187     {
188     char savefile[MAX_PATH];
189     char bakfile[MAX_PATH];
190     char filepath[MAX_PATH];
191     char filename[MAX_PATH];
192     FILE * fd;
193     unsigned short curlen,readlen,leftlen,writelen;
194     struct stat statbuf;
195    
196     strtolower(AccountName);
197     strtolower(CharName);
198    
199     sprintf(filepath,"%s/%s",prefs_get_charinfo_bak_dir(),AccountName);
200     if (stat(filepath,&statbuf)==-1) {
201     p_mkdir(filepath,S_IRWXU|S_IRWXG|S_IRWXO );
202     eventlog(eventlog_level_info,__FUNCTION__,"created charinfo directory: %s",filepath);
203     }
204    
205     sprintf(filename,"%s/%s/.%s.tmp",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);
206     fd = fopen(filename, "wb");
207     if (!fd) {
208     eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);
209     return 0;
210     }
211    
212     curlen=0;
213     leftlen=datalen;
214     while(curlen<datalen) {
215     if (leftlen>2000) writelen=2000;
216     else writelen=leftlen;
217     readlen=fwrite(data+curlen,1,writelen,fd);
218     if (readlen<=0) {
219     fclose(fd);
220     eventlog(eventlog_level_error,__FUNCTION__,"write() failed error : %s",pstrerror(errno));
221     return 0;
222     }
223     curlen+=readlen;
224     leftlen-=readlen;
225     }
226     fclose(fd);
227    
228     sprintf(bakfile,"%s/%s/%s",prefs_get_charinfo_bak_dir(),AccountName,CharName);
229     sprintf(savefile,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);
230     if (p_rename(savefile, bakfile)==-1) {
231     eventlog(eventlog_level_info,__FUNCTION__,"error rename %s to %s", savefile, bakfile);
232     }
233     if (p_rename(filename, savefile)==-1) {
234     eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", filename, savefile);
235     return 0;
236     }
237     eventlog(eventlog_level_info,__FUNCTION__,"saved charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);
238     return datalen;
239     }
240    
241     static unsigned int dbs_packet_getdata_charsave(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize)
242     {
243     char filename[MAX_PATH];
244     char filename_d2closed[MAX_PATH];
245     FILE * fd;
246     unsigned short curlen,readlen,leftlen,writelen;
247     long filesize;
248    
249     strtolower(AccountName);
250     strtolower(CharName);
251    
252     sprintf(filename,"%s/%s",d2dbs_prefs_get_charsave_dir(),CharName);
253     sprintf(filename_d2closed,"%s/%s.d2s",d2dbs_prefs_get_charsave_dir(),CharName);
254     if ((access(filename, F_OK) < 0) && (access(filename_d2closed, F_OK) == 0))
255     {
256     rename(filename_d2closed, filename);
257     }
258     fd = fopen(filename, "rb");
259     if (!fd) {
260     eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);
261     return 0;
262     }
263     fseek(fd,0,SEEK_END);
264     filesize=ftell(fd);
265     rewind(fd);
266     if (filesize==-1) {
267     fclose(fd);
268     eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed");
269     return 0;
270     }
271     if ((signed)bufsize < filesize) {
272     fclose(fd);
273     eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer");
274     return 0;
275     }
276    
277     curlen=0;
278     leftlen=filesize;
279     while(curlen < filesize) {
280     if (leftlen>2000) writelen=2000;
281     else writelen=leftlen;
282     readlen=fread(data+curlen,1,writelen,fd);
283     if (readlen<=0) {
284     fclose(fd);
285     eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno));
286     return 0;
287     }
288     leftlen-=readlen;
289     curlen+=readlen;
290     }
291     fclose(fd);
292     eventlog(eventlog_level_info,__FUNCTION__,"loaded charsave %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);
293     return filesize;
294     }
295    
296     static unsigned int dbs_packet_getdata_charinfo(t_d2dbs_connection* conn,char * AccountName,char * CharName,char * data,unsigned int bufsize)
297     {
298     char filename[MAX_PATH];
299     FILE * fd;
300     unsigned short curlen,readlen,leftlen,writelen;
301     long filesize;
302    
303     strtolower(AccountName);
304     strtolower(CharName);
305    
306     sprintf(filename,"%s/%s/%s",d2dbs_prefs_get_charinfo_dir(),AccountName,CharName);
307     fd = fopen(filename, "rb");
308     if (!fd) {
309     eventlog(eventlog_level_error,__FUNCTION__,"open() failed : %s",filename);
310     return 0;
311     }
312     fseek(fd,0,SEEK_END);
313     filesize=ftell(fd);
314     rewind(fd);
315     if (filesize==-1) {
316     fclose(fd);
317     eventlog(eventlog_level_error,__FUNCTION__,"lseek() failed");
318     return 0;
319     }
320     if ((signed)bufsize < filesize) {
321     fclose(fd);
322     eventlog(eventlog_level_error,__FUNCTION__,"not enough buffer");
323     return 0;
324     }
325    
326     curlen=0;
327     leftlen=filesize;
328     while(curlen < filesize) {
329     if (leftlen>2000)
330     writelen=2000;
331     else
332     writelen=leftlen;
333     readlen=fread(data+curlen,1,writelen,fd);
334     if (readlen<=0)
335     {
336     fclose(fd);
337     eventlog(eventlog_level_error,__FUNCTION__,"read() failed error : %s",pstrerror(errno));
338     return 0;
339     }
340     leftlen-=readlen;
341     curlen+=readlen;
342     }
343     fclose(fd);
344     eventlog(eventlog_level_info,__FUNCTION__,"loaded charinfo %s(*%s) for gs %s(%d)", CharName, AccountName, conn->serverip, conn->serverid);
345     return filesize;
346     }
347    
348     static unsigned int dbs_packet_savedata(t_d2dbs_connection * conn)
349     {
350     unsigned short writelen;
351     unsigned short datatype;
352     unsigned short datalen;
353     unsigned int result;
354     char AccountName[MAX_NAME_LEN+16];
355     char CharName[MAX_NAME_LEN+16];
356     char RealmName[MAX_NAME_LEN+16];
357     t_d2gs_d2dbs_save_data_request * savecom;
358     t_d2dbs_d2gs_save_data_reply * saveret;
359     char * readpos;
360     unsigned char * writepos;
361    
362     readpos=conn->ReadBuf;
363     savecom=(t_d2gs_d2dbs_save_data_request *)readpos;
364     datatype=bn_short_get(savecom->datatype);
365     datalen=bn_short_get(savecom->datalen);
366    
367     readpos+=sizeof(*savecom);
368     strncpy(AccountName,readpos,MAX_NAME_LEN);
369     AccountName[MAX_NAME_LEN]=0;
370     readpos+=strlen(AccountName)+1;
371     strncpy(CharName,readpos,MAX_NAME_LEN);
372     CharName[MAX_NAME_LEN]=0;
373     readpos+=strlen(CharName)+1;
374     strncpy(RealmName,readpos,MAX_NAME_LEN);
375     RealmName[MAX_NAME_LEN]=0;
376     readpos+=strlen(RealmName)+1;
377    
378     if (readpos+datalen!=conn->ReadBuf+bn_short_get(savecom->h.size)) {
379     eventlog(eventlog_level_error,__FUNCTION__,"request packet size error");
380     return -1;
381     }
382    
383     if (datatype==D2GS_DATA_CHARSAVE) {
384     if (dbs_packet_savedata_charsave(conn,AccountName,CharName,readpos,datalen)>0 &&
385     dbs_packet_fix_charinfo(conn,AccountName,CharName,readpos)) {
386     result=D2DBS_SAVE_DATA_SUCCESS;
387     } else {
388     datalen=0;
389     result=D2DBS_SAVE_DATA_FAILED ;
390     }
391     } else if (datatype==D2GS_DATA_PORTRAIT) {
392     /* if level is > 255 , sets level to 255 */
393     dbs_packet_set_charinfo_level(CharName,readpos);
394     if (dbs_packet_savedata_charinfo(conn,AccountName,CharName,readpos,datalen)>0) {
395     result=D2DBS_SAVE_DATA_SUCCESS;
396     } else {
397     datalen=0;
398     result=D2DBS_SAVE_DATA_FAILED;
399     }
400     } else {
401     eventlog(eventlog_level_error,__FUNCTION__,"unknown data type %d",datatype);
402     return -1;
403     }
404     writelen=sizeof(*saveret)+strlen(CharName)+1;
405     if (writelen > kBufferSize-conn->nCharsInWriteBuffer) return 0;
406     writepos=conn->WriteBuf+conn->nCharsInWriteBuffer;
407     saveret=(t_d2dbs_d2gs_save_data_reply *)writepos;
408     bn_short_set(&saveret->h.type, D2DBS_D2GS_SAVE_DATA_REPLY);
409     bn_short_set(&saveret->h.size,writelen);
410     bn_int_set(&saveret->h.seqno,bn_int_get(savecom->h.seqno));
411     bn_short_set(&saveret->datatype,bn_short_get(savecom->datatype));
412     bn_int_set(&saveret->result,result);
413     writepos+=sizeof(*saveret);
414     strncpy(writepos,CharName,MAX_NAME_LEN);
415     conn->nCharsInWriteBuffer += writelen;
416     return 1;
417     }
418    
419     static unsigned int dbs_packet_echoreply(t_d2dbs_connection * conn)
420     {
421     conn->last_active=time(NULL);
422     return 1;
423     }
424    
425     static unsigned int dbs_packet_getdata(t_d2dbs_connection * conn)
426     {
427     unsigned short writelen;
428     unsigned short datatype;
429     unsigned short datalen;
430     unsigned int result;
431     char AccountName[MAX_NAME_LEN+16];
432     char CharName[MAX_NAME_LEN+16];
433     char RealmName[MAX_NAME_LEN+16];
434     t_d2gs_d2dbs_get_data_request * getcom;
435     t_d2dbs_d2gs_get_data_reply * getret;
436     char * readpos;
437     char * writepos;
438     char databuf[kBufferSize ];
439     t_d2charinfo_file charinfo;
440     unsigned short charinfolen;
441     unsigned int gsid;
442    
443     readpos=conn->ReadBuf;
444     getcom=(t_d2gs_d2dbs_get_data_request *)readpos;
445     datatype=bn_short_get(getcom->datatype);
446    
447     readpos+=sizeof(*getcom);
448     strncpy(AccountName,readpos,MAX_NAME_LEN);
449     AccountName[MAX_NAME_LEN]=0;
450     readpos+=strlen(AccountName)+1;
451     strncpy(CharName,readpos,MAX_NAME_LEN);
452     CharName[MAX_NAME_LEN]=0;
453     readpos+=strlen(CharName)+1;
454     strncpy(RealmName,readpos,MAX_NAME_LEN);
455     RealmName[MAX_NAME_LEN]=0;
456     readpos+=strlen(RealmName)+1;
457    
458     if (readpos != conn->ReadBuf+bn_short_get(getcom->h.size)) {
459     eventlog(eventlog_level_error,__FUNCTION__,"request packet size error");
460     return -1;
461     }
462     writepos=conn->WriteBuf+conn->nCharsInWriteBuffer;
463     getret=(t_d2dbs_d2gs_get_data_reply *)writepos;
464     datalen=0;
465     if (datatype==D2GS_DATA_CHARSAVE) {
466     if (cl_query_charlock_status(CharName,RealmName,&gsid)!=0) {
467     eventlog(eventlog_level_warn,__FUNCTION__,"char %s(*%s)@%s is already locked on gs %u",CharName,AccountName,RealmName,gsid);
468     result=D2DBS_GET_DATA_CHARLOCKED;
469     } else if (cl_lock_char(CharName,RealmName,conn->serverid) != 0) {
470     eventlog(eventlog_level_error,__FUNCTION__,"failed to lock char %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
471     result=D2DBS_GET_DATA_CHARLOCKED;
472     } else {
473     eventlog(eventlog_level_info,__FUNCTION__,"lock char %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
474     datalen=dbs_packet_getdata_charsave(conn,AccountName,CharName,databuf,kBufferSize );
475     if (datalen>0) {
476     result=D2DBS_GET_DATA_SUCCESS;
477     charinfolen=dbs_packet_getdata_charinfo(conn,AccountName,CharName,(char *)&charinfo,sizeof(charinfo));
478     if (charinfolen>0) {
479     result=D2DBS_GET_DATA_SUCCESS;
480     } else {
481     result=D2DBS_GET_DATA_FAILED;
482     if (cl_unlock_char(CharName,RealmName,gsid)!=0) {
483     eventlog(eventlog_level_error,__FUNCTION__,"failed to unlock char %s(*%s)@%s for gs %s(%d)",CharName,\
484     AccountName,RealmName,conn->serverip,conn->serverid);
485     } else {
486     eventlog(eventlog_level_info,__FUNCTION__,"unlock char %s(*%s)@%s for gs %s(%d)",CharName,\
487     AccountName,RealmName,conn->serverip,conn->serverid);
488     }
489     }
490     } else {
491     datalen=0;
492     result=D2DBS_GET_DATA_FAILED;
493     if (cl_unlock_char(CharName,RealmName,gsid)!=0) {
494     eventlog(eventlog_level_error,__FUNCTION__,"faled to unlock char %s(*%s)@%s for gs %s(%d)",CharName,\
495     AccountName,RealmName,conn->serverip,conn->serverid);
496     } else {
497     eventlog(eventlog_level_info,__FUNCTION__,"unlock char %s(*%s)@%s for gs %s(%d)",CharName,\
498     AccountName,RealmName,conn->serverip,conn->serverid);
499     }
500    
501     }
502     }
503     if (result==D2DBS_GET_DATA_SUCCESS) {
504     bn_int_set(&getret->charcreatetime,bn_int_get(charinfo.header.create_time));
505     /* FIXME: this should be rewritten to support string formatted time */
506     if (bn_int_get(charinfo.header.create_time)>=prefs_get_ladderinit_time()) {
507     bn_int_set(&getret->allowladder,1);
508     } else {
509     bn_int_set(&getret->allowladder,0);
510     }
511     } else {
512     bn_int_set(&getret->charcreatetime,0);
513     bn_int_set(&getret->allowladder,0);
514     }
515     } else if (datatype==D2GS_DATA_PORTRAIT) {
516     datalen=dbs_packet_getdata_charinfo(conn,AccountName,CharName,databuf,kBufferSize );
517     if (datalen>0) result=D2DBS_GET_DATA_SUCCESS ;
518     else {
519     datalen=0;
520     result=D2DBS_GET_DATA_FAILED ;
521     }
522     } else {
523     eventlog(eventlog_level_error,__FUNCTION__,"unknown data type %d",datatype);
524     return -1;
525     }
526     writelen=datalen+sizeof(*getret)+strlen(CharName)+1;
527     if (writelen > kBufferSize-conn->nCharsInWriteBuffer) return 0;
528     bn_short_set(&getret->h.type,D2DBS_D2GS_GET_DATA_REPLY);
529     bn_short_set(&getret->h.size,writelen);
530     bn_int_set(&getret->h.seqno,bn_int_get(getcom->h.seqno));
531     bn_short_set(&getret->datatype,bn_short_get(getcom->datatype));
532     bn_int_set(&getret->result,result);
533     bn_short_set(&getret->datalen,datalen);
534     writepos+=sizeof(*getret);
535     strncpy(writepos,CharName,MAX_NAME_LEN);
536     writepos+=strlen(CharName)+1;
537     if (datalen) memcpy(writepos,databuf,datalen);
538     conn->nCharsInWriteBuffer += writelen;
539     return 1;
540     }
541    
542     static unsigned int dbs_packet_updateladder(t_d2dbs_connection * conn)
543     {
544     char CharName[MAX_NAME_LEN+16];
545     char RealmName[MAX_NAME_LEN+16];
546     t_d2gs_d2dbs_update_ladder * updateladder;
547     char * readpos;
548     t_d2ladder_info charladderinfo;
549    
550     readpos=conn->ReadBuf;
551     updateladder=(t_d2gs_d2dbs_update_ladder *)readpos;
552    
553     readpos+=sizeof(*updateladder);
554     strncpy(CharName,readpos,MAX_NAME_LEN);
555     CharName[MAX_NAME_LEN]=0;
556     readpos+=strlen(CharName)+1;
557     strncpy(RealmName,readpos,MAX_NAME_LEN);
558     RealmName[MAX_NAME_LEN]=0;
559     readpos+=strlen(RealmName)+1;
560     if (readpos != conn->ReadBuf+bn_short_get(updateladder->h.size)) {
561     eventlog(eventlog_level_error,__FUNCTION__,"request packet size error");
562     return -1;
563     }
564    
565     strcpy(charladderinfo.charname,CharName);
566     charladderinfo.experience=bn_int_get(updateladder->charexplow);
567     charladderinfo.level=bn_int_get(updateladder->charlevel);
568     charladderinfo.status=bn_short_get(updateladder->charstatus);
569     charladderinfo.class=bn_short_get(updateladder->charclass);
570     eventlog(eventlog_level_info,__FUNCTION__,"update ladder for %s@%s for gs %s(%d)",CharName,RealmName,conn->serverip,conn->serverid);
571     d2ladder_update(&charladderinfo);
572     return 1;
573     }
574    
575     static unsigned int dbs_packet_charlock(t_d2dbs_connection * conn)
576     {
577     char CharName[MAX_NAME_LEN+16];
578     char AccountName[MAX_NAME_LEN+16];
579     char RealmName[MAX_NAME_LEN+16];
580     t_d2gs_d2dbs_char_lock * charlock;
581     char * readpos;
582    
583     readpos=conn->ReadBuf;
584     charlock=(t_d2gs_d2dbs_char_lock*)readpos;
585    
586     readpos+=sizeof(*charlock);
587     strncpy(AccountName,readpos,MAX_NAME_LEN);
588     AccountName[MAX_NAME_LEN]=0;
589     readpos+=strlen(AccountName)+1;
590     strncpy(CharName,readpos,MAX_NAME_LEN);
591     CharName[MAX_NAME_LEN]=0;
592     readpos+=strlen(CharName)+1;
593     strncpy(RealmName,readpos,MAX_NAME_LEN);
594     RealmName[MAX_NAME_LEN]=0;
595     readpos+=strlen(RealmName)+1;
596    
597     if (readpos != conn->ReadBuf+ bn_short_get(charlock->h.size)) {
598     eventlog(eventlog_level_error,__FUNCTION__,"request packet size error");
599     return -1;
600     }
601    
602     if (bn_int_get(charlock->lockstatus)) {
603     if (cl_lock_char(CharName,RealmName,conn->serverid)!=0) {
604     eventlog(eventlog_level_error,__FUNCTION__,"failed to lock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
605     } else {
606     eventlog(eventlog_level_info,__FUNCTION__,"lock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
607     }
608     } else {
609     if (cl_unlock_char(CharName,RealmName,conn->serverid) != 0) {
610     eventlog(eventlog_level_error,__FUNCTION__,"failed to unlock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
611     } else {
612     eventlog(eventlog_level_info,__FUNCTION__,"unlock character %s(*%s)@%s for gs %s(%d)",CharName,AccountName,RealmName,conn->serverip,conn->serverid);
613     }
614     }
615     return 1;
616     }
617    
618     /*
619     return value:
620     1 : process one or more packet
621     0 : not get a whole packet,do nothing
622     -1 : error
623     */
624     extern int dbs_packet_handle(t_d2dbs_connection* conn)
625     {
626     unsigned short readlen,writelen;
627     t_d2dbs_d2gs_header * readhead;
628     unsigned short retval;
629    
630     if (conn->stats==0) {
631     if (conn->nCharsInReadBuffer<(signed)sizeof(t_d2gs_d2dbs_connect)) {
632     return 0;
633     }
634     conn->stats=1;
635     conn->type=conn->ReadBuf[0];
636    
637     if (conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) {
638     if (dbs_verify_ipaddr(d2dbs_prefs_get_d2gs_list(),conn)<0) {
639     eventlog(eventlog_level_error,__FUNCTION__,"d2gs connection from unknown ip address");
640     return -1;
641     }
642     readlen=1;
643     writelen=0;
644     eventlog(eventlog_level_info,__FUNCTION__,"set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd);
645     eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"set connection type for gs %s(%d) on socket %d", conn->serverip, conn->serverid, conn->sd);
646     } else {
647     eventlog(eventlog_level_error,__FUNCTION__,"unknown connection type");
648     return -1;
649     }
650     conn->nCharsInReadBuffer -= readlen;
651     memmove(conn->ReadBuf,conn->ReadBuf+readlen,conn->nCharsInReadBuffer);
652     } else if (conn->stats==1) {
653     if (conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) {
654     while (conn->nCharsInReadBuffer >= (signed)sizeof(*readhead)) {
655     readhead=(t_d2dbs_d2gs_header *)conn->ReadBuf;
656     readlen=bn_short_get(readhead->size);
657     if (conn->nCharsInReadBuffer < readlen) break;
658     switch(bn_short_get(readhead->type)) {
659     case D2GS_D2DBS_SAVE_DATA_REQUEST:
660     retval=dbs_packet_savedata(conn);
661     break;
662     case D2GS_D2DBS_GET_DATA_REQUEST:
663     retval=dbs_packet_getdata(conn);
664     break;
665     case D2GS_D2DBS_UPDATE_LADDER:
666     retval=dbs_packet_updateladder(conn);
667     break;
668     case D2GS_D2DBS_CHAR_LOCK:
669     retval=dbs_packet_charlock(conn);
670     break;
671     case D2GS_D2DBS_ECHOREPLY:
672     retval=dbs_packet_echoreply(conn);
673     break;
674     default:
675     eventlog(eventlog_level_error,__FUNCTION__,"unknown request type %d",\
676     bn_short_get(readhead->type));
677     retval=-1;
678     }
679     if (retval!=1) return retval;
680     conn->nCharsInReadBuffer -= readlen;
681     memmove(conn->ReadBuf,conn->ReadBuf+readlen,conn->nCharsInReadBuffer);
682     }
683     } else {
684     eventlog(eventlog_level_error,__FUNCTION__,"unknown connection type %d",conn->type);
685     return -1;
686     }
687     } else {
688     eventlog(eventlog_level_error,__FUNCTION__,"unknown connection stats");
689     return -1;
690     }
691     return 1;
692     }
693    
694     /* FIXME: we should save client ipaddr into c->ipaddr after accept */
695     static int dbs_verify_ipaddr(char const * addrlist,t_d2dbs_connection * c)
696     {
697     struct in_addr in;
698     char * adlist;
699     char const * ipaddr;
700     char * s, * temp;
701     t_elem * elem;
702     t_d2dbs_connection * tempc;
703     unsigned int valid;
704     unsigned int resolveipaddr;
705    
706     in.s_addr=htonl(c->ipaddr);
707     ipaddr=inet_ntoa(in);
708     adlist = xstrdup(addrlist);
709     temp=adlist;
710     valid=0;
711     while ((s=strsep(&temp, ","))) {
712     host_lookup(s, &resolveipaddr);
713     if(resolveipaddr == 0) continue;
714    
715     if (!strcmp(ipaddr, (const char *)addr_num_to_ip_str(resolveipaddr))) {
716     valid=1;
717     break;
718     }
719     }
720     xfree(adlist);
721     if (valid) {
722     eventlog(eventlog_level_info,__FUNCTION__,"ip address %s is valid",ipaddr);
723     LIST_TRAVERSE(dbs_server_connection_list,elem)
724     {
725     if (!(tempc=elem_get_data(elem))) continue;
726     if (tempc !=c && tempc->ipaddr==c->ipaddr) {
727     eventlog(eventlog_level_info,__FUNCTION__,"destroying previous connection %d",tempc->serverid);
728     dbs_server_shutdown_connection(tempc);
729     list_remove_elem(dbs_server_connection_list,&elem);
730     }
731     }
732     c->verified = 1;
733     return 0;
734     } else {
735     eventlog(eventlog_level_info,__FUNCTION__,"ip address %s is invalid",ipaddr);
736     }
737     return -1;
738     }
739    
740     int dbs_check_timeout(void)
741     {
742     t_elem *elem;
743     t_d2dbs_connection *tempc;
744     time_t now;
745     int timeout;
746    
747     now=time(NULL);
748     timeout=d2dbs_prefs_get_idletime();
749     LIST_TRAVERSE(dbs_server_connection_list,elem)
750     {
751     if (!(tempc=elem_get_data(elem))) continue;
752     if (now-tempc->last_active>timeout) {
753     eventlog(eventlog_level_debug,__FUNCTION__,"connection %d timed out",tempc->serverid);
754     dbs_server_shutdown_connection(tempc);
755     list_remove_elem(dbs_server_connection_list,&elem);
756     continue;
757     }
758     }
759     return 0;
760     }
761    
762     int dbs_keepalive(void)
763     {
764     t_elem *elem;
765     t_d2dbs_connection *tempc;
766     t_d2dbs_d2gs_echorequest *echoreq;
767     unsigned short writelen;
768     unsigned char *writepos;
769     time_t now;
770    
771     writelen = sizeof(t_d2dbs_d2gs_echorequest);
772     now=time(NULL);
773     LIST_TRAVERSE(dbs_server_connection_list,elem)
774     {
775     if (!(tempc=elem_get_data(elem))) continue;
776     if (writelen > kBufferSize - tempc->nCharsInWriteBuffer) continue;
777     writepos = tempc->WriteBuf + tempc->nCharsInWriteBuffer;
778     echoreq = (t_d2dbs_d2gs_echorequest*)writepos;
779     bn_short_set(&echoreq->h.type, D2DBS_D2GS_ECHOREQUEST);
780     bn_short_set(&echoreq->h.size, writelen);
781     /* FIXME: sequence number not set */
782     bn_int_set(&echoreq->h.seqno, 0);
783     tempc->nCharsInWriteBuffer += writelen;
784     }
785     return 0;
786     }
787    
788     /*************************************************************************************/
789     #define CHARINFO_SIZE 0xC0
790     #define CHARINFO_PORTRAIT_LEVEL_OFFSET 0x89
791     #define CHARINFO_PORTRAIT_STATUS_OFFSET 0x8A
792     #define CHARINFO_SUMMARY_LEVEL_OFFSET 0xB8
793     #define CHARINFO_SUMMARY_STATUS_OFFSET 0xB4
794     #define CHARINFO_PORTRAIT_GFX_OFFSET 0x72
795     #define CHARINFO_PORTRAIT_COLOR_OFFSET 0x7E
796    
797     #define CHARSAVE_LEVEL_OFFSET 0x2B
798     #define CHARSAVE_STATUS_OFFSET 0x24
799     #define CHARSAVE_GFX_OFFSET 0x88
800     #define CHARSAVE_COLOR_OFFSET 0x98
801    
802     #define charstatus_to_portstatus(status) ((((status & 0xFF00) << 1) | (status & 0x00FF)) | 0x8080)
803     #define portstatus_to_charstatus(status) (((status & 0x7F00) >> 1) | (status & 0x007F))
804    
805     static void dbs_packet_set_charinfo_level(char * CharName,char * charinfo)
806     {
807     if (prefs_get_difficulty_hack()) { /* difficulty hack enabled */
808     unsigned int level = bn_int_get(&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET]);
809     unsigned int plevel = bn_byte_get(&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET]);
810    
811     /* levels 257 thru 355 */
812     if (level != plevel) {
813     eventlog(eventlog_level_info,__FUNCTION__,"level mis-match for %s ( %u != %u ) setting to 255",CharName,level,plevel);
814     bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET],255);
815     bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET],255);
816     }
817     }
818     }
819    
820     static int dbs_packet_fix_charinfo(t_d2dbs_connection * conn,char * AccountName,char * CharName,char * charsave)
821     {
822     if (prefs_get_difficulty_hack()) {
823     unsigned char charinfo[CHARINFO_SIZE];
824     unsigned int level = bn_byte_get(&charsave[CHARSAVE_LEVEL_OFFSET]);
825     unsigned short status = bn_short_get(&charsave[CHARSAVE_STATUS_OFFSET]);
826     unsigned short pstatus = charstatus_to_portstatus(status);
827     int i;
828    
829     /*
830     * charinfo is only updated from level 1 to 99 (d2gs issue)
831     * from 100 to 256 d2gs does not send it
832     * when value rolls over (level 256 = 0)
833     * and charactar reaches level 257 (rolled over to level 1)
834     * d2gs starts sending it agian until level 356 (rolled over to 100)
835     * is reached agian. etc. etc. etc.
836     */
837     if (level == 0) /* level 256, 512, 768, etc */
838     level = 255;
839    
840     if (level < 100)
841     return 1; /* d2gs will send charinfo - level will be set to 255 at that time if needed */
842    
843     eventlog(eventlog_level_info,__FUNCTION__,"level %u > 99 for %s",level,CharName);
844    
845     if(!(dbs_packet_getdata_charinfo(conn,AccountName,CharName,charinfo,CHARINFO_SIZE))) {
846     eventlog(eventlog_level_error,__FUNCTION__,"unable to get charinfo for %s",CharName);
847     return 0;
848     }
849    
850     /* if level in charinfo file is already set to 255,
851     * then is must have been set when d2gs sent the charinfo
852     * and got a level mis-match (levels 257 - 355)
853     * or level is actually 255. In eather case we set to 255
854     * this should work for any level mod
855     */
856     if (bn_byte_get(&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET]) == 255)
857     level = 255;
858    
859     eventlog(eventlog_level_info,__FUNCTION__,"updating charinfo for %s -> level = %u , status = 0x%04X , pstatus = 0x%04X",CharName,level,status,pstatus);
860     bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_LEVEL_OFFSET],level);
861     bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_LEVEL_OFFSET],level);
862     bn_short_set((bn_short *)&charinfo[CHARINFO_PORTRAIT_STATUS_OFFSET],pstatus);
863     bn_int_set((bn_int *)&charinfo[CHARINFO_SUMMARY_STATUS_OFFSET],status);
864    
865     for (i=0;i<11;i++) {
866     bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_GFX_OFFSET+i],bn_byte_get(&charsave[CHARSAVE_GFX_OFFSET+i]));
867     bn_byte_set((bn_byte *)&charinfo[CHARINFO_PORTRAIT_COLOR_OFFSET+i],bn_byte_get(&charsave[CHARSAVE_GFX_OFFSET+i]));
868     }
869    
870     if (!(dbs_packet_savedata_charinfo(conn,AccountName,CharName,charinfo,CHARINFO_SIZE))) {
871     eventlog(eventlog_level_error,__FUNCTION__,"unable to save charinfo for %s",CharName);
872     return 0;
873     }
874    
875     return 1; /* charinfo updated */
876     }
877    
878     return 1; /* difficulty hack not enabled */
879     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1