/[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.7 - (hide 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 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 sysadm 1.4 #include "d2charstatus.h"
77 sysadm 1.1 #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 sysadm 1.3 c->checknum_error_count=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 sysadm 1.4 t_charstatus *cs;
867    
868 sysadm 1.3 ASSERT(c,-1);
869 sysadm 1.4
870     if ((cs = charstatus_list_find_charstatus_by_charname(c->charname)) == NULL)
871     {
872     cs = charstatus_create(c->charname);
873     }
874    
875 sysadm 1.5 if (time(NULL) - cs->ban_begin_time <= prefs_ban_bot_time())
876 sysadm 1.4 return -2; //Banned
877    
878 sysadm 1.6 if ((c->checknum_error_count < (cs->checknum_error_flag ? prefs_checknum_try_min() : prefs_checknum_try_max()))
879     && tolower(c->checknum) == tolower(checknum))
880 sysadm 1.3 {
881 sysadm 1.4 if (c->checknum_error_count==0 && cs->checknum_error_flag>0)
882 sysadm 1.5 cs->checknum_error_flag=0;
883 sysadm 1.3 return 0; //OK
884     }
885     else
886     {
887     c->checknum_error_count++;
888 sysadm 1.7 if (c->checknum_error_count==(cs->checknum_error_flag ? prefs_checknum_try_min() : prefs_checknum_try_max()))
889 sysadm 1.3 {
890 sysadm 1.5 cs->checknum_error_flag++;
891     if (cs->checknum_error_flag >= prefs_checknum_max_fail_times())
892 sysadm 1.3 {
893     // Checksum failed repeatedly
894     eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) is trying checknum", c->charname, c->account);
895 sysadm 1.4 cs->checknum_error_flag=0;
896     cs->ban_begin_time = time(NULL);
897 sysadm 1.3 }
898     }
899     return -1; //Failed
900     }
901     return 1;
902     }

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