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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9 - (show 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
Error occurred while calculating annotation data.
Update

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 "d2charstatus.h"
76 #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 /* sowater */
95 #include "d2cs_random.h"
96
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 char checknum;
207 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 /* 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 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
255 /* sowater */
256 packet_append_data(bnpacket,&checknum,sizeof(checknum));
257
258 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 t_charstatus * cs;
288
289
290 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
306 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
327 /* right checknum? sowater */
328 } 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 reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
331 /* when antibot_when_password is true, by sowater, 20051001 */
332 } else if((strlen(gamepass)!=0 || maxchar==1 || leveldiff<30) && prefs_antibot_when_password() && prefs_enable_antibot()
333 && d2cs_conn_verify_checknum(c, *gamedesc)) {
334 eventlog(eventlog_level_info,__FUNCTION__,"checksum %c from packet not match checksum from connection",*gamedesc);
335 reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
336 } 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 /* By Leaflet, 20060613 */
357 if ((cs=charstatus_list_find_charstatus_by_charname(c->charname)) == NULL)
358 cs = charstatus_create(c->charname);
359
360 if (time(NULL) - cs->last_create_time <= prefs_create_game_interval())
361 cs->frequently_create_count++;
362
363 if (prefs_enable_antibot() && cs->frequently_create_count > prefs_frequently_create_limit()
364 && d2cs_conn_verify_checknum(c, *gamedesc)) {
365 eventlog(eventlog_level_info,__FUNCTION__,"checksum %c from packet not match checksum from connection",*gamedesc);
366 reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED;
367 } else {
368 if (strlen(gamedesc)!=0) {
369 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 eventlog(eventlog_level_info,__FUNCTION__,"checksum %c from packet not match checksum from connection",
376 *gamedesc);
377 }
378 }
379
380 if (time(NULL) - cs->last_create_time > prefs_create_game_interval())
381 {
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 }
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 char checknum;
666
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
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 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
717 /*sowater */
718 packet_append_data(bnpacket,&checknum,sizeof(checknum));
719
720 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