Vanilla Netrek Server Development Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[VANILLA-L:1049] Client to Metaserver Recoding, Client Patch V1.0
Here is the working patch for COW 3.0 (2.02) that adds UDP metaserver
support. It's not finished, but you need it if you are to test your
metaserver patch. ;-)
Again, comments welcome.
Remember it isn't finished.
This patch;
- changes -m to use UDP metaserver mode,
- adds -M for the TCP metaserver mode,
- fixes command usage accordingly,
- removes RSA_client from the parsemeta server struct,
[it was not used??],
- adds code to send and receive the UDP protocol, using
all available metaservers [may change this].
--
James Cameron (james.cameron@digital.com)
Digital Equipment Corporation (Australia) Pty. Ltd. A.C.N. 000 446 800
*** main.c.orig Sun Aug 9 15:08:07 1998
--- main.c Mon Aug 24 19:11:34 1998
***************
*** 152,176 ****
break;
#ifdef META
! case 'm':
if (usemeta && usemeta != 1)
{
! fputs("The options -k and -m are mutuall exclusive\n",
stderr);
err++;
}
usemeta = 1;
break;
! case 'k':
if (usemeta && usemeta != 2)
{
! fputs("The options -k and -m are mutually exclusive\n",
stderr);
err++;
}
usemeta = 2;
break;
#endif
#ifdef RSA
--- 152,186 ----
break;
#ifdef META
! case 'm': /* use multiple metaservers by UDP */
if (usemeta && usemeta != 1)
{
! fputs("The options -k, -m and -M are mutually exclusive\n",
stderr);
err++;
}
usemeta = 1;
break;
! case 'k': /* use metaserver cache from prior -M usage */
if (usemeta && usemeta != 2)
{
! fputs("The options -k, -m and -M are mutually exclusive\n",
stderr);
err++;
}
usemeta = 2;
break;
+
+ case 'M': /* use single metaserver by TCP */
+ if (usemeta && usemeta != 3)
+ {
+ fputs("The options -k, -m and -M are mutually exclusive\n",
+ stderr);
+ err++;
+ }
+ usemeta = 3;
+ break;
#endif
#ifdef RSA
***************
*** 416,423 ****
printf(" [-l filename] Record messages into 'filename'\n");
#ifdef META
! printf(" [-m] check metaserver for active servers\n");
! printf(" [-k] display known servers\n");
#endif
#ifndef WIN32
printf(" [-n] use nearest colors in shared colormap\n");
--- 426,434 ----
printf(" [-l filename] Record messages into 'filename'\n");
#ifdef META
! printf(" [-m] list servers, using UDP/IP to multiple metaservers\n");
! printf(" [-M] list servers, using TCP/IP to single metaserver\n");
! printf(" [-k] list servers from cache generated by -M\n");
#endif
#ifndef WIN32
printf(" [-n] use nearest colors in shared colormap\n");
*** parsemeta.c.orig Sun Aug 9 13:27:56 1998
--- parsemeta.c Mon Aug 24 19:11:31 1998
***************
*** 56,65 ****
{
char address[LINE];
int port;
! int time;
int players;
int status;
- int RSA_client;
char typeflag;
};
--- 56,64 ----
{
char address[LINE];
int port;
! int age;
int players;
int status;
char typeflag;
};
***************
*** 164,174 ****
if (serverName)
{
-
- #ifdef RSA
- serverlist[num_servers].RSA_client = RSA_Client;
- #endif
-
strcpy(serverlist[num_servers].address, serverName);
serverlist[num_servers].port = xtrekPort;
serverlist[num_servers].status = statusDefault;
--- 163,168 ----
***************
*** 229,235 ****
if (sscanf(line, "-h %s -p %d %d %d",
slist->address, &(slist->port),
! &(slist->time)) != 3)
{
continue;
}
--- 223,229 ----
if (sscanf(line, "-h %s -p %d %d %d",
slist->address, &(slist->port),
! &(slist->age)) != 3)
{
continue;
}
***************
*** 255,261 ****
/* Read the flags */
- slist->RSA_client = (*(point - 5) == 'R');
slist->typeflag = *(point - 1);
--- 249,254 ----
***************
*** 270,276 ****
serverlist[num_servers].port,
statusStrings[serverlist[num_servers].status],
serverlist[num_servers].players,
- serverlist[num_servers].RSA_client,
serverlist[num_servers].typeflag);
#endif
--- 263,268 ----
***************
*** 279,285 ****
--- 271,523 ----
}
}
+ #define MAXMETABYTES 2048
+ static int sock; /* the socket to talk to the metaservers */
+ static int sent = 0; /* number of solicitations sent */
+ static int seen = 0; /* number of replies seen */
+
+ static int ReadMetasSend()
+ {
+ struct sockaddr_in address; /* the address of the metaservers */
+ int length; /* length of the address */
+ int bytes; /* number of bytes received from meta' */
+ fd_set readfds; /* the file descriptor set for select() */
+ struct timeval timeout; /* timeout for select() call */
+ char packet[MAXMETABYTES]; /* buffer for packet returned by meta' */
+ int max_servers; /* number of servers we have defined */
+
+ if ((getdefault("metaserver")) != NULL)
+ metaserver = getdefault("metaserver");
+ metaport = intDefault("metaport", metaport);
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) { perror("ReadMetasSend: socket"); return 0; }
+
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_family = AF_INET;
+ address.sin_port = 0;
+ if (bind(sock,(struct sockaddr *)&address, sizeof(address)) < 0) {
+ perror("ReadMetasSend: bind");
+ return 0;
+ }
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(metaport);
+ /* attempt numeric translation first */
+ if ((address.sin_addr.s_addr = inet_addr(metaserver)) == -1) {
+ struct hostent *hp;
+
+ /* then translation by name */
+ if ((hp = gethostbyname(metaserver)) == NULL) {
+ /* if it didn't work, return failure and warning */
+ fprintf(stderr,
+ "Cannot resolve metaserver address of %s, check for DNS problems?\n",
+ metaserver);
+ return 0;
+ } else {
+ int i;
+
+ /* resolution worked, send a query to every metaserver listed */
+ for(i=0;;i++) {
+
+ /* check for end of list of addresses */
+ if (hp->h_addr_list[i] == NULL) break;
+ address.sin_addr.s_addr = *(long *) hp->h_addr_list[i];
+ fprintf(stderr, "Requesting player list from metaserver at %s\n",
+ inet_ntoa(address.sin_addr));
+ if (sendto(sock, "?", 1, 0, (struct sockaddr *)&address,
+ sizeof(address)) < 0) {
+ perror("ReadMetasSend: sendto");
+ return 0;
+ }
+ sent++;
+ }
+ }
+ } else {
+ /* send only to the metaserver specified by numeric IP address */
+ if (sendto(sock, "?", 1, 0, (struct sockaddr *)&address,
+ sizeof(address)) < 0) {
+ perror("ReadMetasSend: sendto");
+ return 0;
+ }
+ sent++;
+ }
+ return 1;
+ }
+
+ static int ReadMetasRecv()
+ {
+ struct sockaddr_in address; /* the address of the metaservers */
+ int length; /* length of the address */
+ int bytes; /* number of bytes received from meta' */
+ fd_set readfds; /* the file descriptor set for select() */
+ struct timeval timeout; /* timeout for select() call */
+ char packet[MAXMETABYTES]; /* buffer for packet returned by meta' */
+ int max_servers; /* number of servers we have defined */
+
+ /* now await and process replies */
+ while(1) {
+ char *p;
+ int servers, i, j;
+
+ FD_ZERO(&readfds);
+ FD_SET(sock, &readfds);
+ timeout.tv_sec=0;
+ timeout.tv_usec=100;
+ if (select(FD_SETSIZE, &readfds, NULL, NULL, &timeout) < 0) {
+ perror("ReadMetasRecv: select");
+ return 0;
+ }
+
+ /* if the wait timed out, then we give up */
+ if (!FD_ISSET(sock, &readfds)) {
+ /* here placeth logic that sees time for reply is up and asks again */
+ return 0;
+ }
+
+ /* so we have data back from a metaserver */
+ length = sizeof(address);
+ bytes = recvfrom(sock, packet, MAXMETABYTES, 0, (struct sockaddr *)&address,
+ &length );
+ if (bytes < 0) {
+ perror("ReadMetasRecv: recvfrom");
+ fprintf(stderr, "sock=%d packet=%08.8x length=%d\n", sock, packet,
+ MAXMETABYTES );
+ return 0;
+ }
+
+ /* terminate the packet received */
+ packet[bytes] = 0;
+ fprintf(stderr, "%s", packet);
+
+ /* process the packet, updating our server list */
+
+ /* version identifier */
+ p = strtok(packet,",");
+ if (p == NULL) continue;
+ if (p[0] != 'r') continue;
+
+ /* number of servers */
+ p = strtok(NULL,"\n");
+ if (p == NULL) continue;
+ servers = atoi(p);
+
+ /* sanity check on number of servers */
+ if (servers > 2048) continue;
+ if (servers < 0) continue;
+
+ fprintf(stderr, "Metaserver at %s responded with %d server%s\n",
+ inet_ntoa(address.sin_addr),
+ servers,
+ servers == 1 ? "" : "s" );
+
+ /* allocate or extend a server list */
+ if (serverlist == NULL) {
+ serverlist = (struct servers *) malloc(
+ sizeof(struct servers) * servers);
+ } else {
+ serverlist = (struct servers *) realloc(serverlist,
+ sizeof(struct servers) * ( servers + num_servers ));
+ }
+
+ /* for each server listed by this metaserver packet */
+ for(i=0;i<servers;i++) {
+ struct servers *sp = serverlist;
+ char *address, type;
+ int port, status, age, players, queue;
+
+ address = strtok(NULL,","); /* hostname */
+ if (address == NULL) continue;
+
+ p = strtok(NULL,","); /* port */
+ if (p == NULL) continue;
+ port = atoi(p);
+
+ p = strtok(NULL,","); /* status */
+ if (p == NULL) continue;
+ status = atoi(p);
+
+ /* ignore servers here based on status */
+
+ p = strtok(NULL,","); /* age (of data in seconds) */
+ if (p == NULL) continue;
+ age = atoi(p);
+
+ p = strtok(NULL,","); /* players */
+ if (p == NULL) continue;
+ players = atoi(p);
+
+ p = strtok(NULL,","); /* queue size */
+ if (p == NULL) continue;
+ queue = atoi(p);
+
+ p = strtok(NULL,"\n"); /* server type */
+ if (p == NULL) continue;
+ type = p[0];
+
+ /* find in current server list? */
+ for(j=0;j<num_servers;j++) {
+ sp = serverlist + j;
+ if ((!strcmp(sp->address,address)) && (sp->port == port)) {
+ fprintf(stderr, "%s:%d already listed\n", address, port);
+ break;
+ }
+ }
+
+ /* if it was found, check age */
+ if (j != num_servers) {
+ if (age > sp->age) continue;
+ } else {
+ /* not found, store it at the end of the list */
+ sp = serverlist + j;
+ fprintf(stderr, "%s:%d new\n", address, port);
+ strncpy(sp->address,address,LINE);
+ sp->port = port;
+ sp->age = age;
+ num_servers++;
+ }
+
+ /* from meta.h of metaserver code */
+ #define SS_WORKING 0
+ #define SS_QUEUE 1
+ #define SS_OPEN 2
+ #define SS_EMPTY 3
+ #define SS_NOCONN 4
+ #define SS_INIT 5
+
+ switch (status) {
+ case SS_QUEUE:
+ sp->status = statusWait;
+ sp->players = queue;
+ break;
+ case SS_OPEN:
+ sp->status = statusOpen;
+ sp->players = players;
+ break;
+ case SS_EMPTY:
+ sp->status = statusNobody;
+ sp->players = 0;
+ break;
+ case SS_NOCONN: /* no connection */
+ case SS_WORKING: /* metaserver should not return this */
+ case SS_INIT: /* nor this */
+ default:
+ sp->status = statusNoConnect;
+ sp->players = 0;
+ break;
+ }
+ sp->typeflag = type;
+ }
+ /* finished processing the packet */
+
+ /* count the number of replies we have received */
+ seen++;
+
+ /* if we have seen the same number of replies to what we sent, end */
+ if (sent == seen) return 1;
+ }
+ }
static int ReadFromMeta(int statusLevel)
/* Read from the meta-server. Return TRUE on success and FALSE on failure. */
***************
*** 460,470 ****
void parsemeta(int metaType)
! /* Read and Parse the meta-server information, either from the meta- server
! * (if metaType = 1) or from the cache (if metaType = 2).
*
* NOTE: This function sets the variable "num_servers" which is later used to
! * decide the hight of the meta-server window. */
{
int statusLevel;
--- 698,708 ----
void parsemeta(int metaType)
! /* Read and Parse the metaserver information, either from the metaservers
! * by UDP (1), from a single metaserver by TCP (3), or from the cache (2).
*
* NOTE: This function sets the variable "num_servers" which is later used to
! * decide the height of the metaserver window. */
{
int statusLevel;
***************
*** 475,495 ****
else if (statusLevel >= statusNull)
statusLevel = statusNull - 1;
!
! if (metaType == 1) /* Read from the Meta-server */
{
! if (ReadFromMeta(statusLevel) || ReadFromCache(statusLevel))
return;
!
! terminate(0);
! }
!
! if (metaType == 2) /* Read from the Cache first */
! {
! if (ReadFromCache(statusLevel) || ReadFromMeta(statusLevel))
! return;
!
! terminate(0);
}
}
--- 713,734 ----
else if (statusLevel >= statusNull)
statusLevel = statusNull - 1;
! switch (metaType)
{
! case 1:
! ReadMetasSend();
! ReadMetasRecv();
return;
! terminate(0);
! break;
! case 2:
! if (ReadFromCache(statusLevel) || ReadFromMeta(statusLevel)) return;
! terminate(0);
! break;
! case 3:
! if (ReadFromMeta(statusLevel) || ReadFromCache(statusLevel)) return;
! terminate(0);
! break;
}
}
***************
*** 546,561 ****
break;
}
}
W_WriteText(metaWin, 0, i, color, buf, strlen(buf), 0);
}
! void metawindow(void)
/* Show the meta server menu window */
{
int i;
for (i = 0; i < num_servers; i++)
metarefresh(i, textColor);
--- 785,805 ----
break;
}
}
+ fprintf(stderr,"%s in\n", buf);
W_WriteText(metaWin, 0, i, color, buf, strlen(buf), 0);
+ fprintf(stderr,"%s ok\n", buf);
}
! void metawindow(int metaType)
/* Show the meta server menu window */
{
int i;
+ /* optimisation; check here for metaserver replies */
+ if (metaType == 1) ReadMetasRecv();
+
for (i = 0; i < num_servers; i++)
metarefresh(i, textColor);
***************
*** 600,609 ****
printf("Attempting to observe on port %d...\n",xtrekPort);
}
serverName = strdup(slist->address);
-
- #ifdef RSA
- RSA_Client = slist->RSA_client;
- #endif
metarefresh(data->y, W_Yellow);
W_Flush();
--- 844,849 ----
*** parsemeta.h.orig Wed Aug 12 17:50:13 1998
--- parsemeta.h Mon Aug 24 19:11:37 1998
***************
*** 24,30 ****
*/
! void metawindow(void);
/*
* Show the meta server menu window
*/
--- 24,30 ----
*/
! void metawindow(int metaType);
/*
* Show the meta server menu window
*/
*** newwin.c.orig Mon Aug 24 19:15:14 1998
--- newwin.c Tue Aug 18 18:06:54 1998
***************
*** 335,341 ****
#ifdef META
if (checkMapped("MetaServer List"))
! metawindow();
#endif
if (checkMapped("review_all"))
--- 335,341 ----
#ifdef META
if (checkMapped("MetaServer List"))
! metawindow(-1);
#endif
if (checkMapped("review_all"))
References: