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/README.md
ADDED
@@ -0,0 +1,752 @@
|
|
1
|
+
# Ruby SRT API [WIP]
|
2
|
+
|
3
|
+
A ruby gem which you can use to build [SRT (Secure Reliable Transport)](https://github.com/Haivision/srt "Haivisionsrt") Servers and Clients.
|
4
|
+
|
5
|
+
> Secure Reliable Transport (SRT) is an open source transport technology that optimizes streaming performance across unpredictable networks, such as the Internet.
|
6
|
+
>
|
7
|
+
> From: Haivision
|
8
|
+
|
9
|
+
Ruby SRT is a Work in Progress, please [create an issue if you find any bugs, leaks, or would like to request additional API](https://github.com/spllr/rbsrt/issues).
|
10
|
+
|
11
|
+
|
12
|
+
## Table Of Contents
|
13
|
+
|
14
|
+
- [Ruby SRT API [WIP]](#ruby-srt-api-wip)
|
15
|
+
- [Table Of Contents](#table-of-contents)
|
16
|
+
- [Installation](#installation)
|
17
|
+
- [Dependencies](#dependencies)
|
18
|
+
- [rbsrt gem](#rbsrt-gem)
|
19
|
+
- [Examples](#examples)
|
20
|
+
- [A Simple SRT Socket Server In File Mode](#a-simple-srt-socket-server-in-file-mode)
|
21
|
+
- [A Simple Socket Client In File Mode](#a-simple-socket-client-in-file-mode)
|
22
|
+
- [A Simple SRT Socket Server In Live Mode](#a-simple-srt-socket-server-in-live-mode)
|
23
|
+
- [A Simple Socket Client In Live Mode](#a-simple-socket-client-in-live-mode)
|
24
|
+
- [A Simple Recording Server](#a-simple-recording-server)
|
25
|
+
- [A Simple ffmpeg Sending Client](#a-simple-ffmpeg-sending-client)
|
26
|
+
- [API](#api)
|
27
|
+
- [`SRT` Module](#srt-module)
|
28
|
+
- [`SRT::Socket` Class](#srtsocket-class)
|
29
|
+
- [`SRT::Server` Class](#srtserver-class)
|
30
|
+
- [`SRT::Connection` Class](#srtconnection-class)
|
31
|
+
- [`SRT::Client` Class](#srtclient-class)
|
32
|
+
- [`SRT::Poll` Class](#srtpoll-class)
|
33
|
+
- [`SRT::StreamIDComponents` Class](#srtstreamidcomponents-class)
|
34
|
+
- [`SRT::Stats` Class](#srtstats-class)
|
35
|
+
- [`SRT::Error` Classes](#srterror-classes)
|
36
|
+
- [License](#license)
|
37
|
+
|
38
|
+
## Installation
|
39
|
+
|
40
|
+
Currently rbsrt must be build with llvm/clang. This will change in the future.
|
41
|
+
|
42
|
+
The gem requires Ruby 2.2 or higher.
|
43
|
+
|
44
|
+
|
45
|
+
### Dependencies
|
46
|
+
|
47
|
+
You will need to install the SRT library. Visit the [SRT Github Repo](https://github.com/Haivision/srt "SRT On Github") for detailed installation instructions.
|
48
|
+
|
49
|
+
On macOs run you can run `brew install srt` to install.
|
50
|
+
|
51
|
+
|
52
|
+
### rbsrt gem
|
53
|
+
|
54
|
+
Install with rubygems:
|
55
|
+
|
56
|
+
```sh
|
57
|
+
gem install rbsrt
|
58
|
+
```
|
59
|
+
|
60
|
+
|
61
|
+
Alternativly you can install the rbsrt Ruby gem from source.
|
62
|
+
|
63
|
+
Clone the git repo:
|
64
|
+
|
65
|
+
```sh
|
66
|
+
git clone https://github.com/spllr/rbsrt.git
|
67
|
+
```
|
68
|
+
|
69
|
+
Install:
|
70
|
+
|
71
|
+
```
|
72
|
+
cd rbsrt
|
73
|
+
rake install
|
74
|
+
```
|
75
|
+
|
76
|
+
|
77
|
+
## Examples
|
78
|
+
|
79
|
+
### A Simple SRT Socket Server In File Mode
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
server = SRT::Socket.new
|
83
|
+
server.transmission_mode = :file
|
84
|
+
|
85
|
+
puts "server state=#{server.state}, id=#{server.id}"
|
86
|
+
|
87
|
+
server.bind "127.0.0.1", "5556"
|
88
|
+
|
89
|
+
puts "server #{server.state}"
|
90
|
+
|
91
|
+
server.listen 3
|
92
|
+
|
93
|
+
puts "server #{server.state}"
|
94
|
+
|
95
|
+
client = server.accept
|
96
|
+
|
97
|
+
puts "server accepted: streamid=\"#{client.streamid}\", id=#{client.id}, tsbpdmode=#{client.tsbpdmode?}"
|
98
|
+
|
99
|
+
loop do
|
100
|
+
break unless client.connected?
|
101
|
+
break unless data = client.recvmsg
|
102
|
+
puts "server received: #{data}"
|
103
|
+
rescue SRT::Error::CONNLOST => e
|
104
|
+
puts "connection lost: #{e}"
|
105
|
+
break
|
106
|
+
rescue SRT::Error => e
|
107
|
+
puts "server error: #{e.class}"
|
108
|
+
end
|
109
|
+
|
110
|
+
puts "client closed #{client.closed?}"
|
111
|
+
|
112
|
+
server.close
|
113
|
+
|
114
|
+
puts "server done"
|
115
|
+
```
|
116
|
+
|
117
|
+
### A Simple Socket Client In File Mode
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
client = SRT::Socket.new
|
121
|
+
|
122
|
+
client.streamid = "a ruby srt socket"
|
123
|
+
client.transmission_mode = :file
|
124
|
+
|
125
|
+
client.connect "127.0.0.1", "5556"
|
126
|
+
|
127
|
+
10.times do |i|
|
128
|
+
payload = "Hello from ruby client #{i}"
|
129
|
+
puts "will send: \"#{payload}\""
|
130
|
+
client.sendmsg "Hello from ruby client #{i}"
|
131
|
+
puts "did send: \"#{payload}\""
|
132
|
+
rescue SRT::Error => e
|
133
|
+
puts "client error: #{e}"
|
134
|
+
end
|
135
|
+
|
136
|
+
client.close
|
137
|
+
```
|
138
|
+
|
139
|
+
### A Simple SRT Socket Server In Live Mode
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
server = SRT::Socket.new
|
143
|
+
server.transmission_mode = :live
|
144
|
+
|
145
|
+
puts "server state=#{server.state}, id=#{server.id}"
|
146
|
+
|
147
|
+
server.bind "127.0.0.1", "5556"
|
148
|
+
|
149
|
+
puts "server #{server.state}"
|
150
|
+
|
151
|
+
server.listen 3
|
152
|
+
|
153
|
+
puts "server #{server.state}"
|
154
|
+
|
155
|
+
client = server.accept
|
156
|
+
|
157
|
+
puts "server accepted: streamid=\"#{client.streamid}\", id=#{client.id}, tsbpdmode=#{client.tsbpdmode?}"
|
158
|
+
|
159
|
+
loop do
|
160
|
+
break unless client.connected?
|
161
|
+
break unless data = client.recvmsg
|
162
|
+
puts "server received: #{data}"
|
163
|
+
rescue SRT::Error::CONNLOST => e
|
164
|
+
puts "connection lost: #{e}"
|
165
|
+
break
|
166
|
+
rescue SRT::Error => e
|
167
|
+
puts "server error: #{e.class}"
|
168
|
+
end
|
169
|
+
|
170
|
+
puts "client closed #{client.closed?}"
|
171
|
+
|
172
|
+
server.close
|
173
|
+
|
174
|
+
puts "server done"
|
175
|
+
```
|
176
|
+
|
177
|
+
### A Simple Socket Client In Live Mode
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
client = SRT::Socket.new
|
181
|
+
|
182
|
+
client.streamid = "a ruby srt socket"
|
183
|
+
client.transmission_mode = :live
|
184
|
+
|
185
|
+
client.connect "127.0.0.1", "5556"
|
186
|
+
|
187
|
+
100.times do |i|
|
188
|
+
payload = "Hello from ruby client #{i}"
|
189
|
+
client.sendmsg "Hello from ruby client #{i}"
|
190
|
+
sleep 1 / 30 # mimic framerate
|
191
|
+
rescue SRT::Error => e
|
192
|
+
puts "client error: #{e}"
|
193
|
+
end
|
194
|
+
|
195
|
+
client.close
|
196
|
+
```
|
197
|
+
|
198
|
+
### A Simple Recording Server
|
199
|
+
|
200
|
+
This example shows how a naive recorder server can be build.
|
201
|
+
|
202
|
+
The server will accept incomming SRT connections and will write whatever comes in to a file on disk.
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
require 'rbsrt'
|
206
|
+
|
207
|
+
server = SRT::Server.new "0.0.0.0", "5555"
|
208
|
+
|
209
|
+
server.start do |connection|
|
210
|
+
|
211
|
+
streaminfo = SRT::StreamIDComponents.new connection.streamid
|
212
|
+
|
213
|
+
puts "new connection: streamid=#{streaminfo.resource_name}, connections=#{connection_count}, id=#{connection.id}"
|
214
|
+
|
215
|
+
# only handle publishing clients
|
216
|
+
return false unless streaminfo.mode == :publish
|
217
|
+
|
218
|
+
output_file = File.new "recording-#{Process.pid}-#{connection.id}", "w+"
|
219
|
+
output_file.close_on_exec = true
|
220
|
+
|
221
|
+
connection.at_data do |chunk|
|
222
|
+
puts "received data"
|
223
|
+
output_file.write(chunk)
|
224
|
+
end
|
225
|
+
|
226
|
+
connection.at_close do
|
227
|
+
puts "closed connection"
|
228
|
+
output_file.close
|
229
|
+
end
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
|
234
|
+
### A Simple ffmpeg Sending Client
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
require 'rbsrt'
|
238
|
+
require 'uri'
|
239
|
+
|
240
|
+
puts "create srt client"
|
241
|
+
|
242
|
+
client = SRT::Client.new
|
243
|
+
|
244
|
+
streaminfo = SRT::StreamIDComponents.new :mode => :publish,
|
245
|
+
:type => :stream,
|
246
|
+
:resource_name => "my_movie.ts"
|
247
|
+
|
248
|
+
client.streamid = streaminfo.to_s
|
249
|
+
|
250
|
+
at_exit { client.close }
|
251
|
+
|
252
|
+
begin
|
253
|
+
client.connect "127.0.0.1", "5555"
|
254
|
+
rescue SRT::Error => e
|
255
|
+
puts "A STR Error occurred. #{e.message}"
|
256
|
+
exit 1
|
257
|
+
rescue StandardError => e
|
258
|
+
puts "Something went wrong: #{e.message}"
|
259
|
+
exit 1
|
260
|
+
end
|
261
|
+
|
262
|
+
# run a ffmpeg command and write stdout to the client
|
263
|
+
require 'open3'
|
264
|
+
|
265
|
+
cmd = "ffmpeg -re -stream_loop 10 -i my_movie.ts -codec copy -f mpegts -"
|
266
|
+
|
267
|
+
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
|
268
|
+
stdout.each do |buf|
|
269
|
+
client.sendmsg buf
|
270
|
+
end
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
274
|
+
## API
|
275
|
+
|
276
|
+
Also see the [Haivision SRT docs](https://github.com/Haivision/srt/tree/master/docs "Haivision SRT docs"), specificly the [API-functions](https://github.com/Haivision/srt/blob/master/docs/API-functions.md) and [API](https://github.com/Haivision/srt/blob/master/docs/API.md) documents, for more information about SRT, it's API and underlaying concepts.
|
277
|
+
|
278
|
+
The Ruby SRT gem comes with the following items:
|
279
|
+
|
280
|
+
|
281
|
+
| Item | Kind | Description |
|
282
|
+
|-------|------|-------------|
|
283
|
+
| `SRT` | Module | The root module |
|
284
|
+
| `SRT::Socket` | Class | A general purpose SRT Socket |
|
285
|
+
| `SRT::Server` | Class | A multi-client SRT Server |
|
286
|
+
| `SRT::Connection` | Class | Used by SRT::Server to represent a client |
|
287
|
+
| `SRT::Client` | Class | A SRT Client |
|
288
|
+
| `SRT::Stats` | Class | Used to obtain statistics from a socket |
|
289
|
+
| `SRT::StreamIDComponents` | Class | SRT Access Control complient streamid parser and compiler |
|
290
|
+
| `SRT::Error` | Class | The base class for a number of SRT specific errors |
|
291
|
+
|
292
|
+
|
293
|
+
### `SRT` Module
|
294
|
+
|
295
|
+
The `SRT` module has the following constants:
|
296
|
+
|
297
|
+
| Name | Kind | Description |
|
298
|
+
|------|------|-------------|
|
299
|
+
| VERSION | String | Gem version string |
|
300
|
+
| SRT_VERSION | String | The version of the linked libsrt |
|
301
|
+
|
302
|
+
|
303
|
+
### `SRT::Socket` Class
|
304
|
+
|
305
|
+
The `SRT::Socket` class is a general purpose SRT socket. It can be used to create both servers and clients.
|
306
|
+
|
307
|
+
The `SRT::Socket` supports the following methods:
|
308
|
+
|
309
|
+
| Name | Kind | Description |
|
310
|
+
|------|------|-------------|
|
311
|
+
| #accept | `SRT::Socket` | Accept a new connection |
|
312
|
+
| #bind(address, port) | | Bind the socket to an address and port |
|
313
|
+
| #broken? | Bool | True when the socket state is `:broken` |
|
314
|
+
| #close | | Closes the socket |
|
315
|
+
| #closed? | Bool | True the when the socket state is `:closed` |
|
316
|
+
| #closing? | Bool | True the when the socket state is `:closing` |
|
317
|
+
| #connect(address, port) | | Opens a connection to a server at `srt://#{address}:#{port}` |
|
318
|
+
| #connected? | Bool | True the when the socket state is `:conneted` |
|
319
|
+
| #connecting? | Bool | True the when the socket state is `:connecting` |
|
320
|
+
| #id | Any | An identifier for the socket. This identifier will be unique for all sockets existing at any one time but might not be unique over the lifetime of a script |
|
321
|
+
| #listen(maxbacklog) | | Start listening. Must be called after `#bind` |
|
322
|
+
| #listening? | Bool | True the when the socket state is `:listening` |
|
323
|
+
| #nonexist? | Bool | True the when the socket state is `:nonexist` |
|
324
|
+
| #opened? | Bool | True the when the socket state is `:opened` |
|
325
|
+
| #rcvsyn= | Bool | Alias for `#read_sync` |
|
326
|
+
| #rcvsyn? | Bool | Alias for `#read_sync?` |
|
327
|
+
| #read | String | Alias for `#recvmsg` |
|
328
|
+
| #read_sync= | Bool | When true, set the socket to read in a non-blocking manner |
|
329
|
+
| #read_sync? | Bool | True when the socket is readable in a non-blocking manner |
|
330
|
+
| #ready? | Bool | True when the socket is ready for usage (e.g. initialized) |
|
331
|
+
| #recvmsg | String | Read data from the socket |
|
332
|
+
| #sendmsg(string) | String | Send bytes to the socket |
|
333
|
+
| #sndsyn= | Bool | Alias of `#write_sync=` |
|
334
|
+
| #sndsyn? | Bool | Alias of `#write_sync?` |
|
335
|
+
| #state | Symbol | Returns the state of the socket. Can be one of: `:broken`, `:closed`, `:closing`, `:connected`, `:connecting`, `:listening`, `:nonexist`, `:opened`, `:ready` |
|
336
|
+
| #streamid | String | The streamid of the socket if supplied |
|
337
|
+
| #streamid= | String | The streamid of the socket, must be 512 characters or less |
|
338
|
+
| #timestamp_based_packet_delivery_mode= | Bool | Indicates if the sending socket will control the timed delivery of data (e.g. video stream) |
|
339
|
+
| #timestamp_based_packet_delivery_mode? | Bool | True if the sending socket controls the timing of data delivery |
|
340
|
+
| #trans_mode= | Symbol | Alias for `#transmission_mode=` |
|
341
|
+
| #transmission_mode= | Symbol | Controls how the socket expects data transmission. Can be set to `:live` or `:file` |
|
342
|
+
| #transtype= | Symbol | Alias for `#transmission_mode=` |
|
343
|
+
| #tsbpdmode= | Bool | Alias of `#timestamp_based_packet_delivery_mode=` |
|
344
|
+
| #tsbpdmode? | Bool | Alias of `#timestamp_based_packet_delivery_mode?` |
|
345
|
+
| #write | String | Alias of `#sendmsg` |
|
346
|
+
| #write_sync= | Any | When true, set the socket to write in a non-blocking manner |
|
347
|
+
| #write_sync? | Any | True when the socket is writable in a non-blocking manner |
|
348
|
+
|
349
|
+
|
350
|
+
### `SRT::Server` Class
|
351
|
+
|
352
|
+
The `SRT::Server` class is an implementation of a multi-client SRT server. It does not inherit from `SRT::Socket` but has similar API where applicable.
|
353
|
+
|
354
|
+
The `SRT::Server` is a higher level abstraction freeing the developer of much of the boiletplate of building a server.
|
355
|
+
|
356
|
+
The `SRT::Server` will `yield` a new `SRT::Connection` instance when a new client connects.
|
357
|
+
|
358
|
+
The `SRT::Server` supports the following methods:
|
359
|
+
|
360
|
+
The constructor takes 2 aguments, an address and a port.Both must be strings.
|
361
|
+
|
362
|
+
| Name | Kind | Description |
|
363
|
+
|------|------|-------------|
|
364
|
+
| #broken? | Bool | True when the server socket state is `:broken` |
|
365
|
+
| #closed? | Bool | True the when the server socket state is `:closed` |
|
366
|
+
| #closing? | Bool | True the when the server socket state is `:closing` |
|
367
|
+
| #connected? | Bool | True the when the server socket state is `:conneted` |
|
368
|
+
| #connecting? | Bool | True the when the server socket state is `:connecting` |
|
369
|
+
| #listening? | Bool | True the when the server socket state is `:listening` |
|
370
|
+
| #nonexist? | Bool | True the when the server socket state is `:nonexist` |
|
371
|
+
| #opened? | Bool | True the when the server socket state is `:opened` |
|
372
|
+
| #rcvsyn? | Bool | Alias for `#read_sync?` |
|
373
|
+
| #read_sync? | Bool | True when the server socket is readable in a non-blocking manner |
|
374
|
+
| #ready? | Bool | True when the server socket is ready for usage (e.g. initialized) |
|
375
|
+
| #start(&blck) | Bool | Starts the servers. The block will be executed each time a new connection is accepted. Return a falsy value to reject the connection. The block will executed with the `self` set to the server |
|
376
|
+
|
377
|
+
|
378
|
+
### `SRT::Connection` Class
|
379
|
+
|
380
|
+
The `SRT::Connection` class is used by the `SRT::Server`. You should not have to instantiate instances of this class yourself.
|
381
|
+
|
382
|
+
`SRT::Connection` does not inherit from `SRT::Socket` but has similar API where applicable.
|
383
|
+
|
384
|
+
Instances of `SRT::Connection` support the following methods:
|
385
|
+
|
386
|
+
|
387
|
+
| Name | Kind | Description |
|
388
|
+
|------|------|-------------|
|
389
|
+
| #at_close(&blck) | Block | A block which will be called when the connection closed |
|
390
|
+
| #at_data(&block) | Block | A block which will be called when new data was read |
|
391
|
+
| #broken? | Bool | True when the connection socket state is `:broken` |
|
392
|
+
| #closed? | Bool | True the when the connection socket state is `:closed` |
|
393
|
+
| #closing? | Bool | True the when the connection socket state is `:closing` |
|
394
|
+
| #connected? | Bool | True the when the connection socket state is `:conneted` |
|
395
|
+
| #connecting? | Bool | True the when the connection socket state is `:connecting` |
|
396
|
+
| #id | Any | An identifier for the connection. This identifier will be unique for all sockets existing at any one time but might not be unique over the lifetime of a script |
|
397
|
+
| #listening? | Bool | True the when the connection socket state is `:listening` |
|
398
|
+
| #nonexist? | Bool | True the when the connection socket state is `:nonexist` |
|
399
|
+
| #opened? | Bool | True the when the connection socket state is `:opened` |
|
400
|
+
| #ready? | Bool | True when the connection socket is ready for usage (e.g. initialized) |
|
401
|
+
| #sendmsg(string) | String | Send bytes to the socket |
|
402
|
+
| #sndsyn= | Bool | Alias of `#write_sync=` |
|
403
|
+
| #sndsyn? | Bool | Alias of `#write_sync?` |
|
404
|
+
| #state | Symbol | Returns the state of the socket. Can be one of: `:broken`, `:closed`, `:closing`, `:connected`, `:connecting`, `:listening`, `:nonexist`, `:opened`, `:ready` |
|
405
|
+
| #streamid | String | The streamid of the socket if supplied |
|
406
|
+
| #streamid= | String | The streamid of the socket, must be 512 characters or less |
|
407
|
+
| #timestamp_based_packet_delivery_mode= | Bool | Indicates if the sending socket will control the timed delivery of data (e.g. video stream) |
|
408
|
+
| #timestamp_based_packet_delivery_mode? | Bool | True if the sending socket controls the timing of data delivery |
|
409
|
+
| #trans_mode= | Symbol | Alias for `#transmission_mode=` |
|
410
|
+
| #transmission_mode= | Symbol | Controls how the socket expects data transmission. Can be set to `:live` or `:file` |
|
411
|
+
| #transtype= | Symbol | Alias for `#transmission_mode=` |
|
412
|
+
| #tsbpdmode= | Bool | Alias of `#timestamp_based_packet_delivery_mode=` |
|
413
|
+
| #tsbpdmode? | Bool | Alias of `#timestamp_based_packet_delivery_mode?` |
|
414
|
+
| #write | String | Alias of `#sendmsg` |
|
415
|
+
| #write_sync= | Any | When true, set the socket to write in a non-blocking manner |
|
416
|
+
| #write_sync? | Any | True when the socket is writable in a non-blocking manner |
|
417
|
+
|
418
|
+
|
419
|
+
### `SRT::Client` Class
|
420
|
+
|
421
|
+
The `SRT::Client` can be used to connect to a SRT server.
|
422
|
+
|
423
|
+
Instances of `SRT::Client` support the following methods and attributes:
|
424
|
+
|
425
|
+
| Name | Kind | Description |
|
426
|
+
|------|------|-------------|
|
427
|
+
| #broken? | Bool | True when the socket state is `:broken` |
|
428
|
+
| #close | | Closes the socket |
|
429
|
+
| #closed? | Bool | True the when the socket state is `:closed` |
|
430
|
+
| #closing? | Bool | True the when the socket state is `:closing` |
|
431
|
+
| #connect(address, port) | | Opens a connection to a server at `srt://#{address}:#{port}` |
|
432
|
+
| #connected? | Bool | True the when the socket state is `:conneted` |
|
433
|
+
| #connecting? | Bool | True the when the socket state is `:connecting` |
|
434
|
+
| #id | Any | An identifier for the socket. This identifier will be unique for all sockets existing at any one time but might not be unique over the lifetime of a script |
|
435
|
+
| #listening? | Bool | True the when the socket state is `:listening` |
|
436
|
+
| #nonexist? | Bool | True the when the socket state is `:nonexist` |
|
437
|
+
| #opened? | Bool | True the when the socket state is `:opened` |
|
438
|
+
| #rcvsyn= | Bool | Alias for `#read_sync` |
|
439
|
+
| #rcvsyn? | Bool | Alias for `#read_sync?` |
|
440
|
+
| #read | String | Alias for `#recvmsg` |
|
441
|
+
| #read_sync= | Bool | When true, set the socket to read in a non-blocking manner |
|
442
|
+
| #read_sync? | Bool | True when the socket is readable in a non-blocking manner |
|
443
|
+
| #ready? | Bool | True when the socket is ready for usage (e.g. initialized) |
|
444
|
+
| #recvmsg | String | Read data from the socket |
|
445
|
+
| #sendmsg(string) | String | Send bytes to the socket |
|
446
|
+
| #sndsyn= | Bool | Alias of `#write_sync=` |
|
447
|
+
| #sndsyn? | Bool | Alias of `#write_sync?` |
|
448
|
+
| #state | Symbol | Returns the state of the socket. Can be one of: `:broken`, `:closed`, `:closing`, `:connected`, `:connecting`, `:listening`, `:nonexist`, `:opened`, `:ready` |
|
449
|
+
| #streamid | String | The streamid of the socket if supplied |
|
450
|
+
| #streamid= | String | The streamid of the socket, must be 512 characters or less |
|
451
|
+
| #timestamp_based_packet_delivery_mode= | Bool | Indicates if the sending socket will control the timed delivery of data (e.g. video stream) |
|
452
|
+
| #timestamp_based_packet_delivery_mode? | Bool | True if the sending socket controls the timing of data delivery |
|
453
|
+
| #trans_mode= | Symbol | Alias for `#transmission_mode=` |
|
454
|
+
| #transmission_mode= | Symbol | Controls how the socket expects data transmission. Can be set to `:live` or `:file` |
|
455
|
+
| #transtype= | Symbol | Alias for `#transmission_mode=` |
|
456
|
+
| #tsbpdmode= | Bool | Alias of `#timestamp_based_packet_delivery_mode=` |
|
457
|
+
| #tsbpdmode? | Bool | Alias of `#timestamp_based_packet_delivery_mode?` |
|
458
|
+
| #write | String | Alias of `#sendmsg` |
|
459
|
+
| #write_sync= | Any | When true, set the socket to write in a non-blocking manner |
|
460
|
+
| #write_sync? | Any | True when the socket is writable in a non-blocking manner |
|
461
|
+
|
462
|
+
|
463
|
+
### `SRT::Poll` Class
|
464
|
+
|
465
|
+
The `SRT::Poll` class provides a way to handle multiple sockets simultaneously. It's function is similar to `IO.select`.
|
466
|
+
|
467
|
+
For example, you could have create a multi-client server using `SRT::Poll`:
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
require "rbsrt"
|
471
|
+
|
472
|
+
server = SRT::Socket.new
|
473
|
+
|
474
|
+
server = SRT::Socket.new
|
475
|
+
server.bind "0.0.0.0", "6789"
|
476
|
+
server.listen 3
|
477
|
+
|
478
|
+
poll = SRT::Poll.new
|
479
|
+
|
480
|
+
poll.add server, :in
|
481
|
+
|
482
|
+
loop do
|
483
|
+
poll.wait do |readable, writable, errors|
|
484
|
+
readable.each do |socket|
|
485
|
+
if socket == server
|
486
|
+
client = socket.accept # accept new client
|
487
|
+
poll.add client, :in, :out, :err # add client to the poll
|
488
|
+
puts "accepted client"
|
489
|
+
else
|
490
|
+
data = socket.recvmsg # read data from a client
|
491
|
+
puts "received data"
|
492
|
+
poll.remote socket unless data # remove client from the poll
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
```
|
498
|
+
|
499
|
+
`SRT::Poll` supports the following actions:
|
500
|
+
|
501
|
+
| Name | Alias | Description |
|
502
|
+
|--|--|--|
|
503
|
+
| `:in` | `:read` | report readiness for reading or incoming connection on a listener socket |
|
504
|
+
| `:out` | `:write` | report readiness for writing or a successful connection |
|
505
|
+
| `:err` | `:error` | report errors on the socket |
|
506
|
+
| `:et` | `:edge` | the event will be edge-triggered. In the edge-triggered mode the function will only return socket states that have changed since the last call. |
|
507
|
+
|
508
|
+
Instances of `SRT::Poll` supports the following methods:
|
509
|
+
|
510
|
+
| Name | Kind | Description |
|
511
|
+
|------|------|-------------|
|
512
|
+
| `#add(sock, *flags)` | Bool | Add a socket to the Poll |
|
513
|
+
| `#remove(sock)` | Socket | Remove a socket from the Poll |
|
514
|
+
| `#update(sock, *flags)` | Update the flags for the socket |
|
515
|
+
|
516
|
+
For more info see the [Asynchronous Operations Epoll](https://github.com/Haivision/srt/blob/master/docs/API-functions.md#Asynchronous-operations-epoll "Asynchronous-operations-epoll") section in the SRT docs.
|
517
|
+
|
518
|
+
### `SRT::StreamIDComponents` Class
|
519
|
+
|
520
|
+
SRT provides a [Access Control Guideline](https://github.com/Haivision/srt/blob/master/docs/AccessControl.md "SRT Access Control Guidelines") allowing a more fine grained method of specifying the intent of connection. Using the "#streamid" clients and servers can pack a number of properties on the socket.
|
521
|
+
|
522
|
+
The `SRT::StreamIDComponents` class can be used to parse and compile such an extended streamid string.
|
523
|
+
|
524
|
+
Instances of `SRT::StreamIDComponents` support the following methods and attributes:
|
525
|
+
|
526
|
+
| Name | Kind | Description |
|
527
|
+
|------|------|-------------|
|
528
|
+
| #host_name | String | The hostname associated with the socket |
|
529
|
+
| #host_name= | String | Set the host associated with the socket. When the host has a pathname, and no other `#resource_name` is specified, the path will will be used as the `#resource_name`. |
|
530
|
+
| #mode | Symbol | The mode associated with the socket. Can be one of: `:request`, `:publish`, `:bidirectional` |
|
531
|
+
| #mode= | Any | Set the mode associated with the socket. Can be one of: `:request`, `:publish`, `:bidirectional` |
|
532
|
+
| #resource_name | Any | The resource name associated with the socket. e.g. "stream1", "/movies/butterfly.ts", "movies.ts?gid=1234" |
|
533
|
+
| #resource_name= | Any | Set the resource name associated with the socket. |
|
534
|
+
| #sessionid | Any | A temporary resource identifier negotiated with the server, used just for verification. Useful when using a different authentication server to negotiate access to a resource. |
|
535
|
+
| #sessionid= | Any | Set the session id |
|
536
|
+
| #to_s | Any | Compiles the Access Control string |
|
537
|
+
| #type | Any | The type associated with the socket. Can be one of `:stream`, `:file`, `:auth` |
|
538
|
+
| #type= | Any | Set the type associated with the socket. Can be one of `:stream`, `:file`, `:auth` |
|
539
|
+
| #user_name | Any | The user name associated with the socket |
|
540
|
+
| #user_name= | Any | Set the user name associated with the socket |
|
541
|
+
|
542
|
+
You can set and get any non-standard property on the `SRT::StreamIDComponents` by simply calling it's getter or setter method:
|
543
|
+
|
544
|
+
```ruby
|
545
|
+
streamid = SRT::StreamIDComponents.new
|
546
|
+
|
547
|
+
# standard
|
548
|
+
|
549
|
+
streamid.mode = :publish
|
550
|
+
streamid.type = :live
|
551
|
+
streamid.resource_name = "movie1.ts"
|
552
|
+
|
553
|
+
# non standard
|
554
|
+
|
555
|
+
streamid.my_property = "foo"
|
556
|
+
streamid.bar = "baz"
|
557
|
+
|
558
|
+
```
|
559
|
+
|
560
|
+
You can use the `SRT::StreamIDComponents` to set and retrieve Access Control properties:
|
561
|
+
|
562
|
+
```ruby
|
563
|
+
# ... on the client side ...
|
564
|
+
|
565
|
+
client = SRT::Client.new
|
566
|
+
|
567
|
+
streamid = SRT::StreamIDComponents.new
|
568
|
+
streamid.mode = :publish
|
569
|
+
streamid.type = :live
|
570
|
+
streamid.resource_name = "movie1.ts"
|
571
|
+
|
572
|
+
client.streamid = streamid.to_s
|
573
|
+
|
574
|
+
# ...
|
575
|
+
|
576
|
+
|
577
|
+
# ... on the server side ...
|
578
|
+
|
579
|
+
client = server.accept
|
580
|
+
|
581
|
+
streamid = SRT::StreamIDComponents.new client.streamid
|
582
|
+
|
583
|
+
if streamid.mode == :publish
|
584
|
+
# read from the client
|
585
|
+
elsif streamid.mode == :request
|
586
|
+
# write to the client
|
587
|
+
end
|
588
|
+
|
589
|
+
# ...
|
590
|
+
```
|
591
|
+
|
592
|
+
You may also pass a hash to construct the `SRT::StreamIDComponents`:
|
593
|
+
|
594
|
+
```ruby
|
595
|
+
streamid = SRT::StreamIDComponents.new :mode => :publish,
|
596
|
+
:type => :live,
|
597
|
+
:resource_name => "my_movie.ts",
|
598
|
+
:user_name => "admin",
|
599
|
+
:sessionid => "12345",
|
600
|
+
:host_name => "stream.recce.nl",
|
601
|
+
:some_custom_property => "somevalue"
|
602
|
+
```
|
603
|
+
|
604
|
+
### `SRT::Stats` Class
|
605
|
+
|
606
|
+
The `SRT::Stats` class can be used to pull statistics from a `SRT::Socket`.
|
607
|
+
|
608
|
+
```ruby
|
609
|
+
stats = SRT::Stats.new my_socket_or_connection_or_server
|
610
|
+
|
611
|
+
puts stats.pkt_sent_total
|
612
|
+
```
|
613
|
+
|
614
|
+
The initializer takes a srt socket like instance and an optional `:clear => true/false` flag.
|
615
|
+
|
616
|
+
See https://github.com/Haivision/srt/blob/master/docs/statistics.md for more information about all the field.
|
617
|
+
|
618
|
+
|
619
|
+
Instances of `SRT::Stats` have the following properties:
|
620
|
+
|
621
|
+
|
622
|
+
| Name | Alias | Description |
|
623
|
+
|-----|---|---|
|
624
|
+
| `#msTimeStamp` | `#ms_time_stamp`, `#mstimestamp` | time since the UDT entity is started, in milliseconds |
|
625
|
+
| `#pktSentTotal` | `#pkt_sent_total`, `#pktsenttotal` | total number of sent data packets, including retransmissions |
|
626
|
+
| `#pktRecvTotal` | `#pkt_recv_total`, `#pktrecvtotal` | total number of received packets |
|
627
|
+
| `#pktSndLossTotal` | `#pkt_snd_loss_total`, `#pktsndlosstotal` | total number of lost packets (sender side) |
|
628
|
+
| `#pktRcvLossTotal` | `#pkt_rcv_loss_total`, `#pktrcvlosstotal` | total number of lost packets (receiver side) |
|
629
|
+
| `#pktRetransTotal` | `#pkt_retrans_total`, `#pktretranstotal` | total number of retransmitted packets |
|
630
|
+
| `#pktSentACKTotal` | `#pkt_sent_ack_total`, `#pktsentacktotal` | total number of sent ACK packets |
|
631
|
+
| `#pktRecvACKTotal` | `#pkt_recv_ack_total`, `#pktrecvacktotal` | total number of received ACK packets |
|
632
|
+
| `#pktSentNAKTotal` | `#pkt_sent_nak_total`, `#pktsentnaktotal` | total number of sent NAK packets |
|
633
|
+
| `#pktRecvNAKTotal` | `#pkt_recv_nak_total`, `#pktrecvnaktotal` | total number of received NAK packets |
|
634
|
+
| `#usSndDurationTotal` | `#us_snd_duration_total`, `#ussnddurationtotal` | total time duration when UDT is sending data (idle time exclusive) |
|
635
|
+
| `#pktSndDropTotal` | `#pkt_snd_drop_total`, `#pktsnddroptotal` | number of too-late-to-send dropped packets |
|
636
|
+
| `#pktRcvDropTotal` | `#pkt_rcv_drop_total`, `#pktrcvdroptotal` | number of too-late-to play missing packets |
|
637
|
+
| `#pktRcvUndecryptTotal` | `#pkt_rcv_undecrypt_total`, `#pktrcvundecrypttotal` | number of undecrypted packets |
|
638
|
+
| `#pktSndFilterExtraTotal` | `#pkt_snd_filter_extra_total`, `#pktsndfilterextratotal` | number of control packets supplied by packet filter |
|
639
|
+
| `#pktRcvFilterExtraTotal` | `#pkt_rcv_filter_extra_total`, `#pktrcvfilterextratotal` | number of control packets received and not supplied back |
|
640
|
+
| `#pktRcvFilterSupplyTotal` | `#pkt_rcv_filter_supply_total`, `#pktrcvfiltersupplytotal` | number of packets that the filter supplied extra (e.g. FEC rebuilt) |
|
641
|
+
| `#pktRcvFilterLossTotal` | `#pkt_rcv_filter_loss_total`, `#pktrcvfilterlosstotal` | number of packet loss not coverable by filter |
|
642
|
+
| `#byteSentTotal` | `#byte_sent_total`, `#bytesenttotal` | total number of sent data bytes, including retransmissions |
|
643
|
+
| `#byteRecvTotal` | `#byte_recv_total`, `#byterecvtotal` | total number of received bytes |
|
644
|
+
| `#byteRcvLossTotal` | `#byte_rcv_loss_total`, `#bytercvlosstotal` | total number of lost bytes SRT_ENABLE_LOSTBYTESCOUNT |
|
645
|
+
| `#byteRetransTotal` | `#byte_retrans_total`, `#byteretranstotal` | total number of retransmitted bytes |
|
646
|
+
| `#byteSndDropTotal` | `#byte_snd_drop_total`, `#bytesnddroptotal` | number of too-late-to-send dropped bytes |
|
647
|
+
| `#byteRcvDropTotal` | `#byte_rcv_drop_total`, `#bytercvdroptotal` | number of too-late-to play missing bytes (estimate based on average packet size) |
|
648
|
+
| `#byteRcvUndecryptTotal` | `#byte_rcv_undecrypt_total`, `#bytercvundecrypttotal` | number of undecrypted bytes |
|
649
|
+
| `#pktSent` | `#pkt_sent`, `#pktsent` | number of sent data packets, including retransmissions |
|
650
|
+
| `#pktRecv` | `#pkt_recv`, `#pktrecv` | number of received packets |
|
651
|
+
| `#pktSndLoss` | `#pkt_snd_loss`, `#pktsndloss` | number of lost packets (sender side) |
|
652
|
+
| `#pktRcvLoss` | `#pkt_rcv_loss`, `#pktrcvloss` | number of lost packets (receiver side) |
|
653
|
+
| `#pktRetrans` | `#pkt_retrans`, `#pktretrans` | number of retransmitted packets |
|
654
|
+
| `#pktRcvRetrans` | `#pkt_rcv_retrans`, `#pktrcvretrans` | number of retransmitted packets received |
|
655
|
+
| `#pktSentACK` | `#pkt_sent_ack`, `#pktsentack` | number of sent ACK packets |
|
656
|
+
| `#pktRecvACK` | `#pkt_recv_ack`, `#pktrecvack` | number of received ACK packets |
|
657
|
+
| `#pktSentNAK` | `#pkt_sent_nak`, `#pktsentnak` | number of sent NAK packets |
|
658
|
+
| `#pktRecvNAK` | `#pkt_recv_nak`, `#pktrecvnak` | number of received NAK packets |
|
659
|
+
| `#pktSndFilterExtra` | `#pkt_snd_filter_extra`, `#pktsndfilterextra` | number of control packets supplied by packet filter |
|
660
|
+
| `#pktRcvFilterExtra` | `#pkt_rcv_filter_extra`, `#pktrcvfilterextra` | number of control packets received and not supplied back |
|
661
|
+
| `#pktRcvFilterSupply` | `#pkt_rcv_filter_supply`, `#pktrcvfiltersupply` | number of packets that the filter supplied extra (e.g. FEC rebuilt) |
|
662
|
+
| `#pktRcvFilterLoss` | `#pkt_rcv_filter_loss`, `#pktrcvfilterloss` | number of packet loss not coverable by filter |
|
663
|
+
| `#mbpsSRate` | `#mbps_s_rate`, `#mbpssrate` | sending rate in Mb/s |
|
664
|
+
| `#mbpsRecvRate` | `#mbps_recv_rate`, `#mbpsrecvrate` | receiving rate in Mb/s |
|
665
|
+
| `#usSndDuration` | `#us_snd_duration`, `#ussndduration` | busy sending time (i.e., idle time exclusive) |
|
666
|
+
| `#pktReorderDistance` | `#pkt_reorder_distance`, `#pktreorderdistance` | size of order discrepancy in received sequences |
|
667
|
+
| `#pktRcvAvgBelatedTime` | `#pkt_rcv_avg_belated_time`, `#pktrcvavgbelatedtime` | average time of packet delay for belated packets (packets with sequence past the ACK) |
|
668
|
+
| `#pktRcvBelated` | `#pkt_rcv_belated`, `#pktrcvbelated` | number of received AND IGNORED packets due to having come too late |
|
669
|
+
| `#pktSndDrop` | `#pkt_snd_drop`, `#pktsnddrop` | number of too-late-to-send dropped packets |
|
670
|
+
| `#pktRcvDrop` | `#pkt_rcv_drop`, `#pktrcvdrop` | number of too-late-to play missing packets |
|
671
|
+
| `#pktRcvUndecrypt` | `#pkt_rcv_undecrypt`, `#pktrcvundecrypt` | number of undecrypted packets |
|
672
|
+
| `#byteSent` | `#byte_sent`, `#bytesent` | number of sent data bytes, including retransmissions |
|
673
|
+
| `#byteRecv` | `#byte_recv`, `#byterecv` | number of received bytes |
|
674
|
+
| `#byteRcvLoss` | `#byte_rcv_loss`, `#bytercvloss` | number of retransmitted bytes SRT_ENABLE_LOSTBYTESCOUNT |
|
675
|
+
| `#byteRetrans` | `#byte_retrans`, `#byteretrans` | number of retransmitted bytes |
|
676
|
+
| `#byteSndDrop` | `#byte_snd_drop`, `#bytesnddrop` | number of too-late-to-send dropped bytes |
|
677
|
+
| `#byteRcvDrop` | `#byte_rcv_drop`, `#bytercvdrop` | number of too-late-to play missing bytes (estimate based on average packet size) |
|
678
|
+
| `#byteRcvUndecrypt` | `#byte_rcv_undecrypt`, `#bytercvundecrypt` | number of undecrypted bytes |
|
679
|
+
| `#usPktSndPeriod` | `#us_pkt_snd_period`, `#uspktsndperiod` | packet sending period, in microseconds |
|
680
|
+
| `#pktFlowWindow` | `#pkt_flow_window`, `#pktflowwindow` | flow window size, in number of packets |
|
681
|
+
| `#pktCongestionWindow` | `#pkt_congestion_window`, `#pktcongestionwindow` | congestion window size, in number of packets |
|
682
|
+
| `#pktFlightSize` | `#pkt_flight_size`, `#pktflightsize` | number of packets on flight |
|
683
|
+
| `#msRTT` | `#ms_rtt`, `#msrtt` | RTT, in milliseconds |
|
684
|
+
| `#mbpsBandwidth` | `#mbps_bandwidth`, `#mbpsbandwidth` | estimated bandwidth, in Mb/s |
|
685
|
+
| `#byteAvailSndBuf` | `#byte_avail_snd_buf`, `#byteavailsndbuf` | available UDT sender buffer size |
|
686
|
+
| `#byteAvailRcvBuf` | `#byte_avail_rcv_buf`, `#byteavailrcvbuf` | available UDT receiver buffer size |
|
687
|
+
| `#mbpsMaxBW` | `#mbps_max_bw`, `#mbpsmaxbw` | Transmit Bandwidth ceiling (Mbps) |
|
688
|
+
| `#byteMSS` | `#byte_mss`, `#bytemss` | MTU |
|
689
|
+
| `#pktSndBuf` | `#pkt_snd_buf`, `#pktsndbuf` | UnACKed packets in UDT sender |
|
690
|
+
| `#byteSndBuf` | `#byte_snd_buf`, `#bytesndbuf` | UnACKed bytes in UDT sender |
|
691
|
+
| `#msSndBuf` | `#ms_snd_buf`, `#mssndbuf` | UnACKed timespan (msec) of UDT sender |
|
692
|
+
| `#msSndTsbPdDelay` | `#ms_snd_tsb_pd_delay`, `#mssndtsbpddelay` | Timestamp-based Packet Delivery Delay |
|
693
|
+
| `#pktRcvBuf` | `#pkt_rcv_buf`, `#pktrcvbuf` | Undelivered packets in UDT receiver |
|
694
|
+
| `#byteRcvBuf` | `#byte_rcv_buf`, `#bytercvbuf` | Undelivered bytes of UDT receiver |
|
695
|
+
| `#msRcvBuf` | `#ms_rcv_buf`, `#msrcvbuf` | Undelivered timespan (msec) of UDT receiver |
|
696
|
+
| `#msRcvTsbPdDelay` | `#ms_rcv_tsb_pd_delay`, `#msrcvtsbpddelay` | Timestamp-based Packet Delivery Delay |
|
697
|
+
|
698
|
+
|
699
|
+
### `SRT::Error` Classes
|
700
|
+
|
701
|
+
SRT specifies a number of error types which can occur. The gem defines an Error class for each one allowing the developer to `rescue` and handle specific errors.
|
702
|
+
|
703
|
+
If you want to catch _any_ SRT error, you can `rescue` `SRT::Error`, when you need more fine grained control (e.g. non block read and write no-data errors), `rescue` the appropriate error.
|
704
|
+
|
705
|
+
Each error has both a constant, and an instance variable defined with it's corresponding error code, these codes correspond with the SRT C API error codes (e.g. `SRT::Error::ASYNCRCV::Code`, `err.code`).
|
706
|
+
|
707
|
+
The gem supplies the following SRT specific errors:
|
708
|
+
|
709
|
+
| Error | Description |
|
710
|
+
|-------|-------------|
|
711
|
+
| SRT::Error | The base class of any SRT related error |
|
712
|
+
| SRT::Error::ASYNCFAIL | ... |
|
713
|
+
| SRT::Error::ASYNCRCV | A non-blocking socket did have data available. |
|
714
|
+
| SRT::Error::ASYNCSND | A non-blocking socket could not accept data. |
|
715
|
+
| SRT::Error::BOUNDSOCK | ... |
|
716
|
+
| SRT::Error::CONGEST | ... |
|
717
|
+
| SRT::Error::CONNFAIL | ... |
|
718
|
+
| SRT::Error::CONNLOST | ... |
|
719
|
+
| SRT::Error::CONNREJ | ... |
|
720
|
+
| SRT::Error::CONNSETUP | ... |
|
721
|
+
| SRT::Error::CONNSOCK | ... |
|
722
|
+
| SRT::Error::DUPLISTEN | ... |
|
723
|
+
| SRT::Error::FILE | ... |
|
724
|
+
| SRT::Error::INVALBUFFERAPI | ... |
|
725
|
+
| SRT::Error::INVALMSGAPI | ... |
|
726
|
+
| SRT::Error::INVOP | ... |
|
727
|
+
| SRT::Error::INVPARAM | ... |
|
728
|
+
| SRT::Error::INVPOLLID | ... |
|
729
|
+
| SRT::Error::INVRDOFF | ... |
|
730
|
+
| SRT::Error::INVSOCK | ... |
|
731
|
+
| SRT::Error::INVWROFF | ... |
|
732
|
+
| SRT::Error::LARGEMSG | ... |
|
733
|
+
| SRT::Error::NOBUF | ... |
|
734
|
+
| SRT::Error::NOCONN | ... |
|
735
|
+
| SRT::Error::NOLISTEN | ... |
|
736
|
+
| SRT::Error::NOSERVER | ... |
|
737
|
+
| SRT::Error::PEERERR | ... |
|
738
|
+
| SRT::Error::RDPERM | ... |
|
739
|
+
| SRT::Error::RDVNOSERV | ... |
|
740
|
+
| SRT::Error::RDVUNBOUND | ... |
|
741
|
+
| SRT::Error::RESOURCE | ... |
|
742
|
+
| SRT::Error::SECFAIL | ... |
|
743
|
+
| SRT::Error::SOCKFAIL | ... |
|
744
|
+
| SRT::Error::THREAD | ... |
|
745
|
+
| SRT::Error::TIMEOUT | ... |
|
746
|
+
| SRT::Error::UNBOUNDSOCK | ... |
|
747
|
+
| SRT::Error::UNKNOWN | ... |
|
748
|
+
| SRT::Error::WRPERM | ... |
|
749
|
+
|
750
|
+
## License
|
751
|
+
|
752
|
+
All Ruby code is released under the MIT License. All C code is released under the Mozilla Public License, v. 2.0.
|