rbsrt 0.1.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/README.md +752 -0
- data/Rakefile +29 -0
- data/bin/rbsrt-client +113 -0
- data/bin/rbsrt-server +68 -0
- data/bin/rbsrt-sockets +82 -0
- data/ext/rbsrt/extconf.rb +37 -0
- data/ext/rbsrt/rbsrt.c +2270 -0
- data/ext/rbsrt/rbsrt.h +265 -0
- data/ext/rbsrt/rbstats.c +960 -0
- data/ext/rbsrt/rbstats.h +24 -0
- data/lib/rbsrt/rbsrt.bundle +0 -0
- data/lib/rbsrt/streamid_components.rb +113 -0
- data/lib/rbsrt/version.rb +3 -0
- data/lib/rbsrt.rb +5 -0
- data/rbsrt.gemspec +22 -0
- data/test/rbsrt/poll_test.rb +153 -0
- data/test/rbsrt/stats_test.rb +546 -0
- data/test/rbsrt/streamid_components_test.rb +281 -0
- metadata +83 -0
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'rake/extensiontask'
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
# desc "Generate Makefile"
|
9
|
+
# file "Makefile" do
|
10
|
+
# cd File.expand_path("../ext/rbsrt/extconf", __FILE__)
|
11
|
+
# require File.expand_path("../ext/rbsrt/extconf", __FILE__)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# desc "Compile extension"
|
15
|
+
# task :compile => ["Makefile"] do
|
16
|
+
# sh "make"
|
17
|
+
# end
|
18
|
+
|
19
|
+
require 'rake/extensiontask'
|
20
|
+
|
21
|
+
Rake::ExtensionTask.new 'rbsrt' do |ext|
|
22
|
+
ext.lib_dir = "lib/rbsrt"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Run tests"
|
26
|
+
task :test => [ :compile ] do
|
27
|
+
require './test/test_helper'
|
28
|
+
Dir.glob( './test/**/*_test.rb').each { |file| require file }
|
29
|
+
end
|
data/bin/rbsrt-client
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
# parse options
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
options = {
|
10
|
+
:direction => "out",
|
11
|
+
:exec => nil,
|
12
|
+
:file => nil,
|
13
|
+
:url => ARGV.last,
|
14
|
+
:passphrase => nil,
|
15
|
+
:streamid => {
|
16
|
+
:mode => :request,
|
17
|
+
:type => :stream
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.banner = "Usage: rbsrt-client [options] srt://host:port"
|
23
|
+
|
24
|
+
opts.on("-e CMD", "--exec=CMD", "command to execute an use as input or output") do |cmd|
|
25
|
+
options[:exec] = cmd
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-f PATH", "--file=PATH", "file to send to the server") do |path|
|
29
|
+
options[:path] = path
|
30
|
+
options[:type] = :file
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-r NAME", "--resource-name=NAME", "name of the resource to transmit or receive") do |resource_name|
|
34
|
+
options[:streamid][:resource_name] = resource_name
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("-u USER_NAME", "--user-name=USER_NAME", "user name") do |user_name|
|
38
|
+
options[:streamid][:user_name] = user_name
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("-m MODE", "--mode=MODE", "connection mode. Can be one of 'request', 'publish' or 'bidirectional'") do |mode|
|
42
|
+
options[:streamid][:mode] = mode
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-t TYPE", "--type=TYPE", "connection type. Can be one of 'stream', 'file' or 'auth'") do |type|
|
46
|
+
options[:streamid][:type] = type
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-s SESSIONID", "--sessionid=SESSIONID", "a sessionid") do |sessionid|
|
50
|
+
options[:streamid][:sessionid] = sessionid
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-S PASSPHRASE", "--passphrase=PASSPHRASE", "passphrase used to derive key for encryption") do |passphrase|
|
54
|
+
options[:passphrase] = passphrase
|
55
|
+
end
|
56
|
+
end.parse!
|
57
|
+
|
58
|
+
|
59
|
+
# start server
|
60
|
+
|
61
|
+
require 'rbsrt'
|
62
|
+
require 'uri'
|
63
|
+
|
64
|
+
puts "create srt client"
|
65
|
+
|
66
|
+
streamid_info = SRT::StreamIDComponents.new options[:streamid]
|
67
|
+
|
68
|
+
puts streamid_info
|
69
|
+
|
70
|
+
client = SRT::Client.new
|
71
|
+
|
72
|
+
client.transmission_mode = streamid_info.type == :file ? :file : :live
|
73
|
+
client.streamid = streamid_info.to_s
|
74
|
+
client.passphrase = options[:passphrase]
|
75
|
+
|
76
|
+
puts "connect srt client"
|
77
|
+
|
78
|
+
puts "before connect: #{client.connected?}"
|
79
|
+
|
80
|
+
at_exit { client.close }
|
81
|
+
|
82
|
+
begin
|
83
|
+
uri = URI.parse(options[:url])
|
84
|
+
puts "connect to #{uri.host.to_s} on port #{uri.port.to_s}"
|
85
|
+
client.connect uri.host.to_s, uri.port.to_s
|
86
|
+
rescue StandardError => e
|
87
|
+
puts "Connection failed. #{e.message}"
|
88
|
+
exit 1
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
if streamid_info.mode == :request
|
93
|
+
while chunk = client.read
|
94
|
+
print chunk
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# transmit file contents
|
99
|
+
if file = options[:file]
|
100
|
+
puts "file transport is not implemented yet"
|
101
|
+
# transmist cmd stdout
|
102
|
+
elsif cmd = options[:exec]
|
103
|
+
require 'open3'
|
104
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
105
|
+
stdout.each do |buf|
|
106
|
+
puts "data: #{buf.length}"
|
107
|
+
client.sendmsg buf
|
108
|
+
end
|
109
|
+
end
|
110
|
+
else
|
111
|
+
|
112
|
+
end
|
113
|
+
|
data/bin/rbsrt-server
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
# parse options
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
options = {
|
10
|
+
:port => "5554",
|
11
|
+
:address => "0.0.0.0",
|
12
|
+
:recording_path => Dir.pwd,
|
13
|
+
:passphrase => nil
|
14
|
+
}
|
15
|
+
|
16
|
+
OptionParser.new do |opts|
|
17
|
+
opts.banner = "Usage: rbsrt-server [options]"
|
18
|
+
|
19
|
+
opts.on("-p PORT", "--port=PORT", "server port (default: #{options[:port]})") do |port|
|
20
|
+
options[:port] = port.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-a ADDRESS", "--address=ADDRESS", "server address (default: #{options[:address]})") do |address|
|
24
|
+
options[:address] = address.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-r PATH", "--recording-path=PATH", "directory to save recordings (default: #{options[:recording_path]})") do |path|
|
28
|
+
options[:recording_path] = File.expand_path(path, Dir.pwd)
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-S PASSPHRASE", "--passphrase=PASSPHRASE", "passphrase use to derive key for encryption") do |passphrase|
|
32
|
+
options[:passphrase] = passphrase
|
33
|
+
end
|
34
|
+
end.parse!
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
# start the server
|
40
|
+
|
41
|
+
require 'rbsrt'
|
42
|
+
|
43
|
+
puts "start srt server on port #{options[:port]}, address #{options[:address]}"
|
44
|
+
|
45
|
+
server = SRT::Server.new options[:address], options[:port]
|
46
|
+
|
47
|
+
# currently we can only set one passphrase for every connection
|
48
|
+
# this will change in the future.
|
49
|
+
server.passphrase = options[:passphrase] if options[:passphrase]
|
50
|
+
|
51
|
+
puts "starting server"
|
52
|
+
|
53
|
+
server.start do |connection|
|
54
|
+
puts "new connection: connections=#{connection_count}, id=#{connection.id}, streamid=#{connection.streamid}"
|
55
|
+
|
56
|
+
output_file = File.new "recording-#{Process.pid}-#{connection.id}.ts", "w+"
|
57
|
+
output_file.close_on_exec = true
|
58
|
+
|
59
|
+
connection.at_data do |chunk|
|
60
|
+
puts "data"
|
61
|
+
output_file.write(chunk)
|
62
|
+
end
|
63
|
+
|
64
|
+
connection.at_close do
|
65
|
+
puts "closed connection"
|
66
|
+
output_file.close
|
67
|
+
end
|
68
|
+
end
|
data/bin/rbsrt-sockets
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
|
5
|
+
require "rbsrt"
|
6
|
+
|
7
|
+
pids = []
|
8
|
+
|
9
|
+
puts "Running rbsrt Sockets examples"
|
10
|
+
puts "SRT version: #{SRT::SRT_VERSION}"
|
11
|
+
|
12
|
+
|
13
|
+
# server
|
14
|
+
|
15
|
+
pids << fork do
|
16
|
+
server = SRT::Socket.new
|
17
|
+
server.transmission_mode = :file
|
18
|
+
|
19
|
+
puts "server state=#{server.state}, id=#{server.id}"
|
20
|
+
|
21
|
+
server.bind "127.0.0.1", "5556"
|
22
|
+
|
23
|
+
puts "server #{server.state}"
|
24
|
+
|
25
|
+
server.listen 3
|
26
|
+
|
27
|
+
puts "server #{server.state}"
|
28
|
+
|
29
|
+
client = server.accept
|
30
|
+
|
31
|
+
puts "server accepted: streamid=\"#{client.streamid}\", id=#{client.id}, tsbpdmode=#{client.tsbpdmode?}"
|
32
|
+
|
33
|
+
loop do
|
34
|
+
break unless client.connected?
|
35
|
+
break unless data = client.recvmsg
|
36
|
+
puts "server received: #{data}"
|
37
|
+
rescue SRT::Error::CONNLOST => e
|
38
|
+
puts "connection lost: #{e}"
|
39
|
+
break
|
40
|
+
rescue SRT::Error => e
|
41
|
+
puts "server error: #{e.class}"
|
42
|
+
end
|
43
|
+
|
44
|
+
puts "client closed #{client.closed?}"
|
45
|
+
|
46
|
+
server.close
|
47
|
+
|
48
|
+
puts "server done"
|
49
|
+
end
|
50
|
+
|
51
|
+
# client
|
52
|
+
|
53
|
+
pids << fork do
|
54
|
+
|
55
|
+
client = SRT::Socket.new
|
56
|
+
|
57
|
+
client.streamid = "a ruby srt socket"
|
58
|
+
client.transmission_mode = :file
|
59
|
+
|
60
|
+
client.connect "127.0.0.1", "5556"
|
61
|
+
|
62
|
+
10.times do |i|
|
63
|
+
payload = "Hello from ruby client #{i}"
|
64
|
+
puts "will send: \"#{payload}\""
|
65
|
+
client.sendmsg "Hello from ruby client #{i}"
|
66
|
+
puts "did send: \"#{payload}\""
|
67
|
+
# sleep 0.1
|
68
|
+
rescue SRT::Error => e
|
69
|
+
puts "client error: #{e}"
|
70
|
+
end
|
71
|
+
|
72
|
+
sleep 0.1
|
73
|
+
|
74
|
+
client.close
|
75
|
+
|
76
|
+
puts "client done"
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
# wait for completion
|
81
|
+
|
82
|
+
pids.each { |pid| Process.wait pid }
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
extension_name = 'rbsrt'
|
4
|
+
|
5
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
6
|
+
|
7
|
+
LIBDIR = CONFIG['libdir']
|
8
|
+
INCLUDEDIR = CONFIG['includedir']
|
9
|
+
|
10
|
+
HEADER_DIRS = []
|
11
|
+
HEADER_DIRS << 'opt/local/include' if File.directory?('opt/local/include')
|
12
|
+
HEADER_DIRS << '/usr/local/include' if File.directory?('/usr/local/include')
|
13
|
+
HEADER_DIRS << INCLUDEDIR
|
14
|
+
HEADER_DIRS << '/usr/include' if File.directory?('/usr/include')
|
15
|
+
|
16
|
+
LIB_DIRS = []
|
17
|
+
LIB_DIRS << '/opt/local/lib' if File.directory?('/opt/local/lib')
|
18
|
+
LIB_DIRS << '/usr/local/lib' if File.directory?('/usr/local/lib')
|
19
|
+
LIB_DIRS << LIBDIR
|
20
|
+
LIB_DIRS << '/usr/lib' if File.directory?('/usr/lib')
|
21
|
+
|
22
|
+
dir_config('srt', HEADER_DIRS, LIB_DIRS)
|
23
|
+
# dir_config('c++', HEADER_DIRS, LIB_DIRS)
|
24
|
+
|
25
|
+
# srt dependencies
|
26
|
+
|
27
|
+
unless find_header('srt/srt.h')
|
28
|
+
abort "libsrt is missing. please install libsrt: https://github.com/Haivision/srt"
|
29
|
+
end
|
30
|
+
|
31
|
+
unless find_library('srt', 'srt_create_socket')
|
32
|
+
abort "libsrt is missing. please install libsrt: https://github.com/Haivision/srt"
|
33
|
+
end
|
34
|
+
|
35
|
+
dir_config(extension_name)
|
36
|
+
|
37
|
+
create_makefile(extension_name)
|