Vanilla Netrek Server Development Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[VANILLA-L:1048] Client to Metaserver Recoding Patch V1.0



Attached is the patch to the metaserver code, as context diffs relative
to Frank's posting of his source two weeks ago.

This patch adds the client to metaserver protocol.
The patch is very small.

I expect one metaserver to take it on, and to advise the others once it
is proven.  

The patch does the following;

    1)  adds recognition of the client request to the incoming
	UDP packet handler, [scan.c]

    2)	corrects an error message prefix, [scan.c]

    3)	adjusts the comment and error on socket creation, 
	[scan.c]

    4)  uses a #define for maximum hostname length, [meta.h]

    5)	adds code that generates the UDP reply, [disp_udp.c]

    6)	adds the new module to the build, [Makefile]

I'm not exactly ecstatic about the code I wrote in disp_udp.c, but I've
sat on it for long enough that it needs airing and production testing. 
It has hasty memory estimation logic which might bite me later.  Review
welcome.

-- 
James Cameron                              (james.cameron@digital.com)
Digital Equipment Corporation (Australia) Pty. Ltd. A.C.N. 000 446 800
*** scan.c.orig	Mon Aug 24 18:58:40 1998
--- scan.c	Mon Aug 24 19:01:20 1998
***************
*** 913,921 ****
      log_msg("%s %s", inet_ntoa(srvbuf.addr), packet );
  #endif
  
!     /* version */
      p = strtok(packet, "\n");
      if (p == NULL) return;
      if (p[0] != 'a') {
  	log_msg("uread: bad version %02.2x from %s\n", p[0],
  	    /* inet_ntoa(srvbuf.addr)); */
--- 913,938 ----
      log_msg("%s %s", inet_ntoa(srvbuf.addr), packet );
  #endif
  
!     /* parse version character of packet */
      p = strtok(packet, "\n");
      if (p == NULL) return;
+ 
+     /* check for netrek client request for listing */
+     if (p[0] == '?') {
+         char *buffer;
+ 	int length;
+ 
+ 	log_msg("uread: player at %s requests using UDP\n", 
+ 	    inet_ntoa(from.sin_addr) );
+ 	buffer = (char *) display_udp(&length);
+         bytes = sendto(usock, buffer, length, 0,
+ 	    (struct sockaddr *)&from, fromlen);
+ 	if (bytes < 0) { perror("uread: sendto"); }
+ 	free(buffer);
+         return;
+     }
+ 
+     /* check for netrek server requests ... version field first */
      if (p[0] != 'a') {
  	log_msg("uread: bad version %02.2x from %s\n", p[0],
  	    /* inet_ntoa(srvbuf.addr)); */
***************
*** 1065,1071 ****
  
  		/* server is being nice, accept the update and return */
  		bcopy(&srvbuf, sp, sizeof(SERVER));
! 		log_msg("usock: updated by %s (%s)\n", srvbuf.hostname, 
  		    srvbuf.ip_addr );
  		return;
          }
--- 1082,1088 ----
  
  		/* server is being nice, accept the update and return */
  		bcopy(&srvbuf, sp, sizeof(SERVER));
! 		log_msg("uread: updated by %s (%s)\n", srvbuf.hostname, 
  		    srvbuf.ip_addr );
  		return;
          }
***************
*** 1085,1091 ****
      bcopy(&srvbuf, &servers[server_count], sizeof(SERVER));
      server_count++;
  
!     log_msg("usock: new server %s (%s)\n", srvbuf.hostname, srvbuf.ip_addr );
      return;
  
  truncated:
--- 1102,1108 ----
      bcopy(&srvbuf, &servers[server_count], sizeof(SERVER));
      server_count++;
  
!     log_msg("uread: new server %s (%s)\n", srvbuf.hostname, srvbuf.ip_addr );
      return;
  
  truncated:
***************
*** 1122,1130 ****
      FD_ZERO(&readfd_set);
      FD_ZERO(&writefd_set);
  
!     /* create UDP socket for servers to send us updates */
      if ((usock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
!         perror("ERROR: unable to create UDP socket for server reports");
          log_msg("exit: unable to create UDP socket");
          exit(1);
      }
--- 1139,1147 ----
      FD_ZERO(&readfd_set);
      FD_ZERO(&writefd_set);
  
!     /* create UDP socket for servers and clients to talk to */
      if ((usock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
!         perror("ERROR: unable to create UDP socket for listening");
          log_msg("exit: unable to create UDP socket");
          exit(1);
      }
*** meta.h.orig	Sun Aug  9 14:47:13 1998
--- meta.h	Tue Aug 18 18:22:20 1998
***************
*** 80,85 ****
--- 80,86 ----
  #define MAX_PLAYER	32		/* must be >= server MAXPLAYER */
  #define NUM_TYPES	8		/* #of different ship types */
  #define PNUM_TYPES	16		/* #of different ship types */
+ #define MAX_HOSTNAME	64
  
  /* global structure declarations */
  typedef enum { SS_WORKING, SS_QUEUE, SS_OPEN, SS_EMPTY, SS_NOCONN, SS_INIT }
***************
*** 93,99 ****
      PROBE_STATE pstate;		/* what we are trying to do (port or port-1) */
      CONN_STATE cstate;		/* what our connection status is */
      WHY_DEAD why_dead;		/* if status==SS_NOCONN, why? */
!     char hostname[64];	/* DNS */
      char ip_addr[32];	/* ASCII IP */
      long addr;		/* actual address */
      int  port;
--- 94,100 ----
      PROBE_STATE pstate;		/* what we are trying to do (port or port-1) */
      CONN_STATE cstate;		/* what our connection status is */
      WHY_DEAD why_dead;		/* if status==SS_NOCONN, why? */
!     char hostname[MAX_HOSTNAME];	/* DNS */
      char ip_addr[32];	/* ASCII IP */
      long addr;		/* actual address */
      int  port;
*** disp_udp.c.orig	Sun Aug  9 14:19:16 1998
--- disp_udp.c	Mon Aug 24 18:53:53 1998
***************
*** 0 ****
--- 1,60 ----
+ /*
+  * disp_udp.c - output to client via returned buffer
+  */
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include "meta.h"
+ 
+ char *
+ display_udp(int *length)
+ {
+     SERVER *sp;
+     int srv, *sorted, count;
+     char *buffer, *bp;
+     time_t now = time(NULL);
+ 
+     /* sort and count the servers that will be returned */
+     sorted = sort_servers();
+     count = 0;
+     for (srv = 0; srv < server_count; srv++) {
+ 	sp = &servers[sorted[srv]];
+ 	if (sp->status == SS_WORKING) sp = &prev_info;
+ 	if (sp->status == SS_INIT) continue;
+ 	if (sp->status == SS_WORKING) continue;
+ 	count++;
+     }
+ 
+     /* estimate memory required and allocate it, match with sprintf()'s */
+     buffer = malloc((MAX_HOSTNAME+1 +6+1 +3+1 +6+1 +3+1 +3+1 +1+1 +1)*count+6);
+     /*			host        port stat age  play que  type \n	*/
+ 
+     /* out of memory? */
+     if ( buffer == NULL ) return "";
+     bp = buffer;
+ 
+     /* include the count at the top to ease the client's coding */
+     sprintf(bp,"r,%d\n",count);
+     bp += strlen(bp);
+ 
+     for (srv = 0; srv < server_count; srv++) {
+ 	sp = &servers[sorted[srv]];
+ 	if (sp->status == SS_WORKING) sp = &prev_info;
+ 	if (sp->status == SS_INIT) continue;
+ 	if (sp->status == SS_WORKING) continue;
+ 
+         sprintf(bp,"%s,%d,%d,%d,%d,%d,%c\n",
+ 	    sp->hostname,		/* host name of server		*/
+ 	    sp->port,			/* port number of server	*/
+ 	    sp->status,			/* metaserver status code	*/
+ 	    now - sp->last_update,	/* age of data in seconds	*/
+ 	    sp->player_count,		/* count of players on server	*/
+ 	    sp->queue_size,		/* length of wait queue		*/
+ 	    sp->type[0] );		/* type code, B, P, etc		*/
+         bp += strlen(bp);
+     }
+ 
+     *length = strlen(buffer);		/* for future optimisation	*/
+ 
+     return buffer;			/* caller must free buffer!	*/
+ }
*** Makefile.orig	Sun Aug  9 14:19:10 1998
--- Makefile	Tue Aug 18 18:22:27 1998
***************
*** 1,7 ****
  #
  # Makefile for MetaServerII
  #
! CFILES	= main.c scan.c server.c disp_old.c disp_new.c disp_web.c disp_info.c BecomeDaemon.c
  OFILES	= $(CFILES:.c=.o)
  HDRS	= meta.h packets.h copyright2.h
  TARGET	= metaserverII
--- 1,7 ----
  #
  # Makefile for MetaServerII
  #
! CFILES	= main.c scan.c server.c disp_old.c disp_new.c disp_web.c disp_udp.c disp_info.c BecomeDaemon.c
  OFILES	= $(CFILES:.c=.o)
  HDRS	= meta.h packets.h copyright2.h
  TARGET	= metaserverII

Follow-Ups: References: