/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/server.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/server.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:37 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 sysadm 1.1 /*
2     * Copyright (C) 1998,1999 Mark Baysinger (mbaysing@ucsd.edu)
3     * Copyright (C) 1998,1999,2000,2001 Ross Combs (rocombs@cs.nmsu.edu)
4     * Copyright (C) 2000,2001 Marco Ziech (mmz@gmx.net)
5     *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU General Public License
8     * as published by the Free Software Foundation; either version 2
9     * of the License, or (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19     */
20     #define SERVER_INTERNAL_ACCESS
21     #include "common/setup_before.h"
22     #include <stdio.h>
23     #ifdef WIN32
24     # include <conio.h> /* for kbhit() and getch() */
25     #endif
26     #ifdef HAVE_STDDEF_H
27     # include <stddef.h>
28     #else
29     # ifndef NULL
30     # define NULL ((void *)0)
31     # endif
32     #endif
33     #ifdef STDC_HEADERS
34     # include <stdlib.h>
35     #else
36     # ifdef HAVE_MALLOC_H
37     # include <malloc.h>
38     # endif
39     #endif
40     #ifdef HAVE_UNISTD_H
41     # include <unistd.h>
42     #endif
43     #ifdef HAVE_FCNTL_H
44     # include <fcntl.h>
45     #else
46     # ifdef HAVE_SYS_FILE_H
47     # include <sys/file.h>
48     # endif
49     #endif
50     #ifdef HAVE_STRING_H
51     # include <string.h>
52     #else
53     # ifdef HAVE_STRINGS_H
54     # include <strings.h>
55     # endif
56     # ifdef HAVE_MEMORY_H
57     # include <memory.h>
58     # endif
59     #endif
60     #include "compat/memset.h"
61     #include <errno.h>
62     #include "compat/strerror.h"
63     #ifdef TIME_WITH_SYS_TIME
64     # include <sys/time.h>
65     # include <time.h>
66     #else
67     # ifdef HAVE_SYS_TIME_H
68     # include <sys/time.h>
69     # else
70     # include <time.h>
71     # endif
72     #endif
73     #include "compat/difftime.h"
74     #ifdef HAVE_SYS_TYPES_H
75     # include <sys/types.h>
76     #endif
77     #ifdef DO_POSIXSIG
78     # include <signal.h>
79     # include "compat/signal.h"
80     #endif
81     #ifdef HAVE_SYS_SOCKET_H
82     # include <sys/socket.h>
83     #endif
84     #include "compat/socket.h"
85     #ifdef HAVE_SYS_PARAM_H
86     # include <sys/param.h>
87     #endif
88     #ifdef HAVE_NETINET_IN_H
89     # include <netinet/in.h>
90     #endif
91     #include "compat/netinet_in.h"
92     #ifdef HAVE_ARPA_INET_H
93     # include <arpa/inet.h>
94     #endif
95     #ifdef HAVE_NETDB_H
96     # include <netdb.h>
97     #endif
98     #include "compat/inet_ntoa.h"
99     #include "compat/psock.h"
100     #include "common/packet.h"
101     #include "connection.h"
102     #include "common/hexdump.h"
103     #include "common/eventlog.h"
104     #include "message.h"
105     #include "handle_bnet.h"
106     #include "handle_bot.h"
107     #include "handle_telnet.h"
108     #include "handle_file.h"
109     #include "handle_init.h"
110     #include "handle_d2cs.h"
111     #include "handle_irc.h"
112     #include "handle_udp.h"
113     #include "common/network.h"
114     #include "prefs.h"
115     #include "account.h"
116     #include "common/tracker.h"
117     #include "common/list.h"
118     #include "adbanner.h"
119     #include "timer.h"
120     #include "common/addr.h"
121     #include "common/util.h"
122     #include "common/rlimit.h"
123     #include "ipban.h"
124     #include "helpfile.h"
125     #include "autoupdate.h"
126     #include "versioncheck.h"
127     #include "realm.h"
128     #include "channel.h"
129     #include "game.h"
130     #include "anongame.h"
131     #include "server.h"
132     #include "command_groups.h"
133     #ifdef WIN32
134     # include "win32/service.h"
135     #endif
136     // aaron
137     #include "ladder.h"
138     #include "output.h"
139     #include "alias_command.h"
140     #include "anongame_infos.h"
141     #include "news.h"
142     #include "common/fdwatch.h"
143     #include "clan.h"
144     #include "common/trans.h"
145     #include "common/xalloc.h"
146     #include "tournament.h"
147     #include <ctype.h>
148     #include "topic.h"
149     #include "common/setup_after.h"
150    
151     extern FILE * hexstrm; /* from main.c */
152     extern int g_ServiceStatus;
153    
154     #ifdef DO_POSIXSIG
155     static void quit_sig_handle(int unused);
156     static void restart_sig_handle(int unused);
157     static void save_sig_handle(int unused);
158     #ifdef HAVE_SETITIMER
159     static void timer_sig_handle(int unused);
160     #endif
161     #endif
162    
163    
164     time_t now;
165     static time_t starttime;
166     static time_t curr_exittime;
167     static volatile time_t sigexittime=0;
168     static volatile int do_restart=0;
169     static volatile int do_save=0;
170     static volatile int got_epipe=0;
171     static char const * server_name=NULL;
172    
173     extern void server_quit_delay(int delay)
174     {
175     /* getting negative delay is ok too because it will force immediate
176     * shutdown */
177     if (delay)
178     sigexittime = time(NULL)+delay;
179     else
180     sigexittime = 0;
181     }
182    
183    
184     extern void server_quit_wraper(void)
185     {
186     if (sigexittime)
187     sigexittime -= prefs_get_shutdown_decr();
188     else
189     sigexittime = time(NULL)+(time_t)prefs_get_shutdown_delay();
190     }
191    
192     extern void server_restart_wraper(void){
193     do_restart = 1;
194     }
195    
196     extern void server_save_wraper(void){
197     do_save = 1;
198     }
199    
200     #ifdef DO_POSIXSIG
201     static void quit_sig_handle(int unused)
202     {
203     server_quit_wraper();
204     }
205    
206    
207     static void restart_sig_handle(int unused)
208     {
209     do_restart = 1;
210     }
211    
212    
213     static void save_sig_handle(int unused)
214     {
215     do_save = 1;
216     }
217    
218     static void pipe_sig_handle(int unused)
219     {
220     got_epipe = 1;
221     }
222    
223     #ifdef HAVE_SETITIMER
224     static void timer_sig_handle(int unused)
225     {
226     time(&now);
227     }
228     #endif
229    
230     static void forced_quit_sig_handle(int unused)
231     {
232     server_quit_delay(-1); /* programs shutdown 1 second before now */
233     }
234     #endif
235    
236    
237     extern unsigned int server_get_uptime(void)
238     {
239     return (unsigned int)difftime(time(NULL),starttime);
240     }
241    
242    
243     extern unsigned int server_get_starttime(void)
244     {
245     return (unsigned int)starttime;
246     }
247    
248    
249     static char const * laddr_type_get_str(t_laddr_type laddr_type)
250     {
251     switch (laddr_type)
252     {
253     case laddr_type_bnet:
254     return "bnet";
255     case laddr_type_w3route:
256     return "w3route";
257     case laddr_type_irc:
258     return "irc";
259     case laddr_type_telnet:
260     return "telnet";
261     default:
262     return "UNKNOWN";
263     }
264     }
265    
266    
267     static int handle_accept(void *data, t_fdwatch_type rw);
268     static int handle_tcp(void *data, t_fdwatch_type rw);
269     static int handle_udp(void *data, t_fdwatch_type rw);
270    
271    
272     static int sd_accept(t_addr const * curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket)
273     {
274     char tempa[32];
275     int csocket;
276     struct sockaddr_in caddr;
277     psock_t_socklen caddr_len;
278     unsigned int raddr;
279     unsigned short rport;
280    
281     if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa)))
282     strcpy(tempa,"x.x.x.x:x");
283    
284     /* accept the connection */
285     memset(&caddr,0,sizeof(caddr)); /* not sure if this is needed... modern systems are ok anyway */
286     caddr_len = sizeof(caddr);
287     if ((csocket = psock_accept(ssocket,(struct sockaddr *)&caddr,&caddr_len))<0)
288     {
289     /* BSD, POSIX error for aborted connections, SYSV often uses EAGAIN or EPROTO */
290     if (
291     #ifdef PSOCK_EWOULDBLOCK
292     psock_errno()==PSOCK_EWOULDBLOCK ||
293     #endif
294     #ifdef PSOCK_ECONNABORTED
295     psock_errno()==PSOCK_ECONNABORTED ||
296     #endif
297     #ifdef PSOCK_EPROTO
298     psock_errno()==PSOCK_EPROTO ||
299     #endif
300     0)
301     eventlog(eventlog_level_error,__FUNCTION__,"client aborted connection on %s (psock_accept: %s)",tempa,pstrerror(psock_errno()));
302     else /* EAGAIN can mean out of resources _or_ connection aborted :( */
303     if (
304     #ifdef PSOCK_EINTR
305     psock_errno()!=PSOCK_EINTR &&
306     #endif
307     1)
308     eventlog(eventlog_level_error,__FUNCTION__,"could not accept new connection on %s (psock_accept: %s)",tempa,pstrerror(psock_errno()));
309     return -1;
310     }
311    
312     /* dont accept new connections while shutdowning */
313     if (curr_exittime) {
314     psock_shutdown(csocket,PSOCK_SHUT_RDWR);
315     psock_close(csocket);
316     return 0;
317     }
318    
319     if (ipbanlist_check(inet_ntoa(caddr.sin_addr))!=0)
320     {
321     eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection from banned address %s denied (closing connection)",csocket,inet_ntoa(caddr.sin_addr));
322     psock_close(csocket);
323     return -1;
324     }
325    
326     if ((prefs_get_max_conns_per_IP()!=0) &&
327     (connlist_count_connections(ntohl(caddr.sin_addr.s_addr)) > prefs_get_max_conns_per_IP()))
328     {
329     eventlog(eventlog_level_error,__FUNCTION__,"[%d] too many connections from address %s (closing connection)",csocket,inet_ntoa(caddr.sin_addr));
330     psock_close(csocket);
331     return -1;
332     }
333    
334     eventlog(eventlog_level_info,__FUNCTION__,"[%d] accepted connection from %s on %s",csocket,addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)),tempa);
335    
336     if (prefs_get_use_keepalive())
337     {
338     int val=1;
339    
340     if (psock_setsockopt(csocket,PSOCK_SOL_SOCKET,PSOCK_SO_KEEPALIVE,&val,(psock_t_socklen)sizeof(val))<0)
341     eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set socket option SO_KEEPALIVE (psock_setsockopt: %s)",csocket,pstrerror(psock_errno()));
342     /* not a fatal error */
343     }
344    
345     {
346     struct sockaddr_in rsaddr;
347     psock_t_socklen rlen;
348    
349     memset(&rsaddr,0,sizeof(rsaddr)); /* not sure if this is needed... modern systems are ok anyway */
350     rlen = sizeof(rsaddr);
351     if (psock_getsockname(csocket,(struct sockaddr *)&rsaddr,&rlen)<0)
352     {
353     eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to determine real local port (psock_getsockname: %s)",csocket,pstrerror(psock_errno()));
354     /* not a fatal error */
355     raddr = addr_get_ip(curr_laddr);
356     rport = addr_get_port(curr_laddr);
357     }
358     else
359     {
360     if (rsaddr.sin_family!=PSOCK_AF_INET)
361     {
362     eventlog(eventlog_level_error,__FUNCTION__,"local address returned with bad address family %d",(int)rsaddr.sin_family);
363     /* not a fatal error */
364     raddr = addr_get_ip(curr_laddr);
365     rport = addr_get_port(curr_laddr);
366     }
367     else
368     {
369     raddr = ntohl(rsaddr.sin_addr.s_addr);
370     rport = ntohs(rsaddr.sin_port);
371     }
372     }
373     }
374    
375     if (psock_ctl(csocket,PSOCK_NONBLOCK)<0)
376     {
377     eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set TCP socket to non-blocking mode (closing connection) (psock_ctl: %s)",csocket,pstrerror(psock_errno()));
378     psock_close(csocket);
379     return -1;
380     }
381    
382     {
383     t_connection * c;
384    
385     if (!(c = conn_create(csocket,usocket,raddr,rport,addr_get_ip(curr_laddr),addr_get_port(curr_laddr),ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port))))
386     {
387     eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to create new connection (closing connection)",csocket);
388     psock_close(csocket);
389     return -1;
390     }
391    
392     if (conn_add_fdwatch(c, handle_tcp) < 0) {
393     eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to add socket to fdwatch pool (max connections?)",csocket);
394     conn_set_state(c,conn_state_destroy);
395     return -1;
396     }
397    
398     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] client connected to a %s listening address",csocket,laddr_type_get_str(laddr_info->type));
399     switch (laddr_info->type)
400     {
401     case laddr_type_irc:
402     conn_set_class(c,conn_class_irc);
403     conn_set_state(c,conn_state_connected);
404     break;
405     case laddr_type_w3route:
406     conn_set_class(c,conn_class_w3route);
407     conn_set_state(c,conn_state_connected);
408     break;
409     case laddr_type_telnet:
410     conn_set_class(c,conn_class_telnet);
411     conn_set_state(c,conn_state_connected);
412     break;
413     case laddr_type_bnet:
414     { /* add a timer to close stale connections */
415     int delay;
416     t_timer_data data;
417    
418     data.p = NULL;
419     delay = prefs_get_initkill_timer();
420     if (delay) timerlist_add_timer(c,time(NULL)+delay,conn_shutdown,data);
421     }
422     default:
423     /* We have to wait for an initial "magic" byte on bnet connections to
424     * tell us exactly what connection class we are dealing with.
425     */
426     break;
427     }
428     }
429    
430     return 0;
431     }
432    
433    
434     static int sd_udpinput(t_addr * const curr_laddr, t_laddr_info const * laddr_info, int ssocket, int usocket)
435     {
436     int err;
437     psock_t_socklen errlen;
438     t_packet * upacket;
439    
440     err = 0;
441     errlen = sizeof(err);
442     if (psock_getsockopt(usocket,PSOCK_SOL_SOCKET,PSOCK_SO_ERROR,&err,&errlen)<0)
443     {
444     eventlog(eventlog_level_error,__FUNCTION__,"[%d] unable to read socket error (psock_getsockopt: %s)",usocket,pstrerror(psock_errno()));
445     return -1;
446     }
447     if (errlen && err) /* if it was an error, there is no packet to read */
448     {
449     eventlog(eventlog_level_error,__FUNCTION__,"[%d] async UDP socket error notification (psock_getsockopt: %s)",usocket,pstrerror(err));
450     return -1;
451     }
452     if (!(upacket = packet_create(packet_class_udp)))
453     {
454     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input");
455     return -1;
456     }
457    
458     {
459     struct sockaddr_in fromaddr;
460     psock_t_socklen fromlen;
461     int len;
462    
463     fromlen = sizeof(fromaddr);
464     if ((len = psock_recvfrom(usocket,packet_get_raw_data_build(upacket,0),MAX_PACKET_SIZE,0,(struct sockaddr *)&fromaddr,&fromlen))<0)
465     {
466     if (
467     #ifdef PSOCK_EINTR
468     psock_errno()!=PSOCK_EINTR &&
469     #endif
470     #ifdef PSOCK_EAGAIN
471     psock_errno()!=PSOCK_EAGAIN &&
472     #endif
473     #ifdef PSOCK_EWOULDBLOCK
474     psock_errno()!=PSOCK_EWOULDBLOCK &&
475     #endif
476     #ifdef PSOCK_ECONNRESET
477     psock_errno()!=PSOCK_ECONNRESET && // this is a win2k/winxp issue
478     // their socket implementation returns this value
479     // although it shouldn't
480     #endif
481     1)
482     eventlog(eventlog_level_error,__FUNCTION__,"could not recv UDP datagram (psock_recvfrom: %s)",pstrerror(psock_errno()));
483     packet_del_ref(upacket);
484     return -1;
485     }
486    
487     if (fromaddr.sin_family!=PSOCK_AF_INET)
488     {
489     eventlog(eventlog_level_error,__FUNCTION__,"got UDP datagram with bad address family %d",(int)fromaddr.sin_family);
490     packet_del_ref(upacket);
491     return -1;
492     }
493    
494     packet_set_size(upacket,len);
495    
496     if (hexstrm)
497     {
498     char tempa[32];
499    
500     if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa)))
501     strcpy(tempa,"x.x.x.x:x");
502     fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] from=%s to=%s length=%u\n",
503     usocket,
504     packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket),
505     packet_get_type_str(upacket,packet_dir_from_client),packet_get_type(upacket),
506     addr_num_to_addr_str(ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port)),
507     tempa,
508     packet_get_size(upacket));
509     hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket));
510     }
511    
512     handle_udp_packet(usocket,ntohl(fromaddr.sin_addr.s_addr),ntohs(fromaddr.sin_port),upacket);
513     packet_del_ref(upacket);
514     }
515    
516     return 0;
517     }
518    
519    
520     static int sd_tcpinput(t_connection * c)
521     {
522     unsigned int currsize;
523     t_packet * packet;
524     int csocket = conn_get_socket(c);
525    
526     currsize = conn_get_in_size(c);
527    
528     if (!conn_get_in_queue(c))
529     {
530     switch (conn_get_class(c))
531     {
532     case conn_class_init:
533     if (!(packet = packet_create(packet_class_init)))
534     {
535     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate init packet for input");
536     return -1;
537     }
538     break;
539     case conn_class_d2cs_bnetd:
540     if (!(packet = packet_create(packet_class_d2cs_bnetd)))
541     {
542     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate d2cs_bnetd packet");
543     return -1;
544     }
545     break;
546     case conn_class_bnet:
547     if (!(packet = packet_create(packet_class_bnet)))
548     {
549     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate bnet packet for input");
550     return -1;
551     }
552     break;
553     case conn_class_file:
554     switch(conn_get_state(c)) {
555     case conn_state_pending_raw:
556     if (!(packet = packet_create(packet_class_raw)))
557     {
558     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input");
559     return -1;
560     }
561     packet_set_size(packet, sizeof(t_client_file_req3));
562     break;
563     default:
564     if (!(packet = packet_create(packet_class_file)))
565     {
566     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate file packet for input");
567     return -1;
568     }
569     break;
570     }
571     break;
572     case conn_class_bot:
573     case conn_class_irc:
574     case conn_class_telnet:
575     if (!(packet = packet_create(packet_class_raw)))
576     {
577     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate raw packet for input");
578     return -1;
579     }
580     packet_set_size(packet,1); /* start by only reading one char */
581     break;
582     case conn_class_w3route:
583     if (!(packet = packet_create(packet_class_w3route)))
584     {
585     eventlog(eventlog_level_error,__FUNCTION__,"could not allocate w3route packet for input");
586     return -1;
587     }
588     break;
589    
590     default:
591     eventlog(eventlog_level_error,__FUNCTION__,"[%d] connection has bad class (closing connection)",conn_get_socket(c));
592     // [quetzal] 20020808 - marking connection as "destroyed", memory will be freed later
593     conn_set_state(c, conn_state_destroy);
594     return -2;
595     }
596     conn_put_in_queue(c,packet);
597     currsize = 0;
598     }
599    
600     packet = conn_get_in_queue(c);
601     switch (net_recv_packet(csocket,packet,&currsize))
602     {
603     case -1:
604     eventlog(eventlog_level_debug,__FUNCTION__,"[%d] read FAILED (closing connection)",conn_get_socket(c));
605     // [quetzal] 20020808 - marking connection as "destroyed", memory will be freed later
606     conn_set_state(c, conn_state_destroy);
607     return -2;
608    
609     case 0: /* still working on it */
610     /* eventlog(eventlog_level_debug,__FUNCTION__,"[%d] still reading \"%s\" packet (%u of %u bytes so far)",conn_get_socket(c),packet_get_class_str(packet),conn_get_in_size(c),packet_get_size(packet)); */
611     conn_set_in_size(c,currsize);
612     break;
613    
614     case 1: /* done reading */
615     switch (conn_get_class(c))
616     {
617     case conn_class_bot:
618     case conn_class_telnet:
619     if (currsize<MAX_PACKET_SIZE) /* if we overflow, we can't wait for the end of the line.
620     handle_*_packet() should take care of it */
621     {
622     char const * const temp=packet_get_raw_data_const(packet,0);
623    
624     if ((temp[currsize-1]=='\003')||(temp[currsize-1]=='\004')) {
625     /* we have to ignore these special characters, since
626     * some bots even send them after login (eg. UltimateBot)
627     */
628     currsize--;
629     break;
630     }
631    
632     if (temp[currsize-1]!='\r' && temp[currsize-1]!='\n')
633     {
634     conn_set_in_size(c,currsize);
635     packet_set_size(packet,currsize+1);
636     break; /* no end of line, get another char */
637     }
638     }
639     /* got a complete line or overflow... fall through */
640    
641     default:
642     conn_put_in_queue(c,NULL);
643    
644     if (hexstrm)
645     {
646     fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] length=%u\n",
647     csocket,
648     packet_get_class_str(packet),(unsigned int)packet_get_class(packet),
649     packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet),
650     packet_get_size(packet));
651     hexdump(hexstrm,packet_get_raw_data_const(packet,0),packet_get_size(packet));
652     }
653    
654     if (conn_get_class(c)==conn_class_bot ||
655     conn_get_class(c)==conn_class_telnet) /* NUL terminate the line to make life easier */
656     {
657     char * const temp=packet_get_raw_data(packet,0);
658    
659     if (temp[currsize-1]=='\r' || temp[currsize-1]=='\n')
660     temp[currsize-1] = '\0'; /* have to do it here instead of above so everything
661     is intact for the hexdump */
662     }
663    
664     {
665     int ret;
666    
667     switch (conn_get_class(c))
668     {
669     case conn_class_init:
670     ret = handle_init_packet(c,packet);
671     break;
672     case conn_class_bnet:
673     ret = handle_bnet_packet(c,packet);
674     break;
675     case conn_class_d2cs_bnetd:
676     ret = handle_d2cs_packet(c,packet);
677     break;
678     case conn_class_bot:
679     ret = handle_bot_packet(c,packet);
680     break;
681     case conn_class_telnet:
682     ret = handle_telnet_packet(c,packet);
683     break;
684     case conn_class_file:
685     ret = handle_file_packet(c,packet);
686     break;
687     case conn_class_irc:
688     ret = handle_irc_packet(c,packet);
689     break;
690     case conn_class_w3route:
691     ret = handle_w3route_packet(c,packet);
692     break;
693     default:
694     eventlog(eventlog_level_error,__FUNCTION__,"[%d] bad packet class %d (closing connection)",conn_get_socket(c),(int)packet_get_class(packet));
695     ret = -1;
696     }
697     packet_del_ref(packet);
698     if (ret<0)
699     {
700     // [quetzal] 20020808 - marking connection as "destroyed", memory will be freed later
701     conn_set_state(c, conn_state_destroy);
702     return -2;
703     }
704     }
705    
706     conn_set_in_size(c,0);
707     }
708     }
709    
710     return 0;
711     }
712    
713    
714     static int sd_tcpoutput(t_connection * c)
715     {
716     unsigned int currsize;
717     unsigned int totsize;
718     t_packet * packet;
719     int csocket = conn_get_socket(c);
720    
721     totsize = 0;
722     for (;;)
723     {
724     currsize = conn_get_out_size(c);
725    
726     if ((packet = conn_peek_outqueue(c)) == NULL)
727     return -2;
728    
729     switch (net_send_packet(csocket,packet,&currsize)) /* avoid warning */
730     {
731     case -1:
732     // [quetzal] 20020808 - marking connection as "destroyed", memory will be freed later
733     conn_set_state(c, conn_state_destroy);
734     return -2;
735    
736     case 0: /* still working on it */
737     conn_set_out_size(c,currsize);
738     return 0; /* bail out */
739    
740     case 1: /* done sending */
741     if (hexstrm)
742     {
743     fprintf(hexstrm,"%d: send class=%s[0x%02x] type=%s[0x%04x] length=%u\n",
744     csocket,
745     packet_get_class_str(packet),(unsigned int)packet_get_class(packet),
746     packet_get_type_str(packet,packet_dir_from_server),packet_get_type(packet),
747     packet_get_size(packet));
748     hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet));
749     }
750    
751     packet = conn_pull_outqueue(c);
752     packet_del_ref(packet);
753     conn_set_out_size(c,0);
754    
755     /* stop at about BNETD_MAX_OUTBURST (or until out of packets or EWOULDBLOCK) */
756     if (totsize>BNETD_MAX_OUTBURST || !conn_peek_outqueue(c))
757     return 0;
758     totsize += currsize;
759     break;
760     }
761     }
762    
763     /* not reached */
764     }
765    
766     void server_check_and_fix_name(char const * sname)
767     {
768     int ok = 1;
769     char * tn = (char *)sname;
770     char * sn = (char *)sname;
771    
772     if (!isalnum((int)*sn))
773     {
774     eventlog(eventlog_level_error,__FUNCTION__,"servername contains invalid first symbol (must be alphanumeric)");
775     *tn='a';
776     }
777     tn++;
778     sn++;
779    
780     for (;*sn!='\0';sn++)
781     {
782     if (isalnum((int)*sn) || *sn=='-' || *sn=='.')
783     {
784     *tn=*sn;
785     tn++;
786     }
787     else
788     ok = 0;
789     }
790     *tn='\0';
791    
792     if (!ok)
793     eventlog(eventlog_level_error,__FUNCTION__,"servername contains invalid symbol(s) (must be alphanumeric, '-' or '.') - skipped those symbols");
794     }
795    
796     extern void server_set_name(void)
797     {
798     char temp[250];
799     char const * sn;
800     #ifdef HAVE_GETHOSTBYNAME
801     struct hostent * hp;
802     #endif
803    
804     if (server_name) {
805     xfree((void *)server_name); /* avoid warning */
806     server_name = NULL;
807     }
808    
809     sn = prefs_get_servername();
810     if ((!sn)||(sn[0]=='\0')) {
811     if (gethostname(temp,sizeof(temp))<0) {
812     #ifdef WIN32
813     sprintf(temp,"localhost");
814     #else
815     eventlog(eventlog_level_error,__FUNCTION__,"could not get hostname: %s",pstrerror(errno));
816     return;
817     #endif
818     }
819     #ifdef HAVE_GETHOSTBYNAME
820     hp = gethostbyname(temp);
821     if (!hp || !hp->h_name) {
822     #endif
823     server_name = xstrdup(temp);
824     #ifdef HAVE_GETHOSTBYNAME
825     } else {
826     int i=0;
827    
828     if (strchr(hp->h_name,'.'))
829     /* Default name is already a FQDN */
830     server_name = xstrdup(hp->h_name);
831     /* ... if not we have to examine the aliases */
832     while (!server_name && hp->h_aliases && hp->h_aliases[i]) {
833     if (strchr(hp->h_aliases[i],'.'))
834     server_name = xstrdup(hp->h_aliases[i]);
835     i++;
836     }
837     if (!server_name)
838     /* Fall back to default name which might not be a FQDN */
839     server_name = xstrdup(hp->h_name);
840     }
841     #endif
842     } else {
843     server_name = xstrdup(sn);
844     }
845     server_check_and_fix_name(server_name);
846     eventlog(eventlog_level_info,__FUNCTION__,"set servername to \"%s\"",server_name);
847     }
848    
849     extern char const * server_get_name(void)
850     {
851     if (!server_name)
852     return "(null)"; /* avoid crashes */
853     else
854     return server_name;
855     }
856    
857    
858     extern void server_clear_name(void)
859     {
860     if (server_name) {
861     xfree((void *)server_name); /* avoid warning */
862     server_name = NULL;
863     }
864     }
865    
866    
867     static int handle_accept(void *data, t_fdwatch_type rw)
868     {
869     t_laddr_info *laddr_info = addr_get_data((t_addr *)data).p;
870    
871     return sd_accept((t_addr *)data, laddr_info, laddr_info->ssocket, laddr_info->usocket);
872     }
873    
874    
875     static int handle_udp(void *data, t_fdwatch_type rw)
876     {
877     t_laddr_info *laddr_info = addr_get_data((t_addr *)data).p;
878    
879     return sd_udpinput((t_addr *)data, laddr_info, laddr_info->ssocket, laddr_info->usocket);
880     }
881    
882    
883     static int handle_tcp(void *data, t_fdwatch_type rw)
884     {
885     switch(rw) {
886     case fdwatch_type_read: return sd_tcpinput((t_connection *)data);
887     case fdwatch_type_write: return sd_tcpoutput((t_connection *)data);
888     default:
889     return -1;
890     }
891     }
892    
893    
894     static int _setup_add_addrs(t_addrlist **pladdrs, const char *str, unsigned int defaddr, unsigned short defport, t_laddr_type type)
895     {
896     t_addr * curr_laddr;
897     t_addr_data laddr_data;
898     t_laddr_info * laddr_info;
899     t_elem const * acurr;
900    
901     if (*pladdrs == NULL) {
902     *pladdrs = addrlist_create(str, defaddr, defport);
903     if (*pladdrs == NULL) return -1;
904     } else if (addrlist_append(*pladdrs, str, defaddr, defport)) return -1;
905    
906     /* Mark all these laddrs for being classic Battle.net service */
907     LIST_TRAVERSE_CONST(*pladdrs,acurr)
908     {
909     curr_laddr = elem_get_data(acurr);
910     if (addr_get_data(curr_laddr).p)
911     continue;
912     laddr_info = xmalloc(sizeof(t_laddr_info));
913     laddr_info->usocket = -1;
914     laddr_info->ssocket = -1;
915     laddr_info->type = type;
916     laddr_data.p = laddr_info;
917     if (addr_set_data(curr_laddr,laddr_data)<0)
918     {
919     eventlog(eventlog_level_error, __FUNCTION__,"could not set address data");
920     if (laddr_info->usocket!=-1)
921     {
922     psock_close(laddr_info->usocket);
923     laddr_info->usocket = -1;
924     }
925     if (laddr_info->ssocket!=-1)
926     {
927     psock_close(laddr_info->ssocket);
928     laddr_info->ssocket = -1;
929     }
930     return -1;
931     }
932     }
933    
934     return 0;
935     }
936    
937     static int _set_reuseaddr(int sock)
938     {
939     int val = 1;
940    
941     return psock_setsockopt(sock,PSOCK_SOL_SOCKET,PSOCK_SO_REUSEADDR,&val,(psock_t_socklen)sizeof(int));
942     }
943    
944     static int _bind_socket(int sock, unsigned addr, short port)
945     {
946     struct sockaddr_in saddr;
947    
948     memset(&saddr,0,sizeof(saddr));
949     saddr.sin_family = PSOCK_AF_INET;
950     saddr.sin_port = htons(port);
951     saddr.sin_addr.s_addr = htonl(addr);
952     return psock_bind(sock,(struct sockaddr *)&saddr,(psock_t_socklen)sizeof(saddr));
953     }
954    
955     static int _setup_listensock(t_addrlist *laddrs)
956     {
957     t_addr * curr_laddr;
958     t_laddr_info * laddr_info;
959     t_elem const * acurr;
960     char tempa[32];
961     int fidx;
962    
963     LIST_TRAVERSE_CONST(laddrs,acurr)
964     {
965     curr_laddr = elem_get_data(acurr);
966     if (!(laddr_info = addr_get_data(curr_laddr).p))
967     {
968     eventlog(eventlog_level_error, __FUNCTION__, "NULL address info");
969     goto err;
970     }
971    
972     if (!addr_get_addr_str(curr_laddr,tempa,sizeof(tempa)))
973     strcpy(tempa,"x.x.x.x:x");
974    
975     laddr_info->ssocket = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP);
976     if (laddr_info->ssocket<0)
977     {
978     eventlog(eventlog_level_error, __FUNCTION__, "could not create a %s listening socket (psock_socket: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno()));
979     goto err;
980     }
981    
982     if (_set_reuseaddr(laddr_info->ssocket)<0)
983     eventlog(eventlog_level_error,__FUNCTION__,"could not set option SO_REUSEADDR on %s socket %d (psock_setsockopt: %s)",laddr_type_get_str(laddr_info->type),laddr_info->ssocket,pstrerror(psock_errno()));
984     /* not a fatal error... */
985    
986     if (_bind_socket(laddr_info->ssocket,addr_get_ip(curr_laddr),addr_get_port(curr_laddr))<0) {
987     eventlog(eventlog_level_error,__FUNCTION__,"could not bind %s socket to address %s TCP (psock_bind: %s)",laddr_type_get_str(laddr_info->type),tempa,pstrerror(psock_errno()));
988     goto errsock;
989     }
990    
991     /* tell socket to listen for connections */
992     if (psock_listen(laddr_info->ssocket,LISTEN_QUEUE)<0) {
993     eventlog(eventlog_level_error,__FUNCTION__,"could not set %s socket %d to listen (psock_listen: %s)",laddr_type_get_str(laddr_info->type),laddr_info->ssocket,pstrerror(psock_errno()));
994     goto errsock;
995     }
996    
997     if (psock_ctl(laddr_info->ssocket,PSOCK_NONBLOCK)<0)
998     eventlog(eventlog_level_error,__FUNCTION__,"could not set %s TCP listen socket to non-blocking mode (psock_ctl: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno()));
999    
1000     /* index not stored persisently because we dont need to refer to it later */
1001     fidx = fdwatch_add_fd(laddr_info->ssocket, fdwatch_type_read, handle_accept, curr_laddr);
1002     if (fidx < 0) {
1003     eventlog(eventlog_level_error, __FUNCTION__, "could not add listening socket %d to fdwatch pool (max sockets?)",laddr_info->ssocket);
1004     goto errsock;
1005     }
1006    
1007     eventlog(eventlog_level_info,__FUNCTION__,"listening for %s connections on %s TCP",laddr_type_get_str(laddr_info->type),tempa);
1008    
1009     if (laddr_info->type==laddr_type_bnet)
1010     {
1011     laddr_info->usocket = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_DGRAM,PSOCK_IPPROTO_UDP);
1012     if (laddr_info->usocket<0)
1013     {
1014     eventlog(eventlog_level_error,__FUNCTION__,"could not create UDP socket (psock_socket: %s)",pstrerror(psock_errno()));
1015     goto errfdw;
1016     }
1017    
1018     if (_set_reuseaddr(laddr_info->usocket)<0)
1019     eventlog(eventlog_level_error,__FUNCTION__,"could not set option SO_REUSEADDR on %s socket %d (psock_setsockopt: %s)",laddr_type_get_str(laddr_info->type),laddr_info->usocket,pstrerror(psock_errno()));
1020     /* not a fatal error... */
1021    
1022     if (_bind_socket(laddr_info->usocket,addr_get_ip(curr_laddr),addr_get_port(curr_laddr))<0) {
1023     eventlog(eventlog_level_error,__FUNCTION__,"could not bind %s socket to address %s UDP (psock_bind: %s)",laddr_type_get_str(laddr_info->type),tempa,pstrerror(psock_errno()));
1024     goto errusock;
1025     }
1026    
1027     if (psock_ctl(laddr_info->usocket,PSOCK_NONBLOCK)<0)
1028     eventlog(eventlog_level_error,__FUNCTION__,"could not set %s UDP socket to non-blocking mode (psock_ctl: %s)",laddr_type_get_str(laddr_info->type),pstrerror(psock_errno()));
1029    
1030     /* index ignored because we never need it after this */
1031     if (fdwatch_add_fd(laddr_info->usocket, fdwatch_type_read, handle_udp, curr_laddr) < 0) {
1032     eventlog(eventlog_level_error, __FUNCTION__, "could not add listening socket %d to fdwatch pool (max sockets?)",laddr_info->usocket);
1033     goto errusock;
1034     }
1035     }
1036     }
1037    
1038     return 0;
1039    
1040     errusock:
1041     psock_close(laddr_info->usocket);
1042     laddr_info->usocket = -1;
1043    
1044     errfdw:
1045     fdwatch_del_fd(fidx);
1046    
1047     errsock:
1048     psock_close(laddr_info->ssocket);
1049     laddr_info->ssocket = -1;
1050    
1051     err:
1052     return -1;
1053     }
1054    
1055     #ifdef DO_POSIXSIG
1056     static sigset_t block_set;
1057     static sigset_t save_set;
1058    
1059     static int _setup_posixsig(void)
1060     {
1061     if (sigemptyset(&save_set)<0)
1062     {
1063     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1064     return -1;
1065     }
1066     if (sigemptyset(&block_set)<0)
1067     {
1068     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1069     return -1;
1070     }
1071     if (sigaddset(&block_set,SIGINT)<0)
1072     {
1073     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1074     return -1;
1075     }
1076     if (sigaddset(&block_set,SIGHUP)<0)
1077     {
1078     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1079     return -1;
1080     }
1081     if (sigaddset(&block_set,SIGTERM)<0)
1082     {
1083     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1084     return -1;
1085     }
1086     if (sigaddset(&block_set,SIGUSR1)<0)
1087     {
1088     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1089     return -1;
1090     }
1091     if (sigaddset(&block_set,SIGUSR2)<0)
1092     {
1093     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1094     return -1;
1095     }
1096     if (sigaddset(&block_set,SIGALRM)<0)
1097     {
1098     eventlog(eventlog_level_error,__FUNCTION__,"could not add signal to set (sigemptyset: %s)",pstrerror(errno));
1099     return -1;
1100     }
1101    
1102     {
1103     struct sigaction quit_action;
1104     struct sigaction restart_action;
1105     struct sigaction save_action;
1106     struct sigaction pipe_action;
1107     #ifdef HAVE_SETITIMER
1108     struct sigaction timer_action;
1109     #endif
1110     struct sigaction forced_quit_action;
1111    
1112     quit_action.sa_handler = quit_sig_handle;
1113     if (sigemptyset(&quit_action.sa_mask)<0)
1114     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1115     quit_action.sa_flags = SA_RESTART;
1116    
1117     restart_action.sa_handler = restart_sig_handle;
1118     if (sigemptyset(&restart_action.sa_mask)<0)
1119     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1120     restart_action.sa_flags = SA_RESTART;
1121    
1122     save_action.sa_handler = save_sig_handle;
1123     if (sigemptyset(&save_action.sa_mask)<0)
1124     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1125     save_action.sa_flags = SA_RESTART;
1126    
1127     pipe_action.sa_handler = pipe_sig_handle;
1128     if (sigemptyset(&pipe_action.sa_mask)<0)
1129     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1130     pipe_action.sa_flags = SA_RESTART;
1131     #ifdef HAVE_SETITIMER
1132     timer_action.sa_handler = timer_sig_handle;
1133     if (sigemptyset(&timer_action.sa_mask)<0)
1134     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1135     timer_action.sa_flags = SA_RESTART;
1136     #endif /* HAVE_SETITIMER */
1137     forced_quit_action.sa_handler = forced_quit_sig_handle;
1138     if (sigemptyset(&forced_quit_action.sa_mask)<0)
1139     eventlog(eventlog_level_error,__FUNCTION__,"could not initialize signal set (sigemptyset: %s)",pstrerror(errno));
1140     forced_quit_action.sa_flags = SA_RESTART;
1141    
1142     if (sigaction(SIGINT,&quit_action,NULL)<0) /* control-c */
1143     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGINT signal handler (sigaction: %s)",pstrerror(errno));
1144     if (sigaction(SIGHUP,&restart_action,NULL)<0)
1145     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGHUP signal handler (sigaction: %s)",pstrerror(errno));
1146     if (sigaction(SIGTERM,&quit_action,NULL)<0)
1147     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGTERM signal handler (sigaction: %s)",pstrerror(errno));
1148     if (sigaction(SIGUSR1,&save_action,NULL)<0)
1149     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGUSR1 signal handler (sigaction: %s)",pstrerror(errno));
1150     if (sigaction(SIGPIPE,&pipe_action,NULL)<0)
1151     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGPIPE signal handler (sigaction: %s)",pstrerror(errno));
1152     #ifdef HAVE_SETITIMER
1153     /* setup asynchronus timestamp update timer */
1154     if (sigaction(SIGALRM,&timer_action,NULL)<0)
1155     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGALRM signal handler (sigaction: %s)",pstrerror(errno));
1156    
1157     {
1158     struct itimerval it;
1159    
1160     it.it_interval.tv_sec = BNETD_JIFFIES / 1000;
1161     it.it_interval.tv_usec = BNETD_JIFFIES % 1000;
1162     it.it_value.tv_sec = BNETD_JIFFIES / 1000;
1163     it.it_value.tv_usec = BNETD_JIFFIES % 1000;
1164    
1165     if (setitimer(ITIMER_REAL, &it, NULL)) {
1166     eventlog(eventlog_level_fatal, __FUNCTION__, "failed to set timers (setitimer(): %s)", pstrerror(errno));
1167     return -1;
1168     }
1169     }
1170     #endif
1171     if (sigaction(SIGQUIT,&forced_quit_action,NULL)<0) /* immediate shutdown */
1172     eventlog(eventlog_level_error,__FUNCTION__,"could not set SIGQUIT signal handler (sigaction: %s)",pstrerror(errno));
1173     }
1174    
1175     return 0;
1176     }
1177     #endif
1178    
1179     static time_t prev_exittime;
1180    
1181     static void _server_mainloop(t_addrlist *laddrs)
1182     {
1183     time_t next_savetime, next_flushtime, track_time;
1184     time_t war3_ladder_updatetime;
1185     time_t output_updatetime;
1186     unsigned int count;
1187     int savestep, flushstep;
1188    
1189     starttime = time(NULL);
1190     track_time = starttime - prefs_get_track();
1191     next_savetime = starttime + prefs_get_user_sync_timer();
1192     next_flushtime = starttime + prefs_get_user_flush_timer();
1193     war3_ladder_updatetime = starttime - prefs_get_war3_ladder_update_secs();
1194     output_updatetime = starttime - prefs_get_output_update_secs();
1195     savestep = flushstep = 0;
1196    
1197     count = 0;
1198    
1199     for (;;)
1200     {
1201     #ifdef WIN32
1202     # ifndef WIN32_GUI
1203     if (g_ServiceStatus<0 && kbhit() && getch()=='q')
1204     server_quit_wraper();
1205     # endif
1206     if (g_ServiceStatus == 0) server_quit_wraper();
1207    
1208     while (g_ServiceStatus == 2) Sleep(1000);
1209     #endif
1210    
1211     #ifdef DO_POSIXSIG
1212     if (sigprocmask(SIG_SETMASK,&save_set,NULL)<0)
1213     eventlog(eventlog_level_error,__FUNCTION__,"could not unblock signals");
1214     /* receive signals here */
1215     if (sigprocmask(SIG_SETMASK,&block_set,NULL)<0)
1216     eventlog(eventlog_level_error,__FUNCTION__,"could not block signals");
1217     #endif
1218     if (got_epipe)
1219     {
1220     got_epipe = 0;
1221     eventlog(eventlog_level_info,__FUNCTION__,"handled SIGPIPE");
1222     }
1223    
1224     #if !defined(DO_POSIXSIG) || !defined(HAVE_SETITIMER)
1225     /* if no DO_POSIXSIG or no HAVE_SETITIMER so we must read timestamp each loop */
1226     time(&now);
1227     #endif
1228     curr_exittime = sigexittime;
1229     if (curr_exittime && (curr_exittime<=now || connlist_login_get_length()<1))
1230     {
1231     eventlog(eventlog_level_info,__FUNCTION__,"the server is shutting down (%d connections left)",connlist_get_length());
1232     clanlist_save();
1233     /* no need for accountlist_save() when using "force" */
1234     accountlist_save(FS_FORCE | FS_ALL);
1235     accountlist_flush(FS_FORCE | FS_ALL);
1236     break;
1237     }
1238     if (prev_exittime!=curr_exittime)
1239     {
1240     t_message * message;
1241     char const * tstr;
1242    
1243     if (curr_exittime!=0)
1244     {
1245     char text[29+256+2+32+24+1]; /* "The ... in " + time + " (" num + " connection ...)." + NUL */
1246    
1247     tstr = seconds_to_timestr(curr_exittime-now);
1248     sprintf(text,"The server will shut down in %s (%d connections remaining).",tstr,connlist_get_length());
1249     if ((message = message_create(message_type_error,NULL,NULL,text)))
1250     {
1251     message_send_all(message);
1252     message_destroy(message);
1253     }
1254     eventlog(eventlog_level_info,__FUNCTION__,"the server will shut down in %s (%d connections remaining)",tstr,connlist_get_length());
1255     }
1256     else
1257     {
1258     if ((message = message_create(message_type_error,NULL,NULL,"Server shutdown has been canceled.")))
1259     {
1260     message_send_all(message);
1261     message_destroy(message);
1262     }
1263     eventlog(eventlog_level_info,__FUNCTION__,"server shutdown canceled");
1264     }
1265     }
1266     prev_exittime = curr_exittime;
1267    
1268     if (next_savetime <=now)
1269     {
1270     if (!savestep) { /* do this stuff only first step of save */
1271     clanlist_save();
1272     gamelist_check_voidgame();
1273     }
1274     savestep = accountlist_save(FS_NONE);
1275    
1276     if (!savestep) /* saving finished */
1277     next_savetime += prefs_get_user_sync_timer();
1278     }
1279    
1280     if (next_flushtime <=now)
1281     {
1282     if (!flushstep) { /* do this stuff only first step of save */
1283     clanlist_save();
1284     gamelist_check_voidgame();
1285     }
1286     flushstep = accountlist_flush(FS_NONE);
1287    
1288     if (!flushstep) /* flushing finished */
1289     next_flushtime += prefs_get_user_flush_timer();
1290     }
1291    
1292     if (prefs_get_track() && track_time+(time_t)prefs_get_track()<=now)
1293     {
1294     track_time = now;
1295     tracker_send_report(laddrs);
1296     }
1297    
1298     if (prefs_get_war3_ladder_update_secs() && war3_ladder_updatetime+(time_t)prefs_get_war3_ladder_update_secs()<=now)
1299     {
1300     war3_ladder_updatetime = now;
1301     ladders_write_to_file();
1302     }
1303    
1304     if (prefs_get_output_update_secs() && output_updatetime+(time_t)prefs_get_output_update_secs()<=now)
1305     {
1306     output_updatetime = now;
1307     output_write_to_file();
1308     }
1309    
1310    
1311     if (do_save)
1312     {
1313     eventlog(eventlog_level_info,__FUNCTION__,"saving accounts due to signal");
1314     clanlist_save();
1315    
1316     savestep = accountlist_save(FS_NONE);
1317     if (!savestep) /* saving finished */
1318     next_savetime += prefs_get_user_sync_timer();
1319    
1320     do_save = 0;
1321     }
1322    
1323     if (do_restart)
1324     {
1325     eventlog(eventlog_level_info,__FUNCTION__,"reading configuration files");
1326     if (preffile)
1327     {
1328     if (prefs_load(preffile)<0)
1329     eventlog(eventlog_level_error,__FUNCTION__,"could not parse configuration file");
1330     }
1331     else
1332     if (prefs_load(BNETD_DEFAULT_CONF_FILE)<0)
1333     eventlog(eventlog_level_error,__FUNCTION__,"using default configuration");
1334    
1335     if (eventlog_open(prefs_get_logfile())<0)
1336     eventlog(eventlog_level_error,__FUNCTION__,"could not use the file \"%s\" for the eventlog",prefs_get_logfile());
1337    
1338     /* FIXME: load new network settings */
1339    
1340     /* reload server name */
1341     server_set_name();
1342    
1343     accountlist_load_default(); /* FIXME: free old one */
1344     /* Dizzy: disabled for the moment, lets see who really needs it,
1345     also it can be the cause for a lot of problems
1346     accountlist_reload(); */
1347    
1348     channellist_reload();
1349    
1350     if (realmlist_reload(prefs_get_realmfile())<0)
1351     eventlog(eventlog_level_error,__FUNCTION__,"could not reload realm list");
1352    
1353     autoupdate_unload();
1354     if (autoupdate_load(prefs_get_mpqfile())<0)
1355     eventlog(eventlog_level_error,__FUNCTION__,"could not load autoupdate list");
1356    
1357     news_unload();
1358     if (news_load(prefs_get_newsfile())<0)
1359     eventlog(eventlog_level_error,__FUNCTION__,"could not load news list");
1360    
1361     versioncheck_unload();
1362     if (versioncheck_load(prefs_get_versioncheck_file())<0)
1363     eventlog(eventlog_level_error,__FUNCTION__,"could not load versioncheck list");
1364    
1365     if (ipbanlist_destroy()<0)
1366     eventlog(eventlog_level_error,__FUNCTION__,"could not unload old IP ban list");
1367     ipbanlist_create();
1368     if (ipbanlist_load(prefs_get_ipbanfile())<0)
1369     eventlog(eventlog_level_error,__FUNCTION__,"could not load new IP ban list");
1370    
1371     helpfile_unload();
1372     if (helpfile_init(prefs_get_helpfile())<0)
1373     eventlog(eventlog_level_error,__FUNCTION__,"could not load the helpfile");
1374    
1375     if (adbannerlist_destroy()<0)
1376     eventlog(eventlog_level_error,__FUNCTION__,"could not unload old adbanner list");
1377     if (adbannerlist_create(prefs_get_adfile())<0)
1378     eventlog(eventlog_level_error,__FUNCTION__,"could not load new adbanner list");
1379    
1380     ladder_reload_conf();
1381    
1382     if (prefs_get_track())
1383     tracker_set_servers(prefs_get_trackserv_addrs());
1384     if (command_groups_reload(prefs_get_command_groups_file())<0)
1385     eventlog(eventlog_level_error,__FUNCTION__,"could not load new command_groups list");
1386    
1387     aliasfile_unload();
1388     aliasfile_load(prefs_get_aliasfile());
1389    
1390     if(trans_reload(prefs_get_transfile(),TRANS_BNETD)<0)
1391     eventlog(eventlog_level_error,__FUNCTION__,"could not reload trans list");
1392    
1393     tournament_reload(prefs_get_tournament_file());
1394    
1395     anongame_infos_unload();
1396     anongame_infos_load(prefs_get_anongame_infos_file());
1397    
1398     topiclist_unload();
1399     if (topiclist_load(prefs_get_topicfile())<0)
1400     eventlog(eventlog_level_error,__FUNCTION__,"could not load new topic list");
1401    
1402     eventlog(eventlog_level_info,__FUNCTION__,"done reconfiguring");
1403    
1404     do_restart = 0;
1405     }
1406    
1407     count += BNETD_POLL_INTERVAL;
1408     if (count>=1000) /* only check timers once a second */
1409     {
1410     timerlist_check_timers(now);
1411     count = 0;
1412     }
1413    
1414     /* no need to populate the fdwatch structures as they are populated on the fly
1415     * by sd_accept, conn_push_outqueue, conn_pull_outqueue, conn_destory */
1416    
1417     /* find which sockets need servicing */
1418     switch (fdwatch(BNETD_POLL_INTERVAL))
1419     {
1420     case -1: /* error */
1421     if (
1422     #ifdef PSOCK_EINTR
1423     psock_errno()!=PSOCK_EINTR &&
1424     #endif
1425     1)
1426     eventlog(eventlog_level_error,__FUNCTION__,"fdwatch() failed (errno: %s)",pstrerror(psock_errno()));
1427     case 0: /* timeout... no sockets need checking */
1428     continue;
1429     }
1430    
1431     /* cycle through the ready sockets and handle them */
1432     fdwatch_handle();
1433    
1434     /* reap dead connections */
1435     connlist_reap();
1436     }
1437     }
1438    
1439    
1440     static void _shutdown_conns(void)
1441     {
1442     t_elem *ccurr;
1443     t_connection *c;
1444    
1445     LIST_TRAVERSE(connlist(),ccurr)
1446     {
1447     c = (t_connection *)elem_get_data(ccurr);
1448     conn_destroy(c,&ccurr,DESTROY_FROM_CONNLIST);
1449     }
1450     }
1451    
1452    
1453     static void _shutdown_addrs(t_addrlist *laddrs)
1454     {
1455     t_addr * curr_laddr;
1456     t_laddr_info * laddr_info;
1457     t_elem const * acurr;
1458    
1459     LIST_TRAVERSE_CONST(laddrs,acurr)
1460     {
1461     curr_laddr = elem_get_data(acurr);
1462     if ((laddr_info = addr_get_data(curr_laddr).p))
1463     {
1464     if (laddr_info->usocket!=-1)
1465     psock_close(laddr_info->usocket);
1466     if (laddr_info->ssocket!=-1)
1467     psock_close(laddr_info->ssocket);
1468     xfree(laddr_info);
1469     }
1470     }
1471     addrlist_destroy(laddrs);
1472     }
1473    
1474     extern int server_process(void)
1475     {
1476     t_addrlist * laddrs;
1477    
1478     laddrs = NULL;
1479     /* Start with the Battle.net address list */
1480     if (_setup_add_addrs(&laddrs, prefs_get_bnetdserv_addrs(),INADDR_ANY,BNETD_SERV_PORT,laddr_type_bnet))
1481     {
1482     eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_bnet),prefs_get_bnetdserv_addrs());
1483     return -1;
1484     }
1485    
1486     /* Append list of addresses to listen for IRC connections */
1487     if (_setup_add_addrs(&laddrs, prefs_get_irc_addrs(),INADDR_ANY,BNETD_IRC_PORT, laddr_type_irc))
1488     {
1489     eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_irc),prefs_get_irc_addrs());
1490     _shutdown_addrs(laddrs);
1491     return -1;
1492     }
1493    
1494     /* Append list of addresses to listen for W3ROUTE connections */
1495     if (_setup_add_addrs(&laddrs,prefs_get_w3route_addr(),INADDR_ANY,BNETD_W3ROUTE_PORT, laddr_type_w3route))
1496     {
1497     eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_w3route),prefs_get_w3route_addr());
1498     _shutdown_addrs(laddrs);
1499     return -1;
1500     }
1501    
1502     /* Append list of addresses to listen for telnet connections */
1503     if (_setup_add_addrs(&laddrs,prefs_get_telnet_addrs(),INADDR_ANY,BNETD_TELNET_PORT,laddr_type_telnet))
1504     {
1505     eventlog(eventlog_level_error,__FUNCTION__,"could not create %s server address list from \"%s\"",laddr_type_get_str(laddr_type_telnet),prefs_get_telnet_addrs());
1506     _shutdown_addrs(laddrs);
1507     return -1;
1508     }
1509    
1510     if (_setup_listensock(laddrs)) {
1511     _shutdown_addrs(laddrs);
1512     return -1;
1513     }
1514    
1515     /* setup signal handlers */
1516     prev_exittime = sigexittime;
1517     #ifdef DO_POSIXSIG
1518     _setup_posixsig();
1519     #endif
1520    
1521     _server_mainloop(laddrs);
1522    
1523     /* cleanup for server shutdown */
1524     _shutdown_conns();
1525     _shutdown_addrs(laddrs);
1526    
1527     return 0;
1528     }

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