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