iodine 0.1.21 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.travis.yml +23 -2
  4. data/CHANGELOG.md +9 -2
  5. data/README.md +232 -179
  6. data/Rakefile +13 -1
  7. data/bin/config.ru +63 -0
  8. data/bin/console +6 -0
  9. data/bin/echo +42 -32
  10. data/bin/http-hello +62 -0
  11. data/bin/http-playground +124 -0
  12. data/bin/playground +62 -0
  13. data/bin/poc/Gemfile.lock +23 -0
  14. data/bin/poc/README.md +37 -0
  15. data/bin/poc/config.ru +66 -0
  16. data/bin/poc/gemfile +1 -0
  17. data/bin/poc/www/index.html +57 -0
  18. data/bin/raw-rbhttp +35 -0
  19. data/bin/raw_broadcast +66 -0
  20. data/bin/test_with_faye +40 -0
  21. data/bin/ws-broadcast +108 -0
  22. data/bin/ws-echo +108 -0
  23. data/exe/iodine +59 -0
  24. data/ext/iodine/base64.c +264 -0
  25. data/ext/iodine/base64.h +72 -0
  26. data/ext/iodine/bscrypt-common.h +109 -0
  27. data/ext/iodine/bscrypt.h +49 -0
  28. data/ext/iodine/extconf.rb +41 -0
  29. data/ext/iodine/hex.c +123 -0
  30. data/ext/iodine/hex.h +70 -0
  31. data/ext/iodine/http.c +200 -0
  32. data/ext/iodine/http.h +128 -0
  33. data/ext/iodine/http1.c +402 -0
  34. data/ext/iodine/http1.h +56 -0
  35. data/ext/iodine/http1_simple_parser.c +473 -0
  36. data/ext/iodine/http1_simple_parser.h +59 -0
  37. data/ext/iodine/http_request.h +128 -0
  38. data/ext/iodine/http_response.c +1606 -0
  39. data/ext/iodine/http_response.h +393 -0
  40. data/ext/iodine/http_response_http1.h +374 -0
  41. data/ext/iodine/iodine_core.c +641 -0
  42. data/ext/iodine/iodine_core.h +70 -0
  43. data/ext/iodine/iodine_http.c +615 -0
  44. data/ext/iodine/iodine_http.h +19 -0
  45. data/ext/iodine/iodine_websocket.c +430 -0
  46. data/ext/iodine/iodine_websocket.h +21 -0
  47. data/ext/iodine/libasync.c +552 -0
  48. data/ext/iodine/libasync.h +117 -0
  49. data/ext/iodine/libreact.c +347 -0
  50. data/ext/iodine/libreact.h +244 -0
  51. data/ext/iodine/libserver.c +912 -0
  52. data/ext/iodine/libserver.h +435 -0
  53. data/ext/iodine/libsock.c +950 -0
  54. data/ext/iodine/libsock.h +478 -0
  55. data/ext/iodine/misc.c +181 -0
  56. data/ext/iodine/misc.h +76 -0
  57. data/ext/iodine/random.c +193 -0
  58. data/ext/iodine/random.h +48 -0
  59. data/ext/iodine/rb-call.c +127 -0
  60. data/ext/iodine/rb-call.h +60 -0
  61. data/ext/iodine/rb-libasync.h +79 -0
  62. data/ext/iodine/rb-rack-io.c +389 -0
  63. data/ext/iodine/rb-rack-io.h +17 -0
  64. data/ext/iodine/rb-registry.c +213 -0
  65. data/ext/iodine/rb-registry.h +33 -0
  66. data/ext/iodine/sha1.c +359 -0
  67. data/ext/iodine/sha1.h +85 -0
  68. data/ext/iodine/sha2.c +825 -0
  69. data/ext/iodine/sha2.h +138 -0
  70. data/ext/iodine/siphash.c +136 -0
  71. data/ext/iodine/siphash.h +15 -0
  72. data/ext/iodine/spnlock.h +235 -0
  73. data/ext/iodine/websockets.c +696 -0
  74. data/ext/iodine/websockets.h +120 -0
  75. data/ext/iodine/xor-crypt.c +189 -0
  76. data/ext/iodine/xor-crypt.h +107 -0
  77. data/iodine.gemspec +25 -18
  78. data/lib/iodine.rb +57 -58
  79. data/lib/iodine/http.rb +0 -189
  80. data/lib/iodine/protocol.rb +36 -245
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/rack/handler/iodine.rb +145 -2
  83. metadata +115 -37
  84. data/bin/core_http_test +0 -51
  85. data/bin/em playground +0 -56
  86. data/bin/hello_world +0 -75
  87. data/bin/setup +0 -7
  88. data/lib/iodine/client.rb +0 -5
  89. data/lib/iodine/core.rb +0 -102
  90. data/lib/iodine/core_init.rb +0 -143
  91. data/lib/iodine/http/hpack.rb +0 -553
  92. data/lib/iodine/http/http1.rb +0 -251
  93. data/lib/iodine/http/http2.rb +0 -507
  94. data/lib/iodine/http/rack_support.rb +0 -108
  95. data/lib/iodine/http/request.rb +0 -462
  96. data/lib/iodine/http/response.rb +0 -474
  97. data/lib/iodine/http/session.rb +0 -143
  98. data/lib/iodine/http/websocket_client.rb +0 -335
  99. data/lib/iodine/http/websocket_handler.rb +0 -101
  100. data/lib/iodine/http/websockets.rb +0 -336
  101. data/lib/iodine/io.rb +0 -56
  102. data/lib/iodine/logging.rb +0 -46
  103. data/lib/iodine/settings.rb +0 -158
  104. data/lib/iodine/ssl_connector.rb +0 -48
  105. data/lib/iodine/timers.rb +0 -95
@@ -0,0 +1,478 @@
1
+ /*
2
+ copyright: Boaz segev, 2016
3
+ license: MIT
4
+
5
+ Feel free to copy, use and enjoy according to the license provided.
6
+ */
7
+ #ifndef LIB_SOCK
8
+ #define LIB_SOCK "0.2.0"
9
+ #define LIB_SOCK_VERSION_MAJOR 0
10
+ #define LIB_SOCK_VERSION_MINOR 2
11
+ #define LIB_SOCK_VERSION_PATCH 0
12
+
13
+ /** \file
14
+ The libsock is a non-blocking socket helper library, using a user level buffer,
15
+ non-blocking sockets and some helper functions.
16
+
17
+ This library is great when using it alongside `libreact`.
18
+
19
+ The library is designed to be thread safe, but not fork safe.
20
+ */
21
+
22
+ #include <stdint.h>
23
+ #include <unistd.h>
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+ #include <sys/types.h>
27
+
28
+ #ifndef __unused
29
+ #define __unused __attribute__((unused))
30
+ #endif
31
+
32
+ /* *****************************************************************************
33
+ User land buffer settings for every packet's pre-alocated memory size (17Kb)
34
+
35
+ This information is also useful when implementing read / write hooks.
36
+ */
37
+ #ifndef BUFFER_PACKET_SIZE
38
+ #define BUFFER_PACKET_SIZE \
39
+ (1024 * 16) /* Use 32 Kb. With sendfile, 16 Kb might be better. */
40
+ #endif
41
+ #ifndef BUFFER_FILE_READ_SIZE
42
+ #define BUFFER_FILE_READ_SIZE BUFFER_PACKET_SIZE
43
+ #endif
44
+ #ifndef BUFFER_PACKET_POOL
45
+ #define BUFFER_PACKET_POOL 248 /* hard limit unless BUFFER_ALLOW_MALLOC */
46
+ #endif
47
+
48
+ /* *****************************************************************************
49
+ A simple, predictable UUID for file-descriptors, for collision prevention
50
+ */
51
+
52
+ #ifndef FD_UUID_TYPE_DEFINED
53
+ #define FD_UUID_TYPE_DEFINED
54
+ /** fduuid_u is used to identify a specific connection, helping to manage file
55
+ * descriptor collisions (when a new connection receives an old connection's
56
+ * file descriptor), especially when the `on_close` event is fired after an
57
+ * `accept` was called and the old file descriptor was already recycled.
58
+ *
59
+ * This requires that sizeof(int) < sizeof(uintptr_t) or sizeof(int)*8 >= 32
60
+ */
61
+ typedef union {
62
+ intptr_t uuid;
63
+ struct {
64
+ int fd : (sizeof(int) < sizeof(intptr_t) ? (sizeof(int) * 8) : 24);
65
+ unsigned counter : (sizeof(int) < sizeof(intptr_t)
66
+ ? ((sizeof(intptr_t) - sizeof(int)) * 8)
67
+ : ((sizeof(intptr_t) * 8) - 24));
68
+ } data;
69
+ } fduuid_u;
70
+
71
+ #define FDUUID_FAIL(uuid) (uuid == -1)
72
+ #define sock_uuid2fd(uuid) ((fduuid_u)(uuid)).data.fd
73
+ #endif
74
+
75
+ /* *****************************************************************************
76
+ C++ extern
77
+ */
78
+ #if defined(__cplusplus)
79
+ extern "C" {
80
+ #endif
81
+
82
+ /* *****************************************************************************
83
+ Process wide and helper sock_API.
84
+ */
85
+
86
+ /**
87
+ Sets a socket to non blocking state.
88
+
89
+ This function is called automatically for the new socket, when using
90
+ `sock_accept` or `sock_connect`.
91
+ */
92
+ int sock_set_non_block(int fd);
93
+
94
+ /**
95
+ Gets the maximum number of file descriptors this process can be allowed to
96
+ access (== maximum fd value + 1).
97
+
98
+ If the "soft" limit is lower then the "hard" limit, the process's limits will be
99
+ extended to the allowed "hard" limit.
100
+ */
101
+ ssize_t sock_max_capacity(void);
102
+
103
+ /* *****************************************************************************
104
+ The main sock_API.
105
+ */
106
+
107
+ /**
108
+ Opens a listening non-blocking socket. Return's the socket's UUID.
109
+
110
+ Returns -1 on error. Returns a valid socket (non-random) UUID.
111
+
112
+ UUIDs with values less then -1 are valid values, depending on the system's
113
+ byte-ordering.
114
+
115
+ Socket UUIDs are predictable and shouldn't be used outside the local system.
116
+ They protect against connection mixups on concurrent systems (i.e. when saving
117
+ client data for "broadcasting" or when an old client task is preparing a
118
+ response in the background while a disconnection and a new connection occur on
119
+ the same `fd`).
120
+ */
121
+ intptr_t sock_listen(const char* address, const char* port);
122
+
123
+ /**
124
+ `sock_accept` accepts a new socket connection from the listening socket
125
+ `server_fd`, allowing the use of `sock_` functions with this new file
126
+ descriptor.
127
+
128
+ When using `libreact`, remember to call `int reactor_add(intptr_t uuid);` to
129
+ listen for events.
130
+
131
+ Returns -1 on error. Returns a valid socket (non-random) UUID.
132
+
133
+ Socket UUIDs are predictable and shouldn't be used outside the local system.
134
+ They protect against connection mixups on concurrent systems (i.e. when saving
135
+ client data for "broadcasting" or when an old client task is preparing a
136
+ response in the background while a disconnection and a new connection occur on
137
+ the same `fd`).
138
+ */
139
+ intptr_t sock_accept(intptr_t srv_uuid);
140
+
141
+ /**
142
+ `sock_connect` is similar to `sock_accept` but should be used to initiate a
143
+ client connection to the address requested.
144
+
145
+ Returns -1 on error. Returns a valid socket (non-random) UUID.
146
+
147
+ Socket UUIDs are predictable and shouldn't be used outside the local system.
148
+ They protect against connection mixups on concurrent systems (i.e. when saving
149
+ client data for "broadcasting" or when an old client task is preparing a
150
+ response in the background while a disconnection and a new connection occur on
151
+ the same `fd`).
152
+
153
+ When using `libreact`, remember to call `int reactor_add(intptr_t uuid);` to
154
+ listen for events.
155
+
156
+ NOTICE:
157
+
158
+ This function is non-blocking, meaning that the connection probably wasn't
159
+ established by the time the function returns (this prevents the function from
160
+ hanging while waiting for a network timeout).
161
+
162
+ Use select, poll, `libreact` or other solutions to review the connection state
163
+ before attempting to write to the socket.
164
+ */
165
+ intptr_t sock_connect(char* address, char* port);
166
+
167
+ /**
168
+ `sock_open` takes an existing file descriptor `fd` and initializes it's status
169
+ as open and available for `sock_API` calls, returning a valid UUID.
170
+
171
+ This will reinitialize the data (user buffer etc') for the file descriptor
172
+ provided, calling the `reactor_on_close` callback if the `fd` was previously
173
+ marked as used.
174
+
175
+ When using `libreact`, remember to call `int reactor_add(intptr_t uuid);` to
176
+ listen for events.
177
+
178
+ Returns -1 on error. Returns a valid socket (non-random) UUID.
179
+
180
+ Socket UUIDs are predictable and shouldn't be used outside the local system.
181
+ They protect against connection mixups on concurrent systems (i.e. when saving
182
+ client data for "broadcasting" or when an old client task is preparing a
183
+ response in the background while a disconnection and a new connection occur on
184
+ the same `fd`).
185
+ */
186
+ intptr_t sock_open(int fd);
187
+
188
+ /**
189
+ Returns 1 if the uuid refers to a valid and open, socket.
190
+
191
+ Returns 0 if not.
192
+ */
193
+ int sock_isvalid(intptr_t uuid);
194
+
195
+ /**
196
+ `sock_fd2uuid` takes an existing file decriptor `fd` and returns it's active
197
+ `uuid`.
198
+
199
+ If the file descriptor is marked as closed (wasn't opened / registered with
200
+ `libsock`) the function returns -1;
201
+
202
+ If the file descriptor was closed remotely (or not using `libsock`), a false
203
+ positive will be possible. This is not an issue, since the use of an invalid fd
204
+ will result in the registry being updated and the fd being closed.
205
+
206
+ Returns -1 on error. Returns a valid socket (non-random) UUID.
207
+ */
208
+ intptr_t sock_fd2uuid(int fd);
209
+
210
+ /**
211
+ "Touches" a socket connection. This is a place holder for an optional callback
212
+ for systems that apply timeout reviews. `libsock` supplies a default
213
+ implementation (that does nothing) is cases where a callback wasn't defined.
214
+ */
215
+ void sock_touch(intptr_t uuid);
216
+
217
+ /**
218
+ `sock_read` attempts to read up to count bytes from the socket into the buffer
219
+ starting at buf.
220
+
221
+ It's behavior should conform to the native `read` implementations, except some
222
+ data might be available in the kernel's buffer while it is not available to be
223
+ read using sock_read (i.e., when using a transport layer, such as TLS).
224
+
225
+ Also, some internal buffering will might be used in cases where the transport
226
+ layer data available is larger then the data requested.
227
+ */
228
+ ssize_t sock_read(intptr_t uuid, void* buf, size_t count);
229
+
230
+ typedef struct {
231
+ /** The fd for sending data. */
232
+ intptr_t fduuid;
233
+ /** The data to be sent. This can be either a byte stream or a file pointer
234
+ * (`FILE *`). */
235
+ const void* buffer;
236
+ /** The length (size) of the buffer. irrelevant for file pointers. */
237
+ size_t length;
238
+ /** Starting point offset, when the buffer is a file
239
+ * (see `sock_write_info_s.is_fd`). */
240
+ off_t offset;
241
+ /** The user land buffer will receive ownership of the buffer (forced as
242
+ * TRUE
243
+ * when `file` is set). */
244
+ unsigned move : 1;
245
+ /** The packet will be sent as soon as possible. */
246
+ unsigned urgent : 1;
247
+ /** The buffer contains the value of a file descriptor int - casting, not
248
+ * pointing, i.e.: `.buffer = (void*)fd;` */
249
+ unsigned is_fd : 1;
250
+ /** for internal use */
251
+ unsigned rsv : 1;
252
+ } sock_write_info_s;
253
+ /**
254
+ `sock_write2_fn` is the actual function behind the macro `sock_write2`.
255
+ */
256
+ ssize_t sock_write2_fn(sock_write_info_s options);
257
+ /**
258
+ `sock_write2` is similar to `sock_write`, except special properties can be set.
259
+
260
+ On error, -1 will be returned. Otherwise returns 0. All the bytes are
261
+ transferred to the socket's user level buffer.
262
+ */
263
+ #define sock_write2(...) sock_write2_fn((sock_write_info_s){__VA_ARGS__})
264
+ /**
265
+ `sock_write` writes up to count bytes from the buffer pointed `buf` to the
266
+ buffer associated with the socket `sockfd`.
267
+
268
+ The data isn't necessarily written to the socket and multiple calls to
269
+ `sock_flush` might be required before all the data is actually sent.
270
+
271
+ On error, -1 will be returned. Otherwise returns 0. All the bytes are
272
+ transferred to the socket's user level buffer.
273
+
274
+ **Note** this is actually a specific case of `sock_write2` and this macro
275
+ actually calls `sock_write2`.
276
+ */
277
+ #define sock_write(uuid, buf, count) \
278
+ sock_write2(.fduuid = (uuid), .buffer = (buf), .length = (count))
279
+
280
+ /**
281
+ Sends data from a file as if it were a single atomic packet (sends up to
282
+ length bytes or until EOF is reached).
283
+
284
+ Once the file was sent, the `source_fd` will be closed using `close`.
285
+
286
+ The file will be buffered to the socket chunk by chunk, so that memory
287
+ consumption is capped. The system's `sendfile` might be used if conditions
288
+ permit.
289
+
290
+ `offset` dictates the starting point for te data to be sent and length sets
291
+ the maximum amount of data to be sent.
292
+
293
+ Returns -1 and closes the file on error. Returns 0 on success.
294
+ */
295
+ __unused static inline ssize_t sock_sendfile(intptr_t uuid,
296
+ int source_fd,
297
+ off_t offset,
298
+ size_t length) {
299
+ return sock_write2(.fduuid = uuid, .buffer = (void*)((intptr_t)source_fd),
300
+ .length = length, .is_fd = 1, .offset = offset);
301
+ }
302
+
303
+ /**
304
+ `sock_flush` writes the data in the internal buffer to the underlying file
305
+ descriptor and closes the underlying fd once it's marked for closure (and all
306
+ the data was sent).
307
+
308
+ Return value: 0 will be returned on success and -1 will be returned on an error
309
+ or when the connection is closed.
310
+
311
+ **Please Note**: when using `libreact`, the `sock_flush` will be called
312
+ automatically when the socket is ready.
313
+ */
314
+ ssize_t sock_flush(intptr_t uuid);
315
+ /**
316
+ `sock_flush_strong` performs the same action as `sock_flush` but returns only
317
+ after all the data was sent. This is a "busy" wait, polling isn't performed.
318
+ */
319
+ void sock_flush_strong(intptr_t uuid);
320
+ /**
321
+ Calls `sock_flush` for each file descriptor that's buffer isn't empty.
322
+ */
323
+ void sock_flush_all(void);
324
+ /**
325
+ `sock_close` marks the connection for disconnection once all the data was sent.
326
+ The actual disconnection will be managed by the `sock_flush` function.
327
+
328
+ `sock_flash` will automatically be called.
329
+ */
330
+ void sock_close(intptr_t uuid);
331
+ /**
332
+ `sock_force_close` closes the connection immediately, without adhering to any
333
+ protocol restrictions and without sending any remaining data in the connection
334
+ buffer.
335
+ */
336
+ void sock_force_close(intptr_t uuid);
337
+
338
+ /* *****************************************************************************
339
+ Direct user level buffer API.
340
+ */
341
+
342
+ /**
343
+ Buffer packets - can be used for directly writing individual or multiple packets
344
+ to the buffer instead of using the `sock_write(2)` helper functions / macros.
345
+
346
+ See `sock_checkout_packet` and `sock_send_packet` for more information.
347
+
348
+ Unused Packets that were checked out using the `sock_checkout_packet` function,
349
+ should never be freed using `free` and should always use the `sock_free_packet`
350
+ function.
351
+ */
352
+ typedef struct sock_packet_s {
353
+ ssize_t length;
354
+ void* buffer;
355
+ /** Metadata about the packet. */
356
+ struct {
357
+ /** allows the linking of a number of packets together. */
358
+ struct sock_packet_s* next;
359
+ /** Starting point offset, when the buffer is a file (see
360
+ * `sock_packet_s.metadata.is_fd`). */
361
+ off_t offset;
362
+ /** sets whether a packet can be inserted before this packet without
363
+ * interrupting the communication flow. */
364
+ unsigned can_interrupt : 1;
365
+ /** sets whether a packet's buffer contains a file descriptor - casting, not
366
+ * pointing, i.e.: `packet->buffer = (void*)fd;` */
367
+ unsigned is_fd : 1;
368
+ /** Keeps the `FILE *` or fd open - avoids automatically closing the file.
369
+ */
370
+ unsigned keep_open : 1;
371
+ /** sets whether a packet's buffer is pre-allocated (references the
372
+ * `internal_memory`) or whether the data is allocated using `malloc` and
373
+ * should be freed. */
374
+ unsigned external : 1;
375
+ /** sets whether this packet (or packet chain) should be inserted in before
376
+ * the first `can_interrupt` packet, or at the end of the queu. */
377
+ unsigned urgent : 1;
378
+ /** Reserved for internal use - (memory shifting flag)*/
379
+ unsigned internal_flag : 1;
380
+ /** Reserved for future use. */
381
+ unsigned rsrv : 2;
382
+ /**/
383
+ } metadata;
384
+ } sock_packet_s;
385
+
386
+ /**
387
+ Checks out a `sock_packet_s` from the packet pool, transfering the
388
+ ownership of the memory to the calling function. The function will hang until a
389
+ packet becomes available, so never check out more then a single packet at a
390
+ time and remember to free or send the packet.
391
+
392
+ Every checked out buffer packet comes with an attached buffer of
393
+ BUFFER_PACKET_SIZE bytes. This buffer is accessible using the `packet->buffer`
394
+ pointer (which can be safely overwritten to point to an external buffer).
395
+
396
+ This attached buffer is safely and automatically freed or returned to the memory
397
+ pool once `sock_send_packet` or `sock_free_packet` are called.
398
+ */
399
+ sock_packet_s* sock_checkout_packet(void);
400
+ /**
401
+ Attaches a packet to a socket's output buffer and calls `sock_flush` for the
402
+ socket.
403
+
404
+ The packet's memory is **always** handled by the `sock_send_packet` function
405
+ (even on error).
406
+
407
+ Returns -1 on error. Returns 0 on success.
408
+ */
409
+ ssize_t sock_send_packet(intptr_t uuid, sock_packet_s* packet);
410
+
411
+ /**
412
+ Use `sock_free_packet` to free unused packets that were checked-out using
413
+ `sock_checkout_packet`.
414
+
415
+ NEVER use `free`, for any packet checked out using the pool management function
416
+ `sock_checkout_packet`.
417
+ */
418
+ void sock_free_packet(sock_packet_s* packet);
419
+
420
+ /* *****************************************************************************
421
+ TLC - Transport Layer Callback.
422
+
423
+ Experimental
424
+ */
425
+
426
+ /**
427
+ The following struct is used for setting a the read/write hooks that will
428
+ replace the default system calls to `recv` and `write`. */
429
+ typedef struct sock_rw_hook_s {
430
+ /** Implement reading from a file descriptor. Should behave like the file
431
+ * system `read` call, including the setup or errno to EAGAIN / EWOULDBLOCK.*/
432
+ ssize_t (*read)(intptr_t fduuid, void* buf, size_t count);
433
+ /** Implement writing to a file descriptor. Should behave like the file system
434
+ * `write` call.*/
435
+ ssize_t (*write)(intptr_t fduuid, const void* buf, size_t count);
436
+ /** When implemented, this function will be called to flush any data remaining
437
+ * in the internal buffer.
438
+ * The function should return the number of bytes remaining in the internal
439
+ * buffer (0 is a valid response) on -1 (on error).
440
+ * It is important thet the `flush` function write to the underlying fd until
441
+ * the
442
+ * writing operation returns -1 with EWOULDBLOCK or all the data was written.
443
+ */
444
+ ssize_t (*flush)(intptr_t fduuid);
445
+ /** The `on_clear` callback is called when the socket data is cleared, ideally
446
+ * when the connection is closed, allowing for dynamic sock_rw_hook_s memory
447
+ * management.
448
+ *
449
+ * The `on_clear` callback should manage is own thread safety mechanism, if
450
+ * required. */
451
+ void (*on_clear)(intptr_t fduuid, struct sock_rw_hook_s* rw_hook);
452
+ } sock_rw_hook_s;
453
+
454
+ /* *****************************************************************************
455
+ RW hooks implementation
456
+ */
457
+
458
+ /** Gets a socket hook state (a pointer to the struct). */
459
+ struct sock_rw_hook_s* sock_rw_hook_get(intptr_t fduuid);
460
+
461
+ /** Sets a socket hook state (a pointer to the struct). */
462
+ int sock_rw_hook_set(intptr_t fduuid, sock_rw_hook_s* rw_hooks);
463
+
464
+ /* *****************************************************************************
465
+ test
466
+ */
467
+ #ifdef DEBUG
468
+ void sock_libtest(void);
469
+ #endif
470
+
471
+ /* *****************************************************************************
472
+ C++ extern
473
+ */
474
+ #if defined(__cplusplus)
475
+ }
476
+ #endif
477
+
478
+ #endif /* LIB_SOCK */