1 /*
2 * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu)
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 #define REALM_INTERNAL_ACCESS
19 #include "common/setup_before.h"
20 #include <stdio.h>
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/strrchr.h"
43 #include "compat/strdup.h"
44 #include "compat/strcasecmp.h"
45 #include <errno.h>
46 #include "compat/strerror.h"
47 #include "common/eventlog.h"
48 #include "common/list.h"
49 #include "common/util.h"
50 #include "common/addr.h"
51 #include "common/xalloc.h"
52 #include "connection.h"
53 #include "common/rcm.h"
54 #include "realm.h"
55 #ifdef HAVE_ASSERT_H
56 # include <assert.h>
57 #endif
58 #include "common/setup_after.h"
59
60
61 static t_list * realmlist_head=NULL;
62
63 static t_realm * realm_create(char const * name, char const * description, unsigned int ip, unsigned int port);
64 static int realm_destroy(t_realm * realm);
65
realm_create(char const * name,char const * description,unsigned int ip,unsigned int port)66 static t_realm * realm_create(char const * name, char const * description, unsigned int ip, unsigned int port)
67 {
68 t_realm * realm;
69
70 if (!name)
71 {
72 eventlog(eventlog_level_error,__FUNCTION__,"got NULL name");
73 return NULL;
74 }
75 if (!description)
76 {
77 eventlog(eventlog_level_error,__FUNCTION__,"got NULL description");
78 return NULL;
79 }
80
81 realm = xmalloc(sizeof(t_realm));
82 realm->name = NULL;
83 realm->description = NULL;
84
85 if (realm_set_name(realm ,name)<0)
86 {
87 eventlog(eventlog_level_error,__FUNCTION__,"failed to set name for realm");
88 xfree(realm);
89 return NULL;
90 }
91 if (realm->description != NULL) xfree((void *)realm->description);
92 realm->description = xstrdup(description);
93 realm->ip = ip;
94 realm->port = port;
95 realm->conn = NULL;
96 realm->active = 0;
97 realm->player_number = 0;
98 realm->game_number = 0;
99 realm->sessionnum = 0;
100 realm->tcp_sock = 0;
101 rcm_init(&realm->rcm);
102
103 eventlog(eventlog_level_info,__FUNCTION__,"created realm \"%s\"",name);
104 return realm;
105 }
106
107
realm_destroy(t_realm * realm)108 static int realm_destroy(t_realm * realm)
109 {
110 if (!realm)
111 {
112 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
113 return -1;
114 }
115
116 if (realm->active)
117 realm_deactive(realm);
118
119 xfree((void *)realm->name); /* avoid warning */
120 xfree((void *)realm->description); /* avoid warning */
121 xfree((void *)realm); /* avoid warning */
122
123 return 0;
124 }
125
126
realm_get_name(t_realm const * realm)127 extern char const * realm_get_name(t_realm const * realm)
128 {
129 if (!realm)
130 {
131 return NULL;
132 }
133 return realm->name;
134 }
135
136
realm_set_name(t_realm * realm,char const * name)137 extern int realm_set_name(t_realm * realm, char const * name)
138 {
139 char const * temp;
140 t_realm const * temprealm;
141
142 if (!realm)
143 {
144 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
145 return -1;
146 }
147
148 if (name && (temprealm=realmlist_find_realm(name)))
149 {
150 if (temprealm == realm)
151 return 0;
152 else
153 {
154 eventlog(eventlog_level_error,__FUNCTION__,"realm %s does already exist in list",name);
155 return -1;
156 }
157 }
158
159 if (name)
160 temp=xstrdup(name);
161 else
162 temp = NULL;
163
164 if (realm->name)
165 xfree((void *)realm->name); /* avoid warning */
166 realm->name = temp;
167
168 return 0;
169 }
170
171
realm_get_description(t_realm const * realm)172 extern char const * realm_get_description(t_realm const * realm)
173 {
174 if (!realm)
175 {
176 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
177 return NULL;
178 }
179 return realm->description;
180 }
181
182
realm_get_port(t_realm const * realm)183 extern unsigned short realm_get_port(t_realm const * realm)
184 {
185 if (!realm)
186 {
187 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
188 return 0;
189 }
190 return realm->port;
191 }
192
193
realm_get_ip(t_realm const * realm)194 extern unsigned int realm_get_ip(t_realm const * realm)
195 {
196 if (!realm)
197 {
198 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
199 return 0;
200 }
201 return realm->ip;
202 }
203
204
realm_get_active(t_realm const * realm)205 extern unsigned int realm_get_active(t_realm const * realm)
206 {
207 if (!realm)
208 {
209 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
210 return 0;
211 }
212 return realm->active;
213 }
214
realm_set_active(t_realm * realm,unsigned int active)215 extern int realm_set_active(t_realm * realm, unsigned int active)
216 {
217 if (!realm)
218 {
219 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
220 return -1;
221 }
222
223 realm->active=active;
224 return 0;
225 }
226
realm_get_player_number(t_realm const * realm)227 extern unsigned int realm_get_player_number(t_realm const * realm)
228 {
229 if (!realm)
230 {
231 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
232 return 0;
233 }
234 return realm->player_number;
235 }
236
realm_add_player_number(t_realm * realm,int number)237 extern int realm_add_player_number(t_realm * realm, int number)
238 {
239 if (!realm)
240 {
241 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
242 return -1;
243 }
244 realm->player_number += number;
245 return 0;
246 }
247
realm_get_game_number(t_realm const * realm)248 extern unsigned int realm_get_game_number(t_realm const * realm)
249 {
250 if (!realm)
251 {
252 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
253 return 0;
254 }
255 return realm->game_number;
256 }
257
realm_add_game_number(t_realm * realm,int number)258 extern int realm_add_game_number(t_realm * realm, int number)
259 {
260 if (!realm)
261 {
262 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
263 return -1;
264 }
265 realm->game_number += number;
266 return 0;
267 }
268
realm_active(t_realm * realm,t_connection * c)269 extern int realm_active(t_realm * realm, t_connection * c)
270 {
271 if (!realm)
272 {
273 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
274 return -1;
275 }
276 if (!c)
277 {
278 eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
279 return -1;
280 }
281 if (realm->active)
282 {
283 eventlog(eventlog_level_debug,__FUNCTION__, "realm %s is already actived,destroy previous one",realm->name);
284 realm_deactive(realm);
285 }
286 realm->active=1;
287 realm->conn=c;
288 conn_set_realm(c,realm);
289 realm->sessionnum=conn_get_sessionnum(c);
290 realm->tcp_sock=conn_get_socket(c);
291 eventlog(eventlog_level_info,__FUNCTION__, "realm %s actived",realm->name);
292 return 0;
293 }
294
realm_deactive(t_realm * realm)295 extern int realm_deactive(t_realm * realm)
296 {
297 t_connection * c;
298
299 if (!realm)
300 {
301 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
302 return -1;
303 }
304 if (!realm->active)
305 {
306 eventlog(eventlog_level_error,__FUNCTION__,"realm %s is not actived",realm->name);
307 return -1;
308 }
309 if ((c = realm_get_conn(realm)))
310 conn_set_state(c,conn_state_destroy);
311
312 realm->active=0;
313 realm->sessionnum=0;
314 realm->tcp_sock=0;
315 /*
316 realm->player_number=0;
317 realm->game_number=0;
318 */
319 eventlog(eventlog_level_info,__FUNCTION__, "realm %s deactived",realm->name);
320 return 0;
321 }
322
323
realmlist_load(char const * filename)324 t_list * realmlist_load(char const * filename)
325 {
326 FILE * fp;
327 unsigned int line;
328 unsigned int pos;
329 unsigned int len;
330 t_addr * raddr;
331 char * temp, *temp2;
332 char * buff;
333 char * name;
334 char * desc;
335 t_realm * realm;
336 t_list * list_head = NULL;
337
338 if (!filename)
339 {
340 eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
341 return NULL;
342 }
343
344 if (!(fp = fopen(filename,"r")))
345 {
346 eventlog(eventlog_level_error,__FUNCTION__,"could not open realm file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
347 return NULL;
348 }
349
350 list_head = list_create();
351
352 for (line=1; (buff = file_get_line(fp)); line++)
353 {
354 for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++);
355 if (buff[pos]=='\0' || buff[pos]=='#')
356 {
357 continue;
358 }
359 if ((temp = strrchr(buff,'#')))
360 {
361 unsigned int endpos;
362
363 *temp = '\0';
364 len = strlen(buff)+1;
365 for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--);
366 buff[endpos+1] = '\0';
367 }
368
369 /* skip any separators */
370 for (temp = buff; *temp && (*temp == ' ' || *temp == '\t');temp++);
371 if (*temp != '"') {
372 eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename);
373 continue;
374 }
375
376 temp2 = temp + 1;
377 /* find the next " */
378 for (temp = temp2; *temp && *temp != '"';temp++);
379 if (*temp != '"' || temp == temp2) {
380 eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no realmname)",line,filename);
381 continue;
382 }
383
384 /* save the realmname */
385 *temp = '\0';
386 name = xstrdup(temp2);
387
388 /* eventlog(eventlog_level_trace, __FUNCTION__,"found realmname: %s",name); */
389
390 /* skip any separators */
391 for(temp = temp + 1; *temp && (*temp == '\t' || *temp == ' ');temp++);
392
393 if (*temp == '"') { /* we have realm description */
394 temp2 = temp + 1;
395 /* find the next " */
396 for(temp = temp2;*temp && *temp != '"';temp++);
397 if (*temp != '"' || temp == temp2) {
398 eventlog(eventlog_level_error,__FUNCTION__,"malformed line %u in file \"%s\" (no valid description)",line,filename);
399 xfree(name);
400 continue;
401 }
402
403 /* save the description */
404 *temp = '\0';
405 desc = xstrdup(temp2);
406
407 /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm desc: %s",desc); */
408
409 /* skip any separators */
410 for(temp = temp + 1; *temp && (*temp == ' ' || *temp == '\t');temp++);
411 } else desc = xstrdup("\0");
412
413 temp2 = temp;
414 /* find out where address ends */
415 for(temp = temp2 + 1; *temp && *temp != ' ' && *temp != '\t';temp++);
416
417 if (*temp) *temp++ = '\0'; /* if is not the end of the file, end addr and move forward */
418
419 /* eventlog(eventlog_level_trace, __FUNCTION__,"found realm ip: %s",temp2); */
420
421 if (!(raddr = addr_create_str(temp2,0,BNETD_REALM_PORT))) /* 0 means "this computer" */ {
422 eventlog(eventlog_level_error,__FUNCTION__,"invalid address value for field 3 on line %u in file \"%s\"",line,filename);
423 xfree(name);
424 xfree(desc);
425 continue;
426 }
427
428 if (!(realm = realm_create(name,desc,addr_get_ip(raddr),addr_get_port(raddr))))
429 {
430 eventlog(eventlog_level_error,__FUNCTION__,"could not create realm");
431 addr_destroy(raddr);
432 xfree(name);
433 xfree(desc);
434 continue;
435 }
436
437 addr_destroy(raddr);
438 xfree(name);
439 xfree(desc);
440
441 list_prepend_data(list_head,realm);
442 }
443 file_get_line(NULL); // clear file_get_line buffer
444 if (fclose(fp)<0)
445 eventlog(eventlog_level_error,__FUNCTION__,"could not close realm file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));
446 return list_head;
447 }
448
realmlist_reload(char const * filename)449 extern int realmlist_reload(char const * filename)
450 {
451 t_elem * new_curr;
452 t_elem * old_curr;
453 t_realm * new_realm;
454 t_realm * old_realm;
455 int match;
456 t_list * newlist = NULL;
457 t_list * oldlist = realmlist_head;
458
459 realmlist_head = NULL;
460
461 if (!(newlist = realmlist_load(filename)))
462 return -1;
463
464 LIST_TRAVERSE(oldlist,old_curr)
465 {
466 if (!(old_realm = elem_get_data(old_curr)))
467 {
468 eventlog(eventlog_level_error,__FUNCTION__,"found NULL elem in list");
469 continue;
470 }
471
472 match = 0;
473
474 LIST_TRAVERSE(newlist,new_curr)
475 {
476 if (!(new_realm = elem_get_data(new_curr)))
477 {
478 eventlog(eventlog_level_error,__FUNCTION__,"found NULL elem in list");
479 continue;
480 }
481
482 if (!strcmp(old_realm->name,new_realm->name))
483 {
484 match = 1;
485 rcm_chref(&old_realm->rcm,new_realm);
486
487 break;
488 }
489
490 }
491 if (!match)
492 rcm_chref(&old_realm->rcm,NULL);
493
494 realm_destroy(old_realm);
495 list_remove_elem(oldlist,&old_curr);
496 }
497
498 list_destroy(oldlist);
499
500 realmlist_head = newlist;
501
502 return 0;
503 }
504
realmlist_create(char const * filename)505 extern int realmlist_create(char const * filename)
506 {
507 if (!(realmlist_head = realmlist_load(filename)))
508 return -1;
509
510 return 0;
511
512 }
513
realmlist_unload(t_list * list_head)514 extern int realmlist_unload(t_list * list_head)
515 {
516 t_elem * curr;
517 t_realm * realm;
518
519 if (list_head)
520 {
521 LIST_TRAVERSE(list_head,curr)
522 {
523 if (!(realm = elem_get_data(curr)))
524 eventlog(eventlog_level_error,__FUNCTION__,"found NULL realm in list");
525 else
526 realm_destroy(realm);
527
528 list_remove_elem(list_head,&curr);
529 }
530 list_destroy(list_head);
531 }
532
533 return 0;
534 }
535
realmlist_destroy()536 extern int realmlist_destroy()
537 {
538 int res;
539
540 res = realmlist_unload(realmlist_head);
541 realmlist_head = NULL;
542
543 return res;
544 }
545
realmlist(void)546 extern t_list * realmlist(void)
547 {
548 return realmlist_head;
549 }
550
551
realmlist_find_realm(char const * realmname)552 extern t_realm * realmlist_find_realm(char const * realmname)
553 {
554 t_elem const * curr;
555 t_realm * realm;
556
557 if (!realmname)
558 {
559 eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname");
560 return NULL;
561 }
562
563 LIST_TRAVERSE_CONST(realmlist_head,curr)
564 {
565 realm = elem_get_data(curr);
566 if (strcasecmp(realm->name,realmname)==0)
567 return realm;
568 }
569
570 return NULL;
571 }
572
realmlist_find_realm_by_ip(unsigned long ip)573 extern t_realm * realmlist_find_realm_by_ip(unsigned long ip)
574 {
575 t_elem const * curr;
576 t_realm * realm;
577
578 LIST_TRAVERSE_CONST(realmlist_head,curr)
579 {
580 realm = elem_get_data(curr);
581 if (realm->ip==ip)
582 return realm;
583 }
584 return NULL;
585 }
586
realm_get_conn(t_realm * realm)587 extern t_connection * realm_get_conn(t_realm * realm)
588 {
589 assert(realm);
590
591 return realm->conn;
592 }
593
realm_get(t_realm * realm,t_rcm_regref * regref)594 extern t_realm * realm_get(t_realm * realm, t_rcm_regref * regref)
595 {
596 rcm_get(&realm->rcm,regref);
597 return realm;
598 }
599
realm_put(t_realm * realm,t_rcm_regref * regref)600 extern void realm_put(t_realm * realm, t_rcm_regref * regref)
601 {
602 rcm_put(&realm->rcm,regref);
603 }
604