/[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.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:38 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) 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     #include "serverqueue.h"
85     #include "common/fdwatch.h"
86     #include "server.h"
87     #include "prefs.h"
88     #include "d2ladder.h"
89     #ifndef WIN32
90     #include "handle_signal.h"
91     #endif
92     #include "common/addr.h"
93     #include "common/list.h"
94     #include "common/hashtable.h"
95     #include "common/eventlog.h"
96     #ifdef WIN32
97     # include <conio.h> /* for kbhit() and getch() */
98     #endif
99     #include "common/setup_after.h"
100    
101     static int server_listen(void);
102     static int server_accept(int sock);
103     static int server_handle_timed_event(void);
104     static int server_handle_socket(void);
105     static int server_loop(void);
106     static int server_cleanup(void);
107    
108     t_addrlist * server_listen_addrs;
109     extern int g_ServiceStatus;
110    
111     static int server_listen(void)
112     {
113     t_addr * curr_laddr;
114     t_addr_data laddr_data;
115     int sock;
116    
117     if (!(server_listen_addrs=addrlist_create(prefs_get_servaddrs(),INADDR_ANY,D2CS_SERVER_PORT))) {
118     eventlog(eventlog_level_error,__FUNCTION__,"error create listening address list");
119     return -1;
120     }
121     BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr)
122     {
123     sock=net_listen(addr_get_ip(curr_laddr),addr_get_port(curr_laddr),PSOCK_SOCK_STREAM);
124     if (sock<0) {
125     eventlog(eventlog_level_error,__FUNCTION__,"error listen socket");
126     return -1;
127     }
128    
129     if (psock_ctl(sock,PSOCK_NONBLOCK)<0) {
130     eventlog(eventlog_level_error,__FUNCTION__,"error set listen socket in non-blocking mode");
131     }
132    
133     laddr_data.i = sock;
134     addr_set_data(curr_laddr,laddr_data);
135    
136     if (fdwatch_add_fd(sock, fdwatch_type_read, d2cs_server_handle_accept, curr_laddr)<0) {
137     eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",sock);
138     psock_close(sock);
139     return -1;
140     }
141    
142     eventlog(eventlog_level_info,__FUNCTION__,"listen on %s", addr_num_to_addr_str(addr_get_ip(curr_laddr),addr_get_port(curr_laddr)));
143     }
144     END_LIST_TRAVERSE_DATA()
145     return 0;
146     }
147    
148     static int server_accept(int sock)
149     {
150     int csock;
151     struct sockaddr_in caddr, raddr;
152     psock_t_socklen caddr_len, raddr_len;
153     int val;
154     unsigned int ip;
155     unsigned short port;
156     t_connection *cc;
157    
158     caddr_len=sizeof(caddr);
159     memset(&caddr,0,sizeof(caddr));
160     csock=psock_accept(sock,(struct sockaddr *)&caddr,&caddr_len);
161     if (csock<0) {
162     eventlog(eventlog_level_error,__FUNCTION__,"error accept new connection");
163     return -1;
164     } else eventlog(eventlog_level_info,__FUNCTION__,"accept connection from %s",inet_ntoa(caddr.sin_addr));
165    
166     val=1;
167     if (psock_setsockopt(csock, PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &val,sizeof(val))<0) {
168     eventlog(eventlog_level_warn,__FUNCTION__,"error set sock option keep alive");
169     }
170     if (psock_ctl(csock, PSOCK_NONBLOCK)<0) {
171     eventlog(eventlog_level_error,__FUNCTION__,"error set socket to non-blocking mode");
172     psock_close(csock);
173     return -1;
174     }
175    
176     raddr_len=sizeof(raddr);
177     memset(&raddr,0,sizeof(raddr));
178     ip=port=0;
179     if (psock_getsockname(csock,(struct sockaddr *)&raddr,&raddr_len)<0) {
180     eventlog(eventlog_level_warn,__FUNCTION__,"unable to get local socket info");
181     } else {
182     if (raddr.sin_family!=PSOCK_AF_INET) {
183     eventlog(eventlog_level_warn,__FUNCTION__,"got bad socket family %d",raddr.sin_family);
184     } else {
185     ip=ntohl(raddr.sin_addr.s_addr);
186     port=ntohs(raddr.sin_port);
187     }
188     }
189     if (!(cc = d2cs_conn_create(csock,ip,port,ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)))) {
190     eventlog(eventlog_level_error,__FUNCTION__,"error create new connection");
191     psock_close(csock);
192     return -1;
193     }
194     if (conn_add_fd(cc, fdwatch_type_read, d2cs_server_handle_tcp)<0) {
195     eventlog(eventlog_level_error,__FUNCTION__,"error adding socket %d to fdwatch pool (max sockets?)",csock);
196     d2cs_conn_set_state(cc,conn_state_destroy);
197     return -1;
198     }
199    
200     return 0;
201     }
202    
203     static int server_handle_timed_event(void)
204     {
205     static time_t prev_list_purgetime=0;
206     static time_t prev_gamequeue_checktime=0;
207     static time_t prev_s2s_checktime=0;
208     static time_t prev_sq_checktime=0;
209     static time_t prev_d2ladder_refresh_time=0;
210     static time_t prev_s2s_keepalive_time=0;
211     static time_t prev_timeout_checktime;
212     time_t now;
213    
214     now=time(NULL);
215     if (now-prev_list_purgetime>(signed)prefs_get_list_purgeinterval()) {
216     hashtable_purge(d2cs_connlist());
217     d2cs_gamelist_check_voidgame();
218     prev_list_purgetime=now;
219     }
220     if (now-prev_gamequeue_checktime>(signed)prefs_get_gamequeue_checkinterval()) {
221     gqlist_update_all_clients();
222     prev_gamequeue_checktime=now;
223     }
224     if (now-prev_s2s_checktime>(signed)prefs_get_s2s_retryinterval()) {
225     s2s_check();
226     prev_s2s_checktime=now;
227     }
228     if (now-prev_sq_checktime>(signed)prefs_get_sq_checkinterval()) {
229     sqlist_check_timeout();
230     prev_sq_checktime=now;
231     }
232     if (now-prev_d2ladder_refresh_time>(signed)prefs_get_d2ladder_refresh_interval()) {
233     d2ladder_refresh();
234     prev_d2ladder_refresh_time=now;
235     }
236     if (now-prev_s2s_keepalive_time>(signed)prefs_get_s2s_keepalive_interval()) {
237     d2gs_keepalive();
238     prev_s2s_keepalive_time=now;
239     }
240     if (now-prev_timeout_checktime>(signed)prefs_get_timeout_checkinterval()) {
241     connlist_check_timeout();
242     prev_timeout_checktime=now;
243     }
244     return 0;
245     }
246    
247     extern int d2cs_server_handle_accept(void *data, t_fdwatch_type rw)
248     {
249     int sock;
250    
251     sock = addr_get_data((t_addr *)data).i;
252     server_accept(sock);
253     return 0;
254     }
255    
256     extern int d2cs_server_handle_tcp(void *data, t_fdwatch_type rw)
257     {
258     t_connection *c = (t_connection *)data;
259    
260     if (rw & fdwatch_type_read) conn_add_socket_flag(c,SOCKET_FLAG_READ);
261     if (rw & fdwatch_type_write) conn_add_socket_flag(c,SOCKET_FLAG_WRITE);
262     if (conn_handle_socket(c)<0)
263     d2cs_conn_set_state(c, conn_state_destroy);
264    
265     return 0;
266     }
267    
268     static int server_handle_socket(void)
269     {
270     switch (fdwatch(BNETD_POLL_INTERVAL)) {
271     case -1:
272     if (
273     #ifdef PSOCK_EINTR
274     psock_errno()!=PSOCK_EINTR &&
275     #endif
276     1) {
277     eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(psock_errno()));
278     return -1;
279     }
280     /* fall through */
281     case 0:
282     return 0;
283     default:
284     break;
285     }
286    
287     fdwatch_handle();
288    
289     return 0;
290     }
291    
292     static int server_loop(void)
293     {
294     unsigned int count;
295    
296     count=0;
297     while (1) {
298    
299     #ifdef WIN32
300     if (g_ServiceStatus<0 && kbhit() && getch()=='q')
301     signal_quit_wrapper();
302     if (g_ServiceStatus == 0) signal_quit_wrapper();
303    
304     while (g_ServiceStatus == 2) Sleep(1000);
305     #endif
306    
307     if (handle_signal()<0) break;
308     if (++count>=(1000/BNETD_POLL_INTERVAL)) {
309     server_handle_timed_event();
310     count=0;
311     }
312     server_handle_socket();
313     d2cs_connlist_reap();
314     }
315     return 0;
316     }
317    
318     static int server_cleanup(void)
319     {
320     t_addr * curr_laddr;
321     int sock;
322    
323     BEGIN_LIST_TRAVERSE_DATA(server_listen_addrs,curr_laddr)
324     {
325     sock=addr_get_data(curr_laddr).i;
326     psock_close(sock);
327     }
328     END_LIST_TRAVERSE_DATA()
329     addrlist_destroy(server_listen_addrs);
330     return 0;
331     }
332    
333     extern int d2cs_server_process(void)
334     {
335     #ifndef WIN32
336     handle_signal_init();
337     #endif
338     if (psock_init()<0) {
339     eventlog(eventlog_level_error,__FUNCTION__,"failed to init network");
340     return -1;
341     }
342     eventlog(eventlog_level_info,__FUNCTION__,"network initialized");
343     if (s2s_init()<0) {
344     eventlog(eventlog_level_error,__FUNCTION__,"failed to init s2s connection");
345     return -1;
346     }
347     if (server_listen()<0) {
348     eventlog(eventlog_level_error,__FUNCTION__,"failed to setup listen socket");
349     return -1;
350     }
351     eventlog(eventlog_level_info,__FUNCTION__,"entering server loop");
352     server_loop();
353     eventlog(eventlog_level_info,__FUNCTION__,"exit from server loop,cleanup");
354     server_cleanup();
355     return 0;
356     }

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