raindrops 0.16.0 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0632eff3853589bfe99f749a3db3d12fa991220a
4
- data.tar.gz: 19c74eeede4492633f1e3b189b24e4a085fbe40f
2
+ SHA256:
3
+ metadata.gz: 1e1444bc6e35e67993745b3627e848537490fd3b02a67e12be9721b031e22e70
4
+ data.tar.gz: 9ed2dff40418e89a71ecf18cfb74b72d28d9570ceef314ee1c81bdff19ed832a
5
5
  SHA512:
6
- metadata.gz: a818ad3da0618365d832b5979de131a6fbafe3737877e4a4e95891b993ae6f0c90fd8938cb60494c95cd8ffaf67dd75a017549878f46739442f2739512f3b272
7
- data.tar.gz: 00b463e110ee126cfbda005af3b6f20c084120428aea74982795b1102dcab9487b461b35834cf3a71885c7d11fea29a3a1596d7f010e93e5210b376c5f6cad96
6
+ metadata.gz: ccb15ce6a96c1619d53d6090851ef8152ebd673b2db8aed9c6d4bb42757de2d9d051888d3f105d6d3461683eb33575d343e7d31a1ddb91a8f9914bb4e6abcb81
7
+ data.tar.gz: ce265e39bf3217f3b62931ead0fff78e7e118785466bc0eecff1858f9d808982c12b14f2645ecfffd96c8cb8e0a1a72ac03c0d6ad220c84950dfd2fe05d7f258
data/.document CHANGED
@@ -4,4 +4,4 @@ NEWS
4
4
  lib
5
5
  ext/raindrops/raindrops.c
6
6
  ext/raindrops/linux_inet_diag.c
7
- ext/raindrops/linux_tcp_info.c
7
+ ext/raindrops/tcp_info.c
data/.olddoc.yml CHANGED
@@ -1,9 +1,13 @@
1
1
  ---
2
- cgit_url: http://bogomips.org/raindrops.git
3
- git_url: git://bogomips.org/raindrops.git
4
- rdoc_url: http://raindrops.bogomips.org/
5
- public_email: raindrops-public@bogomips.org
6
- private_email: raindrops@bogomips.org
7
- ml_url: http://bogomips.org/raindrops-public/
2
+ cgit_url: https://yhbt.net/raindrops.git/
3
+ rdoc_url: https://yhbt.net/raindrops/
4
+ public_email: raindrops-public@yhbt.net
5
+ ml_url:
6
+ - https://yhbt.net/raindrops-public/
7
+ - http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public
8
8
  nntp_url:
9
- - nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
9
+ - nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
10
+ - nntp://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/inbox.comp.lang.ruby.raindrops
11
+ source_code:
12
+ - git clone https://yhbt.net/raindrops.git
13
+ - torsocks git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops.git
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.16.0
4
+ DEF_VER=v0.19.2
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -1,4 +1,4 @@
1
1
  all::
2
- RSYNC_DEST := bogomips.org:/srv/raindrops
2
+ RSYNC_DEST := yhbt.net:/srv/yhbt/raindrops
3
3
  rfpackage := raindrops
4
4
  include pkg.mk
data/LICENSE CHANGED
@@ -3,8 +3,8 @@ revision control for names and email addresses of all of them.
3
3
 
4
4
  You can redistribute it and/or modify it under the terms of the GNU
5
5
  Lesser General Public License (LGPL) as published by the Free Software
6
- Foundation, version {2.1}[http://www.gnu.org/licenses/lgpl-2.1.txt] or
7
- later. Currently version {3}[http://www.gnu.org/licenses/lgpl-3.0.txt],
6
+ Foundation, version {2.1}[https://www.gnu.org/licenses/lgpl-2.1.txt] or
7
+ later. Currently version {3}[https://www.gnu.org/licenses/lgpl-3.0.txt],
8
8
  is preferred (see link:COPYING).
9
9
 
10
10
  raindrops is distributed in the hope that it will be useful, but WITHOUT
@@ -13,4 +13,4 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13
13
  License for more details.
14
14
 
15
15
  You should have received a copy of the GNU Lesser General Public License
16
- along with the raindrops; if not, see <http://www.gnu.org/licenses/>
16
+ along with the raindrops; if not, see <https://www.gnu.org/licenses/>
data/README CHANGED
@@ -40,7 +40,7 @@ and "tcp_diag" kernel modules are loaded as they do not autoload correctly
40
40
  We recommend GCC 4+ (or compatible) to support the __sync builtins
41
41
  (__sync_{add,sub}_and_fetch()):
42
42
 
43
- http://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
43
+ https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
44
44
 
45
45
  For non-GCC 4+ users, we also support compilation with the libatomic_ops
46
46
  package starting with Raindrops 0.4.0:
@@ -54,30 +54,25 @@ If you use RubyGems:
54
54
 
55
55
  gem install raindrops
56
56
 
57
- Otherwise grab the latest tarball from:
58
-
59
- http://raindrops.bogomips.org/files/
60
-
61
- Unpack it, and run "ruby setup.rb"
62
-
63
57
  == Usage
64
58
 
65
59
  See Raindrops::Middleware and Raindrops::LastDataRecv documentation for
66
60
  use Rack servers. The entire library is fully-documented and we are
67
- responsive on the mailing list (mailto:raindrops-public@bogomips.org) if
61
+ responsive on the publically archived mailing list
62
+ (mailto:raindrops-public@yhbt.net) if
68
63
  you have any questions or comments.
69
64
 
70
65
  == Development
71
66
 
72
67
  You can get the latest source via git from the following locations:
73
68
 
74
- git://bogomips.org/raindrops.git
69
+ git://yhbt.net/raindrops.git
75
70
  git://repo.or.cz/raindrops.git (mirror)
76
71
 
77
72
  You may browse the code from the web and download the latest snapshot
78
73
  tarballs here:
79
74
 
80
- * http://bogomips.org/raindrops.git
75
+ * https://yhbt.net/raindrops.git
81
76
  * http://repo.or.cz/w/raindrops.git (gitweb)
82
77
 
83
78
  Inline patches (from "git format-patch") to the mailing list are
@@ -94,9 +89,14 @@ raindrops is licensed under the LGPL-2.1+
94
89
  == Contact
95
90
 
96
91
  All feedback (bug reports, user/development discussion, patches, pull
97
- requests) go to the mailing list: mailto:raindrops-public@bogomips.org
92
+ requests) go to the publically archived mailing list:
93
+ mailto:raindrops-public@yhbt.net
94
+
95
+ Mailing list archives are available over HTTPS and NNTP:
98
96
 
99
- Mailing list archives are available over HTTP and NNTP:
97
+ * https://yhbt.net/raindrops-public/
98
+ * http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/raindrops-public/
99
+ * nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
100
100
 
101
- http://bogomips.org/raindrops-public/
102
- nntp://news.public-inbox.org/inbox.comp.lang.ruby.raindrops
101
+ Since archives are public, scrub sensitive information and
102
+ use anonymity tools such as Tor or Mixmaster if you deem necessary.
data/TODO CHANGED
@@ -1,2 +1,3 @@
1
+ * fix IPv6 inet_diag reporting for Raindrops::Middleware
1
2
  * pure Ruby version for non-forking servers (patches welcome!)
2
3
  * unix_diag and udp_diag support
@@ -15,7 +15,6 @@
15
15
  usage = "Usage: #$0 [-d DELAY] [-t QUEUED_THRESHOLD] ADDR..."
16
16
  ARGV.size > 0 or abort usage
17
17
  delay = false
18
- all = false
19
18
  queued_thresh = -1
20
19
  # "normal" exits when driven on the command-line
21
20
  trap(:INT) { exit 130 }
@@ -25,7 +24,7 @@
25
24
  opts.banner = usage
26
25
  opts.on('-d', '--delay=DELAY', Float) { |n| delay = n }
27
26
  opts.on('-t', '--queued-threshold=INT', Integer) { |n| queued_thresh = n }
28
- opts.on('-a', '--all') { all = true }
27
+ opts.on('-a', '--all') { } # noop
29
28
  opts.parse! ARGV
30
29
  end
31
30
 
@@ -1,5 +1,5 @@
1
1
  # This is a snippet of the config that powers
2
- # http://raindrops-demo.bogomips.org/
2
+ # https://yhbt.net/raindrops-demo/
3
3
  # This may be used with the packaged zbatery.conf.rb
4
4
  #
5
5
  # zbatery -c zbatery.conf.ru watcher_demo.ru -E none
@@ -0,0 +1,30 @@
1
+ # Inlined rack app using yahns server (git clone git://yhbt.net/yahns.git)
2
+ # Usage: yahns -c /path/to/this/file.conf.rb
3
+ # There is no separate config.ru file for this example,
4
+ # but rack_app may also be a string pointing to the path of a
5
+ # config.ru file
6
+
7
+ require 'rack'
8
+ rack_app = Rack::Builder.new do
9
+ use Rack::Head
10
+ addr = %w(0.0.0.0:9418 0.0.0.0:443 [::]:443 0.0.0.0:80 [::]:80
11
+ 127.0.0.1:6081 127.0.0.1:280 0.0.0.0:119 [::]:119)
12
+ use Raindrops::Middleware, listeners: addr
13
+ run Raindrops::Watcher.new(listeners: addr)
14
+ end.to_app
15
+ # rack_app = '/path/to/config.ru' # a more standard config
16
+
17
+ app(:rack, rack_app) do
18
+ # I keep IPv4 and IPv6 on separate sockets to avoid ugly
19
+ # IPv4-mapped-IPv6 addresses:
20
+ listen 8080
21
+ listen '[::]:8080', ipv6only: true
22
+ client_max_body_size 0 # no POST or any uploads
23
+ client_timeout 5
24
+ output_buffering false # needed for /tail/ endpoint to avoid ENOSPC
25
+ queue { worker_threads 30 }
26
+ end
27
+
28
+ # logging is optional, but recommended for diagnosing problems
29
+ # stderr_path '/var/log/yahns/stderr-raindrops.log'
30
+ # stdout_path '/var/log/yahns/stdout-raindrops.log'
@@ -1,6 +1,9 @@
1
1
  # Used for running Raindrops::Watcher, which requires a multi-threaded
2
2
  # Rack server capable of streaming a response. Threads must be used,
3
- # so Zbatery is recommended: http://zbatery.bogomip.org/
3
+ # so any multi-threaded Rack server may be used.
4
+ # zbatery was recommended in the past, but it is abandoned
5
+ # <http://zbatery.bogomip.org/>.
6
+ # yahns may work as an alternative (see yahns.conf.rb in this dir)
4
7
  Rainbows! do
5
8
  use :ThreadSpawn
6
9
  end
@@ -1,4 +1,5 @@
1
1
  require 'mkmf'
2
+ require 'shellwords'
2
3
 
3
4
  dir_config('atomic_ops')
4
5
  have_func('mmap', 'sys/mman.h') or abort 'mmap() not found'
@@ -6,10 +7,112 @@
6
7
 
7
8
  $CPPFLAGS += " -D_GNU_SOURCE "
8
9
  have_func('mremap', 'sys/mman.h')
9
- have_header('linux/tcp.h')
10
+ headers = %w(sys/types.h netdb.h string.h sys/socket.h netinet/in.h)
11
+ if have_header('linux/tcp.h')
12
+ headers << 'linux/tcp.h'
13
+ else
14
+ %w(netinet/tcp.h netinet/tcp_fsm.h).each { |h|
15
+ have_header(h, headers) and headers << h
16
+ }
17
+ end
10
18
 
11
19
  $CPPFLAGS += " -D_BSD_SOURCE "
20
+
21
+ if have_type("struct tcp_info", headers)
22
+ %w(
23
+ tcpi_state
24
+ tcpi_ca_state
25
+ tcpi_retransmits
26
+ tcpi_probes
27
+ tcpi_backoff
28
+ tcpi_options
29
+ tcpi_snd_wscale
30
+ tcpi_rcv_wscale
31
+ tcpi_rto
32
+ tcpi_ato
33
+ tcpi_snd_mss
34
+ tcpi_rcv_mss
35
+ tcpi_unacked
36
+ tcpi_sacked
37
+ tcpi_lost
38
+ tcpi_retrans
39
+ tcpi_fackets
40
+ tcpi_last_data_sent
41
+ tcpi_last_ack_sent
42
+ tcpi_last_data_recv
43
+ tcpi_last_ack_recv
44
+ tcpi_pmtu
45
+ tcpi_rcv_ssthresh
46
+ tcpi_rtt
47
+ tcpi_rttvar
48
+ tcpi_snd_ssthresh
49
+ tcpi_snd_cwnd
50
+ tcpi_advmss
51
+ tcpi_reordering
52
+ tcpi_rcv_rtt
53
+ tcpi_rcv_space
54
+ tcpi_total_retrans
55
+ tcpi_snd_wnd
56
+ tcpi_snd_bwnd
57
+ tcpi_snd_nxt
58
+ tcpi_rcv_nxt
59
+ tcpi_toe_tid
60
+ tcpi_snd_rexmitpack
61
+ tcpi_rcv_ooopack
62
+ tcpi_snd_zerowin
63
+ ).each do |field|
64
+ cfunc = "tcp_info_#{field}"
65
+ if have_struct_member('struct tcp_info', field, headers)
66
+ func_body = <<EOF
67
+ static VALUE #{cfunc}(VALUE self)
68
+ {
69
+ struct tcp_info *info = DATA_PTR(self);
70
+ return UINT2NUM((uint32_t)info->#{field});
71
+ }
72
+ EOF
73
+ func_body.delete!("\n")
74
+ $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
75
+ else
76
+ func_body = "static inline void #{cfunc}(void) {}"
77
+ $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
78
+ cfunc = 'rb_f_notimplement'.freeze
79
+ end
80
+ rbmethod = %Q("#{field.sub(/\Atcpi_/, ''.freeze)}")
81
+ $defs << "-DDEFINE_METHOD_tcp_info_#{field}=" \
82
+ "#{Shellwords.shellescape(
83
+ %Q[rb_define_method(cTCP_Info,#{rbmethod},#{cfunc},0)])}"
84
+ end
85
+ tcp_state_map = {
86
+ ESTABLISHED: %w(TCP_ESTABLISHED TCPS_ESTABLISHED),
87
+ SYN_SENT: %w(TCP_SYN_SENT TCPS_SYN_SENT),
88
+ SYN_RECV: %w(TCP_SYN_RECV TCPS_SYN_RECEIVED),
89
+ FIN_WAIT1: %w(TCP_FIN_WAIT1 TCPS_FIN_WAIT_1),
90
+ FIN_WAIT2: %w(TCP_FIN_WAIT2 TCPS_FIN_WAIT_2),
91
+ TIME_WAIT: %w(TCP_TIME_WAIT TCPS_TIME_WAIT),
92
+ CLOSE: %w(TCP_CLOSE TCPS_CLOSED),
93
+ CLOSE_WAIT: %w(TCP_CLOSE_WAIT TCPS_CLOSE_WAIT),
94
+ LAST_ACK: %w(TCP_LAST_ACK TCPS_LAST_ACK),
95
+ LISTEN: %w(TCP_LISTEN TCPS_LISTEN),
96
+ CLOSING: %w(TCP_CLOSING TCPS_CLOSING),
97
+ }
98
+ nstate = 0
99
+ tcp_state_map.each do |state, try|
100
+ try.each do |os_name|
101
+ have_const(os_name, headers) or next
102
+ tcp_state_map[state] = os_name
103
+ nstate += 1
104
+ end
105
+ end
106
+ if nstate == tcp_state_map.size
107
+ $defs << '-DRAINDROPS_TCP_STATES_ALL_KNOWN=1'
108
+ tcp_state_map.each do |state, name|
109
+ $defs << "-DRAINDROPS_TCP_#{state}=#{name}"
110
+ end
111
+ end
112
+ end
113
+
12
114
  have_func("getpagesize", "unistd.h")
115
+ have_func('rb_thread_call_without_gvl')
13
116
  have_func('rb_thread_blocking_region')
14
117
  have_func('rb_thread_io_blocking_region')
15
118
 
@@ -40,7 +143,7 @@
40
143
  $defs.push(format("-DHAVE_GCC_ATOMIC_BUILTINS"))
41
144
  true
42
145
  else
43
- prev_cflags = $CFLAGS
146
+ $CFLAGS = prev_cflags
44
147
  false
45
148
  end
46
149
  end
@@ -53,4 +156,5 @@
53
156
 
54
157
  apt-get install libatomic-ops-dev
55
158
  SRC
159
+ create_header # generate extconf.h to avoid excessively long command-line
56
160
  create_makefile('raindrops_ext')
@@ -1,46 +1,24 @@
1
1
  #include <ruby.h>
2
2
  #include <stdarg.h>
3
- #ifdef HAVE_RUBY_ST_H
4
- # include <ruby/st.h>
5
- #else
6
- # include <st.h>
7
- #endif
3
+ #include <ruby/st.h>
8
4
  #include "my_fileno.h"
9
5
  #ifdef __linux__
10
6
 
11
- /* Ruby 1.8.6+ macros (for compatibility with Ruby 1.9) */
12
- #ifndef RSTRING_LEN
13
- # define RSTRING_LEN(s) (RSTRING(s)->len)
14
- #endif
15
-
16
- /* partial emulation of the 1.9 rb_thread_blocking_region under 1.8 */
17
- #if !defined(HAVE_RB_THREAD_BLOCKING_REGION) && \
18
- !defined(HAVE_RB_THREAD_IO_BLOCKING_REGION)
19
- # include <rubysig.h>
20
- # define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
21
- typedef void rb_unblock_function_t(void *);
22
- typedef VALUE rb_blocking_function_t(void *);
23
- static VALUE
24
- rb_thread_blocking_region(
25
- rb_blocking_function_t *func, void *data1,
26
- rb_unblock_function_t *ubf, void *data2)
27
- {
28
- VALUE rv;
29
-
30
- TRAP_BEG;
31
- rv = func(data1);
32
- TRAP_END;
33
-
34
- return rv;
35
- }
36
- #endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
37
-
38
7
  #ifdef HAVE_RB_THREAD_IO_BLOCKING_REGION
8
+ /* Ruby 1.9.3 and 2.0.0 */
39
9
  VALUE rb_thread_io_blocking_region(rb_blocking_function_t *, void *, int);
10
+ # define rd_fd_region(fn,data,fd) \
11
+ rb_thread_io_blocking_region((fn),(data),(fd))
12
+ #elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && \
13
+ defined(HAVE_RUBY_THREAD_H) && HAVE_RUBY_THREAD_H
14
+ /* in case Ruby 2.0+ ever drops rb_thread_io_blocking_region: */
15
+ # include <ruby/thread.h>
16
+ # define COMPAT_FN (void *(*)(void *))
17
+ # define rd_fd_region(fn,data,fd) \
18
+ rb_thread_call_without_gvl(COMPAT_FN(fn),(data),RUBY_UBF_IO,NULL)
40
19
  #else
41
- # define rb_thread_io_blocking_region(fn,data,fd) \
42
- rb_thread_blocking_region((fn),(data),RUBY_UBF_IO,0)
43
- #endif /* HAVE_RB_THREAD_IO_BLOCKING_REGION */
20
+ # error Ruby <= 1.8 not supported
21
+ #endif
44
22
 
45
23
  #include <assert.h>
46
24
  #include <errno.h>
@@ -214,6 +192,10 @@ static const char *addr_any(sa_family_t family)
214
192
  return ipv6;
215
193
  }
216
194
 
195
+ #ifdef __GNUC__
196
+ static void bug_warn_nogvl(const char *, ...)
197
+ __attribute__((format(printf,1,2)));
198
+ #endif
217
199
  static void bug_warn_nogvl(const char *fmt, ...)
218
200
  {
219
201
  va_list ap;
@@ -223,86 +205,76 @@ static void bug_warn_nogvl(const char *fmt, ...)
223
205
  va_end(ap);
224
206
 
225
207
  fprintf(stderr, "Please report how you produced this at "\
226
- "raindrops-public@bogomips.org\n");
208
+ "raindrops-public@yhbt.net\n");
227
209
  fflush(stderr);
228
210
  }
229
211
 
230
212
  static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
231
213
  {
232
- char *key, *port, *old_key;
214
+ char *host, *key, *port, *old_key;
233
215
  size_t alloca_len;
234
216
  struct listen_stats *stats;
235
- socklen_t keylen;
217
+ socklen_t hostlen;
236
218
  socklen_t portlen = (socklen_t)sizeof("65535");
237
- union any_addr sa;
238
- socklen_t len = sizeof(struct sockaddr_storage);
239
- int rc;
240
- int flags = NI_NUMERICHOST | NI_NUMERICSERV;
219
+ int n;
220
+ const void *src = r->id.idiag_src;
241
221
 
242
- switch ((sa.ss.ss_family = r->idiag_family)) {
222
+ switch (r->idiag_family) {
243
223
  case AF_INET: {
244
- sa.in.sin_port = r->id.idiag_sport;
245
- sa.in.sin_addr.s_addr = r->id.idiag_src[0];
246
- keylen = INET_ADDRSTRLEN;
247
- alloca_len = keylen + 1 + portlen;
248
- key = alloca(alloca_len);
249
- key[keylen] = 0; /* will be ':' later */
250
- port = key + keylen + 1;
251
- rc = getnameinfo(&sa.sa, len,
252
- key, keylen, port, portlen, flags);
224
+ hostlen = INET_ADDRSTRLEN;
225
+ alloca_len = hostlen + portlen;
226
+ host = key = alloca(alloca_len);
253
227
  break;
254
228
  }
255
229
  case AF_INET6: {
256
- sa.in6.sin6_port = r->id.idiag_sport;
257
- memcpy(&sa.in6.sin6_addr, &r->id.idiag_src, sizeof(__be32[4]));
258
- keylen = INET6_ADDRSTRLEN;
259
- /* [ ] */
260
- alloca_len = 1 + keylen + 1 + 1 + portlen;
230
+ hostlen = INET6_ADDRSTRLEN;
231
+ alloca_len = 1 + hostlen + 1 + portlen;
261
232
  key = alloca(alloca_len);
262
- *key = '[';
263
- key[1 + keylen + 1] = 0; /* will be ':' later */
264
- port = 1 + key + keylen + 1 + 1;
265
- rc = getnameinfo(&sa.sa, len,
266
- key + 1, keylen, port, portlen, flags);
233
+ host = key + 1;
267
234
  break;
268
235
  }
269
236
  default:
270
237
  assert(0 && "unsupported address family, could that be IPv7?!");
271
238
  }
272
- if (rc != 0) {
273
- bug_warn_nogvl("BUG: getnameinfo: %s\n", gai_strerror(rc));
274
- *key = 0;
239
+ if (!inet_ntop(r->idiag_family, src, host, hostlen)) {
240
+ bug_warn_nogvl("BUG: inet_ntop: %s\n", strerror(errno));
241
+ *key = '\0';
242
+ *host = '\0';
275
243
  }
276
-
277
- keylen = (socklen_t)strlen(key);
278
- portlen = (socklen_t)strlen(port);
279
-
280
- switch (sa.ss.ss_family) {
244
+ hostlen = (socklen_t)strlen(host);
245
+ switch (r->idiag_family) {
281
246
  case AF_INET:
282
- key[keylen] = ':';
283
- memmove(key + keylen + 1, port, portlen + 1);
247
+ host[hostlen] = ':';
248
+ port = host + hostlen + 1;
284
249
  break;
285
250
  case AF_INET6:
286
- key[keylen] = ']';
287
- key[keylen + 1] = ':';
288
- memmove(key + keylen + 2, port, portlen + 1);
289
- keylen++;
251
+ key[0] = '[';
252
+ host[hostlen] = ']';
253
+ host[hostlen + 1] = ':';
254
+ port = host + hostlen + 2;
290
255
  break;
291
256
  default:
292
257
  assert(0 && "unsupported address family, could that be IPv7?!");
293
258
  }
294
259
 
260
+ n = snprintf(port, portlen, "%u", ntohs(r->id.idiag_sport));
261
+ if (n <= 0) {
262
+ bug_warn_nogvl("BUG: snprintf port: %d\n", n);
263
+ *key = '\0';
264
+ }
265
+
295
266
  if (st_lookup(table, (st_data_t)key, (st_data_t *)&stats))
296
267
  return stats;
297
268
 
298
269
  old_key = key;
299
270
 
300
271
  if (r->idiag_state == TCP_ESTABLISHED) {
301
- int n = snprintf(key, alloca_len, "%s:%u",
302
- addr_any(sa.ss.ss_family),
272
+ n = snprintf(key, alloca_len, "%s:%u",
273
+ addr_any(r->idiag_family),
303
274
  ntohs(r->id.idiag_sport));
304
275
  if (n <= 0) {
305
276
  bug_warn_nogvl("BUG: snprintf: %d\n", n);
277
+ *key = '\0';
306
278
  }
307
279
  if (st_lookup(table, (st_data_t)key, (st_data_t *)&stats))
308
280
  return stats;
@@ -315,8 +287,9 @@ static struct listen_stats *stats_for(st_table *table, struct inet_diag_msg *r)
315
287
  memcpy(key, old_key, n + 1);
316
288
  }
317
289
  } else {
318
- key = xmalloc(keylen + 1 + portlen + 1);
319
- memcpy(key, old_key, keylen + 1 + portlen + 1);
290
+ size_t old_len = strlen(old_key) + 1;
291
+ key = xmalloc(old_len);
292
+ memcpy(key, old_key, old_len);
320
293
  }
321
294
  stats = xcalloc(1, sizeof(struct listen_stats));
322
295
  st_insert(table, (st_data_t)key, (st_data_t)stats);
@@ -613,7 +586,7 @@ static VALUE tcp_stats(struct nogvl_args *args, VALUE addr)
613
586
  gen_bytecode(&args->iov[2], &query_addr);
614
587
 
615
588
  memset(&args->stats, 0, sizeof(struct listen_stats));
616
- nl_errcheck(rb_thread_io_blocking_region(diag, args, args->fd));
589
+ nl_errcheck(rd_fd_region(diag, args, args->fd));
617
590
 
618
591
  return rb_listen_stats(&args->stats);
619
592
  }
@@ -690,7 +663,7 @@ static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
690
663
  "addr must be an array of strings, a string, or nil");
691
664
  }
692
665
 
693
- nl_errcheck(rb_thread_io_blocking_region(diag, &args, args.fd));
666
+ nl_errcheck(rd_fd_region(diag, &args, args.fd));
694
667
 
695
668
  st_foreach(args.table, NIL_P(addrs) ? st_to_hash : st_AND_hash, rv);
696
669
  st_free_table(args.table);
@@ -705,11 +678,12 @@ static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
705
678
 
706
679
  void Init_raindrops_linux_inet_diag(void)
707
680
  {
708
- VALUE cRaindrops = rb_const_get(rb_cObject, rb_intern("Raindrops"));
681
+ VALUE cRaindrops = rb_define_class("Raindrops", rb_cObject);
709
682
  VALUE mLinux = rb_define_module_under(cRaindrops, "Linux");
683
+ VALUE Socket;
710
684
 
711
685
  rb_require("socket");
712
- cIDSock = rb_const_get(rb_cObject, rb_intern("Socket"));
686
+ Socket = rb_const_get(rb_cObject, rb_intern("Socket"));
713
687
  id_new = rb_intern("new");
714
688
 
715
689
  /*
@@ -718,10 +692,11 @@ void Init_raindrops_linux_inet_diag(void)
718
692
  * This is a subclass of +Socket+ specifically for talking
719
693
  * to the inet_diag facility of Netlink.
720
694
  */
721
- cIDSock = rb_define_class_under(cRaindrops, "InetDiagSocket", cIDSock);
695
+ cIDSock = rb_define_class_under(cRaindrops, "InetDiagSocket", Socket);
722
696
  rb_define_singleton_method(cIDSock, "new", ids_s_new, 0);
723
697
 
724
698
  cListenStats = rb_const_get(cRaindrops, rb_intern("ListenStats"));
699
+ rb_gc_register_mark_object(cListenStats); /* pin */
725
700
 
726
701
  rb_define_module_function(mLinux, "tcp_listener_stats",
727
702
  tcp_listener_stats, -1);