summaryrefslogtreecommitdiff
path: root/src/fscomch.c
blob: 412f9cff4bb9cfcbc187986ac4255f6518e59ede (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <string.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;
		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;
}