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,151 @@
1
+ Code style
2
+ ==========
3
+
4
+ In general, FreeBSD style(9) should be followed unless it is irrelevant
5
+ (e.g., $FreeBSD$ tags).
6
+
7
+ Functions with external linkage are declared like this:
8
+ /**
9
+ * module_func(arg1, arg2):
10
+ * Description of what the function does, referring to arguments as
11
+ * ${arg1} or suchlike.
12
+ */
13
+ int module_func(void *, int);
14
+
15
+ The identical comment appears in the C file where the function is defined.
16
+
17
+ Static functions may have the above form of comment, or simply a
18
+ /* Brief description of what the function does. */
19
+ line before the function.
20
+
21
+ In general, functions should return (int)(-1) or NULL to indicate error.
22
+
23
+ Errors should be printed via warnp (if errno is relevant) or warn0 (if errno
24
+ is not relevant) when they are first detected and also at higher levels where
25
+ useful. As an exception to this, malloc failures (i.e., errno = ENOMEM) can
26
+ result in failure being passed back up the call chain without being printed
27
+ immediately. (Naturally, other errors can be passed back where a function
28
+ definition so specifies; e.g., ENOENT in cases where a file not existing is
29
+ not erronous.)
30
+
31
+ The first statement in main(), after variable declarations, should be
32
+ "WARNP_INIT;" in order to set the program name used for printing warnings.
33
+
34
+ In general, functions should be structured with one return statement per
35
+ status, e.g., one return() for success and one return() for failure. Errors
36
+ should be handled by using goto to enter the error return path, e.g.,
37
+ int
38
+ foo(int bar)
39
+ {
40
+
41
+ if (something fails)
42
+ goto err0;
43
+ /* ... */
44
+ if (something else fails)
45
+ goto err1;
46
+ /* ... */
47
+ if (yet another operation fails)
48
+ goto err2;
49
+
50
+ /* Success! */
51
+ return (0);
52
+
53
+ err2:
54
+ /* Clean up something. */
55
+ err1:
56
+ /* Clean up something else. */
57
+ err0:
58
+ /* Failure! */
59
+ return (-1);
60
+ }
61
+
62
+ As an exception to the above, if there is only one way for the function to
63
+ fail, the idioms
64
+ return (baz(bar));
65
+ and
66
+ int rc;
67
+
68
+ rc = baz(bar);
69
+ /* ... cleanup code here ... */
70
+ return (rc);
71
+ are allowed; furthermore, in cases such as foo_free(), the idiom
72
+ if (we shouldn't do anything)
73
+ return;
74
+ is preferred over
75
+ if (we shouldn't do anything)
76
+ goto done;
77
+ at the start of a function.
78
+
79
+ Headers should be included in the following groups, with a blank line after
80
+ each (non-empty) group:
81
+ 1. <sys/*.h>, with <sys/types.h> first followed by others alphabetically.
82
+ 2. <net/*.h>, in alphabetical order.
83
+ 3. <*.h>, in alphabetical order.
84
+ 4. header files from /lib/, in alphabetical order.
85
+ 5. header files from the program being built, in alphabetical order.
86
+ 6. header files (usually just one) defining the interface for this C file.
87
+
88
+ If ssize_t is needed, <unistd.h> should be included to provide it.
89
+
90
+ If size_t is needed, <stddef.h> should be included to provide it unless
91
+ <stdio.h>, <stdlib.h>, <string.h>, or <unistd.h> is already required.
92
+
93
+ If the C99 integer types (uint8_t, int64_t, etc.) are required, <stdint.h>
94
+ should be included to provide them unless <inttypes.h> is already required.
95
+
96
+ The type 'char' should only be used to represent human-readable characters
97
+ (input from users, output to users, pathnames, et cetera). The type
98
+ 'char *' should normally be a NUL-terminated string. The types 'signed
99
+ char' and 'unsigned char' should never be used; C99 integer types should
100
+ be used instead.
101
+
102
+ When a variable is declared to have a pointer type, there should be a space
103
+ between the '*' and the variable name, e.g.,
104
+ int
105
+ main(int argc, char * argv[])
106
+ {
107
+ char * opt_p = NULL;
108
+ Note that this is inconsistent with FreeBSD style(9). When used as a unary
109
+ operator, '*' is not separated from its argument, e.g.,
110
+ while (*p != '\0')
111
+ p++;
112
+
113
+ When a struct is referenced, the idiom
114
+ /* Opaque types. */
115
+ struct foo;
116
+
117
+ struct bar * bar_from_foo(struct foo *);
118
+ is preferable to
119
+ #include "foo.h" /* needed for struct foo */
120
+
121
+ struct bar * bar_from_foo(struct foo *);
122
+ unless there is some reason why the internal layout of struct foo is needed
123
+ (e.g., if struct bar contains a struct foo rather than a struct foo *). Such
124
+ struct declarations should be sorted alphabetically.
125
+
126
+ The file foo.c should only export symbols of the following forms:
127
+ foo_* -- most symbols should be of this form.
128
+ FOO_* / BAR_FOO_*
129
+ -- allowed in cases where FOO or BAR_FOO is idiomatic (e.g.,
130
+ MD5, HMAC_SHA256).
131
+ foo() / defoo() / unfoo()
132
+ -- where "foo" is a verb and this improves code clarity.
133
+
134
+ Functions named foo_free should return void, and foo_free(NULL) should have
135
+ no effect.
136
+
137
+ If static variables need to be initialized to 0 (or NULL) then they should be
138
+ explicitly declared that way; implicit initialization should not be used.
139
+
140
+ In non-trivial code, comments should be included which describe in English
141
+ what is being done by the surrounding code with sufficient detail that if the
142
+ code were removed, it could be replaced based on reading the comments without
143
+ requiring any significant creativity.
144
+
145
+ Comments and documentation should be written in en-GB-oed; i.e., with
146
+ the 'u' included in words such as "honour", "colour", and "neighbour",
147
+ and the ending '-ize' in words such as "organize" and "realize". The
148
+ Oxford (aka. serial) comma should be used in lists. Quotation marks
149
+ should be placed logically, i.e., not including punctuation marks which
150
+ do not form a logical part of the quoted text. Two spaces should be used
151
+ after a period which ends a sentence.
@@ -0,0 +1,464 @@
1
+ #include <sys/socket.h>
2
+
3
+ #include <errno.h>
4
+ #include <pthread.h>
5
+ #include <stdint.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <unistd.h>
9
+
10
+ #include "events.h"
11
+ #include "noeintr.h"
12
+ #include "sock.h"
13
+ #include "warnp.h"
14
+
15
+ #include "dnsthread.h"
16
+
17
+ /* Thread management structure. */
18
+ struct dnsthread_internal {
19
+ /* Threading glue. */
20
+ pthread_t thr; /* Thread ID. */
21
+ pthread_mutex_t mtx; /* Controls access to this structure. */
22
+ pthread_cond_t cv; /* Thread sleeps on this. */
23
+
24
+ /* State management. */
25
+ int state; /* THREAD_* as below. */
26
+ int wakeupsock[2]; /* Writes to [0], reads from [1]. */
27
+
28
+ /* Address resolution variables. */
29
+ char * addr; /* Address to be resolved. */
30
+ struct sock_addr ** sas; /* Results. */
31
+ int res_errno; /* Errno to be passed back on failure. */
32
+
33
+ /* Callback to occur when resolution is complete. */
34
+ int (*callback)(void *, struct sock_addr **); /* Callback. */
35
+ void * cookie; /* Cookie. */
36
+ };
37
+
38
+ /* Cookie used by dnsthread_resolve. */
39
+ struct resolve_cookie {
40
+ int (*callback)(void *, struct sock_addr **);
41
+ void * cookie;
42
+ DNSTHREAD T;
43
+ };
44
+
45
+ /*
46
+ * Thread states. _resolveone moves the thread from SLEEPING to HASWORK;
47
+ * workthread moves the thread from HASWORK to SLEEPING; and _kill moves the
48
+ * thread from either state to SUICIDE.
49
+ */
50
+ #define THREAD_SLEEPING 0
51
+ #define THREAD_HASWORK 1
52
+ #define THREAD_SUICIDE 2
53
+
54
+ /* Callback functions used below. */
55
+ static int callback_resolveone(void * cookie);
56
+ static int callback_resolve(void *, struct sock_addr **);
57
+
58
+ /* Address resolution thread. */
59
+ static void *
60
+ workthread(void * cookie)
61
+ {
62
+ struct dnsthread_internal * T = cookie;
63
+ char * addr;
64
+ struct sock_addr ** sas;
65
+ int res_errno = 0;
66
+ int rc;
67
+ uint8_t zero = 0;
68
+
69
+ /* Grab the mutex. */
70
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
71
+ warn0("pthread_mutex_lock: %s", strerror(rc));
72
+ exit(1);
73
+ }
74
+
75
+ /* Infinite loop doing work until told to suicide. */
76
+ do {
77
+ /*
78
+ * Sleep on the condition variable as long as we're in the
79
+ * SLEEPING state.
80
+ */
81
+ while (T->state == THREAD_SLEEPING) {
82
+ /* Sleep until we're woken up. */
83
+ if ((rc = pthread_cond_wait(&T->cv, &T->mtx)) != 0) {
84
+ warn0("pthread_cond_wait: %s", strerror(rc));
85
+ exit(1);
86
+ }
87
+ }
88
+
89
+ /* If we need to kill ourself, stop looping. */
90
+ if (T->state == THREAD_SUICIDE)
91
+ break;
92
+
93
+ /* Grab the work. */
94
+ addr = T->addr;
95
+
96
+ /* Release the mutex. */
97
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
98
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
99
+ exit(1);
100
+ }
101
+
102
+ /* Perform the address resolution. */
103
+ if ((sas = sock_resolve(addr)) == NULL)
104
+ res_errno = errno;
105
+
106
+ /* Grab the mutex again. */
107
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
108
+ warn0("pthread_mutex_lock: %s", strerror(rc));
109
+ exit(1);
110
+ }
111
+
112
+ /* Write the answer back. */
113
+ T->sas = sas;
114
+ T->res_errno = res_errno;
115
+
116
+ /* Send a completion message. */
117
+ if (noeintr_write(T->wakeupsock[0], &zero, 1) != 1) {
118
+ warnp("Error writing to wakeup socket");
119
+ exit(1);
120
+ }
121
+
122
+ /* Return to sleeping, unless we were instructed to die. */
123
+ if (T->state != THREAD_SUICIDE)
124
+ T->state = THREAD_SLEEPING;
125
+ } while (1);
126
+
127
+ /* Close the socket pair. */
128
+ close(T->wakeupsock[1]);
129
+ close(T->wakeupsock[0]);
130
+
131
+ /* Destroy the condition variable. */
132
+ if ((rc = pthread_cond_destroy(&T->cv)) != 0) {
133
+ warn0("pthread_cond_destroy: %s", strerror(rc));
134
+ exit(1);
135
+ }
136
+
137
+ /* Release the mutex. */
138
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
139
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
140
+ exit(1);
141
+ }
142
+
143
+ /* Destroy the mutex. */
144
+ if ((rc = pthread_mutex_destroy(&T->mtx)) != 0) {
145
+ warn0("pthread_mutex_destroy: %s", strerror(rc));
146
+ exit(1);
147
+ }
148
+
149
+ /* Free the control structure. */
150
+ free(T);
151
+
152
+ /* Successful thread termination. */
153
+ return (NULL);
154
+ }
155
+
156
+ /**
157
+ * dnsthread_spawn(void):
158
+ * Spawn a thread for performing address resolution. Return a token which can
159
+ * be passed to dnsthread_resolveone and dnsthread_kill.
160
+ */
161
+ DNSTHREAD
162
+ dnsthread_spawn(void)
163
+ {
164
+ struct dnsthread_internal * T;
165
+ int rc;
166
+
167
+ /* Allocate a thread management structure. */
168
+ if ((T = malloc(sizeof(struct dnsthread_internal))) == NULL)
169
+ goto err0;
170
+
171
+ /* Create and lock a mutex. */
172
+ if ((rc = pthread_mutex_init(&T->mtx, NULL)) != 0) {
173
+ warn0("pthread_mutex_init: %s", strerror(rc));
174
+ goto err1;
175
+ }
176
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
177
+ warn0("pthread_mutex_lock: %s", strerror(rc));
178
+ goto err2;
179
+ }
180
+
181
+ /* Create state-changed condition variable. */
182
+ if ((rc = pthread_cond_init(&T->cv, NULL)) != 0) {
183
+ warn0("pthread_cond_init: %s", strerror(rc));
184
+ goto err3;
185
+ }
186
+
187
+ /* Create wakeup socketpair. */
188
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, T->wakeupsock)) {
189
+ warnp("socketpair");
190
+ goto err4;
191
+ }
192
+
193
+ /* The thread starts out sleeping. */
194
+ T->state = THREAD_SLEEPING;
195
+
196
+ /* Create the thread. */
197
+ if ((rc = pthread_create(&T->thr, NULL, workthread, T)) != 0) {
198
+ warn0("pthread_create: %s", strerror(rc));
199
+ goto err5;
200
+ }
201
+
202
+ /* Unlock the mutex. */
203
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
204
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
205
+ goto err0;
206
+ }
207
+
208
+ /* Success! */
209
+ return (T);
210
+
211
+ err5:
212
+ close(T->wakeupsock[1]);
213
+ close(T->wakeupsock[0]);
214
+ err4:
215
+ pthread_cond_destroy(&T->cv);
216
+ err3:
217
+ pthread_mutex_unlock(&T->mtx);
218
+ err2:
219
+ pthread_mutex_destroy(&T->mtx);
220
+ err1:
221
+ free(T);
222
+ err0:
223
+ /* Failure! */
224
+ return (NULL);
225
+ }
226
+
227
+ /**
228
+ * dnsthread_resolveone(T, addr, callback, cookie):
229
+ * Using the thread for which ${T} was returned by dnsthread_spawn, resolve
230
+ * the address ${addr}, which must be in one of the forms accepted by the
231
+ * sock_resolve function. If ${T} is already resolving an address, do not
232
+ * resolve this address and instead return with errno == EALREADY. Upon
233
+ * completion, invoke ${callback}(${cookie}, sas), where ${sas} is a
234
+ * NULL-terminated array of pointers to sock_addr structures or NULL on
235
+ * resolution failure.
236
+ */
237
+ int
238
+ dnsthread_resolveone(DNSTHREAD T, const char * addr,
239
+ int (* callback)(void *, struct sock_addr **), void * cookie)
240
+ {
241
+ int err = 0;
242
+ int rc;
243
+
244
+ /* Grab the mutex. */
245
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
246
+ warn0("pthread_mutex_lock: %s", strerror(rc));
247
+ goto err0;
248
+ }
249
+
250
+ /* If the resolver is already busy, fail. */
251
+ if (T->state == THREAD_HASWORK) {
252
+ err = EALREADY;
253
+ goto ealready;
254
+ }
255
+
256
+ /* Duplicate the address to be resolved. */
257
+ if ((T->addr = strdup(addr)) == NULL)
258
+ goto err1;
259
+
260
+ /* Remember what callback we'll need to do eventually. */
261
+ T->callback = callback;
262
+ T->cookie = cookie;
263
+
264
+ /* There is now work for the thread to do. */
265
+ T->state = THREAD_HASWORK;
266
+
267
+ /* Wake up the worker thread. */
268
+ if ((rc = pthread_cond_signal(&T->cv)) != 0) {
269
+ warn0("pthread_cond_signal: %s", strerror(rc));
270
+ goto err1;
271
+ }
272
+
273
+ /* We want a callback when the worker thread pokes us. */
274
+ if (events_network_register(callback_resolveone, T, T->wakeupsock[1],
275
+ EVENTS_NETWORK_OP_READ)) {
276
+ warnp("Error registering wakeup listener");
277
+ goto err1;
278
+ }
279
+
280
+ ealready:
281
+ /* Release the mutex. */
282
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
283
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
284
+ goto err0;
285
+ }
286
+
287
+ /* If err was set earlier, store the value in errno. */
288
+ if (err)
289
+ errno = err;
290
+
291
+ /* Success! */
292
+ return (0);
293
+
294
+ err1:
295
+ pthread_mutex_unlock(&T->mtx);
296
+ err0:
297
+ /* Failure! */
298
+ return (-1);
299
+ }
300
+
301
+ /* Callback for dnsthread_resolveone, from wakeup socket. */
302
+ static int
303
+ callback_resolveone(void * cookie)
304
+ {
305
+ struct dnsthread_internal * T = cookie;
306
+ struct sock_addr ** sas;
307
+ uint8_t zero;
308
+ int res_errno = 0;
309
+ int (*callback)(void *, struct sock_addr **);
310
+ void * cb_cookie;
311
+ int rc;
312
+
313
+ /* Drain the byte from the socketpair. */
314
+ if (read(T->wakeupsock[1], &zero, 1) != 1) {
315
+ warn0("Error reading from wakeup socket");
316
+ goto err0;
317
+ }
318
+
319
+ /* Grab the mutex. */
320
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
321
+ warn0("pthread_mutex_lock: %s", strerror(rc));
322
+ goto err0;
323
+ }
324
+
325
+ /* Free the (strduped) address which was to be resolved. */
326
+ free(T->addr);
327
+
328
+ /* Grab the result. */
329
+ sas = T->sas;
330
+ res_errno = T->res_errno;
331
+
332
+ /* Grab the callback. */
333
+ callback = T->callback;
334
+ cb_cookie = T->cookie;
335
+
336
+ /* Release the mutex. */
337
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
338
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
339
+ goto err0;
340
+ }
341
+
342
+ /* Perform the callback. */
343
+ if (sas == NULL)
344
+ errno = res_errno;
345
+ return ((callback)(cb_cookie, sas));
346
+
347
+ err0:
348
+ /* Failure! */
349
+ return (-1);
350
+ }
351
+
352
+ /**
353
+ * dnsthread_kill(T):
354
+ * Instruct an address resolution thread to die. If the thread does not have
355
+ * an address resolution operation currently pending, wait for the thread to
356
+ * die before returning.
357
+ */
358
+ int
359
+ dnsthread_kill(DNSTHREAD T)
360
+ {
361
+ int rc;
362
+ int ostate;
363
+ pthread_t thr;
364
+
365
+ /* Lock the control structure. */
366
+ if ((rc = pthread_mutex_lock(&T->mtx)) != 0) {
367
+ warn0("pthread_mutex_lock: %s", strerror(rc));
368
+ goto err0;
369
+ }
370
+
371
+ /* Remember what state the thread is currently in. */
372
+ ostate = T->state;
373
+
374
+ /* Grab the thread ID. */
375
+ thr = T->thr;
376
+
377
+ /* Tell the thread to die, and wake it up. */
378
+ T->state = THREAD_SUICIDE;
379
+ if ((rc = pthread_cond_signal(&T->cv)) != 0) {
380
+ warn0("pthread_cond_signal: %s", strerror(rc));
381
+ goto err1;
382
+ }
383
+
384
+ /* Unlock the control structure. */
385
+ if ((rc = pthread_mutex_unlock(&T->mtx)) != 0) {
386
+ warn0("pthread_mutex_unlock: %s", strerror(rc));
387
+ goto err0;
388
+ }
389
+
390
+ /* If the thread was sleeping, wait for it to wake up and die. */
391
+ if (ostate == THREAD_SLEEPING) {
392
+ if ((rc = pthread_join(thr, NULL)) != 0) {
393
+ warn0("pthread_join: %s", strerror(rc));
394
+ goto err0;
395
+ }
396
+ }
397
+
398
+ /* Success! */
399
+ return (0);
400
+
401
+ err1:
402
+ pthread_mutex_unlock(&T->mtx);
403
+ err0:
404
+ /* Failure! */
405
+ return (-1);
406
+ }
407
+
408
+ /**
409
+ * dnsthread_resolve(addr, callback, cookie):
410
+ * Perform a non-blocking address resolution of ${addr}. This function may
411
+ * spawn a thread internally.
412
+ */
413
+ int
414
+ dnsthread_resolve(const char * addr,
415
+ int (* callback)(void *, struct sock_addr **), void * cookie)
416
+ {
417
+ struct resolve_cookie * R;
418
+
419
+ /* Bake a cookie. */
420
+ if ((R = malloc(sizeof(struct resolve_cookie))) == NULL)
421
+ goto err0;
422
+ R->callback = callback;
423
+ R->cookie = cookie;
424
+
425
+ /* Spawn a thread. */
426
+ if ((R->T = dnsthread_spawn()) == NULL)
427
+ goto err1;
428
+
429
+ /* Launch the request. */
430
+ if (dnsthread_resolveone(R->T, addr, callback_resolve, R))
431
+ goto err2;
432
+
433
+ /* Success! */
434
+ return (0);
435
+
436
+ err2:
437
+ dnsthread_kill(R->T);
438
+ err1:
439
+ free(R);
440
+ err0:
441
+ /* Failure! */
442
+ return (-1);
443
+ }
444
+
445
+ /* Callback for dnsthread_resolve, from dnsthread_resolveone. */
446
+ static int
447
+ callback_resolve(void * cookie, struct sock_addr ** sas)
448
+ {
449
+ struct resolve_cookie * R = cookie;
450
+ int rc;
451
+
452
+ /* Invoke the upstream callback. */
453
+ rc = (R->callback)(R->cookie, sas);
454
+
455
+ /* Kill the resolver thread. */
456
+ if (dnsthread_kill(R->T))
457
+ rc = -1;
458
+
459
+ /* Free our cookie. */
460
+ free(R);
461
+
462
+ /* Return upstream return code or failure. */
463
+ return (rc);
464
+ }