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

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