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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show 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 /*
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