spiped 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/spiped/extconf.rb +3 -0
- data/ext/spiped/spiped-source/BUILDING +46 -0
- data/ext/spiped/spiped-source/CHANGELOG +44 -0
- data/ext/spiped/spiped-source/COPYRIGHT +33 -0
- data/ext/spiped/spiped-source/Makefile +47 -0
- data/ext/spiped/spiped-source/Makefile.POSIX +27 -0
- data/ext/spiped/spiped-source/Makefile.inc +20 -0
- data/ext/spiped/spiped-source/Makefile.prog +23 -0
- data/ext/spiped/spiped-source/POSIX/README +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-cflags.sh +10 -0
- data/ext/spiped/spiped-source/POSIX/posix-clock_realtime.c +3 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.c +1 -0
- data/ext/spiped/spiped-source/POSIX/posix-l.sh +14 -0
- data/ext/spiped/spiped-source/POSIX/posix-msg_nosignal.c +3 -0
- data/ext/spiped/spiped-source/README +198 -0
- data/ext/spiped/spiped-source/STYLE +151 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.c +464 -0
- data/ext/spiped/spiped-source/lib/dnsthread/dnsthread.h +45 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.c +442 -0
- data/ext/spiped/spiped-source/libcperciva/alg/sha256.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-AESNI.c +13 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport-X86-CPUID.c +8 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/Build/cpusupport.sh +37 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport.h +63 -0
- data/ext/spiped/spiped-source/libcperciva/cpusupport/cpusupport_x86_aesni.c +30 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.c +166 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.c +229 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aes_aesni.h +31 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.c +124 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_aesctr.h +41 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.c +293 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh.h +43 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.c +46 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_dh_group14.h +9 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.c +215 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_entropy.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.c +21 -0
- data/ext/spiped/spiped-source/libcperciva/crypto/crypto_verify_bytes.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.c +276 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/elasticarray.h +167 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/mpool.h +85 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.c +334 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/ptrheap.h +89 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.c +241 -0
- data/ext/spiped/spiped-source/libcperciva/datastruct/timerqueue.h +60 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.c +203 -0
- data/ext/spiped/spiped-source/libcperciva/events/events.h +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_immediate.c +149 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_internal.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network.c +347 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_network_selectstats.c +106 -0
- data/ext/spiped/spiped-source/libcperciva/events/events_timer.c +273 -0
- data/ext/spiped/spiped-source/libcperciva/network/network.h +95 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_accept.c +103 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_connect.c +258 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_read.c +155 -0
- data/ext/spiped/spiped-source/libcperciva/network/network_write.c +188 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.c +49 -0
- data/ext/spiped/spiped-source/libcperciva/util/asprintf.h +16 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.c +134 -0
- data/ext/spiped/spiped-source/libcperciva/util/daemonize.h +10 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/entropy.h +13 -0
- data/ext/spiped/spiped-source/libcperciva/util/imalloc.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.c +19 -0
- data/ext/spiped/spiped-source/libcperciva/util/insecure_memzero.h +33 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.c +52 -0
- data/ext/spiped/spiped-source/libcperciva/util/monoclock.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.c +54 -0
- data/ext/spiped/spiped-source/libcperciva/util/noeintr.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.c +472 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock.h +56 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_internal.h +14 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.c +271 -0
- data/ext/spiped/spiped-source/libcperciva/util/sock_util.h +51 -0
- data/ext/spiped/spiped-source/libcperciva/util/sysendian.h +146 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.c +76 -0
- data/ext/spiped/spiped-source/libcperciva/util/warnp.h +59 -0
- data/ext/spiped/spiped-source/proto/proto_conn.c +362 -0
- data/ext/spiped/spiped-source/proto/proto_conn.h +25 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.c +396 -0
- data/ext/spiped/spiped-source/proto/proto_crypt.h +102 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.c +330 -0
- data/ext/spiped/spiped-source/proto/proto_handshake.h +30 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.c +202 -0
- data/ext/spiped/spiped-source/proto/proto_pipe.h +23 -0
- data/ext/spiped/spiped-source/spipe/Makefile +90 -0
- data/ext/spiped/spiped-source/spipe/README +24 -0
- data/ext/spiped/spiped-source/spipe/main.c +178 -0
- data/ext/spiped/spiped-source/spipe/pushbits.c +101 -0
- data/ext/spiped/spiped-source/spipe/pushbits.h +10 -0
- data/ext/spiped/spiped-source/spipe/spipe.1 +60 -0
- data/ext/spiped/spiped-source/spiped/Makefile +98 -0
- data/ext/spiped/spiped-source/spiped/README +62 -0
- data/ext/spiped/spiped-source/spiped/dispatch.c +214 -0
- data/ext/spiped/spiped-source/spiped/dispatch.h +27 -0
- data/ext/spiped/spiped-source/spiped/main.c +267 -0
- data/ext/spiped/spiped-source/spiped/spiped.1 +112 -0
- data/lib/spiped.rb +3 -0
- 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
|
+
}
|