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,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
+ }