00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdio.h>
00041 #include <ctype.h>
00042 #include <sys/types.h>
00043 #include <sys/time.h>
00044 #include <stdlib.h>
00045 #include <sys/socket.h>
00046 #include <arpa/inet.h>
00047 #include <netdb.h>
00048 #include <errno.h>
00049 #include "defs.h"
00050 #include "struct.h"
00051 #include "data.h"
00052 #include "parsemeta.h"
00053
00054
00055 #define BUF 6144
00056 #define MAXMETABYTES 2048
00057 static int msock = -1;
00058 static int sent = 0;
00059 static int seen = 0;
00060 static int verbose = 0;
00061 static int type;
00062
00063
00064 int num_servers = 0;
00065 int metaHeight = 0;
00066 char *metaWindowName;
00067 char *serverName = NULL;
00068 int statusLevel;
00069 struct servers *serverlist = NULL;
00070
00071
00072 char *metaserver = "metaserver.netrek.org";
00073 int metaport = 3521;
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 char *statusStrings[] =
00089 {"OPEN:", "Wait queue:", "Nobody", "Timed out", "No connection",
00090 "Active", "CANNOT CONNECT", "DEFAULT SERVER"};
00091
00092 enum statusTypes {
00093 statusOpen = 0, statusWait, statusNobody, statusTout, statusNoConnect,
00094 statusNull, statusCantConnect, statusDefault
00095 };
00096
00097 const int defaultStatLevel = statusTout;
00098
00099
00100
00101 extern void terminate(int error);
00102
00103 static int open_port(char *host, int port, int verbose)
00104
00105
00106 {
00107 struct sockaddr_in addr;
00108 struct hostent *hp;
00109 int sock;
00110
00111
00112
00113 if ((addr.sin_addr.s_addr = inet_addr(host)) == -1) {
00114 if ((hp = gethostbyname(host)) == NULL) {
00115 if (verbose) fprintf(stderr, "unknown host '%s'\n", host);
00116 return (-1);
00117 } else {
00118 addr.sin_addr.s_addr = *(long *) hp->h_addr;
00119 }
00120 }
00121 addr.sin_family = AF_INET;
00122 addr.sin_port = htons(port);
00123 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00124 if (verbose) perror("socket");
00125 return (-1);
00126 }
00127 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00128 if (verbose) perror("connect");
00129 close(sock);
00130 return (-1);
00131 }
00132 return (sock);
00133 }
00134
00135
00136 static void parseInput(char *in, FILE * out)
00137
00138 {
00139 char line[LINE + 1], *numstr, *point, **statStr;
00140 struct servers *slist;
00141 int rtn, max_servers;
00142 int count;
00143
00144
00145
00146
00147
00148 serverlist = (struct servers *) malloc(sizeof(struct servers) * 10);
00149
00150 max_servers = 10;
00151 num_servers = 0;
00152
00153
00154
00155 if (serverName != NULL) {
00156 strcpy(serverlist[num_servers].address, serverName);
00157 serverlist[num_servers].port = xtrekPort;
00158 serverlist[num_servers].status = statusDefault;
00159 serverlist[num_servers].players = 0;
00160 serverlist[num_servers].typeflag = ' ';
00161 num_servers++;
00162 }
00163
00164
00165 while (1) {
00166
00167 point = line;
00168 count = LINE + 1;
00169
00170 do {
00171 if (!(--count)) {
00172 fputs("Warning: Line from meta server was too long!!!\n", stderr);
00173 ++point;
00174 break;
00175 }
00176
00177 rtn = *in++;
00178 if (!rtn)
00179 return;
00180
00181 *(point++) = rtn;
00182 }
00183 while (rtn != EOF && rtn != '\n');
00184
00185 *(--point) = '\0';
00186
00187 if (out != NULL) {
00188
00189 fputs(line, out);
00190 putc('\n', out);
00191 }
00192
00193
00194
00195
00196
00197 if (num_servers >= max_servers) {
00198 max_servers += 5;
00199 size_t size = sizeof(struct servers) * max_servers;
00200 serverlist = (struct servers *) realloc(serverlist, size);
00201 }
00202
00203 slist = serverlist + num_servers;
00204
00205
00206
00207
00208
00209 if (sscanf(line, "-h %s -p %d %d %d",
00210 slist->address, &(slist->port),
00211 &(slist->age)) != 3) {
00212 continue;
00213 }
00214
00215
00216
00217 for (statStr = statusStrings + statusLevel
00218 ; statStr >= statusStrings
00219 ; --statStr) {
00220 if ((numstr = strstr(line, *statStr)) != NULL) {
00221 (slist->status) = statStr - statusStrings;
00222 (slist->players) = 0;
00223 sscanf(numstr, "%*[^0123456789] %d", &(slist->players));
00224 break;
00225 }
00226 }
00227
00228 if (statStr < statusStrings)
00229 continue;
00230
00231
00232
00233
00234 slist->typeflag = *(point - 1);
00235
00236
00237
00238
00239 if (slist->typeflag != 'P') {
00240
00241 #ifdef DEBUG
00242 printf("HOST:%-30s PORT:%-6d %12s %-5d %d %c\n",
00243 serverlist[num_servers].address,
00244 serverlist[num_servers].port,
00245 statusStrings[serverlist[num_servers].status],
00246 serverlist[num_servers].players,
00247 serverlist[num_servers].typeflag);
00248 #endif
00249
00250 ++num_servers;
00251 }
00252 }
00253 }
00254
00255 static int ReadMetasSend()
00256 {
00257 char *metaservers;
00258 char *token;
00259 struct sockaddr_in address;
00260 int length;
00261
00262
00263 if ((getdefault("metaserver")) != NULL)
00264 metaserver = getdefault("metaserver");
00265
00266
00267 metaport = intDefault("metaport", metaport);
00268
00269
00270 verbose = booleanDefault("metaverbose", verbose);
00271
00272
00273 if (msock < 0) {
00274 msock = socket(AF_INET, SOCK_DGRAM, 0);
00275 if (msock < 0) { perror("ReadMetasSend: socket"); return 0; }
00276
00277
00278 address.sin_addr.s_addr = INADDR_ANY;
00279 address.sin_family = AF_INET;
00280 address.sin_port = 0;
00281 if (bind(msock,(struct sockaddr *)&address, sizeof(address)) < 0) {
00282 perror("ReadMetasSend: bind");
00283 close(msock);
00284 return 0;
00285 }
00286 }
00287
00288
00289 address.sin_family = AF_INET;
00290 address.sin_port = htons(metaport);
00291 address.sin_addr.s_addr = inet_addr("224.0.0.1");
00292 if (verbose) fprintf(stderr,
00293 "Requesting player list from nearby servers on %s\n",
00294 inet_ntoa(address.sin_addr));
00295 if (sendto(msock, "?", 1, 0, (struct sockaddr *)&address,
00296 sizeof(address)) < 0) {
00297 perror("ReadMetasSend: sendto");
00298 } else {
00299 sent++;
00300 }
00301
00302
00303 metaservers = strdup(metaserver);
00304 token = strtok(metaservers,",");
00305
00306 while (token != NULL) {
00307
00308 address.sin_family = AF_INET;
00309 address.sin_port = htons(metaport);
00310
00311
00312 while (*token == ' ') token++;
00313
00314
00315 if ((address.sin_addr.s_addr = inet_addr(token)) == -1) {
00316 struct hostent *hp;
00317
00318
00319 if ((hp = gethostbyname(token)) == NULL) {
00320
00321 fprintf(stderr,
00322 "Cannot resolve host %s, check for DNS problems?\n",
00323 token);
00324 } else {
00325 int i;
00326
00327
00328 for(i=0;;i++) {
00329
00330
00331 if (hp->h_addr_list[i] == NULL) break;
00332 address.sin_addr.s_addr = *(long *) hp->h_addr_list[i];
00333 if (verbose) fprintf(stderr,
00334 "Requesting player list from metaserver %s at %s\n",
00335 token, inet_ntoa(address.sin_addr));
00336 if (sendto(msock, "?", 1, 0, (struct sockaddr *)&address,
00337 sizeof(address)) < 0) {
00338 perror("ReadMetasSend: sendto");
00339 } else {
00340 sent++;
00341 }
00342 }
00343 }
00344 } else {
00345
00346 if (verbose) fprintf(stderr,
00347 "Requesting player list from metaserver %s\n",
00348 inet_ntoa(address.sin_addr));
00349 if (sendto(msock, "?", 1, 0, (struct sockaddr *)&address,
00350 sizeof(address)) < 0) {
00351 perror("ReadMetasSend: sendto");
00352 } else {
00353 sent++;
00354 }
00355 }
00356
00357
00358 token = strtok(NULL,",");
00359 }
00360 return sent;
00361 }
00362
00363
00364 static void grow(int servers)
00365 {
00366 int size;
00367 if (serverlist == NULL) {
00368 size = sizeof(struct servers) * servers;
00369 serverlist = (struct servers *) malloc(size);
00370 } else {
00371 size = sizeof(struct servers) * ( servers + num_servers );
00372 serverlist = (struct servers *) realloc(serverlist, size);
00373 }
00374 }
00375
00376 static struct servers *server_find(char *address, int port)
00377 {
00378 int j;
00379
00380 for(j=0;j<num_servers;j++) {
00381 struct servers *sp = serverlist + j;
00382 if ((!strcmp(sp->address, address)) && (sp->port == port)) {
00383 return sp;
00384 }
00385 }
00386 return NULL;
00387 }
00388
00389 static void version_r(struct sockaddr_in *address) {
00390 char *p;
00391 int servers, i, j;
00392 time_t now = time(NULL);
00393
00394
00395 p = strtok(NULL,"\n");
00396 if (p == NULL) return;
00397 servers = atoi(p);
00398
00399
00400 if (servers > 2048) return;
00401 if (servers < 0) return;
00402
00403 if (verbose) fprintf(stderr,
00404 "Metaserver at %s responded with %d server%s\n",
00405 inet_ntoa(address->sin_addr),
00406 servers,
00407 servers == 1 ? "" : "s" );
00408
00409 if (servers == 0) return;
00410
00411 grow(servers);
00412
00413
00414 for(i=0;i<servers;i++) {
00415 struct servers *sp = NULL;
00416 char *host, type;
00417 int port, status, age, players, queue, throwaway;
00418
00419 throwaway = 0;
00420
00421 host = strtok(NULL,",");
00422 if (host == NULL) continue;
00423
00424 p = strtok(NULL,",");
00425 if (p == NULL) continue;
00426 port = atoi(p);
00427
00428 p = strtok(NULL,",");
00429 if (p == NULL) continue;
00430 status = atoi(p);
00431
00432
00433 if (status > statusLevel)
00434 throwaway++;
00435
00436 if (status == 6)
00437 if ((status - 3) <= statusLevel)
00438 throwaway--;
00439
00440 p = strtok(NULL,",");
00441 if (p == NULL) continue;
00442 age = atoi(p);
00443
00444 p = strtok(NULL,",");
00445 if (p == NULL) continue;
00446 players = atoi(p);
00447
00448 p = strtok(NULL,",");
00449 if (p == NULL) continue;
00450 queue = atoi(p);
00451
00452 p = strtok(NULL,"\n");
00453 if (p == NULL) continue;
00454 type = p[0];
00455
00456
00457 if (type == 'P') throwaway++;
00458
00459
00460 if (throwaway) continue;
00461
00462
00463 sp = server_find(host, port);
00464
00465
00466 if (sp != NULL) {
00467 if ((now-age) < (sp->when-sp->age)) {
00468 sp->age = now - (sp->when-sp->age);
00469 sp->when = now;
00470 sp->refresh = 1;
00471 sp->lifetime = 20;
00472 continue;
00473 } else {
00474 sp->age = age;
00475 sp->when = now;
00476 sp->lifetime = 20;
00477 }
00478 } else {
00479
00480 sp = serverlist + sizeof(struct servers);
00481 strncpy(sp->address,host,LINE);
00482 sp->port = port;
00483 sp->age = age;
00484 sp->when = now;
00485 sp->lifetime = 4;
00486 num_servers++;
00487 }
00488 sp->refresh = 1;
00489
00490
00491 #define SS_WORKING 0
00492 #define SS_QUEUE 1
00493 #define SS_OPEN 2
00494 #define SS_EMPTY 3
00495 #define SS_NOCONN 4
00496 #define SS_INIT 5
00497
00498
00499 #define SS_TOUT 6
00500 switch (status) {
00501 case SS_QUEUE:
00502 sp->status = statusWait;
00503 sp->players = queue;
00504 break;
00505 case SS_OPEN:
00506 sp->status = statusOpen;
00507 sp->players = players;
00508 break;
00509 case SS_EMPTY:
00510 sp->status = statusNobody;
00511 sp->players = 0;
00512 break;
00513 case SS_TOUT:
00514 sp->status = statusTout;
00515 sp->players = 0;
00516 break;
00517 case SS_NOCONN:
00518 case SS_WORKING:
00519 case SS_INIT:
00520 default:
00521 sp->status = statusNoConnect;
00522 sp->players = 0;
00523 break;
00524 }
00525 sp->typeflag = type;
00526 strcpy(sp->comment, "");
00527 }
00528 }
00529
00530 static void version_s(struct sockaddr_in *address)
00531 {
00532 char *p;
00533 time_t now = time(NULL);
00534 int throwaway = 0;
00535
00536
00537
00538
00539 char *host = inet_ntoa(address->sin_addr);
00540
00541 if (verbose) fprintf(stderr, "Server at %s responded\n", host);
00542
00543 p = strtok(NULL,",");
00544 if (p == NULL) return;
00545 char type = p[0];
00546
00547
00548 if (type == 'P') return;
00549
00550 p = strtok(NULL,",");
00551 if (p == NULL) return;
00552 char *comment = strdup(p);
00553
00554 p = strtok(NULL,",");
00555 if (p == NULL) return;
00556 int ports = atoi(p);
00557
00558
00559
00560 p = strtok(NULL,",");
00561 if (p == NULL) return;
00562 int port = atoi(p);
00563
00564 p = strtok(NULL,",");
00565 if (p == NULL) return;
00566 int players = atoi(p);
00567
00568 p = strtok(NULL,",");
00569 if (p == NULL) return;
00570 int queue = atoi(p);
00571
00572
00573 struct servers *sp = server_find(host, port);
00574
00575
00576 if (sp == NULL) {
00577 grow(1);
00578 sp = serverlist + num_servers;
00579 num_servers++;
00580 }
00581
00582
00583 strncpy(sp->address, host, LINE);
00584 sp->port = port;
00585 sp->age = 0;
00586 sp->when = now;
00587 sp->refresh = 1;
00588 sp->lifetime = 20;
00589 sp->players = players;
00590 sp->status = statusOpen;
00591 sp->typeflag = type;
00592 strncpy(sp->comment, comment, LINE);
00593 free(comment);
00594 }
00595
00596 static int ReadMetasRecv(int x)
00597 {
00598 struct sockaddr_in address;
00599 socklen_t length;
00600 int bytes;
00601 fd_set readfds;
00602 struct timeval timeout;
00603 char packet[MAXMETABYTES];
00604 time_t now;
00605 int isawsomething = 0;
00606
00607
00608 while(1) {
00609 char *p;
00610
00611 FD_ZERO(&readfds);
00612 if (msock >= 0) FD_SET(msock, &readfds);
00613 timeout.tv_sec=4;
00614 timeout.tv_usec=0;
00615
00616 if (x != -1) FD_SET(x, &readfds);
00617 if (select(FD_SETSIZE, &readfds, NULL, NULL,
00618 (x != -1) ? NULL : &timeout) < 0) {
00619 perror("ReadMetasRecv: select");
00620 return 0;
00621 }
00622
00623
00624 if (x != -1 && FD_ISSET(x, &readfds)) return 0;
00625 if (msock < 0) return 0;
00626
00627
00628 if (!FD_ISSET(msock, &readfds)) {
00629 if(isawsomething)
00630 return 1;
00631 else
00632 return 0;
00633 }
00634
00635
00636 isawsomething++;
00637 length = sizeof(address);
00638 bytes = recvfrom(msock, packet, MAXMETABYTES, 0, (struct sockaddr *)&address,
00639 &length );
00640 if (bytes < 0) {
00641 perror("ReadMetasRecv: recvfrom");
00642 return 0;
00643 }
00644
00645
00646 packet[bytes] = 0;
00647 #ifdef DEBUG
00648 fprintf(stderr, "%s", packet);
00649 #endif
00650
00651
00652
00653
00654 p = strtok(packet,",");
00655 if (p == NULL) continue;
00656
00657 switch (p[0]) {
00658 case 'r': version_r(&address); seen++; break;
00659 case 's': version_s(&address); seen++; break;
00660 }
00661
00662
00663
00664
00665 if (x == -1) return 1;
00666
00667
00668 if (sent == seen) return 1;
00669 }
00670 }
00671
00672 static void SaveMetasCache()
00673 {
00674 FILE *cache;
00675 char cacheFileName[PATH_MAX];
00676 char tmpFileName[PATH_MAX];
00677 char *cacheName;
00678 int len;
00679
00680 cacheName = getdefault("metaUDPCache");
00681
00682 if (cacheName && !findfile(cacheName, cacheFileName))
00683 strcpy(cacheFileName, cacheName);
00684
00685 if (cacheName)
00686 {
00687 len = strlen(cacheFileName);
00688 strcpy(tmpFileName, cacheFileName);
00689
00690
00691 if ((cacheFileName[len - 1] == 'T') || (cacheFileName[len - 1] == 't'))
00692 tmpFileName[len-1] = 'R';
00693 else
00694 tmpFileName[len-1] = 'T';
00695
00696 cache = fopen(tmpFileName, "w");
00697
00698 if (cache == NULL)
00699 {
00700 fprintf(stderr,
00701 "Cannot create a metaUDPCache temporary file `%s'\n",
00702 tmpFileName);
00703 fprintf(stderr, "Meta-server read will not be cached.\n");
00704 }
00705 }
00706 else
00707 {
00708 cache = NULL;
00709 }
00710
00711
00712 if (cache != NULL)
00713 {
00714
00715 fwrite(&statusLevel, sizeof(statusLevel), 1, cache);
00716 fwrite(&num_servers, sizeof(num_servers), 1, cache);
00717 fwrite(serverlist, sizeof(struct servers), num_servers, cache);
00718
00719 fclose(cache);
00720
00721 #ifdef WIN32
00722
00723 #ifdef _MSC_VER
00724 _unlink(cacheName);
00725 #else
00726 unlink(cacheName);
00727 #endif
00728 #endif
00729 if (rename(tmpFileName, cacheName) == -1)
00730 perror("Could not rename new cache file");
00731 }
00732
00733 }
00734
00735 static void LoadMetasCache()
00736 {
00737 FILE *cache;
00738 char *cacheName;
00739 char cacheFileName[PATH_MAX];
00740 int i;
00741
00742 cacheName = getdefault("metaUDPCache");
00743
00744 if(!cacheName)
00745 {
00746 num_servers = 0;
00747 return;
00748 }
00749
00750 findfile(cacheName, cacheFileName);
00751
00752 cache = fopen(cacheFileName, "r");
00753 if (cache == NULL)
00754 {
00755 num_servers = 0;
00756 return;
00757 }
00758
00759
00760 fread(&i, sizeof(i), 1, cache);
00761 if (i != statusLevel)
00762 {
00763 num_servers = 0;
00764 fclose(cache);
00765 return;
00766 }
00767
00768
00769
00770 fread(&num_servers, sizeof(num_servers), 1, cache);
00771 serverlist = (struct servers *) malloc(sizeof(struct servers)*num_servers);
00772 fread(serverlist, sizeof(struct servers), num_servers, cache);
00773 fclose(cache);
00774
00775
00776 for(i=0;i<num_servers;i++)
00777 {
00778 int j;
00779
00780
00781 serverlist[i].refresh = 1;
00782
00783
00784 if (serverlist[i].lifetime-- > 0) continue;
00785
00786
00787 for(j=i;j<num_servers-1;i++)
00788 {
00789 memcpy(&serverlist[j],&serverlist[j+1],sizeof(struct servers));
00790 }
00791
00792
00793 i--;
00794 num_servers--;
00795 serverlist =
00796 (struct servers *) realloc(serverlist,
00797 sizeof(struct servers) * ( num_servers ));
00798 }
00799 }
00800
00801 static int ReadFromMeta()
00802
00803 {
00804 FILE *out;
00805 char *cacheName;
00806 char cacheFileName[PATH_MAX];
00807 char tmpFileName[PATH_MAX];
00808 char *sockbuf, *buf;
00809 int bufleft = BUF - 1;
00810 int len;
00811 int sock;
00812
00813 if ((getdefault("metaserver")) != NULL)
00814 metaserver = getdefault("metaserver");
00815
00816 metaport = intDefault("metaport", metaport);
00817
00818 if ((sock = open_port(metaserver, metaport, 1)) <= 0)
00819 {
00820 fprintf(stderr, "Cannot connect to MetaServer (%s , %d)\n",
00821 metaserver, metaport);
00822 return 0;
00823 }
00824
00825
00826 buf = sockbuf = (char *)malloc(BUF);
00827 while (bufleft > 0 && (len = read(sock, buf, bufleft)) > 0)
00828 {
00829 bufleft-=len;
00830 buf += len;
00831 #ifdef DEBUG
00832 printf("Read %d bytes from Metaserver\n", len);
00833 #endif
00834 }
00835 close (sock);
00836 *buf = 0;
00837
00838 if (len<0)
00839 {
00840 perror ("read");
00841 free(sockbuf);
00842 return 0;
00843 }
00844
00845 cacheName = getdefault("metaCache");
00846 if (cacheName && !findfile(cacheName, cacheFileName))
00847 strcpy(cacheFileName, cacheName);
00848
00849 if (cacheName)
00850 {
00851 len = strlen(cacheFileName);
00852 strcpy(tmpFileName, cacheFileName);
00853
00854
00855
00856 if ((cacheFileName[len - 1] == 'T') || (cacheFileName[len - 1] == 't'))
00857 tmpFileName[len-1] = 'R';
00858 else
00859 tmpFileName[len-1] = 'T';
00860
00861 out = fopen(tmpFileName, "w");
00862
00863 if (out == NULL)
00864 {
00865 fprintf(stderr,
00866 "Cannot write to the metaCache temporary file `%s'.\n",
00867 tmpFileName);
00868 fprintf(stderr, "Meta-server read will not be cached.\n");
00869 }
00870 }
00871 else
00872 {
00873 out = NULL;
00874 }
00875
00876 parseInput(sockbuf, out);
00877
00878 if (out != NULL)
00879 {
00880 fclose(out);
00881
00882 #ifdef WIN32
00883
00884 #ifdef _MSC_VER
00885 _unlink(cacheName);
00886 #else
00887 unlink(cacheName);
00888 #endif
00889 #endif
00890 if (rename(tmpFileName, cacheName) == -1)
00891 perror("Could not write to cache file");
00892 }
00893
00894 free(sockbuf);
00895 metaWindowName = "MetaServer List";
00896
00897 return 1;
00898 }
00899
00900
00901 static int ReadFromCache()
00902
00903 {
00904 FILE *in;
00905 char *cacheName;
00906 struct servers *slist;
00907 char *sockbuf, *buf;
00908 int bufleft = BUF - 1;
00909 int len;
00910 char cacheFileName[PATH_MAX];
00911
00912 cacheName = getdefault("metaCache");
00913
00914 if (!cacheName)
00915 {
00916 fprintf(stderr,
00917 "You must define the .xtrekrc variable `metaCache' in\n");
00918 fprintf(stderr,
00919 "order to use the `show known servers' option.\n");
00920 return 0;
00921 }
00922 else
00923 if (!findfile(cacheName, cacheFileName) || !(in = fopen(cacheFileName, "r")) )
00924 {
00925 fprintf(stderr,
00926 "The metaCache file `%s' is empty or not accessable.\n",
00927 cacheName);
00928 return 0;
00929 }
00930
00931
00932
00933
00934
00935 buf = sockbuf = (char *)malloc(BUF);
00936
00937 while (bufleft >0 && ((len = fread(buf, 1, bufleft, in)) > 0))
00938 {
00939 bufleft-=len;
00940 buf += len;
00941 #ifdef DEBUG
00942 printf("Read %d bytes from Metaserver cache file\n", len);
00943 #endif
00944 }
00945 *buf = 0;
00946 fclose (in);
00947
00948 if (len<0)
00949 {
00950 perror ("fread");
00951 free(sockbuf);
00952 return 0;
00953 }
00954
00955
00956
00957 if (statusLevel <= statusNobody)
00958 statusLevel = statusNobody;
00959
00960 parseInput(sockbuf, NULL);
00961
00962
00963
00964 for (slist = serverlist + num_servers - 1
00965 ; slist >= serverlist
00966 ; --slist)
00967 {
00968 if (slist->status <= statusNobody)
00969 slist->status = statusNull;
00970 }
00971
00972 free(sockbuf);
00973 metaWindowName = "Known Servers";
00974
00975 return 1;
00976 }
00977
00978
00979 void parsemeta(int metaType)
00980
00981
00982
00983
00984
00985
00986 {
00987 statusLevel = intDefault("metaStatusLevel", defaultStatLevel);
00988
00989 if (statusLevel < 0)
00990 statusLevel = 0;
00991 else if (statusLevel >= statusNull)
00992 statusLevel = statusNull - 1;
00993
00994 type = metaType;
00995 switch (type)
00996 {
00997 case 1:
00998 ReadMetasSend();
00999 LoadMetasCache();
01000 if (num_servers == 0) ReadMetasRecv(-1);
01001 if (num_servers != 0) {
01002 metaHeight = num_servers + 5;
01003 } else {
01004 printf("Warning: no response from metaservers, "
01005 "are you firewalled?\n"
01006 " (no reply to probe on UDP port %d)\n", metaport);
01007 metaHeight = num_servers + 10;
01008 }
01009 return;
01010 break;
01011 case 2:
01012 if (ReadFromCache() || ReadFromMeta())
01013 {
01014
01015 metaHeight = num_servers + 2;
01016 return;
01017 }
01018 terminate(0);
01019 break;
01020 case 3:
01021 if (ReadFromMeta() || ReadFromCache())
01022 {
01023
01024 metaHeight = num_servers + 2;
01025 return;
01026 }
01027
01028 break;
01029 }
01030 }
01031
01032
01033 static void metarefresh(int i)
01034
01035 {
01036 char buf[LINE + 1];
01037 struct servers *sp;
01038
01039
01040 if (i >= num_servers) {
01041
01042
01043 return;
01044 }
01045
01046 sp = serverlist + i;
01047
01048 sprintf(buf, "%-40s %14s ",
01049 strlen(sp->comment) > 0 ? sp->comment : sp->address,
01050 statusStrings[sp->status]);
01051
01052 if (sp->status <= statusNull)
01053 {
01054 if (sp->status == statusOpen || sp->status == statusWait)
01055 {
01056
01057 sprintf(buf + strlen(buf), "%-5d ", sp->players);
01058 }
01059 else
01060 {
01061 strcat(buf, " ");
01062 }
01063
01064 switch (sp->typeflag)
01065 {
01066 case 'P':
01067 strcat(buf, "Paradise");
01068 break;
01069 case 'B':
01070 strcat(buf, "Bronco ");
01071 break;
01072 case 'C':
01073 strcat(buf, "Chaos ");
01074 break;
01075 case 'I':
01076 strcat(buf, "INL ");
01077 break;
01078 case 'S':
01079 strcat(buf, "Sturgeon");
01080 break;
01081 case 'H':
01082 strcat(buf, "Hockey ");
01083 break;
01084 case 'F':
01085 strcat(buf, "Dogfight");
01086 break;
01087 default:
01088 strcat(buf, "Unknown ");
01089 break;
01090 }
01091
01092 if (type == 1)
01093 {
01094 int age = sp->age;
01095 char *units;
01096
01097 if (age > 86400)
01098 {
01099 age = age / 86400;
01100 units = "d";
01101 }
01102 else if (age > 3600)
01103 {
01104 age = age / 3600;
01105 units = "h";
01106 }
01107 else if (age > 90)
01108 {
01109 age = age / 60;
01110 units = "m";
01111 }
01112 else
01113 {
01114 units = "s";
01115 }
01116 sprintf(buf + strlen(buf), " %4d%s", age, units);
01117 }
01118 }
01119
01120
01121 sp->refresh = 0;
01122 }
01123
01124
01125 void metawindow()
01126
01127 {
01128 int i;
01129 char *header;
01130
01131 if (type == 1) {
01132 header = "Server ----------------------------------------- Status ------ Type ----- Age";
01133 } else {
01134 header = "Server ----------------------------------------- Status ------ Type";
01135 }
01136
01137
01138 for (i = 0; i < metaHeight; i++)
01139 metarefresh(i);
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 }
01152
01153
01154 static void metadone(void)
01155
01156 {
01157
01158
01159 if (type == 1) SaveMetasCache();
01160 free(serverlist);
01161 }
01162
01163
01164
01165