#include #include #include #include #include #include #include #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; nanosleep(&req, NULL); } /* connect to streams */ 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, "a"); /* 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(); /* create and connect to streams */ 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, "a"); match_t match = init_match(uuid, streamIn, streamOut); /* send uuid to the host */ FILE* matchFile = fopen("/tmp/chess/match", "a"); fputs(uuid, matchFile); fclose(matchFile); /* joining match complete, close the descriptor */ close(fd); return match; } void send_message(char* content, match_t match) { fprintf(match.streamOut, "%s\n", content); fflush(match.streamOut); } char* read_message(match_t match, char* cancelToken) { char* buffer = calloc(256, sizeof(char)); while (cancelToken == NULL || *cancelToken) { if (fgets(buffer, 256, match.streamIn) != NULL) { break; } /* wtf? */ fseek(match.streamIn, ftell(match.streamIn), SEEK_SET); struct timespec req; req.tv_sec = 0; req.tv_nsec = awaitMoveNs; nanosleep(&req, NULL); } /* overwrite potential newline */ buffer[strlen(buffer) - 1] = '\0'; return buffer; } 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; }