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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Sat Jun 24 09:19:48 2006 UTC (19 years, 8 months ago) by sysadm
Branch: MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, HEAD
Changes since 1.2: +1 -0 lines
Content type: text/x-csrc
no message

1 sysadm 1.1 /*
2     * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the Free Software
16     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17     */
18     #include "common/setup_before.h"
19     #include "setup.h"
20    
21     #ifdef HAVE_STRING_H
22     # include <string.h>
23     #else
24     # ifdef HAVE_STRINGS_H
25     # include <strings.h>
26     # endif
27     # ifdef HAVE_MEMORY_H
28     # include <memory.h>
29     # endif
30     #endif
31     #ifdef STDC_HEADERS
32     # include <stdlib.h>
33     #else
34     # ifdef HAVE_MALLOC_H
35     # include <malloc.h>
36     # endif
37     #endif
38     #include "compat/memset.h"
39     #include <errno.h>
40     #include "compat/strerror.h"
41     #ifdef TIME_WITH_SYS_TIME
42     # include <time.h>
43     # include <sys/time.h>
44     #else
45     # ifdef HAVE_SYS_TIME_H
46     # include <sys/time.h>
47     # else
48     # include <time.h>
49     # endif
50     #endif
51     #ifdef HAVE_FCNTL_H
52     # include <fcntl.h>
53     #else
54     # ifdef HAVE_SYS_FILE_H
55     # include <sys/file.h>
56     # endif
57     #endif
58     #ifdef HAVE_UNISTD_H
59     # include <unistd.h>
60     #endif
61     #ifdef HAVE_SYS_SOCKET_H
62     # include <sys/socket.h>
63     #endif
64     #include "compat/psock.h"
65     #ifdef HAVE_SYS_TYPES_H
66     # include <sys/types.h>
67     #endif
68     #ifdef HAVE_NETINET_IN_H
69     # include <netinet/in.h>
70     #endif
71     #include "compat/netinet_in.h"
72     #ifdef HAVE_ARPA_INET_H
73     # include <arpa/inet.h>
74     #endif
75     #include "compat/inet_ntoa.h"
76     #include "compat/psock.h"
77    
78     #include "d2gs.h"
79     #include "net.h"
80     #include "s2s.h"
81     #include "gamequeue.h"
82     #include "game.h"
83     #include "connection.h"
84 sysadm 1.2 #include "d2charstatus.h"
85 sysadm 1.1 #include "serverqueue.h"
86     #include "common/fdwatch.h"
87     #include "server.h"
88     #include "prefs.h"
89     #include "d2ladder.h"
90     #ifndef WIN32
91     #include "handle_signal.h"
92     #endif
93     #include "common/addr.h"
94     #include "common/list.h"
95     #include "common/hashtable.h"
96     #include "common/eventlog.h"
97     #ifdef WIN32
98     # include <conio.h> /* for kbhit() and getch() */
99     #endif
100     #include "common/setup_after.h"
101 sysadm 1.3 #include "cmdline_parse.h"
102 sysadm 1.1
103     static int server_listen(void);
104     static int server_accept(int sock);
105     static int server_handle_timed_event(void);
106     static int server_handle_socket(void);
107     static int server_loop(void);
108     static int server_cleanup(void);
109    
110     t_addrlist * server_listen_addrs;
111     extern int g_ServiceStatus;
112    
113     static int server_listen(void)
114     {
115     t_addr * curr_laddr;
116     t_addr_data laddr_data;
117     int sock;
118    
119     if (!(server_listen_addrs=addrlist_create(prefs_get_servaddrs(),INADDR_ANY,D2CS_SERVER_PORT))) {
120     eventlog(eventlog_level_error,__FUNCTION__,"error create listening address list");
121     return -1;
122     }
123     BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr)
124     {
125     sock=net_listen(addr_get_ip(curr_laddr),addr_get_port(curr_laddr),PSOCK_SOCK_STREAM);
126     if (sock<0) {
127     eventlog(eventlog_level_error,__FUNCTION__,"error listen socket");
128     return -1;
129     }
130    
131     if (psock_ctl(sock,PSOCK_NONBLOCK)<0) {
132     eventlog(eventlog_level_error,__FUNCTION__,"error set listen socket in non-blocking mode");
133     }
134    
135     laddr_data.i = sock;
136     addr_set_data(curr_laddr,laddr_data);
137    
138     if (fdwatch_add_fd(sock, fdwatch_type_read, d2cs_server_handle_accept, curr_laddr)<0) {
139     eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",sock);
140     psock_close(sock);
141     return -1;
142     }
143    
144     eventlog(eventlog_level_info,__FUNCTION__,"listen on %s", addr_num_to_addr_str(addr_get_ip(curr_laddr),addr_get_port(curr_laddr)));
145     }
146     END_LIST_TRAVERSE_DATA()
147     return 0;
148     }
149    
150     static int server_accept(int sock)
151     {
152     int csock;
153     struct sockaddr_in caddr, raddr;
154     psock_t_socklen caddr_len, raddr_len;
155     int val;
156     unsigned int ip;
157     unsigned short port;
158     t_connection *cc;
159    
160     caddr_len=sizeof(caddr);
161     memset(&caddr,0,sizeof(caddr));
162     csock=psock_accept(sock,(struct sockaddr *)&caddr,&caddr_len);
163     if (csock<0) {
164     eventlog(eventlog_level_error,__FUNCTION__,"error accept new connection");
165     return -1;
166     } else eventlog(eventlog_level_info,__FUNCTION__,"accept connection from %s",inet_ntoa(caddr.sin_addr));
167    
168     val=1;
169     if (psock_setsockopt(csock, PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &val,sizeof(val))<0) {
170     eventlog(eventlog_level_warn,__FUNCTION__,"error set sock option keep alive");
171     }
172     if (psock_ctl(csock, PSOCK_NONBLOCK)<0) {
173     eventlog(eventlog_level_error,__FUNCTION__,"error set socket to non-blocking mode");
174     psock_close(csock);
175     return -1;
176     }
177    
178     raddr_len=sizeof(raddr);
179     memset(&raddr,0,sizeof(raddr));
180     ip=port=0;
181     if (psock_getsockname(csock,(struct sockaddr *)&raddr,&raddr_len)<0) {
182     eventlog(eventlog_level_warn,__FUNCTION__,"unable to get local socket info");
183     } else {
184     if (raddr.sin_family!=PSOCK_AF_INET) {
185     eventlog(eventlog_level_warn,__FUNCTION__,"got bad socket family %d",raddr.sin_family);
186     } else {
187     ip=ntohl(raddr.sin_addr.s_addr);
188     port=ntohs(raddr.sin_port);
189     }
190     }
191     if (!(cc = d2cs_conn_create(csock,ip,port,ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) {
192     eventlog(eventlog_level_error,__FUNCTION__,"error create new connection");
193     psock_close(csock);
194     return -1;
195     }
196     if (conn_add_fd(cc, fdwatch_type_read, d2cs_server_handle_tcp)<0) {
197     eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",csock);
198     d2cs_conn_set_state(cc,conn_state_destroy);
199     return -1;
200     }
201    
202     return 0;
203     }
204    
205     static int server_handle_timed_event(void)
206     {
207     static time_t prev_list_purgetime=0;
208     static time_t prev_gamequeue_checktime=0;
209     static time_t prev_s2s_checktime=0;
210     static time_t prev_sq_checktime=0;
211     static time_t prev_d2ladder_refresh_time=0;
212     static time_t prev_s2s_keepalive_time=0;
213     static time_t prev_timeout_checktime;
214 sysadm 1.2 static time_t prev_dump_charstatus_list_interval=0;
215 sysadm 1.1 time_t now;
216    
217     now=time(NULL);
218     if (now-prev_list_purgetime>(signed)prefs_get_list_purgeinterval()) {
219     hashtable_purge(d2cs_connlist());
220     d2cs_gamelist_check_voidgame();
221     prev_list_purgetime=now;
222     }
223     if (now-prev_gamequeue_checktime>(signed)prefs_get_gamequeue_checkinterval()) {
224     gqlist_update_all_clients();
225     prev_gamequeue_checktime=now;
226     }
227     if (now-prev_s2s_checktime>(signed)prefs_get_s2s_retryinterval()) {
228     s2s_check();
229     prev_s2s_checktime=now;
230     }
231     if (now-prev_sq_checktime>(signed)prefs_get_sq_checkinterval()) {
232     sqlist_check_timeout();
233     prev_sq_checktime=now;
234     }
235     if (now-prev_d2ladder_refresh_time>(signed)prefs_get_d2ladder_refresh_interval()) {
236     d2ladder_refresh();
237     prev_d2ladder_refresh_time=now;
238     }
239     if (now-prev_s2s_keepalive_time>(signed)prefs_get_s2s_keepalive_interval()) {
240     d2gs_keepalive();
241     prev_s2s_keepalive_time=now;
242     }
243     if (now-prev_timeout_checktime>(signed)prefs_get_timeout_checkinterval()) {
244     connlist_check_timeout();
245     prev_timeout_checktime=now;
246     }
247 sysadm 1.2 /* by Leaflet */
248     if (now-prev_dump_charstatus_list_interval>(signed)prefs_dump_charstatus_list_interval()) {
249     charstatus_list_dump(cmdline_get_charstatus_file());
250     prev_dump_charstatus_list_interval=now;
251     }
252 sysadm 1.1 return 0;
253     }
254    
255     extern int d2cs_server_handle_accept(void *data, t_fdwatch_type rw)
256     {
257     int sock;
258    
259     sock = addr_get_data((t_addr *)data).i;
260     server_accept(sock);
261     return 0;
262     }
263    
264     extern int d2cs_server_handle_tcp(void *data, t_fdwatch_type rw)
265     {
266     t_connection *c = (t_connection *)data;
267    
268     if (rw & fdwatch_type_read) conn_add_socket_flag(c,SOCKET_FLAG_READ);
269     if (rw & fdwatch_type_write) conn_add_socket_flag(c,SOCKET_FLAG_WRITE);
270     if (conn_handle_socket(c)<0)
271     d2cs_conn_set_state(c, conn_state_destroy);
272    
273     return 0;
274     }
275    
276     static int server_handle_socket(void)
277     {
278     switch (fdwatch(BNETD_POLL_INTERVAL)) {
279     case -1:
280     if (
281     #ifdef PSOCK_EINTR
282     psock_errno()!=PSOCK_EINTR &&
283     #endif
284     1) {
285     eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(psock_errno()));
286     return -1;
287     }
288     /* fall through */
289     case 0:
290     return 0;
291     default:
292     break;
293     }
294    
295     fdwatch_handle();
296    
297     return 0;
298     }
299    
300     static int server_loop(void)
301     {
302     unsigned int count;
303    
304     count=0;
305     while (1) {
306    
307     #ifdef WIN32
308     if (g_ServiceStatus<0 && kbhit() && getch()=='q')
309     signal_quit_wrapper();
310     if (g_ServiceStatus == 0) signal_quit_wrapper();
311    
312     while (g_ServiceStatus == 2) Sleep(1000);
313     #endif
314    
315     if (handle_signal()<0) break;
316     if (++count>=(1000/BNETD_POLL_INTERVAL)) {
317     server_handle_timed_event();
318     count=0;
319     }
320     server_handle_socket();
321     d2cs_connlist_reap();
322     }
323     return 0;
324     }
325    
326     static int server_cleanup(void)
327     {
328     t_addr * curr_laddr;
329     int sock;
330    
331     BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr)
332     {
333     sock=addr_get_data(curr_laddr).i;
334     psock_close(sock);
335     }
336     END_LIST_TRAVERSE_DATA()
337     addrlist_destroy(server_listen_addrs);
338     return 0;
339     }
340    
341     extern int d2cs_server_process(void)
342     {
343     #ifndef WIN32
344     handle_signal_init();
345     #endif
346     if (psock_init()<0) {
347     eventlog(eventlog_level_error,__FUNCTION__,"failed to init network");
348     return -1;
349     }
350     eventlog(eventlog_level_info,__FUNCTION__,"network initialized");
351     if (s2s_init()<0) {
352     eventlog(eventlog_level_error,__FUNCTION__,"failed to init s2s connection");
353     return -1;
354     }
355     if (server_listen()<0) {
356     eventlog(eventlog_level_error,__FUNCTION__,"failed to setup listen socket");
357     return -1;
358     }
359     eventlog(eventlog_level_info,__FUNCTION__,"entering server loop");
360     server_loop();
361     eventlog(eventlog_level_info,__FUNCTION__,"exit from server loop,cleanup");
362     server_cleanup();
363     return 0;
364     }

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