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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Tue Jun 13 05:06:23 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Changes since 1.2: +30 -0 lines
Content type: text/x-csrc
Improve Antibot

1 sysadm 1.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 sysadm 1.3 c->checknum_error_count=0;
463     c->checknum_error_flag=0;
464 sysadm 1.1 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 sysadm 1.2
849     /* sowater */
850     extern int d2cs_conn_set_checknum(t_connection *c, char checknum)
851     {
852     ASSERT(c,-1);
853     c->checknum=checknum;
854 sysadm 1.3 c->checknum_error_count=0;
855 sysadm 1.2 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 sysadm 1.3 extern int d2cs_conn_verify_checknum(t_connection *c, char checknum)
865     {
866     ASSERT(c,-1);
867     if (c->checknum_error_flag>=6)
868     return -2; //Banned, reconnect is required
869     if ((c->checknum_error_count < (c->checknum_error_flag ? 1 : 2)) && c->checknum == checknum)
870     {
871     if (c->checknum_error_count==0 && c->checknum_error_flag>0)
872     c->checknum_error_flag--;
873     return 0; //OK
874     }
875     else
876     {
877     c->checknum_error_count++;
878     if (c->checknum_error_count==2)
879     {
880     c->checknum_error_flag = (c->checknum_error_flag / 3 + 1) * 3;
881     if (c->checknum_error_flag >= 6)
882     {
883     // Checksum failed repeatedly
884     eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) is trying checknum", c->charname, c->account);
885     }
886     }
887     return -1; //Failed
888     }
889     return 1;
890     }

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