/* > The one problem I see is that the list is getting sorted via the IP address & > port. Are we going this route or sorting by player number? I strongly suggest > sorting by player number. Which makes updating servers a little more CPU > intensive but the majority of the work is going to be user requests. The internal index is for updating. The list will have to be resorted on every change to player counts anyway. */ #include "svr.h" static struct server *servers[MAXSERVERS]; static int count; /* ** Internal comparison function. Compare one server entry with another and ** return zero if they are for the same server and port number, or either 1 ** or -1 according to how they are different. Used in calls to qsort() ** and bsearch(). */ static int compar0(struct server *one, struct server *two) { int value; if ( one == NULL && two != NULL ) return 1; if ( one != NULL && two == NULL ) return -1; if ( one == NULL && two == NULL ) return 0; value = memcmp ( one->source, two->source ); if ( value != 0 ) return value; value = strcmp ( one->server.port, two->server.port ); return value; } /* ** Internal comparison function. Compare one server entry with another and ** for the purposes of ordering the server list for output to the clients. ** Used in calls to qsort() and bsearch(). */ static int compar1(struct server *one, struct server *two) { int value; if ( one == NULL && two != NULL ) return 1; if ( one != NULL && two == NULL ) return -1; if ( one == NULL && two == NULL ) return 0; value = strcmp ( one->server.free, two->server.free ); if ( value != 0 ) return value; value = strcmp ( one->server.address, two->server.address ); return value; } int svr_initialise() { int i; for(i=0;ibogus = ( server->received - old->received < man_get_minupdsecs() ); /* free the old entry's packet buffer */ free(old->buffer); /* overwrite the new entry */ memcpy(old,server,sizeof(struct server)); } else { /* ignore insert if array full */ if(countreceived < cutoff) { /* yes; clear the array entry */ servers[i] = NULL; /* free the allocated storage */ free ( old->buffer ); free ( old ); /* count the expired entries */ expired++; } } /* if entries were expired or inserted, resort the array */ if(expired!=0 || inserted!=0) { /* brutally resort the primary array */ qsort(servers, count, sizeof(struct server *), compar0); count = count - expired; } } int svr_traverse ( int ((*compar)(const struct server *, const struct server *)), int ((*action)(const struct server *)) ) { int i; /* allocate a private copy of the server list */ auto struct server *ours[MAXSERVERS]; auto int tally; /* copy the real one into our copy */ tally = count; memcpy(ours, servers, sizeof(struct server *)* tally); /* sort the copy using the caller's comparison routine */ qsort(ours, tally, sizeof(struct server *), compar ); /* call the caller's action routine for every packet */ for(i=0;isource, server->received, server->buffer); } /* close file and return success */ fclose(file); return 1; } int svr_load() { char *name = man_get_database(); FILE *file; struct server *server; char buffer[MAXBUFFER]; char *line; file = fopen(name, "r"); if(file==NULL) return 0; /* first line must be our special marker, or we give up */ line = fgets(buffer,MAXBUFFER,file); if(line==NULL) { fclose(file); return 0; } if(strcmp(line,"~~~\n")) { fclose(file); return 0; } while(!feof(file)) { server = malloc(sizeof(server)); sscanf(file,"%08.8x\n",&server->source); sscanf(file,"%d\n",&server->received); line = fgets(buffer,MAXBUFFER,file); if (line==NULL) break; while(!strcmp(line,"~~~\n")) { line = fgets(line,MAXBUFFER-strlen(buffer),file); if (line==NULL) break; } server->length = strlen(buffer); server->buffer = malloc(server->length+1); memcpy(server->buffer,buffer,server->length+1); svr_update(server); } fclose(file); return 1; }