Commit 3647bea769d5f7d13af7ee97046bbdae9bfecdad
1 parent
9f59b128f3
Exists in
master
Fixed?
Showing 3 changed files with 17 additions and 17 deletions Inline Diff
server/server.c
View file @
3647bea
#include <sys/types.h> | 1 | 1 | #include <sys/types.h> | |
#include <sys/socket.h> | 2 | 2 | #include <sys/socket.h> | |
#include <arpa/inet.h> | 3 | 3 | #include <arpa/inet.h> | |
#include <netinet/in.h> | 4 | 4 | #include <netinet/in.h> | |
#include <stdio.h> | 5 | 5 | #include <stdio.h> | |
#include <stdlib.h> | 6 | 6 | #include <stdlib.h> | |
#include <string.h> | 7 | 7 | #include <string.h> | |
#include <netdb.h> | 8 | 8 | #include <netdb.h> | |
#include <errno.h> | 9 | 9 | #include <errno.h> | |
#include <unistd.h> | 10 | 10 | #include <unistd.h> | |
#include <time.h> | 11 | 11 | #include <time.h> | |
#include "../common/mot_maze.h" | 12 | 12 | #include "../common/mot_maze.h" | |
#include "server.h" | 13 | 13 | #include "server.h" | |
14 | 14 | |||
void * | 15 | 15 | void * | |
get_in_addr(struct sockaddr *sa) | 16 | 16 | get_in_addr(struct sockaddr *sa) | |
{ | 17 | 17 | { | |
if (sa->sa_family == AF_INET) | 18 | 18 | if (sa->sa_family == AF_INET) | |
{ | 19 | 19 | { | |
return &(((struct sockaddr_in*)sa)->sin_addr); | 20 | 20 | return &(((struct sockaddr_in*)sa)->sin_addr); | |
} | 21 | 21 | } | |
22 | 22 | |||
return &(((struct sockaddr_in6*)sa)->sin6_addr); | 23 | 23 | return &(((struct sockaddr_in6*)sa)->sin6_addr); | |
} | 24 | 24 | } | |
25 | 25 | |||
26 | 26 | |||
size_t | 27 | 27 | size_t | |
sendall(int s, char *buf, size_t len) | 28 | 28 | sendall(int s, char *buf, size_t len) | |
{ | 29 | 29 | { | |
int total = 0; // how many bytes we've sent | 30 | 30 | int total = 0; // how many bytes we've sent | |
int bytesleft = len; // how many we have left to send | 31 | 31 | int bytesleft = len; // how many we have left to send | |
int n; | 32 | 32 | int n; | |
33 | 33 | |||
while (total < len) | 34 | 34 | while (total < len) | |
{ | 35 | 35 | { | |
n = send(s, buf+total, bytesleft, 0); | 36 | 36 | n = send(s, buf+total, bytesleft, 0); | |
37 | 37 | |||
if (n == -1) | 38 | 38 | if (n == -1) | |
{ | 39 | 39 | { | |
perror("sendall"); | 40 | 40 | perror("sendall"); | |
return total; | 41 | 41 | return total; | |
} | 42 | 42 | } | |
43 | 43 | |||
total += n; | 44 | 44 | total += n; | |
bytesleft -= n; | 45 | 45 | bytesleft -= n; | |
} | 46 | 46 | } | |
return total; | 47 | 47 | return total; | |
} | 48 | 48 | } | |
49 | 49 | |||
50 | 50 | |||
size_t | 51 | 51 | size_t | |
recvall(int s, char *buf, size_t len) | 52 | 52 | recvall(int s, char *buf, size_t len) | |
{ | 53 | 53 | { | |
int total = 0; | 54 | 54 | int total = 0; | |
int bytesleft = len; | 55 | 55 | int bytesleft = len; | |
int n; | 56 | 56 | int n; | |
57 | 57 | |||
while (total < len) | 58 | 58 | while (total < len) | |
{ | 59 | 59 | { | |
if ((n = recv(s, buf, bytesleft, 0)) == -1) | 60 | 60 | if ((n = recv(s, buf, bytesleft, 0)) == -1) | |
{ | 61 | 61 | { | |
perror("recvall"); | 62 | 62 | perror("recvall"); | |
return total; | 63 | 63 | return total; | |
} | 64 | 64 | } | |
total += n; | 65 | 65 | total += n; | |
bytesleft -= n; | 66 | 66 | bytesleft -= n; | |
} | 67 | 67 | } | |
return total; | 68 | 68 | return total; | |
} | 69 | 69 | } | |
70 | 70 | |||
71 | 71 | |||
short | 72 | 72 | short | |
getshort(int sock) | 73 | 73 | getshort(int sock) | |
{ | 74 | 74 | { | |
short ret; | 75 | 75 | short ret; | |
recvall(sock, (char *) &ret, sizeof(short)); | 76 | 76 | recvall(sock, (char *) &ret, sizeof(short)); | |
77 | 77 | |||
return ntohs(ret); | 78 | 78 | return ntohs(ret); | |
} | 79 | 79 | } | |
80 | 80 | |||
/* | 81 | 81 | /* | |
* Return: 0 on success | 82 | 82 | * Return: 0 on success | |
* 1 on failure | 83 | 83 | * 1 on failure | |
*/ | 84 | 84 | */ | |
size_t | 85 | 85 | size_t | |
sendshort(int sock, short s) | 86 | 86 | sendshort(int sock, short s) | |
{ | 87 | 87 | { | |
s = htons(s); | 88 | 88 | s = htons(s); | |
return sendall(sock, (char *) &s, sizeof(s)) != sizeof(s); | 89 | 89 | return sendall(sock, (char *) &s, sizeof(s)) != sizeof(s); | |
} | 90 | 90 | } | |
91 | 91 | |||
int | 92 | 92 | int | |
main(int argc, char *argv[]) | 93 | 93 | main(int argc, char *argv[]) | |
{ | 94 | 94 | { | |
int ssockfd, csockfd, err;; | 95 | 95 | int ssockfd, csockfd, err;; | |
unsigned int magic, x, y; | 96 | 96 | unsigned short magic, x, y; | |
unsigned int u; | 97 | 97 | unsigned int u; | |
struct addrinfo hints, *srvinfo, *p; | 98 | 98 | struct addrinfo hints, *srvinfo, *p; | |
struct sockaddr_storage caddr; | 99 | 99 | struct sockaddr_storage caddr; | |
socklen_t addr_size; | 100 | 100 | socklen_t addr_size; | |
size_t len, bytes_sent; | 101 | 101 | size_t len, bytes_sent; | |
Player_set *pset; | 102 | 102 | Player_set *pset; | |
103 | 103 | |||
int i, j; | 104 | 104 | int i, j; | |
105 | 105 | |||
/* For handling multiple clients using select() */ | 106 | 106 | /* For handling multiple clients using select() */ | |
107 | 107 | |||
fd_set master; | 108 | 108 | fd_set master; | |
fd_set read_fds; /* File descriptors with readable data */ | 109 | 109 | fd_set read_fds; /* File descriptors with readable data */ | |
int fdmax; /* Highest file descriptor in the master set */ | 110 | 110 | int fdmax; /* Highest file descriptor in the master set */ | |
int newfd; /* File descriptor for handling incoming connections */ | 111 | 111 | int newfd; /* File descriptor for handling incoming connections */ | |
char buf[256]; | 112 | 112 | char buf[256]; | |
int nbytes; | 113 | 113 | int nbytes; | |
char remoteIP[INET6_ADDRSTRLEN]; | 114 | 114 | char remoteIP[INET6_ADDRSTRLEN]; | |
115 | 115 | |||
int players_connected = 0; | 116 | 116 | int players_connected = 0; | |
time_t launchtime = 0; | 117 | 117 | time_t launchtime = 0; | |
unsigned char game_started = 0; | 118 | 118 | unsigned char game_started = 0; | |
119 | 119 | |||
/* Should be moved to config file/cli arg ALONG WITH hostname/port */ | 120 | 120 | /* Should be moved to config file/cli arg ALONG WITH hostname/port */ | |
int min_players = 2; | 121 | 121 | int min_players = 2; | |
time_t time_thresh = 2; | 122 | 122 | time_t time_thresh = 2; | |
123 | 123 | |||
FD_ZERO(&master); /* Empty the master set */ | 124 | 124 | FD_ZERO(&master); /* Empty the master set */ | |
FD_ZERO(&read_fds); /* Empty the readfds set */ | 125 | 125 | FD_ZERO(&read_fds); /* Empty the readfds set */ | |
pset = calloc(1, sizeof(Player_set)); | 126 | 126 | pset = calloc(1, sizeof(Player_set)); | |
127 | 127 | |||
genmaze(20, 20); | 128 | 128 | genmaze(20, 20); | |
memset(&hints, 0, sizeof(hints)); | 129 | 129 | memset(&hints, 0, sizeof(hints)); | |
130 | 130 | |||
/* Currently using TCP. */ | 131 | 131 | /* Currently using TCP. */ | |
hints.ai_family = AF_UNSPEC; | 132 | 132 | hints.ai_family = AF_UNSPEC; | |
hints.ai_flags = AI_PASSIVE; | 133 | 133 | hints.ai_flags = AI_PASSIVE; | |
hints.ai_socktype = SOCK_STREAM; | 134 | 134 | hints.ai_socktype = SOCK_STREAM; | |
hints.ai_protocol = IPPROTO_TCP; | 135 | 135 | hints.ai_protocol = IPPROTO_TCP; | |
136 | 136 | |||
if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo))) | 137 | 137 | if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo))) | |
{ | 138 | 138 | { | |
fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err)); | 139 | 139 | fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err)); | |
return 10; | 140 | 140 | return 10; | |
} | 141 | 141 | } | |
142 | 142 | |||
/* | 143 | 143 | /* | |
* Allocate socket file descriptor with address information acquired | 144 | 144 | * Allocate socket file descriptor with address information acquired | |
* from getaddrinfo. | 145 | 145 | * from getaddrinfo. | |
*/ | 146 | 146 | */ | |
147 | 147 | |||
if (ssockfd == -1) | 148 | 148 | if (ssockfd == -1) | |
{ | 149 | 149 | { | |
perror("Failed to allocate server socket descriptor."); | 150 | 150 | perror("Failed to allocate server socket descriptor."); | |
return 7; | 151 | 151 | return 7; | |
} | 152 | 152 | } | |
153 | 153 | |||
for (p = srvinfo; p != NULL; p = p->ai_next) | 154 | 154 | for (p = srvinfo; p != NULL; p = p->ai_next) | |
{ | 155 | 155 | { | |
ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol); | 156 | 156 | ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol); | |
157 | 157 | |||
if( ssockfd < 0 ) | 158 | 158 | if( ssockfd < 0 ) | |
{ | 159 | 159 | { | |
continue; | 160 | 160 | continue; | |
} | 161 | 161 | } | |
162 | 162 | |||
/* | 163 | 163 | /* | |
* If system thinks the socket is on use but it isn't, fix it... | 164 | 164 | * If system thinks the socket is on use but it isn't, fix it... | |
*/ | 165 | 165 | */ | |
setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); | 166 | 166 | setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); | |
167 | 167 | |||
/* | 168 | 168 | /* | |
* Bind socket to port. | 169 | 169 | * Bind socket to port. | |
*/ | 170 | 170 | */ | |
if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0) | 171 | 171 | if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0) | |
{ | 172 | 172 | { | |
close(ssockfd); | 173 | 173 | close(ssockfd); | |
continue; | 174 | 174 | continue; | |
} | 175 | 175 | } | |
176 | 176 | |||
break; | 177 | 177 | break; | |
} | 178 | 178 | } | |
179 | 179 | |||
180 | 180 | |||
/* | 181 | 181 | /* | |
* If p reached NULL, it means we didn't bind at all. | 182 | 182 | * If p reached NULL, it means we didn't bind at all. | |
*/ | 183 | 183 | */ | |
184 | 184 | |||
if (p == NULL) | 185 | 185 | if (p == NULL) | |
{ | 186 | 186 | { | |
fprintf( stderr, "failed to bind ssockfd\n" ); | 187 | 187 | fprintf( stderr, "failed to bind ssockfd\n" ); | |
return 2; | 188 | 188 | return 2; | |
} | 189 | 189 | } | |
190 | 190 | |||
freeaddrinfo(srvinfo); | 191 | 191 | freeaddrinfo(srvinfo); | |
192 | 192 | |||
/* | 193 | 193 | /* | |
* Start listening on server socket descriptor. | 194 | 194 | * Start listening on server socket descriptor. | |
*/ | 195 | 195 | */ | |
196 | 196 | |||
if (listen(ssockfd, BACKLOG ) == -1) | 197 | 197 | if (listen(ssockfd, BACKLOG ) == -1) | |
{ | 198 | 198 | { | |
perror("Server can't listen."); | 199 | 199 | perror("Server can't listen."); | |
return 3; | 200 | 200 | return 3; | |
} | 201 | 201 | } | |
202 | 202 | |||
/* | 203 | 203 | /* | |
* Add ssockfd to master set of sockets. | 204 | 204 | * Add ssockfd to master set of sockets. | |
*/ | 205 | 205 | */ | |
FD_SET(ssockfd, &master); | 206 | 206 | FD_SET(ssockfd, &master); | |
207 | 207 | |||
/* | 208 | 208 | /* | |
* Since ssockfd is currently the only socket in master, | 209 | 209 | * Since ssockfd is currently the only socket in master, | |
* it's the highest descriptor. | 210 | 210 | * it's the highest descriptor. | |
*/ | 211 | 211 | */ | |
fdmax = ssockfd; | 212 | 212 | fdmax = ssockfd; | |
213 | 213 | |||
214 | 214 | |||
while (1) | 215 | 215 | while (1) | |
{ | 216 | 216 | { | |
read_fds = master; | 217 | 217 | read_fds = master; | |
218 | 218 | |||
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1) | 219 | 219 | if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1) | |
{ | 220 | 220 | { | |
perror("select"); | 221 | 221 | perror("select"); | |
return 4; | 222 | 222 | return 4; | |
} | 223 | 223 | } | |
224 | 224 | |||
/* | 225 | 225 | /* | |
* Now read_fds has only those sockets that have readable data to | 226 | 226 | * Now read_fds has only those sockets that have readable data to | |
* show. | 227 | 227 | * show. | |
* Run through all the sockets to find data to read. | 228 | 228 | * Run through all the sockets to find data to read. | |
*/ | 229 | 229 | */ | |
230 | 230 | |||
for (i = 0; i <= fdmax; i++) | 231 | 231 | for (i = 0; i <= fdmax; i++) | |
{ | 232 | 232 | { | |
if (!FD_ISSET(i, &read_fds)) | 233 | 233 | if (!FD_ISSET(i, &read_fds)) | |
{ | 234 | 234 | { | |
continue; | 235 | 235 | continue; | |
} | 236 | 236 | } | |
237 | 237 | |||
/* If we're here, i has data to show */ | 238 | 238 | /* If we're here, i has data to show */ | |
if (i == ssockfd) | 239 | 239 | if (i == ssockfd) | |
{ | 240 | 240 | { | |
/* Handle new connections. */ | 241 | 241 | /* Handle new connections. */ | |
242 | 242 | |||
addr_size = sizeof caddr; | 243 | 243 | addr_size = sizeof caddr; | |
newfd = accept(ssockfd, | 244 | 244 | newfd = accept(ssockfd, | |
(struct sockaddr *) &caddr, &addr_size); | 245 | 245 | (struct sockaddr *) &caddr, &addr_size); | |
246 | 246 | |||
if (newfd == -1) | 247 | 247 | if (newfd == -1) | |
{ | 248 | 248 | { | |
perror("accept"); | 249 | 249 | perror("accept"); | |
continue; | 250 | 250 | continue; | |
} | 251 | 251 | } | |
252 | 252 | |||
/* Add the new socket descriptor to master. */ | 253 | 253 | /* Add the new socket descriptor to master. */ | |
FD_SET(newfd, &master); | 254 | 254 | FD_SET(newfd, &master); | |
255 | 255 | |||
if (newfd > fdmax) | 256 | 256 | if (newfd > fdmax) | |
{ | 257 | 257 | { | |
fdmax = newfd; | 258 | 258 | fdmax = newfd; | |
} | 259 | 259 | } | |
printf("server: new connection from %s on socket %d\n", | 260 | 260 | printf("server: new connection from %s on socket %d\n", | |
inet_ntop(caddr.ss_family, | 261 | 261 | inet_ntop(caddr.ss_family, | |
get_in_addr((struct sockaddr*)&caddr), | 262 | 262 | get_in_addr((struct sockaddr*)&caddr), | |
remoteIP, INET6_ADDRSTRLEN), newfd ); | 263 | 263 | remoteIP, INET6_ADDRSTRLEN), newfd ); | |
264 | 264 | |||
if (game_started) | 265 | 265 | if (game_started) | |
{ | 266 | 266 | { | |
magic = htons(SRV_BUSY); | 267 | 267 | magic = htons(SRV_BUSY); | |
sendshort(newfd, magic); | 268 | 268 | sendshort(newfd, magic); | |
close(newfd); | 269 | 269 | close(newfd); | |
FD_CLR(newfd, &master); | 270 | 270 | FD_CLR(newfd, &master); | |
continue; | 271 | 271 | continue; | |
} | 272 | 272 | } | |
273 | 273 | |||
printf("checking if game started!!\n"); | 274 | 274 | printf("checking if game started!!\n"); | |
275 | 275 | |||
if (!launchtime) launchtime = time(NULL); | 276 | 276 | if (!launchtime) launchtime = time(NULL); | |
277 | 277 | |||
players_connected++; | 278 | 278 | players_connected++; | |
handle_connecting_player(newfd, pset); | 279 | 279 | handle_connecting_player(newfd, pset); | |
280 | 280 | |||
printf("new connection handled!!\n"); | 281 | 281 | printf("new connection handled!!\n"); | |
if (time(NULL) - launchtime >= time_thresh && | 282 | 282 | if (time(NULL) - launchtime >= time_thresh && | |
players_connected >= min_players) | 283 | 283 | players_connected >= min_players) | |
{ | 284 | 284 | { | |
printf("game started!!\n"); | 285 | 285 | printf("game started!!\n"); | |
begin_game(pset); | 286 | 286 | begin_game(pset); | |
game_started = 1; | 287 | 287 | game_started = 1; | |
} | 288 | 288 | } | |
} | 289 | 289 | } | |
else | 290 | 290 | else | |
{ | 291 | 291 | { | |
/* Handle data from a client. (ONLY A SHORT/magic no) */ | 292 | 292 | /* Handle data from a client. (ONLY A SHORT/magic no) */ | |
293 | 293 | |||
if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0) | 294 | 294 | if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0) | |
{ | 295 | 295 | { | |
if (nbytes < 0) | 296 | 296 | if (nbytes < 0) | |
{ | 297 | 297 | { | |
perror("recv"); | 298 | 298 | perror("recv"); | |
} | 299 | 299 | } | |
300 | 300 | |||
printf("server: socket %d hung up\n", i); | 301 | 301 | printf("server: socket %d hung up\n", i); | |
broadcast_disconnect(pset, i, 0); | 302 | 302 | broadcast_disconnect(pset, i, 0); | |
close(i); | 303 | 303 | close(i); | |
FD_CLR(i, &master); | 304 | 304 | FD_CLR(i, &master); | |
305 | 305 | |||
continue; | 306 | 306 | continue; | |
} | 307 | 307 | } | |
308 | 308 | |||
switch (htons(magic)) | 309 | 309 | switch (htons(magic)) | |
{ | 310 | 310 | { | |
case PLAYER_MOV: | 311 | 311 | case PLAYER_MOV: | |
x = getshort(i); | 312 | 312 | x = getshort(i); | |
y = getshort(i); | 313 | 313 | y = getshort(i); | |
printf("player with socket %d moved to %d, %d\n", | 314 | 314 | printf("player with socket %d moved to %d, %d\n", | |
i, x, y); | 315 | 315 | i, x, y); | |
break; | 316 | 316 | break; | |
} | 317 | 317 | } | |
318 | 318 | |||
for (j = 0; j <= fdmax; j++) | 319 | 319 | for (j = 0; j <= fdmax; j++) | |
{ | 320 | 320 | { | |
if (FD_ISSET(j, &master)) | 321 | 321 | if (FD_ISSET(j, &master)) | |
{ | 322 | 322 | { | |
Player *justMoved = player_byfd(pset, i); | 323 | 323 | Player *justMoved = player_byfd(pset, i); | |
Player *coll; | 324 | 324 | Player *coll; | |
int movPnum = justMoved->playerno; | 325 | 325 | int movPnum = justMoved->playerno; | |
326 | 326 | |||
/* | 327 | 327 | /* | |
* If the player that just moved is a hunter, and it | 328 | 328 | * If the player that just moved is a hunter, and it | |
* just stepped on a regular player, kill the (regular) | 329 | 329 | * just stepped on a regular player, kill the (regular) | |
* player! | 330 | 330 | * player! | |
*/ | 331 | 331 | */ | |
if (justMoved->type && | 332 | 332 | if (justMoved->type && | |
(coll = check_collision(pset, justMoved)) != NULL) | 333 | 333 | (coll = check_collision(pset, justMoved)) != NULL) | |
{ | 334 | 334 | { | |
int dead = coll->fd; | 335 | 335 | int dead = coll->fd; | |
336 | 336 | |||
printf("%s died, socket %d dropped.\n", coll->name, dead); | 337 | 337 | printf("%s died, socket %d dropped.\n", coll->name, dead); | |
broadcast_disconnect(pset, dead, 1); | 338 | 338 | broadcast_disconnect(pset, dead, 1); | |
close(dead); | 339 | 339 | close(dead); | |
FD_CLR(dead, &master); | 340 | 340 | FD_CLR(dead, &master); | |
} | 341 | 341 | } | |
342 | 342 | |||
/* | 343 | 343 | /* | |
* Avoid sending the data to the current client and | 344 | 344 | * Avoid sending the data to the current client and | |
* server. | 345 | 345 | * server. | |
*/ | 346 | 346 | */ | |
if (j != ssockfd | 347 | 347 | if (j != ssockfd | |
&& j != i | 348 | 348 | && j != i | |
&& sendMov(j, movPnum, x, y) == -1) | 349 | 349 | && sendMov(j, movPnum, x, y) == -1) | |
{ | 350 | 350 | { | |
perror("send"); | 351 | 351 | perror("send"); | |
} | 352 | 352 | } | |
} | 353 | 353 | } | |
} | 354 | 354 | } | |
355 | 355 | |||
} | 356 | 356 | } | |
} | 357 | 357 | } | |
} | 358 | 358 | } | |
359 | 359 | |||
360 | 360 | |||
/* | 361 | 361 | /* | |
* Free things (sockets, addrinfo, player data, maze) and exit. | 362 | 362 | * Free things (sockets, addrinfo, player data, maze) and exit. | |
*/ | 363 | 363 | */ | |
close(ssockfd); | 364 | 364 | close(ssockfd); | |
close(csockfd); | 365 | 365 | close(csockfd); | |
freeaddrinfo(srvinfo); | 366 | 366 | freeaddrinfo(srvinfo); | |
free(MAZE.data); | 367 | 367 | free(MAZE.data); | |
368 | 368 | |||
return 0; | 369 | 369 | return 0; | |
} | 370 | 370 | } | |
371 | 371 | |||
void | 372 | 372 | void | |
handle_connecting_player(int newfd, Player_set *pset) | 373 | 373 | handle_connecting_player(int newfd, Player_set *pset) | |
{ | 374 | 374 | { | |
char *pname; | 375 | 375 | char *pname; | |
unsigned char pnum; | 376 | 376 | unsigned char pnum; | |
unsigned int magic; | 377 | 377 | unsigned short magic; | |
unsigned int u; | 378 | 378 | unsigned int u; | |
379 | 379 | |||
/* | 380 | 380 | /* | |
* When a player first connects, send maze magic, data width, size. | 381 | 381 | * When a player first connects, send maze magic, data width, size. | |
* Then send the maze itself. Then await confirmation. | 382 | 382 | * Then send the maze itself. Then await confirmation. | |
*/ | 383 | 383 | */ | |
384 | 384 | |||
add_player(pset); | 385 | 385 | add_player(pset); | |
magic = htons(MAZE_MAGIC); | 386 | 386 | magic = htons(MAZE_MAGIC); | |
sendall(newfd, (char *) &magic, sizeof(magic)); | 387 | 387 | sendall(newfd, (char *) &magic, sizeof(magic)); | |
388 | 388 | |||
/* Maze width */ | 389 | 389 | /* Maze width */ | |
u = htonl(MAZE.w); | 390 | 390 | u = htonl(MAZE.w); | |
sendall(newfd, (char *) &u, sizeof(u)); | 391 | 391 | sendall(newfd, (char *) &u, sizeof(u)); | |
392 | 392 | |||
u = htonl(MAZE.size); | 393 | 393 | u = htonl(MAZE.size); | |
sendall(newfd, (char *) &u, sizeof(u)); | 394 | 394 | sendall(newfd, (char *) &u, sizeof(u)); | |
395 | 395 | |||
sendall(newfd, (char *) MAZE.data, MAZE.size); | 396 | 396 | sendall(newfd, (char *) MAZE.data, MAZE.size); | |
397 | 397 | |||
if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic) | 398 | 398 | if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic) | |
|| ntohs(magic) != MAZE_MAGIC) | 399 | 399 | || ntohs(magic) != MAZE_MAGIC) | |
{ | 400 | 400 | { | |
fprintf(stderr, "Failed to get client confirmation\n"); | 401 | 401 | fprintf(stderr, "Failed to get client confirmation\n"); | |
exit(1); | 402 | 402 | exit(1); | |
} | 403 | 403 | } | |
404 | 404 | |||
pname = malloc(PNAMELEN); | 405 | 405 | pname = malloc(PNAMELEN); | |
recvall(newfd, pname, PNAMELEN); | 406 | 406 | recvall(newfd, pname, PNAMELEN); | |
printf("%s connected !!!\n", pname); | 407 | 407 | printf("%s connected !!!\n", pname); | |
408 | 408 | |||
sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum)); | 409 | 409 | sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum)); | |
410 | 410 | |||
pset->last->name = pname; | 411 | 411 | pset->last->name = pname; | |
pset->last->x = -1; | 412 | 412 | pset->last->x = -1; | |
pset->last->y = -1; | 413 | 413 | pset->last->y = -1; | |
pset->last->fd = newfd; | 414 | 414 | pset->last->fd = newfd; | |
printf("new file descriptor: %d (%d)\n", pset->last->fd,newfd); | 415 | 415 | printf("new file descriptor: %d (%d)\n", pset->last->fd,newfd); | |
} | 416 | 416 | } | |
417 | 417 | |||
static void | 418 | 418 | static void | |
send_dc(Player *p, int pno_removed, unsigned int sig) | 419 | 419 | send_dc(Player *p, int pno_removed, unsigned short sig) | |
{ | 420 | 420 | { | |
sendshort(p->fd, sig); | 421 | 421 | sendshort(p->fd, sig); | |
sendshort(p->fd, pno_removed); | 422 | 422 | sendshort(p->fd, pno_removed); | |
} | 423 | 423 | } | |
424 | 424 | |||
/* | 425 | 425 | /* | |
* Remove player with file descriptor fd from the list, and broadcast its | 426 | 426 | * Remove player with file descriptor fd from the list, and broadcast its | |
* disconnecting. | 427 | 427 | * disconnecting. | |
*/ | 428 | 428 | */ | |
void | 429 | 429 | void | |
broadcast_disconnect(Player_set *pset, int fd, int death) | 430 | 430 | broadcast_disconnect(Player_set *pset, int fd, int death) | |
{ | 431 | 431 | { | |
Player *to_remove = player_byfd(pset, fd); | 432 | 432 | Player *to_remove = player_byfd(pset, fd); | |
int remove_pno = to_remove->playerno; | 433 | 433 | int remove_pno = to_remove->playerno; | |
rm_player(pset, to_remove); | 434 | 434 | rm_player(pset, to_remove); | |
pset_map(pset, &send_dc, remove_pno, death ? PLAYER_DIE : PLAYER_DC); | 435 | 435 | pset_map(pset, &send_dc, remove_pno, death ? PLAYER_DIE : PLAYER_DC); | |
} | 436 | 436 | } | |
437 | 437 | |||
/* | 438 | 438 | /* | |
* Check if some player in `pset' has the same x, y as `node'. Return the | 439 | 439 | * Check if some player in `pset' has the same x, y as `node'. Return the | |
* first player that is colliding, or NULL if there are no collisions. | 440 | 440 | * first player that is colliding, or NULL if there are no collisions. | |
*/ | 441 | 441 | */ | |
Player * | 442 | 442 | Player * | |
check_collision(Player_set *pset, Player *node) | 443 | 443 | check_collision(Player_set *pset, Player *node) | |
{ | 444 | 444 | { | |
Player *temp; | 445 | 445 | Player *temp; | |
446 | 446 | |||
for (temp = pset->first; temp != NULL; temp = temp->next) | 447 | 447 | for (temp = pset->first; temp != NULL; temp = temp->next) | |
{ | 448 | 448 | { | |
if (temp != node && temp->x == node->x && temp->y == node->y) | 449 | 449 | if (temp != node && temp->x == node->x && temp->y == node->y) | |
return temp; | 450 | 450 | return temp; | |
} | 451 | 451 | } | |
return NULL; | 452 | 452 | return NULL; | |
} | 453 | 453 | } | |
454 | 454 | |||
455 | 455 | |||
void | 456 | 456 | void | |
set_positions(Player_set *pset) | 457 | 457 | set_positions(Player_set *pset) | |
{ | 458 | 458 | { | |
Player *temp; | 459 | 459 | Player *temp; | |
for (temp = pset->first; temp != NULL; temp = temp->next) | 460 | 460 | for (temp = pset->first; temp != NULL; temp = temp->next) | |
{ | 461 | 461 | { |
server/server.h
View file @
3647bea
#ifndef _MOTSRV_H_ | 1 | 1 | #ifndef _MOTSRV_H_ | |
#define _MOTSRV_H_ | 2 | 2 | #define _MOTSRV_H_ | |
3 | 3 | |||
#define MOTSRV_ADDR "127.0.0.1" | 4 | 4 | #define MOTSRV_ADDR "127.0.0.1" | |
#define MOTSRV_PORT "6666" | 5 | 5 | #define MOTSRV_PORT "6666" | |
#define BACKLOG 8 | 6 | 6 | #define BACKLOG 8 | |
7 | 7 | |||
#define PNAMELEN 32 | 8 | 8 | #define PNAMELEN 32 | |
#define MAX_PLAYERNUM 32 | 9 | 9 | #define MAX_PLAYERNUM 32 | |
10 | 10 | |||
#define MAZE_MAGIC 0x6D7A | 11 | 11 | #define MAZE_MAGIC 0x6D7A | |
#define ADD_PLAYER 0x4E45 | 12 | 12 | #define ADD_PLAYER 0x4E45 | |
#define HUNTER 0x4855 | 13 | 13 | #define HUNTER 0x4855 | |
#define ILLEGAL_MOV 0xF000 | 14 | 14 | #define ILLEGAL_MOV 0xF000 | |
#define PLAYER_MOV 0x4D4F | 15 | 15 | #define PLAYER_MOV 0x4D4F | |
#define PLAYER_DC 0x4443 | 16 | 16 | #define PLAYER_DC 0x4443 | |
#define PLAYER_DIE 0x4B4F | 17 | 17 | #define PLAYER_DIE 0x4B4F | |
#define PLAYER_WIN 0x5749 | 18 | 18 | #define PLAYER_WIN 0x5749 | |
#define SRV_BUSY 0xEEEE | 19 | 19 | #define SRV_BUSY 0xEEEE | |
20 | 20 | |||
#define _MOT_SERVER | 21 | 21 | #define _MOT_SERVER | |
22 | 22 | |||
/* Player linked list stuff */ | 23 | 23 | /* Player linked list stuff */ | |
24 | 24 | |||
typedef struct _player Player; | 25 | 25 | typedef struct _player Player; | |
typedef struct _player_set Player_set; | 26 | 26 | typedef struct _player_set Player_set; | |
27 | 27 | |||
struct _player | 28 | 28 | struct _player | |
{ | 29 | 29 | { | |
char *name; | 30 | 30 | char *name; | |
short x, y; | 31 | 31 | short x, y; | |
32 | 32 | |||
int fd; | 33 | 33 | int fd; | |
unsigned char playerno; | 34 | 34 | unsigned char playerno; | |
unsigned char type; // 0 is prey, 1 is predator | 35 | 35 | unsigned char type; // 0 is prey, 1 is predator | |
unsigned char dead; | 36 | 36 | unsigned char dead; | |
37 | 37 | |||
Player *next; | 38 | 38 | Player *next; | |
Player *prev; | 39 | 39 | Player *prev; | |
}; | 40 | 40 | }; | |
41 | 41 | |||
struct _player_set | 42 | 42 | struct _player_set | |
{ | 43 | 43 | { | |
Player *first; | 44 | 44 | Player *first; | |
Player *last; | 45 | 45 | Player *last; | |
Player *cur; | 46 | 46 | Player *cur; | |
int last_pno; | 47 | 47 | int last_pno; | |
}; | 48 | 48 | }; | |
49 | 49 | |||
void begin_game(Player_set *pset); | 50 | 50 | void begin_game(Player_set *pset); | |
int sendMov(int psock, short int movepno, int x, int y); | 51 | 51 | int sendMov(int psock, short int movepno, int x, int y); | |
void broadcast_disconnect(Player_set *pset, int fd, int death); | 52 | 52 | void broadcast_disconnect(Player_set *pset, int fd, int death); | |
Player *check_collision(Player_set *pset, Player *node); | 53 | 53 | Player *check_collision(Player_set *pset, Player *node); |
server/srv_player.c
View file @
3647bea
/* | 1 | 1 | /* | |
* VERY FAST VERY OPTIMIZED BRUTE FORCE LINEAR SEARCH LINKED LIST ALONG | 2 | 2 | * VERY FAST VERY OPTIMIZED BRUTE FORCE LINEAR SEARCH LINKED LIST ALONG | |
* WITH select() FOR AMAZING BLAZING FAST DATACENTER GRADE ENTERPRISE | 3 | 3 | * WITH select() FOR AMAZING BLAZING FAST DATACENTER GRADE ENTERPRISE | |
* SERVER PERFORMANCE | 4 | 4 | * SERVER PERFORMANCE | |
*/ | 5 | 5 | */ | |
6 | 6 | |||
#include <stdlib.h> | 7 | 7 | #include <stdlib.h> | |
#include "server.h" | 8 | 8 | #include "server.h" | |
9 | 9 | |||
Player_set * | 10 | 10 | Player_set * | |
init_pset() | 11 | 11 | init_pset() | |
{ | 12 | 12 | { | |
return calloc(1, sizeof(Player_set)); | 13 | 13 | return calloc(1, sizeof(Player_set)); | |
} | 14 | 14 | } | |
15 | 15 | |||
void | 16 | 16 | void | |
free_pset(Player_set *p) | 17 | 17 | free_pset(Player_set *p) | |
{ | 18 | 18 | { | |
/* | 19 | 19 | /* | |
* Scan through the entire linked list and free each element of each | 20 | 20 | * Scan through the entire linked list and free each element of each | |
* struct, then free p. | 21 | 21 | * struct, then free p. | |
*/ | 22 | 22 | */ | |
while (p->first != NULL) | 23 | 23 | while (p->first != NULL) | |
{ | 24 | 24 | { | |
rm_player(p, p->first); | 25 | 25 | rm_player(p, p->first); | |
} | 26 | 26 | } | |
27 | 27 | |||
free(p); | 28 | 28 | free(p); | |
} | 29 | 29 | } | |
30 | 30 | |||
/* | 31 | 31 | /* | |
* Add a player at the end of the linked list. Make the current Player | 32 | 32 | * Add a player at the end of the linked list. Make the current Player | |
* element in the set point to this new player. | 33 | 33 | * element in the set point to this new player. | |
*/ | 34 | 34 | */ | |
void | 35 | 35 | void | |
add_player(Player_set *set) | 36 | 36 | add_player(Player_set *set) | |
{ | 37 | 37 | { | |
if (set->first == NULL) | 38 | 38 | if (set->first == NULL) | |
{ | 39 | 39 | { | |
/* Player elements should be initialized to all zeroes. */ | 40 | 40 | /* Player elements should be initialized to all zeroes. */ | |
set->first = calloc(1, sizeof(Player)); | 41 | 41 | set->first = calloc(1, sizeof(Player)); | |
set->cur = set->last = set->first; | 42 | 42 | set->cur = set->last = set->first; | |
} | 43 | 43 | } | |
else | 44 | 44 | else | |
{ | 45 | 45 | { | |
set->last->next = calloc(1, sizeof(Player)); | 46 | 46 | set->last->next = calloc(1, sizeof(Player)); | |
set->cur = set->last = set->last->next; | 47 | 47 | set->cur = set->last = set->last->next; | |
} | 48 | 48 | } | |
set->last->playerno = ++(set->last_pno); | 49 | 49 | set->last->playerno = ++(set->last_pno); | |
} | 50 | 50 | } | |
51 | 51 | |||
void | 52 | 52 | void | |
rm_player(Player_set *set, Player *p) | 53 | 53 | rm_player(Player_set *set, Player *p) | |
{ | 54 | 54 | { | |
if (p->prev != NULL) | 55 | 55 | if (p->prev != NULL) | |
{ | 56 | 56 | { | |
p->prev->next = p->next; | 57 | 57 | p->prev->next = p->next; | |
} | 58 | 58 | } | |
59 | 59 | |||
if (p->next != NULL) | 60 | 60 | if (p->next != NULL) | |
{ | 61 | 61 | { | |
p->next->prev = p->prev; | 62 | 62 | p->next->prev = p->prev; | |
} | 63 | 63 | } | |
64 | 64 | |||
if (set->first == p) | 65 | 65 | if (set->first == p) | |
{ | 66 | 66 | { | |
set->first = p->next; | 67 | 67 | set->first = p->next; | |
} | 68 | 68 | } | |
69 | 69 | |||
if (set->last == p) | 70 | 70 | if (set->last == p) | |
{ | 71 | 71 | { | |
set->last = p->prev; | 72 | 72 | set->last = p->prev; | |
} | 73 | 73 | } | |
74 | 74 | |||
free(p->name); | 75 | 75 | free(p->name); | |
free(p); | 76 | 76 | free(p); | |
} | 77 | 77 | } | |
78 | 78 | |||
/* | 79 | 79 | /* | |
* Glorious optimized enterprise-level search algorithm. | 80 | 80 | * Glorious optimized enterprise-level search algorithm. | |
*/ | 81 | 81 | */ | |
Player * | 82 | 82 | Player * | |
player_byfd(Player_set *s, int fd) | 83 | 83 | player_byfd(Player_set *s, int fd) | |
{ | 84 | 84 | { | |
Player *this = s->first; | 85 | 85 | Player *this = s->first; | |
86 | 86 | |||
while (this != NULL) | 87 | 87 | while (this != NULL) | |
{ | 88 | 88 | { | |
if (this->fd == fd) | 89 | 89 | if (this->fd == fd) | |
{ | 90 | 90 | { | |
return this; | 91 | 91 | return this; | |
} | 92 | 92 | } | |
this = this->next; | 93 | 93 | this = this->next; | |
} | 94 | 94 | } | |
return NULL; | 95 | 95 | return NULL; | |
} | 96 | 96 | } | |
97 | 97 | |||
/* | 98 | 98 | /* | |
* blazing fast seeking algorithm | 99 | 99 | * blazing fast seeking algorithm | |
*/ | 100 | 100 | */ | |
Player * | 101 | 101 | Player * | |
player_byindex(Player_set *s, int index) | 102 | 102 | player_byindex(Player_set *s, int index) | |
{ | 103 | 103 | { | |
Player *this = s->first; | 104 | 104 | Player *this = s->first; | |
int counter = 0; | 105 | 105 | int counter = 0; | |
while (this != NULL) | 106 | 106 | while (this != NULL) | |
{ | 107 | 107 | { | |
if (counter++ == index) | 108 | 108 | if (counter++ == index) | |
{ | 109 | 109 | { | |
return this; | 110 | 110 | return this; | |
} | 111 | 111 | } | |
this = this->next; | 112 | 112 | this = this->next; | |
} | 113 | 113 | } | |
return NULL; | 114 | 114 | return NULL; | |
} | 115 | 115 | } |