/* -*- c-basic-offset: 4 -*- */ #include #include #include #include #include #include #include #include #include #include #include #include "net.h" #define MAX_CLIENTS 2 #define SRV_FDS 1 int servsock; struct pollfd pollfds[SRV_FDS+MAX_CLIENTS]; int nclients = 0; FILE *net_side[2]; int errx(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(eval); } void net_server(int port) { struct sockaddr_in serveraddr; serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(port); servsock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (servsock<0) errx(1, "socket: %s\n", strerror(errno)); int r; 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) 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].events=POLLIN|POLLERR|POLLHUP; for (int i=SRV_FDS; i<(SRV_FDS+MAX_CLIENTS); i++) { pollfds[0].fd=-1; 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 net_poll() { int npoll; npoll=poll(pollfds, SRV_FDS+MAX_CLIENTS, -1); if (npoll<0) errx(1, "poll: %s", strerror(errno)); if (pollfds[0].revents) { struct sockaddr_in clientaddr; int cfd; socklen_t slen; cfd=accept(servsock, (struct sockaddr *)&clientaddr, &slen); if (cfd<0) errx(1, "accept: %s", strerror(errno)); // FIXME log, shout, or something if (nclients>MAX_CLIENTS) { #define STR_SERVER_FULL "Sorry, the server is full" write(cfd, STR_SERVER_FULL, sizeof(STR_SERVER_FULL)-1); close(cfd); } else { int i; for (i=SRV_FDS; i<(SRV_FDS+MAX_CLIENTS); i++) if (pollfds[i].fd==-1) break; pollfds[i].fd=cfd; pollfds[i].events=POLLIN|POLLERR|POLLHUP; nclients++; } npoll--; } for (int i=SRV_FDS; npoll && i<(SRV_FDS+MAX_CLIENTS); i++) { if (pollfds[SRV_FDS+i].revents) { int n; char buf[100]; n=read(pollfds[SRV_FDS+i].fd, &buf, sizeof(buf)); // parse buf // handle disconnections } } }