wm: glendy

Download patch

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;
 }