cargosocket 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 47b62251f65e525e81eacb09114d5a02de7960df
4
+ data.tar.gz: e6b19b1a1e83babb0afb075178e2bec8b1c9f90d
5
+ SHA512:
6
+ metadata.gz: c072d7ec21a201c6b95cf06fb9a77ec599241154312a2b0eac9ea5deda9893fde5bf549b8429c042cabf9215c7503d854c156713e9ccb07c746a199e19095ac8
7
+ data.tar.gz: cdaef4f77b65a5236bf721445658bc7e5fc37a23bf68bcdab03918aa9ef91177c8ccf32197fa73ed0ab572e4cde6d1c877e1deeadf511ecb68c577e524195c90
data/LICENSE.md ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2016, Matthias Geier
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,6 @@
1
+ require 'em-websocket'
2
+ require 'cargosocket/stream_adapters/cargobull_adapter'
3
+ require 'cargosocket/stream_adapters/e_m_channel_adapter'
4
+ require 'cargosocket/stream'
5
+ require 'cargobull'
6
+ require 'cargosocket/extensions/cargobull.rb'
@@ -0,0 +1,25 @@
1
+
2
+ module Cargobull
3
+ def self.streamer(cargoenv=env.get)
4
+ cargoenv[:session] = {}
5
+ cargoenv.freeze
6
+ Cargosocket::Stream.call(cargoenv)
7
+ end
8
+
9
+ module Dispatch
10
+ METHOD_MAP.merge!({
11
+ "CHANNELS" => :channels,
12
+ "REFERENCE" => :reference,
13
+ "SUBSCRIBE" => :subscribe,
14
+ "UNSUBSCRIBE" => :unsubscribe,
15
+ "ERROR" => :error,
16
+ "POP" => :pop,
17
+ "PUSH" => :push
18
+ })
19
+
20
+ def self.call_no_transform(env, *args)
21
+ dispatch(env, nil, nil, *args)
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,75 @@
1
+
2
+ module Cargosocket
3
+ module Stream
4
+ WS_OPT_KEYS = %w{host port debug secure secure_proxy tls_options
5
+ close_timeout outbound_limit}.map(&:to_sym)
6
+
7
+ def self.call(cargoenv)
8
+ raise "requires stream adapter" unless cargoenv[:adapter]
9
+
10
+ EM.run do
11
+ ws_config = WS_OPT_KEYS.reduce({}) do |acc, key|
12
+ acc[key] = cargoenv[key] if cargoenv.has_key?(key)
13
+ next acc
14
+ end
15
+ EM::WebSocket.run(ws_config){ |ws| config_socket(cargoenv, ws) }
16
+ end
17
+ end
18
+
19
+ def self.config_socket(cargoenv, ws)
20
+ ws.onopen do |w|
21
+ path = w.path.sub(/^\//, '')
22
+ periodic_ping(cargoenv, ws)
23
+ EM.add_timer(0.5){ setup_connection(cargoenv, ws, path, w.query) }
24
+ end
25
+ end
26
+
27
+ def self.periodic_ping(cargoenv, ws)
28
+ EM.add_periodic_timer(cargoenv[:ping_timer] || 5){ ws.ping }
29
+ end
30
+
31
+ def self.setup_connection(cargoenv, ws, path, query)
32
+ cb_adapter = StreamAdapters::CargobullAdapter
33
+
34
+ channels = cb_adapter.channels(cargoenv, path, query)
35
+ ref = cb_adapter.reference(cargoenv, path, query)
36
+ if channels && ref
37
+ state = cargoenv[:adapter].subscribe(*channels) do |channel, message|
38
+ cb_adapter.pop(cargoenv, path, ref, channel, message,
39
+ &ws.method(:send))
40
+ end
41
+
42
+ state.keys.each do |channel|
43
+ cb_adapter.subscribe(cargoenv, path, ref, channel) do |v|
44
+ cargoenv[:adapter].push(channel, v)
45
+ end
46
+ end
47
+
48
+ ws.onmessage do |message|
49
+ state.keys.each do |channel|
50
+ cb_adapter.push(cargoenv, path, ref, channel,
51
+ message.strip){ |v| cargoenv[:adapter].push(channel, v) }
52
+ end
53
+ end
54
+
55
+ ws.onerror do |error|
56
+ cargoenv[:adapter].unsubscribe(state) do |channel|
57
+ cb_adapter.error(cargoenv, path, ref, channel) do |v|
58
+ cargoenv[:adapter].push(channel, v)
59
+ end
60
+ end
61
+ end
62
+
63
+ ws.onclose do
64
+ cargoenv[:adapter].unsubscribe(state) do |channel|
65
+ cb_adapter.unsubscribe(cargoenv, path, ref, channel) do |v|
66
+ cargoenv[:adapter].push(channel, v)
67
+ end
68
+ end
69
+ end
70
+ else
71
+ ws.close(3001, channels.inspect || ref.to_s || "unknown")
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,49 @@
1
+
2
+ module Cargosocket
3
+ module StreamAdapters
4
+ module CargobullAdapter
5
+ def self.if_value(value)
6
+ return if value.last.nil?
7
+ yield(value.last)
8
+ end
9
+
10
+ def self.dispatch_to(m, *args)
11
+ Cargobull::Dispatch.send(m, *args)
12
+ end
13
+
14
+ def self.channels(cargoenv, path, query)
15
+ r = dispatch_to(:call_no_transform, cargoenv, "CHANNELS", path, query)
16
+ if r.first == 200 && r.last.is_a?(Array) && !r.last.empty?
17
+ r.last.map(&:to_sym)
18
+ end
19
+ end
20
+
21
+ def self.reference(cargoenv, path, query)
22
+ r = dispatch_to(:call_no_transform, cargoenv, "REFERENCE", path, query)
23
+ if r.first == 200
24
+ r.last
25
+ end
26
+ end
27
+
28
+ def self.subscribe(cargoenv, *args)
29
+ if_value(dispatch_to(:call, cargoenv, "SUBSCRIBE", *args), &Proc.new)
30
+ end
31
+
32
+ def self.unsubscribe(cargoenv, *args)
33
+ if_value(dispatch_to(:call, cargoenv, "UNSUBSCRIBE", *args), &Proc.new)
34
+ end
35
+
36
+ def self.error(cargoenv, *args)
37
+ if_value(dispatch_to(:call, cargoenv, "ERROR", *args), &Proc.new)
38
+ end
39
+
40
+ def self.push(cargoenv, *args)
41
+ if_value(dispatch_to(:call, cargoenv, "PUSH", *args), &Proc.new)
42
+ end
43
+
44
+ def self.pop(cargoenv, *args)
45
+ if_value(dispatch_to(:call, cargoenv, "POP", *args), &Proc.new)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module Cargosocket
3
+ module StreamAdapters
4
+ module EMChannelAdapter
5
+ CHANNELS = {}
6
+ DISPATCHERS = []
7
+
8
+ def self.dispatch(to)
9
+ # DISPATCHERS << to
10
+ end
11
+
12
+ def self.push(*to, message)
13
+ to.each do |channel|
14
+ if channel.is_a?(Symbol)
15
+ CHANNELS[channel].push(message) if CHANNELS.has_key?(channel)
16
+ else
17
+ # channel.push(message)
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.subscribe(*to)
23
+ callback = Proc.new
24
+ return to.reduce({}) do |acc, channel|
25
+ CHANNELS[channel] ||= EM::Channel.new
26
+ acc[channel] = CHANNELS[channel].subscribe(&callback.curry[channel])
27
+ next acc
28
+ end
29
+ end
30
+
31
+ def self.unsubscribe(from)
32
+ from.each do |channel, cid|
33
+ yield(channel)
34
+ CHANNELS[channel].unsubscribe(cid)
35
+ if CHANNELS[channel].num_subscribers == DISPATCHERS.count
36
+ CHANNELS.delete(channel)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1 @@
1
+ require 'cargosocket'
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cargosocket
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matthias Geier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-websocket
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: cargobull
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.3'
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE.md
48
+ - lib/cargosocket.rb
49
+ - lib/cargosocket/extensions/cargobull.rb
50
+ - lib/cargosocket/stream.rb
51
+ - lib/cargosocket/stream_adapters/cargobull_adapter.rb
52
+ - lib/cargosocket/stream_adapters/e_m_channel_adapter.rb
53
+ - lib/cargosocket/test_helper.rb
54
+ homepage: https://github.com/matthias-geier/cargosocket
55
+ licenses:
56
+ - BSD-2
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.1.0
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.4.5.1
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Middleware to create a websocket service
78
+ test_files: []