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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Mon Jun 12 18:31:17 2006 UTC (19 years, 9 months ago) by sysadm
Branch: MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, HEAD
Changes since 1.1: +1 -145 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_STDDEF_H
22     # include <stddef.h>
23     #else
24     # ifndef NULL
25     # define NULL ((void *)0)
26     # endif
27     #endif
28     #ifdef STDC_HEADERS
29     # include <stdlib.h>
30     #else
31     # ifdef HAVE_MALLOC_H
32     # include <malloc.h>
33     # endif
34     #endif
35     #ifdef HAVE_STRING_H
36     # include <string.h>
37     #else
38     # ifdef HAVE_STRINGS_H
39     # include <strings.h>
40     # endif
41     #endif
42     #include "compat/strsep.h"
43     #include "compat/char_bit.h"
44     #ifdef HAVE_SYS_TYPES_H
45     # include <sys/types.h> /* needed to include netinet/in.h */
46     #endif
47     #ifdef HAVE_SYS_SOCKET_H
48     # include <sys/socket.h>
49     #endif
50     #include "compat/socket.h"
51     #ifdef HAVE_SYS_PARAM_H
52     # include <sys/param.h>
53     #endif
54     #ifdef HAVE_NETINET_IN_H
55     # include <netinet/in.h>
56     #endif
57     #include "compat/netinet_in.h"
58     #ifdef HAVE_ARPA_INET_H
59     # include <arpa/inet.h> /* FIXME: probably not needed... do some systems put types in here or something? */
60     #endif
61     #ifdef TIME_WITH_SYS_TIME
62     # include <sys/time.h>
63     # include <time.h>
64     #else
65     # ifdef HAVE_SYS_TIME_H
66     # include <sys/time.h>
67     # else
68     # include <time.h>
69     # endif
70     #endif
71     #include "compat/psock.h"
72    
73     #include "d2gs.h"
74     #include "game.h"
75     #include "net.h"
76     #include "bit.h"
77     #include "prefs.h"
78 sysadm 1.2 #include "gs_scope.h"
79 sysadm 1.1 #include "connection.h"
80     #include "common/introtate.h"
81     #include "common/addr.h"
82     #include "common/list.h"
83     #include "common/eventlog.h"
84     #include "common/xalloc.h"
85     #include "common/setup_after.h"
86    
87     static t_list * d2gslist_head=NULL;
88     static unsigned int d2gs_id=0;
89     static unsigned int total_d2gs=0;
90    
91     extern t_list * d2gslist(void)
92     {
93     return d2gslist_head;
94     }
95    
96     extern int d2gslist_create(void)
97     {
98     d2gslist_head=list_create();
99     return d2gslist_reload(prefs_get_d2gs_list());
100     }
101    
102     extern int d2gslist_reload(char const * gslist)
103     {
104     t_addrlist * gsaddrs;
105     t_d2gs * gs;
106    
107     if (!d2gslist_head) return -1;
108    
109     BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)
110     {
111     BIT_CLR_FLAG(gs->flag, D2GS_FLAG_VALID);
112     }
113     END_LIST_TRAVERSE_DATA()
114    
115     gsaddrs = addrlist_create(gslist, INADDR_ANY, 0);
116     if (gsaddrs) {
117     t_elem const *acurr;
118     t_addr * curr_laddr;
119    
120     LIST_TRAVERSE_CONST(gsaddrs, acurr)
121     {
122     curr_laddr = (t_addr*)elem_get_data(acurr);
123     if (!curr_laddr) {
124     eventlog(eventlog_level_error, __FUNCTION__, "found NULL value in gslist");
125     continue;
126     }
127     if (!(gs=d2gslist_find_gs_by_ip(addr_get_ip(curr_laddr))))
128     gs = d2gs_create(addr_num_to_ip_str(addr_get_ip(curr_laddr)));
129     if (gs) BIT_SET_FLAG(gs->flag, D2GS_FLAG_VALID);
130     }
131     addrlist_destroy(gsaddrs);
132     }
133    
134     BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)
135     {
136     if (!BIT_TST_FLAG(gs->flag, D2GS_FLAG_VALID)) {
137     d2gs_destroy(gs,&curr_elem_);
138     }
139     }
140     END_LIST_TRAVERSE_DATA()
141    
142     return 0;
143     }
144    
145     extern int d2gslist_destroy(void)
146     {
147     t_d2gs * gs;
148    
149     BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)
150     {
151     d2gs_destroy(gs,(t_elem **)&curr_elem_);
152     }
153     END_LIST_TRAVERSE_DATA_CONST()
154     d2cs_connlist_reap();
155    
156     if (list_destroy(d2gslist_head)<0) {
157     eventlog(eventlog_level_error,__FUNCTION__,"error destroy d2gs list");
158     return -1;
159     }
160     d2gslist_head=NULL;
161    
162     return 0;
163     }
164    
165     extern t_d2gs * d2gslist_find_gs_by_ip(unsigned int ip)
166     {
167     t_d2gs * gs;
168    
169     BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)
170     {
171     if (gs->ip==ip) return gs;
172     }
173     END_LIST_TRAVERSE_DATA_CONST()
174     return NULL;
175     }
176    
177     extern t_d2gs * d2gslist_find_gs(unsigned int id)
178     {
179     t_d2gs * gs;
180    
181     BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)
182     {
183     if (gs->id==id) return gs;
184     }
185     END_LIST_TRAVERSE_DATA_CONST()
186     return NULL;
187     }
188    
189     extern t_d2gs * d2gs_create(char const * ipaddr)
190     {
191     t_d2gs * gs;
192     unsigned int ip;
193    
194     ASSERT(ipaddr,NULL);
195     if ((ip=net_inet_addr(ipaddr))==~0U) {
196     eventlog(eventlog_level_error,__FUNCTION__,"got bad ip address %s",ipaddr);
197     return NULL;
198     }
199     if (d2gslist_find_gs_by_ip(ntohl(ip))) {
200     eventlog(eventlog_level_error,__FUNCTION__,"game server %s already in list",ipaddr);
201     return NULL;
202     }
203     gs=xmalloc(sizeof(t_d2gs));
204     gs->ip=ntohl(ip);
205     gs->id=++d2gs_id;
206     gs->active=0;
207     gs->token=0;
208     gs->state=d2gs_state_none;
209     gs->gamenum=0;
210     gs->maxgame=0;
211     gs->connection=NULL;
212    
213     if (list_append_data(d2gslist_head,gs)<0) {
214     eventlog(eventlog_level_error,__FUNCTION__,"error add gs to list");
215     xfree(gs);
216     return NULL;
217     }
218     eventlog(eventlog_level_info,__FUNCTION__,"added game server %s (id: %d) to list",ipaddr,gs->id);
219     return gs;
220     }
221    
222     extern int d2gs_destroy(t_d2gs * gs, t_elem ** curr)
223     {
224     ASSERT(gs,-1);
225     if (list_remove_data(d2gslist_head,gs,curr)<0) {
226     eventlog(eventlog_level_error,__FUNCTION__,"error remove gs from list");
227     return -1;
228     }
229     if (gs->active && gs->connection) {
230     d2cs_conn_set_state(gs->connection, conn_state_destroy);
231     d2gs_deactive(gs, gs->connection);
232     }
233     eventlog(eventlog_level_info,__FUNCTION__,"removed game server %s (id: %d) from list",addr_num_to_ip_str(gs->ip),gs->id);
234     xfree(gs);
235     return 0;
236     }
237    
238     extern t_d2gs * d2gslist_get_server_by_id(unsigned int id)
239     {
240     t_d2gs * gs;
241    
242     BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)
243     {
244     if (gs->id==id) return gs;
245     }
246     END_LIST_TRAVERSE_DATA_CONST()
247     return NULL;
248     }
249    
250     extern t_d2gs * d2gslist_choose_server(t_connection * c)
251     {
252     t_d2gs * gs;
253     t_d2gs * ogs;
254     unsigned int percent;
255     unsigned int min_percent=100;
256    
257     ogs=NULL;
258     BEGIN_LIST_TRAVERSE_DATA_CONST(d2gslist_head,gs)
259     {
260     if (!gs->active) continue;
261     if (!gs->connection) continue;
262     if (gs->state!=d2gs_state_authed) continue;
263     if (!gs->maxgame) continue;
264     if (gs->gamenum>=gs->maxgame) continue;
265    
266     /* Added by Leaflet at 2006-06-05 -- Begin */
267     if (serve_scope_list_validate (gs->ip, c)) continue;
268     /* End */
269    
270     percent=100*gs->gamenum/gs->maxgame;
271     if (percent<min_percent) {
272     min_percent=percent;
273     ogs=gs;
274     }
275     }
276     END_LIST_TRAVERSE_DATA_CONST()
277     return ogs;
278     }
279    
280     extern int d2gs_set_state(t_d2gs * gs, t_d2gs_state state)
281     {
282     ASSERT(gs,-1);
283     gs->state=state;
284     return 0;
285     }
286    
287     extern t_d2gs_state d2gs_get_state(t_d2gs const * gs)
288     {
289     ASSERT(gs,d2gs_state_none);
290     return gs->state;
291     }
292    
293     extern int d2gs_add_gamenum(t_d2gs * gs, int number)
294     {
295     ASSERT(gs,-1);
296     gs->gamenum += number;
297     return 0;
298     }
299    
300     extern unsigned int d2gs_get_gamenum(t_d2gs const * gs)
301     {
302     ASSERT(gs,0);
303     return gs->gamenum;
304     }
305    
306    
307     extern int d2gs_set_maxgame(t_d2gs * gs,unsigned int maxgame)
308     {
309     ASSERT(gs,-1);
310     gs->maxgame=maxgame;
311     return 0;
312     }
313    
314     extern unsigned int d2gs_get_maxgame(t_d2gs const * gs)
315     {
316     ASSERT(gs,0);
317     return gs->maxgame;
318     }
319    
320     extern unsigned int d2gs_get_id(t_d2gs const * gs)
321     {
322     ASSERT(gs,0);
323     return gs->id;
324     }
325    
326     extern unsigned int d2gs_get_ip(t_d2gs const * gs)
327     {
328     ASSERT(gs,0);
329     return gs->ip;
330     }
331    
332     extern unsigned int d2gs_get_token(t_d2gs const * gs)
333     {
334     return gs->token;
335     }
336    
337     extern unsigned int d2gs_make_token(t_d2gs * gs)
338     {
339     return ((unsigned int)rand())^((++(gs->token))+((unsigned int)time(NULL)));
340     }
341    
342     extern t_connection * d2gs_get_connection(t_d2gs const * gs)
343     {
344     ASSERT(gs,NULL);
345     return gs->connection;
346     }
347    
348     extern int d2gs_active(t_d2gs * gs, t_connection * c)
349     {
350     ASSERT(gs,-1);
351     ASSERT(c,-1);
352    
353     if (gs->active && gs->connection) {
354     eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is already actived, deactive previous connection first",gs->id);
355     d2gs_deactive(gs, gs->connection);
356     }
357     total_d2gs++;
358     eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) actived (%d total)",addr_num_to_addr_str(d2cs_conn_get_addr(c),
359     d2cs_conn_get_port(c)),gs->id,total_d2gs);
360     gs->state=d2gs_state_authed;
361     gs->connection=c;
362     gs->active=1;
363     gs->gamenum=0;
364     gs->maxgame=0;
365     return 0;
366     }
367    
368     extern int d2gs_deactive(t_d2gs * gs, t_connection * c)
369     {
370     t_game * game;
371    
372     ASSERT(gs,-1);
373     if (!gs->active || !gs->connection) {
374     eventlog(eventlog_level_warn,__FUNCTION__,"game server %d is not actived yet", gs->id);
375     return -1;
376     }
377     if (gs->connection != c) {
378     eventlog(eventlog_level_debug,__FUNCTION__,"game server %d connection mismatch,ignore it", gs->id);
379     return 0;
380     }
381     total_d2gs--;
382     eventlog(eventlog_level_info,__FUNCTION__,"game server %s (id: %d) deactived (%d left)",addr_num_to_addr_str(d2cs_conn_get_addr(gs->connection),d2cs_conn_get_port(gs->connection)),gs->id,total_d2gs);
383     gs->state=d2gs_state_none;
384     gs->connection=NULL;
385     gs->active=0;
386     gs->maxgame=0;
387     eventlog(eventlog_level_info,__FUNCTION__,"destroying all games on game server %d",gs->id);
388     BEGIN_LIST_TRAVERSE_DATA(d2cs_gamelist(),game)
389     {
390     if (game_get_d2gs(game)==gs) game_destroy(game,&curr_elem_);
391     }
392     END_LIST_TRAVERSE_DATA()
393     if (gs->gamenum!=0) {
394     eventlog(eventlog_level_error,__FUNCTION__,"game server %d deactived but still with games left",gs->id);
395     }
396     gs->gamenum=0;
397     return 0;
398     }
399    
400     extern unsigned int d2gs_calc_checksum(t_connection * c)
401     {
402     unsigned int sessionnum, checksum, port, addr;
403     unsigned int i, len, ch;
404     char const * realmname;
405     char const * password;
406    
407     ASSERT(c,0);
408     sessionnum=d2cs_conn_get_sessionnum(c);
409     checksum=prefs_get_d2gs_checksum();
410     port=d2cs_conn_get_port(c);
411     addr=d2cs_conn_get_addr(c);
412     realmname=prefs_get_realmname();
413     password=prefs_get_d2gs_password();
414    
415     len=strlen(realmname);
416     for (i=0; i<len ; i++) {
417     ch = (unsigned int)(unsigned char) realmname[i];
418     checksum ^= ROTL(sessionnum,i, sizeof(unsigned int) * CHAR_BIT);
419     checksum ^= ROTL(port , ch, sizeof(unsigned int) * CHAR_BIT);
420     }
421     len=strlen(password);
422     for (i=0; i<len ; i++) {
423     ch = (unsigned int)(unsigned char) password[i];
424     checksum ^= ROTL(sessionnum,i, sizeof(unsigned int) * CHAR_BIT);
425     checksum ^= ROTL(port , ch, sizeof(unsigned int) * CHAR_BIT);
426     }
427     checksum ^= addr;
428     return checksum;
429     }
430    
431     extern int d2gs_keepalive(void)
432     {
433     t_packet * packet;
434     t_d2gs * gs;
435    
436     if (!(packet=packet_create(packet_class_d2gs))) {
437     eventlog(eventlog_level_error,__FUNCTION__,"error creating packet");
438     return -1;
439     }
440     packet_set_size(packet,sizeof(t_d2cs_d2gs_echoreq));
441     packet_set_type(packet,D2CS_D2GS_ECHOREQ);
442     /* FIXME: sequence number not set */
443     bn_int_set(&packet->u.d2cs_d2gs.h.seqno,0);
444     BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)
445     {
446     if (gs->active && gs->connection) {
447     conn_push_outqueue(gs->connection,packet);
448     }
449     }
450     END_LIST_TRAVERSE_DATA()
451     packet_del_ref(packet);
452     return 0;
453     }
454    
455     extern int d2gs_restart_all_gs(void)
456     {
457     t_packet * packet;
458     t_d2gs * gs;
459    
460     if (!(packet=packet_create(packet_class_d2gs))) {
461     eventlog(eventlog_level_error, __FUNCTION__, "error creating packet");
462     return -1;
463     }
464     packet_set_size(packet,sizeof(t_d2cs_d2gs_control));
465     packet_set_type(packet,D2CS_D2GS_CONTROL);
466     /* FIXME: sequence number not set */
467     bn_int_set(&packet->u.d2cs_d2gs.h.seqno,0);
468     bn_int_set(&packet->u.d2cs_d2gs_control.cmd, D2CS_D2GS_CONTROL_CMD_RESTART);
469     bn_int_set(&packet->u.d2cs_d2gs_control.value, prefs_get_d2gs_restart_delay());
470    
471     BEGIN_LIST_TRAVERSE_DATA(d2gslist_head,gs)
472     {
473     if (gs->connection) {
474     conn_push_outqueue(gs->connection,packet);
475     }
476     }
477    
478     END_LIST_TRAVERSE_DATA()
479     packet_del_ref(packet);
480     return 0;
481     }
482    

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