README: update with extra disclaimer
[raindrops.git] / ext / raindrops / tcp_info.c
blobc0d34e02c29082ba141e5c83257a956132e7836c
1 #include <ruby.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #if defined(HAVE_LINUX_TCP_H)
5 # include <linux/tcp.h>
6 #else
7 # if defined(HAVE_NETINET_TCP_H)
8 # include <netinet/tcp.h>
9 # endif
10 # if defined(HAVE_NETINET_TCP_FSM_H)
11 # include <netinet/tcp_fsm.h>
12 # endif
13 #endif
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 = {
57 "tcp_info",
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);
70 * call-seq:
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);
84 if (rc != 0)
85 rb_sys_fail("getsockopt");
87 return self;
90 void Init_raindrops_tcp_info(void)
92 VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
93 VALUE cTCP_Info;
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
101 * tcp_info struct.
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).
112 * - state
113 * - ca_state
114 * - retransmits
115 * - probes
116 * - backoff
117 * - options
118 * - snd_wscale
119 * - rcv_wscale
120 * - rto
121 * - ato
122 * - snd_mss
123 * - rcv_mss
124 * - unacked
125 * - sacked
126 * - lost
127 * - retrans
128 * - fackets
129 * - last_data_sent
130 * - last_ack_sent
131 * - last_data_recv
132 * - last_ack_recv
133 * - pmtu
134 * - rcv_ssthresh
135 * - rtt
136 * - rttvar
137 * - snd_ssthresh
138 * - snd_cwnd
139 * - advmss
140 * - reordering
141 * - rcv_rtt
142 * - rcv_space
143 * - total_retrans
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!
154 * call-seq:
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:
210 * - :ESTABLISHED
211 * - :SYN_SENT
212 * - :SYN_RECV
213 * - :FIN_WAIT1
214 * - :FIN_WAIT2
215 * - :TIME_WAIT
216 * - :CLOSE
217 * - :CLOSE_WAIT
218 * - :LAST_ACK
219 * - :LISTEN
220 * - :CLOSING
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);
239 #undef TCPSET
240 OBJ_FREEZE(tcp);
241 rb_define_const(cRaindrops, "TCP", tcp);
243 #endif
245 #endif /* HAVE_STRUCT_TCP_INFO */