-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.h
314 lines (284 loc) · 10.4 KB
/
client.h
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
/*
* client.h - Client-related subroutines
* Copyright (c) 2020 Nicholas West, Hantao Cui, CURENT, et. al.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided "as is" and the author disclaims all
* warranties with regard to this software including all implied warranties
* of merchantability and fitness. In no event shall the author be liable
* for any special, direct, indirect, or consequential damages or any
* damages whatsoever resulting from loss of use, data or profits, whether
* in an action of contract, negligence or other tortious action, arising
* out of or in connection with the use or performance of this software.
*/
/**
* @file client.h
* @brief Client-related subroutines
* @author Nicholas West
* @date 2020
*
* Contains data structures and subroutines intended to manage a
* client's state. Each valid command that can be sent by clients has a
* corresponding function in this file to handle it.
*/
#include <stdint.h>
#include <jansson.h>
#include "deque.h"
#include "server.h"
#include "socket.h"
#ifndef __DIME_client_H
#define __DIME_client_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Client's state
*
* Contains all data relevant to a single client's server-side state.
* This includes a @link dime_socket_t @endlink and a
* @link dime_deque_t @endlink queue of @link dime_rcmessage_t @endlink
* messages that act as a secondary buffer. "send" and "broadcast"
* commands from other clients add messages to the queue, while "sync"
* commands flush the queue to the socket.
*
* @see dime_client_init
* @see dime_client_destroy
* @see dime_client_join
* @see dime_client_leave
* @see dime_client_send
* @see dime_client_broadcast
* @see dime_client_sync
* @see dime_client_wait
* @see dime_client_devices
*/
typedef struct __dime_client dime_client_t;
/**
* @brief Reference-counted message
*
* Record that contains a single DiME message and a count of how many
* references it has in memory. Note that there are no functions
* introduced to manage this struct; the reference count is managed
* directly by the functions in this file, and when the reference count
* reaches zero, it is deallocated manually by said functions.
*/
typedef struct {
unsigned int refs; /** Reference count */
char *jsondata; /** JSON portion of the message as a string */
void *bindata; /** Binary portion of the message */
size_t bindata_len; /** Length of binary portion of the message */
} dime_rcmessage_t;
/**
* @brief Group of clients
*
* Record that contains a list of clients that all share a named group.
*/
typedef struct {
char *name; /** Group name */
dime_client_t **clnts; /** Array of clients */
size_t clnts_len; /** Length of client array */
size_t clnts_cap; /** Capacity of client array */
} dime_group_t;
struct __dime_client {
int fd; /** File descriptor */
int waiting; /** Whether or not this client is waiting for a new message */
char *addr; /** Address of connection, as a human-readable string */
dime_group_t **groups; /** Array of associated groups */
size_t groups_len; /** Length of groups */
size_t groups_cap; /** Capacity of groups */
dime_socket_t sock; /** DiME socket */
dime_deque_t queue; /** Queue of reference-counted messages */
dime_server_t *srv;
char err[81]; /** Error string */
};
/**
* @brief Initialize a new client
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param fd File descriptor to send/receive on
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_destroy
*/
int dime_client_init(dime_client_t *clnt, int fd, const struct sockaddr *addr);
/**
* @brief Free resources used by a client
*
* By default, this function closes the file descriptor that was used to
* initialize the client. Pass a file descriptor created with @c dup if
* this behavior is undesirable.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
*
* @see dime_client_init
*/
void dime_client_destroy(dime_client_t *clnt);
/**
* @brief Handle a "handshake" command
*
* The "handshake" command mostly does housekeeping w.r.t. the
* serialization method.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @todo Remove this
*/
int dime_client_handshake(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "join" command
*
* The "join" command instructs the server to add the client @em clnt to
* the group specified in the JSON field @c name.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_leave
*/
int dime_client_join(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "leave" command
*
* The "leave" command instructs the server to remove the client @em
* clnt from the group specified in the JSON field @c name.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_join
* @todo Implement this
*/
int dime_client_leave(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "send" command
*
* The "send" command instructs the server to relay the message to all
* clients in the group specified in the JSON field @c name.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_broadcast
* @see dime_client_sync
* @see dime_client_wait
*/
int dime_client_send(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "broadcast" command
*
* The "broadcast" command instructs the server to relay the message to
* all other clients.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_send
* @see dime_client_sync
* @see dime_client_wait
*/
int dime_client_broadcast(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "sync" command
*
* The "sync" command instructs the server to send the client @em clnt
* the messages that have been relayed by other clients. The JSON field
* @c n may optionally specify a limit on the number of messages to
* download.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_send
* @see dime_client_broadcast
*/
int dime_client_sync(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "wait" command
*
* The "sync" command instructs the server to send the client @em clnt a
* DiME message as soon as another client has queued a message via a
* "send" or "broadcast" command. This effectively blocks the client's
* thread of execution until at least one message can be retrieved.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*
* @see dime_client_send
* @see dime_client_broadcast
*/
int dime_client_wait(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
/**
* @brief Handle a "devices" command
*
* The "devices" command instructs the server to send the client a list
* of the groups with active clients in them.
*
* @param clnt Pointer to a @link dime_client_t @endlink struct
* @param srv Pointer to the @link dime_server_t @endlink struct from
* which the client connection was accepted
* @param jsondata JSON portion of the message
* @param pbindata Binary portion of the message
* @param bindata_len Length of binary portion of the message
*
* @return A nonnegative value on success, or a negative value on
* failure
*/
int dime_client_devices(dime_client_t *clnt, dime_server_t *srv, json_t *jsondata, void **pbindata, size_t bindata_len);
#ifdef __cplusplus
}
#endif
#endif