/[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.9 - (hide annotations)
Sat Jul 12 09:58:50 2008 UTC (17 years, 8 months ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +7 -3 lines
Content type: text/x-csrc
Update

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

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