surro-gate 1.0.4 → 1.0.5

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
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