1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| | #include "kgio.h"
#include <sys/utsname.h>
#include <stdio.h>
/* true if TCP Fast Open is usable */
unsigned kgio_tfo;
static VALUE eErrno_EPIPE, eErrno_ECONNRESET;
static ID id_set_backtrace;
static void tfo_maybe(void)
{
VALUE mKgio = rb_define_module("Kgio");
/* Deal with the case where system headers have not caught up */
if (KGIO_TFO_MAYBE) {
/* Ensure Linux 3.7 or later for TCP_FASTOPEN */
struct utsname buf;
unsigned maj, min;
if (uname(&buf) != 0)
rb_sys_fail("uname");
if (sscanf(buf.release, "%u.%u", &maj, &min) != 2)
return;
if (maj < 3 || (maj == 3 && min < 7))
return;
}
/*
* KGIO_TFO_MAYBE will be false if a distro backports TFO
* to a pre-3.7 kernel, but includes the necessary constants
* in system headers
*/
#if defined(MSG_FASTOPEN) && defined(TCP_FASTOPEN)
rb_define_const(mKgio, "TCP_FASTOPEN", INT2NUM(TCP_FASTOPEN));
rb_define_const(mKgio, "MSG_FASTOPEN", INT2NUM(MSG_FASTOPEN));
kgio_tfo = 1;
#endif
}
void kgio_raise_empty_bt(VALUE err, const char *msg)
{
VALUE exc = rb_exc_new2(err, msg);
VALUE bt = rb_ary_new();
rb_funcall(exc, id_set_backtrace, 1, bt);
rb_exc_raise(exc);
}
void kgio_wr_sys_fail(const char *msg)
{
switch (errno) {
case EPIPE:
errno = 0;
kgio_raise_empty_bt(eErrno_EPIPE, msg);
case ECONNRESET:
errno = 0;
kgio_raise_empty_bt(eErrno_ECONNRESET, msg);
}
rb_sys_fail(msg);
}
void kgio_rd_sys_fail(const char *msg)
{
if (errno == ECONNRESET) {
errno = 0;
kgio_raise_empty_bt(eErrno_ECONNRESET, msg);
}
rb_sys_fail(msg);
}
void Init_kgio_ext(void)
{
VALUE mKgio = rb_define_module("Kgio");
VALUE mPipeMethods = rb_define_module_under(mKgio, "PipeMethods");
VALUE mSocketMethods = rb_define_module_under(mKgio, "SocketMethods");
VALUE mWaiters = rb_define_module_under(mKgio, "DefaultWaiters");
id_set_backtrace = rb_intern("set_backtrace");
eErrno_EPIPE = rb_const_get(rb_mErrno, rb_intern("EPIPE"));
eErrno_ECONNRESET = rb_const_get(rb_mErrno, rb_intern("ECONNRESET"));
/*
* Returns the client IP address of the socket as a string
* (e.g. "127.0.0.1" or "::1").
* This is always the value of the Kgio::LOCALHOST constant
* for UNIX domain sockets.
*/
rb_define_attr(mSocketMethods, "kgio_addr", 1, 1);
rb_include_module(mPipeMethods, mWaiters);
rb_include_module(mSocketMethods, mWaiters);
tfo_maybe();
init_kgio_wait();
init_kgio_read();
init_kgio_write();
init_kgio_writev();
init_kgio_connect();
init_kgio_accept();
init_kgio_autopush();
init_kgio_poll();
init_kgio_tryopen();
}
|