/[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.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU
CVS Tags: arelease
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

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

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