diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2023-03-19 23:20:53 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2023-03-19 23:20:53 -0700 |
| commit | e33dc4755fb08ed08f30b5e1af65457556d5bcb7 (patch) | |
| tree | c075e9c4f076a7772eb5c0665fbd137e2fd6c3ab | |
| parent | 26321477ae47bbf5d89b651842d8295e9ea9ea5d (diff) | |
fscomch--communication between multiple chess processes
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | src/chess.c (renamed from chess.c) | 22 | ||||
| -rw-r--r-- | src/chess.h (renamed from chess.h) | 0 | ||||
| -rw-r--r-- | src/chesshelpers.c (renamed from chesshelpers.c) | 0 | ||||
| -rw-r--r-- | src/chesshelpers.h (renamed from chesshelpers.h) | 0 | ||||
| -rw-r--r-- | src/console.c (renamed from console.c) | 0 | ||||
| -rw-r--r-- | src/console.h (renamed from console.h) | 0 | ||||
| -rw-r--r-- | src/fscomch.c | 97 | ||||
| -rw-r--r-- | src/fscomch.h | 24 | ||||
| -rw-r--r-- | src/vector.c (renamed from vector.c) | 0 | ||||
| -rw-r--r-- | src/vector.h (renamed from vector.h) | 0 |
11 files changed, 144 insertions, 1 deletions
@@ -2,7 +2,7 @@ CC=gcc CFLAGS=-I. generate: - $(CC) -o chess chess.c vector.c chesshelpers.c console.c $(CFLAGS) + $(CC) -o chess src/chess.c src/vector.c src/chesshelpers.c src/console.c src/fscomch.c $(CFLAGS) install: cp chess /usr/local/bin/ @@ -4,6 +4,7 @@ #include "vector.h" #include "console.h" #include "chesshelpers.h" +#include "fscomch.h" #include "chess.h" int main(int argc, char **argv) { @@ -33,6 +34,27 @@ int main(int argc, char **argv) { } } board_t board = init_board(pieces); + /* try to acquire a lock on the local matchfile */ + FILE* matchFile = try_lock_match(); + match_t match; + if (matchFile != NULL) { + /* we are acting as the host--await a connection */ + printf("awaiting connection\n"); + match = await_match(matchFile, NULL); + printf("connection completed. match is %s\n", match.uuid); + } + else { + /* we are joining an existing match */ + printf("attempting to join existing match\n"); + match = join_match(); + if (match.uuid != NULL) { + printf("joined match %s\n", match.uuid); + } + else { + printf("error joining match. reload the program\n"); + } + } + exit(0); int turn = 0; while(1) { //draw the board, write some info diff --git a/chesshelpers.c b/src/chesshelpers.c index b64a0f4..b64a0f4 100644 --- a/chesshelpers.c +++ b/src/chesshelpers.c diff --git a/chesshelpers.h b/src/chesshelpers.h index b3a3d21..b3a3d21 100644 --- a/chesshelpers.h +++ b/src/chesshelpers.h diff --git a/console.c b/src/console.c index e675ba2..e675ba2 100644 --- a/console.c +++ b/src/console.c diff --git a/console.h b/src/console.h index c0ca9f7..c0ca9f7 100644 --- a/console.h +++ b/src/console.h diff --git a/src/fscomch.c b/src/fscomch.c new file mode 100644 index 0000000..a9fc27b --- /dev/null +++ b/src/fscomch.c @@ -0,0 +1,97 @@ +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <time.h> +#include <sys/stat.h> +#include "fscomch.h" + +match_t init_match(char* uuid, FILE* streamIn, FILE* streamOut) { + match_t match; + match.uuid = uuid; + match.streamIn = streamIn; + match.streamOut = streamOut; + return match; +} +void destroy_match(match_t match) { + free(match.uuid); + fclose(match.streamIn); + fclose(match.streamOut); +} +FILE* try_lock_match() { + mkdir("/tmp/chess/", 0777); + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + int fd = open("/tmp/chess/match", O_RDONLY | O_CREAT | O_EXCL, mode); + if (fd == -1) { + return NULL; + } + return fdopen(fd, "r"); +} +match_t await_match(FILE* matchFile, char* cancelToken) { + /* await match UUID */ + char* uuid = calloc(37, sizeof(char)); + while (cancelToken == NULL || *cancelToken) { + if (fgets(uuid, 37, matchFile) != NULL) { + break; + } + fseek(matchFile, 0, SEEK_SET); + struct timespec req; + req.tv_sec = 0; + req.tv_nsec = awaitMatchNs; + printf("sleeping\n"); + nanosleep(&req, NULL); + } + /* connect to files created by joining player */ + char aName[256]; + char bName[256]; + snprintf(aName, 256, "/tmp/chess/%s.a", uuid); + snprintf(bName, 256, "/tmp/chess/%s.b", uuid); + FILE* streamIn = fopen(aName, "r"); + FILE* streamOut = fopen(bName, "w"); + /* connection complete, delete the match file and the join lock */ + remove("/tmp/chess/match"); + remove("/tmp/chess/matchjoin"); + return init_match(uuid, streamIn, streamOut); +} +match_t join_match() { + /* create a join lock so that no one else can join this match */ + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + int fd = open("/tmp/chess/matchjoin", O_WRONLY | O_CREAT | O_EXCL, mode); + if (fd == -1) { + /* another process is in the process of joining this game */ + match_t match; + return match; + } + /* this is definitely the only process joining the game + proceed to generate a uuid */ + char* uuid = make_uuid(); + /* make the .a and .b files based on the uuid */ + char aName[256]; + char bName[256]; + snprintf(aName, 256, "/tmp/chess/%s.a", uuid); + snprintf(bName, 256, "/tmp/chess/%s.b", uuid); + FILE* streamIn = fopen(bName, "w+"); + FILE* streamOut = fopen(aName, "w"); + match_t match = init_match(uuid, streamIn, streamOut); + /* send uuid to the host */ + FILE* matchFile = fopen("/tmp/chess/match", "a"); + fputs(uuid, matchFile); + /* joining match complete, close the descriptor */ + close(fd); + return match; +} +char* make_uuid() { + char sym[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f'}; + char* out = calloc(37, sizeof(char)); + srand(time(NULL)); + for (int i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + out[i] = '-'; + } + else { + out[i] = sym[rand() % 16]; + } + } + out[37] = '\0'; + return out; +} diff --git a/src/fscomch.h b/src/fscomch.h new file mode 100644 index 0000000..b7900e3 --- /dev/null +++ b/src/fscomch.h @@ -0,0 +1,24 @@ +#include <stdio.h> +#ifndef FSCOMCH +#define FSCOMCH + +/* 1/2 second */ +static const unsigned long int awaitMatchNs = 500000000L; +/* 1/4 second */ +static const unsigned long int awaitMoveNs = 250000000L; + +typedef struct Match { + char* uuid; + FILE* streamIn; + FILE* streamOut; +} match_t; +match_t init_match(char* uuid, FILE* streamIn, FILE* streamOut); +void destroy_match(match_t match); +/* returns null if the matchfile is already extant */ +FILE* try_lock_match(); +/* creates a new match, waits for it to be joined by another player */ +match_t await_match(FILE* matchFile, char* cancelToken); +/* joins an existing match */ +match_t join_match(); +char* make_uuid(); +#endif |
