Almost working network support.

This commit is contained in:
Steinar Hamre 2008-10-09 19:20:37 +00:00
parent 7d42846db7
commit 227e1e9254
3 changed files with 138 additions and 56 deletions

View File

@ -1 +1,3 @@
CFLAGS=-g -std=c99 -Wall -pedantic CFLAGS=-g -std=gnu99 -Wall -pedantic
server: server.o net.o

View File

@ -10,6 +10,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include "net.h"
#define MAX_CLIENTS 2 #define MAX_CLIENTS 2
#define SRV_FDS 1 #define SRV_FDS 1
@ -18,10 +21,14 @@ int servsock;
struct pollfd pollfds[SRV_FDS+MAX_CLIENTS]; struct pollfd pollfds[SRV_FDS+MAX_CLIENTS];
int nclients = 0; int nclients = 0;
FILE *net_side[2];
int int
errx(int eval, const char *fmt, ...) { errx(int eval, const char *fmt, ...) {
va_list ap; va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
va_end(ap);
exit(eval); exit(eval);
} }
@ -32,21 +39,76 @@ net_server(int port) {
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(port); serveraddr.sin_port = htons(port);
servsock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); servsock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (servsock<0) if (servsock<0)
errx(1, "socket: %s", strerror(errno)); errx(1, "socket: %s\n", strerror(errno));
if (bind(servsock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) int r;
errx(1, "bind port %d: %s", port, strerror(errno)); do r=bind(servsock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
while ((r<0) && (errno==EADDRINUSE));
if (r < 0)
errx(1, "bind port %d: %s\n", port, strerror(errno));
if (listen(servsock, 10) < 0) if (listen(servsock, 10) < 0)
errx(1, "listen: %s", strerror(errno)); errx(1, "listen: %s\n", strerror(errno));
#if 1
// FIXME Temporary startup. Use net_poll for this later:
printf("Waiting for connections...\n");
for (int i=0; i<2; i++) {
struct sockaddr_in clientaddr;
int cfd;
socklen_t slen;
FILE *f;
cfd=accept(servsock, (struct sockaddr *)&clientaddr, &slen);
if (cfd<0)
errx(1, "accept: %s\n", strerror(errno));
// FIXME log, shout, or something
printf("client log on...\n");
f = fdopen(cfd, "r+");
if (!f)
errx(1, "fdopen: %s\n", strerror(errno));
setlinebuf(f);
fprintf(f, "Welcome!\n");
if (i==0)
fprintf(f, "Waiting for another player...\n");
fflush(f);
net_side[i]=f;
}
net_all_printf("Starting game\n");
#else
pollfds[0].fd=servsock; pollfds[0].fd=servsock;
pollfds[0].events=POLLIN|POLLERR|POLLHUP; pollfds[0].events=POLLIN|POLLERR|POLLHUP;
for (int i=SRV_FDS; i<(SRV_FDS+MAX_CLIENTS); i++) { for (int i=SRV_FDS; i<(SRV_FDS+MAX_CLIENTS); i++) {
pollfds[0].fd=-1; pollfds[0].fd=-1;
pollfds[0].events=0; pollfds[0].events=0;
} }
#endif
} }
void
net_all_flush() {
for (int i=0; i<2; i++)
fflush(net_side[i]);
}
void
net_all_printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
for (int i=0; i<2; i++)
vfprintf(net_side[i], fmt, ap);
va_end(ap);
}
void
net_side_printf(int side, const char *fmt, ...) {
va_list ap;
assert((side==0) || (side==1));
va_start(ap, fmt);
vfprintf(net_side[side], fmt, ap);
va_end(ap);
}
void void
net_poll() { net_poll() {

View File

@ -5,6 +5,8 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "net.h"
#define NONE 0 #define NONE 0
#define PHARAO 1 #define PHARAO 1
#define DJHED 2 #define DJHED 2
@ -105,9 +107,9 @@ void
print_piece_small(int piece, int side, int dir) print_piece_small(int piece, int side, int dir)
{ {
int index = (piece*4*2 + side*4 + dir) * 2; int index = (piece*4*2 + side*4 + dir) * 2;
printf("%c%c", net_all_printf("%c%c",
asciiart_small_pieces[index], asciiart_small_pieces[index],
asciiart_small_pieces[index+1]); asciiart_small_pieces[index+1]);
} }
int int
@ -116,6 +118,9 @@ laser_at(int x, int y)
return laser_pos[0] == x && laser_pos[1] == y; return laser_pos[0] == x && laser_pos[1] == y;
} }
// FIXME rewrite this to format the board in a char *?
void void
print_board_small() print_board_small()
{ {
@ -126,59 +131,59 @@ print_board_small()
vline = '|', hline = '-', xline = '+'; vline = '|', hline = '-', xline = '+';
lline = '#'; lline = '#';
printf("%s(%c)\n", sideinfo[RED].name, sideinfo[RED].ch); net_all_printf("%s(%c)\n", sideinfo[RED].name, sideinfo[RED].ch);
// column numbers // column numbers
printf(" %c", vline); net_all_printf(" %c", vline);
for (x = 0; x < BOARD_WIDTH; x++) { for (x = 0; x < BOARD_WIDTH; x++) {
printf(" %d%c", x, vline); net_all_printf(" %d%c", x, vline);
} }
printf("\n"); net_all_printf("\n");
// line // line
printf("%c%c%c", hline, hline, xline); net_all_printf("%c%c%c", hline, hline, xline);
for (x = 0; x < BOARD_WIDTH; x++) for (x = 0; x < BOARD_WIDTH; x++)
printf("%c%c%c", net_all_printf("%c%c%c",
laser_at(x, -1) ? lline : hline, laser_at(x, -1) ? lline : hline,
laser_at(x, -1) ? lline : hline, laser_at(x, -1) ? lline : hline,
xline); xline);
printf("%c%c\n", hline, hline); net_all_printf("%c%c\n", hline, hline);
for (y = 0; y < BOARD_HEIGHT; y++) { for (y = 0; y < BOARD_HEIGHT; y++) {
// row name // row name
printf(" %c%c", 'A'+y, laser_at(-1,y) ? lline : vline); net_all_printf(" %c%c", 'A'+y, laser_at(-1,y) ? lline : vline);
// row // row
for (x = 0; x < BOARD_WIDTH; x++) { for (x = 0; x < BOARD_WIDTH; x++) {
if (laser_at(x, y)) if (laser_at(x, y))
printf("%s", dead_piece); net_all_printf("%s", dead_piece);
else else
print_piece_small(board[x][y].piece, print_piece_small(board[x][y].piece,
board[x][y].side, board[x][y].side,
board[x][y].dir); board[x][y].dir);
printf("%c", (x==BOARD_WIDTH-1 && laser_at(x+1, y)) ? lline : vline); net_all_printf("%c", (x==BOARD_WIDTH-1 && laser_at(x+1, y)) ? lline : vline);
} }
// row name // row name
printf("%c\n", 'A'+y); net_all_printf("%c\n", 'A'+y);
// line // line
printf("%c%c%c", hline, hline, xline); net_all_printf("%c%c%c", hline, hline, xline);
for (x = 0; x < BOARD_WIDTH; x++) for (x = 0; x < BOARD_WIDTH; x++)
printf("%c%c%c", net_all_printf("%c%c%c",
(y==BOARD_HEIGHT-1 && laser_at(x, y+1)) ? lline : hline, (y==BOARD_HEIGHT-1 && laser_at(x, y+1)) ? lline : hline,
(y==BOARD_HEIGHT-1 && laser_at(x, y+1)) ? lline : hline, (y==BOARD_HEIGHT-1 && laser_at(x, y+1)) ? lline : hline,
xline); xline);
printf("%c%c\n", hline, hline); net_all_printf("%c%c\n", hline, hline);
} }
// column numbers // column numbers
printf(" %c", vline); net_all_printf(" %c", vline);
for (x = 0; x < BOARD_WIDTH; x++) for (x = 0; x < BOARD_WIDTH; x++)
printf(" %d%c", x, vline); net_all_printf(" %d%c", x, vline);
printf("\n"); net_all_printf("\n");
for (x = 0; x < (BOARD_WIDTH+2)*3-1-strlen(sideinfo[SILVER].name)-3; x++) for (x = 0; x < (BOARD_WIDTH+2)*3-1-strlen(sideinfo[SILVER].name)-3; x++)
printf(" "); net_all_printf(" ");
printf("%s(%c)\n", sideinfo[SILVER].name, sideinfo[SILVER].ch); net_all_printf("%s(%c)\n", sideinfo[SILVER].name, sideinfo[SILVER].ch);
} }
@ -196,7 +201,7 @@ laser(int side) {
2 2
*/ */
printf("LASER (%s)\n", sideinfo[side].name); net_all_printf("LASER (%s)\n", sideinfo[side].name);
assert(side == 0 || side == 1); assert(side == 0 || side == 1);
switch (side) { switch (side) {
@ -209,7 +214,7 @@ laser(int side) {
} }
for (;;) { for (;;) {
printf("pos: (%d,%d)\n", y, x); net_all_printf("pos: (%d,%d)\n", y, x);
switch (board[x][y].piece) { switch (board[x][y].piece) {
case NONE: case NONE:
break; break;
@ -235,10 +240,18 @@ laser(int side) {
break; break;
} }
switch (dir & 3) { switch (dir & 3) {
case 0: y--; if (y<0) lreturn(L_WALL); break; case 0: y--;
case 1: x++; if (x>BOARD_WIDTH-1) lreturn(L_WALL); break; if (y<0) lreturn(L_WALL);
case 2: y++; if (y>BOARD_HEIGHT-1) lreturn(L_WALL); break; break;
case 3: x--; if (x<0) lreturn(L_WALL); break; case 1: x++;
if (x>BOARD_WIDTH-1) lreturn(L_WALL);
break;
case 2: y++;
if (y>BOARD_HEIGHT-1) lreturn(L_WALL);
break;
case 3: x--;
if (x<0) lreturn(L_WALL);
break;
} }
} }
@ -379,19 +392,20 @@ setup_board(char *desc)
} }
int int
read_message(message_t *m) read_message(int side, message_t *m)
{ {
char buf[MAX_MSG_LEN+1]; char buf[MAX_MSG_LEN+1];
char c; char c;
int i; int i;
for (i = 0; i < MAX_MSG_LEN+1; i++) { for (i = 0; i < MAX_MSG_LEN+1; i++) {
c = getchar(); c = net_getc(side);
printf("input '%c'\n", c);
if (c == '\n') if (c == '\n')
break; break;
buf[i] = c; buf[i] = c;
} }
buf[i] = '\0'; buf[i] = '\0';
while (c != '\n') c = getchar(); while (c != '\n') c = net_getc(side);
switch (buf[0]) { switch (buf[0]) {
case 'M': m->type = MSG_MOVE; break; case 'M': m->type = MSG_MOVE; break;
@ -417,8 +431,8 @@ read_message(message_t *m)
break; break;
} }
printf("msg: MOVE (%d,%d) %d\n", m->args.move.row, m->args.move.col, net_all_printf("msg: MOVE (%d,%d) %d\n", m->args.move.row, m->args.move.col,
m->args.move.dir); m->args.move.dir);
} else if (m->type == MSG_ROTATE) { } else if (m->type == MSG_ROTATE) {
m->args.rotate.row = buf[2]-'A'; m->args.rotate.row = buf[2]-'A';
m->args.rotate.col = buf[3]-'0'; m->args.rotate.col = buf[3]-'0';
@ -439,7 +453,7 @@ execute_message(message_t msg, int side)
return rotate(side, msg.args.rotate.row, msg.args.rotate.col, return rotate(side, msg.args.rotate.row, msg.args.rotate.col,
msg.args.rotate.dir); msg.args.rotate.dir);
default: default:
printf("unknown command type %d\n", msg.type); net_side_printf(side, "unknown command type %d\n", msg.type);
return E_UNKNOWN_COMMAND; return E_UNKNOWN_COMMAND;
} }
} }
@ -456,17 +470,20 @@ simple_game()
message_t msg; message_t msg;
int r; int r;
printf("%s's move\n", sideinfo[side].name); net_all_printf("%s's move\n", sideinfo[side].name);
prompt:
net_side_printf(side, "> ");
net_all_flush();
r = read_message(&msg); r = read_message(side, &msg);
switch (r) { switch (r) {
case HUGE_SUCCESS: break; case HUGE_SUCCESS: break;
case E_UNKNOWN_COMMAND: case E_UNKNOWN_COMMAND:
printf("unknown command\n"); net_side_printf(side, "unknown command\n");
continue; goto prompt;
default: default:
printf("uh oh (strange return value from read_message: %d)\n", r); net_side_printf(side, "uh oh (strange return value from read_message: %d)\n", r);
continue; goto prompt;
} }
r = execute_message(msg, side); r = execute_message(msg, side);
@ -477,31 +494,32 @@ simple_game()
print_board_small(); print_board_small();
switch (r) { switch (r) {
case SILVER_WINS: case SILVER_WINS:
printf("SILVER WINS\n"); net_all_printf("SILVER WINS\n");
return; return;
case RED_WINS: case RED_WINS:
printf("RED WINS\n"); net_all_printf("RED WINS\n");
return; return;
case L_WALL: case L_WALL:
case L_PIECE: case L_PIECE:
printf("laser hits %s at %c%c\n", net_all_printf("laser hits %s at %c%c\n",
r==L_WALL ? "wall" : "piece", r==L_WALL ? "wall" : "piece",
laser_pos[1]+'A', laser_pos[0]+'0'); laser_pos[1]+'A', laser_pos[0]+'0');
break; break;
} }
side = 1-side; side = 1-side;
break; break;
case E_ILLEGAL_MOVE: case E_ILLEGAL_MOVE:
printf("illegal move\n"); net_side_printf(side, "illegal move\n");
continue; goto prompt;
default: default:
printf("uh oh (strange return value from execute_message: %d)\n", r); net_side_printf(side, "uh oh (strange return value from execute_message: %d)\n", r);
continue; goto prompt;
} }
} }
} }
int int
main() { main() {
net_server(15239);
simple_game(); simple_game();
} }