This repository was archived by the owner on Feb 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathos_client.c
More file actions
152 lines (123 loc) · 4.28 KB
/
Copy pathos_client.c
File metadata and controls
152 lines (123 loc) · 4.28 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <os_server.h>
#include <os_client.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <fs.h>
const char *ok = "OK \n";
//Convert command string to int
static int getcommand(os_msg_t *msg) {
if (msg->cmd) {
if (strcmp(msg->cmd, "REGISTER") == 0 && msg->name) return OS_CLIENT_REGISTER;
if (strcmp(msg->cmd, "STORE") == 0 && msg->name && msg->len && msg->data) return OS_CLIENT_STORE;
if (strcmp(msg->cmd, "RETRIEVE") == 0 && msg->name) return OS_CLIENT_RETRIEVE;
if (strcmp(msg->cmd, "DELETE") == 0 && msg->name) return OS_CLIENT_DELETE;
if (strcmp(msg->cmd, "LEAVE") == 0) return OS_CLIENT_LEAVE;
}
//Not a command
return -1;
}
//Helper functions for sending OKs or KOs
static void send_ok(int fd) {
ssize_t result = sendn(fd, ok, 5, 0);
if (result < 0) err_write(fd);
}
static void send_ko(int fd, const char *msg) {
//5 is the length of "KO \n" and a null terminator
char to_send[5 + strlen(msg)];
sprintf(to_send, "KO %s\n", msg);
ssize_t result = sendn(fd, to_send, 5 + strlen(msg), 0);
if (result < 0) err_write(fd);
}
static int namecompare(const void *ptr, void *arg) {
client_t *client = (client_t*)ptr;
char *name = (char*)arg;
if (client->name) return strcmp(client->name, name) == 0;
return 0;
}
static client_t *os_client_handleregistration(int fd, client_t *client, char *name) {
client->socketfd = fd;
client->running = 1;
//Check for name duplicate
client_t *dup = (client_t*)myhash_search(client_list, HASHTABLE_SIZE, name, &namecompare, name);
if (dup) {
send_ko(fd, "Username already registered");
client->running = 0;
return NULL;
}
//...no dupe (truncate name if longer than 255 chars)
client->name = (char*)calloc(256, sizeof(char));
if (client->name == NULL) {
err_malloc((size_t)256);
exit(EXIT_FAILURE);
}
strncpy(client->name, name, 255);
myhash_insert(client_list, HASHTABLE_SIZE, client->name, client);
fs_mkdir(client);
send_ok(fd);
if (VERBOSE) fprintf(stderr, "OBJSTORE: Client on fd %d registered as \'%s\'\n", fd, name);
return client;
}
//LEAVE handler
static void os_client_handleleave(int fd, client_t *client) {
if (VERBOSE) {
char *name = client->name;
fprintf(stderr, "OBJSTORE: Client on fd %d (%s) left\n", fd, name);
}
send_ok(fd);
//Stop the client's worker thread
client->running = 0;
}
//RETRIEVE handler
static void os_client_handleretrieve(int fd, client_t *client, char *filename) {
if (!fs_read(fd, client, filename)) {
char buf[128];
strerror_r(errno, buf, 128);
send_ko(fd, buf);
}
}
//DELETE handler
static void os_client_handledelete(int fd, client_t *client, char *filename) {
int err = fs_delete(client, filename);
if (err == 0) {
char buf[128];
strerror_r(errno, buf, 128);
send_ko(fd, buf);
} else send_ok(fd);
}
//STORE handler
static void os_client_handlestore(int fd, client_t *client, char *filename, char *data, size_t len, size_t datalen) {
int err = fs_write(fd, client, filename, len, data, datalen);
if (err == 0) {
char buf[128];
strerror_r(errno, buf, 128);
send_ko(fd, buf);
} else send_ok(fd);
}
int os_client_commandhandler(int fd, client_t *client, os_msg_t *msg) {
int cmd_num = getcommand(msg);
switch (cmd_num) {
case OS_CLIENT_REGISTER:
os_client_handleregistration(fd, client, msg->name);
break;
case OS_CLIENT_STORE:
os_client_handlestore(fd, client, msg->name, msg->data, msg->len, msg->datalen);
return 0;
break;
case OS_CLIENT_RETRIEVE:
os_client_handleretrieve(fd, client, msg->name);
break;
case OS_CLIENT_DELETE:
os_client_handledelete(fd, client, msg->name);
break;
case OS_CLIENT_LEAVE:
os_client_handleleave(fd, client);
return 0;
break;
default:
//What we got is not a message (???)
send_ko(fd, "Broken message");
return 0;
break;
}
return 0;
}