minitcp 0.10.0 → 0.15.0
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/CHANGELOG.txt +20 -0
- data/README.md +37 -1
- data/VERSION +1 -1
- data/lib/minitcp.rb +47 -7
- data/samples/pxy.rb +429 -0
- data/samples/relay/README.md +24 -1
- data/samples/relay/relai_config.data +2 -1
- data/samples/relay/relaiproxy.rb +167 -68
- data/test.rb +38 -2
- metadata +13 -15
- data/samples/pingpongplot.rb +0 -26
- data/samples/plot.rb +0 -190
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40c86e0923a11e1d1399840594700ed14d087f5b
|
4
|
+
data.tar.gz: 25fc9a740519e40ed6ccf029cb986bb85e0e0a13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e59ae815447e1bd2639a3a49a8c536f9af7856c88a6c0861e643e671f78f68973eeec0ecb1cc1c067c6730e88d1bd3ee61b9633d7844550f4c09fcdee72d445
|
7
|
+
data.tar.gz: b204d6cb22237371a6bb93e449ee977564d7e8d9931ed86b0d1c76b15c1b310f726611f8f7168a6627f7a834fde673f6366361cdd933358ed6c3f433a0f962c5
|
data/CHANGELOG.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
0.15.0 : 2015-04-02 15:51:14 +0200
|
2
|
+
minitcp.rb : force data received to encding BINARY
|
3
|
+
0.14.0 : 2015-01-13 20:56:17 +0100
|
4
|
+
minitcp.rb : no audit, no log for tcp server
|
5
|
+
relaiproxy.rb : notraces
|
6
|
+
relai_config.data : test1 aded
|
7
|
+
minitcp.rb : no traces
|
8
|
+
0.13.0 : 2014-11-28 13:35:33 +0100
|
9
|
+
plot.rb : window resize enable
|
10
|
+
pingpongplot.rb : multiple url test
|
11
|
+
README.md : message agent expample
|
12
|
+
README.md : massage agent expalple
|
13
|
+
README.md : example message
|
14
|
+
README.md : example for agent message
|
15
|
+
0.12.0 : 2014-10-30 21:31:33 +0100
|
16
|
+
0.11.0 : 2014-10-30 21:30:28 +0100
|
17
|
+
README.md : ocpp
|
18
|
+
README.md : plugin doc
|
19
|
+
Rakefile.rb : version management
|
20
|
+
README.md : plugin ocpp description
|
1
21
|
0.10.0 : 2014-09-24 20:18:54 +0200
|
2
22
|
minitcp.rb : reveive_n_byte correction
|
3
23
|
0.9.0 : 2014-09-18 22:38:31 +0200
|
data/README.md
CHANGED
@@ -61,6 +61,28 @@ A UDP sender :
|
|
61
61
|
)
|
62
62
|
```
|
63
63
|
|
64
|
+
A Message agent :
|
65
|
+
Message Client:
|
66
|
+
```ruby
|
67
|
+
MClientAgent.run("localhost",2222) do |chan|
|
68
|
+
chan.send_message({date: Time.now.to_f})
|
69
|
+
chan.on_message do |mess|
|
70
|
+
puts "cli: receive: #{mess.inspect}"
|
71
|
+
chan.close
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
chan.on_timeout(10_000) { p "timeout" ; chan.close rescue nil }
|
75
|
+
chan.wait_end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
Message Server:
|
80
|
+
```ruby
|
81
|
+
MServerAgent.run(2222,"localhost",22) do |chan|
|
82
|
+
chan.on_message { |mess| p mess ; "ok" }
|
83
|
+
chan.wait_end
|
84
|
+
end
|
85
|
+
```
|
64
86
|
|
65
87
|
Docs: http://rubydoc.info/gems/minitcp
|
66
88
|
|
@@ -126,13 +148,27 @@ UDP
|
|
126
148
|
* **send_datagram(host,port,message)** : create a socket, send mesage and close socket (ca'nt receive a reply)
|
127
149
|
* **send_datagram_on_socket(socket,host,port,message)** : use existant socket for send a message to ip:port
|
128
150
|
|
151
|
+
Messages
|
152
|
+
===
|
153
|
+
Serveur and client ```MServerAgent``` and ```MClientAgent``` define a 'agent ' which
|
154
|
+
can communicate by messages.
|
155
|
+
|
156
|
+
Messages are ```ruby-data.inspect```, max size is 1 MByte.
|
157
|
+
* MClientAgent.run(host,port) : connect to a MServerAgent, for communicate by message
|
158
|
+
* MServerAgent.run(port,host,max-connections) : message server
|
159
|
+
|
160
|
+
in Agent, socket are extended with this capability :
|
161
|
+
* socket.send_message(data)
|
162
|
+
* socket.on_message { |data| .... ; ret_data} will send ret_data to sender if not nil
|
163
|
+
|
164
|
+
See test.rb for an example
|
129
165
|
|
130
166
|
TODO
|
131
167
|
==
|
132
168
|
|
133
169
|
* Serial line
|
134
170
|
* more socket primitive
|
135
|
-
|
171
|
+
* messages Agent : use Marchal instead of inspect/eval ....
|
136
172
|
|
137
173
|
Tests case
|
138
174
|
==
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.15.0
|
data/lib/minitcp.rb
CHANGED
@@ -11,9 +11,9 @@ require 'gserver'
|
|
11
11
|
|
12
12
|
|
13
13
|
module SocketReactive
|
14
|
-
|
14
|
+
def strempty() ''.force_encoding Encoding::BINARY end
|
15
15
|
def data_readed=(v) @data_readed=v end
|
16
|
-
def data_readed() @data_readed||=
|
16
|
+
def data_readed() @data_readed||=strempty end
|
17
17
|
|
18
18
|
# read n byte, block the caller, return nil if socket if close
|
19
19
|
# if block is defined, it is yield with data, method return whith the value of yield
|
@@ -29,7 +29,7 @@ module SocketReactive
|
|
29
29
|
loop do
|
30
30
|
#p ["waiting ",s,data_readed]
|
31
31
|
sd=s>1024 ? 1024 : s
|
32
|
-
data=(self.recv(sd) rescue nil)
|
32
|
+
data=(self.recv(sd) rescue (p $!;nil))
|
33
33
|
#p "nrec: w#{sizemax}/ rec:#{(data||'').size} / #{sd} old=#{data_readed.size} /// #{(data||'').size<70 ? data : "."}"
|
34
34
|
if data && data.size>0
|
35
35
|
self.data_readed=self.data_readed+data
|
@@ -75,7 +75,7 @@ module SocketReactive
|
|
75
75
|
Thread.new() do
|
76
76
|
begin
|
77
77
|
if self.data_readed.size>0
|
78
|
-
buff,self.data_readed=self.data_readed,
|
78
|
+
buff,self.data_readed=self.data_readed,strempty
|
79
79
|
yield(buff)
|
80
80
|
end
|
81
81
|
loop do
|
@@ -317,16 +317,16 @@ end
|
|
317
317
|
# Run a TCP serveur, with a max connection simultaneous,
|
318
318
|
# When connection succes, call the bloc given with socket (extended by SocketReactive).
|
319
319
|
#
|
320
|
-
# MServer( "8080" , "0.0.0.0" ,1) { |socket| loop { p socket.gets} }
|
320
|
+
# MServer.new( "8080" , "0.0.0.0" ,1) { |socket| loop { p socket.gets} }
|
321
321
|
class MServer < GServer
|
322
322
|
def self.service(port,host,max,&b)
|
323
323
|
srv=new(port,host,max,&b)
|
324
|
-
srv.audit =
|
324
|
+
srv.audit = false
|
325
325
|
srv.start
|
326
326
|
srv
|
327
327
|
end
|
328
328
|
def initialize(port,host,max=1,&b)
|
329
|
-
super(port,host,max)
|
329
|
+
super(port,host,max,nil)
|
330
330
|
@bloc=b
|
331
331
|
end
|
332
332
|
def serve( io )
|
@@ -339,3 +339,43 @@ class MServer < GServer
|
|
339
339
|
end
|
340
340
|
end
|
341
341
|
|
342
|
+
##########################################################
|
343
|
+
# messages stream
|
344
|
+
##########################################################
|
345
|
+
|
346
|
+
module SocketMessage
|
347
|
+
def on_message(timeout=nil,&b)
|
348
|
+
on_n_receive(6) do |head|
|
349
|
+
len=head.to_i
|
350
|
+
received_n_timeout(len,10_000) do |data|
|
351
|
+
response=b.call(eval(data))
|
352
|
+
send(response) if response
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
def send_message(message)
|
357
|
+
data=message.inspect
|
358
|
+
send(("%6d" % data.size)+data,0)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class MClientAgent
|
363
|
+
def self.run(host,port,&b)
|
364
|
+
me=MClientAgent.new
|
365
|
+
MClient.run_continious(host,port,10_000) do |so|
|
366
|
+
so.extend(SocketMessage)
|
367
|
+
me.instance_eval { b.call(so) }
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
class MServerAgent
|
373
|
+
def self.run(port,host,n,&b)
|
374
|
+
me=MClientAgent.new
|
375
|
+
MServer.service( port , host ,n) do |so|
|
376
|
+
so.extend(SocketMessage)
|
377
|
+
me.instance_eval { b.call(so) }
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
data/samples/pxy.rb
ADDED
@@ -0,0 +1,429 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# LGPL
|
3
|
+
####################################################
|
4
|
+
# proxy.rb : pure tcp proxy, for dev/admin/fun :)
|
5
|
+
#
|
6
|
+
# Usage :
|
7
|
+
# > ruby proxy.rb target-hostname target-port [mode]
|
8
|
+
# mode= ascii/bin/none : style of printing
|
9
|
+
####################################################
|
10
|
+
# LGPL, Author: Regis d'Aubarede <regis.aubarede@gmail.com>
|
11
|
+
#
|
12
|
+
##################################################### start minitcp
|
13
|
+
|
14
|
+
##############################################################
|
15
|
+
# minitcp.rb
|
16
|
+
##############################################################
|
17
|
+
|
18
|
+
require 'thread'
|
19
|
+
require 'timeout'
|
20
|
+
require 'socket'
|
21
|
+
require 'gserver'
|
22
|
+
|
23
|
+
|
24
|
+
module SocketReactive
|
25
|
+
|
26
|
+
def data_readed=(v) @data_readed=v end
|
27
|
+
def data_readed() @data_readed||="" end
|
28
|
+
|
29
|
+
# read n byte, block the caller, return nil if socket if close
|
30
|
+
# if block is defined, it is yield with data, method return whith the value of yield
|
31
|
+
# if looping is true, the method loop until socket close, (or current thread is killed)
|
32
|
+
def receive_n_bytes(sizemax,looping=false,&b)
|
33
|
+
s=sizemax
|
34
|
+
if self.data_readed.size>=sizemax
|
35
|
+
buff,self.data_readed=self.data_readed[0..sizemax-1],self.data_readed[sizemax..-1]
|
36
|
+
buff=b.call(buff) if block_given?
|
37
|
+
return buff unless looping
|
38
|
+
end
|
39
|
+
s=sizemax-self.data_readed.size
|
40
|
+
loop do
|
41
|
+
#p ["waiting ",s,data_readed]
|
42
|
+
sd=s>1024 ? 1024 : s
|
43
|
+
data=(self.recv(sd) rescue (p $!;nil))
|
44
|
+
#p "nrec: w#{sizemax}/ rec:#{(data||'').size} / #{sd} old=#{data_readed.size} /// #{(data||'').size<70 ? data : "."}"
|
45
|
+
if data && data.size>0
|
46
|
+
self.data_readed=self.data_readed+data
|
47
|
+
s=sizemax-self.data_readed.size
|
48
|
+
if s<=0
|
49
|
+
buff,self.data_readed=self.data_readed,""
|
50
|
+
s=sizemax
|
51
|
+
buff=b.call(buff) if block_given?
|
52
|
+
return buff unless looping
|
53
|
+
end
|
54
|
+
else
|
55
|
+
close rescue nil
|
56
|
+
break # socket close
|
57
|
+
end
|
58
|
+
end #loop
|
59
|
+
end
|
60
|
+
# wait n byte or timeout. if block is defined, it is yielded with data
|
61
|
+
# return nil if timeout/socket closed, or data if no bloc, or yield value
|
62
|
+
def received_n_timeout(sizemax,timeout_ms,&b)
|
63
|
+
timeout(timeout_ms/1000.0) {
|
64
|
+
ret=receive_n_bytes(sizemax,false,&b)
|
65
|
+
return ret
|
66
|
+
}
|
67
|
+
rescue Timeout::Error
|
68
|
+
return nil
|
69
|
+
rescue Exception => e
|
70
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def received_any_timeout(sizemax,timeout_ms)
|
74
|
+
timeout(timeout_ms/1000.0) {
|
75
|
+
return recv(sizemax)
|
76
|
+
}
|
77
|
+
rescue Timeout::Error
|
78
|
+
return nil
|
79
|
+
rescue Exception => e
|
80
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
81
|
+
end
|
82
|
+
|
83
|
+
# async wait and read data on socket, yield values readed,
|
84
|
+
# return thread spawned, which can be kill
|
85
|
+
def on_any_receive()
|
86
|
+
Thread.new() do
|
87
|
+
begin
|
88
|
+
if self.data_readed.size>0
|
89
|
+
buff,self.data_readed=self.data_readed,""
|
90
|
+
yield(buff)
|
91
|
+
end
|
92
|
+
loop do
|
93
|
+
data=(self.recv(64*1024) rescue nil)
|
94
|
+
data && data.size>0 ? yield(data) : break
|
95
|
+
end
|
96
|
+
rescue Exception => e
|
97
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
98
|
+
end
|
99
|
+
close rescue nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
# async yield on received n bytes
|
105
|
+
# return thread spawned, which can be kill
|
106
|
+
def on_n_receive(sizemax=1,&b)
|
107
|
+
Thread.new() do
|
108
|
+
begin
|
109
|
+
receive_n_bytes(sizemax,true,&b)
|
110
|
+
rescue Exception => e
|
111
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# read until separator reached, block the caller, return nil if socket is close
|
117
|
+
# if block is defined, it is yield with data, method return whith the value of yield
|
118
|
+
# if looping is true, the method loop until socket close, (or current thread is killed)
|
119
|
+
# this read some extra data. they can be retrieve with in socket.data_readed.
|
120
|
+
# data_readed is use for next calls to receives_n_byte/receive_sep
|
121
|
+
def receive_sep(separator,sizemax=1024,looping=false,&b)
|
122
|
+
if self.data_readed.size>0
|
123
|
+
a=self.data_readed.split(separator,2)
|
124
|
+
while a.size>1
|
125
|
+
buff= a.size>2 ? a[0..-2] : a.first
|
126
|
+
self.data_readed=a.last
|
127
|
+
buff=b.call(buff) if block_given?
|
128
|
+
return buff unless looping
|
129
|
+
a=self.data_readed.split(separator,2)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
loop do
|
133
|
+
data=(self.recv(sizemax-self.data_readed.size) rescue nil)
|
134
|
+
if data && data.size>0
|
135
|
+
self.data_readed=self.data_readed+data
|
136
|
+
a=(self.data_readed).split(separator,2)
|
137
|
+
while a.size>1
|
138
|
+
buff= a.size>2 ? a[0..-2] : a.first
|
139
|
+
self.data_readed=a.last
|
140
|
+
buff=b.call(buff) if block_given?
|
141
|
+
return buff unless looping
|
142
|
+
a=(self.data_readed).split(separator,2)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
close rescue nil
|
146
|
+
break
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# async yield on received data until end-buffer string
|
152
|
+
# end-buffer can be string or regexp (args of data.split(,2))
|
153
|
+
# return thread spawned, which can be kill
|
154
|
+
# this read some extra data. they can be retrieve with in socket.data_readed.
|
155
|
+
# data_readed is use for next calls to receives_n_byte/receive_sep
|
156
|
+
def on_receive_sep(separator,sizemax=1024,&b)
|
157
|
+
Thread.new() do
|
158
|
+
begin
|
159
|
+
receive_sep(separator,sizemax,looping=true,&b)
|
160
|
+
rescue Exception => e
|
161
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# async yield after a duration, if socket is open
|
167
|
+
# return thread spawned, which can be kill
|
168
|
+
def after(duration_ms)
|
169
|
+
Thread.new() do
|
170
|
+
begin
|
171
|
+
sleep(duration_ms/1000.0)
|
172
|
+
yield unless self.connected?()
|
173
|
+
rescue Exception => e
|
174
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# async yield periodicaly, if socket is open
|
180
|
+
# return thread spawned, which can be kill
|
181
|
+
def on_timer(value=1000)
|
182
|
+
Thread.new() {
|
183
|
+
begin
|
184
|
+
nbtick=(value/TICK)+1
|
185
|
+
loop do
|
186
|
+
i=0
|
187
|
+
sleep(TICK/1000.0) while self.connected?() && (i+=1)<nbtick
|
188
|
+
self.connected?() ? yield() : break
|
189
|
+
end
|
190
|
+
rescue Exception => e
|
191
|
+
$stdout.puts "#{e} :\n #{e.backtrace.join("\n ")}"
|
192
|
+
end
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
# wait until curent socket is close.
|
197
|
+
def wait_end()
|
198
|
+
begin
|
199
|
+
loop do
|
200
|
+
sleep(TICK/1000.0) while (self.connected?() rescue nil)
|
201
|
+
break
|
202
|
+
end
|
203
|
+
rescue Exception => e
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Test if a socket is open. (use socket.remote_address() !)
|
208
|
+
def connected?()
|
209
|
+
(self.remote_address rescue nil) ? true : false
|
210
|
+
end
|
211
|
+
# duration of sleep when active wait (wait_end,on_timer...)
|
212
|
+
TICK=600
|
213
|
+
|
214
|
+
def self.make_socket_reactive(socket)
|
215
|
+
socket.extend(SocketReactive)
|
216
|
+
socket.data_readed=""
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Assure connection to server, extend socket connection by SocketReactive module.
|
221
|
+
#
|
222
|
+
# MClient.run_one_shot("localhost",2200) do |socket| .. end.join
|
223
|
+
#
|
224
|
+
# MClient.run_continous("localhost",2200,6000) do |socket| .. end.join
|
225
|
+
#
|
226
|
+
class MClient
|
227
|
+
# maintain a conntection to a TCP serveur, sleep timer_interconnection_ms millisecondes
|
228
|
+
# beetwen each reconnections
|
229
|
+
def self.run_continious(host,port,timer_interconnection_ms,&b)
|
230
|
+
Thread.new do
|
231
|
+
loop { run_one_shot(host,port,&b).join ; sleep timer_interconnection_ms/1000.0 }
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.run_continous(host,port,timer_interconnection,&b)
|
236
|
+
self.run_continious(host,port,timer_interconnection,&b)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Connecte to a TCP server, call block with client socket if connection sucess.
|
240
|
+
# enssure close connection after end of block
|
241
|
+
def self.run_one_shot(host="localhost",port=80)
|
242
|
+
begin
|
243
|
+
sleep(0.03) # give some time for server ready (for test...)
|
244
|
+
socket = TCPSocket.new(host,port)
|
245
|
+
rescue
|
246
|
+
puts "not connected to #{host}:#{port}: " + $!.to_s
|
247
|
+
return (Thread.new {})
|
248
|
+
end
|
249
|
+
SocketReactive::make_socket_reactive(socket)
|
250
|
+
Thread.new do
|
251
|
+
begin
|
252
|
+
yield(socket)
|
253
|
+
rescue Exception => e
|
254
|
+
puts "#{e}\n #{e.backtrace.join("\n ")}"
|
255
|
+
ensure
|
256
|
+
socket.close() rescue nil
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
# Assure connection to server, extend socket connection by SocketReactive module.
|
264
|
+
#
|
265
|
+
# MClient.run_one_shot("localhost",2200) do |socket| .. end.join
|
266
|
+
#
|
267
|
+
# MClient.run_continous("localhost",2200,6000) do |socket| .. end.join
|
268
|
+
#
|
269
|
+
class UDPAgent
|
270
|
+
# maintain a conntection to a TCP serveur, sleep timer_interconnection_ms millisecondes
|
271
|
+
# beetwen each reconnections
|
272
|
+
def self.send_datagram(host,port,mess)
|
273
|
+
sock = UDPSocket.new
|
274
|
+
#p ["sock.send",mess, 0, host, port]
|
275
|
+
sock.send(mess, 0, host, port)
|
276
|
+
sock.close
|
277
|
+
end
|
278
|
+
def self.send_datagram_on_socket(socket,host,port,mess)
|
279
|
+
socket.send(mess, 0, host, port)
|
280
|
+
end
|
281
|
+
|
282
|
+
Thread.abort_on_exception=true
|
283
|
+
|
284
|
+
# send datagram on timer
|
285
|
+
def self.on_timer(periode,options)
|
286
|
+
Thread.new do
|
287
|
+
sleep periode/1000.0
|
288
|
+
sock = UDPSocket.new
|
289
|
+
if options[:port]
|
290
|
+
sock.bind("0.0.0.0", options[:port])
|
291
|
+
end
|
292
|
+
loop do
|
293
|
+
rep=IO.select([sock],nil,nil,periode/1000.0)
|
294
|
+
#puts "IO.SELECT => #{rep}"
|
295
|
+
if rep
|
296
|
+
Thread.new {
|
297
|
+
data,peer=sock.recvfrom(1024)
|
298
|
+
options[:on_receive].call(data,peer,sock)
|
299
|
+
} if options[:on_receive]
|
300
|
+
elsif options[:on_timer]
|
301
|
+
h=options[:on_timer].call()
|
302
|
+
self.send_datagram_on_socket(sock,h[:host], h[:port],h[:mess]) if h && h[:mess] && h[:host] && h[:port]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
# recieved UDP datagramme, bloc can ellaborate a reply, which will be sending to client
|
308
|
+
def self.on_datagramme(host,port)
|
309
|
+
serv = UDPSocket.new
|
310
|
+
serv.bind(host, port)
|
311
|
+
Thread.new do
|
312
|
+
loop do
|
313
|
+
begin
|
314
|
+
Thread.new(*serv.recvfrom(1024)) do |data,peer| # peer=["AF_INET", 59340, "127.0.0.1", "127.0.0.1"]
|
315
|
+
proto,cli_port,srv_addr,cli_addr=*peer
|
316
|
+
response=yield(data,cli_addr,cli_port)
|
317
|
+
self.send_datagram_on_socket(serv,cli_addr,cli_port,response) if response
|
318
|
+
end
|
319
|
+
rescue Exception => e
|
320
|
+
puts "#{e}\n #{e.backtrace.join("\n ")}"
|
321
|
+
ensure
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# Run a TCP serveur, with a max connection simultaneous,
|
329
|
+
# When connection succes, call the bloc given with socket (extended by SocketReactive).
|
330
|
+
#
|
331
|
+
# MServer.new( "8080" , "0.0.0.0" ,1) { |socket| loop { p socket.gets} }
|
332
|
+
class MServer < GServer
|
333
|
+
def self.service(port,host,max,&b)
|
334
|
+
srv=new(port,host,max,&b)
|
335
|
+
srv.audit = true
|
336
|
+
srv.start
|
337
|
+
srv
|
338
|
+
end
|
339
|
+
def initialize(port,host,max=1,&b)
|
340
|
+
super(port,host,max)
|
341
|
+
@bloc=b
|
342
|
+
end
|
343
|
+
def serve( io )
|
344
|
+
SocketReactive::make_socket_reactive(io)
|
345
|
+
begin
|
346
|
+
@bloc.call(io)
|
347
|
+
rescue Exception => e
|
348
|
+
puts "Error in Mserver block: #{e} :\n #{e.backtrace.join("\n ")}"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
##########################################################
|
354
|
+
# messages stream
|
355
|
+
##########################################################
|
356
|
+
|
357
|
+
module SocketMessage
|
358
|
+
def on_message(timeout=nil,&b)
|
359
|
+
on_n_receive(6) do |head|
|
360
|
+
len=head.to_i
|
361
|
+
received_n_timeout(len,10_000) do |data|
|
362
|
+
response=b.call(eval(data))
|
363
|
+
send(response) if response
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
def send_message(message)
|
368
|
+
data=message.inspect
|
369
|
+
send(("%6d" % data.size)+data,0)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
class MClientAgent
|
374
|
+
def self.run(host,port,&b)
|
375
|
+
me=MClientAgent.new
|
376
|
+
MClient.run_continious(host,port,10_000) do |so|
|
377
|
+
so.extend(SocketMessage)
|
378
|
+
me.instance_eval { b.call(so) }
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
class MServerAgent
|
384
|
+
def self.run(port,host,n,&b)
|
385
|
+
me=MClientAgent.new
|
386
|
+
MServer.service( port , host ,n) do |so|
|
387
|
+
so.extend(SocketMessage)
|
388
|
+
me.instance_eval { b.call(so) }
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
##################################################### end minitcp
|
394
|
+
|
395
|
+
$host,$port,$opt=ARGV[0]||"localhost",ARGV[1]||80,ARGV[2]||"ascii"
|
396
|
+
puts "Server on port 2200, proxy to #{$host}:#{$port}..."
|
397
|
+
|
398
|
+
|
399
|
+
MServer.service(2200,"0.0.0.0",22) do |s_cli|
|
400
|
+
puts "> ======== client Connected ========"
|
401
|
+
srv=MClient.run_one_shot($host,$port) do |s_srv|
|
402
|
+
puts "< ======== server Concected ========"
|
403
|
+
s_srv.on_any_receive { |data| spy 1,data; s_cli.print data }
|
404
|
+
s_cli.on_any_receive { |data| spy 2,data; s_srv.print data}
|
405
|
+
s_srv.wait_end
|
406
|
+
s_cli.close rescue nil
|
407
|
+
end
|
408
|
+
s_cli.wait_end
|
409
|
+
p "end cli, stop proxy"
|
410
|
+
srv.kill
|
411
|
+
end
|
412
|
+
|
413
|
+
def spy(sens,data)
|
414
|
+
return if $opt=="none"
|
415
|
+
prefix=(sens==1 ? "< " : "> ")
|
416
|
+
if $opt=="ascii"
|
417
|
+
data.each_line {|line| puts "#{prefix}#{line.chomp}" }
|
418
|
+
else
|
419
|
+
data.chars.each_slice(16) do |aline|
|
420
|
+
a=(aline.map { |char| "%02X " % char.ord }).join.ljust(16*3)+prefix+
|
421
|
+
aline.map { |char| (char.ord>30 ? char : "~") }.join()
|
422
|
+
puts "#{prefix}#{a}"
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
sleep
|
428
|
+
|
429
|
+
|
data/samples/relay/README.md
CHANGED
@@ -26,16 +26,39 @@ Server ---------------> | proxy-relai | <------//--------| relai | -----------
|
|
26
26
|
internet server server-in-intranet intranet hosts
|
27
27
|
```
|
28
28
|
|
29
|
+
Plugin
|
30
|
+
======
|
31
|
+
|
32
|
+
Relai receive http request for an intranet server.
|
33
|
+
Plugin must be writing for find ip:port/path for the host target.
|
34
|
+
this can varying with http-subprotocole used.
|
35
|
+
|
36
|
+
occp plugin is the first plugin used :
|
37
|
+
* requests servied by this plugin are SOAP, header contain a field ```<ChargeBoxId>name-equipment</ChargeBoxId>```
|
38
|
+
* a local config file give url for each id
|
39
|
+
* the plugin will :
|
40
|
+
1) parse the request for finding the value of ChargeBoxId (regexp)
|
41
|
+
2) find ip:port/path for the itranet-server adressed
|
42
|
+
3) modify the path in the GET http command
|
29
43
|
|
30
44
|
Usage
|
31
45
|
=====
|
32
46
|
Extranet:
|
47
|
+
|
48
|
+
```
|
33
49
|
> ruby relaiproxy.rb proxyhttp proxy-hostname proxy-port
|
50
|
+
```
|
34
51
|
|
35
52
|
Intranet:
|
53
|
+
|
54
|
+
```
|
36
55
|
> vi relai_config.rb
|
56
|
+
```
|
57
|
+
|
58
|
+
```
|
37
59
|
> ruby relaiproxy.rb relai proxy-ip proxy-port plugin-name
|
60
|
+
```
|
38
61
|
|
39
|
-
(actualy ocpp is
|
62
|
+
(actualy 'ocpp' is only plugin disponible)
|
40
63
|
|
41
64
|
|
data/samples/relay/relaiproxy.rb
CHANGED
@@ -27,67 +27,106 @@ Server ---------------> | proxy-relai | <------//--------| relai | -----------
|
|
27
27
|
internet server server-in-intranet intranet hosts
|
28
28
|
=end
|
29
29
|
|
30
|
-
|
31
|
-
require_relative 'minitcp/lib/minitcp.rb'
|
30
|
+
require 'minitcp'
|
31
|
+
#require_relative 'minitcp/lib/minitcp.rb'
|
32
32
|
|
33
33
|
if ARGV.size<1
|
34
34
|
puts"Usage>"
|
35
|
-
puts" #{$0} type
|
35
|
+
puts" #{$0} type hostname port"
|
36
36
|
puts" #{$0} proxyhttp proxy-hostname proxy-port"
|
37
|
-
puts" #{$0} relai proxy-saia-ip proxy-
|
37
|
+
puts" #{$0} relai proxy-saia-ip proxy-port plugin"
|
38
38
|
exit(1)
|
39
39
|
end
|
40
40
|
|
41
41
|
$opt,$host,$port=ARGV[0]||"proxyhttp",ARGV[1]||"localhost",ARGV[2]||80
|
42
42
|
|
43
43
|
NBDIGITHEAD=8
|
44
|
-
QUEUE_SIZE=
|
44
|
+
QUEUE_SIZE=10
|
45
45
|
|
46
46
|
def sformat(socket,mess)
|
47
|
-
|
47
|
+
puts "sformat message len=#{mess.size} #{mess.inspect[0..30]}..."
|
48
|
+
data=("%-#{NBDIGITHEAD}d%s" % [mess.size,mess])
|
49
|
+
socket.send(data,0)
|
50
|
+
end
|
51
|
+
|
52
|
+
def sformat0(socket,mess)
|
53
|
+
data=("%-#{NBDIGITHEAD}d%s" % [mess.size,mess])
|
54
|
+
l=socket.send(data,0)
|
48
55
|
end
|
49
56
|
def receive(socket)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
57
|
+
log "r1 len=#{NBDIGITHEAD} #{socket}"
|
58
|
+
resp_length= socket.receive_n_bytes(NBDIGITHEAD)
|
59
|
+
return nil unless resp_length
|
60
|
+
len =resp_length.strip.to_i
|
61
|
+
log "header: #{resp_length} => #{len}"
|
62
|
+
(len>0) ? socket.receive_n_bytes(len) : ""
|
63
|
+
end
|
64
|
+
def receive_to(socket,to=1000)
|
65
|
+
begin
|
66
|
+
timeout(to/1000.0) {
|
67
|
+
#log "r1 len=#{NBDIGITHEAD} #{socket}"
|
68
|
+
resp_length= socket.receive_n_bytes(NBDIGITHEAD)
|
69
|
+
return nil unless resp_length
|
70
|
+
len =resp_length.strip.to_i
|
71
|
+
#log "header: #{resp_length} => #{len}"
|
72
|
+
(len>0) ? socket.receive_n_bytes(len) : ""
|
73
|
+
}
|
74
|
+
rescue Exception => e
|
75
|
+
return(nil)
|
76
|
+
end
|
54
77
|
end
|
55
78
|
def log(t) puts "%10s | %s" % [Time.now.to_s,t] end
|
56
79
|
|
57
80
|
if $opt=="proxyhttp"
|
58
81
|
##################################################################################
|
59
|
-
## P R O X Y
|
82
|
+
## P R O X Y : extranet side
|
60
83
|
##################################################################################
|
61
84
|
|
62
85
|
$client_sockets ={}
|
63
86
|
$queue=Queue.new
|
64
87
|
############# Proxy serveur http saia >>> machine distante #######################
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
begin relai=$queue.pop end until $client_sockets[relai]
|
88
|
+
def relai_command(mess)
|
89
|
+
relai=nil
|
69
90
|
begin
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
log("wait response...")
|
80
|
-
response= (timeout(5) { receive(relai) } rescue nil)
|
81
|
-
log(response!=nil ? "response ok" : "timeout") unless response
|
82
|
-
s_cli.write(response ? response : "HTTP/1.0 500 NOK\r\n\r\n")
|
83
|
-
else
|
84
|
-
s_cli.write( "HTTP/1.0 501 NOK\r\n\r\n")
|
85
|
-
end
|
91
|
+
loop {
|
92
|
+
begin relai=$queue.pop end until $client_sockets[relai]
|
93
|
+
sformat(relai,"SDV")
|
94
|
+
break if receive_to(relai,1000)!=nil
|
95
|
+
}
|
96
|
+
log("getted relai #{relai}")
|
97
|
+
sformat(relai,mess)
|
98
|
+
log("wait response...")
|
99
|
+
receive_to(relai,9000)
|
86
100
|
ensure
|
87
|
-
$queue.push(relai)
|
101
|
+
$queue.push(relai) if relai
|
88
102
|
end
|
89
103
|
end
|
90
104
|
|
105
|
+
MServer.service($port.to_i,"0.0.0.0",22) do |s_cli|
|
106
|
+
log("telecommande")
|
107
|
+
timeout(10) {
|
108
|
+
begin
|
109
|
+
header=s_cli.receive_sep("\r\n\r\n")
|
110
|
+
#log("request header=#{header.inspect}")
|
111
|
+
if header.match(/^Content-Length: (\d+)/i) || "0"=~/(.)/
|
112
|
+
length=$1.strip.to_i
|
113
|
+
#log("length body==#{length}")
|
114
|
+
body= length>0 ? s_cli.receive_n_bytes(length) : ""
|
115
|
+
#log("request body=#{body.inspect}")
|
116
|
+
mess="#{header}\r\n\r\n#{body}"
|
117
|
+
log("transmit request...")
|
118
|
+
response=relai_command(mess)
|
119
|
+
log(response!=nil ? "response ok" : "timeout") unless response
|
120
|
+
s_cli.write(response ? response : "HTTP/1.0 500 NOK\r\n\r\n")
|
121
|
+
else
|
122
|
+
s_cli.write( "HTTP/1.0 501 NOK\r\n\r\n")
|
123
|
+
end
|
124
|
+
rescue Exception => e
|
125
|
+
puts "global error: #{e} #{}"
|
126
|
+
end
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
91
130
|
############# serveur http machine distante #######################
|
92
131
|
|
93
132
|
MServer.service($port.to_i+1,"0.0.0.0",22) do |s_cli|
|
@@ -99,17 +138,48 @@ MServer.service($port.to_i+1,"0.0.0.0",22) do |s_cli|
|
|
99
138
|
$client_sockets.delete(s_cli)
|
100
139
|
end
|
101
140
|
|
141
|
+
#-- signe de vie sur chaque socket du pool
|
142
|
+
|
143
|
+
Thread.new { loop {
|
144
|
+
begin relai=$queue.pop end until $client_sockets[relai]
|
145
|
+
#puts "testing #{relai}..."
|
146
|
+
sformat0(relai,"SDV")
|
147
|
+
receive_to(relai,1000)
|
148
|
+
sleep(0.1)
|
149
|
+
if $client_sockets[relai]
|
150
|
+
$queue.push(relai)
|
151
|
+
sleep 5
|
152
|
+
else
|
153
|
+
puts "testing socket pool: nok"
|
154
|
+
end
|
155
|
+
} }
|
102
156
|
else
|
103
157
|
|
104
158
|
##################################################################################
|
105
|
-
## R E L A Y
|
159
|
+
## R E L A Y : intranet side
|
106
160
|
##################################################################################
|
107
161
|
CONF="relai_config.data"
|
108
|
-
plugin=ARGV.last||"ocpp"
|
109
|
-
p plugin
|
162
|
+
$plugin=ARGV.last||"ocpp"
|
110
163
|
$config=nil
|
111
164
|
$configtime=nil
|
112
|
-
|
165
|
+
=begin
|
166
|
+
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
|
167
|
+
<soap:Header>
|
168
|
+
<chargeBoxIdentity xmlns="urn://Ocpp/Cp/2012/06/">TEST1</chargeBoxIdentity>
|
169
|
+
<Action xmlns="http://www.w3.org/2005/08/addressing">/ChangeAvailability</Action>
|
170
|
+
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:4efc4b17-6fc0-4a91-bf0b-153ecbc03cd0</MessageID>
|
171
|
+
<To xmlns="http://www.w3.org/2005/08/addressing">http://localhost:7700/</To>
|
172
|
+
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
|
173
|
+
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
|
174
|
+
</ReplyTo>
|
175
|
+
</soap:Header>
|
176
|
+
<soap:Body><changeAvailabilityRequest xmlns="urn://Ocpp/Cp/2012/06/">
|
177
|
+
<connectorId>1</connectorId>
|
178
|
+
<type>Operative</type>
|
179
|
+
</changeAvailabilityRequest>
|
180
|
+
</soap:Body>
|
181
|
+
</soap:Envelope>
|
182
|
+
=end
|
113
183
|
def load_config()
|
114
184
|
return if $configtime!=nil && $configtime.to_f == File.mtime(CONF).to_f
|
115
185
|
begin
|
@@ -121,58 +191,87 @@ def load_config()
|
|
121
191
|
log("Error loading configration : #{$!}")
|
122
192
|
end
|
123
193
|
end
|
124
|
-
|
194
|
+
def verify_request_ocpp(request)
|
195
|
+
(log("request does not contain ChargeBoxId0");return false) unless request =~/chargeBoxIdentity/i
|
196
|
+
return(true)
|
197
|
+
end
|
125
198
|
def transform_ocpp(request)
|
126
199
|
load_config
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
200
|
+
(log("request does not contain valid ChargeBoxId");return nil) unless request =~ /chargeBoxIdentity.*?>(.*?)<\/.*?chargeBoxIdentity/
|
201
|
+
chargeboxIdentity=$1.strip
|
202
|
+
ip=$config[chargeboxIdentity] # [ip,port,path]
|
203
|
+
unless ip
|
204
|
+
p request
|
205
|
+
log("unknown CS #{chargeboxIdentity} in config")
|
206
|
+
nil
|
207
|
+
else
|
208
|
+
#request.gsub!(
|
209
|
+
# %r{(<To[^>]*>http://)([^<]*)(</To>)},
|
210
|
+
# "\\1#{ip[0]}:#{ip[1]}#{ip[2]}\\3"
|
211
|
+
#)
|
212
|
+
#puts request
|
213
|
+
ip+[request] # return [ip, port, path, request]
|
214
|
+
end
|
137
215
|
end
|
138
216
|
|
139
217
|
def transmit(ip,port=nil,path=nil,request=nil)
|
140
|
-
return "HTTP/1.0 404 NOK\r\n\r\n"
|
141
|
-
|
218
|
+
return "HTTP/1.0 404 NOK\r\n\r\n" unless request
|
219
|
+
|
220
|
+
#log("send data <#{request.inspect[0..70]}...\n > to #{ip}:#{port}#{path} len=#{request.size}")
|
142
221
|
response=nil
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
222
|
+
begin
|
223
|
+
timeout(5) do
|
224
|
+
MClient.run_one_shot(ip,port) { |client|
|
225
|
+
client.send(request,0)
|
226
|
+
header=client.receive_sep("\r\n\r\n")
|
227
|
+
if header=~/Content-Length: (\d+)/i && $1.to_i>0
|
228
|
+
log( "receive data with content-length #{$1}")
|
229
|
+
begin
|
230
|
+
data_response=client.received_timeout($1.to_i,3000)
|
231
|
+
rescue
|
232
|
+
log($!.to_s)
|
233
|
+
data_response="ERROR_TIMEOUT"
|
234
|
+
end
|
235
|
+
else
|
236
|
+
puts "until close"
|
237
|
+
rep=""
|
238
|
+
rep+=(a=client.receive_any(1000_000)) until a==nil
|
239
|
+
data_response=rep
|
240
|
+
end
|
241
|
+
#log( "data_response="+data_response)
|
242
|
+
response=header+"\r\n\r\n" + data_response
|
243
|
+
}.join
|
244
|
+
response
|
155
245
|
end
|
156
|
-
|
157
|
-
|
246
|
+
rescue Exception => e
|
247
|
+
p e
|
248
|
+
nil
|
249
|
+
end
|
158
250
|
end
|
159
251
|
|
160
252
|
QUEUE_SIZE.times do
|
161
253
|
MClient.run_continious($host,$port.to_i+1,1000) do |socket|
|
162
254
|
nbr=0
|
255
|
+
puts "connected..."
|
163
256
|
socket.on_n_receive(NBDIGITHEAD) do |header|
|
164
|
-
p header
|
257
|
+
#p header
|
165
258
|
nbr+=1
|
166
259
|
len=header.strip.to_i
|
167
260
|
#p len
|
168
261
|
request=socket.receive_n_bytes(len)
|
169
262
|
#p request
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
263
|
+
if request!="SDV" && send("verify_request_#{$plugin}",request)
|
264
|
+
ip,port,path,request=send("transform_#{$plugin}",request)
|
265
|
+
response= transmit(ip,port,path,request)
|
266
|
+
puts "\n\nreplay with len=#{(response||"").size} <<<\n#{(response.inspect||"")[0..150]}..#{(response.inspect||"")[-40..-1]}\n>>"
|
267
|
+
sformat( socket, response ? response : "NOK #{Time.now}\r\n")
|
268
|
+
else
|
269
|
+
sformat(socket,"OK")
|
270
|
+
print "."
|
271
|
+
end
|
174
272
|
end
|
175
273
|
socket.wait_end
|
274
|
+
puts "deconnected."
|
176
275
|
end
|
177
276
|
end
|
178
277
|
|
data/test.rb
CHANGED
@@ -42,7 +42,7 @@ if ARGV.size==0 || ARGV[0]=="2"
|
|
42
42
|
(socket.close; next) if s!="e"
|
43
43
|
size=data.to_i
|
44
44
|
puts " Server waiting for #{size} Bytes of data"
|
45
|
-
socket.
|
45
|
+
socket.received_n_timeout(size,100_000) do |data|
|
46
46
|
puts " Server recieved buffer : #{data.size} Bytes"
|
47
47
|
puts " emit ack..."
|
48
48
|
socket.send("o",0)
|
@@ -61,7 +61,7 @@ if ARGV.size==0 || ARGV[0]=="2"
|
|
61
61
|
s,data=data[0..(1024-1)],data[1024..-1]
|
62
62
|
socket.send s,0
|
63
63
|
end
|
64
|
-
p socket.
|
64
|
+
p socket.received_n_timeout(1,[size/1000,1000].max) ? "ack ok" : "!!! timeout ack"
|
65
65
|
#puts "\n"*7
|
66
66
|
}
|
67
67
|
p "end client"
|
@@ -189,4 +189,40 @@ if ARGV.size==0 || ARGV[0]=="5"
|
|
189
189
|
sleep 10
|
190
190
|
end
|
191
191
|
|
192
|
+
if ARGV.size==0 || ARGV[0]=="6"
|
193
|
+
th=MServerAgent.run(2222,"localhost",22) do |chan|
|
194
|
+
puts "sv: connect"
|
195
|
+
@lchan||={}
|
196
|
+
@lchan[chan]=chan
|
197
|
+
chan.on_message do |mess|
|
198
|
+
puts "sv: broadcast #{mess.inspect}..."
|
199
|
+
@lchan.keys.each {|chan1| chan1.send_message(mess) if chan1!=chan }
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
chan.wait_end
|
203
|
+
@lchan.delete(chan)
|
204
|
+
end
|
205
|
+
lth=[]
|
206
|
+
5.times {
|
207
|
+
puts "####################### Run Client ########################"
|
208
|
+
lth << MClientAgent.run("localhost",2222) do |chan|
|
209
|
+
nb=0
|
210
|
+
chan.on_timer(100*rand(5..15)) {
|
211
|
+
chan.send_message(["C",1,2,1.2,Time.now.to_f,true])
|
212
|
+
nb+=1
|
213
|
+
(chan.close rescue nil)if nb>50
|
214
|
+
}
|
215
|
+
chan.on_message { |mess| p "cli: receive: #{mess.inspect}" ; nil}
|
216
|
+
chan.wait_end
|
217
|
+
puts "client closed"
|
218
|
+
end
|
219
|
+
sleep rand(1..2)
|
220
|
+
}
|
221
|
+
sleep 10
|
222
|
+
puts "\n\n############# Kill all agents...\n\n"
|
223
|
+
lth.each { |th| th.kill}
|
224
|
+
th.shutdown
|
225
|
+
sleep 2
|
226
|
+
end
|
227
|
+
|
192
228
|
puts "Test End !"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Regis d'Aubarede
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
A DSL for programming little Tcp client and server
|
@@ -18,25 +18,24 @@ extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- CHANGELOG.txt
|
21
|
-
- lib/minitcp.rb
|
22
21
|
- LICENSE
|
23
|
-
- minitcp.gemspec
|
24
|
-
- Rakefile.rb
|
25
22
|
- README.md
|
23
|
+
- Rakefile.rb
|
24
|
+
- VERSION
|
25
|
+
- lib/minitcp.rb
|
26
|
+
- minitcp.gemspec
|
27
|
+
- samples/README.md
|
26
28
|
- samples/name_server.rb
|
27
|
-
- samples/pingpongplot.rb
|
28
|
-
- samples/plot.rb
|
29
29
|
- samples/proxy.rb
|
30
|
-
- samples/
|
31
|
-
- samples/relay
|
30
|
+
- samples/pxy.rb
|
31
|
+
- samples/relay.rb
|
32
32
|
- samples/relay/README.md
|
33
|
-
- samples/relay/
|
33
|
+
- samples/relay/c.rb
|
34
34
|
- samples/relay/relai_config.data
|
35
|
-
- samples/relay.rb
|
35
|
+
- samples/relay/relaiproxy.rb
|
36
36
|
- samples/spdy.rb
|
37
37
|
- samples/statcpu.rb
|
38
38
|
- test.rb
|
39
|
-
- VERSION
|
40
39
|
homepage: https://github.com/glurp/minitcp
|
41
40
|
licenses:
|
42
41
|
- LGPL
|
@@ -57,15 +56,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
56
|
version: '0'
|
58
57
|
requirements: []
|
59
58
|
rubyforge_project:
|
60
|
-
rubygems_version: 2.
|
59
|
+
rubygems_version: 2.4.6
|
61
60
|
signing_key:
|
62
61
|
specification_version: 3
|
63
62
|
summary: A DSL for programming little Tcp client and server
|
64
63
|
test_files:
|
65
64
|
- samples/name_server.rb
|
66
|
-
- samples/pingpongplot.rb
|
67
|
-
- samples/plot.rb
|
68
65
|
- samples/proxy.rb
|
66
|
+
- samples/pxy.rb
|
69
67
|
- samples/README.md
|
70
68
|
- samples/relay.rb
|
71
69
|
- samples/spdy.rb
|
data/samples/pingpongplot.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# LGPL, Author: Regis d'Aubarede <regis.aubarede@gmail.com>
|
2
|
-
#################################################################
|
3
|
-
# pingpongplot.rb : measure pingpong time on google, plot it
|
4
|
-
#
|
5
|
-
# Usage :
|
6
|
-
# > ruby pingpongplot.rb | ruby plot.rb 0 0 300 pingpong auto
|
7
|
-
#################################################################
|
8
|
-
require_relative '../lib/minitcp.rb'
|
9
|
-
|
10
|
-
|
11
|
-
$stdout.sync=true
|
12
|
-
|
13
|
-
MClient.run_continious("google.com",80,100) do |socket|
|
14
|
-
s=Time.now.to_f
|
15
|
-
socket.on_receive_sep("\r\n") do |data|
|
16
|
-
$stdout.puts("#{(Time.now.to_f-s)*1000}")
|
17
|
-
socket.close rescue nil
|
18
|
-
Thread.current.kill
|
19
|
-
end
|
20
|
-
s=Time.now.to_f
|
21
|
-
socket.print "GET /blabla HTTP/1.0\r\n\r\n"
|
22
|
-
socket.wait_end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
sleep
|
data/samples/plot.rb
DELETED
@@ -1,190 +0,0 @@
|
|
1
|
-
# LGPL
|
2
|
-
###############################################################
|
3
|
-
# plot.rb plot data(s) of stdin to Gui display
|
4
|
-
# Usage:
|
5
|
-
# > vmstat 1 | ruby plot.rb -2 0-value 100%-value cpu -- 10 0 5000 io auto
|
6
|
-
# ^input-column ^label ^in-column .. ^auto-scale
|
7
|
-
#
|
8
|
-
###############################################################
|
9
|
-
|
10
|
-
require 'Ruiby'
|
11
|
-
$bgcolor=::Gdk::Color.parse("#023")
|
12
|
-
$fgcolor=[
|
13
|
-
::Gdk::Color.parse("#FFAA00"),
|
14
|
-
::Gdk::Color.parse("#99DDFF"),
|
15
|
-
::Gdk::Color.parse("#00FF00"),
|
16
|
-
::Gdk::Color.parse("#0000FF"),
|
17
|
-
::Gdk::Color.parse("#FFFF00"),
|
18
|
-
::Gdk::Color.parse("#00FFFF"),
|
19
|
-
::Gdk::Color.parse("#FF00FF"),
|
20
|
-
::Gdk::Color.parse("#999"),
|
21
|
-
]
|
22
|
-
class Measure
|
23
|
-
class << self
|
24
|
-
def create(argv)
|
25
|
-
noc=argv.shift.to_i
|
26
|
-
y0=(argv.shift||"0.0").to_f
|
27
|
-
y1=(argv.shift||"100.0").to_f
|
28
|
-
label=argv.shift||"?"
|
29
|
-
autoscale=argv.size>0
|
30
|
-
@lcurve||=[]
|
31
|
-
@lcurve << Measure.new(noc,y0,y1,label,autoscale)
|
32
|
-
@lcurve.size-1
|
33
|
-
end
|
34
|
-
def add(noc,y0,y1,label,autoscale)
|
35
|
-
@lcurve << Measure.new(noc,y0,y1,label,autoscale)
|
36
|
-
@lcurve.size-1
|
37
|
-
end
|
38
|
-
def scan_line(line)
|
39
|
-
nums=line.scan(/[\d+.]+/)
|
40
|
-
@lcurve.each { |m| m.register_value(nums) }
|
41
|
-
end
|
42
|
-
def add_value(index,value)
|
43
|
-
@lcurve[index].register_value(value)
|
44
|
-
end
|
45
|
-
def draw_measures(ctx)
|
46
|
-
@lcurve.each_with_index { |m,index| m.plot_curve(index,ctx) }
|
47
|
-
@lcurve.each_with_index { |m,index| m.plot_label(index,ctx) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
def initialize(noc,min,max,label,auto_scale)
|
51
|
-
@noc=noc
|
52
|
-
@div,@offset=calc_coef(min,0.0,max,1.0)
|
53
|
-
@name=label
|
54
|
-
@value= 0
|
55
|
-
@curve=[]
|
56
|
-
@label=@name
|
57
|
-
@autoscale=auto_scale
|
58
|
-
end
|
59
|
-
def register_value(data)
|
60
|
-
if data.is_a? Array
|
61
|
-
svalue=data[@noc]
|
62
|
-
return if !svalue || svalue !~ /[\d.]+/
|
63
|
-
@value=svalue.to_f
|
64
|
-
else
|
65
|
-
@value=data
|
66
|
-
end
|
67
|
-
@label = "%s %5.2f" % [@name,@value]
|
68
|
-
v= @value * @div + @offset
|
69
|
-
py=[0.0,(H-HHEAD)*1.0,(H-HHEAD)*(1.0-v)].sort[1]+HHEAD
|
70
|
-
@curve << [W+PAS,py,v,@value]
|
71
|
-
@curve.select! {|pt| pt[0]-=PAS; pt[0]>=0}
|
72
|
-
p [i,@value,v,py] if $DEBUG
|
73
|
-
auto_scale if @autoscale && @curve.size>5
|
74
|
-
end
|
75
|
-
def auto_scale()
|
76
|
-
min,max=@curve.minmax_by {|pt| pt[2]}
|
77
|
-
if min!=max && (min[2]<-0.01 || max[2]>1.01)
|
78
|
-
p "correction1 #{@name} #{min} // #{max}"
|
79
|
-
@div,@offset=calc_coef(min[3],0.0,max[3],1.0)
|
80
|
-
@curve.each {|a| a[2]=a[3]*@div+@offset ; a[1] = (H-HHEAD)*(1-a[2])}
|
81
|
-
elsif (d=(max[2]-min[2]))< 0.1 && (@curve.size-1) >= W/PAS && d>0.0001
|
82
|
-
p "correction2 #{@name} #{min} // #{max}"
|
83
|
-
@div,@offset=calc_coef(min[3],min[2]-3*d,max[3],max[2]+3*d)
|
84
|
-
@curve.each {|a| a[2]=a[3]*@div+@offset ; a[1] = (H-HHEAD)*(1.0-a[2])}
|
85
|
-
end
|
86
|
-
end
|
87
|
-
def calc_coef(x0,y0,x1,y1)
|
88
|
-
y0=[0.0,1.0,y0].sort[1]
|
89
|
-
y1=[0.0,1.0,y1].sort[1]
|
90
|
-
a=1.0*(y0-y1)/(x0-x1)
|
91
|
-
b= (y0+y1-(x0+x1)*a)/2
|
92
|
-
[a,b]
|
93
|
-
end
|
94
|
-
def plot_curve(index,ctx)
|
95
|
-
return if @curve.size<2
|
96
|
-
a,*l=@curve
|
97
|
-
style(ctx,3,$fgcolor.last) ; draw(ctx,a,l)
|
98
|
-
style(ctx,1,$fgcolor[index]) ; draw(ctx,a,l)
|
99
|
-
end
|
100
|
-
def style(ctx,width,color)
|
101
|
-
ctx.set_line_width(width)
|
102
|
-
ctx.set_source_rgba(color.red/65000.0,color.green/65000.0,color.blue/65000.0, 1.0)
|
103
|
-
end
|
104
|
-
def draw(ctx,h,t)
|
105
|
-
ctx.move_to(h.first,h[1])
|
106
|
-
t.each {|x,y,*q| ctx.line_to(x,y) }
|
107
|
-
ctx.stroke
|
108
|
-
end
|
109
|
-
def plot_label(index,ctx)
|
110
|
-
style(ctx,3,$fgcolor[index])
|
111
|
-
ctx.move_to(5+60*index,HHEAD-5)
|
112
|
-
ctx.show_text(@label)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
def run(app)
|
118
|
-
$str=$stdin.gets
|
119
|
-
if $str
|
120
|
-
p $str if $DEBUG
|
121
|
-
Measure.scan_line($str)
|
122
|
-
gui_invoke { @cv.redraw }
|
123
|
-
else
|
124
|
-
exit!(0)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def run_window()
|
129
|
-
Ruiby.app width: W, height: H, title: "Curve" do
|
130
|
-
stack do
|
131
|
-
@cv=canvas(W,H) do
|
132
|
-
on_canvas_draw { |w,ctx| expose(w,ctx) }
|
133
|
-
end
|
134
|
-
popup(@cv) do
|
135
|
-
pp_item(" Plot ") { }
|
136
|
-
pp_separator
|
137
|
-
pp_item("htop") { system("lxterminal", "-e", "htop") }
|
138
|
-
pp_item("Gnome Monitor") { Process.spawn("gnome-system-monitor") }
|
139
|
-
pp_item("Terminal") { system("lxterminal") }
|
140
|
-
pp_separator
|
141
|
-
pp_item("Exit") { ask("Exit ?") && exit(0) }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
chrome(false)
|
145
|
-
move($posxy[0],$posxy[1])
|
146
|
-
@ow,@oh=size
|
147
|
-
def expose(cv,ctx)
|
148
|
-
ctx.set_source_rgba($bgcolor.red/65000.0, $bgcolor.green/65000.0, $bgcolor.blue/65000.0, 1)
|
149
|
-
ctx.rectangle(0,0,W,H)
|
150
|
-
ctx.fill()
|
151
|
-
ctx.set_source_rgba($bgcolor.red/65000.0, $bgcolor.green/65000.0, 05+$bgcolor.blue/65000.0, 0.3)
|
152
|
-
ctx.rectangle(0,0,W,HHEAD)
|
153
|
-
ctx.fill()
|
154
|
-
Measure.draw_measures(ctx)
|
155
|
-
(puts "source modified!!!";exit!(0)) if File.mtime(__FILE__)!=$mtime
|
156
|
-
end
|
157
|
-
$mtime=File.mtime(__FILE__)
|
158
|
-
|
159
|
-
Thread.new(self) { |app| loop { run(app) } }
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
############################### Main #################################
|
164
|
-
|
165
|
-
if $0==__FILE__
|
166
|
-
trap("TERM") { exit!(0) }
|
167
|
-
|
168
|
-
PAS=2
|
169
|
-
HHEAD=20
|
170
|
-
$posxy=[0,0]
|
171
|
-
|
172
|
-
if ARGV.size>=2 && ARGV[0]=="--pos"
|
173
|
-
_,posxy=ARGV.shift,ARGV.shift
|
174
|
-
$posxy=posxy.split(/[x,:]/).map(&:to_i)
|
175
|
-
end
|
176
|
-
if ARGV.size>=2 && ARGV[0]=="--dim"
|
177
|
-
_,geom=ARGV.shift,ARGV.shift
|
178
|
-
W,H=geom.split(/[x,:]/).map(&:to_i)
|
179
|
-
else
|
180
|
-
W,H=200,100
|
181
|
-
end
|
182
|
-
|
183
|
-
while ARGV.size>0
|
184
|
-
argv=[]
|
185
|
-
argv << ARGV.shift while ARGV.size>0 && ARGV.first!="--"
|
186
|
-
Measure.create(argv)
|
187
|
-
ARGV.shift if ARGV.size>0 && ARGV.first=="--"
|
188
|
-
end
|
189
|
-
run_window
|
190
|
-
end
|