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.
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,106 @@
1
+ #ifndef _EVENTS_H_
2
+ #define _EVENTS_H_
3
+
4
+ #include <sys/select.h>
5
+
6
+ /**
7
+ * events_immediate_register(func, cookie, prio):
8
+ * Register ${func}(${cookie}) to be run the next time events_run is invoked,
9
+ * after immediate events with smaller ${prio} values and before events with
10
+ * larger ${prio} values. The value ${prio} must be in the range [0, 31].
11
+ * Return a cookie which can be passed to events_immediate_cancel.
12
+ */
13
+ void * events_immediate_register(int (*)(void *), void *, int);
14
+
15
+ /**
16
+ * events_immediate_cancel(cookie):
17
+ * Cancel the immediate event for which the cookie ${cookie} was returned by
18
+ * events_immediate_register.
19
+ */
20
+ void events_immediate_cancel(void *);
21
+
22
+ /* "op" parameter to events_network_register. */
23
+ #define EVENTS_NETWORK_OP_READ 0
24
+ #define EVENTS_NETWORK_OP_WRITE 1
25
+
26
+ /**
27
+ * events_network_register(func, cookie, s, op):
28
+ * Register ${func}(${cookie}) to be run when socket ${s} is ready for
29
+ * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or
30
+ * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for
31
+ * this ${s}/${op} pair, errno will be set to EEXIST and the function will
32
+ * fail.
33
+ */
34
+ int events_network_register(int (*)(void *), void *, int, int);
35
+
36
+ /**
37
+ * events_network_cancel(s, op):
38
+ * Cancel the event registered for the socket/operation pair ${s}/${op}. If
39
+ * there is no such registration, errno will be set to ENOENT and the
40
+ * function will fail.
41
+ */
42
+ int events_network_cancel(int, int);
43
+
44
+ /**
45
+ * events_network_selectstats(N, mu, va, max):
46
+ * Return statistics on the inter-select durations since the last time this
47
+ * function was called.
48
+ */
49
+ void events_network_selectstats(double *, double *, double *, double *);
50
+
51
+ /**
52
+ * events_timer_register(func, cookie, timeo):
53
+ * Register ${func}(${cookie}) to be run ${timeo} in the future. Return a
54
+ * cookie which can be passed to events_timer_cancel or events_timer_reset.
55
+ */
56
+ void * events_timer_register(int (*)(void *), void *, const struct timeval *);
57
+
58
+ /**
59
+ * events_timer_register_double(func, cookie, timeo):
60
+ * As events_timer_register, but ${timeo} is a double-precision floating point
61
+ * value specifying a number of seconds.
62
+ */
63
+ void * events_timer_register_double(int (*)(void *), void *, double);
64
+
65
+ /**
66
+ * events_timer_cancel(cookie):
67
+ * Cancel the timer for which the cookie ${cookie} was returned by
68
+ * events_timer_register.
69
+ */
70
+ void events_timer_cancel(void *);
71
+
72
+ /**
73
+ * events_timer_reset(cookie):
74
+ * Reset the timer for which the cookie ${cookie} was returned by
75
+ * events_timer_register to its initial value.
76
+ */
77
+ int events_timer_reset(void *);
78
+
79
+ /**
80
+ * events_run(void):
81
+ * Run events. Events registered via events_immediate_register will be run
82
+ * first, in order of increasing ${prio} values; then events associated with
83
+ * ready sockets registered via events_network_register; finally, events
84
+ * associated with expired timers registered via events_timer_register will
85
+ * be run. If any event function returns a non-zero result, no further
86
+ * events will be run and said non-zero result will be returned; on error,
87
+ * -1 will be returned.
88
+ */
89
+ int events_run(void);
90
+
91
+ /**
92
+ * events_spin(done):
93
+ * Run events until ${done} is non-zero (and return 0), an error occurs (and
94
+ * return -1), or a callback returns a non-zero status (and return the status
95
+ * code from the callback).
96
+ */
97
+ int events_spin(int *);
98
+
99
+ /**
100
+ * events_shutdown(void):
101
+ * Clean up and free memory. This call is not necessary on program exit and
102
+ * is only expected to be useful when checking for memory leaks.
103
+ */
104
+ void events_shutdown(void);
105
+
106
+ #endif /* !_EVENTS_H_ */
@@ -0,0 +1,149 @@
1
+ #include <assert.h>
2
+ #include <stdint.h>
3
+ #include <stdlib.h>
4
+
5
+ #include "mpool.h"
6
+
7
+ #include "events_internal.h"
8
+ #include "events.h"
9
+
10
+ struct eventq {
11
+ struct eventrec * r;
12
+ struct eventq * next;
13
+ struct eventq * prev;
14
+ int prio;
15
+ };
16
+
17
+ MPOOL(eventq, struct eventq, 4096);
18
+
19
+ /* First nodes in the linked lists. */
20
+ static struct eventq * heads[32] = {
21
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
22
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
23
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
24
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
25
+ };
26
+
27
+ /* For non-NULL heads[i], tails[i] is the last node in the list. */
28
+ static struct eventq * tails[32];
29
+
30
+ /* For i < minq, heads[i] == NULL. */
31
+ static int minq = 32;
32
+
33
+ /**
34
+ * events_immediate_register(func, cookie, prio):
35
+ * Register ${func}(${cookie}) to be run the next time events_run is invoked,
36
+ * after immediate events with smaller ${prio} values and before events with
37
+ * larger ${prio} values. The value ${prio} must be in the range [0, 31].
38
+ * Return a cookie which can be passed to events_immediate_cancel.
39
+ */
40
+ void *
41
+ events_immediate_register(int (*func)(void *), void * cookie, int prio)
42
+ {
43
+ struct eventrec * r;
44
+ struct eventq * q;
45
+
46
+ /* Sanity check. */
47
+ assert((prio >= 0) && (prio < 32));
48
+
49
+ /* Bundle into an eventrec record. */
50
+ if ((r = events_mkrec(func, cookie)) == NULL)
51
+ goto err0;
52
+
53
+ /* Create a linked list node. */
54
+ if ((q = mpool_eventq_malloc()) == NULL)
55
+ goto err1;
56
+ q->r = r;
57
+ q->next = NULL;
58
+ q->prev = NULL;
59
+ q->prio = prio;
60
+
61
+ /* Add to the queue. */
62
+ if (heads[prio] == NULL) {
63
+ heads[prio] = q;
64
+ if (prio < minq)
65
+ minq = prio;
66
+ } else {
67
+ tails[prio]->next = q;
68
+ q->prev = tails[prio];
69
+ }
70
+ tails[prio] = q;
71
+
72
+ /* Success! */
73
+ return (q);
74
+
75
+ err1:
76
+ events_freerec(r);
77
+ err0:
78
+ /* Failure! */
79
+ return (NULL);
80
+ }
81
+
82
+ /**
83
+ * events_immediate_cancel(cookie):
84
+ * Cancel the immediate event for which the cookie ${cookie} was returned by
85
+ * events_immediate_register.
86
+ */
87
+ void
88
+ events_immediate_cancel(void * cookie)
89
+ {
90
+ struct eventq * q = cookie;
91
+ int prio = q->prio;
92
+
93
+ /* If we have a predecessor, point it at our successor. */
94
+ if (q->prev != NULL)
95
+ q->prev->next = q->next;
96
+ else
97
+ heads[prio] = q->next;
98
+
99
+ /* If we have a successor, point it at our predecessor. */
100
+ if (q->next != NULL)
101
+ q->next->prev = q->prev;
102
+ else
103
+ tails[prio] = q->prev;
104
+
105
+ /* Free the eventrec. */
106
+ events_freerec(q->r);
107
+
108
+ /* Return the node to the malloc pool. */
109
+ mpool_eventq_free(q);
110
+ }
111
+
112
+ /**
113
+ * events_immediate_get(void):
114
+ * Remove and return an eventrec structure from the immediate event queue,
115
+ * or return NULL if there are no such events. The caller is responsible for
116
+ * freeing the returned memory.
117
+ */
118
+ struct eventrec *
119
+ events_immediate_get(void)
120
+ {
121
+ struct eventq * q;
122
+ struct eventrec * r;
123
+
124
+ /* Advance past priorities which have no events. */
125
+ while ((minq < 32) && (heads[minq] == NULL))
126
+ minq++;
127
+
128
+ /* Are there any events? */
129
+ if (minq == 32)
130
+ return (NULL);
131
+
132
+ /*
133
+ * Remove the first node from the highest priority non-empty linked
134
+ * list.
135
+ */
136
+ q = heads[minq];
137
+ heads[minq] = q->next;
138
+ if (heads[minq] != NULL)
139
+ heads[minq]->prev = NULL;
140
+
141
+ /* Extract the eventrec. */
142
+ r = q->r;
143
+
144
+ /* Return the node to the malloc pool. */
145
+ mpool_eventq_free(q);
146
+
147
+ /* Return the eventrec. */
148
+ return (r);
149
+ }
@@ -0,0 +1,95 @@
1
+ #ifndef _EVENTS_INTERNAL_H_
2
+ #define _EVENTS_INTERNAL_H_
3
+
4
+ #include <sys/time.h>
5
+
6
+ /* Opaque event structure. */
7
+ struct eventrec;
8
+
9
+ /**
10
+ * events_mkrec(func, cookie):
11
+ * Package ${func}, ${cookie} into a struct eventrec.
12
+ */
13
+ struct eventrec * events_mkrec(int (*)(void *), void *);
14
+
15
+ /**
16
+ * events_freerec(r):
17
+ * Free the eventrec ${r}.
18
+ */
19
+ void events_freerec(struct eventrec *);
20
+
21
+ /**
22
+ * events_immediate_get(void):
23
+ * Remove and return an eventrec structure from the immediate event queue,
24
+ * or return NULL if there are no such events. The caller is responsible for
25
+ * freeing the returned memory.
26
+ */
27
+ struct eventrec * events_immediate_get(void);
28
+
29
+ /**
30
+ * events_network_select(tv):
31
+ * Check for socket readiness events, waiting up to ${tv} time if there are
32
+ * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value
33
+ * stored in ${tv} may be modified.
34
+ */
35
+ int events_network_select(struct timeval *);
36
+
37
+ /**
38
+ * events_network_selectstats_startclock(void):
39
+ * Start the inter-select duration clock: There is a selectable event.
40
+ */
41
+ void events_network_selectstats_startclock(void);
42
+
43
+ /**
44
+ * events_network_selectstats_stopclock(void):
45
+ * Stop the inter-select duration clock: There are no selectable events.
46
+ */
47
+ void events_network_selectstats_stopclock(void);
48
+
49
+ /**
50
+ * events_network_selectstats_select(void):
51
+ * Update inter-select duration statistics in relation to an upcoming
52
+ * select(2) call.
53
+ */
54
+ void events_network_selectstats_select(void);
55
+
56
+ /**
57
+ * events_network_get(void):
58
+ * Find a socket readiness event which was identified by a previous call to
59
+ * events_network_select, and return it as an eventrec structure; or return
60
+ * NULL if there are no such events available. The caller is responsible for
61
+ * freeing the returned memory.
62
+ */
63
+ struct eventrec * events_network_get(void);
64
+
65
+ /**
66
+ * events_network_shutdown(void)
67
+ * Clean up and free memory. This call is not necessary on program exit and
68
+ * is only expected to be useful when checking for memory leaks.
69
+ */
70
+ void events_network_shutdown(void);
71
+
72
+ /**
73
+ * events_timer_min(timeo):
74
+ * Return via ${timeo} a pointer to the minimum time which must be waited
75
+ * before a timer will expire; or to NULL if there are no timers. The caller
76
+ * is responsible for freeing the returned pointer.
77
+ */
78
+ int events_timer_min(struct timeval **);
79
+
80
+ /**
81
+ * events_timer_get(r):
82
+ * Return via ${r} a pointer to an eventrec structure corresponding to an
83
+ * expired timer, and delete said timer; or to NULL if there are no expired
84
+ * timers. The caller is responsible for freeing the returned pointer.
85
+ */
86
+ int events_timer_get(struct eventrec **);
87
+
88
+ /**
89
+ * events_timer_shutdown(void):
90
+ * Clean up and free memory. This call is not necessary on program exit and
91
+ * is only expected to be useful when checking for memory leaks.
92
+ */
93
+ void events_timer_shutdown(void);
94
+
95
+ #endif /* !_EVENTS_INTERNAL_H_ */
@@ -0,0 +1,347 @@
1
+ #include <sys/select.h>
2
+
3
+ #include <errno.h>
4
+ #include <stdlib.h>
5
+
6
+ #include "elasticarray.h"
7
+ #include "warnp.h"
8
+
9
+ #include "events_internal.h"
10
+ #include "events.h"
11
+
12
+ /* Structure for holding readability and writability events for a socket. */
13
+ struct socketrec {
14
+ struct eventrec * reader;
15
+ struct eventrec * writer;
16
+ };
17
+
18
+ /* List of sockets. */
19
+ ELASTICARRAY_DECL(SOCKETLIST, socketlist, struct socketrec);
20
+ static SOCKETLIST S = NULL;
21
+
22
+ /* File descriptor sets containing unevented ready sockets. */
23
+ static fd_set readfds;
24
+ static fd_set writefds;
25
+
26
+ /* Position to which events_network_get has scanned in *fds. */
27
+ static size_t fdscanpos;
28
+
29
+ /* Number of registered events. */
30
+ static size_t nev;
31
+
32
+ /* Initialize the socket list if we haven't already done so. */
33
+ static int
34
+ initsocketlist(void)
35
+ {
36
+
37
+ /* If we're already initialized, do nothing. */
38
+ if (S != NULL)
39
+ goto done;
40
+
41
+ /* Initialize the socket list. */
42
+ if ((S = socketlist_init(0)) == NULL)
43
+ goto err0;
44
+
45
+ /* There are no events registered. */
46
+ nev = 0;
47
+
48
+ /* There are no unevented ready sockets. */
49
+ fdscanpos = FD_SETSIZE;
50
+
51
+ done:
52
+ /* Success! */
53
+ return (0);
54
+
55
+ err0:
56
+ /* Failure! */
57
+ return (-1);
58
+ }
59
+
60
+ /* Grow the socket list and initialize new records. */
61
+ static int
62
+ growsocketlist(size_t nrec)
63
+ {
64
+ size_t i;
65
+
66
+ /* Get the old size. */
67
+ i = socketlist_getsize(S);
68
+
69
+ /* Grow the list. */
70
+ if (socketlist_resize(S, nrec))
71
+ goto err0;
72
+
73
+ /* Initialize new members. */
74
+ for (; i < nrec; i++) {
75
+ socketlist_get(S, i)->reader = NULL;
76
+ socketlist_get(S, i)->writer = NULL;
77
+ }
78
+
79
+ /* Success! */
80
+ return (0);
81
+
82
+ err0:
83
+ /* Failure! */
84
+ return (-1);
85
+ }
86
+
87
+ /**
88
+ * events_network_register(func, cookie, s, op):
89
+ * Register ${func}(${cookie}) to be run when socket ${s} is ready for
90
+ * reading or writing depending on whether ${op} is EVENTS_NETWORK_OP_READ or
91
+ * EVENTS_NETWORK_OP_WRITE. If there is already an event registration for
92
+ * this ${s}/${op} pair, errno will be set to EEXIST and the function will
93
+ * fail.
94
+ */
95
+ int
96
+ events_network_register(int (*func)(void *), void * cookie, int s, int op)
97
+ {
98
+ struct eventrec ** r;
99
+
100
+ /* Initialize if necessary. */
101
+ if (initsocketlist())
102
+ goto err0;
103
+
104
+ /* Sanity-check socket number. */
105
+ if ((s < 0) || (s >= (int)FD_SETSIZE)) {
106
+ warn0("Invalid file descriptor for network event: %d", s);
107
+ goto err0;
108
+ }
109
+
110
+ /* Sanity-check operation. */
111
+ if ((op != EVENTS_NETWORK_OP_READ) &&
112
+ (op != EVENTS_NETWORK_OP_WRITE)) {
113
+ warn0("Invalid operation for network event: %d", op);
114
+ goto err0;
115
+ }
116
+
117
+ /* Grow the array if necessary. */
118
+ if (((size_t)(s) >= socketlist_getsize(S)) &&
119
+ (growsocketlist(s + 1) != 0))
120
+ goto err0;
121
+
122
+ /* Look up the relevant event pointer. */
123
+ if (op == EVENTS_NETWORK_OP_READ)
124
+ r = &socketlist_get(S, s)->reader;
125
+ else
126
+ r = &socketlist_get(S, s)->writer;
127
+
128
+ /* Error out if we already have an event registered. */
129
+ if (*r != NULL) {
130
+ errno = EEXIST;
131
+ goto err0;
132
+ }
133
+
134
+ /* Register the new event. */
135
+ if ((*r = events_mkrec(func, cookie)) == NULL)
136
+ goto err0;
137
+
138
+ /*
139
+ * Increment events-registered counter; and if it was zero, start the
140
+ * inter-select duration clock.
141
+ */
142
+ if (nev++ == 0)
143
+ events_network_selectstats_startclock();
144
+
145
+ /* Success! */
146
+ return (0);
147
+
148
+ err0:
149
+ /* Failure! */
150
+ return (-1);
151
+ }
152
+
153
+ /**
154
+ * events_network_cancel(s, op):
155
+ * Cancel the event registered for the socket/operation pair ${s}/${op}. If
156
+ * there is no such registration, errno will be set to ENOENT and the
157
+ * function will fail.
158
+ */
159
+ int
160
+ events_network_cancel(int s, int op)
161
+ {
162
+ struct eventrec ** r;
163
+
164
+ /* Initialize if necessary. */
165
+ if (initsocketlist())
166
+ goto err0;
167
+
168
+ /* Sanity-check socket number. */
169
+ if ((s < 0) || (s >= (int)FD_SETSIZE)) {
170
+ warn0("Invalid file descriptor for network event: %d", s);
171
+ goto err0;
172
+ }
173
+
174
+ /* Sanity-check operation. */
175
+ if ((op != EVENTS_NETWORK_OP_READ) &&
176
+ (op != EVENTS_NETWORK_OP_WRITE)) {
177
+ warn0("Invalid operation for network event: %d", op);
178
+ goto err0;
179
+ }
180
+
181
+ /* We have no events registered beyond the end of the array. */
182
+ if ((size_t)(s) >= socketlist_getsize(S)) {
183
+ errno = ENOENT;
184
+ goto err0;
185
+ }
186
+
187
+ /* Look up the relevant event pointer. */
188
+ if (op == EVENTS_NETWORK_OP_READ)
189
+ r = &socketlist_get(S, s)->reader;
190
+ else
191
+ r = &socketlist_get(S, s)->writer;
192
+
193
+ /* Check if we have an event. */
194
+ if (*r == NULL) {
195
+ errno = ENOENT;
196
+ goto err0;
197
+ }
198
+
199
+ /* Free the event. */
200
+ events_freerec(*r);
201
+ *r = NULL;
202
+
203
+ /*
204
+ * Since there is no longer an event registered for this socket /
205
+ * operation pair, it doesn't make any sense for it to be ready.
206
+ */
207
+ if (op == EVENTS_NETWORK_OP_READ)
208
+ FD_CLR(s, &readfds);
209
+ else
210
+ FD_CLR(s, &writefds);
211
+
212
+ /*
213
+ * Decrement events-registered counter; and if it is becoming zero,
214
+ * stop the inter-select duration clock.
215
+ */
216
+ if (--nev == 0)
217
+ events_network_selectstats_stopclock();
218
+
219
+ /* Success! */
220
+ return (0);
221
+
222
+ err0:
223
+ /* Failure! */
224
+ return (-1);
225
+ }
226
+
227
+ /**
228
+ * events_network_select(tv):
229
+ * Check for socket readiness events, waiting up to ${tv} time if there are
230
+ * no sockets immediately ready, or indefinitely if ${tv} is NULL. The value
231
+ * stored in ${tv} may be modified.
232
+ */
233
+ int
234
+ events_network_select(struct timeval * tv)
235
+ {
236
+ size_t i;
237
+
238
+ /* Initialize if necessary. */
239
+ if (initsocketlist())
240
+ goto err0;
241
+
242
+ /* Zero the fd sets... */
243
+ FD_ZERO(&readfds);
244
+ FD_ZERO(&writefds);
245
+
246
+ /* ... and add the ones we care about. */
247
+ for (i = 0; i < socketlist_getsize(S); i++) {
248
+ if (socketlist_get(S, i)->reader)
249
+ FD_SET(i, &readfds);
250
+ if (socketlist_get(S, i)->writer)
251
+ FD_SET(i, &writefds);
252
+ }
253
+
254
+ /* We're about to call select! */
255
+ events_network_selectstats_select();
256
+
257
+ /* Select. */
258
+ while (select(socketlist_getsize(S), &readfds, &writefds,
259
+ NULL, tv) == -1) {
260
+ /* EINTR is harmless. */
261
+ if (errno == EINTR)
262
+ continue;
263
+
264
+ /* Anything else is an error. */
265
+ warnp("select()");
266
+ goto err0;
267
+ }
268
+
269
+ /* If we have any events registered, start the clock again. */
270
+ if (nev > 0)
271
+ events_network_selectstats_startclock();
272
+
273
+ /* We should start scanning for events at the beginning. */
274
+ fdscanpos = 0;
275
+
276
+ /* Success! */
277
+ return (0);
278
+
279
+ err0:
280
+ /* Failure! */
281
+ return (-1);
282
+ }
283
+
284
+ /**
285
+ * events_network_get(void):
286
+ * Find a socket readiness event which was identified by a previous call to
287
+ * events_network_select, and return it as an eventrec structure; or return
288
+ * NULL if there are no such events available. The caller is responsible for
289
+ * freeing the returned memory.
290
+ */
291
+ struct eventrec *
292
+ events_network_get(void)
293
+ {
294
+ struct eventrec * r;
295
+ size_t nfds = socketlist_getsize(S);
296
+
297
+ /* We haven't found any events yet. */
298
+ r = NULL;
299
+
300
+ /* Scan through the fd sets looking for ready sockets. */
301
+ for (; fdscanpos < nfds; fdscanpos++) {
302
+ /* Are we ready for reading? */
303
+ if (FD_ISSET(fdscanpos, &readfds)) {
304
+ r = socketlist_get(S, fdscanpos)->reader;
305
+ socketlist_get(S, fdscanpos)->reader = NULL;
306
+ if (--nev == 0)
307
+ events_network_selectstats_stopclock();
308
+ FD_CLR(fdscanpos, &readfds);
309
+ break;
310
+ }
311
+
312
+ /* Are we ready for writing? */
313
+ if (FD_ISSET(fdscanpos, &writefds)) {
314
+ r = socketlist_get(S, fdscanpos)->writer;
315
+ socketlist_get(S, fdscanpos)->writer = NULL;
316
+ if (--nev == 0)
317
+ events_network_selectstats_stopclock();
318
+ FD_CLR(fdscanpos, &writefds);
319
+ break;
320
+ }
321
+ }
322
+
323
+ /* Return the event we found, or NULL if we didn't find any. */
324
+ return (r);
325
+ }
326
+
327
+ /**
328
+ * events_network_shutdown(void)
329
+ * Clean up and free memory. This call is not necessary on program exit and
330
+ * is only expected to be useful when checking for memory leaks.
331
+ */
332
+ void
333
+ events_network_shutdown(void)
334
+ {
335
+
336
+ /* If we're not initialized, do nothing. */
337
+ if (S == NULL)
338
+ return;
339
+
340
+ /* If we have any registered events, do nothing. */
341
+ if (nev > 0)
342
+ return;
343
+
344
+ /* Free the socket list. */
345
+ socketlist_free(S);
346
+ S = NULL;
347
+ }