editor: #undef O after use
[0verkill.git] / test_server.c
blob3153db63380152bb1296c071272c68cd4af016c2
1 #include <stdio.h>
2 #include <errno.h>
3 #ifndef WIN32
4 #include <sys/time.h>
5 #endif
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #ifndef WIN32
10 #include <sys/socket.h>
11 #include <netdb.h>
12 #include <netinet/in.h>
13 #else
14 #include <winsock.h>
15 #endif
17 #include "net.h"
18 #include "data.h"
19 #include "cfg.h"
20 #include "getopt.h"
21 #include "error.h"
23 #ifdef HAVE_SYS_SELECT_H
24 #include <sys/select.h>
25 #endif
28 static int port=DEFAULT_PORT;
29 static struct sockaddr_in server;
30 static char *name=NULL;
31 static int ttime=1;
32 static int verbose=0; /* whether to print a verbose message */
33 static int toplist=0; /* whether to print the list of top players */
34 int fd;
37 /* print info based on the recieved packet */
38 static void print_info (char * packet)
40 int n_pl; /* number of players */
42 n_pl=get_int(packet+1);
43 if (verbose) {
44 if (n_pl)
45 printf ((n_pl>1)? "There are %d players on the server.\n"
46 : "There is %d player on the server.\n", n_pl);
47 else
48 printf ("This server is not being used.\n");
49 } else
50 printf("%d\n",n_pl);
51 if (toplist && n_pl) {
52 unsigned int n_tp=*(packet+5); /* number of players on top list */
54 if (!n_tp)
55 printf("The top list is empty.\n");
56 else {
57 unsigned int i; /* iterator */
58 /* pointer to the next set of player-specific info */
59 char * p = packet+6;
61 packet[256-1]='\0';
62 printf ("Players on top list (%d):\n", n_tp);
63 printf ("rank\tfrags\tdeaths\tcolor\tname\n");
64 for (i=0; i<n_tp; i++) {
65 printf ("#%d\t%d\t%d\t%d\t%s\n",
66 i+1, get_int(p), get_int(p+4),
67 *(p+8), p+9);
68 p+=10+strlen(p+9);
75 /* find server address from name and put it into server structure */
76 static void find_server(void)
78 struct hostent *h;
80 h=gethostbyname(name);
81 if (!h){fprintf(stderr,"Error: Can't resolve server address.\n");exit(1);}
83 server.sin_family=AF_INET;
84 server.sin_port=htons(port);
85 server.sin_addr=*((struct in_addr*)(h->h_addr_list[0]));
89 /* find a socket and and initialize it */
90 static void init_socket(void)
92 fd=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
93 if(fd<0){fprintf(stderr,"Can't get socket.\n");exit(1);}
97 /* contact server, send information request and wait for response */
98 static int contact_server(void)
100 static char packet[256];
102 fd_set fds;
103 struct timeval tv;
104 tv.tv_sec=ttime;
105 tv.tv_usec=0;
106 FD_ZERO(&fds);
107 FD_SET(fd,&fds);
109 packet[0]=P_INFO;
111 send_packet(packet,1,(struct sockaddr*)(&server),0,0);
113 if (!select(fd+1,&fds,NULL,NULL,&tv)){fprintf(stderr,"No reply within %i second%s.\n",ttime,ttime==1?"":"s");return 1;}
115 if (recv_packet(packet,256,0,0,1,0,0)<0)
117 if (errno==EINTR){fprintf(stderr,"Server hung up.\n");return 1;}
118 else {fprintf(stderr,"Connection refused.\n");return 1;}
121 if ((*packet)!=P_INFO){fprintf(stderr,"Server error.\n");return 1;}
122 print_info(packet);
123 return 0;
128 /* write help to stdout */
129 static void print_help(void)
131 printf( "0verkill server testing program.\n"
132 "(c)2000 Brainsoft\n"
133 "Usage: test_server [-hvT] [-t <timeout>] [-p <port number>] -a <address>\n"
134 " -v produce verbose output\n"
135 " -T print the list of top players (implies -v)\n");
139 static int parse_number (const char * arg)
141 char *c; /* used by strtoul */
142 int n;
144 n=strtoul(arg,&c,10);
145 if (*c){fprintf(stderr,"Error: Not a number.\n");exit(1);}
146 if (errno==ERANGE)
148 if (!port){fprintf(stderr,"Error: Number underflow.\n");exit(1);}
149 else {fprintf(stderr,"Error: Number overflow.\n");exit(1);}
152 return n;
156 static void parse_command_line(int argc,char **argv)
158 int a;
160 while((a=getopt(argc,argv,"hvTp:a:t:")) != -1)
162 switch(a)
164 case 'T':
165 toplist = 1;
166 case 'v':
167 verbose = 1;
168 break;
170 case 'a':
171 name=optarg;
172 break;
174 case 'p':
175 port=parse_number(optarg);
176 break;
178 case 't':
179 ttime=parse_number(optarg);
180 if(ttime<1){fprintf(stderr,"Error: Timeout too low.\n");exit(1);}
181 break;
183 case '?':
184 case ':':
185 case 'h':
186 print_help();
187 exit(0);
193 int main(int argc, char **argv)
195 int ret;
196 #ifdef WIN32
197 WSADATA wd;
199 WSAStartup(0x101, &wd);
200 #endif
202 parse_command_line(argc,argv);
203 if (!name){print_help();exit(1);}
205 init_socket();
206 find_server();
207 ret=contact_server();
208 free_packet_buffer();
209 if(fd) close(fd);
210 return ret;