janus_gateway 0.0.1
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/LICENSE +21 -0
- data/README.md +118 -0
- data/lib/janus_gateway.rb +21 -0
- data/lib/janus_gateway/client.rb +38 -0
- data/lib/janus_gateway/error.rb +27 -0
- data/lib/janus_gateway/plugin/rtpbroadcast.rb +12 -0
- data/lib/janus_gateway/plugin/rtpbroadcast/mountpoint.rb +116 -0
- data/lib/janus_gateway/resource.rb +37 -0
- data/lib/janus_gateway/resource/plugin.rb +72 -0
- data/lib/janus_gateway/resource/session.rb +103 -0
- data/lib/janus_gateway/transport.rb +45 -0
- data/lib/janus_gateway/transport/websocket.rb +122 -0
- data/lib/janus_gateway/version.rb +3 -0
- metadata +143 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9ef894fe4018704ac9bb29bda7b1d12add02ba10
|
4
|
+
data.tar.gz: ccbd4074640d1e190d16eaf56afcf13a0ad20813
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1606c18623b561ebd0f4b8b2e9363b0ddc350cd80fd845a8adf7424925874bfce6065cd1804779ecb09266d6bb0acecd81462faee865b686f0145e55e6db2582
|
7
|
+
data.tar.gz: e00f2f6f51b735d3aff9625d24e64603db06a4d64dbf95744c03760a22a079c345ad0b735a0a31a0316ad10ea7da084fa4c22b714885c23bae5f2e2412268dd9
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Cargo Media
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
janus-gateway-ruby [](https://travis-ci.org/cargomedia/janus-gateway-ruby)
|
2
|
+
==================
|
3
|
+
Minimalistic [janus-gateway](https://github.com/meetecho/janus-gateway) client for ruby
|
4
|
+
|
5
|
+
Installation
|
6
|
+
------------
|
7
|
+
```
|
8
|
+
gem install janus_gateway
|
9
|
+
```
|
10
|
+
|
11
|
+
API coverage
|
12
|
+
------------
|
13
|
+
Current implementation support only a few of API features. For more details please follow official documentation of [REST API](https://janus.conf.meetecho.com/docs/rest.html)
|
14
|
+
|
15
|
+
Library usage
|
16
|
+
-------------
|
17
|
+
|
18
|
+
Source code itself is well-documented so when writing code it should auto-complete and hint in all supported usages.
|
19
|
+
|
20
|
+
### Client
|
21
|
+
In order to make any request you need to instantiate client with correct transport layer (see transport section).
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
ws = JanusGateway::Transport::WebSocket.new('ws://localhost:8188/janus')
|
25
|
+
client = JanusGateway::Client.new(ws)
|
26
|
+
```
|
27
|
+
|
28
|
+
This client is used by all other classes connecting to api no matter if it's Resource or helper class like Agent.
|
29
|
+
|
30
|
+
### Transports
|
31
|
+
Client allows to use multiple, supported by Janus transportation layers. Currently the `WebSocket` transport is implemented and is the default.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
ws = JanusGateway::Transport::WebSocket.new('ws://localhost:8188/janus')
|
35
|
+
```
|
36
|
+
|
37
|
+
### Resources
|
38
|
+
Each resource has built-in event emitter to handle basic behaviours like `create` and `destroy`. Additionally the creation of resources can be chained.
|
39
|
+
There are two types of resources: Janus-API resource and Plugin-API (please see Plugin section).
|
40
|
+
|
41
|
+
You can bind on events:
|
42
|
+
```ruby
|
43
|
+
session = JanusGateway::Resource::Session.new(client)
|
44
|
+
|
45
|
+
session.on :create do
|
46
|
+
# do something
|
47
|
+
end
|
48
|
+
|
49
|
+
session.on :destroy do
|
50
|
+
# do something
|
51
|
+
end
|
52
|
+
|
53
|
+
session.create
|
54
|
+
```
|
55
|
+
|
56
|
+
Resource creation and destroying are asynchronous operations which return a `Concurrent::Promise`:
|
57
|
+
```ruby
|
58
|
+
session = JanusGateway::Resource::Session.new(client)
|
59
|
+
|
60
|
+
session.create.then do |session|
|
61
|
+
# do something with success
|
62
|
+
end.rescue do |error|
|
63
|
+
# do something with error
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
#### Session
|
68
|
+
Create new session:
|
69
|
+
```ruby
|
70
|
+
session = JanusGateway::Resource::Session.new(client)
|
71
|
+
session.create
|
72
|
+
```
|
73
|
+
|
74
|
+
Destroy a session:
|
75
|
+
```ruby
|
76
|
+
session.destroy
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Plugin
|
80
|
+
Create new plugin:
|
81
|
+
```ruby
|
82
|
+
plugin = JanusGateway::Resource::Plugin.new(client, session, 'plugin-name')
|
83
|
+
plugin.create
|
84
|
+
```
|
85
|
+
|
86
|
+
Destroy a plugin:
|
87
|
+
```ruby
|
88
|
+
plugin.destroy
|
89
|
+
```
|
90
|
+
|
91
|
+
### Plugins
|
92
|
+
Janus support for native and custom [plugins](https://janus.conf.meetecho.com/docs/group__plugins.html).
|
93
|
+
|
94
|
+
#### Rtpbrodcast plugin
|
95
|
+
This is custom plugin for `RTP` streaming. Please find more details in official [repository](https://github.com/cargomedia/janus-gateway-rtpbroadcast).
|
96
|
+
Plugin must be installed and active in `Janus` server.
|
97
|
+
|
98
|
+
Plugin resource supports `events` and `chaining` in the same way like `Janus` resource.
|
99
|
+
|
100
|
+
##### Mountpoint create
|
101
|
+
Plugins allows to create `RTP` mountpoint.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
ws = JanusGateway::Transport::WebSocket.new('ws://localhost:8188/janus')
|
105
|
+
client = JanusGateway::Client.new(ws)
|
106
|
+
|
107
|
+
client.on :open do
|
108
|
+
JanusGateway::Resource::Session.new(client).create.then do |session|
|
109
|
+
JanusGateway::Plugin::Rtpbroadcast.new(client, session).create.then do |plugin|
|
110
|
+
JanusGateway::Plugin::Rtpbroadcast::Mountpoint.new(client, plugin, 'test-mountpoint').create.then do |mountpoint|
|
111
|
+
# do something with mountpoint
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
client.connect
|
118
|
+
```
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'events'
|
5
|
+
require 'concurrent'
|
6
|
+
|
7
|
+
require 'janus_gateway/client'
|
8
|
+
require 'janus_gateway/transport'
|
9
|
+
require 'janus_gateway/resource'
|
10
|
+
require 'janus_gateway/error'
|
11
|
+
|
12
|
+
require 'janus_gateway/resource/session'
|
13
|
+
require 'janus_gateway/resource/plugin'
|
14
|
+
|
15
|
+
require 'janus_gateway/transport/websocket'
|
16
|
+
|
17
|
+
require 'janus_gateway/plugin/rtpbroadcast'
|
18
|
+
require 'janus_gateway/plugin/rtpbroadcast/mountpoint'
|
19
|
+
|
20
|
+
require 'janus_gateway/version'
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
attr_accessor :transport
|
6
|
+
|
7
|
+
# @param [JanusGateway::Transport]
|
8
|
+
def initialize(transport)
|
9
|
+
@transport = transport
|
10
|
+
end
|
11
|
+
|
12
|
+
def connect
|
13
|
+
@transport.run
|
14
|
+
end
|
15
|
+
|
16
|
+
def disconnect
|
17
|
+
@transport.disconnect
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Hash] data
|
21
|
+
# @return [Concurrent::Promise]
|
22
|
+
def send_transaction(data)
|
23
|
+
@transport.send_transaction(data)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [TrueClass, FalseClass]
|
27
|
+
def is_connected?
|
28
|
+
@transport.is_connected?
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [Symbol, String] event
|
32
|
+
# @param [Proc] block
|
33
|
+
def on(event, &block)
|
34
|
+
@transport.on(event, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
|
5
|
+
# @param [Integer] error_code
|
6
|
+
# @param [String] error_info
|
7
|
+
def initialize(error_code, error_info)
|
8
|
+
@code, @info = error_code, error_info
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [String]
|
12
|
+
def message
|
13
|
+
"<Code: #{code}> <Info: #{info}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
def code
|
18
|
+
@code
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
def info
|
23
|
+
@info
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module JanusGateway::Plugin
|
2
|
+
|
3
|
+
class Rtpbroadcast < JanusGateway::Resource::Plugin
|
4
|
+
|
5
|
+
# @param [JanusGateway::Client] client
|
6
|
+
# @param [JanusGateway::Resource::Session] session
|
7
|
+
def initialize(client, session)
|
8
|
+
super(client, session, 'janus.plugin.cm.rtpbroadcast')
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module JanusGateway::Plugin
|
2
|
+
|
3
|
+
class Rtpbroadcast::Mountpoint < JanusGateway::Resource
|
4
|
+
|
5
|
+
# @param [JanusGateway::Client] client
|
6
|
+
# @param [JanusGateway::Plugin::Rtpbroadcast] plugin
|
7
|
+
# @param [String] id
|
8
|
+
# @param [Array] streams
|
9
|
+
def initialize(client, plugin, id, streams = nil)
|
10
|
+
@plugin = plugin
|
11
|
+
@id = id
|
12
|
+
@data = nil
|
13
|
+
|
14
|
+
@streams = streams || [
|
15
|
+
{
|
16
|
+
:audio => 'yes',
|
17
|
+
:video => 'yes',
|
18
|
+
:audiopt => 111,
|
19
|
+
:audiortpmap => 'opus/48000/2',
|
20
|
+
:videopt => 100,
|
21
|
+
:videortpmap => 'VP8/90000'
|
22
|
+
}
|
23
|
+
]
|
24
|
+
|
25
|
+
super(client)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Concurrent::Promise]
|
29
|
+
def create
|
30
|
+
promise = Concurrent::Promise.new
|
31
|
+
|
32
|
+
client.send_transaction(
|
33
|
+
{
|
34
|
+
:janus => 'message',
|
35
|
+
:session_id => plugin.session.id,
|
36
|
+
:handle_id => plugin.id,
|
37
|
+
:body => {
|
38
|
+
:request => 'create',
|
39
|
+
:id => id,
|
40
|
+
:name => id,
|
41
|
+
:description => id,
|
42
|
+
:recorded => true,
|
43
|
+
:streams => @streams
|
44
|
+
}
|
45
|
+
}
|
46
|
+
).then do |data|
|
47
|
+
plugindata = data['plugindata']['data']
|
48
|
+
if plugindata['error_code'].nil?
|
49
|
+
_on_created(data)
|
50
|
+
|
51
|
+
promise.set(self).execute
|
52
|
+
else
|
53
|
+
error = JanusGateway::Error.new(plugindata['error_code'], plugindata['error'])
|
54
|
+
|
55
|
+
_on_error(error)
|
56
|
+
|
57
|
+
promise.fail(error).execute
|
58
|
+
end
|
59
|
+
end.rescue do |error|
|
60
|
+
promise.fail(error).execute
|
61
|
+
end
|
62
|
+
|
63
|
+
promise
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Array<Hash>]
|
67
|
+
def streams
|
68
|
+
!data.nil? ? data['data']['stream']['streams'] : []
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Concurrent::Promise]
|
72
|
+
def destroy
|
73
|
+
promise = Concurrent::Promise.new
|
74
|
+
|
75
|
+
_on_destroyed
|
76
|
+
promise.set(self).execute
|
77
|
+
|
78
|
+
promise
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [JanusGateway::Resource::Session]
|
82
|
+
def session
|
83
|
+
plugin.session
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [JanusGateway::Resource::Plugin]
|
87
|
+
def plugin
|
88
|
+
@plugin
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [Hash, NilClass]
|
92
|
+
def data
|
93
|
+
@data
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def _on_error(error)
|
99
|
+
self.emit :error, error
|
100
|
+
end
|
101
|
+
|
102
|
+
def _on_created(data)
|
103
|
+
@data = data['plugindata']
|
104
|
+
|
105
|
+
plugin.on :destroy do
|
106
|
+
destroy
|
107
|
+
end
|
108
|
+
|
109
|
+
self.emit :create, @id
|
110
|
+
end
|
111
|
+
|
112
|
+
def _on_destroyed
|
113
|
+
self.emit :destroy, @id
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Resource
|
4
|
+
|
5
|
+
include Events::Emitter
|
6
|
+
|
7
|
+
attr_accessor :id
|
8
|
+
|
9
|
+
# @param [JanusGateway::Client] client
|
10
|
+
# @param [String] id
|
11
|
+
def initialize(client, id = nil)
|
12
|
+
@client = client
|
13
|
+
@id = id
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String, NilClass]
|
17
|
+
def id
|
18
|
+
@id
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [JanusGateway::Client]
|
22
|
+
def client
|
23
|
+
@client
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Concurrent::Promise]
|
27
|
+
def create
|
28
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Concurrent::Promise]
|
32
|
+
def destroy
|
33
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Resource::Plugin < Resource
|
4
|
+
|
5
|
+
# @param [JanusGateway::Client] client
|
6
|
+
# @param [JanusGateway::Resource::Session] session
|
7
|
+
# @param [String] plugin_name
|
8
|
+
def initialize(client, session, plugin_name)
|
9
|
+
@session = session
|
10
|
+
@name = plugin_name
|
11
|
+
|
12
|
+
super(client)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
def name
|
17
|
+
@name
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Concurrent::Promise]
|
21
|
+
def create
|
22
|
+
promise = Concurrent::Promise.new
|
23
|
+
|
24
|
+
client.send_transaction(
|
25
|
+
{
|
26
|
+
:janus => 'attach',
|
27
|
+
:plugin => name,
|
28
|
+
:session_id => @session.id
|
29
|
+
}
|
30
|
+
).then do |*args|
|
31
|
+
_on_created(*args)
|
32
|
+
|
33
|
+
promise.set(self).execute
|
34
|
+
end.rescue do |error|
|
35
|
+
promise.fail(error).execute
|
36
|
+
end
|
37
|
+
|
38
|
+
promise
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy
|
42
|
+
promise = Concurrent::Promise.new
|
43
|
+
|
44
|
+
_on_destroyed
|
45
|
+
promise.set(self).execute
|
46
|
+
|
47
|
+
promise
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [JanusGateway::Resource::Session]
|
51
|
+
def session
|
52
|
+
@session
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def _on_created(data)
|
58
|
+
@id = data['data']['id']
|
59
|
+
|
60
|
+
session.on :destroy do |data|
|
61
|
+
destroy
|
62
|
+
end
|
63
|
+
|
64
|
+
self.emit :create, @id
|
65
|
+
end
|
66
|
+
|
67
|
+
def _on_destroyed
|
68
|
+
self.emit :destroy, @id
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Resource::Session < Resource
|
4
|
+
|
5
|
+
# @param [JanusGateway::Client] client
|
6
|
+
def initialize(client)
|
7
|
+
@heartbeat_thread = nil
|
8
|
+
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Concurrent::Promise]
|
13
|
+
def create
|
14
|
+
promise = Concurrent::Promise.new
|
15
|
+
|
16
|
+
client.send_transaction(
|
17
|
+
{
|
18
|
+
:janus => 'create'
|
19
|
+
}
|
20
|
+
).then do |*args|
|
21
|
+
_on_created(*args)
|
22
|
+
heartbeat
|
23
|
+
|
24
|
+
promise.set(self).execute
|
25
|
+
end.rescue do |error|
|
26
|
+
promise.fail(error).execute
|
27
|
+
end
|
28
|
+
|
29
|
+
promise
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Concurrent::Promise]
|
33
|
+
def destroy
|
34
|
+
promise = Concurrent::Promise.new
|
35
|
+
|
36
|
+
client.send_transaction(
|
37
|
+
{
|
38
|
+
:janus => 'destroy',
|
39
|
+
:session_id => @id
|
40
|
+
}
|
41
|
+
).then do |*args|
|
42
|
+
_on_destroyed
|
43
|
+
|
44
|
+
promise.set(self).execute
|
45
|
+
end.rescue do |error|
|
46
|
+
promise.fail(error).execute
|
47
|
+
end
|
48
|
+
|
49
|
+
promise
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Thread]
|
53
|
+
def heartbeat
|
54
|
+
@heartbeat_thread.exit unless @heartbeat_thread.nil?
|
55
|
+
|
56
|
+
@heartbeat_thread = Thread.new do
|
57
|
+
sleep_time = 5
|
58
|
+
while true do
|
59
|
+
sleep(sleep_time)
|
60
|
+
client.send_transaction(
|
61
|
+
{
|
62
|
+
:janus => 'keepalive',
|
63
|
+
:session_id => @id
|
64
|
+
}
|
65
|
+
).then do |*args|
|
66
|
+
sleep_time = 30
|
67
|
+
end.rescue do |error|
|
68
|
+
sleep_time = 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# @param [Hash] data
|
77
|
+
def _on_created(data)
|
78
|
+
@id = data['data']['id']
|
79
|
+
|
80
|
+
client.on :message do |data|
|
81
|
+
if data['janus'] == 'timeout' and data['session_id'] == @id
|
82
|
+
send(:_on_destroyed)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
client.on :close do
|
87
|
+
self.emit :destroy
|
88
|
+
end
|
89
|
+
|
90
|
+
client.on :error do
|
91
|
+
self.emit :destroy
|
92
|
+
end
|
93
|
+
|
94
|
+
self.emit :create
|
95
|
+
end
|
96
|
+
|
97
|
+
def _on_destroyed
|
98
|
+
@heartbeat_thread.exit unless @heartbeat_thread.nil?
|
99
|
+
self.emit :destroy
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module JanusGateway
|
2
|
+
|
3
|
+
class Transport
|
4
|
+
|
5
|
+
include Events::Emitter
|
6
|
+
|
7
|
+
def run
|
8
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect
|
12
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
13
|
+
end
|
14
|
+
|
15
|
+
def disconnect
|
16
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Hash] data
|
20
|
+
def send(data)
|
21
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [Hash] data
|
25
|
+
# @return [Concurrent::Promise]
|
26
|
+
def send_transaction(data)
|
27
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [TrueClass, FalseClass]
|
31
|
+
def is_connected?
|
32
|
+
raise("`#{__method__}` is not implemented for `#{self.class.name}`")
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
def transaction_id_new
|
37
|
+
transaction_id = ''
|
38
|
+
24.times do
|
39
|
+
transaction_id << (65 + rand(25)).chr
|
40
|
+
end
|
41
|
+
transaction_id
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'faye/websocket'
|
3
|
+
|
4
|
+
module JanusGateway
|
5
|
+
|
6
|
+
class Transport::WebSocket < Transport
|
7
|
+
|
8
|
+
attr_reader :transaction_queue
|
9
|
+
|
10
|
+
# @param [String] url
|
11
|
+
# @param [String] protocol
|
12
|
+
def initialize(url, protocol = 'janus-protocol')
|
13
|
+
@url = url
|
14
|
+
@protocol = protocol
|
15
|
+
@client = nil
|
16
|
+
@transaction_queue = Hash.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
EventMachine.run do
|
21
|
+
EM.error_handler { |e| raise(e) }
|
22
|
+
connect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def connect
|
27
|
+
raise('WebSocket client already exists!') unless @client.nil?
|
28
|
+
|
29
|
+
@client = _create_client(@url, @protocol)
|
30
|
+
|
31
|
+
client.on :open do
|
32
|
+
self.emit :open
|
33
|
+
end
|
34
|
+
|
35
|
+
client.on :message do |event|
|
36
|
+
data = JSON.parse(event.data)
|
37
|
+
|
38
|
+
transaction_list = @transaction_queue.clone
|
39
|
+
|
40
|
+
transaction_id = data['transaction']
|
41
|
+
unless transaction_id.nil?
|
42
|
+
promise = transaction_list[transaction_id]
|
43
|
+
unless promise.nil?
|
44
|
+
if ['success', 'ack'].include?(data['janus'])
|
45
|
+
promise.set(data).execute
|
46
|
+
else
|
47
|
+
error_data = data['error']
|
48
|
+
error = JanusGateway::Error.new(error_data['code'], error_data['reason'])
|
49
|
+
promise.fail(error).execute
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
self.emit :message, data
|
55
|
+
end
|
56
|
+
|
57
|
+
client.on :close do
|
58
|
+
self.emit :close
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [Hash] data
|
63
|
+
def send(data)
|
64
|
+
client.send(JSON.generate(data))
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [Hash] data
|
68
|
+
# @return [Concurrent::Promise]
|
69
|
+
def send_transaction(data)
|
70
|
+
promise = Concurrent::Promise.new
|
71
|
+
transaction = transaction_id_new
|
72
|
+
|
73
|
+
data[:transaction] = transaction
|
74
|
+
send(data)
|
75
|
+
|
76
|
+
@transaction_queue[transaction] = promise
|
77
|
+
|
78
|
+
thread = Thread.new do
|
79
|
+
sleep(_transaction_timeout)
|
80
|
+
error = JanusGateway::Error.new(0, "Transaction id `#{transaction}` has failed due to timeout!")
|
81
|
+
promise.fail(error).execute
|
82
|
+
@transaction_queue.remove(transaction)
|
83
|
+
end
|
84
|
+
|
85
|
+
promise.then { thread.exit }
|
86
|
+
promise.rescue { thread.exit }
|
87
|
+
|
88
|
+
promise
|
89
|
+
end
|
90
|
+
|
91
|
+
def disconnect
|
92
|
+
client.close unless client.nil?
|
93
|
+
EventMachine.stop if EventMachine.reactor_running?
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [TrueClass, FalseClass]
|
97
|
+
def is_connected?
|
98
|
+
!client.nil? and (client.ready_state == Faye::WebSocket::API::OPEN)
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Faye::WebSocket::Client, NilClass]
|
102
|
+
def client
|
103
|
+
@client
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# @param [String] url
|
109
|
+
# @param [String] protocol
|
110
|
+
# @return [Faye::WebSocket::Client]
|
111
|
+
def _create_client(url, protocol)
|
112
|
+
Faye::WebSocket::Client.new(url, protocol)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [Float, Integer]
|
116
|
+
def _transaction_timeout
|
117
|
+
30
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: janus_gateway
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cargo Media
|
8
|
+
- kris-lab
|
9
|
+
- tomaszdurka
|
10
|
+
- njam
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2015-11-26 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: faye-websocket
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.10.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.10.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: eventmachine
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.0.8
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.8
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: events
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 0.9.8
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 0.9.8
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: concurrent-ruby
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - "~>"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.0.0
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.0.0
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: rake
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: rspec
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - "~>"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '2.0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '2.0'
|
100
|
+
description: janus-gateway API client
|
101
|
+
email: tech@cargomedia.ch
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- LICENSE
|
107
|
+
- README.md
|
108
|
+
- lib/janus_gateway.rb
|
109
|
+
- lib/janus_gateway/client.rb
|
110
|
+
- lib/janus_gateway/error.rb
|
111
|
+
- lib/janus_gateway/plugin/rtpbroadcast.rb
|
112
|
+
- lib/janus_gateway/plugin/rtpbroadcast/mountpoint.rb
|
113
|
+
- lib/janus_gateway/resource.rb
|
114
|
+
- lib/janus_gateway/resource/plugin.rb
|
115
|
+
- lib/janus_gateway/resource/session.rb
|
116
|
+
- lib/janus_gateway/transport.rb
|
117
|
+
- lib/janus_gateway/transport/websocket.rb
|
118
|
+
- lib/janus_gateway/version.rb
|
119
|
+
homepage: https://github.com/cargomedia/janus-gateway-ruby
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 2.5.0
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: janus-gateway client
|
143
|
+
test_files: []
|