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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Branch point for: GNU
Content type: text/x-csrc
Initial revision

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