spiped 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/ext/spiped/extconf.rb +3 -0
  3. data/ext/spiped/spiped-source/BUILDING +46 -0
  4. data/ext/spiped/spiped-source/CHANGELOG +44 -0
  5. data/ext/spiped/spiped-source/COPYRIGHT +33 -0
  6. data/ext/spiped/spiped-source/Makefile +47 -0
  7. data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
  8. data/ext/spiped/spiped-source/Makefile.inc +20 -0
  9. data/ext/spiped/spiped-source/Makefile.prog +23 -0
  10. data/ext/spiped/spiped-source/POSIX/README +10 -0
  11. data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
  12. data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
  13. data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
  14. data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
  15. data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
  16. data/ext/spiped/spiped-source/README +198 -0
  17. data/ext/spiped/spiped-source/STYLE +151 -0
  18. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
  19. data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
  20. data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
  21. data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
  22. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
  23. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
  24. data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
  25. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
  26. data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
  27. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
  28. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
  29. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
  30. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
  31. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
  32. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
  33. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
  34. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
  35. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
  36. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
  37. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
  38. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
  39. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
  40. data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
  41. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
  42. data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
  43. data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
  44. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
  45. data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
  46. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
  47. data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
  48. data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
  49. data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
  50. data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
  51. data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
  52. data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
  53. data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
  54. data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
  55. data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
  56. data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
  57. data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
  58. data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
  59. data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
  60. data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
  61. data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
  62. data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
  63. data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
  64. data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
  65. data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
  66. data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
  67. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
  68. data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
  69. data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
  70. data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
  71. data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
  72. data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
  73. data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
  74. data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
  75. data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
  76. data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
  77. data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
  78. data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
  79. data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
  80. data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
  81. data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
  82. data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
  83. data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
  84. data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
  85. data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
  86. data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
  87. data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
  88. data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
  89. data/ext/spiped/spiped-source/spipe/Makefile +90 -0
  90. data/ext/spiped/spiped-source/spipe/README +24 -0
  91. data/ext/spiped/spiped-source/spipe/main.c +178 -0
  92. data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
  93. data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
  94. data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
  95. data/ext/spiped/spiped-source/spiped/Makefile +98 -0
  96. data/ext/spiped/spiped-source/spiped/README +62 -0
  97. data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
  98. data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
  99. data/ext/spiped/spiped-source/spiped/main.c +267 -0
  100. data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
  101. data/lib/spiped.rb +3 -0
  102. metadata +143 -0
@@ -0,0 +1,103 @@
1
+ #include <sys/types.h>
2
+ #include <sys/socket.h>
3
+
4
+ #include <errno.h>
5
+ #include <stdlib.h>
6
+
7
+ #include "events.h"
8
+
9
+ #include "network.h"
10
+
11
+ struct accept_cookie {
12
+ int (* callback)(void *, int);
13
+ void * cookie;
14
+ int fd;
15
+ };
16
+
17
+ /* Accept the connection and invoke the callback. */
18
+ static int
19
+ callback_accept(void * cookie)
20
+ {
21
+ struct accept_cookie * C = cookie;
22
+ int s;
23
+ int rc;
24
+
25
+ /* Attempt to accept a new connection. */
26
+ if ((s = accept(C->fd, NULL, NULL)) == -1) {
27
+ /* If a connection isn't available, reset the callback. */
28
+ if ((errno == EAGAIN) ||
29
+ (errno == EWOULDBLOCK) ||
30
+ (errno == ECONNABORTED) ||
31
+ (errno == EINTR))
32
+ goto tryagain;
33
+ }
34
+
35
+ /* Call the upstream callback. */
36
+ rc = (C->callback)(C->cookie, s);
37
+
38
+ /* Free the cookie. */
39
+ free(C);
40
+
41
+ /* Return status from upstream callback. */
42
+ return (rc);
43
+
44
+ tryagain:
45
+ /* Reset the callback. */
46
+ return (events_network_register(callback_accept, C, C->fd,
47
+ EVENTS_NETWORK_OP_READ));
48
+ }
49
+
50
+ /**
51
+ * network_accept(fd, callback, cookie):
52
+ * Asynchronously accept a connection on the socket ${fd}, which must be
53
+ * already marked as listening and non-blocking. When a connection has been
54
+ * accepted or an error occurs, invoke ${callback}(${cookie}, s) where s is
55
+ * the accepted connection or -1 on error. Return a cookie which can be
56
+ * passed to network_accept_cancel in order to cancel the accept.
57
+ */
58
+ void *
59
+ network_accept(int fd, int (* callback)(void *, int), void * cookie)
60
+ {
61
+ struct accept_cookie * C;
62
+
63
+ /* Bake a cookie. */
64
+ if ((C = malloc(sizeof(struct accept_cookie))) == NULL)
65
+ goto err0;
66
+ C->callback = callback;
67
+ C->cookie = cookie;
68
+ C->fd = fd;
69
+
70
+ /*
71
+ * Register a network event. A connection arriving on a listening
72
+ * socket is treated by select(2) as the socket becoming readable.
73
+ */
74
+ if (events_network_register(callback_accept, C, C->fd,
75
+ EVENTS_NETWORK_OP_READ))
76
+ goto err1;
77
+
78
+ /* Success! */
79
+ return (C);
80
+
81
+ err1:
82
+ free(C);
83
+ err0:
84
+ /* Failure! */
85
+ return (NULL);
86
+ }
87
+
88
+ /**
89
+ * network_accept_cancel(cookie);
90
+ * Cancel the connection accept for which the cookie ${cookie} was returned
91
+ * by network_accept. Do not invoke the callback associated with the accept.
92
+ */
93
+ void
94
+ network_accept_cancel(void * cookie)
95
+ {
96
+ struct accept_cookie * C = cookie;
97
+
98
+ /* Cancel the network event. */
99
+ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ);
100
+
101
+ /* Free the cookie. */
102
+ free(C);
103
+ }
@@ -0,0 +1,258 @@
1
+ #include <sys/types.h>
2
+ #include <sys/select.h>
3
+ #include <sys/socket.h>
4
+
5
+ #include <assert.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <unistd.h>
9
+
10
+ #include "events.h"
11
+ #include "sock.h"
12
+
13
+ #include "network.h"
14
+
15
+ struct connect_cookie {
16
+ int (* callback)(void *, int);
17
+ void * cookie;
18
+ struct sock_addr * const * sas;
19
+ struct timeval timeo;
20
+ void * cookie_immediate;
21
+ int s;
22
+ int timeo_enabled;
23
+ void * cookie_timeo;
24
+ };
25
+
26
+ static int tryconnect(struct connect_cookie *);
27
+
28
+ /* Invoke the upstream callback and clean up. */
29
+ static int
30
+ docallback(void * cookie)
31
+ {
32
+ struct connect_cookie * C = cookie;
33
+ int rc;
34
+
35
+ /* Invoke the upstream callback. */
36
+ rc = (C->callback)(C->cookie, C->s);
37
+
38
+ /* Free the cookie. */
39
+ free(C);
40
+
41
+ /* Return status from upstream callback. */
42
+ return (rc);
43
+ }
44
+
45
+ /* An address failed to connect. */
46
+ static int
47
+ dofailed(struct connect_cookie * C)
48
+ {
49
+
50
+ /* Close the socket which failed to connect. */
51
+ close(C->s);
52
+
53
+ /* We don't have an open socket any more. */
54
+ C->s = -1;
55
+
56
+ /* This address didn't work. */
57
+ C->sas++;
58
+
59
+ /* Try other addresses until we run out of options. */
60
+ return (tryconnect(C));
61
+ }
62
+
63
+ /* Callback when connect(2) succeeds or fails. */
64
+ static int
65
+ callback_connect(void * cookie)
66
+ {
67
+ struct connect_cookie * C = cookie;
68
+ int sockerr;
69
+ socklen_t sockerrlen = sizeof(int);
70
+
71
+ /* Stop waiting for the timer callback. */
72
+ if (C->cookie_timeo != NULL) {
73
+ events_timer_cancel(C->cookie_timeo);
74
+ C->cookie_timeo = NULL;
75
+ }
76
+
77
+ /* Did we succeed? */
78
+ if (getsockopt(C->s, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen))
79
+ goto err1;
80
+ if (sockerr != 0)
81
+ return (dofailed(C));
82
+
83
+ /*
84
+ * Perform the callback (this can be done here rather than being
85
+ * scheduled as an immediate callback, as we're already running from
86
+ * callback context).
87
+ */
88
+ return (docallback(C));
89
+
90
+ err1:
91
+ close(C->s);
92
+ free(C);
93
+
94
+ /* Fatal error! */
95
+ return (-1);
96
+ }
97
+
98
+ /* Callback when a timer expires. */
99
+ static int
100
+ callback_timeo(void * cookie)
101
+ {
102
+ struct connect_cookie * C = cookie;
103
+
104
+ /* We're not waiting for a timer callback any more. */
105
+ C->cookie_timeo = NULL;
106
+
107
+ /* Stop listening for this socket. */
108
+ events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE);
109
+
110
+ /* This connect attempt failed. */
111
+ return (dofailed(C));
112
+ }
113
+
114
+ /* Try to launch a connection. Free the cookie on fatal errors. */
115
+ static int
116
+ tryconnect(struct connect_cookie * C)
117
+ {
118
+
119
+ /* Try addresses until we find one which doesn't fail immediately. */
120
+ for (; C->sas[0] != NULL; C->sas++) {
121
+ /* Can we try to connect to this address? */
122
+ if ((C->s = sock_connect_nb(C->sas[0])) != -1)
123
+ break;
124
+ }
125
+
126
+ /* Did we run out of addresses to try? */
127
+ if (C->sas[0] == NULL)
128
+ goto failed;
129
+
130
+ /* If we've been asked to have a timeout, set one. */
131
+ if (C->timeo_enabled) {
132
+ if ((C->cookie_timeo = events_timer_register(callback_timeo,
133
+ C, &C->timeo)) == NULL)
134
+ goto err1;
135
+ } else {
136
+ C->cookie_timeo = NULL;
137
+ }
138
+
139
+ /* Wait until this socket connects or fails to do so. */
140
+ if (events_network_register(callback_connect, C, C->s,
141
+ EVENTS_NETWORK_OP_WRITE))
142
+ goto err2;
143
+
144
+ /* Success! */
145
+ return (0);
146
+
147
+ failed:
148
+ /* Schedule a callback. */
149
+ if ((C->cookie_immediate =
150
+ events_immediate_register(docallback, C, 0)) == NULL)
151
+ goto err1;
152
+
153
+ /* Failure successfully handled. */
154
+ return (0);
155
+
156
+ err2:
157
+ if (C->cookie_timeo != NULL)
158
+ events_timer_cancel(C->cookie_timeo);
159
+ err1:
160
+ if (C->s != -1)
161
+ close(C->s);
162
+ free(C);
163
+
164
+ /* Fatal error. */
165
+ return (-1);
166
+ }
167
+
168
+ /**
169
+ * network_connect(sas, callback, cookie):
170
+ * Iterate through the addresses in ${sas}, attempting to create and connect
171
+ * a non-blocking socket. Once connected, invoke ${callback}(${cookie}, s)
172
+ * where s is the connected socket; upon fatal error or if there are no
173
+ * addresses remaining to attempt, invoke ${callback}(${cookie}, -1). Return
174
+ * a cookie which can be passed to network_connect_cancel in order to cancel
175
+ * the connection attempt.
176
+ */
177
+ void *
178
+ network_connect(struct sock_addr * const * sas,
179
+ int (* callback)(void *, int), void * cookie)
180
+ {
181
+
182
+ /* Let network_connect_timeo handle this. */
183
+ return (network_connect_timeo(sas, NULL, callback, cookie));
184
+ }
185
+
186
+ /**
187
+ * network_connect_timeo(sas, timeo, callback, cookie):
188
+ * Behave as network_connect, but wait a duration of at most ${timeo} for
189
+ * each address which is being attempted.
190
+ */
191
+ void *
192
+ network_connect_timeo(struct sock_addr * const * sas,
193
+ const struct timeval * timeo,
194
+ int (* callback)(void *, int), void * cookie)
195
+ {
196
+ struct connect_cookie * C;
197
+
198
+ /* Bake a cookie. */
199
+ if ((C = malloc(sizeof(struct connect_cookie))) == NULL)
200
+ goto err0;
201
+ C->callback = callback;
202
+ C->cookie = cookie;
203
+ C->sas = sas;
204
+ C->cookie_immediate = NULL;
205
+ C->cookie_timeo = NULL;
206
+ C->s = -1;
207
+
208
+ /* Do we have a timeout? */
209
+ if (timeo != NULL) {
210
+ memcpy(&C->timeo, timeo, sizeof(struct timeval));
211
+ C->timeo_enabled = 1;
212
+ } else {
213
+ C->timeo_enabled = 0;
214
+ }
215
+
216
+ /* Try to connect to the first address. */
217
+ if (tryconnect(C))
218
+ goto err0;
219
+
220
+ /* Success! */
221
+ return (C);
222
+
223
+ err0:
224
+ /* Failure! */
225
+ return (NULL);
226
+ }
227
+
228
+ /**
229
+ * network_connect_cancel(cookie):
230
+ * Cancel the connection attempt for which ${cookie} was returned by
231
+ * network_connect. Do not invoke the associated callback.
232
+ */
233
+ void
234
+ network_connect_cancel(void * cookie)
235
+ {
236
+ struct connect_cookie * C = cookie;
237
+
238
+ /* We should have either an immediate callback or a socket. */
239
+ assert((C->cookie_immediate != NULL) || (C->s != -1));
240
+ assert((C->cookie_immediate == NULL) || (C->s == -1));
241
+
242
+ /* Cancel any timer. */
243
+ if (C->cookie_timeo != NULL)
244
+ events_timer_cancel(C->cookie_timeo);
245
+
246
+ /* Cancel any immediate callback. */
247
+ if (C->cookie_immediate != NULL)
248
+ events_immediate_cancel(C->cookie_immediate);
249
+
250
+ /* Close any socket. */
251
+ if (C->s != -1) {
252
+ events_network_cancel(C->s, EVENTS_NETWORK_OP_WRITE);
253
+ close(C->s);
254
+ }
255
+
256
+ /* Free the cookie. */
257
+ free(C);
258
+ }
@@ -0,0 +1,155 @@
1
+ #include <sys/socket.h>
2
+
3
+ #include <assert.h>
4
+ #include <errno.h>
5
+ #include <limits.h>
6
+ #include <stdint.h>
7
+ #include <stdlib.h>
8
+ #include <unistd.h>
9
+
10
+ #include "events.h"
11
+ #include "warnp.h"
12
+
13
+ #include "network.h"
14
+
15
+ struct network_read_cookie {
16
+ int (*callback)(void *, ssize_t);
17
+ void * cookie;
18
+ int fd;
19
+ uint8_t * buf;
20
+ size_t buflen;
21
+ size_t minlen;
22
+ size_t bufpos;
23
+ };
24
+
25
+ /* Invoke the callback, clean up, and return the callback's status. */
26
+ static int
27
+ docallback(struct network_read_cookie * C, ssize_t nbytes)
28
+ {
29
+ int rc;
30
+
31
+ /* Invoke the callback. */
32
+ rc = (C->callback)(C->cookie, nbytes);
33
+
34
+ /* Clean up. */
35
+ free(C);
36
+
37
+ /* Return the callback's status. */
38
+ return (rc);
39
+ }
40
+
41
+ /* The socket is ready for reading/writing. */
42
+ static int
43
+ callback_buf(void * cookie)
44
+ {
45
+ struct network_read_cookie * C = cookie;
46
+ size_t oplen;
47
+ ssize_t len;
48
+
49
+ /* Attempt to read/write data to/from the buffer. */
50
+ oplen = C->buflen - C->bufpos;
51
+ len = recv(C->fd, C->buf + C->bufpos, oplen, 0);
52
+
53
+ /* Failure? */
54
+ if (len == -1) {
55
+ /* Was it really an error, or just a try-again? */
56
+ if ((errno == EAGAIN) ||
57
+ (errno == EWOULDBLOCK) ||
58
+ (errno == EINTR))
59
+ goto tryagain;
60
+
61
+ /* Something went wrong. */
62
+ goto failed;
63
+ } else if (len == 0) {
64
+ /* The socket was shut down by the remote host. */
65
+ goto eof;
66
+ }
67
+
68
+ /* We processed some data. Do we need to keep going? */
69
+ if ((C->bufpos += len) < C->minlen)
70
+ goto tryagain;
71
+
72
+ /* Invoke the callback and return. */
73
+ return (docallback(C, C->bufpos));
74
+
75
+ tryagain:
76
+ /* Reset the event. */
77
+ if (events_network_register(callback_buf, C, C->fd,
78
+ EVENTS_NETWORK_OP_READ))
79
+ goto failed;
80
+
81
+ /* Callback was reset. */
82
+ return (0);
83
+
84
+ eof:
85
+ /* Invoke the callback with an EOF status and return. */
86
+ return (docallback(C, 0));
87
+
88
+ failed:
89
+ /* Invoke the callback with a failure status and return. */
90
+ return (docallback(C, -1));
91
+ }
92
+
93
+ /**
94
+ * network_read(fd, buf, buflen, minread, callback, cookie):
95
+ * Asynchronously read up to ${buflen} bytes of data from ${fd} into ${buf}.
96
+ * When at least ${minread} bytes have been read or on error, invoke
97
+ * ${callback}(${cookie}, lenread), where lenread is 0 on EOF or -1 on error,
98
+ * and the number of bytes read (between ${minread} and ${buflen} inclusive)
99
+ * otherwise. Return a cookie which can be passed to network_read_cancel in
100
+ * order to cancel the read.
101
+ */
102
+ void *
103
+ network_read(int fd, uint8_t * buf, size_t buflen, size_t minread,
104
+ int (* callback)(void *, ssize_t), void * cookie)
105
+ {
106
+ struct network_read_cookie * C;
107
+
108
+ /* Make sure buflen is non-zero. */
109
+ assert(buflen != 0);
110
+
111
+ /* Sanity-check: # bytes must fit into a ssize_t. */
112
+ assert(buflen <= SSIZE_MAX);
113
+
114
+ /* Bake a cookie. */
115
+ if ((C = malloc(sizeof(struct network_read_cookie))) == NULL)
116
+ goto err0;
117
+ C->callback = callback;
118
+ C->cookie = cookie;
119
+ C->fd = fd;
120
+ C->buf = buf;
121
+ C->buflen = buflen;
122
+ C->minlen = minread;
123
+ C->bufpos = 0;
124
+
125
+ /* Register a callback for network readiness. */
126
+ if (events_network_register(callback_buf, C, C->fd,
127
+ EVENTS_NETWORK_OP_READ))
128
+ goto err1;
129
+
130
+ /* Success! */
131
+ return (C);
132
+
133
+ err1:
134
+ free(C);
135
+ err0:
136
+ /* Failure! */
137
+ return (NULL);
138
+ }
139
+
140
+ /**
141
+ * network_read_cancel(cookie):
142
+ * Cancel the buffer read for which the cookie ${cookie} was returned by
143
+ * network_read. Do not invoke the callback associated with the read.
144
+ */
145
+ void
146
+ network_read_cancel(void * cookie)
147
+ {
148
+ struct network_read_cookie * C = cookie;
149
+
150
+ /* Kill the network event. */
151
+ events_network_cancel(C->fd, EVENTS_NETWORK_OP_READ);
152
+
153
+ /* Free the cookie. */
154
+ free(C);
155
+ }