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

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

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