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 +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
|
[![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,
|
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
|