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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (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.6: +1 -1 lines
Content type: text/x-csrc
Update

1 /*
2 * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include "common/setup_before.h"
19 #include "setup.h"
20
21 #include <ctype.h>
22 #ifdef HAVE_STRING_H
23 # include <string.h>
24 #else
25 # ifdef HAVE_STRINGS_H
26 # include <strings.h>
27 # endif
28 # ifdef HAVE_MEMORY_H
29 # include <memory.h>
30 # endif
31 #endif
32 #ifdef STDC_HEADERS
33 # include <stdlib.h>
34 #else
35 # ifdef HAVE_MALLOC_H
36 # include <malloc.h>
37 # endif
38 #endif
39 #include "compat/memcpy.h"
40 #include "compat/strdup.h"
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #ifdef HAVE_SYS_TYPES_H
45 # include <sys/types.h>
46 #endif
47 #ifdef HAVE_SYS_SOCKET_H
48 # include <sys/socket.h>
49 #endif
50 #include "compat/psock.h"
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h>
53 #endif
54 #include "compat/netinet_in.h"
55 #ifdef HAVE_LIMITS_H
56 # include <limits.h>
57 #endif
58 #include "compat/char_bit.h"
59 #ifdef TIME_WITH_SYS_TIME
60 # include <time.h>
61 # include <sys/time.h>
62 #else
63 # ifdef HAVE_SYS_TIME_H
64 # include <sys/time.h>
65 # else
66 # include <time.h>
67 # endif
68 #endif
69 #ifdef HAVE_ASSERT_H
70 # include <assert.h>
71 #endif
72
73 #include "compat/psock.h"
74 #include "compat/strcasecmp.h"
75 #include "connection.h"
76 #include "d2charstatus.h"
77 #include "game.h"
78 #include "gamequeue.h"
79 #include "prefs.h"
80 #include "d2gs.h"
81 #include "net.h"
82 #include "s2s.h"
83 #include "handle_d2gs.h"
84 #include "handle_d2cs.h"
85 #include "handle_init.h"
86 #include "handle_bnetd.h"
87 #include "d2charfile.h"
88 #include "common/fdwatch.h"
89 #include "common/addr.h"
90 #include "common/introtate.h"
91 #include "common/network.h"
92 #include "common/packet.h"
93 #include "common/hashtable.h"
94 #include "common/queue.h"
95 #include "common/eventlog.h"
96 #include "common/xalloc.h"
97 #include "common/setup_after.h"
98
99 static t_hashtable * connlist_head=NULL;
100 static t_hashtable * conn_charname_list_head=NULL;
101 static t_list * connlist_dead=NULL;
102 static unsigned int total_connection=0;
103
104 static int conn_handle_connecting(t_connection * c);
105 static t_packet * conn_create_packet(t_connection * c);
106 static int conn_handle_packet(t_connection * c, t_packet * packet);
107 static int conn_handle_read(t_connection * c);
108 static int conn_handle_write(t_connection * c);
109 static unsigned int conn_charname_hash(char const * charname);
110 static unsigned int conn_sessionnum_hash(unsigned int sessionnum);
111
112 static unsigned int conn_sessionnum_hash(unsigned int sessionnum)
113 {
114 return sessionnum;
115 }
116
117 static unsigned int conn_charname_hash(char const * charname)
118 {
119 unsigned int hash;
120 unsigned int i, len, pos;
121 unsigned int ch;
122
123 ASSERT(charname,0);
124 len=strlen(charname);
125 for (hash=0, i=0, pos=0; i<len; i++) {
126 if (isascii((int)charname[i])) {
127 ch=(unsigned int)(unsigned char)tolower((int)charname[i]);
128 } else {
129 ch=(unsigned int)(unsigned char)charname[i];
130 }
131 hash ^= ROTL(ch,pos,sizeof(unsigned int) * CHAR_BIT);
132 pos += CHAR_BIT-1;
133 }
134 return hash;
135 }
136
137 extern t_hashtable * d2cs_connlist(void)
138 {
139 return connlist_head;
140 }
141
142 extern int d2cs_connlist_create(void)
143 {
144 if (!(connlist_head=hashtable_create(200))) return -1;
145 if (!(conn_charname_list_head=hashtable_create(200))) return -1;
146 return 0;
147 }
148
149 extern int d2cs_connlist_destroy(void)
150 {
151 t_connection * c;
152 t_elem * curr;
153
154
155 if (connlist_dead) {
156 d2cs_connlist_reap();
157 if (list_destroy(connlist_dead))
158 eventlog(eventlog_level_error,__FUNCTION__,"error destroy conndead list");
159 connlist_dead = NULL;
160 }
161
162 BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)
163 {
164 d2cs_conn_destroy(c,&curr);
165 }
166 END_HASHTABLE_TRAVERSE_DATA()
167
168 if (hashtable_destroy(connlist_head)<0) {
169 eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection list");
170 return -1;
171 }
172 connlist_head=NULL;
173
174 if (hashtable_destroy(conn_charname_list_head)<0) {
175 eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection charname list");
176 return -1;
177 }
178 conn_charname_list_head=NULL;
179 return 0;
180 }
181
182 extern int d2cs_connlist_reap(void)
183 {
184 t_connection * c;
185
186 if (!connlist_dead) return 0;
187 BEGIN_LIST_TRAVERSE_DATA(connlist_dead, c)
188 {
189 d2cs_conn_destroy(c,&curr_elem_);
190 }
191 END_LIST_TRAVERSE_DATA()
192
193 return 0;
194 }
195
196 extern int conn_check_multilogin(t_connection const * c,char const * charname)
197 {
198 t_connection * conn;
199
200 ASSERT(charname,-1);
201 if (!prefs_check_multilogin()) return 0;
202 if (gamelist_find_character(charname)) {
203 return -1;
204 }
205 conn=d2cs_connlist_find_connection_by_charname(charname);
206 if (conn && conn!=c) {
207 return -1;
208 }
209 return 0;
210 }
211
212 extern t_connection * d2cs_connlist_find_connection_by_sessionnum(unsigned int sessionnum)
213 {
214 t_connection * c;
215 t_entry * curr;
216 unsigned int hash;
217
218 hash=conn_sessionnum_hash(sessionnum);
219 HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)
220 {
221 if (!(c=entry_get_data(curr))) {
222 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");
223 } else if (c->sessionnum==sessionnum) {
224 hashtable_entry_release(curr);
225 return c;
226 }
227 }
228 return NULL;
229 }
230
231 extern t_connection * d2cs_connlist_find_connection_by_charname(char const * charname)
232 {
233 t_entry * curr;
234 t_connection * c;
235 unsigned int hash;
236
237 hash=conn_charname_hash(charname);
238 HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)
239 {
240 if (!(c=entry_get_data(curr))) {
241 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");
242 } else {
243 if (!c->charname) continue;
244 if (!strcmp_charname(c->charname,charname)) {
245 hashtable_entry_release(curr);
246 return c;
247 }
248 }
249 }
250 return NULL;
251 }
252
253 static t_packet * conn_create_packet(t_connection * c)
254 {
255 t_packet * packet;
256
257 switch (c->class) {
258 CASE(conn_class_init, packet=packet_create(packet_class_init));
259 CASE(conn_class_d2cs, packet=packet_create(packet_class_d2cs));
260 CASE(conn_class_d2gs, packet=packet_create(packet_class_d2gs));
261 CASE(conn_class_bnetd, packet=packet_create(packet_class_d2cs_bnetd));
262 default:
263 eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);
264 return NULL;
265 }
266 if (!packet) {
267 eventlog(eventlog_level_error,__FUNCTION__,"error create packet");
268 return NULL;
269 }
270 d2cs_conn_set_in_queue(c,packet);
271 return packet;
272 }
273
274 static int conn_handle_connecting(t_connection * c)
275 {
276 int retval;
277
278 if (net_check_connected(c->sock)<0) {
279 eventlog(eventlog_level_warn,__FUNCTION__,"can not connect to %s",addr_num_to_addr_str(c->addr, c->port));
280 return -1;
281 }
282 eventlog(eventlog_level_info,__FUNCTION__,"connected to %s",addr_num_to_addr_str(c->addr, c->port));
283 c->state=conn_state_init;
284 /* this is a kind of hack to not update fd but updating breaks kqueue
285 * and the clean fix would require a cache a userland copy of the kernel
286 * kqueue fds, considering that it also doesnt brake anything else should do
287 * for the moment
288 fdwatch_update_fd(c->sock, fdwatch_type_read); */
289 switch (c->class) {
290 case conn_class_bnetd:
291 retval=handle_bnetd_init(c);
292 break;
293 default:
294 eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);
295 return -1;
296 }
297 return retval;
298 }
299
300 static int conn_handle_packet(t_connection * c, t_packet * packet)
301 {
302 int retval;
303
304 switch (c->class) {
305 CASE (conn_class_init, retval=d2cs_handle_init_packet(c,packet));
306 CASE (conn_class_d2cs, retval=d2cs_handle_d2cs_packet(c,packet));
307 CASE (conn_class_d2gs, retval=handle_d2gs_packet(c,packet));
308 CASE (conn_class_bnetd, retval=handle_bnetd_packet(c,packet));
309 default:
310 eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d (close connection)",c->class);
311 retval=-1;
312 break;
313 }
314 return retval;
315 }
316
317 static int conn_handle_read(t_connection * c)
318 {
319 t_packet * packet;
320 int retval;
321
322 packet = d2cs_conn_get_in_queue(c);
323 if (!packet) {
324 packet = conn_create_packet(c);
325 if (!packet) return -1;
326 c->insize=0;
327 }
328
329 switch (net_recv_packet(c->sock,packet,&c->insize)) {
330 case -1:
331 retval=-1;
332 break;
333 case 0:
334 retval=0;
335 break;
336 case 1:
337 c->insize=0;
338 d2cs_conn_set_in_queue(c,NULL);
339 retval=conn_handle_packet(c,packet);
340 packet_del_ref(packet);
341 break;
342 default:
343 retval=0;
344 break;
345 }
346 return retval;
347 }
348
349 static int conn_handle_write(t_connection * c)
350 {
351 t_packet * packet;
352 int retval;
353
354 if (c->state==conn_state_connecting) {
355 return conn_handle_connecting(c);
356 }
357
358 if (!(packet=conn_peek_outqueue(c))) return 0;
359
360 switch (net_send_packet(c->sock, packet, &c->outsize)) {
361 case -1:
362 retval=-1;
363 break;
364 case 0:
365 retval=0;
366 break;
367 case 1:
368 c->outsize=0;
369 packet=conn_pull_outqueue(c);
370 packet_del_ref(packet);
371 retval=0;
372 break;
373 default:
374 retval = -1;
375 }
376 return retval;
377 }
378
379 extern int conn_handle_socket(t_connection * c)
380 {
381 time_t now;
382
383 ASSERT(c,-1);
384 now=time(NULL);
385 if (c->socket_flag & SOCKET_FLAG_READ) {
386 if (conn_handle_read(c)<0) return -1;
387 c->last_active=now;
388 }
389 if (c->socket_flag & SOCKET_FLAG_WRITE) {
390 if (conn_handle_write(c)<0) return -1;
391 c->last_active=now;
392 }
393 c->socket_flag=0;
394 return 0;
395 }
396
397 extern int connlist_check_timeout(void)
398 {
399 t_connection * c;
400 time_t now;
401
402 now=time(NULL);
403 BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)
404 {
405 switch (c->class) {
406 case conn_class_d2cs:
407 if (prefs_get_idletime() && (now - c->last_active > prefs_get_idletime())) {
408 eventlog(eventlog_level_info,__FUNCTION__,"client %d idled too long time, destroy it",c->sessionnum);
409 d2cs_conn_set_state(c,conn_state_destroy);
410 }
411 break;
412 case conn_class_d2gs:
413 if (prefs_get_s2s_idletime() && now - c->last_active > prefs_get_s2s_idletime()) {
414 eventlog(eventlog_level_info,__FUNCTION__,"server %d timed out",c->sessionnum);
415 d2cs_conn_set_state(c,conn_state_destroy);
416 }
417 break;
418 case conn_class_bnetd:
419 break;
420 default:
421 break;
422 }
423 }
424 END_HASHTABLE_TRAVERSE_DATA()
425 return 0;
426 }
427
428 extern t_connection * d2cs_conn_create(int sock, unsigned int local_addr, unsigned short local_port,
429 unsigned int addr, unsigned short port)
430 {
431 static unsigned int sessionnum=1;
432 t_connection * c;
433
434 if (sock<0) {
435 eventlog(eventlog_level_error,__FUNCTION__,"got bad socket");
436 return NULL;
437 }
438 c=xmalloc(sizeof(t_connection));
439 c->charname=NULL;
440 c->account=NULL;
441 c->sock=sock;
442 c->fdw_idx = -1;
443 c->socket_flag=0;
444 c->local_addr=local_addr;
445 c->local_port=local_port;
446 c->addr=addr;
447 c->port=port;
448 c->class=conn_class_init;
449 c->state=conn_state_init;
450 c->sessionnum=sessionnum++;
451 c->outqueue=NULL;
452 c->inqueue=NULL;
453 c->outsize=0;
454 c->outsizep=0;
455 c->insize=0;
456 c->charinfo=NULL;
457 c->d2gs_id=0;
458 c->gamequeue=NULL;
459 c->last_active=time(NULL);
460 c->sessionnum_hash=conn_sessionnum_hash(c->sessionnum);
461 c->bnetd_sessionnum=0;
462 c->charname_hash=0;
463 c->checknum_error_count=0;
464 if (hashtable_insert_data(connlist_head, c, c->sessionnum_hash)<0) {
465 xfree(c);
466 eventlog(eventlog_level_error,__FUNCTION__,"error add connection to list");
467 return NULL;
468 }
469 total_connection++;
470 eventlog(eventlog_level_info,__FUNCTION__,"created session=%d socket=%d (%d current connections)", c->sessionnum, sock, total_connection);
471 return c;
472 }
473
474 extern int d2cs_conn_destroy(t_connection * c, t_elem ** curr)
475 {
476 t_elem * elem;
477
478 ASSERT(c,-1);
479 if (c->state==conn_state_destroying) return 0;
480 if (hashtable_remove_data(connlist_head,c,c->sessionnum_hash)<0) {
481 eventlog(eventlog_level_error,__FUNCTION__,"error remove connection from list");
482 return -1;
483 }
484 c->state=conn_state_destroying;
485 if (c->d2gs_id && c->class==conn_class_d2gs) {
486 d2gs_deactive(d2gslist_find_gs(c->d2gs_id),c);
487 }
488 if (c->class==conn_class_bnetd) {
489 s2s_destroy(c);
490 }
491 if (c->gamequeue) {
492 gq_destroy(c->gamequeue,&elem);
493 }
494 if (c->account) xfree((void *)c->account);
495 if (c->charinfo) xfree((void *)c->charinfo);
496 if (c->charname) d2cs_conn_set_charname(c,NULL);
497 if (c->inqueue) packet_del_ref(c->inqueue);
498 queue_clear(&c->outqueue);
499
500 if (connlist_dead) list_remove_data(connlist_dead, c, curr);
501 fdwatch_del_fd(c->fdw_idx);
502 psock_shutdown(c->sock,PSOCK_SHUT_RDWR);
503 psock_close(c->sock);
504
505 total_connection--;
506 eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed connection %d (%d left)",c->sock,c->sessionnum,total_connection);
507 xfree(c);
508 return 0;
509 }
510
511 extern int d2cs_conn_get_socket(t_connection const * c)
512 {
513 ASSERT(c,-1);
514 return c->sock;
515 }
516
517 extern t_conn_state d2cs_conn_get_state(t_connection const * c)
518 {
519 ASSERT(c,conn_state_none);
520 return c->state;
521 }
522
523 extern int d2cs_conn_set_state(t_connection * c, t_conn_state state)
524 {
525 t_elem * curr;
526
527 ASSERT(c,-1);
528 /* special case for destroying connections, add them to connlist_dead list */
529 if (state == conn_state_destroy && c->state != conn_state_destroy) {
530 if (!connlist_dead)
531 connlist_dead = list_create();
532 list_append_data(connlist_dead, c);
533 } else if (state != conn_state_destroy && c->state == conn_state_destroy) {
534 if (list_remove_data(connlist_dead, c, &curr)) {
535 eventlog(eventlog_level_error, __FUNCTION__, "could not remove dead connection");
536 return -1;
537 }
538 }
539 c->state=state;
540 return 0;
541 }
542
543 extern t_conn_class d2cs_conn_get_class(t_connection const * c)
544 {
545 ASSERT(c,conn_class_none);
546 return c->class;
547 }
548
549 extern int d2cs_conn_set_class(t_connection * c, t_conn_class class)
550 {
551 ASSERT(c,-1);
552 c->class=class;
553 return 0;
554 }
555
556 extern t_packet * d2cs_conn_get_in_queue(t_connection const * c)
557 {
558 ASSERT(c,NULL);
559 return c->inqueue;
560 }
561
562 extern void d2cs_conn_set_in_queue(t_connection * c, t_packet *packet)
563 {
564 assert(c);
565 c->inqueue = packet;
566 }
567
568 extern unsigned int d2cs_conn_get_out_size(t_connection const * c)
569 {
570 ASSERT(c,0);
571 return c->outsize;
572 }
573
574 extern t_queue * * d2cs_conn_get_out_queue(t_connection const * c)
575 {
576 ASSERT(c,NULL);
577 return (t_queue * *)&c->outqueue;
578 }
579
580 extern unsigned int d2cs_conn_get_in_size(t_connection const * c)
581 {
582 ASSERT(c,0);
583 return c->insize;
584 }
585
586 extern int conn_push_outqueue(t_connection * c, t_packet * packet)
587 {
588 if (!c)
589 {
590 eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
591 return -1;
592 }
593
594 if (!packet)
595 {
596 eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet");
597 return -1;
598 }
599
600 queue_push_packet((t_queue * *)&c->outqueue, packet);
601 if (!c->outsizep++) fdwatch_update_fd(c->fdw_idx, fdwatch_type_read | fdwatch_type_write);
602
603 return 0;
604 }
605
606 extern t_packet * conn_peek_outqueue(t_connection * c)
607 {
608 if (!c)
609 {
610 eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
611 return NULL;
612 }
613
614 return queue_peek_packet((t_queue const * const *)&c->outqueue);
615 }
616
617 extern t_packet * conn_pull_outqueue(t_connection * c)
618 {
619 if (!c)
620 {
621 eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
622 return NULL;
623 }
624
625 if (c->outsizep) {
626 if (!(--c->outsizep)) fdwatch_update_fd(c->fdw_idx, fdwatch_type_read);
627 return queue_pull_packet((t_queue * *)&c->outqueue);
628 }
629
630 return NULL;
631 }
632
633 extern int conn_add_socket_flag(t_connection * c, unsigned int flag)
634 {
635 ASSERT(c,-1);
636 c->socket_flag |= flag;
637 return 0;
638 }
639
640 extern int conn_process_packet(t_connection * c, t_packet * packet, t_packet_handle_table * table,
641 unsigned int table_size)
642 {
643 unsigned int type;
644 unsigned int size;
645
646 ASSERT(c,-1);
647 ASSERT(packet,-1);
648 ASSERT(table,-1);
649 type=packet_get_type(packet);
650 size=packet_get_size(packet);
651
652 if (type >= table_size || !table[type].size) {
653 eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d (class %d)",type,packet_get_class(packet));
654 return -1;
655 }
656 if (size < table[type].size) {
657 eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size %d (type %d class %d)",size,type,packet_get_class(packet));
658 return -1;
659 }
660 if (!(c->state & table[type].state)) {
661 eventlog(eventlog_level_error,__FUNCTION__,"connection %d state mismatch for packet type %d (class %d)",c->sessionnum,
662 type,packet_get_class(packet));
663 return -1;
664 }
665 if (!table[type].handler) {
666 eventlog(eventlog_level_error,__FUNCTION__,"missing handler for packet type %d (class %d)",type,packet_get_class(packet));
667 return -1;
668 }
669 return table[type].handler(c,packet);
670 }
671
672 extern int d2cs_conn_set_account(t_connection * c, char const * account)
673 {
674 ASSERT(c,-1);
675 if (!account) {
676 if (c->account) xfree((void *)c->account);
677 c->account=NULL;
678 }
679 if (c->account) xfree((void *)c->account);
680 c->account=xstrdup(account);
681
682 return 0;
683 }
684
685 extern char const * d2cs_conn_get_account(t_connection const * c)
686 {
687 ASSERT(c,NULL);
688 return c->account;
689 }
690
691 extern int d2cs_conn_set_charname(t_connection * c, char const * charname)
692 {
693 char const * temp;
694
695 ASSERT(c,-1);
696 temp=NULL;
697 if (charname) temp=xstrdup(charname);
698 if (c->charname) {
699 if (hashtable_remove_data(conn_charname_list_head,c,c->charname_hash) <0) {
700 eventlog(eventlog_level_error,__FUNCTION__,"error remove charname %s from list",charname);
701 if (temp) xfree((void *)temp);
702 return -1;
703 }
704 hashtable_purge(conn_charname_list_head);
705 xfree((void *)c->charname);
706 }
707 if (charname) {
708 c->charname=temp;
709 c->charname_hash=conn_charname_hash(charname);
710 if (hashtable_insert_data(conn_charname_list_head,c,c->charname_hash) <0) {
711 eventlog(eventlog_level_error,__FUNCTION__,"error insert charname %s to list",charname);
712 xfree((void *)c->charname);
713 c->charname=NULL;
714 return -1;
715 }
716 } else {
717 c->charname=NULL;
718 c->charname_hash=0;
719 }
720 return 0;
721 }
722
723 extern char const * d2cs_conn_get_charname(t_connection const * c)
724 {
725 ASSERT(c,NULL);
726 return c->charname;
727 }
728
729 extern unsigned int d2cs_conn_get_sessionnum(t_connection const * c)
730 {
731 ASSERT(c,0);
732 return c->sessionnum;
733 }
734
735 extern unsigned int conn_get_charinfo_ladder(t_connection const * c)
736 {
737 ASSERT(c,0);
738 return d2charinfo_get_ladder(c->charinfo);
739 }
740
741 extern unsigned int conn_get_charinfo_expansion(t_connection const * c)
742 {
743 ASSERT(c,0);
744 return d2charinfo_get_expansion(c->charinfo);
745 }
746
747 extern unsigned int conn_get_charinfo_hardcore(t_connection const * c)
748 {
749 ASSERT(c,0);
750 return d2charinfo_get_hardcore(c->charinfo);
751 }
752
753 extern unsigned int conn_get_charinfo_dead(t_connection const * c)
754 {
755 ASSERT(c,0);
756 return d2charinfo_get_dead(c->charinfo);
757 }
758
759 extern unsigned int conn_get_charinfo_difficulty(t_connection const * c)
760 {
761 ASSERT(c,0);
762 return d2charinfo_get_difficulty(c->charinfo);
763 }
764
765 extern unsigned int conn_get_charinfo_level(t_connection const * c)
766 {
767 ASSERT(c,0);
768 return d2charinfo_get_level(c->charinfo);
769 }
770
771 extern unsigned int conn_get_charinfo_class(t_connection const * c)
772 {
773 ASSERT(c,0);
774 return d2charinfo_get_class(c->charinfo);
775 }
776
777 extern int conn_set_charinfo(t_connection * c, t_d2charinfo_summary const * charinfo)
778 {
779 ASSERT(c,-1);
780 if (!charinfo) {
781 if (c->charinfo) xfree((void *)c->charinfo);
782 c->charinfo=NULL;
783 return 0;
784 }
785 if (c->charinfo) xfree((void *)c->charinfo);
786 c->charinfo=xmalloc(sizeof(t_d2charinfo_summary));
787 memcpy((void*)c->charinfo,charinfo,sizeof(t_d2charinfo_summary));
788 return 0;
789 }
790
791 extern int conn_set_d2gs_id(t_connection * c, unsigned int d2gs_id)
792 {
793 ASSERT(c,-1)
794 c->d2gs_id=d2gs_id;
795 return 0;
796 }
797
798 extern unsigned int conn_get_d2gs_id(t_connection const * c)
799 {
800 ASSERT(c,0)
801 return c->d2gs_id;
802 }
803
804 extern unsigned int d2cs_conn_get_addr(t_connection const * c)
805 {
806 ASSERT(c,0);
807 return c->addr;
808 }
809
810 extern unsigned short d2cs_conn_get_port(t_connection const * c)
811 {
812 ASSERT(c,0);
813 return c->port;
814 }
815
816 extern t_gq * conn_get_gamequeue(t_connection const * c)
817 {
818 ASSERT(c,NULL);
819 return c->gamequeue;
820 }
821
822 extern int conn_set_gamequeue(t_connection * c, t_gq * gq)
823 {
824 ASSERT(c,-1);
825 c->gamequeue=gq;
826 return 0;
827 }
828
829 extern int conn_set_bnetd_sessionnum(t_connection * c, unsigned int sessionnum)
830 {
831 ASSERT(c,-1);
832 c->bnetd_sessionnum=sessionnum;
833 return 0;
834 }
835
836 extern unsigned int conn_get_bnetd_sessionnum(t_connection const * c)
837 {
838 ASSERT(c,-1);
839 return c->bnetd_sessionnum;
840 }
841
842 extern int conn_add_fd(t_connection * c, t_fdwatch_type rw, fdwatch_handler handler)
843 {
844 assert(c);
845 c->fdw_idx = fdwatch_add_fd(c->sock,rw,handler,c);
846 return c->fdw_idx;
847 }
848
849 /* sowater */
850 extern int d2cs_conn_set_checknum(t_connection *c, char checknum)
851 {
852 ASSERT(c,-1);
853 c->checknum=checknum;
854 c->checknum_error_count=0;
855 return 0;
856 }
857
858 extern char d2cs_conn_get_checknum(t_connection *c)
859 {
860 ASSERT(c,-1);
861 return c->checknum;
862 }
863
864 extern int d2cs_conn_verify_checknum(t_connection *c, char checknum)
865 {
866 t_charstatus *cs;
867
868 ASSERT(c,-1);
869
870 if ((cs = charstatus_list_find_charstatus_by_charname(c->charname)) == NULL)
871 {
872 cs = charstatus_create(c->charname);
873 }
874
875 if (time(NULL) - cs->ban_begin_time <= prefs_ban_bot_time())
876 return -2; //Banned
877
878 if ((c->checknum_error_count < (cs->checknum_error_flag ? prefs_checknum_try_min() : prefs_checknum_try_max()))
879 && tolower(c->checknum) == tolower(checknum))
880 {
881 if (c->checknum_error_count==0 && cs->checknum_error_flag>0)
882 cs->checknum_error_flag=0;
883 return 0; //OK
884 }
885 else
886 {
887 c->checknum_error_count++;
888 if (c->checknum_error_count==(cs->checknum_error_flag ? prefs_checknum_try_min() : prefs_checknum_try_max()))
889 {
890 cs->checknum_error_flag++;
891 if (cs->checknum_error_flag >= prefs_checknum_max_fail_times())
892 {
893 // Checksum failed repeatedly
894 eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) is trying checknum", c->charname, c->account);
895 cs->checknum_error_flag=0;
896 cs->ban_begin_time = time(NULL);
897 }
898 }
899 return -1; //Failed
900 }
901 return 1;
902 }

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