kgio 1.1.0 → 1.2.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.
@@ -0,0 +1,40 @@
1
+ #ifndef KGIO_H
2
+ #define KGIO_H
3
+
4
+ #include <ruby.h>
5
+ #ifdef HAVE_RUBY_IO_H
6
+ # include <ruby/io.h>
7
+ #else
8
+ # include <rubyio.h>
9
+ #endif
10
+ #include <errno.h>
11
+ #include <sys/types.h>
12
+ #include <sys/socket.h>
13
+ #include <sys/un.h>
14
+ #include <netinet/in.h>
15
+ #include <fcntl.h>
16
+ #include <unistd.h>
17
+ #include <arpa/inet.h>
18
+ #include <assert.h>
19
+
20
+ #include "missing/ancient_ruby.h"
21
+ #include "nonblock.h"
22
+ #include "my_fileno.h"
23
+
24
+ struct io_args {
25
+ VALUE io;
26
+ VALUE buf;
27
+ char *ptr;
28
+ long len;
29
+ int fd;
30
+ };
31
+
32
+ void init_kgio_wait(VALUE mKgio);
33
+ void init_kgio_read_write(VALUE mKgio);
34
+ void init_kgio_accept(VALUE mKgio);
35
+ void init_kgio_connect(VALUE mKgio);
36
+
37
+ void kgio_wait_writable(VALUE io, int fd);
38
+ void kgio_wait_readable(VALUE io, int fd);
39
+
40
+ #endif /* KGIO_H */
@@ -1,1095 +1,11 @@
1
- #include <ruby.h>
2
- #ifdef HAVE_RUBY_IO_H
3
- # include <ruby/io.h>
4
- #else
5
- # include <rubyio.h>
6
- #endif
7
- #include <errno.h>
8
- #include <sys/types.h>
9
- #include <sys/socket.h>
10
- #include <sys/un.h>
11
- #include <netinet/in.h>
12
- #include <fcntl.h>
13
- #include <unistd.h>
14
- #include <arpa/inet.h>
15
- #include <assert.h>
16
-
17
- #include "missing/accept4.h"
18
- #include "missing/ancient_ruby.h"
19
- #include "nonblock.h"
20
- #include "my_fileno.h"
21
- #include "sock_for_fd.h"
22
-
23
- #if defined(__linux__)
24
- /*
25
- * we know MSG_DONTWAIT works properly on all stream sockets under Linux
26
- * we can define this macro for other platforms as people care and
27
- * notice.
28
- */
29
- # define USE_MSG_DONTWAIT
30
- static int accept4_flags = A4_SOCK_CLOEXEC;
31
- #else /* ! linux */
32
- static int accept4_flags = A4_SOCK_CLOEXEC | A4_SOCK_NONBLOCK;
33
- #endif /* ! linux */
34
-
35
- static VALUE cClientSocket;
36
- static VALUE mSocketMethods;
37
- static VALUE cSocket;
38
- static VALUE localhost;
39
- static VALUE mKgio_WaitReadable, mKgio_WaitWritable;
40
- static ID io_wait_rd, io_wait_wr;
41
- static ID iv_kgio_addr;
42
-
43
- struct io_args {
44
- VALUE io;
45
- VALUE buf;
46
- char *ptr;
47
- long len;
48
- int fd;
49
- };
50
-
51
- struct accept_args {
52
- int fd;
53
- struct sockaddr *addr;
54
- socklen_t *addrlen;
55
- };
56
-
57
- static void wait_readable(VALUE io, int fd)
58
- {
59
- if (io_wait_rd) {
60
- (void)rb_funcall(io, io_wait_rd, 0, 0);
61
- } else {
62
- if (!rb_io_wait_readable(fd))
63
- rb_sys_fail("wait readable");
64
- }
65
- }
66
-
67
- static void wait_writable(VALUE io, int fd)
68
- {
69
- if (io_wait_wr) {
70
- (void)rb_funcall(io, io_wait_wr, 0, 0);
71
- } else {
72
- if (!rb_io_wait_writable(fd))
73
- rb_sys_fail("wait writable");
74
- }
75
- }
76
-
77
- static void prepare_read(struct io_args *a, int argc, VALUE *argv, VALUE io)
78
- {
79
- VALUE length;
80
-
81
- a->io = io;
82
- a->fd = my_fileno(io);
83
- rb_scan_args(argc, argv, "11", &length, &a->buf);
84
- a->len = NUM2LONG(length);
85
- if (NIL_P(a->buf)) {
86
- a->buf = rb_str_new(NULL, a->len);
87
- } else {
88
- StringValue(a->buf);
89
- rb_str_resize(a->buf, a->len);
90
- }
91
- a->ptr = RSTRING_PTR(a->buf);
92
- }
93
-
94
- static int read_check(struct io_args *a, long n, const char *msg, int io_wait)
95
- {
96
- if (n == -1) {
97
- if (errno == EINTR)
98
- return -1;
99
- rb_str_set_len(a->buf, 0);
100
- if (errno == EAGAIN) {
101
- if (io_wait) {
102
- wait_readable(a->io, a->fd);
103
-
104
- /* buf may be modified in other thread/fiber */
105
- rb_str_resize(a->buf, a->len);
106
- a->ptr = RSTRING_PTR(a->buf);
107
- return -1;
108
- } else {
109
- a->buf = mKgio_WaitReadable;
110
- return 0;
111
- }
112
- }
113
- rb_sys_fail(msg);
114
- }
115
- rb_str_set_len(a->buf, n);
116
- if (n == 0)
117
- a->buf = Qnil;
118
- return 0;
119
- }
120
-
121
- static VALUE my_read(int io_wait, int argc, VALUE *argv, VALUE io)
122
- {
123
- struct io_args a;
124
- long n;
125
-
126
- prepare_read(&a, argc, argv, io);
127
- set_nonblocking(a.fd);
128
- retry:
129
- n = (long)read(a.fd, a.ptr, a.len);
130
- if (read_check(&a, n, "read", io_wait) != 0)
131
- goto retry;
132
- return a.buf;
133
- }
134
-
135
- /*
136
- * call-seq:
137
- *
138
- * io.kgio_read(maxlen) -> buffer
139
- * io.kgio_read(maxlen, buffer) -> buffer
140
- *
141
- * Reads at most maxlen bytes from the stream socket. Returns with a
142
- * newly allocated buffer, or may reuse an existing buffer if supplied.
143
- *
144
- * Calls the method assigned to Kgio.wait_readable, or blocks in a
145
- * thread-safe manner for writability.
146
- *
147
- * Returns nil on EOF.
148
- *
149
- * This behaves like read(2) and IO#readpartial, NOT fread(3) or
150
- * IO#read which possess read-in-full behavior.
151
- */
152
- static VALUE kgio_read(int argc, VALUE *argv, VALUE io)
153
- {
154
- return my_read(1, argc, argv, io);
155
- }
156
-
157
- /*
158
- * call-seq:
159
- *
160
- * io.kgio_tryread(maxlen) -> buffer
161
- * io.kgio_tryread(maxlen, buffer) -> buffer
162
- *
163
- * Reads at most maxlen bytes from the stream socket. Returns with a
164
- * newly allocated buffer, or may reuse an existing buffer if supplied.
165
- *
166
- * Returns nil on EOF.
167
- *
168
- * Returns Kgio::WaitReadable if EAGAIN is encountered.
169
- */
170
- static VALUE kgio_tryread(int argc, VALUE *argv, VALUE io)
171
- {
172
- return my_read(0, argc, argv, io);
173
- }
174
-
175
- #ifdef USE_MSG_DONTWAIT
176
- static VALUE my_recv(int io_wait, int argc, VALUE *argv, VALUE io)
177
- {
178
- struct io_args a;
179
- long n;
180
-
181
- prepare_read(&a, argc, argv, io);
182
- retry:
183
- n = (long)recv(a.fd, a.ptr, a.len, MSG_DONTWAIT);
184
- if (read_check(&a, n, "recv", io_wait) != 0)
185
- goto retry;
186
- return a.buf;
187
- }
188
-
189
- /*
190
- * This method may be optimized on some systems (e.g. GNU/Linux) to use
191
- * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
192
- * Otherwise this is the same as Kgio::PipeMethods#kgio_read
193
- */
194
- static VALUE kgio_recv(int argc, VALUE *argv, VALUE io)
195
- {
196
- return my_recv(1, argc, argv, io);
197
- }
198
-
199
- /*
200
- * This method may be optimized on some systems (e.g. GNU/Linux) to use
201
- * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
202
- * Otherwise this is the same as Kgio::PipeMethods#kgio_tryread
203
- */
204
- static VALUE kgio_tryrecv(int argc, VALUE *argv, VALUE io)
205
- {
206
- return my_recv(0, argc, argv, io);
207
- }
208
- #else /* ! USE_MSG_DONTWAIT */
209
- # define kgio_recv kgio_read
210
- # define kgio_tryrecv kgio_tryread
211
- #endif /* USE_MSG_DONTWAIT */
212
-
213
- static void prepare_write(struct io_args *a, VALUE io, VALUE str)
214
- {
215
- a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
216
- a->ptr = RSTRING_PTR(a->buf);
217
- a->len = RSTRING_LEN(a->buf);
218
- a->io = io;
219
- a->fd = my_fileno(io);
220
- }
221
-
222
- static int write_check(struct io_args *a, long n, const char *msg, int io_wait)
223
- {
224
- if (a->len == n) {
225
- done:
226
- a->buf = Qnil;
227
- } else if (n == -1) {
228
- if (errno == EINTR)
229
- return -1;
230
- if (errno == EAGAIN) {
231
- if (io_wait) {
232
- long written = RSTRING_LEN(a->buf) - a->len;
233
-
234
- wait_writable(a->io, a->fd);
235
-
236
- /* buf may be modified in other thread/fiber */
237
- a->len = RSTRING_LEN(a->buf) - written;
238
- if (a->len <= 0)
239
- goto done;
240
- a->ptr = RSTRING_PTR(a->buf) + written;
241
- return -1;
242
- } else {
243
- a->buf = mKgio_WaitWritable;
244
- return 0;
245
- }
246
- }
247
- rb_sys_fail(msg);
248
- } else {
249
- assert(n >= 0 && n < a->len && "write/send syscall broken?");
250
- if (io_wait) {
251
- a->ptr += n;
252
- a->len -= n;
253
- return -1;
254
- }
255
- a->buf = rb_str_new(a->ptr + n, a->len - n);
256
- }
257
- return 0;
258
- }
259
-
260
- static VALUE my_write(VALUE io, VALUE str, int io_wait)
261
- {
262
- struct io_args a;
263
- long n;
264
-
265
- prepare_write(&a, io, str);
266
- set_nonblocking(a.fd);
267
- retry:
268
- n = (long)write(a.fd, a.ptr, a.len);
269
- if (write_check(&a, n, "write", io_wait) != 0)
270
- goto retry;
271
- return a.buf;
272
- }
273
-
274
- /*
275
- * call-seq:
276
- *
277
- * io.kgio_write(str) -> nil
278
- *
279
- * Returns nil when the write completes.
280
- *
281
- * Calls the method Kgio.wait_writable if it is set. Otherwise this
282
- * blocks in a thread-safe manner until all data is written or a
283
- * fatal error occurs.
284
- */
285
- static VALUE kgio_write(VALUE io, VALUE str)
286
- {
287
- return my_write(io, str, 1);
288
- }
289
-
290
- /*
291
- * call-seq:
292
- *
293
- * io.kgio_trywrite(str) -> nil or Kgio::WaitWritable
294
- *
295
- * Returns nil if the write was completed in full.
296
- *
297
- * Returns a String containing the unwritten portion if there was a
298
- * partial write.
299
- *
300
- * Returns Kgio::WaitWritable if EAGAIN is encountered.
301
- */
302
- static VALUE kgio_trywrite(VALUE io, VALUE str)
303
- {
304
- return my_write(io, str, 0);
305
- }
306
-
307
- #ifdef USE_MSG_DONTWAIT
308
- /*
309
- * This method behaves like Kgio::PipeMethods#kgio_write, except
310
- * it will use send(2) with the MSG_DONTWAIT flag on sockets to
311
- * avoid unnecessary calls to fcntl(2).
312
- */
313
- static VALUE my_send(VALUE io, VALUE str, int io_wait)
314
- {
315
- struct io_args a;
316
- long n;
317
-
318
- prepare_write(&a, io, str);
319
- retry:
320
- n = (long)send(a.fd, a.ptr, a.len, MSG_DONTWAIT);
321
- if (write_check(&a, n, "send", io_wait) != 0)
322
- goto retry;
323
- return a.buf;
324
- }
325
-
326
- /*
327
- * This method may be optimized on some systems (e.g. GNU/Linux) to use
328
- * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
329
- * Otherwise this is the same as Kgio::PipeMethods#kgio_write
330
- */
331
- static VALUE kgio_send(VALUE io, VALUE str)
332
- {
333
- return my_send(io, str, 1);
334
- }
335
-
336
- /*
337
- * This method may be optimized on some systems (e.g. GNU/Linux) to use
338
- * MSG_DONTWAIT to avoid explicitly setting the O_NONBLOCK flag via fcntl.
339
- * Otherwise this is the same as Kgio::PipeMethods#kgio_trywrite
340
- */
341
- static VALUE kgio_trysend(VALUE io, VALUE str)
342
- {
343
- return my_send(io, str, 0);
344
- }
345
- #else /* ! USE_MSG_DONTWAIT */
346
- # define kgio_send kgio_write
347
- # define kgio_trysend kgio_trywrite
348
- #endif /* ! USE_MSG_DONTWAIT */
349
-
350
- /*
351
- * call-seq:
352
- *
353
- * Kgio.wait_readable = :method_name
354
- * Kgio.wait_readable = nil
355
- *
356
- * Sets a method for kgio_read to call when a read would block.
357
- * This is useful for non-blocking frameworks that use Fibers,
358
- * as the method referred to this may cause the current Fiber
359
- * to yield execution.
360
- *
361
- * A special value of nil will cause Ruby to wait using the
362
- * rb_io_wait_readable() function.
363
- */
364
- static VALUE set_wait_rd(VALUE mod, VALUE sym)
365
- {
366
- switch (TYPE(sym)) {
367
- case T_SYMBOL:
368
- io_wait_rd = SYM2ID(sym);
369
- return sym;
370
- case T_NIL:
371
- io_wait_rd = 0;
372
- return sym;
373
- }
374
- rb_raise(rb_eTypeError, "must be a symbol or nil");
375
- return sym;
376
- }
377
-
378
- /*
379
- * call-seq:
380
- *
381
- * Kgio.wait_writable = :method_name
382
- * Kgio.wait_writable = nil
383
- *
384
- * Sets a method for kgio_write to call when a read would block.
385
- * This is useful for non-blocking frameworks that use Fibers,
386
- * as the method referred to this may cause the current Fiber
387
- * to yield execution.
388
- *
389
- * A special value of nil will cause Ruby to wait using the
390
- * rb_io_wait_writable() function.
391
- */
392
- static VALUE set_wait_wr(VALUE mod, VALUE sym)
393
- {
394
- switch (TYPE(sym)) {
395
- case T_SYMBOL:
396
- io_wait_wr = SYM2ID(sym);
397
- return sym;
398
- case T_NIL:
399
- io_wait_wr = 0;
400
- return sym;
401
- }
402
- rb_raise(rb_eTypeError, "must be a symbol or nil");
403
- return sym;
404
- }
405
-
406
- /*
407
- * call-seq:
408
- *
409
- * Kgio.wait_writable -> Symbol or nil
410
- *
411
- * Returns the symbolic method name of the method assigned to
412
- * call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_write
413
- * or Kgio::SocketMethods#kgio_write call
414
- */
415
- static VALUE wait_wr(VALUE mod)
416
- {
417
- return io_wait_wr ? ID2SYM(io_wait_wr) : Qnil;
418
- }
419
-
420
- /*
421
- * call-seq:
422
- *
423
- * Kgio.wait_readable -> Symbol or nil
424
- *
425
- * Returns the symbolic method name of the method assigned to
426
- * call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_read
427
- * or Kgio::SocketMethods#kgio_read call.
428
- */
429
- static VALUE wait_rd(VALUE mod)
430
- {
431
- return io_wait_rd ? ID2SYM(io_wait_rd) : Qnil;
432
- }
433
-
434
- static VALUE xaccept(void *ptr)
435
- {
436
- struct accept_args *a = ptr;
437
-
438
- return (VALUE)accept4(a->fd, a->addr, a->addrlen, accept4_flags);
439
- }
440
-
441
- #ifdef HAVE_RB_THREAD_BLOCKING_REGION
442
- # include <time.h>
443
- /*
444
- * Try to use a (real) blocking accept() since that can prevent
445
- * thundering herds under Linux:
446
- * http://www.citi.umich.edu/projects/linux-scalability/reports/accept.html
447
- *
448
- * So we periodically disable non-blocking, but not too frequently
449
- * because other processes may set non-blocking (especially during
450
- * a process upgrade) with Rainbows! concurrency model changes.
451
- */
452
- static int thread_accept(struct accept_args *a, int force_nonblock)
453
- {
454
- if (force_nonblock)
455
- set_nonblocking(a->fd);
456
- return (int)rb_thread_blocking_region(xaccept, a, RUBY_UBF_IO, 0);
457
- }
458
-
459
- static void set_blocking_or_block(int fd)
460
- {
461
- static time_t last_set_blocking;
462
- time_t now = time(NULL);
463
-
464
- if (last_set_blocking == 0) {
465
- last_set_blocking = now;
466
- (void)rb_io_wait_readable(fd);
467
- } else if ((now - last_set_blocking) <= 5) {
468
- (void)rb_io_wait_readable(fd);
469
- } else {
470
- int flags = fcntl(fd, F_GETFL);
471
- if (flags == -1)
472
- rb_sys_fail("fcntl(F_GETFL)");
473
- if (flags & O_NONBLOCK) {
474
- flags = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
475
- if (flags == -1)
476
- rb_sys_fail("fcntl(F_SETFL)");
477
- }
478
- last_set_blocking = now;
479
- }
480
- }
481
- #else /* ! HAVE_RB_THREAD_BLOCKING_REGION */
482
- # include <rubysig.h>
483
- static int thread_accept(struct accept_args *a, int force_nonblock)
484
- {
485
- int rv;
486
-
487
- /* always use non-blocking accept() under 1.8 for green threads */
488
- set_nonblocking(a->fd);
489
- TRAP_BEG;
490
- rv = (int)xaccept(a);
491
- TRAP_END;
492
- return rv;
493
- }
494
- #define set_blocking_or_block(fd) (void)rb_io_wait_readable(fd)
495
- #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
496
-
497
- static VALUE
498
- my_accept(VALUE io, struct sockaddr *addr, socklen_t *addrlen, int nonblock)
499
- {
500
- int client;
501
- struct accept_args a;
502
-
503
- a.fd = my_fileno(io);
504
- a.addr = addr;
505
- a.addrlen = addrlen;
506
- retry:
507
- client = thread_accept(&a, nonblock);
508
- if (client == -1) {
509
- switch (errno) {
510
- case EAGAIN:
511
- if (nonblock)
512
- return Qnil;
513
- set_blocking_or_block(a.fd);
514
- #ifdef ECONNABORTED
515
- case ECONNABORTED:
516
- #endif /* ECONNABORTED */
517
- #ifdef EPROTO
518
- case EPROTO:
519
- #endif /* EPROTO */
520
- case EINTR:
521
- goto retry;
522
- case ENOMEM:
523
- case EMFILE:
524
- case ENFILE:
525
- #ifdef ENOBUFS
526
- case ENOBUFS:
527
- #endif /* ENOBUFS */
528
- errno = 0;
529
- rb_gc();
530
- client = thread_accept(&a, nonblock);
531
- }
532
- if (client == -1) {
533
- if (errno == EINTR)
534
- goto retry;
535
- rb_sys_fail("accept");
536
- }
537
- }
538
- return sock_for_fd(cClientSocket, client);
539
- }
540
-
541
- static void in_addr_set(VALUE io, struct sockaddr_in *addr)
542
- {
543
- VALUE host = rb_str_new(0, INET_ADDRSTRLEN);
544
- socklen_t addrlen = (socklen_t)INET_ADDRSTRLEN;
545
- const char *name;
546
-
547
- name = inet_ntop(AF_INET, &addr->sin_addr, RSTRING_PTR(host), addrlen);
548
- if (name == NULL)
549
- rb_sys_fail("inet_ntop");
550
- rb_str_set_len(host, strlen(name));
551
- rb_ivar_set(io, iv_kgio_addr, host);
552
- }
553
-
554
- /*
555
- * call-seq:
556
- *
557
- * server = Kgio::TCPServer.new('0.0.0.0', 80)
558
- * server.kgio_tryaccept -> Kgio::Socket or nil
559
- *
560
- * Initiates a non-blocking accept and returns a generic Kgio::Socket
561
- * object with the kgio_addr attribute set to the IP address of the
562
- * connected client on success.
563
- *
564
- * Returns nil on EAGAIN, and raises on other errors.
565
- */
566
- static VALUE tcp_tryaccept(VALUE io)
567
- {
568
- struct sockaddr_in addr;
569
- socklen_t addrlen = sizeof(struct sockaddr_in);
570
- VALUE rv = my_accept(io, (struct sockaddr *)&addr, &addrlen, 1);
571
-
572
- if (!NIL_P(rv))
573
- in_addr_set(rv, &addr);
574
- return rv;
575
- }
576
-
577
- /*
578
- * call-seq:
579
- *
580
- * server = Kgio::TCPServer.new('0.0.0.0', 80)
581
- * server.kgio_accept -> Kgio::Socket or nil
582
- *
583
- * Initiates a blocking accept and returns a generic Kgio::Socket
584
- * object with the kgio_addr attribute set to the IP address of
585
- * the client on success.
586
- *
587
- * On Ruby implementations using native threads, this can use a blocking
588
- * accept(2) (or accept4(2)) system call to avoid thundering herds.
589
- */
590
- static VALUE tcp_accept(VALUE io)
591
- {
592
- struct sockaddr_in addr;
593
- socklen_t addrlen = sizeof(struct sockaddr_in);
594
- VALUE rv = my_accept(io, (struct sockaddr *)&addr, &addrlen, 0);
595
-
596
- in_addr_set(rv, &addr);
597
- return rv;
598
- }
599
-
600
- /*
601
- * call-seq:
602
- *
603
- * server = Kgio::UNIXServer.new("/path/to/unix/socket")
604
- * server.kgio_tryaccept -> Kgio::Socket or nil
605
- *
606
- * Initiates a non-blocking accept and returns a generic Kgio::Socket
607
- * object with the kgio_addr attribute set (to the value of
608
- * Kgio::LOCALHOST) on success.
609
- *
610
- * Returns nil on EAGAIN, and raises on other errors.
611
- */
612
- static VALUE unix_tryaccept(VALUE io)
613
- {
614
- VALUE rv = my_accept(io, NULL, NULL, 1);
615
-
616
- if (!NIL_P(rv))
617
- rb_ivar_set(rv, iv_kgio_addr, localhost);
618
- return rv;
619
- }
620
-
621
- /*
622
- * call-seq:
623
- *
624
- * server = Kgio::UNIXServer.new("/path/to/unix/socket")
625
- * server.kgio_accept -> Kgio::Socket or nil
626
- *
627
- * Initiates a blocking accept and returns a generic Kgio::Socket
628
- * object with the kgio_addr attribute set (to the value of
629
- * Kgio::LOCALHOST) on success.
630
- *
631
- * On Ruby implementations using native threads, this can use a blocking
632
- * accept(2) (or accept4(2)) system call to avoid thundering herds.
633
- */
634
- static VALUE unix_accept(VALUE io)
635
- {
636
- VALUE rv = my_accept(io, NULL, NULL, 0);
637
-
638
- rb_ivar_set(rv, iv_kgio_addr, localhost);
639
- return rv;
640
- }
641
-
642
- /*
643
- * call-seq:
644
- *
645
- * Kgio.accept_cloexec? -> true or false
646
- *
647
- * Returns true if newly accepted Kgio::Sockets are created with the
648
- * FD_CLOEXEC file descriptor flag, false if not.
649
- */
650
- static VALUE get_cloexec(VALUE mod)
651
- {
652
- return (accept4_flags & A4_SOCK_CLOEXEC) ==
653
- A4_SOCK_CLOEXEC ? Qtrue : Qfalse;
654
- }
655
-
656
- /*
657
- *
658
- * call-seq:
659
- *
660
- * Kgio.accept_nonblock? -> true or false
661
- *
662
- * Returns true if newly accepted Kgio::Sockets are created with the
663
- * O_NONBLOCK file status flag, false if not.
664
- */
665
- static VALUE get_nonblock(VALUE mod)
666
- {
667
- return (accept4_flags & A4_SOCK_NONBLOCK) ==
668
- A4_SOCK_NONBLOCK ? Qtrue : Qfalse;
669
- }
670
-
671
- /*
672
- * call-seq:
673
- *
674
- * Kgio.accept_cloexec = true
675
- * Kgio.accept_clocexec = false
676
- *
677
- * Sets whether or not Kgio::Socket objects created by
678
- * TCPServer#kgio_accept,
679
- * TCPServer#kgio_tryaccept,
680
- * UNIXServer#kgio_accept,
681
- * and UNIXServer#kgio_tryaccept
682
- * are created with the FD_CLOEXEC file descriptor flag.
683
- *
684
- * This is on by default, as there is little reason to deal to enable
685
- * it for client sockets on a socket server.
686
- */
687
- static VALUE set_cloexec(VALUE mod, VALUE boolean)
688
- {
689
- switch (TYPE(boolean)) {
690
- case T_TRUE:
691
- accept4_flags |= A4_SOCK_CLOEXEC;
692
- return boolean;
693
- case T_FALSE:
694
- accept4_flags &= ~A4_SOCK_CLOEXEC;
695
- return boolean;
696
- }
697
- rb_raise(rb_eTypeError, "not true or false");
698
- return Qnil;
699
- }
700
-
701
- /*
702
- * call-seq:
703
- *
704
- * Kgio.accept_nonblock = true
705
- * Kgio.accept_nonblock = false
706
- *
707
- * Sets whether or not Kgio::Socket objects created by
708
- * TCPServer#kgio_accept,
709
- * TCPServer#kgio_tryaccept,
710
- * UNIXServer#kgio_accept,
711
- * and UNIXServer#kgio_tryaccept
712
- * are created with the O_NONBLOCK file status flag.
713
- *
714
- * This defaults to +false+ for GNU/Linux where MSG_DONTWAIT is
715
- * available (and on newer GNU/Linux, accept4() may also set
716
- * the non-blocking flag. This defaults to +true+ on non-GNU/Linux
717
- * systems.
718
- */
719
- static VALUE set_nonblock(VALUE mod, VALUE boolean)
720
- {
721
- switch (TYPE(boolean)) {
722
- case T_TRUE:
723
- accept4_flags |= A4_SOCK_NONBLOCK;
724
- return boolean;
725
- case T_FALSE:
726
- accept4_flags &= ~A4_SOCK_NONBLOCK;
727
- return boolean;
728
- }
729
- rb_raise(rb_eTypeError, "not true or false");
730
- return Qnil;
731
- }
732
-
733
- static void close_fail(int fd, const char *msg)
734
- {
735
- int saved_errno = errno;
736
- (void)close(fd);
737
- errno = saved_errno;
738
- rb_sys_fail(msg);
739
- }
740
-
741
- #ifdef SOCK_NONBLOCK
742
- # define MY_SOCK_STREAM (SOCK_STREAM|SOCK_NONBLOCK)
743
- #else
744
- # define MY_SOCK_STREAM SOCK_STREAM
745
- #endif /* ! SOCK_NONBLOCK */
746
-
747
- static VALUE
748
- my_connect(VALUE klass, int io_wait, int domain, void *addr, socklen_t addrlen)
749
- {
750
- int fd = socket(domain, MY_SOCK_STREAM, 0);
751
-
752
- if (fd == -1) {
753
- switch (errno) {
754
- case EMFILE:
755
- case ENFILE:
756
- #ifdef ENOBUFS
757
- case ENOBUFS:
758
- #endif /* ENOBUFS */
759
- errno = 0;
760
- rb_gc();
761
- fd = socket(domain, MY_SOCK_STREAM, 0);
762
- }
763
- if (fd == -1)
764
- rb_sys_fail("socket");
765
- }
766
-
767
- #ifndef SOCK_NONBLOCK
768
- if (fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK) == -1)
769
- close_fail(fd, "fcntl(F_SETFL, O_RDWR | O_NONBLOCK)");
770
- #endif /* SOCK_NONBLOCK */
771
-
772
- if (connect(fd, addr, addrlen) == -1) {
773
- if (errno == EINPROGRESS) {
774
- VALUE io = sock_for_fd(klass, fd);
775
-
776
- if (io_wait) {
777
- errno = EAGAIN;
778
- wait_writable(io, fd);
779
- }
780
- return io;
781
- }
782
- close_fail(fd, "connect");
783
- }
784
- return sock_for_fd(klass, fd);
785
- }
786
-
787
- static VALUE tcp_connect(VALUE klass, VALUE ip, VALUE port, int io_wait)
788
- {
789
- struct sockaddr_in addr = { 0 };
790
-
791
- addr.sin_family = AF_INET;
792
- addr.sin_port = htons((unsigned short)NUM2INT(port));
793
-
794
- switch (inet_pton(AF_INET, StringValuePtr(ip), &addr.sin_addr)) {
795
- case 1:
796
- return my_connect(klass, io_wait, PF_INET, &addr, sizeof(addr));
797
- case -1:
798
- rb_sys_fail("inet_pton");
799
- }
800
- rb_raise(rb_eArgError, "invalid address: %s", StringValuePtr(ip));
801
-
802
- return Qnil;
803
- }
804
-
805
- /*
806
- * call-seq:
807
- *
808
- * Kgio::TCPSocket.new('127.0.0.1', 80) -> socket
809
- *
810
- * Creates a new Kgio::TCPSocket object and initiates a
811
- * non-blocking connection.
812
- *
813
- * This may block and call any method assigned to Kgio.wait_writable.
814
- *
815
- * Unlike the TCPSocket.new in Ruby, this does NOT perform DNS
816
- * lookups (which is subject to a different set of timeouts and
817
- * best handled elsewhere).
818
- */
819
- static VALUE kgio_tcp_connect(VALUE klass, VALUE ip, VALUE port)
820
- {
821
- return tcp_connect(klass, ip, port, 1);
822
- }
823
-
824
- /*
825
- * call-seq:
826
- *
827
- * Kgio::TCPSocket.start('127.0.0.1', 80) -> socket
828
- *
829
- * Creates a new Kgio::TCPSocket object and initiates a
830
- * non-blocking connection. The caller should select/poll
831
- * on the socket for writability before attempting to write
832
- * or optimistically attempt a write and handle Kgio::WaitWritable
833
- * or Errno::EAGAIN.
834
- *
835
- * Unlike the TCPSocket.new in Ruby, this does NOT perform DNS
836
- * lookups (which is subject to a different set of timeouts and
837
- * best handled elsewhere).
838
- */
839
- static VALUE kgio_tcp_start(VALUE klass, VALUE ip, VALUE port)
840
- {
841
- return tcp_connect(klass, ip, port, 0);
842
- }
843
-
844
- static VALUE unix_connect(VALUE klass, VALUE path, int io_wait)
845
- {
846
- struct sockaddr_un addr = { 0 };
847
- long len;
848
-
849
- StringValue(path);
850
- len = RSTRING_LEN(path);
851
- if (sizeof(addr.sun_path) <= len)
852
- rb_raise(rb_eArgError,
853
- "too long unix socket path (max: %dbytes)",
854
- (int)sizeof(addr.sun_path)-1);
855
-
856
- memcpy(addr.sun_path, RSTRING_PTR(path), len);
857
- addr.sun_family = AF_UNIX;
858
-
859
- return my_connect(klass, io_wait, PF_UNIX, &addr, sizeof(addr));
860
- }
861
-
862
- /*
863
- * call-seq:
864
- *
865
- * Kgio::UNIXSocket.new("/path/to/unix/socket") -> socket
866
- *
867
- * Creates a new Kgio::UNIXSocket object and initiates a
868
- * non-blocking connection.
869
- *
870
- * This may block and call any method assigned to Kgio.wait_writable.
871
- */
872
- static VALUE kgio_unix_connect(VALUE klass, VALUE path)
873
- {
874
- return unix_connect(klass, path, 1);
875
- }
876
-
877
- /*
878
- * call-seq:
879
- *
880
- * Kgio::UNIXSocket.start("/path/to/unix/socket") -> socket
881
- *
882
- * Creates a new Kgio::UNIXSocket object and initiates a
883
- * non-blocking connection. The caller should select/poll
884
- * on the socket for writability before attempting to write
885
- * or optimistically attempt a write and handle Kgio::WaitWritable
886
- * or Errno::EAGAIN.
887
- */
888
- static VALUE kgio_unix_start(VALUE klass, VALUE path)
889
- {
890
- return unix_connect(klass, path, 0);
891
- }
892
-
893
- static VALUE stream_connect(VALUE klass, VALUE addr, int io_wait)
894
- {
895
- int domain;
896
- socklen_t addrlen;
897
- struct sockaddr *sockaddr;
898
-
899
- if (TYPE(addr) == T_STRING) {
900
- sockaddr = (struct sockaddr *)(RSTRING_PTR(addr));
901
- addrlen = (socklen_t)RSTRING_LEN(addr);
902
- } else {
903
- rb_raise(rb_eTypeError, "invalid address");
904
- }
905
- switch (((struct sockaddr_in *)(sockaddr))->sin_family) {
906
- case AF_UNIX: domain = PF_UNIX; break;
907
- case AF_INET: domain = PF_INET; break;
908
- #ifdef AF_INET6 /* IPv6 support incomplete */
909
- case AF_INET6: domain = PF_INET6; break;
910
- #endif /* AF_INET6 */
911
- default:
912
- rb_raise(rb_eArgError, "invalid address family");
913
- }
914
-
915
- return my_connect(klass, io_wait, domain, sockaddr, addrlen);
916
- }
917
-
918
- /* call-seq:
919
- *
920
- * addr = Socket.pack_sockaddr_in(80, 'example.com')
921
- * Kgio::Socket.connect(addr) -> socket
922
- *
923
- * addr = Socket.pack_sockaddr_un("/path/to/unix/socket")
924
- * Kgio::Socket.connect(addr) -> socket
925
- *
926
- * Creates a generic Kgio::Socket object and initiates a
927
- * non-blocking connection.
928
- *
929
- * This may block and call any method assigned to Kgio.wait_writable.
930
- */
931
- static VALUE kgio_connect(VALUE klass, VALUE addr)
932
- {
933
- return stream_connect(klass, addr, 1);
934
- }
935
-
936
- /* call-seq:
937
- *
938
- * addr = Socket.pack_sockaddr_in(80, 'example.com')
939
- * Kgio::Socket.start(addr) -> socket
940
- *
941
- * addr = Socket.pack_sockaddr_un("/path/to/unix/socket")
942
- * Kgio::Socket.start(addr) -> socket
943
- *
944
- * Creates a generic Kgio::Socket object and initiates a
945
- * non-blocking connection. The caller should select/poll
946
- * on the socket for writability before attempting to write
947
- * or optimistically attempt a write and handle Kgio::WaitWritable
948
- * or Errno::EAGAIN.
949
- */
950
- static VALUE kgio_start(VALUE klass, VALUE addr)
951
- {
952
- return stream_connect(klass, addr, 0);
953
- }
954
-
955
- static VALUE set_accepted(VALUE klass, VALUE aclass)
956
- {
957
- VALUE tmp;
958
-
959
- if (NIL_P(aclass))
960
- aclass = cSocket;
961
-
962
- tmp = rb_funcall(aclass, rb_intern("included_modules"), 0, 0);
963
- tmp = rb_funcall(tmp, rb_intern("include?"), 1, mSocketMethods);
964
-
965
- if (tmp != Qtrue)
966
- rb_raise(rb_eTypeError,
967
- "class must include Kgio::SocketMethods");
968
-
969
- cClientSocket = aclass;
970
-
971
- return aclass;
972
- }
973
-
974
- static VALUE get_accepted(VALUE klass)
975
- {
976
- return cClientSocket;
977
- }
1
+ #include "kgio.h"
978
2
 
979
3
  void Init_kgio_ext(void)
980
4
  {
981
- VALUE mKgio = rb_define_module("Kgio");
982
- VALUE mPipeMethods;
983
- VALUE cUNIXServer, cTCPServer, cUNIXSocket, cTCPSocket;
984
-
985
- rb_require("socket");
986
-
987
- /*
988
- * Document-module: Kgio::Socket
989
- *
990
- * A generic socket class with Kgio::SocketMethods included.
991
- * This is returned by all Kgio methods that accept(2) a connected
992
- * stream socket.
993
- */
994
- cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
995
- cSocket = rb_define_class_under(mKgio, "Socket", cSocket);
996
- cClientSocket = cSocket;
997
-
998
- localhost = rb_str_new2("127.0.0.1");
999
-
1000
- /*
1001
- * The IPv4 address of UNIX domain sockets, useful for creating
1002
- * Rack (and CGI) servers that also serve HTTP traffic over
1003
- * UNIX domain sockets.
1004
- */
1005
- rb_const_set(mKgio, rb_intern("LOCALHOST"), localhost);
1006
-
1007
- /*
1008
- * Document-module: Kgio::WaitReadable
1009
- *
1010
- * PipeMethods#kgio_tryread and SocketMethods#kgio_tryread will
1011
- * return this constant when waiting for a read is required.
1012
- */
1013
- mKgio_WaitReadable = rb_define_module_under(mKgio, "WaitReadable");
1014
-
1015
- /*
1016
- * Document-module: Kgio::WaitWritable
1017
- *
1018
- * PipeMethods#kgio_trywrite and SocketMethods#kgio_trywrite will
1019
- * return this constant when waiting for a read is required.
1020
- */
1021
- mKgio_WaitWritable = rb_define_module_under(mKgio, "WaitWritable");
1022
-
1023
- rb_define_singleton_method(mKgio, "wait_readable=", set_wait_rd, 1);
1024
- rb_define_singleton_method(mKgio, "wait_writable=", set_wait_wr, 1);
1025
- rb_define_singleton_method(mKgio, "wait_readable", wait_rd, 0);
1026
- rb_define_singleton_method(mKgio, "wait_writable", wait_wr, 0);
1027
- rb_define_singleton_method(mKgio, "accept_cloexec?", get_cloexec, 0);
1028
- rb_define_singleton_method(mKgio, "accept_cloexec=", set_cloexec, 1);
1029
- rb_define_singleton_method(mKgio, "accept_nonblock?", get_nonblock, 0);
1030
- rb_define_singleton_method(mKgio, "accept_nonblock=", set_nonblock, 1);
1031
- rb_define_singleton_method(mKgio, "accept_class=", set_accepted, 1);
1032
- rb_define_singleton_method(mKgio, "accept_class", get_accepted, 0);
1033
-
1034
- /*
1035
- * Document-module: Kgio::PipeMethods
1036
- *
1037
- * This module may be used used to create classes that respond to
1038
- * various Kgio methods for reading and writing. This is included
1039
- * in Kgio::Pipe by default.
1040
- */
1041
- mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
1042
- rb_define_method(mPipeMethods, "kgio_read", kgio_read, -1);
1043
- rb_define_method(mPipeMethods, "kgio_write", kgio_write, 1);
1044
- rb_define_method(mPipeMethods, "kgio_tryread", kgio_tryread, -1);
1045
- rb_define_method(mPipeMethods, "kgio_trywrite", kgio_trywrite, 1);
1046
-
1047
- /*
1048
- * Document-module: Kgio::SocketMethods
1049
- *
1050
- * This method behaves like Kgio::PipeMethods, but contains
1051
- * optimizations for sockets on certain operating systems
1052
- * (e.g. GNU/Linux).
1053
- */
1054
- mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
1055
- rb_define_method(mSocketMethods, "kgio_read", kgio_recv, -1);
1056
- rb_define_method(mSocketMethods, "kgio_write", kgio_send, 1);
1057
- rb_define_method(mSocketMethods, "kgio_tryread", kgio_tryrecv, -1);
1058
- rb_define_method(mSocketMethods, "kgio_trywrite", kgio_trysend, 1);
1059
-
1060
- /*
1061
- * Returns the client IPv4 address of the socket in dotted quad
1062
- * form as a string. This is always the value of the
1063
- * Kgio::LOCALHOST constant for UNIX domain sockets.
1064
- */
1065
- rb_define_attr(mSocketMethods, "kgio_addr", 1, 1);
1066
-
1067
- rb_include_module(cSocket, mSocketMethods);
1068
- rb_define_singleton_method(cSocket, "new", kgio_connect, 1);
1069
- rb_define_singleton_method(cSocket, "start", kgio_start, 1);
1070
-
1071
- cUNIXServer = rb_const_get(rb_cObject, rb_intern("UNIXServer"));
1072
- cUNIXServer = rb_define_class_under(mKgio, "UNIXServer", cUNIXServer);
1073
- rb_define_method(cUNIXServer, "kgio_tryaccept", unix_tryaccept, 0);
1074
- rb_define_method(cUNIXServer, "kgio_accept", unix_accept, 0);
1075
-
1076
- cTCPServer = rb_const_get(rb_cObject, rb_intern("TCPServer"));
1077
- cTCPServer = rb_define_class_under(mKgio, "TCPServer", cTCPServer);
1078
- rb_define_method(cTCPServer, "kgio_tryaccept", tcp_tryaccept, 0);
1079
- rb_define_method(cTCPServer, "kgio_accept", tcp_accept, 0);
1080
-
1081
- cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
1082
- cTCPSocket = rb_define_class_under(mKgio, "TCPSocket", cTCPSocket);
1083
- rb_include_module(cTCPSocket, mSocketMethods);
1084
- rb_define_singleton_method(cTCPSocket, "new", kgio_tcp_connect, 2);
1085
- rb_define_singleton_method(cTCPSocket, "start", kgio_tcp_start, 2);
1086
-
1087
- cUNIXSocket = rb_const_get(rb_cObject, rb_intern("UNIXSocket"));
1088
- cUNIXSocket = rb_define_class_under(mKgio, "UNIXSocket", cUNIXSocket);
1089
- rb_include_module(cUNIXSocket, mSocketMethods);
1090
- rb_define_singleton_method(cUNIXSocket, "new", kgio_unix_connect, 1);
1091
- rb_define_singleton_method(cUNIXSocket, "start", kgio_unix_start, 1);
5
+ VALUE mKgio = rb_const_get(rb_cObject, rb_intern("Kgio"));
1092
6
 
1093
- iv_kgio_addr = rb_intern("@kgio_addr");
1094
- init_sock_for_fd();
7
+ init_kgio_wait(mKgio);
8
+ init_kgio_read_write(mKgio);
9
+ init_kgio_connect(mKgio);
10
+ init_kgio_accept(mKgio);
1095
11
  }