surro-gate 1.0.4 → 1.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fbbe2cc9fc406489f83bd1a5313f4d3228561a3a0995f70c4adafba46ef485f
4
- data.tar.gz: cbe94944cf56bac71822c2049932e030538a130563ac7e5490599b9403df6a05
3
+ metadata.gz: 424ad5ad77841b6c66059f77feee8fe7ba7edf67b4c896af81932187e67793cc
4
+ data.tar.gz: b420bd8ff5148a1b65c326090e944e3b510f1e25bc247e6814a10a4bdcf07f44
5
5
  SHA512:
6
- metadata.gz: 4e832268db84ec8ae285517fa63cf3bf634ecfafdcb01d533e370a6290528dfbc87215e2dbdd5dc993d21ea21f2ede39f6ca6469b22732ff53a1675c1f4abddf
7
- data.tar.gz: 4de9ab81b9ba2fb2170badf9f8fedaa719cf224e6a63f421d1cb96e99520c3b717100ae6eeae4b38329d3c7c5f8a5f2b895ff13d3a1cf6aa635d70610ca91517
6
+ metadata.gz: c6dcea2dcf0637437a8ea177aa24a4d80f34175b0f06d77253b5c4cb0d0df28e7bba676644c843d62d47f83f00d639e71b63273ccb5ba7c81136b848b3f30ab4
7
+ data.tar.gz: 93c7c0af5dd2558523e92987f2cf969cedde14ba11ba9ea4554f8200409fcdf5006eb4a1c18778f550ff6bb180306df7ddadee0edbf2a6ce0875b2a2f6dc0d42
@@ -8,7 +8,6 @@ compiler:
8
8
  - gcc
9
9
  - clang
10
10
  rvm:
11
- - 2.2
12
11
  - 2.3
13
12
  - 2.4
14
13
  - 2.5
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/surro-gate.svg)](https://badge.fury.io/rb/surro-gate)
4
4
  [![Build Status](https://travis-ci.org/skateman/surro-gate.svg?branch=master)](https://travis-ci.org/skateman/surro-gate)
5
- [![Dependency Status](https://gemnasium.com/skateman/surro-gate.svg)](https://gemnasium.com/skateman/surro-gate)
6
5
  [![Inline docs](http://inch-ci.org/github/skateman/surro-gate.svg?branch=master)](http://inch-ci.org/github/skateman/surro-gate)
7
6
  [![Code Climate](https://codeclimate.com/github/skateman/surro-gate/badges/gpa.svg)](https://codeclimate.com/github/skateman/surro-gate)
8
7
 
@@ -69,4 +68,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/skatem
69
68
  ## License
70
69
 
71
70
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
72
-
@@ -3,23 +3,24 @@
3
3
  static VALUE mSurroGate = Qnil;
4
4
  static VALUE cSurroGate_Selector = Qnil;
5
5
  static VALUE cSurroGate_Pair = Qnil;
6
+ static VALUE cSurroGate_Scoreboard = Qnil;
6
7
 
7
- void epoll_register(int *epoll, int socket, int ltr, int rtl) {
8
+ void epoll_register(int *epoll, VALUE socket) {
8
9
  struct epoll_event ev;
9
- ev.data.u64 = ((uint64_t)ltr) << 32 | rtl;
10
+ ev.data.u64 = (uint64_t) socket;
10
11
  ev.events = EPOLLONESHOT | EPOLLIN | EPOLLOUT;
11
- epoll_ctl(*epoll, EPOLL_CTL_ADD, socket, &ev);
12
+ epoll_ctl(*epoll, EPOLL_CTL_ADD, SOCK_PTR(socket), &ev);
12
13
  }
13
14
 
14
- void epoll_deregister(int *epoll, int socket) {
15
- epoll_ctl(*epoll, EPOLL_CTL_DEL, socket, NULL);
15
+ void epoll_deregister(int *epoll, VALUE socket) {
16
+ epoll_ctl(*epoll, EPOLL_CTL_DEL, SOCK_PTR(socket), NULL);
16
17
  }
17
18
 
18
- void epoll_rearm(int *epoll, int socket, int ltr, int rtl, int events) {
19
+ void epoll_rearm(int *epoll, VALUE socket, int events) {
19
20
  struct epoll_event ev;
20
- ev.data.u64 = ((uint64_t)ltr) << 32 | rtl;
21
+ ev.data.u64 = (uint64_t) socket;
21
22
  ev.events = EPOLLONESHOT | events;
22
- epoll_ctl(*epoll, EPOLL_CTL_MOD, socket, &ev);
23
+ epoll_ctl(*epoll, EPOLL_CTL_MOD, SOCK_PTR(socket), &ev);
23
24
  }
24
25
 
25
26
  void* wait_func(void *ptr) {
@@ -29,40 +30,25 @@ void* wait_func(void *ptr) {
29
30
  return NULL;
30
31
  }
31
32
 
32
- static VALUE pairing_compare(VALUE pair, VALUE sockets) {
33
- int i;
34
- VALUE left = rb_iv_get(pair, "@left");
35
- VALUE right = rb_iv_get(pair, "@right");
36
-
37
- for (i=0; i<RARRAY_LEN(sockets); i++) { // sockets.each
38
- VALUE item = rb_ary_entry(sockets, i);
39
- if (left == item || right == item) {
40
- return Qtrue;
41
- }
42
- }
43
-
44
- return Qnil;
45
- };
46
-
47
- static VALUE pairing_iterate(VALUE pair, VALUE self, int argc, VALUE *argv) {
33
+ static VALUE scoreboard_iterate(VALUE pair, VALUE self, int argc, VALUE *argv) {
48
34
  int *selector;
49
- VALUE inverse, inv_idx;
35
+ VALUE inverse;
36
+
37
+ VALUE scoreboard = rb_iv_get(self, "@scoreboard");
38
+ Data_Get_Struct(self, int, selector);
50
39
 
51
40
  // Yield only for the pairs that are ready
52
41
  if (rb_funcall(pair, rb_intern("ready?"), 0) == Qtrue) {
53
42
  rb_yield_values(2, rb_iv_get(pair, "@left"), rb_iv_get(pair, "@right")); // yield(pair.left, pair.right)
54
43
 
55
- inv_idx = rb_iv_get(pair, "@inverse");
56
- inverse = rb_funcall(rb_iv_get(self, "@pairing"), rb_intern("[]"), 1, inv_idx); // @pairing[inv_idx]
57
-
58
- rb_iv_set(pair, "@rd_rdy", Qfalse);
59
- rb_iv_set(pair, "@wr_rdy", Qfalse);
60
-
61
- Data_Get_Struct(self, int, selector);
44
+ // Unmark the readiness of the socket pair
45
+ rb_funcall(pair, rb_intern("unmark"), 0);
46
+ // Get the inverse socket pairing of the current one
47
+ inverse = rb_funcall(scoreboard, rb_intern("inverse"), 1, pair);
62
48
  // Rearm left socket for reading and also writing if not ready for writing
63
- epoll_rearm(selector, SOCK_PTR(rb_iv_get(pair, "@left")), NUM2INT(inv_idx), NUM2INT(argv[1]), EPOLLIN | (IVAR_TRUE(inverse, "@wr_rdy") ? 0 : EPOLLOUT));
49
+ epoll_rearm(selector, rb_iv_get(pair, "@left"), EPOLLIN | (IVAR_TRUE(inverse, "@wr_rdy") ? 0 : EPOLLOUT));
64
50
  // Rearm right socket for writing and also reading if not ready for reading
65
- epoll_rearm(selector, SOCK_PTR(rb_iv_get(pair, "@right")), NUM2INT(argv[1]), NUM2INT(inv_idx), EPOLLOUT | (IVAR_TRUE(inverse, "@rd_rdy") ? 0 : EPOLLIN));
51
+ epoll_rearm(selector, rb_iv_get(pair, "@right"), EPOLLOUT | (IVAR_TRUE(inverse, "@rd_rdy") ? 0 : EPOLLIN));
66
52
  }
67
53
  return Qnil;
68
54
  }
@@ -89,69 +75,54 @@ static void SurroGate_Selector_free(int *selector) {
89
75
  }
90
76
 
91
77
  static VALUE SurroGate_Selector_initialize(VALUE self, VALUE logger) {
92
- VALUE mConcurrent = rb_const_get(rb_cObject, rb_intern("Concurrent"));
93
- VALUE cArray = rb_const_get(mConcurrent, rb_intern("Array"));
94
-
95
- rb_iv_set(self, "@pairing", rb_class_new_instance(0, NULL, cArray)); // @pairing = Concurrent::Array.new
78
+ rb_iv_set(self, "@scoreboard", rb_class_new_instance(0, NULL, cSurroGate_Scoreboard)); // @scoreboard = Scoreboard.new
96
79
  rb_iv_set(self, "@logger", logger);
97
80
 
98
81
  return Qnil;
99
82
  }
100
83
 
101
84
  static VALUE SurroGate_Selector_push(VALUE self, VALUE left, VALUE right) {
102
- int index_ltr, index_rtl, *selector;
103
-
104
- VALUE pair_LTR[2] = {left, right};
105
- VALUE pair_RTL[2] = {right, left};
106
- VALUE left_to_right = rb_class_new_instance(2, pair_RTL, cSurroGate_Pair); // SurroGate::Pair.new(left, right)
107
- VALUE right_to_left = rb_class_new_instance(2, pair_LTR, cSurroGate_Pair); // SurroGate::Pair.new(right, left)
108
-
109
- VALUE pairing = rb_iv_get(self, "@pairing");
85
+ int *selector;
86
+ VALUE scoreboard = rb_iv_get(self, "@scoreboard");
110
87
 
88
+ // Check the arguments for the correct type
111
89
  Check_Type(left, T_FILE);
112
90
  Check_Type(right, T_FILE);
113
91
 
114
- // raise ArgumentError if @pairing.detect(&pairing_compare)
115
- if (rb_block_call(pairing, rb_intern("detect"), 0, NULL, pairing_compare, rb_ary_new_from_values(2, pair_LTR)) != Qnil) {
92
+ // raise ArgumentError if a socket is already registered
93
+ if (rb_funcall(scoreboard, rb_intern("include?"), 1, left) == Qtrue || rb_funcall(scoreboard, rb_intern("include?"), 1, right) == Qtrue) {
116
94
  rb_raise(rb_eArgError, "Socket already registered!");
117
95
  }
118
96
 
119
97
  Data_Get_Struct(self, int, selector);
98
+ rb_funcall(scoreboard, rb_intern("push"), 2, left, right);
120
99
 
121
- rb_funcall(pairing, rb_intern("push"), 2, left_to_right, right_to_left); // @pairing.push(left_to_right, right_to_left)
122
- index_ltr = NUM2INT(rb_funcall(pairing, rb_intern("index"), 1, left_to_right)); // @pairing.index(left_to_right)
123
- index_rtl = NUM2INT(rb_funcall(pairing, rb_intern("index"), 1, right_to_left)); // @pairing.index(right_to_left)
124
-
125
- rb_iv_set(left_to_right, "@inverse", INT2NUM(index_rtl));
126
- rb_iv_set(right_to_left, "@inverse", INT2NUM(index_ltr));
127
-
128
- epoll_register(selector, SOCK_PTR(left), index_ltr, index_rtl);
129
- epoll_register(selector, SOCK_PTR(right), index_rtl, index_ltr);
100
+ epoll_register(selector, left);
101
+ epoll_register(selector, right);
130
102
 
131
103
  return Qtrue;
132
104
  }
133
105
 
134
- static VALUE SurroGate_Selector_pop(VALUE self, VALUE sockets) {
135
- int i, *selector;
106
+ static VALUE SurroGate_Selector_pop(VALUE self, VALUE left, VALUE right) {
107
+ int *selector;
136
108
 
137
- VALUE pairing = rb_iv_get(self, "@pairing");
138
- rb_block_call(pairing, rb_intern("delete_if"), 0, NULL, pairing_compare, sockets); // @pairing.delete_if(&pairing_compare)
109
+ VALUE scoreboard = rb_iv_get(self, "@scoreboard");
110
+ rb_funcall(scoreboard, rb_intern("pop"), 2, left, right);
139
111
 
140
112
  Data_Get_Struct(self, int, selector);
141
- for (i=0; i<RARRAY_LEN(sockets); i++) {
142
- epoll_deregister(selector, SOCK_PTR(rb_ary_entry(sockets, i)));
143
- }
113
+ epoll_deregister(selector, left);
114
+ epoll_deregister(selector, right);
144
115
 
145
116
  return Qnil;
146
117
  }
147
118
 
148
119
  static VALUE SurroGate_Selector_select(VALUE self, VALUE timeout) {
149
- int i, *selector, source, target;
120
+ int i, *selector;
150
121
  struct epoll_event events[256];
151
122
  struct epoll_wait_args wait_args;
152
- VALUE read, write, socket;
123
+ VALUE socket;
153
124
 
154
- VALUE pairing = rb_iv_get(self, "@pairing");
125
+ VALUE scoreboard = rb_iv_get(self, "@scoreboard");
155
126
  Data_Get_Struct(self, int, selector);
156
127
 
157
128
  // The code after the comments has the same result as the code below, but with GVL
@@ -164,29 +135,23 @@ static VALUE SurroGate_Selector_select(VALUE self, VALUE timeout) {
164
135
  rb_thread_call_without_gvl(wait_func, &wait_args, NULL, NULL);
165
136
 
166
137
  for (i=0; i<wait_args.result; i++) {
167
- source = (int)((events[i].data.u64 & 0xFFFFFFFF00000000LL) >> 32);
168
- target = (int)(events[i].data.u64 & 0xFFFFFFFFLL);
169
-
170
- read = rb_funcall(pairing, rb_intern("[]"), 1, INT2NUM(target)); // @pairing[target]
171
- write = rb_funcall(pairing, rb_intern("[]"), 1, INT2NUM(source)); // @pairing[source]
138
+ socket = (VALUE) events[i].data.u64;
172
139
 
173
140
  if (events[i].events & EPOLLIN && events[i].events & EPOLLOUT) {
174
141
  // Socket is both available for read and write
175
- rb_iv_set(read, "@rd_rdy", Qtrue); // read.rd_rdy = true
176
- rb_iv_set(write, "@wr_rdy", Qtrue); // write.wr_rdy = true
142
+ rb_funcall(scoreboard, rb_intern("mark_rd"), 1, socket);
143
+ rb_funcall(scoreboard, rb_intern("mark_wr"), 1, socket);
177
144
  } else if (events[i].events & EPOLLIN) {
178
145
  // Socket is available for read, reregister it for write if not writable
179
- rb_iv_set(read, "@rd_rdy", Qtrue); // read.rd_rdy = true
180
- if (rb_iv_get(write, "@wr_rdy") == Qfalse) { // if !write.wr_rdy
181
- socket = rb_iv_get(read, "@left"); // read.left
182
- epoll_rearm(selector, SOCK_PTR(socket), target, source, EPOLLOUT);
146
+ rb_funcall(scoreboard, rb_intern("mark_rd"), 1, socket);
147
+ if (rb_funcall(scoreboard, rb_intern("marked_wr?"), 1, socket) == Qfalse) {
148
+ epoll_rearm(selector, socket, EPOLLOUT);
183
149
  }
184
150
  } else if (events[i].events & EPOLLOUT) {
185
151
  // Socket is available for write, reregister it for read if not readable
186
- rb_iv_set(write, "@wr_rdy", Qtrue); // write.wr_rdy = true
187
- if (rb_iv_get(write, "@rd_rdy") == Qfalse) { // if !source.rd_rdy
188
- socket = rb_iv_get(write, "@right"); // write.right
189
- epoll_rearm(selector, SOCK_PTR(socket), source, target, EPOLLIN);
152
+ rb_funcall(scoreboard, rb_intern("mark_wr"), 1, socket);
153
+ if (rb_funcall(scoreboard, rb_intern("marked_rd?"), 1, socket) == Qfalse) {
154
+ epoll_rearm(selector, socket, EPOLLIN);
190
155
  }
191
156
  }
192
157
  }
@@ -195,24 +160,25 @@ static VALUE SurroGate_Selector_select(VALUE self, VALUE timeout) {
195
160
  }
196
161
 
197
162
  static VALUE SurroGate_Selector_each_ready(VALUE self) {
198
- VALUE pairing = rb_iv_get(self, "@pairing");
163
+ VALUE scoreboard = rb_iv_get(self, "@scoreboard");
199
164
  rb_need_block();
200
- return rb_block_call(pairing, rb_intern("each_with_index"), 0, NULL, pairing_iterate, self);
165
+ return rb_block_call(scoreboard, rb_intern("each"), 0, NULL, scoreboard_iterate, self);
201
166
  }
202
167
 
203
168
  void Init_selector_ext() {
204
- rb_require("concurrent");
205
169
  rb_require("surro-gate/pair");
170
+ rb_require("surro-gate/scoreboard");
206
171
 
207
172
  mSurroGate = rb_define_module("SurroGate");
208
173
  cSurroGate_Selector = rb_define_class_under(mSurroGate, "Selector", rb_cObject);
209
174
  cSurroGate_Pair = rb_const_get(mSurroGate, rb_intern("Pair"));
175
+ cSurroGate_Scoreboard = rb_const_get(mSurroGate, rb_intern("Scoreboard"));
210
176
 
211
177
  rb_define_alloc_func(cSurroGate_Selector, SurroGate_Selector_allocate);
212
178
 
213
179
  rb_define_method(cSurroGate_Selector, "initialize", SurroGate_Selector_initialize, 1);
214
180
  rb_define_method(cSurroGate_Selector, "push", SurroGate_Selector_push, 2);
215
- rb_define_method(cSurroGate_Selector, "pop", SurroGate_Selector_pop, -2);
181
+ rb_define_method(cSurroGate_Selector, "pop", SurroGate_Selector_pop, 2);
216
182
  rb_define_method(cSurroGate_Selector, "select", SurroGate_Selector_select, 1);
217
183
  rb_define_method(cSurroGate_Selector, "each_ready", SurroGate_Selector_each_ready, 0);
218
184
  }
@@ -26,7 +26,6 @@ static VALUE SurroGate_Selector_select(VALUE self, VALUE timeout);
26
26
  static VALUE SurroGate_Selector_each_ready(VALUE self);
27
27
 
28
28
  static void SurroGate_Selector_free(int *epoll);
29
- static VALUE pairing_compare(VALUE pair, VALUE sockets);
30
- static VALUE pairing_iterate(VALUE pair, VALUE self, int argc, VALUE *argv);
29
+ static VALUE scoreboard_iterate(VALUE pair, VALUE self, int argc, VALUE *argv);
31
30
 
32
31
  #endif
@@ -7,11 +7,31 @@ module SurroGate
7
7
  def initialize(left, right)
8
8
  @left = left
9
9
  @right = right
10
- @rd_rdy = @wr_rdy = false
10
+ unmark
11
11
  end
12
12
 
13
13
  def ready?
14
14
  @rd_rdy && @wr_rdy || @left.closed? || @right.closed?
15
15
  end
16
+
17
+ def marked_rd?
18
+ @rd_rdy
19
+ end
20
+
21
+ def marked_wr?
22
+ @wr_rdy
23
+ end
24
+
25
+ def mark_rd
26
+ @rd_rdy = true
27
+ end
28
+
29
+ def mark_wr
30
+ @wr_rdy = true
31
+ end
32
+
33
+ def unmark
34
+ @rd_rdy = @wr_rdy = false
35
+ end
16
36
  end
17
37
  end
@@ -0,0 +1,70 @@
1
+ require 'thread'
2
+
3
+ module SurroGate
4
+ class Scoreboard
5
+ def initialize
6
+ @rd = {}
7
+ @wr = {}
8
+
9
+ @lock = Mutex.new
10
+ end
11
+
12
+ def push(left, right)
13
+ left_to_right = Pair.new(left, right)
14
+ right_to_left = Pair.new(right, left)
15
+
16
+ @lock.synchronize do
17
+ @rd[left] = left_to_right
18
+ @wr[right] = left_to_right
19
+
20
+ @rd[right] = right_to_left
21
+ @wr[left] = right_to_left
22
+ end
23
+
24
+ [left, right]
25
+ end
26
+
27
+ def pop(left, right)
28
+ @lock.synchronize do
29
+ @rd.delete(left)
30
+ @rd.delete(right)
31
+ @wr.delete(left)
32
+ @wr.delete(right)
33
+ end
34
+
35
+ [left, right]
36
+ end
37
+
38
+ def mark_rd(sock)
39
+ @rd[sock].mark_rd
40
+ end
41
+
42
+ def mark_wr(sock)
43
+ @wr[sock].mark_wr
44
+ end
45
+
46
+ def marked_rd?(sock)
47
+ @rd[sock].marked_rd?
48
+ end
49
+
50
+ def marked_wr?(sock)
51
+ @wr[sock].marked_wr?
52
+ end
53
+
54
+ def unmark(sock)
55
+ @rd[sock].unmark
56
+ end
57
+
58
+ def include?(sock)
59
+ @rd.key?(sock) || @wr.key?(sock)
60
+ end
61
+
62
+ def each(&block)
63
+ @rd.values.each(&block)
64
+ end
65
+
66
+ def inverse(pair)
67
+ @wr[pair.left]
68
+ end
69
+ end
70
+ end
@@ -97,8 +97,8 @@ module SurroGate
97
97
  end
98
98
 
99
99
  def pairing_compare(pair, sockets)
100
- sockets.each do |sock|
101
- return true if [pair.left, pair.right].include?(sock)
100
+ sockets.any? do |sock|
101
+ pair.left == sock || pair.right == sock
102
102
  end
103
103
  end
104
104
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SurroGate
4
- VERSION = '1.0.4'.freeze
4
+ VERSION = '1.0.5'.freeze
5
5
  HAVE_EXT = RUBY_PLATFORM =~ /linux/ && !defined?(JRUBY_VERSION) && !ENV['SURRO_GATE_NOEXT']
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surro-gate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dávid Halász
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-10 00:00:00.000000000 Z
11
+ date: 2019-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -106,6 +106,7 @@ files:
106
106
  - ext/surro-gate/selector_ext.h
107
107
  - lib/surro-gate.rb
108
108
  - lib/surro-gate/pair.rb
109
+ - lib/surro-gate/scoreboard.rb
109
110
  - lib/surro-gate/selector.rb
110
111
  - lib/surro-gate/version.rb
111
112
  - surro-gate.gemspec
@@ -128,8 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
129
  - !ruby/object:Gem::Version
129
130
  version: '0'
130
131
  requirements: []
131
- rubyforge_project:
132
- rubygems_version: 2.7.6
132
+ rubygems_version: 3.0.2
133
133
  signing_key:
134
134
  specification_version: 4
135
135
  summary: A generic purrpose TCP-to-TCP proxy in Ruby