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 +4 -4
- data/.travis.yml +0 -1
- data/README.md +0 -2
- data/ext/surro-gate/selector_ext.c +52 -86
- data/ext/surro-gate/selector_ext.h +1 -2
- data/lib/surro-gate/pair.rb +21 -1
- data/lib/surro-gate/scoreboard.rb +70 -0
- data/lib/surro-gate/selector.rb +2 -2
- data/lib/surro-gate/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 424ad5ad77841b6c66059f77feee8fe7ba7edf67b4c896af81932187e67793cc
|
4
|
+
data.tar.gz: b420bd8ff5148a1b65c326090e944e3b510f1e25bc247e6814a10a4bdcf07f44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6dcea2dcf0637437a8ea177aa24a4d80f34175b0f06d77253b5c4cb0d0df28e7bba676644c843d62d47f83f00d639e71b63273ccb5ba7c81136b848b3f30ab4
|
7
|
+
data.tar.gz: 93c7c0af5dd2558523e92987f2cf969cedde14ba11ba9ea4554f8200409fcdf5006eb4a1c18778f550ff6bb180306df7ddadee0edbf2a6ce0875b2a2f6dc0d42
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/surro-gate)
|
4
4
|
[](https://travis-ci.org/skateman/surro-gate)
|
5
|
-
[](https://gemnasium.com/skateman/surro-gate)
|
6
5
|
[](http://inch-ci.org/github/skateman/surro-gate)
|
7
6
|
[](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,
|
8
|
+
void epoll_register(int *epoll, VALUE socket) {
|
8
9
|
struct epoll_event ev;
|
9
|
-
ev.data.u64 = (
|
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,
|
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,
|
19
|
+
void epoll_rearm(int *epoll, VALUE socket, int events) {
|
19
20
|
struct epoll_event ev;
|
20
|
-
ev.data.u64 = (
|
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
|
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
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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,
|
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,
|
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
|
-
|
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
|
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
|
115
|
-
if (
|
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
|
-
|
122
|
-
|
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
|
135
|
-
int
|
106
|
+
static VALUE SurroGate_Selector_pop(VALUE self, VALUE left, VALUE right) {
|
107
|
+
int *selector;
|
136
108
|
|
137
|
-
VALUE
|
138
|
-
|
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
|
-
|
142
|
-
|
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
|
120
|
+
int i, *selector;
|
150
121
|
struct epoll_event events[256];
|
151
122
|
struct epoll_wait_args wait_args;
|
152
|
-
VALUE
|
123
|
+
VALUE socket;
|
153
124
|
|
154
|
-
VALUE
|
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
|
-
|
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
|
-
|
176
|
-
|
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
|
-
|
180
|
-
if (
|
181
|
-
|
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
|
-
|
187
|
-
if (
|
188
|
-
|
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
|
163
|
+
VALUE scoreboard = rb_iv_get(self, "@scoreboard");
|
199
164
|
rb_need_block();
|
200
|
-
return rb_block_call(
|
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,
|
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
|
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
|
data/lib/surro-gate/pair.rb
CHANGED
@@ -7,11 +7,31 @@ module SurroGate
|
|
7
7
|
def initialize(left, right)
|
8
8
|
@left = left
|
9
9
|
@right = right
|
10
|
-
|
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
|
data/lib/surro-gate/selector.rb
CHANGED
data/lib/surro-gate/version.rb
CHANGED
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
|
+
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:
|
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
|
-
|
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
|