rbsrt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Ruby SRT - Ruby binding for Secure, Reliable, Transport
3
+ * Copyright (c) 2019 Klaas Speller, Recce.
4
+ *
5
+ * This Source Code Form is subject to the terms of the Mozilla Public
6
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
7
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
+ *
9
+ */
10
+
11
+ /**
12
+ * A Ruby wrapper for SRT (Secure Reliable Transport)
13
+ *
14
+ * @author: Klaas Speller <klaas@recce.nl>
15
+ */
16
+
17
+ #ifndef RBSRT_STATS_H
18
+ #define RBSRT_STATS_H
19
+
20
+ #include <ruby/ruby.h>
21
+
22
+ void RBSRT_stat_init(VALUE srt_module);
23
+
24
+ #endif /* RBSRT_STATS_H */
Binary file
@@ -0,0 +1,113 @@
1
+ # srt streamid parser based on https://github.com/Haivision/srt/blob/master/docs/AccessControl.md
2
+
3
+ require "uri"
4
+
5
+ module SRT
6
+ class StreamIDComponents
7
+ Types = ["stream", "file", "auth"]
8
+
9
+ Modes = ["request", "publish", "bidirectional"]
10
+
11
+ Header = "#!::"
12
+
13
+ attr_accessor :resource_name
14
+ attr_accessor :user_name
15
+ attr_accessor :mode
16
+ attr_accessor :host_name
17
+ attr_accessor :type
18
+ attr_accessor :sessionid
19
+ attr_reader :extra
20
+
21
+ def initialize(*args)
22
+
23
+ @mode = :request
24
+ @type = :stream
25
+ @extra = {}
26
+
27
+ # no args
28
+ return unless args.first
29
+
30
+ # hash args
31
+ if args.first.class == ::Hash
32
+ merge_hash!(args.first)
33
+ elsif streamid = args.first.to_s
34
+ if streamid.index(Header) == 0
35
+ merge_str!(streamid)
36
+ elsif streamid =~ URI::regexp
37
+ merge_uri!(URI(streamid))
38
+ else
39
+ @resource_name = streamid
40
+ end
41
+ end
42
+ end
43
+
44
+ def to_s
45
+ streamid = Header.dup
46
+
47
+ vars = []
48
+
49
+ vars << "r=#{resource_name}" if resource_name
50
+ vars << "u=#{user_name}" if user_name
51
+ vars << "m=#{mode}" if mode
52
+ vars << "h=#{host_name}" if host_name
53
+ vars << "t=#{type}" if type
54
+ vars << "s=#{sessionid}" if sessionid
55
+
56
+ extra.each { |key,val| vars << "#{key}=#{val}" }
57
+
58
+ streamid + vars.join(",")
59
+ end
60
+
61
+ def method_missing(name, *args)
62
+ return extra[name.to_s] if extra.key? name.to_s
63
+ match = name.to_s.match(/^(.*?)(=?)$/)
64
+ case match[2]
65
+ when "="
66
+ @extra[match[1]] = args.first
67
+ else
68
+ return nil
69
+ end
70
+ end
71
+
72
+ def set(key, val)
73
+ case key.to_s
74
+ when 'resource_name', 'r' then @resource_name = val
75
+ when 'user_name', 'u' then @user_name = val
76
+ when 'mode', 'm' then @mode = val.to_sym if Modes.include?(val.to_s)
77
+ when 'host_name', 'h'
78
+ if sep = val.index("/")
79
+ @host_name = val[0..(sep - 1)]
80
+ (@resource_name = val[(sep + 1)..-1] unless @resource_name)
81
+ else
82
+ @host_name = val
83
+ end
84
+ when 'type', 't' then (@type = val.to_sym if Types.include?(val.to_s))
85
+ when 'sessionid', 's' then @sessionid = val
86
+ else @extra[key] = val
87
+ end
88
+ end
89
+
90
+ def merge_uri!(streamid)
91
+ uri = URI(streamid)
92
+
93
+ @host_name = uri.hostname
94
+ @resource_name = uri.path[1..-1] if uri.path
95
+
96
+ if uri.query && form = URI.decode_www_form(uri.query)
97
+ merge_hash!(Hash[form])
98
+ end
99
+ end
100
+
101
+ def merge_str!(streamid)
102
+ streamid.scan(/([a-z0-9_-]+?)=(.+?)(,|$)/i).each do |key,val,_|
103
+ set(key, val)
104
+ end
105
+ end
106
+
107
+ def merge_hash!(hash)
108
+ hash.each do |key, val|
109
+ set(key, val)
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,3 @@
1
+ module SRT
2
+ VERSION = "0.1.0"
3
+ end
data/lib/rbsrt.rb ADDED
@@ -0,0 +1,5 @@
1
+ $:.push File.expand_path("../", __FILE__)
2
+
3
+ require_relative "rbsrt/version"
4
+ require_relative "rbsrt/streamid_components"
5
+ require_relative "rbsrt/rbsrt"
data/rbsrt.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require "rbsrt/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rbsrt'
7
+ s.version = SRT::VERSION
8
+ s.licenses = ['MPLv2.0', 'MIT']
9
+ s.summary = "Ruby API for SRT (Secure Reliable Transport)"
10
+ s.description = "Build SRT (Secure Reliable Transport) servers and clients with Ruby"
11
+ s.authors = ["Klaas Speller"]
12
+ s.email = ["klaas@recce.nl"]
13
+ s.files = Dir['README*.md', 'lib/**/*', 'ext/**/*', 'bin/**/*'] + ['Rakefile', 'rbsrt.gemspec']
14
+ s.test_files = Dir['test/**/*_test.rb']
15
+ s.bindir = "bin"
16
+ s.executables = ["rbsrt-server", "rbsrt-client"]
17
+ s.homepage = 'https://github.com/spllr/rbsrt'
18
+ s.metadata = { "source_code_uri" => "https://github.com/spllr/rbsrt" }
19
+ s.extensions = %w[ext/rbsrt/extconf.rb]
20
+ s.required_ruby_version = ">= 2.2.0"
21
+ s.add_development_dependency "rake-compiler", "~> 1.0"
22
+ end
@@ -0,0 +1,153 @@
1
+ require 'minitest/spec'
2
+
3
+ require "rbsrt"
4
+ require "thread"
5
+
6
+ describe SRT::Poll do
7
+ it "can be created" do
8
+ assert_instance_of(SRT::Poll, SRT::Poll.new)
9
+ end
10
+
11
+
12
+
13
+ describe "monitor server sockets" do
14
+ before do
15
+ # puts "server start"
16
+ @server = SRT::Socket.new
17
+ @server.bind "127.0.0.1", "6789"
18
+ @server.listen 2
19
+ end
20
+
21
+ after do
22
+ # puts "server stop"
23
+ @client.close if @client
24
+ @server.close if @server
25
+ end
26
+
27
+ it "will trigger when an new connection is available" do
28
+ poll = SRT::Poll.new
29
+
30
+ poll.add @server, :in
31
+
32
+ Thread.new do
33
+ # puts "connect to server"
34
+ @client = SRT::Socket.new
35
+ @client.connect "127.0.0.1", "6789"
36
+ end
37
+
38
+
39
+ # block/ yield style
40
+
41
+ did_call = false
42
+
43
+ poll.wait do |readable, writable, errors|
44
+ did_call = true
45
+ refute_empty readable
46
+ assert_empty writable
47
+ assert_empty errors
48
+
49
+ assert_equal @server, readable.first
50
+
51
+ @accepted_sock = readable.first.accept
52
+
53
+ poll.add @accepted_sock, :in, :err
54
+ end
55
+
56
+ assert_equal true, did_call, "wait block must yield"
57
+
58
+ # return style
59
+
60
+ Thread.new do
61
+ # puts "write data to server"
62
+ @client.sendmsg "data from client"
63
+ end
64
+
65
+ readable, writable, errors = poll.wait 1000
66
+
67
+ refute_empty readable
68
+ assert_empty writable
69
+ assert_empty errors
70
+
71
+ assert_equal @accepted_sock, readable.first
72
+
73
+ assert_equal "data from client", readable.first.recvmsg
74
+
75
+ # removing sockets
76
+
77
+ poll.remove @client
78
+
79
+ Thread.new do
80
+ # puts "write data to server"
81
+ @client.sendmsg "data from client"
82
+ end
83
+
84
+ readable, writable, errors = poll.wait 100
85
+
86
+ assert_empty readable
87
+ assert_empty writable
88
+ assert_empty errors
89
+ end
90
+ end
91
+
92
+
93
+ describe "adding and updating sockets" do
94
+ before do
95
+ # puts "server start"
96
+ @server = SRT::Socket.new
97
+ @server.bind "127.0.0.1", "6789"
98
+ @server.listen 2
99
+ end
100
+
101
+ after do
102
+ # puts "server stop"
103
+ @client.close if @client
104
+ @server.close if @server
105
+ end
106
+
107
+ it "can update a socket" do
108
+ poll = SRT::Poll.new
109
+
110
+ poll.add @server, :in
111
+
112
+ Thread.new do
113
+ @client = SRT::Socket.new
114
+ @client.connect "127.0.0.1", "6789"
115
+ end
116
+
117
+ readable, _, _ = poll.wait 100
118
+
119
+ remote_client = readable.first.accept
120
+
121
+ # puts "++ IN OUT"
122
+ poll.add remote_client, :err
123
+ # puts "-- IN OUT"
124
+
125
+ Thread.new do
126
+ @client.write "foobar 1"
127
+ end
128
+
129
+ readable, writable, errors = poll.wait 100
130
+
131
+ assert_empty readable
132
+ assert_empty writable
133
+ assert_empty errors
134
+
135
+ _ = remote_client.read
136
+
137
+ # upddate
138
+
139
+ poll.update remote_client, :in
140
+
141
+ Thread.new do
142
+ @client.write "foobar 2"
143
+ end
144
+
145
+ readable, writable, errors = poll.wait 100
146
+
147
+ # pending
148
+ # refute_empty readable
149
+ # assert_empty writable
150
+ # assert_empty errors
151
+ end
152
+ end
153
+ end