/[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.2 - (hide 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 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    
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 sysadm 1.2 static time_t prev_dump_charstatus_list_interval=0;
214 sysadm 1.1 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 sysadm 1.2 /* 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 sysadm 1.1 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