2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #if defined(HAVE_LINUX_TCP_H)
5 # include <linux/tcp.h>
7 # if defined(HAVE_NETINET_TCP_H)
8 # include <netinet/tcp.h>
10 # if defined(HAVE_NETINET_TCP_FSM_H)
11 # include <netinet/tcp_fsm.h>
15 #ifdef HAVE_TYPE_STRUCT_TCP_INFO
16 #include "my_fileno.h"
18 CFUNC_tcp_info_tcpi_state
19 CFUNC_tcp_info_tcpi_ca_state
20 CFUNC_tcp_info_tcpi_retransmits
21 CFUNC_tcp_info_tcpi_probes
22 CFUNC_tcp_info_tcpi_backoff
23 CFUNC_tcp_info_tcpi_options
24 CFUNC_tcp_info_tcpi_snd_wscale
25 CFUNC_tcp_info_tcpi_rcv_wscale
26 CFUNC_tcp_info_tcpi_rto
27 CFUNC_tcp_info_tcpi_ato
28 CFUNC_tcp_info_tcpi_snd_mss
29 CFUNC_tcp_info_tcpi_rcv_mss
30 CFUNC_tcp_info_tcpi_unacked
31 CFUNC_tcp_info_tcpi_sacked
32 CFUNC_tcp_info_tcpi_lost
33 CFUNC_tcp_info_tcpi_retrans
34 CFUNC_tcp_info_tcpi_fackets
35 CFUNC_tcp_info_tcpi_last_data_sent
36 CFUNC_tcp_info_tcpi_last_ack_sent
37 CFUNC_tcp_info_tcpi_last_data_recv
38 CFUNC_tcp_info_tcpi_last_ack_recv
39 CFUNC_tcp_info_tcpi_pmtu
40 CFUNC_tcp_info_tcpi_rcv_ssthresh
41 CFUNC_tcp_info_tcpi_rtt
42 CFUNC_tcp_info_tcpi_rttvar
43 CFUNC_tcp_info_tcpi_snd_ssthresh
44 CFUNC_tcp_info_tcpi_snd_cwnd
45 CFUNC_tcp_info_tcpi_advmss
46 CFUNC_tcp_info_tcpi_reordering
47 CFUNC_tcp_info_tcpi_rcv_rtt
48 CFUNC_tcp_info_tcpi_rcv_space
49 CFUNC_tcp_info_tcpi_total_retrans
51 static size_t tcpi_memsize(const void *ptr
)
53 return sizeof(struct tcp_info
);
56 static const rb_data_type_t tcpi_type
= {
58 { NULL
, RUBY_TYPED_DEFAULT_FREE
, tcpi_memsize
, /* reserved */ },
59 /* parent, data, [ flags ] */
62 static VALUE
alloc(VALUE klass
)
64 struct tcp_info
*info
;
66 return TypedData_Make_Struct(klass
, struct tcp_info
, &tcpi_type
, info
);
72 * Raindrops::TCP_Info.new(tcp_socket) -> TCP_Info object
74 * Reads a TCP_Info object from any given +tcp_socket+. See the tcp(7)
75 * manpage and /usr/include/linux/tcp.h for more details.
77 static VALUE
init(VALUE self
, VALUE io
)
79 int fd
= my_fileno(rb_io_get_io(io
));
80 struct tcp_info
*info
= DATA_PTR(self
);
81 socklen_t len
= (socklen_t
)sizeof(struct tcp_info
);
82 int rc
= getsockopt(fd
, IPPROTO_TCP
, TCP_INFO
, info
, &len
);
85 rb_sys_fail("getsockopt");
90 void Init_raindrops_tcp_info(void)
92 VALUE cRaindrops
= rb_define_class("Raindrops", rb_cObject
);
96 * Document-class: Raindrops::TCP_Info
98 * This is used to wrap "struct tcp_info" as described in tcp(7)
99 * and /usr/include/linux/tcp.h. The following readers methods
100 * are defined corresponding to the "tcpi_" fields in the
103 * As of raindrops 0.18.0+, this is supported on FreeBSD and OpenBSD
104 * systems as well as Linux, although not all fields exist or
105 * match the documentation, below.
107 * In particular, the +last_data_recv+ field is useful for measuring
108 * the amount of time a client spent in the listen queue before
109 * +accept()+, but only if +TCP_DEFER_ACCEPT+ is used with the
110 * listen socket (it is on by default in Unicorn).
145 * https://kernel.org/doc/man-pages/online/pages/man7/tcp.7.html
147 cTCP_Info
= rb_define_class_under(cRaindrops
, "TCP_Info", rb_cObject
);
148 rb_define_alloc_func(cTCP_Info
, alloc
);
149 rb_define_private_method(cTCP_Info
, "initialize", init
, 1);
152 * Document-method: Raindrops::TCP_Info#get!
156 * info = Raindrops::TCP_Info.new(tcp_socket)
157 * info.get!(tcp_socket)
159 * Update an existing TCP_Info objects with the latest stats
160 * from the given socket. This even allows sharing TCP_Info
161 * objects between different sockets to avoid garbage.
163 rb_define_method(cTCP_Info
, "get!", init
, 1);
165 DEFINE_METHOD_tcp_info_tcpi_state
;
166 DEFINE_METHOD_tcp_info_tcpi_ca_state
;
167 DEFINE_METHOD_tcp_info_tcpi_retransmits
;
168 DEFINE_METHOD_tcp_info_tcpi_probes
;
169 DEFINE_METHOD_tcp_info_tcpi_backoff
;
170 DEFINE_METHOD_tcp_info_tcpi_options
;
171 DEFINE_METHOD_tcp_info_tcpi_snd_wscale
;
172 DEFINE_METHOD_tcp_info_tcpi_rcv_wscale
;
173 DEFINE_METHOD_tcp_info_tcpi_rto
;
174 DEFINE_METHOD_tcp_info_tcpi_ato
;
175 DEFINE_METHOD_tcp_info_tcpi_snd_mss
;
176 DEFINE_METHOD_tcp_info_tcpi_rcv_mss
;
177 DEFINE_METHOD_tcp_info_tcpi_unacked
;
178 DEFINE_METHOD_tcp_info_tcpi_sacked
;
179 DEFINE_METHOD_tcp_info_tcpi_lost
;
180 DEFINE_METHOD_tcp_info_tcpi_retrans
;
181 DEFINE_METHOD_tcp_info_tcpi_fackets
;
182 DEFINE_METHOD_tcp_info_tcpi_last_data_sent
;
183 DEFINE_METHOD_tcp_info_tcpi_last_ack_sent
;
184 DEFINE_METHOD_tcp_info_tcpi_last_data_recv
;
185 DEFINE_METHOD_tcp_info_tcpi_last_ack_recv
;
186 DEFINE_METHOD_tcp_info_tcpi_pmtu
;
187 DEFINE_METHOD_tcp_info_tcpi_rcv_ssthresh
;
188 DEFINE_METHOD_tcp_info_tcpi_rtt
;
189 DEFINE_METHOD_tcp_info_tcpi_rttvar
;
190 DEFINE_METHOD_tcp_info_tcpi_snd_ssthresh
;
191 DEFINE_METHOD_tcp_info_tcpi_snd_cwnd
;
192 DEFINE_METHOD_tcp_info_tcpi_advmss
;
193 DEFINE_METHOD_tcp_info_tcpi_reordering
;
194 DEFINE_METHOD_tcp_info_tcpi_rcv_rtt
;
195 DEFINE_METHOD_tcp_info_tcpi_rcv_space
;
196 DEFINE_METHOD_tcp_info_tcpi_total_retrans
;
198 #ifdef RAINDROPS_TCP_STATES_ALL_KNOWN
201 * Document-const: Raindrops::TCP
203 * This is a frozen hash storing the numeric values
204 * maps platform-independent symbol keys to
205 * platform-dependent numeric values. These states
206 * are all valid values for the Raindrops::TCP_Info#state field.
208 * The platform-independent names of the keys in this hash are:
222 * This is only supported on platforms where TCP_Info is supported,
223 * currently FreeBSD, OpenBSD, and Linux-based systems.
226 #define TCPSET(n,v) rb_hash_aset(tcp, ID2SYM(rb_intern(#n)), INT2NUM(v))
227 VALUE tcp
= rb_hash_new();
228 TCPSET(ESTABLISHED
, RAINDROPS_TCP_ESTABLISHED
);
229 TCPSET(SYN_SENT
, RAINDROPS_TCP_SYN_SENT
);
230 TCPSET(SYN_RECV
, RAINDROPS_TCP_SYN_RECV
);
231 TCPSET(FIN_WAIT1
, RAINDROPS_TCP_FIN_WAIT1
);
232 TCPSET(FIN_WAIT2
, RAINDROPS_TCP_FIN_WAIT2
);
233 TCPSET(TIME_WAIT
, RAINDROPS_TCP_TIME_WAIT
);
234 TCPSET(CLOSE
, RAINDROPS_TCP_CLOSE
);
235 TCPSET(CLOSE_WAIT
, RAINDROPS_TCP_CLOSE_WAIT
);
236 TCPSET(LAST_ACK
, RAINDROPS_TCP_LAST_ACK
);
237 TCPSET(LISTEN
, RAINDROPS_TCP_LISTEN
);
238 TCPSET(CLOSING
, RAINDROPS_TCP_CLOSING
);
241 rb_define_const(cRaindrops
, "TCP", tcp
);
245 #endif /* HAVE_STRUCT_TCP_INFO */