/[LeafOK_CVS]/pvpgn-1.7.4/src/d2cs/handle_d2cs.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/d2cs/handle_d2cs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sat Jun 10 16:21:03 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Changes since 1.1: +45 -1 lines
Content type: text/x-csrc
Antibot

1 sysadm 1.1 /*
2     * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3     * Copyright (C) 2004 Olaf Freyer (aaron@cs.tu-berlin.de)
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * as published by the Free Software Foundation; either version 2
8     * of the License, or (at your option) any later version.
9     *
10     * This program is distributed in the hope that it will be useful,
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     * GNU General Public License for more details.
14     *
15     * You should have received a copy of the GNU General Public License
16     * along with this program; if not, write to the Free Software
17     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18     */
19     #include "common/setup_before.h"
20     #include "setup.h"
21    
22     #include <stdio.h>
23     #ifdef HAVE_STRING_H
24     # include <string.h>
25     #else
26     # ifdef HAVE_STRINGS_H
27     # include <strings.h>
28     # endif
29     # ifdef HAVE_MEMORY_H
30     # include <memory.h>
31     # endif
32     #endif
33     #ifdef STDC_HEADERS
34     # include <stdlib.h>
35     #else
36     # ifdef HAVE_MALLOC_H
37     # include <malloc.h>
38     # endif
39     #endif
40     #include "compat/memcpy.h"
41     #ifdef TIME_WITH_SYS_TIME
42     # include <time.h>
43     # include <sys/time.h>
44     #else
45     # ifdef HAVE_SYS_TIME_H
46     # include <sys/time.h>
47     # else
48     # include <time.h>
49     # endif
50     #endif
51     #ifdef HAVE_UNISTD_H
52     # include <unistd.h>
53     #endif
54     #ifdef HAVE_SYS_STAT_H
55     # include <sys/stat.h>
56     #endif
57    
58     #ifdef HAVE_SYS_SOCKET_H
59     # include <sys/socket.h>
60     #endif
61     #ifdef HAVE_NETINET_IN_H
62     # include <netinet/in.h>
63     #endif
64     #include "compat/socket.h"
65     #include "compat/netinet_in.h"
66     #ifdef HAVE_ARPA_INET_H
67     # include <arpa/inet.h>
68     #endif
69     #include "compat/inet_ntoa.h"
70    
71     #include "compat/pdir.h"
72     #include "compat/mkdir.h"
73     #include "d2charfile.h"
74     #include "connection.h"
75     #include "game.h"
76     #include "bnetd.h"
77     #include "d2cs_protocol.h"
78     #include "d2cs_bnetd_protocol.h"
79     #include "handle_d2cs.h"
80     #include "d2ladder.h"
81     #include "gamequeue.h"
82     #include "serverqueue.h"
83     #include "prefs.h"
84     #include "common/bn_type.h"
85     #include "common/queue.h"
86     #include "common/packet.h"
87     #include "common/eventlog.h"
88     #include "d2charlist.h"
89     #include "common/elist.h"
90     #include "common/xalloc.h"
91     #include "common/setup_after.h"
92    
93 sysadm 1.2 /* sowater */
94     #include "d2cs_random.h"
95 sysadm 1.1
96     static int d2cs_send_client_ladder(t_connection * c, unsigned char type, unsigned short from);
97     static unsigned int d2cs_try_joingame(t_connection const * c, t_game const * game, char const * gamepass);
98    
99     DECLARE_PACKET_HANDLER(on_client_loginreq)
100     DECLARE_PACKET_HANDLER(on_client_createcharreq)
101     DECLARE_PACKET_HANDLER(on_client_creategamereq)
102     DECLARE_PACKET_HANDLER(on_client_joingamereq)
103     DECLARE_PACKET_HANDLER(on_client_gamelistreq)
104     DECLARE_PACKET_HANDLER(on_client_gameinforeq)
105     DECLARE_PACKET_HANDLER(on_client_charloginreq)
106     DECLARE_PACKET_HANDLER(on_client_deletecharreq)
107     DECLARE_PACKET_HANDLER(on_client_ladderreq)
108     DECLARE_PACKET_HANDLER(on_client_motdreq)
109     DECLARE_PACKET_HANDLER(on_client_cancelcreategame)
110     DECLARE_PACKET_HANDLER(on_client_charladderreq)
111     DECLARE_PACKET_HANDLER(on_client_charlistreq)
112     DECLARE_PACKET_HANDLER(on_client_charlistreq_110)
113     DECLARE_PACKET_HANDLER(on_client_convertcharreq)
114    
115    
116     static t_packet_handle_table d2cs_packet_handle_table[]={
117     /* 0x00 */ { 0, conn_state_none, NULL },
118     /* 0x01 */ { sizeof(t_client_d2cs_loginreq), conn_state_connected, on_client_loginreq },
119     /* 0x02 */ { sizeof(t_client_d2cs_createcharreq), conn_state_authed|conn_state_char_authed, on_client_createcharreq },
120     /* 0x03 */ { sizeof(t_client_d2cs_creategamereq), conn_state_char_authed, on_client_creategamereq },
121     /* 0x04 */ { sizeof(t_client_d2cs_joingamereq), conn_state_char_authed, on_client_joingamereq },
122     /* 0x05 */ { sizeof(t_client_d2cs_gamelistreq), conn_state_char_authed, on_client_gamelistreq },
123     /* 0x06 */ { sizeof(t_client_d2cs_gameinforeq), conn_state_char_authed, on_client_gameinforeq },
124     /* 0x07 */ { sizeof(t_client_d2cs_charloginreq), conn_state_authed|conn_state_char_authed, on_client_charloginreq },
125     /* 0x08 */ { 0, conn_state_none, NULL },
126     /* 0x09 */ { 0, conn_state_none, NULL },
127     /* 0x0a */ { sizeof(t_client_d2cs_deletecharreq), conn_state_authed|conn_state_char_authed, on_client_deletecharreq },
128     /* 0x0b */ { 0, conn_state_none, NULL },
129     /* 0x0c */ { 0, conn_state_none, NULL },
130     /* 0x0d */ { 0, conn_state_none, NULL },
131     /* 0x0e */ { 0, conn_state_none, NULL },
132     /* 0x0f */ { 0, conn_state_none, NULL },
133     /* 0x10 */ { 0, conn_state_none, NULL },
134     /* 0x11 */ { sizeof(t_client_d2cs_ladderreq), conn_state_char_authed, on_client_ladderreq },
135     /* 0x12 */ { sizeof(t_client_d2cs_motdreq), conn_state_char_authed, on_client_motdreq },
136     /* 0x13 */ { sizeof(t_client_d2cs_cancelcreategame),conn_state_char_authed, on_client_cancelcreategame},
137     /* 0x14 */ { 0, conn_state_none, NULL },
138     /* 0x15 */ { 0, conn_state_none, NULL },
139     /* 0x16 */ { sizeof(t_client_d2cs_charladderreq), conn_state_char_authed, on_client_charladderreq },
140     /* 0x17 */ { sizeof(t_client_d2cs_charlistreq), conn_state_authed|conn_state_char_authed, on_client_charlistreq },
141     /* 0x18 */ { sizeof(t_client_d2cs_convertcharreq), conn_state_authed|conn_state_char_authed, on_client_convertcharreq },
142     /* 0x19 */ { sizeof(t_client_d2cs_charlistreq_110), conn_state_authed|conn_state_char_authed, on_client_charlistreq_110 }
143     };
144    
145    
146     extern int d2cs_handle_d2cs_packet(t_connection * c, t_packet * packet)
147     {
148     return conn_process_packet(c,packet,d2cs_packet_handle_table,NELEMS(d2cs_packet_handle_table));
149     }
150    
151     static int on_client_loginreq(t_connection * c, t_packet * packet)
152     {
153     t_packet * bnpacket;
154     char const * account;
155     t_sq * sq;
156     unsigned int sessionnum;
157    
158     if (!(account=packet_get_str_const(packet,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN))) {
159     eventlog(eventlog_level_error,__FUNCTION__,"got bad account name");
160     return -1;
161     }
162     if (d2char_check_acctname(account)<0) {
163     eventlog(eventlog_level_error,__FUNCTION__,"got bad account name");
164     return -1;
165     }
166     if (!bnetd_conn()) {
167     eventlog(eventlog_level_warn,__FUNCTION__,"d2cs is offline with bnetd, login request will be rejected");
168     return -1;
169     }
170     sessionnum=bn_int_get(packet->u.client_d2cs_loginreq.sessionnum);
171     conn_set_bnetd_sessionnum(c,sessionnum);
172     eventlog(eventlog_level_info,__FUNCTION__,"got client (*%s) login request sessionnum=0x%X",account,sessionnum);
173     if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) {
174     if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) {
175     packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_accountloginreq));
176     packet_set_type(bnpacket,D2CS_BNETD_ACCOUNTLOGINREQ);
177     bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.h.seqno,sq_get_seqno(sq));
178     bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.seqno,
179     bn_int_get(packet->u.client_d2cs_loginreq.seqno));
180     bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionkey,
181     bn_int_get(packet->u.client_d2cs_loginreq.sessionkey));
182     bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionnum,sessionnum);
183     memcpy(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash,
184     packet->u.client_d2cs_loginreq.secret_hash,
185     sizeof(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash));
186     packet_append_string(bnpacket,account);
187     conn_push_outqueue(bnetd_conn(),bnpacket);
188     }
189     packet_del_ref(bnpacket);
190     }
191     return 0;
192     }
193    
194     static int on_client_createcharreq(t_connection * c, t_packet * packet)
195     {
196     t_packet * rpacket, * bnpacket;
197     char const * charname;
198     char const * account;
199     char * path;
200     t_pdir * dir;
201     t_sq * sq;
202     unsigned int reply;
203     unsigned short status, class;
204     t_d2charinfo_file data;
205 sysadm 1.2 char checknum;
206 sysadm 1.1 if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN))) {
207     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
208     return -1;
209     }
210     if (!(account=d2cs_conn_get_account(c))) {
211     eventlog(eventlog_level_error,__FUNCTION__,"missing account for character %s",charname);
212     return -1;
213     }
214     class=bn_short_get(packet->u.client_d2cs_createcharreq.class);
215     status=bn_short_get(packet->u.client_d2cs_createcharreq.status);
216    
217     path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1);
218     d2char_get_infodir_name(path,account);
219     if (!(dir=p_opendir(path))) {
220     eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account);
221     p_mkdir(path,S_IRWXU);
222     }
223     else
224     p_closedir(dir);
225     xfree(path);
226    
227 sysadm 1.2 /* generate checknum, save it in t_connection, and send it to bnetd, by sowater */
228     do {
229     checknum=d2cs_random_char();
230     }while(d2cs_conn_get_checknum(c)==checknum);
231     d2cs_conn_set_checknum(c,checknum);
232     eventlog(eventlog_level_info,__FUNCTION__,"set checknum %c to connection",checknum);
233    
234 sysadm 1.1 if (d2char_create(account,charname,class,status)<0) {
235     eventlog(eventlog_level_warn,__FUNCTION__,"error create character %s for account %s",charname,account);
236     reply=D2CS_CLIENT_CREATECHARREPLY_ALREADY_EXIST;
237     } else if (d2charinfo_load(account,charname,&data)<0) {
238     eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for character %s(*%s)",charname,account);
239     reply=D2CS_CLIENT_CREATECHARREPLY_FAILED;
240     } else {
241     eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) created",charname,account);
242     reply=D2CS_CLIENT_CREATECHARREPLY_SUCCEED;
243     conn_set_charinfo(c,&data.summary);
244     if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) {
245     if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) {
246     packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_charloginreq));
247     packet_set_type(bnpacket,D2CS_BNETD_CHARLOGINREQ);
248     bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.h.seqno,sq_get_seqno(sq));
249     bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.sessionnum,
250     conn_get_bnetd_sessionnum(c));
251     packet_append_string(bnpacket,charname);
252     packet_append_string(bnpacket,(char const *)&data.portrait);
253 sysadm 1.2
254     /* sowater */
255     packet_append_data(bnpacket,&checknum,sizeof(checknum));
256    
257 sysadm 1.1 conn_push_outqueue(bnetd_conn(),bnpacket);
258     }
259     packet_del_ref(bnpacket);
260     }
261     return 0;
262     }
263     if ((rpacket=packet_create(packet_class_d2cs))) {
264     packet_set_size(rpacket,sizeof(t_d2cs_client_createcharreply));
265     packet_set_type(rpacket,D2CS_CLIENT_CREATECHARREPLY);
266     bn_int_set(&rpacket->u.d2cs_client_createcharreply.reply,reply);
267     conn_push_outqueue(c,rpacket);
268     packet_del_ref(rpacket);
269     }
270     return 0;
271     }
272    
273     static int on_client_creategamereq(t_connection * c, t_packet * packet)
274     {
275     char const * gamename;
276     char const * gamepass;
277     char const * gamedesc;
278     t_game * game;
279     t_d2gs * gs;
280     t_gq * gq;
281     unsigned int tempflag,gameflag;
282     unsigned int leveldiff, maxchar, difficulty, expansion, hardcore, ladder;
283     unsigned int seqno, reply;
284     unsigned int pos;
285     t_elem * elem;
286 sysadm 1.2 char checksum_con;
287    
288 sysadm 1.1
289 sysadm 1.2
290 sysadm 1.1 pos=sizeof(t_client_d2cs_creategamereq);
291     if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) {
292     eventlog(eventlog_level_error,__FUNCTION__,"got bad game name");
293     return -1;
294     }
295     pos+=strlen(gamename)+1;
296     if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) {
297     eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass");
298     return -1;
299     }
300     pos+=strlen(gamepass)+1;
301     if (!(gamedesc=packet_get_str_const(packet,pos,MAX_GAMEDESC_LEN))) {
302     eventlog(eventlog_level_error,__FUNCTION__,"got bad game desc");
303     return -1;
304     }
305 sysadm 1.2
306     /* get checknum from client, by sowater */
307     checksum_con=d2cs_conn_get_checknum(c);
308    
309    
310 sysadm 1.1 tempflag=bn_int_get(packet->u.client_d2cs_creategamereq.gameflag);
311     leveldiff=bn_byte_get(packet->u.client_d2cs_creategamereq.leveldiff);
312     maxchar=bn_byte_get(packet->u.client_d2cs_creategamereq.maxchar);
313     difficulty=gameflag_get_difficulty(tempflag);
314     if (difficulty > conn_get_charinfo_difficulty(c)) {
315     eventlog(eventlog_level_error,__FUNCTION__,"game difficulty exceed character limit %d %d",difficulty,
316     conn_get_charinfo_difficulty(c));
317     return 0;
318     }
319     expansion=conn_get_charinfo_expansion(c);
320     hardcore=conn_get_charinfo_hardcore(c);
321     ladder=conn_get_charinfo_ladder(c);
322     gameflag=gameflag_create(ladder,expansion,hardcore,difficulty);
323    
324     gs = NULL;
325     game = NULL;
326     gq=conn_get_gamequeue(c);
327     if (d2cs_gamelist_find_game(gamename)) {
328     eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in gamelist",gamename);
329     reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST;
330 sysadm 1.2
331     /* right checknum? sowater */
332     } else if((*gamedesc!=checksum_con) && (prefs_antibot_when_password()==0) && prefs_enable_antibot()) {
333     eventlog(eventlog_level_info,__FUNCTION__,"checksum %c from packet not match checksum %c from connection",*gamedesc,checksum_con);
334     reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
335     /* when antibot_when_password is true, by sowater, 20051001 */
336     } else if((*gamedesc!=checksum_con) && (strlen(gamepass)!=0) && prefs_antibot_when_password()
337     && prefs_enable_antibot()) {
338     eventlog(eventlog_level_info,__FUNCTION__,"checksum %c from packet not match checksum %c from connection",*gamedesc,checksum_con);
339     reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
340 sysadm 1.1 } else if (!gq && gqlist_find_game(gamename)) {
341     eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in game queue",gamename);
342     reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST;
343     } else if (!(gs=d2gslist_choose_server(c))) {
344     if (gq) {
345     eventlog(eventlog_level_error,__FUNCTION__,"client %d is already in game queue",d2cs_conn_get_sessionnum(c));
346     conn_set_gamequeue(c,NULL);
347     gq_destroy(gq,&elem);
348     return 0;
349     } else if ((gq=gq_create(d2cs_conn_get_sessionnum(c), packet, gamename))) {
350     conn_set_gamequeue(c,gq);
351     d2cs_send_client_creategamewait(c,gqlist_get_length());
352     return 0;
353     }
354     reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
355     } else if (hardcore && conn_get_charinfo_dead(c)) {
356     reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
357     } else if (!(game=d2cs_game_create(gamename,gamepass,gamedesc,gameflag))) {
358     reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST;
359     } else {
360     reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED;
361     game_set_d2gs(game,gs);
362     d2gs_add_gamenum(gs, 1);
363     game_set_gameflag_ladder(game,ladder);
364     game_set_gameflag_expansion(game,expansion);
365     game_set_created(game,0);
366     game_set_leveldiff(game,leveldiff);
367     game_set_charlevel(game,conn_get_charinfo_level(c));
368     game_set_maxchar(game,maxchar);
369     game_set_gameflag_difficulty(game,difficulty);
370     game_set_gameflag_hardcore(game,hardcore);
371     }
372    
373     seqno=bn_short_get(packet->u.client_d2cs_creategamereq.seqno);
374     if (reply!=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED) {
375     t_packet * rpacket;
376    
377     if ((rpacket=packet_create(packet_class_d2cs))) {
378     packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply));
379     packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY);
380     bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno,seqno);
381     bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,0);
382     bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,0);
383     bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply);
384     conn_push_outqueue(c,rpacket);
385     packet_del_ref(rpacket);
386     }
387     } else {
388     t_packet * gspacket;
389     t_sq * sq;
390     struct in_addr addr;
391    
392     if ((gspacket=packet_create(packet_class_d2gs))) {
393     if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) {
394     packet_set_size(gspacket,sizeof(t_d2cs_d2gs_creategamereq));
395     packet_set_type(gspacket,D2CS_D2GS_CREATEGAMEREQ);
396     bn_int_set(&gspacket->u.d2cs_d2gs_creategamereq.h.seqno,sq_get_seqno(sq));
397     bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.difficulty,difficulty);
398     bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.hardcore,hardcore);
399     bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.expansion,expansion);
400     bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.ladder,ladder);
401     packet_append_string(gspacket,gamename);
402     packet_append_string(gspacket,gamepass);
403     packet_append_string(gspacket,gamedesc);
404     packet_append_string(gspacket,d2cs_conn_get_account(c));
405     packet_append_string(gspacket,d2cs_conn_get_charname(c));
406     addr.s_addr = htonl(d2cs_conn_get_addr(c));
407     packet_append_string(gspacket,inet_ntoa(addr));
408     conn_push_outqueue(d2gs_get_connection(gs),gspacket);
409     }
410     packet_del_ref(gspacket);
411     eventlog(eventlog_level_info,__FUNCTION__,"request create game %s on gs %d",gamename,d2gs_get_id(gs));
412     }
413     }
414     return 0;
415     }
416    
417     static int on_client_joingamereq(t_connection * c, t_packet * packet)
418     {
419     char const * gamename;
420     char const * gamepass;
421     char const * charname;
422     char const * account;
423     t_game * game;
424     t_d2gs * gs;
425     int reply;
426     unsigned int pos;
427     unsigned int seqno;
428    
429     gs = NULL;
430     pos=sizeof(t_client_d2cs_joingamereq);
431     if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) {
432     eventlog(eventlog_level_error,__FUNCTION__,"got bad game name");
433     return -1;
434     }
435     pos+=strlen(gamename)+1;
436     if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) {
437     eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass");
438     return -1;
439     }
440     if (!(charname=d2cs_conn_get_charname(c))) {
441     eventlog(eventlog_level_error,__FUNCTION__,"missing character name for connection");
442     return -1;
443     }
444     if (!(account=d2cs_conn_get_account(c))) {
445     eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection");
446     return -1;
447     }
448     if (conn_check_multilogin(c,charname)<0) {
449     eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
450     return -1;
451     }
452     if (!(game=d2cs_gamelist_find_game(gamename))) {
453     eventlog(eventlog_level_info,__FUNCTION__,"game %s not found",gamename);
454     reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
455     } else if (!(gs=game_get_d2gs(game))) {
456     eventlog(eventlog_level_error,__FUNCTION__,"missing game server for game %s",gamename);
457     reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
458     } else {
459     reply=d2cs_try_joingame(c,game,gamepass);
460     }
461    
462     seqno=bn_short_get(packet->u.client_d2cs_joingamereq.seqno);
463     if (reply!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) {
464     t_packet * rpacket;
465    
466     if ((rpacket=packet_create(packet_class_d2cs))) {
467     packet_set_size(rpacket,sizeof(t_d2cs_client_joingamereply));
468     packet_set_type(rpacket,D2CS_CLIENT_JOINGAMEREPLY);
469     bn_short_set(&rpacket->u.d2cs_client_joingamereply.seqno,seqno);
470     bn_short_set(&rpacket->u.d2cs_client_joingamereply.u1,0);
471     bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,0);
472     bn_int_set(&rpacket->u.d2cs_client_joingamereply.addr,0);
473     bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,0);
474     bn_int_set(&rpacket->u.d2cs_client_joingamereply.reply,reply);
475     conn_push_outqueue(c,rpacket);
476     packet_del_ref(rpacket);
477     }
478     } else {
479     t_packet * gspacket;
480     t_sq * sq;
481     struct in_addr addr;
482    
483     if ((gspacket=packet_create(packet_class_d2gs))) {
484     if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) {
485     packet_set_size(gspacket,sizeof(t_d2cs_d2gs_joingamereq));
486     packet_set_type(gspacket,D2CS_D2GS_JOINGAMEREQ);
487     bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.h.seqno,sq_get_seqno(sq));
488     bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.gameid,
489     game_get_d2gs_gameid(game));
490     sq_set_gametoken(sq,d2gs_make_token(gs));
491     bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.token,sq_get_gametoken(sq));
492     packet_append_string(gspacket,charname);
493     packet_append_string(gspacket,account);
494     addr.s_addr = htonl(d2cs_conn_get_addr(c));
495     packet_append_string(gspacket,inet_ntoa(addr));
496     conn_push_outqueue(d2gs_get_connection(gs),gspacket);
497     }
498     packet_del_ref(gspacket);
499     eventlog(eventlog_level_info,__FUNCTION__,"request join game %s for character %s on gs %d",gamename,
500     charname,d2gs_get_id(gs));
501     }
502     }
503     return 0;
504     }
505    
506     static int on_client_gamelistreq(t_connection * c, t_packet * packet)
507     {
508     t_packet * rpacket;
509     t_game * game;
510     unsigned int count;
511     unsigned int seqno;
512     time_t now;
513     unsigned int maxlifetime;
514     t_elem const * start_elem;
515     t_elem const * elem;
516    
517     seqno=bn_short_get(packet->u.client_d2cs_gamelistreq.seqno);
518     /* if (seqno%2) return 0; */
519     count=0;
520     now=time(NULL);
521     maxlifetime=prefs_get_game_maxlifetime();
522    
523     elem=start_elem=gamelist_get_curr_elem();
524     if (!elem) elem=list_get_first_const(d2cs_gamelist());
525     else elem=elem_get_next_const(d2cs_gamelist(),elem);
526    
527     for (; elem != start_elem; elem=elem_get_next_const(d2cs_gamelist(),elem)) {
528     if (!elem) {
529     elem=list_get_first_const(d2cs_gamelist());
530     if (elem == start_elem) break;
531     }
532     if (!(game=elem_get_data(elem))) {
533     eventlog(eventlog_level_error,__FUNCTION__,"got NULL game");
534     break;
535     }
536     if (maxlifetime && (now-game->create_time>maxlifetime)) continue;
537     if (!game_get_currchar(game)) continue;
538     if (!prefs_allow_gamelist_showall()) {
539     if (conn_get_charinfo_difficulty(c)!=game_get_gameflag_difficulty(game)) continue;
540     }
541     if (d2cs_try_joingame(c,game,"")!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) continue;
542     if ((rpacket=packet_create(packet_class_d2cs))) {
543     packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply));
544     packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY);
545     bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno);
546     bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,d2cs_game_get_id(game));
547     bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,game_get_currchar(game));
548     bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,game_get_gameflag(game));
549     packet_append_string(rpacket,d2cs_game_get_name(game));
550     packet_append_string(rpacket,game_get_desc(game));
551     conn_push_outqueue(c,rpacket);
552     packet_del_ref(rpacket);
553     count++;
554     if (prefs_get_maxgamelist() && count>=prefs_get_maxgamelist()) break;
555     }
556     }
557     gamelist_set_curr_elem(elem);
558     if (count) {
559     if ((rpacket=packet_create(packet_class_d2cs))) {
560     packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply));
561     packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY);
562     bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno);
563     bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,0);
564     bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,0);
565     bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,0);
566     packet_append_string(rpacket,"");
567     packet_append_string(rpacket,"");
568     packet_append_string(rpacket,"");
569     conn_push_outqueue(c,rpacket);
570     packet_del_ref(rpacket);
571     }
572     }
573     return 0;
574     }
575    
576     static int on_client_gameinforeq(t_connection * c, t_packet * packet)
577     {
578     t_game_charinfo * info;
579     t_packet * rpacket;
580     char const * gamename;
581     t_game * game;
582     unsigned int seqno, n;
583    
584     if (!(gamename=packet_get_str_const(packet,sizeof(t_client_d2cs_gameinforeq),MAX_GAMENAME_LEN))) {
585     eventlog(eventlog_level_error,__FUNCTION__,"got bad game name");
586     return -1;
587     }
588     if (!(game=d2cs_gamelist_find_game(gamename))) {
589     eventlog(eventlog_level_error,__FUNCTION__,"game %s not found",gamename);
590     return 0;
591     }
592     seqno=bn_short_get(packet->u.client_d2cs_gameinforeq.seqno);
593     if ((rpacket=packet_create(packet_class_d2cs))) {
594     packet_set_size(rpacket,sizeof(t_d2cs_client_gameinforeply));
595     packet_set_type(rpacket,D2CS_CLIENT_GAMEINFOREPLY);
596     bn_short_set(&rpacket->u.d2cs_client_gameinforeply.seqno,seqno);
597     bn_int_set(&rpacket->u.d2cs_client_gameinforeply.gameflag,game_get_gameflag(game));
598     bn_int_set(&rpacket->u.d2cs_client_gameinforeply.etime,time(NULL)-d2cs_game_get_create_time(game));
599     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.charlevel,game_get_charlevel(game));
600     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.leveldiff,game_get_leveldiff(game));
601     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.maxchar,game_get_maxchar(game));
602     packet_append_string(rpacket, game_get_desc(game) ? game_get_desc(game) : NULL);
603    
604     n=0;
605     BEGIN_LIST_TRAVERSE_DATA_CONST(game_get_charlist(game),info)
606     {
607     if (!info->charname) {
608     eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname in game %s char list",gamename);
609     continue;
610     }
611     packet_append_string(rpacket,info->charname);
612     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.class[n],info->class);
613     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n],info->level);
614     n++;
615     }
616     END_LIST_TRAVERSE_DATA_CONST()
617    
618     bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.currchar,n);
619     if (n!=game_get_currchar(game)) {
620     eventlog(eventlog_level_error,__FUNCTION__,"game %s character list corrupted",gamename);
621     }
622     conn_push_outqueue(c,rpacket);
623     packet_del_ref(rpacket);
624     }
625     return 0;
626     }
627    
628     static int on_client_charloginreq(t_connection * c, t_packet * packet)
629     {
630     t_packet * bnpacket;
631     char const * charname;
632     char const * account;
633     t_sq * sq;
634     t_d2charinfo_file data;
635     unsigned int expire_time;
636 sysadm 1.2 char checknum;
637 sysadm 1.1
638     if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_charloginreq),MAX_CHARNAME_LEN))) {
639     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
640     return -1;
641     }
642     if (!(account=d2cs_conn_get_account(c))) {
643     eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection");
644     return -1;
645     }
646     if (d2charinfo_load(account,charname,&data)<0) {
647     eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for character %s(*%s)",charname,account);
648     return -1;
649     } else if (!bnetd_conn()) {
650     eventlog(eventlog_level_error,__FUNCTION__,"no bnetd connection available,character login rejected");
651     return -1;
652     }
653     expire_time = prefs_get_char_expire_time();
654     if (expire_time && (time(NULL) > bn_int_get(data.header.last_time) + expire_time)) {
655     t_packet * rpacket;
656    
657     if ((rpacket=packet_create(packet_class_d2cs))) {
658     packet_set_size(rpacket,sizeof(t_d2cs_client_charloginreply));
659     packet_set_type(rpacket,D2CS_CLIENT_CHARLOGINREPLY);
660     bn_int_set(&rpacket->u.d2cs_client_charloginreply.reply, D2CS_CLIENT_CHARLOGINREPLY_EXPIRED);
661     conn_push_outqueue(c,rpacket);
662     packet_del_ref(rpacket);
663     }
664     eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) login rejected due to char expired",charname,account);
665     return 0;
666     }
667    
668     conn_set_charinfo(c,&data.summary);
669     eventlog(eventlog_level_info,__FUNCTION__,"got character %s(*%s) login request",charname,account);
670 sysadm 1.2
671     /* generate checknum, save it in t_connection, and send it to bnetd, by sowater */
672     do {
673     checknum=d2cs_random_char();
674     }while(d2cs_conn_get_checknum(c)==checknum);
675     d2cs_conn_set_checknum(c,checknum);
676     eventlog(eventlog_level_info,__FUNCTION__,"set checknum %c to connection",checknum);
677    
678 sysadm 1.1 if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) {
679     if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) {
680     packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_charloginreq));
681     packet_set_type(bnpacket,D2CS_BNETD_CHARLOGINREQ);
682     bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.h.seqno,sq_get_seqno(sq));
683     bn_int_set(&bnpacket->u.d2cs_bnetd_charloginreq.sessionnum,
684     conn_get_bnetd_sessionnum(c));
685     packet_append_string(bnpacket,charname);
686     packet_append_string(bnpacket,(char const *)&data.portrait);
687 sysadm 1.2
688     /*sowater */
689     packet_append_data(bnpacket,&checknum,sizeof(checknum));
690    
691 sysadm 1.1 conn_push_outqueue(bnetd_conn(),bnpacket);
692     }
693     packet_del_ref(bnpacket);
694     }
695     return 0;
696     }
697    
698     static int on_client_deletecharreq(t_connection * c, t_packet * packet)
699     {
700     t_packet * rpacket;
701     char const * charname;
702     char const * account;
703     unsigned int reply;
704    
705     if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_deletecharreq),MAX_CHARNAME_LEN))) {
706     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
707     return -1;
708     }
709     if (conn_check_multilogin(c,charname)<0) {
710     eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
711     return -1;
712     }
713     d2cs_conn_set_charname(c,NULL);
714     account=d2cs_conn_get_account(c);
715     if (d2char_delete(account,charname)<0) {
716     eventlog(eventlog_level_error,__FUNCTION__,"failed to delete character %s(*%s)",charname,account);
717     reply = D2CS_CLIENT_DELETECHARREPLY_FAILED;
718     } else {
719     reply = D2CS_CLIENT_DELETECHARREPLY_SUCCEED;
720     }
721     if ((rpacket=packet_create(packet_class_d2cs))) {
722     packet_set_size(rpacket,sizeof(t_d2cs_client_deletecharreply));
723     packet_set_type(rpacket,D2CS_CLIENT_DELETECHARREPLY);
724     bn_short_set(&rpacket->u.d2cs_client_deletecharreply.u1,0);
725     bn_int_set(&rpacket->u.d2cs_client_deletecharreply.reply,reply);
726     conn_push_outqueue(c,rpacket);
727     packet_del_ref(rpacket);
728     }
729     return 0;
730     }
731    
732     static int on_client_ladderreq(t_connection * c, t_packet * packet)
733     {
734     unsigned char type;
735     unsigned short start_pos;
736    
737     type=bn_byte_get(packet->u.client_d2cs_ladderreq.type);
738     start_pos=bn_short_get(packet->u.client_d2cs_ladderreq.start_pos);
739     d2cs_send_client_ladder(c,type,start_pos);
740     return 0;
741     }
742    
743     static int d2cs_send_client_ladder(t_connection * c, unsigned char type, unsigned short from)
744     {
745     t_packet * rpacket;
746     t_d2cs_client_ladderinfo const * ladderinfo;
747     unsigned int curr_len, cont_len, total_len;
748     t_d2cs_client_ladderheader ladderheader;
749     t_d2cs_client_ladderinfoheader infoheader;
750     unsigned int start_pos, count, count_per_packet, npacket;
751     unsigned int i, n, curr_pos;
752    
753     start_pos=from;
754     count=prefs_get_ladderlist_count();
755     if (d2ladder_get_ladder(&start_pos,&count,type,&ladderinfo)<0) {
756     eventlog(eventlog_level_error,__FUNCTION__,"error get ladder for type %d start_pos %d",type,from);
757     return 0;
758     }
759    
760     count_per_packet=14;
761     npacket=count/count_per_packet;
762     if (count % count_per_packet) npacket++;
763    
764     curr_len=0;
765     cont_len=0;
766     total_len = count * sizeof(*ladderinfo) + sizeof(ladderheader) + sizeof(infoheader) * npacket;
767     total_len -= 4;
768     bn_short_set(&ladderheader.start_pos,start_pos);
769     bn_short_set(&ladderheader.u1,0);
770     bn_int_set(&ladderheader.count1,count);
771    
772     for (i=0; i< npacket; i++) {
773     curr_len=0;
774     if ((rpacket=packet_create(packet_class_d2cs))) {
775     packet_set_size(rpacket,sizeof(t_d2cs_client_ladderreply));
776     packet_set_type(rpacket,D2CS_CLIENT_LADDERREPLY);
777     bn_byte_set(&rpacket->u.d2cs_client_ladderreply.type, type);
778     bn_short_set(&rpacket->u.d2cs_client_ladderreply.total_len, total_len);
779     bn_short_set(&rpacket->u.d2cs_client_ladderreply.cont_len,cont_len);
780     if (i==0) {
781     bn_int_set(&infoheader.count2,count);
782     packet_append_data(rpacket,&ladderheader,sizeof(ladderheader));
783     curr_len += sizeof(ladderheader);
784     } else {
785     bn_int_set(&infoheader.count2,0);
786     }
787     packet_append_data(rpacket,&infoheader,sizeof(infoheader));
788     curr_len += sizeof(infoheader);
789     for (n=0; n< count_per_packet; n++) {
790     curr_pos = n + i * count_per_packet;
791     if (curr_pos >= count) break;
792     packet_append_data(rpacket, ladderinfo+curr_pos, sizeof(*ladderinfo));
793     curr_len += sizeof(*ladderinfo);
794     }
795     if (i==0) {
796     packet_set_size(rpacket, packet_get_size(rpacket)-4);
797     curr_len -= 4;
798     }
799     bn_short_set(&rpacket->u.d2cs_client_ladderreply.curr_len,curr_len);
800     conn_push_outqueue(c,rpacket);
801     packet_del_ref(rpacket);
802     }
803     cont_len += curr_len;
804     }
805     return 0;
806     }
807    
808     static int on_client_motdreq(t_connection * c, t_packet * packet)
809     {
810     t_packet * rpacket;
811    
812     if (!packet)
813     return -1;
814    
815     if ((rpacket=packet_create(packet_class_d2cs))) {
816     packet_set_size(rpacket,sizeof(t_d2cs_client_motdreply));
817     packet_set_type(rpacket,D2CS_CLIENT_MOTDREPLY);
818     bn_byte_set(&rpacket->u.d2cs_client_motdreply.u1,0);
819     packet_append_string(rpacket,prefs_get_motd());
820     conn_push_outqueue(c,rpacket);
821     packet_del_ref(rpacket);
822     }
823     return 0;
824     }
825    
826     static int on_client_cancelcreategame(t_connection * c, t_packet * packet)
827     {
828     t_gq * gq;
829     t_elem * elem;
830    
831     if (!packet)
832     return -1;
833    
834     if (!(gq=conn_get_gamequeue(c))) {
835     return 0;
836     }
837     conn_set_gamequeue(c,NULL);
838     gq_destroy(gq,&elem);
839     return 0;
840     }
841    
842     static int on_client_charladderreq(t_connection * c, t_packet * packet)
843     {
844     t_packet * rpacket;
845     char const * charname;
846     unsigned int expansion, hardcore, type;
847     int pos;
848    
849     if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_charladderreq),MAX_CHARNAME_LEN))) {
850     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
851     return -1;
852     }
853     expansion=bn_int_get(packet->u.client_d2cs_charladderreq.expansion);
854     hardcore=bn_int_get(packet->u.client_d2cs_charladderreq.hardcore);
855     type=0; /* avoid warning */
856     if (hardcore && expansion) {
857     type=D2LADDER_EXP_HC_OVERALL;
858     } else if (!hardcore && expansion) {
859     type=D2LADDER_EXP_STD_OVERALL;
860     } else if (hardcore && !expansion) {
861     type=D2LADDER_HC_OVERALL;
862     } else if (!hardcore && !expansion) {
863     type=D2LADDER_STD_OVERALL;
864     }
865     if ((pos=d2ladder_find_character_pos(type,charname))<0) {
866     if ((rpacket=packet_create(packet_class_d2cs))) {
867     packet_set_size(rpacket,sizeof(t_d2cs_client_ladderreply));
868     packet_set_type(rpacket,D2CS_CLIENT_LADDERREPLY);
869     bn_byte_set(&rpacket->u.d2cs_client_ladderreply.type, type);
870     bn_short_set(&rpacket->u.d2cs_client_ladderreply.total_len,0);
871     bn_short_set(&rpacket->u.d2cs_client_ladderreply.curr_len,0);
872     bn_short_set(&rpacket->u.d2cs_client_ladderreply.cont_len,0);
873     conn_push_outqueue(c,rpacket);
874     packet_del_ref(rpacket);
875     }
876     return 0;
877     }
878     pos -= prefs_get_ladderlist_count()/2;
879     if (pos < 0) pos=0;
880     d2cs_send_client_ladder(c,type,pos);
881     return 0;
882     }
883    
884     static int on_client_charlistreq(t_connection * c, t_packet * packet)
885     {
886     t_packet * rpacket;
887     t_pdir * dir;
888     char const * account;
889     char const * charname;
890     char * path;
891     t_d2charinfo_file * charinfo;
892     unsigned int n, maxchar;
893     t_elist charlist_head;
894     char const * charlist_sort_order;
895    
896     if (!packet)
897     return -1;
898    
899     if (!(account=d2cs_conn_get_account(c))) {
900     eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection");
901     return -1;
902     }
903     path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1);
904     charlist_sort_order = prefs_get_charlist_sort_order();
905    
906     elist_init(&charlist_head);
907    
908     d2char_get_infodir_name(path,account);
909     maxchar=prefs_get_maxchar();
910     if ((rpacket=packet_create(packet_class_d2cs))) {
911     packet_set_size(rpacket,sizeof(t_d2cs_client_charlistreply));
912     packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY);
913     bn_short_set(&rpacket->u.d2cs_client_charlistreply.u1,0);
914     n=0;
915     if (!(dir=p_opendir(path))) {
916     eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account);
917     p_mkdir(path,S_IRWXU);
918     } else {
919     while ((charname=p_readdir(dir))) {
920     if (charname[0]=='.') continue;
921     charinfo = xmalloc(sizeof(t_d2charinfo_file));
922     if (d2charinfo_load(account,charname,charinfo)<0) {
923     eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for %s(*%s)",charname,account);
924     xfree((void *)charinfo);
925     continue;
926     }
927     eventlog(eventlog_level_debug,__FUNCTION__,"adding char %s (*%s)", charname, account);
928     d2charlist_add_char(&charlist_head,charinfo,0);
929     n++;
930     if (n>=maxchar) break;
931     }
932     if (prefs_allow_newchar() && (n<maxchar)) {
933     bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);
934     } else {
935     bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,0);
936     }
937     p_closedir(dir);
938     if (!strcmp(charlist_sort_order, "ASC"))
939     {
940     t_elist * curr, * safe;
941     t_d2charlist * ccharlist;
942    
943     elist_for_each_safe(curr,&charlist_head,safe)
944     {
945     ccharlist = elist_entry(curr,t_d2charlist,list);
946     packet_append_string(rpacket,ccharlist->charinfo->header.charname);
947     packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
948     xfree((void *)ccharlist->charinfo);
949     xfree((void *)ccharlist);
950     }
951     }
952     else
953     {
954     t_elist * curr, * safe;
955     t_d2charlist * ccharlist;
956    
957     elist_for_each_safe_rev(curr,&charlist_head,safe)
958     {
959     ccharlist = elist_entry(curr,t_d2charlist,list);
960     packet_append_string(rpacket,ccharlist->charinfo->header.charname);
961     packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
962     xfree((void *)ccharlist->charinfo);
963     xfree((void *)ccharlist);
964    
965     }
966     }
967     }
968     bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
969     bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
970     conn_push_outqueue(c,rpacket);
971     packet_del_ref(rpacket);
972     }
973     xfree(path);
974     return 0;
975     }
976    
977     static int on_client_charlistreq_110(t_connection * c, t_packet * packet)
978     {
979     t_packet * rpacket;
980     t_pdir * dir;
981     char const * account;
982     char const * charname;
983     char * path;
984    
985     t_d2charinfo_file * charinfo;
986     unsigned int n, maxchar;
987     t_elist charlist_head;
988    
989     unsigned int exp_time;
990     unsigned int curr_exp_time;
991     char const * charlist_sort_order;
992    
993     if (!packet)
994     return -1;
995    
996     if (!(account=d2cs_conn_get_account(c))) {
997     eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection");
998     return -1;
999     }
1000     path=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1);
1001     charlist_sort_order = prefs_get_charlist_sort_order();
1002    
1003     elist_init(&charlist_head);
1004    
1005     d2char_get_infodir_name(path,account);
1006     if (prefs_allow_newchar())
1007     maxchar=prefs_get_maxchar();
1008     else
1009     maxchar=0;
1010    
1011     if ((rpacket=packet_create(packet_class_d2cs))) {
1012     packet_set_size(rpacket,sizeof(t_d2cs_client_charlistreply_110));
1013     packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY_110);
1014     bn_short_set(&rpacket->u.d2cs_client_charlistreply_110.u1,0);
1015     n=0;
1016     if (!(dir=p_opendir(path))) {
1017     eventlog(eventlog_level_info,__FUNCTION__,"(*%s) charinfo directory do not exist, building it",account);
1018     p_mkdir(path,S_IRWXU);
1019     } else {
1020     exp_time = prefs_get_char_expire_time();
1021     while ((charname=p_readdir(dir))) {
1022     if (charname[0]=='.') continue;
1023     charinfo = xmalloc(sizeof(t_d2charinfo_file));
1024     if (d2charinfo_load(account,charname,charinfo)<0) {
1025     eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for %s(*%s)",charname,account);
1026     xfree(charinfo);
1027     continue;
1028     }
1029     if (exp_time) {
1030     curr_exp_time = bn_int_get(charinfo->header.last_time)+exp_time;
1031     } else {
1032     curr_exp_time = 0x7FFFFFFF;
1033     }
1034     eventlog(eventlog_level_debug,__FUNCTION__,"adding char %s (*%s)", charname, account);
1035     d2charlist_add_char(&charlist_head,charinfo,curr_exp_time);
1036     n++;
1037     if (n>=maxchar) break;
1038     }
1039     if (n>=maxchar)
1040     maxchar = 0;
1041    
1042     p_closedir(dir);
1043     if (!strcmp(charlist_sort_order, "ASC"))
1044     {
1045     t_elist * curr, *safe;
1046     t_d2charlist * ccharlist;
1047    
1048     elist_for_each_safe(curr,&charlist_head,safe)
1049     {
1050     bn_int bn_exp_time;
1051    
1052     ccharlist = elist_entry(curr,t_d2charlist,list);
1053     bn_int_set(&bn_exp_time,ccharlist->expiration_time);
1054     packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
1055     packet_append_string(rpacket,ccharlist->charinfo->header.charname);
1056     packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
1057     xfree((void *)ccharlist->charinfo);
1058     xfree((void *)ccharlist);
1059     }
1060     }
1061     else
1062     {
1063     t_elist * curr, *safe;
1064     t_d2charlist * ccharlist;
1065    
1066     elist_for_each_safe_rev(curr,&charlist_head,safe)
1067     {
1068     bn_int bn_exp_time;
1069    
1070     ccharlist = elist_entry(curr,t_d2charlist,list);
1071     bn_int_set(&bn_exp_time,ccharlist->expiration_time);
1072     packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
1073     packet_append_string(rpacket,ccharlist->charinfo->header.charname);
1074     packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
1075     xfree((void *)ccharlist->charinfo);
1076     xfree((void *)ccharlist);
1077     }
1078     }
1079     }
1080     bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
1081     bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
1082     bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);
1083    
1084     conn_push_outqueue(c,rpacket);
1085     packet_del_ref(rpacket);
1086     }
1087     xfree(path);
1088     return 0;
1089     }
1090    
1091     static int on_client_convertcharreq(t_connection * c, t_packet * packet)
1092     {
1093     t_packet * rpacket;
1094     char const * charname;
1095     char const * account;
1096     unsigned int reply;
1097    
1098     if (!(charname=packet_get_str_const(packet,sizeof(t_client_d2cs_convertcharreq),MAX_CHARNAME_LEN))) {
1099     eventlog(eventlog_level_error,__FUNCTION__,"got bad character name");
1100     return -1;
1101     }
1102     if (conn_check_multilogin(c,charname)<0) {
1103     eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
1104     return -1;
1105     }
1106     account=d2cs_conn_get_account(c);
1107     if (d2char_convert(account,charname)<0) {
1108     eventlog(eventlog_level_error,__FUNCTION__,"failed to convert character %s(*%s)",charname,account);
1109     reply = D2CS_CLIENT_CONVERTCHARREPLY_FAILED;
1110     } else {
1111     reply = D2CS_CLIENT_CONVERTCHARREPLY_SUCCEED;
1112     }
1113     if ((rpacket=packet_create(packet_class_d2cs))) {
1114     packet_set_size(rpacket,sizeof(t_d2cs_client_convertcharreply));
1115     packet_set_type(rpacket,D2CS_CLIENT_CONVERTCHARREPLY);
1116     bn_int_set(&rpacket->u.d2cs_client_convertcharreply.reply,reply);
1117     conn_push_outqueue(c,rpacket);
1118     packet_del_ref(rpacket);
1119     }
1120     return 0;
1121     }
1122    
1123     extern int d2cs_send_client_creategamewait(t_connection * c, unsigned int position)
1124     {
1125     t_packet * packet;
1126    
1127     ASSERT(c,-1);
1128     if ((packet=packet_create(packet_class_d2cs))) {
1129     packet_set_size(packet,sizeof(t_d2cs_client_creategamewait));
1130     packet_set_type(packet,D2CS_CLIENT_CREATEGAMEWAIT);
1131     bn_int_set(&packet->u.d2cs_client_creategamewait.position,position);
1132     conn_push_outqueue(c,packet);
1133     packet_del_ref(packet);
1134     }
1135     return 0;
1136     }
1137    
1138     extern int d2cs_handle_client_creategame(t_connection * c, t_packet * packet)
1139     {
1140     return on_client_creategamereq(c,packet);
1141     }
1142    
1143     static unsigned int d2cs_try_joingame(t_connection const * c, t_game const * game, char const * gamepass)
1144     {
1145     unsigned int reply;
1146    
1147     ASSERT(c,D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST);
1148     ASSERT(game,D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST);
1149     if (!game_get_created(game)) {
1150     reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
1151     } else if (!game_get_d2gs(game)) {
1152     reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
1153     } else if (conn_get_charinfo_ladder(c) != game_get_gameflag_ladder(game)) {
1154     reply=D2CS_CLIENT_JOINGAMEREPLY_NORMAL_LADDER;
1155     } else if (conn_get_charinfo_expansion(c) != game_get_gameflag_expansion(game)) {
1156     reply=D2CS_CLIENT_JOINGAMEREPLY_CLASSIC_EXPANSION;
1157     } else if (conn_get_charinfo_hardcore(c) != game_get_gameflag_hardcore(game)) {
1158     reply=D2CS_CLIENT_JOINGAMEREPLY_HARDCORE_SOFTCORE;
1159     } else if (conn_get_charinfo_difficulty(c) < game_get_gameflag_difficulty(game)) {
1160     reply=D2CS_CLIENT_JOINGAMEREPLY_NORMAL_NIGHTMARE;
1161     } else if (prefs_allow_gamelimit()) {
1162     if (game_get_maxchar(game) <= game_get_currchar(game)) {
1163     reply=D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL;
1164     } else if (conn_get_charinfo_level(c) > game_get_maxlevel(game)) {
1165     reply=D2CS_CLIENT_JOINGAMEREPLY_LEVEL_LIMIT;
1166     } else if (conn_get_charinfo_level(c) < game_get_minlevel(game)) {
1167     reply=D2CS_CLIENT_JOINGAMEREPLY_LEVEL_LIMIT;
1168     } else if (strcmp(d2cs_game_get_pass(game),gamepass)) {
1169     reply=D2CS_CLIENT_JOINGAMEREPLY_BAD_PASS;
1170     } else {
1171     reply=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED;
1172     }
1173     } else {
1174     if (game_get_currchar(game) >= MAX_CHAR_PER_GAME) {
1175     reply=D2CS_CLIENT_JOINGAMEREPLY_GAME_FULL;
1176     } else {
1177     reply=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED;
1178     }
1179     }
1180     return reply;
1181     }

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