/[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.2 - (show annotations)
Tue Jun 13 16:07:52 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
Changes since 1.1: +7 -0 lines
Content type: text/x-csrc
Antibot (for non-password protected game)

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

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