ref: 3edf0f3d3bc73e05dc0a21e58305502470be910d
parent: d5c2af3bcb04031bd6f2724a480b9c7758eeacbb
author: mkf <mkf@cloud9p.org>
date: Thu Dec 12 07:37:57 EST 2024
srv4.c: remove
--- a/srv4.c
+++ /dev/null
@@ -1,504 +1,0 @@
-/*
- * glendy (unix) server, 4th revision
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <time.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include "unix.h"
-#include "engine.h"
-#include "util.h"
-#include "srv.h"
-
-#define playersock sockfd[turn % 2]
-
-int listenfd;
-int port = 1768;
-int debug = 1;
-char syncmsg[8];
-
-int sockfd[2];
-
-int gcount = 0;
-
-int id = 0;
-
-pthread_mutex_t game_lock;
-
-Game games[32];
-pthread_t threads[32][2];
-
-static void
-error(const char *msg)
-{
- perror(msg);
- pthread_exit(NULL);
-}
-
-static void
-cleanup(int game)
-{
- dprint("cleanup(%d)\n", game);
- close(games[game].sockfd[0]);
- close(games[game].sockfd[1]);
-}
-
-static void
-printclients(char *fmt, ...)
-{
- /* it seems arg gets changed during the first call to vprint, thus we need two */
- va_list arg, arg2;
-
- va_start(arg, fmt);
- va_start(arg2, fmt);
-
- vfprint(sockfd[0], fmt, arg);
- vfprint(sockfd[1], fmt, arg2);
- va_end(arg);
- va_end(arg2);
-}
-
-int
-setuplistener(int portno)
-{
- int sockfd, option = 1;
- struct sockaddr_in serv_addr;
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0)
- error("ERROR opening listener socket.");
-
- memset(&serv_addr, 0, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_port = htons(portno);
- setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
-
- if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
- error("ERROR binding listener socket.");
-
- dprint("listener on\n");
-
- return sockfd;
-}
-
-void
-drawlevel(void)
-{
- /* prints first row, this assumes SzX = SzY, is there a better way? */
- print("T%2d|", turn);
- for(int i = 0 ; i < SzX ; i++)
- print("%2d |", i);
-
- dprint(" G%2d\n", id);
-
- for(int x = 0; x < SzX; x++)
- {
- for(int i = 0 ; i < SzY+1 ; i++)
- print("----");
- print(x % 2 ? "\\" : "/");
- print("\n");
-
- /* show column number and have a zig-zag effect */
- print("%2d %s|", x, x % 2 ? " " : "");
-
- for(int y = 0; y < SzY; y++)
- {
- /* it's [y][x], not [x][y] */
- switch(grid[y][x])
- {
- case Wall:
- print(" * |");
- break;
- case Glenda:
- /* fancy effect for glenda's face */
- print(" g |");
- break;
- default:
- print(" |");
- break;
- }
- }
- print("\n");
- }
-}
-
-void
-sendlevel(void)
-{
- if(state == Start)
- {
- printclients("INIT\n");
-
- for(int x = 0; x < SzX; x++)
- {
- for(int y = 0; y < SzY; y++)
- {
- switch(grid[x][y])
- {
- case Wall:
- printclients("w %d %d\n", x, y);
- break;
- case Glenda:
- printclients("g %d %d\n", x, y);
- break;
- }
- }
- }
- printclients("SENT\n");
- }
- else if(state == Playing)
- {
- printclients("SYNC %d %s\n", turn, syncmsg);
- }
- else
- {
- printclients("SYNC %d %s\n", turn, syncmsg);
- if(state == Won)
- {
- dprint("hah, trapper won\n");
- fprint(sockfd[0], "WON\n");
- fprint(sockfd[1], "LOST\n");
- }
- else if(state == Lost)
- {
- dprint("welp, trapper lost\n");
- fprint(sockfd[0], "LOST\n");
- fprint(sockfd[1], "WON\n");
- }
- cleanup(id);
- return;
- }
- dprint("Game %d, Turn is %d, min = %d\n", id, turn, findmin(findglenda()));
- fprint(playersock, "TURN\n");
- fprint(sockfd[!(turn % 2)], "WAIT\n");
-}
-
-/* p x y */
-void
-proc_put(char *s)
-{
- char *xpos, *ypos;
- unsigned int x, y, r;
-
- xpos = strtok(s, " ");
- ypos = strtok(nil, " ");
-
- if(xpos == nil || ypos == nil)
- {
- fprint(playersock, "ERR INVALIDINPUT proc_put():"
- "not enough arguments or malformed string\n");
- return;
- }
-
- if(!isnum(xpos, strlen(xpos)) || !isnum(ypos, strlen(ypos)))
- {
- fprint(playersock, "ERR invalidinput proc_put():"
- "expected string in %s and %s\n", xpos, ypos);
- return;
- }
-
- /* engine assumes it's XY, protocol assumes it's YX */
- x = atoi(xpos);
- y = atoi(ypos);
-
- dprint("put %d %d\n", x, y);
-
- if(x >= SzX || x < 0 || y >= SzY || y < 0)
- {
- fprint(playersock, "ERR invalidinput proc_put(): %d %d\n", x, y);
- return;
- }
-
- r = doput(Pt(x, y));
- if(r == Wall)
- fprint(playersock, "WALL %d %d\n", x, y);
- else if(r == Glenda)
- fprint(playersock, "GLND %d %d\n", x, y);
- else
- {
- sprint(syncmsg, "%u %u", x, y);
- syncmsg[7] = '\0';
- dprint("syncmsg = %s\n", syncmsg);
- }
-}
-
-/* m x y */
-void
-proc_move(char *s)
-{
- int d;
- Point p;
-
- p = findglenda();
- d = strtodir(s);
-
- if(d == Err)
- {
- fprint(playersock, "ERR invalidinput proc_move(): %s\n", s);
- return;
- }
-
- if(domove(d) == Wall)
- {
- fprint(playersock, "WALL %s %d %d\n", s, p.x, p.y);
- return;
- }
- else
- {
- strncpy(syncmsg, s, 7);
- /* better be safe than sorry */
- syncmsg[7] = '\0';
- dprint("syncmsg = %s\n", syncmsg);
- }
-}
-
-/*
- * handle input, which is in the form of:
- * trapper> p xx yy
- * puts a wall in xx yy
- * glenda> m {NE, E, SE, SW, W, NW}
- * moves the bunny
- * > q
- * quits the game
- */
-int
-proc(int player, char *s)
-{
- int oturn;
-
- /* early return paths */
- if(*s == '\0' || *s == 'q')
- {
- fprint(sockfd[player], "DIE disconnected\n");
- fprint(sockfd[!player], "DIE other client have been disconnected\n");
-
- /* mmhm... what happens if we close a fd we are reading from? */
- cleanup(id);
- return Err;
- }
- else if(turn % 2 != player)
- {
- fprint(sockfd[player], "ERR WAIT\n");
- return Ok;
- }
-
- oturn = turn;
- /* s+2 skips command and first space after it */
- switch(*s)
- {
- case 'p':
- if(turn % 2 == 0)
- proc_put(s+2);
- else if(turn % 2 == 1)
- fprint(playersock, "CANTP\n");
- break;
- case 'm':
- if(turn % 2 == 0)
- fprint(playersock, "CANTM\n");
- else if(turn % 2 == 1)
- proc_move(s+2);
- break;
- default:
- fprint(playersock, "ERR proc() unkown command %c\n", *s);
- }
- /* only print the map if turn have changed */
- if(turn != oturn)
- {
- if(debug)
- drawlevel();
- sendlevel();
- }
- return Ok;
-}
-
-static char*
-input(int game, int player)
-{
- char *s, c;
- int n = 0;
-
- /* sang bozorg */
- s = emalloc(1024);
- memset(s, 0, 1024);
-
- /* we could use local variables, but that not worth the trouble */
- while((c = read(games[game].sockfd[player], s+n, 1) == 1) && n < 1024)
- {
- if(s[n] == '\n' || s[n] == '\0')
- {
- s[n] = '\0';
- break;
- }
- n++;
- }
- dprint("[G%2d/P%2d], got input: %s\n", game, player, s);
-
- return s;
-}
-
-/*
- * most of game engine's works on global variables
- * set the global variables with one game from the array
- */
-static void
-loadgame(int n)
-{
- if(n > sizeof(games) / sizeof(Game))
- sysfatal("loadgame(%d): invalid game", n);
-
- id = games[n].id;
- difficulty = games[n].difficulty;
- state = games[n].state;
- turn = games[n].turn;
-
- strncpy(syncmsg, games[n].syncmsg, 8);
-
- sockfd[0] = games[n].sockfd[0];
- sockfd[1] = games[n].sockfd[1];
-
- memcpy(grid, games[n].grid, sizeof(grid));
-}
-
-static void
-setgame(int n)
-{
- if(n > sizeof(games) / sizeof(Game))
- sysfatal("setgame(%d): invalid game", n);
-
- /* id got to change when we set game */
- id = n;
- games[n].id = n;
- games[n].difficulty = difficulty;
- games[n].state = state;
- games[n].turn = turn;
-
- games[n].sockfd[0] = sockfd[0];
- games[n].sockfd[1] = sockfd[1];
-
- memcpy(games[n].grid, grid, sizeof(grid));
-}
-
-/* player is either 0 or 1, trapper or glenda */
-static void
-clienthandler(void *data)
-{
- int res, player, game;
- char *s;
-
- game = ((int*)data)[0];
- player = ((int*)data)[1];
-
- for(;;)
- {
- /* most of time is spent here */
- s = input(game, player);
-
-
- if(!strcmp(s, ""))
- {
- cleanup(game);
- break;
- }
-
- pthread_mutex_lock(&game_lock);
-
- loadgame(game);
- res = proc(player, s);
- setgame(game);
-
- pthread_mutex_unlock(&game_lock);
- free(s);
- }
-}
-
-void
-srv(int listenfd)
-{
- int clientfd[2], res[2];
- socklen_t clilen;
- struct sockaddr_in clientaddr;
- int tdata[2][2];
-
- while(gcount < 32)
- {
- for(int conns = 0 ; conns < 2 ; conns++)
- {
- listen(listenfd, 64);
- memset(&clientaddr, 0, sizeof(clientaddr));
-
- clilen = sizeof(clientaddr);
- clientfd[conns] = accept(listenfd, (struct sockaddr *) &clientaddr, &clilen);
-
- if(clientfd[conns] < 0)
- error("srv(): failed to accept connection");
-
- fprint(clientfd[conns], "CONN %d\n", conns);
- dprint("game %d: srv(): client %d connected\n", gcount, conns);
-
- if(conns == 0)
- fprint(clientfd[conns], "WAIT\n");
- }
- pthread_mutex_lock(&game_lock);
- gcount++;
-
- sockfd[0] = clientfd[0];
- sockfd[1] = clientfd[1];
-
- initlevel();
- setgame(gcount);
-
- if(debug)
- drawlevel();
-
- sendlevel();
-
- pthread_mutex_unlock(&game_lock);
-
-
- tdata[0][0] = gcount;
- tdata[0][1] = 0;
-
- tdata[1][0] = gcount;
- tdata[1][1] = 1;
-
- res[0] = pthread_create(&threads[gcount][0], NULL, (void*)clienthandler, (void*)tdata[0]);
- res[1] = pthread_create(&threads[gcount][1], NULL, (void*)clienthandler, (void*)tdata[1]);
-
- if(res[0] || res[1])
- {
- dprint("pthread_create() failed: %d\n", res[0] ? res[0] : res[1]);
- exit(-1);
- }
- else
- dprint("threads for game %d are created\n", gcount);
- }
-}
-
-int
-main(int argc, char **argv)
-{
- /* it might not be a real human */
- ptype[0] = Human;
- ptype[1] = Human;
-
- listenfd = setuplistener(port);
- pthread_mutex_init(&game_lock, NULL);
-
- /* OpenBSD ignores this */
- srand(time(nil));
-
- srv(listenfd);
-
- close(listenfd);
- pthread_mutex_destroy(&game_lock);
- pthread_exit(NULL);
- return 0;
-}