minitcp 0.10.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 +7 -0
- data/CHANGELOG.txt +42 -0
- data/LICENSE +2 -0
- data/README.md +200 -0
- data/Rakefile.rb +217 -0
- data/VERSION +1 -0
- data/lib/minitcp.rb +341 -0
- data/minitcp.gemspec +37 -0
- data/samples/README.md +19 -0
- data/samples/name_server.rb +131 -0
- data/samples/pingpongplot.rb +26 -0
- data/samples/plot.rb +190 -0
- data/samples/proxy.rb +46 -0
- data/samples/relay/README.md +41 -0
- data/samples/relay/c.rb +21 -0
- data/samples/relay/relai_config.data +4 -0
- data/samples/relay/relaiproxy.rb +180 -0
- data/samples/relay.rb +102 -0
- data/samples/spdy.rb +43 -0
- data/samples/statcpu.rb +37 -0
- data/test.rb +192 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a5ea8ac3aaaa06e3051b9d4e696713132b1e721
|
4
|
+
data.tar.gz: 98eb5966f3ff14ca68c1522110b6fdd3d941b3d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 87f235759fc78198cbeeb0446b788c685f4c82ca79947fe551f0822da7c29e5fb7961e756eec422b524d92d2821688871caeaee01ac502d831d093aa598288f5
|
7
|
+
data.tar.gz: d217d33d86b4181190730605dfe88ccbfc3405eeb022521ae8fab0b32041a4ed57d7a199c73fc34fa7bf0836c9e3a3cbb36e99aad413e1d65bf1a89b665e95bf
|
data/CHANGELOG.txt
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
0.10.0 : 2014-09-24 20:18:54 +0200
|
2
|
+
minitcp.rb : reveive_n_byte correction
|
3
|
+
0.9.0 : 2014-09-18 22:38:31 +0200
|
4
|
+
0.7.0 : 2014-09-18 22:37:45 +0200
|
5
|
+
README.md : titles
|
6
|
+
test.rb : UDP tests
|
7
|
+
minitcp.rb : udp creation
|
8
|
+
README.md : UDP creation
|
9
|
+
statcpu.rb : windows version, not finish...
|
10
|
+
README.md : spdy start demo
|
11
|
+
README.md : best code example
|
12
|
+
README.md : presentation
|
13
|
+
README.md : continious
|
14
|
+
0.6.1
|
15
|
+
plot.rb : refactoring Measure.class
|
16
|
+
pingpongplot.rb : temporisation
|
17
|
+
0.6.0 : 2014-08-21 11:06:44 +0200
|
18
|
+
README.md : todo
|
19
|
+
plot.rb : auto-scale
|
20
|
+
name_server.rb : creation
|
21
|
+
plot.rb : color
|
22
|
+
plot.rb : interaction with mouse
|
23
|
+
name_server.rb : forget debug
|
24
|
+
0.5.0 : 2014-08-18 16:39:35 +0200
|
25
|
+
0.4.0 : 2014-08-18 16:37:12 +0200
|
26
|
+
minitcp.rb : error on stdout for SocketReactive
|
27
|
+
README.md : typo
|
28
|
+
README.md : sockets presentation
|
29
|
+
README.md : rdoc url
|
30
|
+
minitcp.rb : comments
|
31
|
+
README.md : presentations, format
|
32
|
+
proxy.rb : prefix correction
|
33
|
+
README.md : proxy correction
|
34
|
+
README.md : todo, presentation
|
35
|
+
0.3.0 : 2014-08-18 01:27:40 +0200
|
36
|
+
test.rb : sleep before thread good stoping detection
|
37
|
+
minitcp.rb : all read hendler do socket close when necessary
|
38
|
+
README.md : todo
|
39
|
+
0.2.0 : 2014-08-17 16:07:03 +0200
|
40
|
+
Rakefile.rb : update
|
41
|
+
test.rb : license
|
42
|
+
proxy.rb : license
|
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
Minitcp
|
2
|
+
===
|
3
|
+
|
4
|
+
Presentation
|
5
|
+
==
|
6
|
+
|
7
|
+
A little tool for doing some TCP/UDP sockets communications.
|
8
|
+
|
9
|
+
This tool have no pretention : it is not EventMachine ! :
|
10
|
+
|
11
|
+
* no mainloop,
|
12
|
+
* many threads are created/deleted.
|
13
|
+
* it is useful for send some data one-shot, test a ascii communication in few minutes...
|
14
|
+
* should be equivalent to netcat+bash ...
|
15
|
+
|
16
|
+
|
17
|
+
A TCP client :
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
MClient.run_one_shot("localhost",2200) do |socket|
|
21
|
+
socket.on_any_receive { |data| p "client recieved #{data.inspect}"}
|
22
|
+
3.times { |j| socket.puts "Hello #{j}..." ; sleep(1) }
|
23
|
+
end.join
|
24
|
+
```
|
25
|
+
|
26
|
+
An echo server :
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
srv=MServer.service(2200,"0.0.0.0",22) do |socket|
|
30
|
+
socket.on_any_receive { |data| socket.print(data) }
|
31
|
+
socket.on_timer(2000) do
|
32
|
+
socket.close
|
33
|
+
end
|
34
|
+
socket.wait_end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
A UDP server :
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
UDPAgent.on_datagramme("127.0.0.2",SRV_PORT ) { |data,from,p|
|
42
|
+
puts "Agent: received #{data} from #{from}:#{p}"
|
43
|
+
data && data.size>3 ? "OK-#{data}." : nil
|
44
|
+
}
|
45
|
+
```
|
46
|
+
|
47
|
+
A UDP sender :
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
UDPAgent.on_timer(1000,
|
51
|
+
port: 2232,
|
52
|
+
on_timer: proc do
|
53
|
+
data=Time.now.to_i.to_s
|
54
|
+
puts "\n\n\non timer send <#{data}>"
|
55
|
+
{mess: data,host: "127.0.0.2",port: SRV_PORT}
|
56
|
+
end,
|
57
|
+
on_receive: proc { |data,from,sock|
|
58
|
+
puts "Client: received #{data} from #{from}"
|
59
|
+
UDPAgent.send_datagram_on_socket(sock,from.last,from[1],'ack')
|
60
|
+
}
|
61
|
+
)
|
62
|
+
```
|
63
|
+
|
64
|
+
|
65
|
+
Docs: http://rubydoc.info/gems/minitcp
|
66
|
+
|
67
|
+
|
68
|
+
TCP
|
69
|
+
===
|
70
|
+
|
71
|
+
Client
|
72
|
+
---
|
73
|
+
|
74
|
+
```
|
75
|
+
MClient.run_one_shot(host,port) do |socket| ... end
|
76
|
+
MClient.run_continious(host,port,time_inter_connection) do |socket| ... end
|
77
|
+
```
|
78
|
+
|
79
|
+
Client socket is extended with all specifiques commandes (```SocketReactive```, see Sockets).
|
80
|
+
|
81
|
+
Server
|
82
|
+
---
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
srv=MServer.service(port,"0.0.0.0",max_client) do |socket| ... end
|
86
|
+
```
|
87
|
+
Mserver run a GServer.
|
88
|
+
Connected sockets are extended with same module as in client.
|
89
|
+
|
90
|
+
Sockets
|
91
|
+
---
|
92
|
+
|
93
|
+
Handlers are disponibles for any sockets : client or server.
|
94
|
+
All handler's bloc run in distinct thread : so any handler-bloc can wait anything.
|
95
|
+
if socket is closed, handler/thread are cleanly (?) stoped.
|
96
|
+
|
97
|
+
* socket.**on_any_receive() {|data| ...}** : on receive some data, any size
|
98
|
+
* socket.**on_n_receive(sizemax=1) {|data| ...}** : receives n byte(s) only
|
99
|
+
* socket.**on_receive_sep(";") {|field | ... }** : reveive data until string separator
|
100
|
+
* socket.**on_timer(value_ms) { ... }** : each time do something, if socket is open
|
101
|
+
* socket.**after(duration) { ... }** : do something after n millisecondes, if socket is open
|
102
|
+
|
103
|
+
Some primitives are here for help (no thread):
|
104
|
+
|
105
|
+
* **received_timeout(sizemax,timeout)** : wait for n bytes, with timeout, (blocking caller),
|
106
|
+
* **wait_end()** : wait, (blocking caller) until socket is close. this
|
107
|
+
work only if something has closed the socket.this is possible unicly by receiving 0 bte on a
|
108
|
+
* **receive_n_bytes** / **on_receive_sep** : bocking version of handler,
|
109
|
+
* **connected?** : test if a close have been done,
|
110
|
+
* **data_readed()** : some receives (receive_sep...) can read more data form sockets,
|
111
|
+
this data are used by ```n_revieve/any_receive/receive_sep```, but they can be read/reseted
|
112
|
+
whith data_readed getseter.
|
113
|
+
|
114
|
+
This primitives are declared in SocketReactive module.
|
115
|
+
|
116
|
+
UDP
|
117
|
+
===
|
118
|
+
|
119
|
+
2 type of agents :
|
120
|
+
|
121
|
+
* **Server** : receive data from anywhere, can reply to sender
|
122
|
+
* **Timer** : emit to everybody, can receive response to them
|
123
|
+
|
124
|
+
2 primitives :
|
125
|
+
|
126
|
+
* **send_datagram(host,port,message)** : create a socket, send mesage and close socket (ca'nt receive a reply)
|
127
|
+
* **send_datagram_on_socket(socket,host,port,message)** : use existant socket for send a message to ip:port
|
128
|
+
|
129
|
+
|
130
|
+
TODO
|
131
|
+
==
|
132
|
+
|
133
|
+
* Serial line
|
134
|
+
* more socket primitive
|
135
|
+
|
136
|
+
|
137
|
+
Tests case
|
138
|
+
==
|
139
|
+
A TCP proxy, debug tool (see samples/proxy.rb) :
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
MServer.service(2200,"0.0.0.0",22) do |scli|
|
143
|
+
px 2, "======== client Connected ========"
|
144
|
+
srv=MClient.run_one_shot("ip",2200) do |ssrv|
|
145
|
+
px 1, "======== server Connected ========"
|
146
|
+
ssrv.on_any_receive { |data| px 1,data; scli.print data }
|
147
|
+
scli.on_any_receive { |data| px 2,data; ssrv.print data}
|
148
|
+
ssrv.wait_end
|
149
|
+
scli.close rescue nil
|
150
|
+
end
|
151
|
+
scli.wait_end
|
152
|
+
srv.stop rescue nil
|
153
|
+
end
|
154
|
+
def px(sens,data)
|
155
|
+
data.each_line {|line| puts "#{(sens==1 ? "> " : "< ")}#{line.chomp}"
|
156
|
+
end
|
157
|
+
|
158
|
+
```
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
Test serial **protocole-like** : header/body => ack/timeout:
|
164
|
+
|
165
|
+
* client send <length><data> , wait one char acquit or timeout
|
166
|
+
* serveur receive heade( size: 4 chars) , then data with size, send ack
|
167
|
+
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
|
171
|
+
srv=MServer.service(2200,"0.0.0.0",22) do |socket|
|
172
|
+
socket.on_n_receive(4) { |data|
|
173
|
+
size=data.to_i
|
174
|
+
data=socket.recv(size)
|
175
|
+
puts " Server recieved buffer : #{data.inspect}"
|
176
|
+
if rand(100)>50
|
177
|
+
socket.print("o")
|
178
|
+
else
|
179
|
+
puts " !!!non-ack by serv"
|
180
|
+
end
|
181
|
+
}
|
182
|
+
socket.on_timer(40*1000) { puts " serv close after 40 seconds"; socket.close }
|
183
|
+
socket.wait_end
|
184
|
+
end
|
185
|
+
|
186
|
+
MClient.run_one_shot("localhost",2200) do |socket|
|
187
|
+
10.times { |j|
|
188
|
+
size=rand(1..10)
|
189
|
+
puts "Sending #{size} data..."
|
190
|
+
data='*'*size
|
191
|
+
socket.print "%04d" % size
|
192
|
+
socket.print data
|
193
|
+
p socket.received_timeout(1,100) ? "ack ok" : "!!! timeout ack"
|
194
|
+
}
|
195
|
+
p "end client"
|
196
|
+
end.join
|
197
|
+
|
198
|
+
|
199
|
+
```
|
200
|
+
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
# Creative Commons BY-SA : Regis d'Aubarede <regis.aubarede@gmail.com>
|
2
|
+
# LGPL
|
3
|
+
#################################################################
|
4
|
+
# Rakefile : git commit/add ; git push, test/spec & gem push
|
5
|
+
#################################################################
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
# > rake commit # commit in local directory and push to repository
|
9
|
+
# > rake gem # make gem,and test it, and push it to gemcutter
|
10
|
+
# > rake travis # travis CI run commands
|
11
|
+
#
|
12
|
+
#################################################################
|
13
|
+
# Requirements :
|
14
|
+
# version : X.Y.Z
|
15
|
+
# X : to be hand-modified
|
16
|
+
# Y : incremented at each 'rake gem'
|
17
|
+
# Z : increment on each file 'rake commit'
|
18
|
+
# auto commit all changed file, sking comment for each
|
19
|
+
# log all commment in CHANGELOG?Txt file
|
20
|
+
# increment VERSION content with version numbering rule
|
21
|
+
# so CHANGELOG.txt is updated with each comment/version change
|
22
|
+
# so VERSION is updated in each commit (Z part) and each gem build (Y part)
|
23
|
+
#
|
24
|
+
# commit:
|
25
|
+
# Use 'git status' output for each new/modified file,
|
26
|
+
# with asking some comment
|
27
|
+
# (no add/commit of comment is empty)
|
28
|
+
#
|
29
|
+
# gem:
|
30
|
+
# execute rspec if specs exists,
|
31
|
+
# make a gem, install it, execute samples/test.rb in it, if exist
|
32
|
+
# ask to operator if execution is ok and :
|
33
|
+
# increment version
|
34
|
+
# update change log/version
|
35
|
+
# do a 'gem push' and a 'gem yanked'
|
36
|
+
# make a coffe
|
37
|
+
#
|
38
|
+
#################################################################
|
39
|
+
|
40
|
+
FIGNORES=%w{VERSION CHANGELOG.txt .gitignore}
|
41
|
+
NAME= Dir.pwd.gsub(File.dirname(Dir.pwd)+'/',"")
|
42
|
+
|
43
|
+
Rake.application.options.trace = false
|
44
|
+
|
45
|
+
def push_changelog(line)
|
46
|
+
b=File.read('CHANGELOG.txt').split(/\r?\n/)
|
47
|
+
b.unshift(line)
|
48
|
+
File.open('CHANGELOG.txt','w') {|f| f.write(b[0..500].join("\n")) }
|
49
|
+
end
|
50
|
+
def changelog_push_currrent_versions()
|
51
|
+
version=File.read('VERSION').strip
|
52
|
+
b=File.read('CHANGELOG.txt').split(/\r?\n/)
|
53
|
+
b.unshift(version)
|
54
|
+
File.open('CHANGELOG.txt','w') {|f| f.write(b.join("\n")) }
|
55
|
+
yield rescue p $!.to_s
|
56
|
+
b.shift
|
57
|
+
File.open('CHANGELOG.txt','w') {|f| f.write(b.join("\n")) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def change_version()
|
61
|
+
a=File.read('VERSION').strip.split('.')[0..2]
|
62
|
+
yield(a)
|
63
|
+
version=a.join('.')
|
64
|
+
File.open('VERSION','w') {|f| f.write(version) }
|
65
|
+
version
|
66
|
+
end
|
67
|
+
def verification_file(fn)
|
68
|
+
return unless File.extname(fn)==".rb"
|
69
|
+
content=File.read(fn)[0..600]
|
70
|
+
unless content =~ /LGPL/
|
71
|
+
puts "\nFile #{fn} seem not contain licenses data LGPL\n"
|
72
|
+
exit(0)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
#############################################################
|
76
|
+
# Comment each file add/modified ##
|
77
|
+
#############################################################
|
78
|
+
|
79
|
+
|
80
|
+
desc "commit file changed and created"
|
81
|
+
task :commit_status do
|
82
|
+
`git status -s`.split(/\r?\n/).each do |line|
|
83
|
+
words=line.split(/\s+/)
|
84
|
+
case line
|
85
|
+
when /^ M /
|
86
|
+
filename=words[2]
|
87
|
+
next if FIGNORES.include?(filename)
|
88
|
+
system("git","diff",filename)
|
89
|
+
print("Comment for change in #{filename} : ")
|
90
|
+
comment=$stdin.gets
|
91
|
+
if comment && comment.chomp.size>0
|
92
|
+
comment.chomp!
|
93
|
+
(puts "Abort!";exit!) if comment=~/^a(b(o(r(t)?)?)?)?$/
|
94
|
+
verification_file(filename)
|
95
|
+
sh "git commit #{filename} -m \"#{comment.strip}\"" rescue 1
|
96
|
+
push_changelog(" #{File.basename(filename)} : #{comment}")
|
97
|
+
$changed=true
|
98
|
+
end
|
99
|
+
when /^\?\?/
|
100
|
+
filename=words[1]
|
101
|
+
print("Comment for new file in #{filename} : ")
|
102
|
+
comment=$stdin.gets.chomp
|
103
|
+
(puts "Abort!";exit!) if comment=~/^a(b(o(r(t)?)?)?)?$/
|
104
|
+
if comment =~ /^y|o/i
|
105
|
+
verification_file(filename)
|
106
|
+
sh "git add #{filename}"
|
107
|
+
sh "git commit #{filename} -m \"creation\"" rescue 1
|
108
|
+
$changed=true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
#############################################################
|
116
|
+
# before commit
|
117
|
+
#############################################################
|
118
|
+
|
119
|
+
desc "job before commit"
|
120
|
+
task :pre_commit do
|
121
|
+
sh "cls" if RUBY_PLATFORM =~ /(win32)|(mingw)/i
|
122
|
+
puts <<EEND2
|
123
|
+
|
124
|
+
|
125
|
+
--------------------------------------------------------------------
|
126
|
+
Commmit and push #{NAME}
|
127
|
+
--------------------------------------------------------------------
|
128
|
+
EEND2
|
129
|
+
|
130
|
+
#sh "giti"
|
131
|
+
$changed=false
|
132
|
+
end
|
133
|
+
|
134
|
+
#############################################################
|
135
|
+
# after commit
|
136
|
+
#############################################################
|
137
|
+
desc "job after local commit done: push to git repo"
|
138
|
+
task :post_commit do
|
139
|
+
if $changed
|
140
|
+
$version=change_version { |a| a[-1]=(a.last.to_i+1) }
|
141
|
+
sh "git commit VERSION -m update"
|
142
|
+
changelog_push_currrent_versions {
|
143
|
+
sh "git commit CHANGELOG.txt -m update"
|
144
|
+
sh "git push"
|
145
|
+
puts "\n\nNew version is #{$version}\n"
|
146
|
+
}
|
147
|
+
else
|
148
|
+
puts "no change!"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#############################################################
|
153
|
+
# commit
|
154
|
+
#############################################################
|
155
|
+
desc "commit local and then distant repo"
|
156
|
+
task :commit => [:pre_commit,"commit_status",:post_commit]
|
157
|
+
|
158
|
+
|
159
|
+
#############################################################
|
160
|
+
# gem build & push
|
161
|
+
#############################################################
|
162
|
+
desc "make a gem and push it to gemcutter"
|
163
|
+
task :gem do
|
164
|
+
$version=change_version { |a|
|
165
|
+
a[-2]=(a[-2].to_i+1)
|
166
|
+
a[-1]=0
|
167
|
+
}
|
168
|
+
puts "New version ==>> #{$version}"
|
169
|
+
l=FileList['*.gem']
|
170
|
+
l.each { |fn| rm fn }
|
171
|
+
gem_name="#{NAME}-#{$version}.gem"
|
172
|
+
push_changelog "#{$version} : #{Time.now}"
|
173
|
+
sh "gem build #{NAME}.gemspec"
|
174
|
+
Rake::Task["test"].execute if File.exists?("samples/test.rb")
|
175
|
+
sh "gem push #{gem_name}"
|
176
|
+
l.each { |fn|
|
177
|
+
ov=fn.split('-')[1].gsub('.gem',"")
|
178
|
+
sh "gem yank -v #{ov} #{NAME}"
|
179
|
+
}
|
180
|
+
end
|
181
|
+
#############################################################
|
182
|
+
# execute tests
|
183
|
+
#############################################################
|
184
|
+
|
185
|
+
desc "test the current version of the framework by installing the gem and run a test programme"
|
186
|
+
task :test do
|
187
|
+
if File.exists?("spec/test_all.rb")
|
188
|
+
system("rspec spec/test_all.rb")
|
189
|
+
end
|
190
|
+
if File.exists?("samples/test.rb")
|
191
|
+
cd ".."
|
192
|
+
mkdir "#{NAME}Test" unless File.exists?("#{NAME}Test")
|
193
|
+
nname="#{NAME}Test/test.rb"
|
194
|
+
content=File.read("#{NAME}/samples/test.rb").gsub(/require_relative/," require").gsub('../lib/','')
|
195
|
+
File.open(nname,"w") { |f| f.write(content) }
|
196
|
+
sh "gem install #{FileList["#{NAME}/#{NAME}*.gem"][-1]}"
|
197
|
+
ruby nname rescue nil
|
198
|
+
cd NAME
|
199
|
+
print "\n\nOk for diffusion ? "
|
200
|
+
rep=$stdin.gets
|
201
|
+
raise("aborted!") unless rep && rep =~ /^y|o|d/
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
#############################################################
|
206
|
+
# travis command
|
207
|
+
#############################################################
|
208
|
+
|
209
|
+
task :travis do
|
210
|
+
puts "Starting travis test..."
|
211
|
+
cmd="bundle exec rspec spec/test_all.rb"
|
212
|
+
system("export DISPLAY=:99.0 && #{cmd}")
|
213
|
+
#system(cmd)
|
214
|
+
raise "rspec failed!" unless $?.exitstatus == 0
|
215
|
+
end
|
216
|
+
|
217
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.10.0
|