ref: a24f56bcfdc76fb4aad5f8df0d286c18aee5b62e
parent: 8d1be93bf09d840d8e3eb1e077fa344405dc13a4
author: mkf <mkf@cloud9p.org>
date: Mon May 13 07:00:43 EDT 2024
srv: go multi-threaded, changed input, main and proc to act better in a multi-threaded environment
--- a/srv.c
+++ b/srv.c
@@ -23,6 +23,8 @@
#define playersock sockfd[turn % 2]
+int listenfd;
+int port = 1768;
int pcount = 0;
int sockfd[2];
int debug = 1;
@@ -294,28 +296,39 @@
}
/*
- * handle input, which is in the form of
- * p1> p xx yy
- * which puts a wall in xx yy
- * p2> m {NE, E, SE, W, SW, NW}
- * which moves the bunny
- * > r
- * restarts the game
- * > u
- * undos last move
+ * handle input, which is in the form of:
+ * trapper> p xx yy
+ * puts a wall in xx yy
+ * glenda> m {NE, E, SE, W, SW, NW}
+ * moves the bunny
* > q
* quits the game
*/
int
-proc(char *s)
+proc(char *s, int player)
{
char *t;
int oturn, n;
- /* skip \n, so we don't need to process it later */
- t = strchr(s, '\n');
- if(t != nil)
- *t = '\0';
+ /* early return paths */
+ if(*s == '\0' || *s == 'q')
+ {
+ /* should we end the game at this point? XXX important */
+ fprint(playersock, "DIE disconnected\n");
+ fprint(sockfd[!(turn % 2)], "DIE other client have been disconnected\n");
+
+ /* mmhm... one may wonder what happens if
+ * we close a fd that happens to be read from? */
+ close(sockfd[0]);
+ close(sockfd[1]);
+ pcount -= 2;
+ return Err;
+ }
+ else if(turn % 2 != player)
+ {
+ fprint(sockfd[player], "WAIT\n");
+ return Ok;
+ }
oturn = turn;
/* s+2 skips command and first space after it */
@@ -333,25 +346,8 @@
else if(turn % 2 == 1)
proc_move(s+2);
break;
- /*
- case 'u':
- fprint(playersock, "ERR not implmented\n");
- break;
- */
- case 'r':
- /* maybe we need to put a confirm message here */
- fprint(playersock, "ERR not implmented\n");
- break;
- case 'q':
- case '\0':
- /* should we end the game at this point? XXX important */
- fprint(playersock, "DIE disconnected\n");
- fprint(sockfd[!(turn % 2)], "DIE other client have been disconnected\n");
- close(sockfd[0]);
- close(sockfd[1]);
- return Err;
default:
- fprint(playersock, "ERR invalidinput %c\n", *s);
+ fprint(playersock, "ERR proc() unkown command %c\n", *s);
}
/* only print the map if turn have changed */
if(turn != oturn)
@@ -363,8 +359,8 @@
return Ok;
}
-static int
-input(void)
+static char*
+input(int player)
{
char *s, c;
int n = 0;
@@ -371,12 +367,9 @@
/* sang bozorg */
s = malloc(1024);
-
- fprint(playersock, "TURN\n");
- fprint(sockfd[!(turn % 2)], "WAIT\n");
memset(s, 0, 1024);
- while(read(playersock, s+n, 1) == 1 && n < 1024)
+ while(read(sockfd[player], s+n, 1) == 1 && n < 1024)
{
if(s[n] == '\n' || s[n] == '\0')
{
@@ -387,13 +380,58 @@
}
dprint("got input: %s\n", s);
- return proc(s);
+ return s;
}
+/* player is either 0 or 1, trapper or glenda */
+static void
+clienthandler(void *player)
+{
+ char *s;
+ int p;
+ p = *(int*)player;
+
+ for(;;)
+ {
+ s = input(p);
+
+ proc(s, p);
+ free(s);
+ }
+}
+
+static void
+srv(void)
+{
+ int res[2];
+ /* meh. i can't have pointers like &(1) in ANSI */
+ int zero = 0, one = 1;
+ pthread_t p1_thread, p2_thread;
+ for(;;)
+ {
+ getclients(listenfd);
+ initlevel();
+
+ if(debug)
+ drawlevel();
+
+ sendlevel();
+ fprint(playersock, "TURN\n");
+ fprint(sockfd[!(turn % 2)], "WAIT\n");
+
+ res[0] = pthread_create(&p1_thread, NULL, (void*)clienthandler, &zero);
+ res[1] = pthread_create(&p2_thread, NULL, (void*)clienthandler, &one);
+ if(res[0] || res[1]){
+ dprint("Thread creation failed with return code %d\n", res[0] ? res[0] : res[1]);
+ exit(-1);
+ }
+
+ }
+}
+
int
main(int argc, char **argv)
{
- int listenfd, port, result;
char r;
pthread_t input_thread;
@@ -400,8 +438,6 @@
/* it might not be a real human */
ptype[0] = Human;
ptype[1] = Human;
-
- port = 1768;
listenfd = setuplistener(port);
pthread_mutex_init(&pcount_mutex, NULL);
@@ -409,28 +445,11 @@
/* OpenBSD ignores this */
srand(time(nil));
-
+ srv();
- result = pthread_create(&input_thread, NULL, (void*)input, NULL);
- if(result){
- dprint("Thread creation failed with return code %d\n", result);
- exit(-1);
- }
-
- for(;;)
- {
- getclients(listenfd);
- initlevel();
-
- if(debug)
- drawlevel();
-
- sendlevel();
- while(input() != Err)
- ;
- }
close(listenfd);
pthread_mutex_destroy(&pcount_mutex);
+ pthread_exit(NULL);
return 0;
}