jstp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jstp.gemspec
4
+ gemspec
5
+
6
+ group :debug do
7
+ gem 'pry'
8
+ end
@@ -0,0 +1,41 @@
1
+ JSTP es un protocolo de comunicación serializado en JSON montado sobre websockets que utiliza por defecto el puerto 33333.
2
+
3
+ El protocolo es simétrico: esto quiere decir que hay un solo tipo de mensajes. La acción de enviar un mensaje es un `dispatch`. Siendo que es basado en WebSockets, es también asincrónico, significando que los Dispatch no tienen porqué recibir respuesta. Para facilitar seguimiento de un hilo de comunicación, JSTP provee un encabezado `token` donde se sugiere ingresar un hash de control (similar al Etag de HTTP). El encabezado `token` es extensible a un array para contener varios tokens con distinta prioridad.
4
+
5
+ La estructura de cabeceras, métodos (acciones), nombres de recursos y cuerpo de mensaje está diseñada para ser completamente compatible con REST (implicando que se puede hacer _fallback_ a HTTP regular si es necesario). Las cabeceras no necesariamente incluyen todo los mismos datos que las de HTTP regular, pero es posible incluir la misma información. Una Dispatch de ejemplo sería:
6
+
7
+ {
8
+ "protocol": ["JSTP", "0.1"]
9
+ "method": "POST",
10
+ "resource": [
11
+ "session.manager",
12
+ "User"
13
+ ],
14
+ "timestamp": 1357334118,
15
+ "token": 3523902859084057289594,
16
+ "referer": [
17
+ "browser",
18
+ "Registerer"
19
+ ],
20
+ "body": {
21
+ "login": "xavier",
22
+ "email": "xavier@fetcher.com",
23
+ "password": "secret"
24
+ }
25
+ }
26
+
27
+ Un JSTP Dispatch es representable en forma abreviada similar en un HTTP Request. De esta manera, el ejemplo de arriba se puede presentar como:
28
+
29
+ POST session.manager/User JSTP/0.1
30
+ timestamp: 1357334118
31
+ token: 3523902859084057289594
32
+ referer: browser/Registerer
33
+
34
+ login: xavier
35
+ email: xavier@fetcher.com
36
+ password: secret
37
+
38
+ Gateways
39
+ -------------
40
+
41
+ Todo servidor de JSTP conoce su host, que corresponde a la parte inicial del mensaje. Si el host del mensaje recibido no se corresponde con el
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Fernando Vía, Matías Domingues, Luciano Bertenasco
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # JSTP Ruby Gem
2
+
3
+ Server & Client reference implementation of the sketch protocol JSTP (JavaScript Serialization Transfer Protocol). Here follows the basics of the protocol as of version 0.1.
4
+
5
+ JSTP
6
+ ----
7
+
8
+ JSTP is a communication protocol based on JSON serialization that works over websockets in the default TCP port `33333`. It's inspired and aimed to maintain compatibility with HTTP as used in REST architectures but using JSON as the protocol language.
9
+
10
+ The protocol is symmetrical: this means that there is only one type of message, in constrast to _Request-Response_ kind of protocols such as `HTTP`. Sending a message is called `dispatch` in the JSTP vocabulary. As JSTP is built upon Web Sockets, is also by design asynchronous, meaning that a Dispatch is not necessarily follow by any kind of response by the receiver. To facilitate the follow up in communication threads, JSTP provides a `token` header which we suggest to fill with a control hash (a similar concept to HTTP's Etag header). As much of the headers, the `token` header is extensible to an array capable of containing several tokens ordered by priority (is still to be seen is all JSTP headers by default will support or not multiple values).
11
+
12
+ The headers types, available protocol methods, resource taxonomy and message body are designed to be 100% compatible with REST (implying that system that make use of JSTP for their network communications may fall back to plain HTTP if technical limitations require it). Headers are not bound to include all of the same data that HTTP regular _Requests_ or _Responses_, but can.
13
+
14
+ An sample Dispatch will look like:
15
+
16
+ {
17
+ "protocol": ["JSTP", "0.1"]
18
+ "method": "POST",
19
+ "resource": [
20
+ "session.manager",
21
+ "User"
22
+ ],
23
+ "timestamp": 1357334118,
24
+ "token": 3523902859084057289594,
25
+ "referer": [
26
+ "browser",
27
+ "Registerer"
28
+ ],
29
+ "body": {
30
+ "login": "xavier",
31
+ "email": "xavier@fetcher.com",
32
+ "password": "secret"
33
+ }
34
+ }
35
+
36
+ A **JSTP Dispatch** can also be formatted in a short hand notation similar to that of an HTTP Request. The previous example can be presented as follows:
37
+
38
+ POST session.manager/User JSTP/0.1
39
+ timestamp: 1357334118
40
+ token: 3523902859084057289594
41
+ referer: browser/Registerer
42
+
43
+ login: xavier
44
+ email: xavier@fetcher.com
45
+ password: secret
46
+
47
+ Gateways
48
+ --------
49
+
50
+ Every JSTP server knows its own hostname, which should match the first string in the resource array of the message. If the host as received in the message does not corresponds to this server, it should look up for the right server and dispatch it.
51
+
52
+ ## Installation
53
+
54
+ Add this line to your application's Gemfile:
55
+
56
+ gem 'jstp'
57
+
58
+ And then execute:
59
+
60
+ $ bundle
61
+
62
+ Or install it yourself as:
63
+
64
+ $ gem install jstp
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/jstp/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Xavier Via", "Luciano Bertenasco", "Matias Domingues"]
6
+ gem.email = ["xavierviacanel@gmail.com"]
7
+ gem.description = %q{Reference implementation for the sketch protocol JSTP}
8
+ gem.summary = %q{Reference implementation for the sketch protocol JSTP}
9
+ gem.homepage = "https://github.com/Fetcher/jstp"
10
+
11
+ gem.add_dependency 'em-websocket'
12
+ gem.add_dependency 'em-websocket-client'
13
+
14
+ gem.add_development_dependency 'rspec'
15
+
16
+ gem.files = `git ls-files`.split($\)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.name = "jstp"
20
+ gem.require_paths = ["lib"]
21
+ gem.version = Jstp::VERSION
22
+ end
@@ -0,0 +1,17 @@
1
+ require 'singleton'
2
+ require 'em-websocket'
3
+ require 'em-websocket-client'
4
+ require 'json'
5
+
6
+ require 'jstp/event/on_message'
7
+ require 'jstp/connector'
8
+ require 'jstp/api'
9
+ require 'jstp/registry'
10
+ require 'jstp/server'
11
+ require 'jstp/event_machine'
12
+
13
+ module JSTP
14
+ class << self
15
+ include API
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module JSTP
2
+ module API
3
+ def dispatch &block
4
+ JSTP::Registry.instance.set block
5
+
6
+ ::EventMachine.run &JSTP::EventMachine
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module JSTP
2
+
3
+ # Handles the connection functionality for this JSTP reference implementation
4
+ class Connector
5
+ include Singleton
6
+
7
+ # Discovers the server and sends the message
8
+ # @param [Hash/Array] message
9
+ def dispatch message
10
+ client(message["resource"]).send_msg message.to_json
11
+ end
12
+
13
+ # Access to the client pool
14
+ # @param [Array] the resource data
15
+ # @return [EventMachine::WebSocketClient] the client for the address
16
+ def client resource
17
+ ::EventMachine::WebSocketClient.connect "ws://#{resource.first}:33333/#{resource[1..-1].join('/')}"
18
+ end
19
+
20
+ # Sets up the server to be executed within an EventMachine reactor
21
+ def server
22
+ ::EventMachine::WebSocket.start host: "0.0.0.0", port: 33333, &JSTP::Server
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module JSTP
2
+ module Event
3
+ OnMessage = proc { |message|
4
+ JSTP::Registry.instance.get.call JSON.parse message
5
+ }
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module JSTP
2
+ EventMachine = proc {
3
+ JSTP::Connector.instance.server
4
+ }
5
+ end
@@ -0,0 +1,13 @@
1
+ module JSTP
2
+ class Registry
3
+ include Singleton
4
+
5
+ def set block
6
+ @block = block
7
+ end
8
+
9
+ def get
10
+ @block
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module JSTP
2
+ Server = proc { |websocket|
3
+ websocket.onmessage &Event::OnMessage
4
+ }
5
+ end
@@ -0,0 +1,3 @@
1
+ module Jstp
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSTP::API do
4
+ describe '#dispatch' do
5
+ context 'a block is passed' do
6
+ it 'should register the block and send JSTP::Server to the EventMachine reactor' do
7
+ block = proc {
8
+ "lalal"
9
+ }
10
+
11
+ JSTP::Registry.instance.should_receive(:set)
12
+ .with block
13
+
14
+ JSTP::EventMachine.should_receive :call
15
+ EventMachine.should_receive(:run)
16
+ .with &JSTP::EventMachine
17
+
18
+ o = Object.new
19
+ o.extend JSTP::API
20
+ o.dispatch &block
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSTP::Connector do
4
+ it 'should be a singleton' do
5
+ JSTP::Connector.ancestors.should include Singleton
6
+ end
7
+
8
+ describe '#dispatch' do
9
+ before do
10
+ @message = {
11
+ "protocol" => ["JSTP", "0.1"],
12
+ "method" => "POST",
13
+ "resource" => [
14
+ "session.manager",
15
+ "User"
16
+ ],
17
+ "timestamp" => 1357334118,
18
+ "token" => 3523902859084057289594,
19
+ "referer" => [
20
+ "browser",
21
+ "Registerer"
22
+ ],
23
+ "body" => {
24
+ "login" => "xavier",
25
+ "email" => "xavier@fetcher.com",
26
+ "password" => "secret"
27
+ }
28
+ }
29
+
30
+ @web_socket_client = stub 'web socket client'
31
+ @message_json = stub 'message json'
32
+ end
33
+
34
+ it 'should open a websocket to the correct resource in the standard port 33333 and set the callback' do
35
+ JSTP::Connector.instance.should_receive(:client)
36
+ .with(@message["resource"])
37
+ .and_return @web_socket_client
38
+
39
+ @web_socket_client.should_receive(:send_msg)
40
+ .with(@message_json)
41
+ @message.should_receive(:to_json).and_return @message_json
42
+
43
+ JSTP::Connector.instance.dispatch @message
44
+ end
45
+ end
46
+
47
+ describe '#client' do
48
+ context 'there is no connection for that address' do
49
+ before do
50
+ @web_socket_client = stub 'web socket client'
51
+ @resource = ["localhost", "hola", "quetal"]
52
+ end
53
+
54
+ it 'should initialize the websocket client' do
55
+ EventMachine::WebSocketClient.should_receive(:connect)
56
+ .with("ws://#{@resource.first}:33333/#{@resource[1..-1].join('/')}")
57
+ .and_return @web_socket_client
58
+
59
+ JSTP::Connector.instance
60
+ .client(@resource)
61
+ .should == @web_socket_client
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '#server' do
67
+ it 'should start a websocket server in 33333' do
68
+ JSTP::Server.should_receive :call
69
+ EventMachine::WebSocket.should_receive(:start)
70
+ .with({ host: '0.0.0.0', port: 33333 }, &JSTP::Server)
71
+
72
+ JSTP::Connector.instance.server
73
+ end
74
+
75
+ it 'should pass the proc JSTP::Server' do
76
+ pending "Warning, this isn't actually testing the JSTP::Server, I don't know why"
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'JSTP::Event::OnMessage' do
4
+ it 'should call the registered block with the parsed message' do
5
+ @the_proc = stub 'the proc'
6
+ @message = stub 'message'
7
+ @parsed_message = stub 'parsed message'
8
+
9
+ JSON.should_receive(:parse).with(@message)
10
+ .and_return @parsed_message
11
+
12
+ JSTP::Registry.instance.should_receive(:get)
13
+ .and_return @the_proc
14
+
15
+ @the_proc.should_receive(:call)
16
+ .with @parsed_message
17
+
18
+ JSTP::Event::OnMessage.call @message
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'JSTP::EventMachine' do
4
+ it 'should ask the connector to initialize the server' do
5
+ JSTP::Connector.instance.should_receive(:server)
6
+
7
+ JSTP::EventMachine.call
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe JSTP::Registry do
4
+ it 'should be a Singleton' do
5
+ JSTP::Registry.ancestors.should include Singleton
6
+ end
7
+
8
+ describe '#get' do
9
+ it 'should return the registered block' do
10
+ @data = stub 'data'
11
+ JSTP::Registry.instance.set @data
12
+ JSTP::Registry.instance.get.should == @data
13
+ end
14
+ end
15
+
16
+ describe '#set' do
17
+ it 'should set the block in the registry' do
18
+ @data = stub 'data'
19
+ JSTP::Registry.instance.set @data
20
+ JSTP::Registry.instance.get.should == @data
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'JSTP::Server' do
4
+ it 'should set JSTP::Event::OnMessage to onmessage' do
5
+ server = stub 'server'
6
+ JSTP::Event::OnMessage.stub :call
7
+
8
+ server.should_receive(:onmessage)
9
+ .with(&JSTP::Event::OnMessage)
10
+
11
+ JSTP::Server.call server
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ require 'jstp'
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jstp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Xavier Via
9
+ - Luciano Bertenasco
10
+ - Matias Domingues
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-01-05 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: em-websocket
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: em-websocket-client
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ description: Reference implementation for the sketch protocol JSTP
65
+ email:
66
+ - xavierviacanel@gmail.com
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - .gitignore
72
+ - Gemfile
73
+ - JSTP.es.md
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - jstp.gemspec
78
+ - lib/jstp.rb
79
+ - lib/jstp/api.rb
80
+ - lib/jstp/connector.rb
81
+ - lib/jstp/event/on_message.rb
82
+ - lib/jstp/event_machine.rb
83
+ - lib/jstp/registry.rb
84
+ - lib/jstp/server.rb
85
+ - lib/jstp/version.rb
86
+ - spec/jstp/api_spec.rb
87
+ - spec/jstp/connector_spec.rb
88
+ - spec/jstp/event/on_message_spec.rb
89
+ - spec/jstp/event_machine_spec.rb
90
+ - spec/jstp/registry_spec.rb
91
+ - spec/jstp/server_spec.rb
92
+ - spec/spec_helper.rb
93
+ homepage: https://github.com/Fetcher/jstp
94
+ licenses: []
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 1.8.21
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: Reference implementation for the sketch protocol JSTP
117
+ test_files:
118
+ - spec/jstp/api_spec.rb
119
+ - spec/jstp/connector_spec.rb
120
+ - spec/jstp/event/on_message_spec.rb
121
+ - spec/jstp/event_machine_spec.rb
122
+ - spec/jstp/registry_spec.rb
123
+ - spec/jstp/server_spec.rb
124
+ - spec/spec_helper.rb
125
+ has_rdoc: