websocket-eventmachine-client 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +5 -0
- data/README.md +208 -0
- data/Rakefile +16 -0
- data/autobahn.json +11 -0
- data/examples/autobahn_client.rb +50 -0
- data/examples/echo_client.rb +42 -0
- data/lib/websocket-eventmachine-client.rb +1 -0
- data/lib/websocket/eventmachine/client.rb +134 -0
- data/lib/websocket/eventmachine/client/version.rb +7 -0
- data/websocket-eventmachine-client.gemspec +21 -0
- metadata +73 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# WebSocket Client for Ruby
|
2
|
+
|
3
|
+
WebSocket-EventMachine-Client is Ruby WebSocket client based on EventMachine.
|
4
|
+
|
5
|
+
- [Autobahn tests](http://imanel.github.com/websocket-ruby/autobahn/client)
|
6
|
+
- [Docs](http://rdoc.info/github/imanel/websocket-eventmachine-client/master/frames)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
``` bash
|
11
|
+
gem install websocket-eventmachine-client
|
12
|
+
```
|
13
|
+
|
14
|
+
or in Gemfile
|
15
|
+
|
16
|
+
``` ruby
|
17
|
+
gem 'websocket-eventmachine-client'
|
18
|
+
```
|
19
|
+
|
20
|
+
## Simple client example
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
EM.run do
|
24
|
+
|
25
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => 'ws://localhost:8080')
|
26
|
+
|
27
|
+
ws.onopen do
|
28
|
+
puts "Connected"
|
29
|
+
end
|
30
|
+
|
31
|
+
ws.onmessage do |msg, type|
|
32
|
+
puts "Received message: #{msg}"
|
33
|
+
end
|
34
|
+
|
35
|
+
ws.onclose do
|
36
|
+
puts "Disconnected"
|
37
|
+
end
|
38
|
+
|
39
|
+
ws.send "Hello Server!"
|
40
|
+
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
## Options
|
45
|
+
|
46
|
+
Following options can be passed to WebSocket::EventMachine::Client initializer:
|
47
|
+
|
48
|
+
- `[String] :host` - IP or host of server to connect
|
49
|
+
- `[Integer] :port` - Port of server to connect
|
50
|
+
- `[String] :uri` - Full URI for server(optional - use instead of host/port combination)
|
51
|
+
- `[Integer] :version` - Version of WebSocket to use. Default: 13
|
52
|
+
|
53
|
+
## Methods
|
54
|
+
|
55
|
+
Following methods are available for WebSocket::EventMachine::Client object:
|
56
|
+
|
57
|
+
### onopen
|
58
|
+
|
59
|
+
Called after successfully connecting.
|
60
|
+
|
61
|
+
Example:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
ws.onopen do
|
65
|
+
puts "Client connected"
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### onclose
|
70
|
+
|
71
|
+
Called after closing connection.
|
72
|
+
|
73
|
+
Example:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
ws.onclose do
|
77
|
+
puts "Client disconnected"
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
### onmessage
|
82
|
+
|
83
|
+
Called when client receive message.
|
84
|
+
|
85
|
+
Parameters:
|
86
|
+
|
87
|
+
- `[String] message` - content of message
|
88
|
+
- `[Symbol] type` - type is type of message(:text or :binary)
|
89
|
+
|
90
|
+
Example:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
ws.onmessage do |msg, type|
|
94
|
+
puts "Received message: #{msg} or type: #{type}"
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
### onerror
|
99
|
+
|
100
|
+
Called when client discovers error.
|
101
|
+
|
102
|
+
Parameters:
|
103
|
+
|
104
|
+
- `[String] error` - error reason.
|
105
|
+
|
106
|
+
Example:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
ws.onerror do |error|
|
110
|
+
puts "Error occured: #{error}"
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
### onping
|
115
|
+
|
116
|
+
Called when client receive ping request. Pong request is sent automatically.
|
117
|
+
|
118
|
+
Parameters:
|
119
|
+
|
120
|
+
- `[String] message` - message for ping request.
|
121
|
+
|
122
|
+
Example:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
ws.onping do |message|
|
126
|
+
puts "Ping received: #{message}"
|
127
|
+
end
|
128
|
+
```
|
129
|
+
|
130
|
+
### onpong
|
131
|
+
|
132
|
+
Called when client receive pong response.
|
133
|
+
|
134
|
+
Parameters:
|
135
|
+
|
136
|
+
- `[String] message` - message for pong response.
|
137
|
+
|
138
|
+
Example:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
ws.onpong do |message|
|
142
|
+
puts "Pong received: #{message}"
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
### send
|
147
|
+
|
148
|
+
Sends message to server.
|
149
|
+
|
150
|
+
Parameters:
|
151
|
+
|
152
|
+
- `[String] message` - message that should be sent to client
|
153
|
+
- `[Hash] params` - params for message(optional)
|
154
|
+
- `[Symbol] :type` - type of message. Valid values are :text, :binary(default is :text)
|
155
|
+
|
156
|
+
Example:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
ws.send "Hello Server!"
|
160
|
+
ws.send "binary data", :type => :binary
|
161
|
+
```
|
162
|
+
|
163
|
+
### close
|
164
|
+
|
165
|
+
Closes connection and optionally send close frame to server.
|
166
|
+
|
167
|
+
Parameters:
|
168
|
+
|
169
|
+
- `[Integer] code` - code of closing, according to WebSocket specification(optional)
|
170
|
+
- `[String] data` - data to send in closing frame(optional)
|
171
|
+
|
172
|
+
Example:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
ws.close
|
176
|
+
```
|
177
|
+
|
178
|
+
### ping
|
179
|
+
|
180
|
+
Sends ping request.
|
181
|
+
|
182
|
+
Parameters:
|
183
|
+
|
184
|
+
- `[String] data` - data to send in ping request(optional)
|
185
|
+
|
186
|
+
Example:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
ws.ping 'Hi'
|
190
|
+
```
|
191
|
+
|
192
|
+
### pong
|
193
|
+
|
194
|
+
Sends pong request. Usually there should be no need to send this request, as pong responses are sent automatically by client.
|
195
|
+
|
196
|
+
Parameters:
|
197
|
+
|
198
|
+
- `[String] data` - data to send in pong request(optional)
|
199
|
+
|
200
|
+
Example:
|
201
|
+
|
202
|
+
``` ruby
|
203
|
+
ws.pong 'Hello'
|
204
|
+
```
|
205
|
+
|
206
|
+
## License
|
207
|
+
|
208
|
+
The MIT License - Copyright (c) 2012 Bernard Potocki
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
# require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
# RSpec::Core::RakeTask.new do |t|
|
7
|
+
# t.rspec_opts = ["-c", "-f progress"]
|
8
|
+
# t.pattern = 'spec/**/*_spec.rb'
|
9
|
+
# end
|
10
|
+
|
11
|
+
# task :default => :spec
|
12
|
+
|
13
|
+
desc "Run autobahn tests for client"
|
14
|
+
task :autobahn do
|
15
|
+
system('wstest --mode=fuzzingserver --spec=autobahn.json')
|
16
|
+
end
|
data/autobahn.json
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path('../../lib/websocket-eventmachine-client', __FILE__)
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
EM.epoll
|
6
|
+
EM.run do
|
7
|
+
|
8
|
+
host = 'ws://localhost:9001'
|
9
|
+
agent = "WebSocket-EventMachine-Client (1.0.0)"
|
10
|
+
cases = 0
|
11
|
+
skip = []
|
12
|
+
|
13
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/getCaseCount")
|
14
|
+
|
15
|
+
ws.onmessage do |msg, type|
|
16
|
+
puts "$ Total cases to run: #{msg}"
|
17
|
+
cases = msg.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
ws.onclose do
|
21
|
+
|
22
|
+
run_case = lambda do |n|
|
23
|
+
|
24
|
+
if n > cases
|
25
|
+
puts "$ Requesting report"
|
26
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/updateReports?agent=#{CGI.escape agent}")
|
27
|
+
ws.onclose do
|
28
|
+
EM.stop
|
29
|
+
end
|
30
|
+
|
31
|
+
elsif skip.include?(n)
|
32
|
+
EM.next_tick { run_case.call(n+1) }
|
33
|
+
|
34
|
+
else
|
35
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/runCase?case=#{n}&agent=#{CGI.escape agent}")
|
36
|
+
|
37
|
+
ws.onmessage do |msg, type|
|
38
|
+
ws.send(msg, :type => type)
|
39
|
+
end
|
40
|
+
|
41
|
+
ws.onclose do |msg|
|
42
|
+
EM.add_timer(0.1) { run_case.call(n + 1) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
run_case.call(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path('../../lib/websocket-eventmachine-client', __FILE__)
|
2
|
+
|
3
|
+
EM.epoll
|
4
|
+
EM.run do
|
5
|
+
|
6
|
+
trap("TERM") { stop }
|
7
|
+
trap("INT") { stop }
|
8
|
+
|
9
|
+
ws = WebSocket::EventMachine::Client.connect(:uri => "ws://localhost:9001");
|
10
|
+
|
11
|
+
ws.onopen do
|
12
|
+
puts "Connected"
|
13
|
+
ws.send "Hello"
|
14
|
+
end
|
15
|
+
|
16
|
+
ws.onmessage do |msg, type|
|
17
|
+
puts "Received message: #{msg}"
|
18
|
+
ws.send msg, :type => type
|
19
|
+
end
|
20
|
+
|
21
|
+
ws.onclose do
|
22
|
+
puts "Disconnected"
|
23
|
+
end
|
24
|
+
|
25
|
+
ws.onerror do |e|
|
26
|
+
puts "Error: #{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
ws.onping do |msg|
|
30
|
+
puts "Receied ping: #{msg}"
|
31
|
+
end
|
32
|
+
|
33
|
+
ws.onpong do |msg|
|
34
|
+
puts "Received pong: #{msg}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def stop
|
38
|
+
puts "Terminating connection"
|
39
|
+
EventMachine.stop
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../websocket/eventmachine/client', __FILE__)
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'websocket-eventmachine-base'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module WebSocket
|
5
|
+
module EventMachine
|
6
|
+
|
7
|
+
# WebSocket Client (using EventMachine)
|
8
|
+
# @example
|
9
|
+
# ws = WebSocket::EventMachine::Client.connect(:host => "0.0.0.0", :port => 8080)
|
10
|
+
# ws.onmessage { |msg| ws.send "Pong: #{msg}" }
|
11
|
+
# ws.send "data"
|
12
|
+
class Client < Base
|
13
|
+
|
14
|
+
###########
|
15
|
+
### API ###
|
16
|
+
###########
|
17
|
+
|
18
|
+
# Connect to websocket server
|
19
|
+
# @param args [Hash] The request arguments
|
20
|
+
# @option args [String] :host The host IP/DNS name
|
21
|
+
# @option args [Integer] :port The port to connect too(default = 80)
|
22
|
+
# @option args [Integer] :version Version of protocol to use(default = 13)
|
23
|
+
def self.connect(args = {})
|
24
|
+
host = nil
|
25
|
+
port = nil
|
26
|
+
if args[:uri]
|
27
|
+
uri = URI.parse(args[:uri])
|
28
|
+
host = uri.host
|
29
|
+
port = uri.port
|
30
|
+
end
|
31
|
+
host = args[:host] if args[:host]
|
32
|
+
port = args[:port] if args[:port]
|
33
|
+
port ||= 80
|
34
|
+
|
35
|
+
::EventMachine.connect host, port, self, args
|
36
|
+
end
|
37
|
+
|
38
|
+
# Initialize connection
|
39
|
+
# @param args [Hash] Arguments for connection
|
40
|
+
# @option args [String] :host The host IP/DNS name
|
41
|
+
# @option args [Integer] :port The port to connect too(default = 80)
|
42
|
+
# @option args [Integer] :version Version of protocol to use(default = 13)
|
43
|
+
def initialize(args)
|
44
|
+
@args = args
|
45
|
+
end
|
46
|
+
|
47
|
+
############################
|
48
|
+
### EventMachine methods ###
|
49
|
+
############################
|
50
|
+
|
51
|
+
# Called after initialize of connection, but before connecting to server
|
52
|
+
# Eventmachine internal
|
53
|
+
# @private
|
54
|
+
def post_init
|
55
|
+
@state = :connecting
|
56
|
+
@handshake = WebSocket::Handshake::Client.new(@args)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Called by EventMachine after connecting.
|
60
|
+
# Sends handshake to server
|
61
|
+
# Eventmachine internal
|
62
|
+
# @private
|
63
|
+
def connection_completed
|
64
|
+
send(@handshake.to_s, :type => :plain)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def incoming_frame
|
70
|
+
WebSocket::Frame::Incoming::Client
|
71
|
+
end
|
72
|
+
|
73
|
+
def outgoing_frame
|
74
|
+
WebSocket::Frame::Outgoing::Client
|
75
|
+
end
|
76
|
+
|
77
|
+
public
|
78
|
+
|
79
|
+
#########################
|
80
|
+
### Inherited methods ###
|
81
|
+
#########################
|
82
|
+
|
83
|
+
# Called when connection is opened.
|
84
|
+
# No parameters are passed to block
|
85
|
+
def onopen(&blk); super; end
|
86
|
+
|
87
|
+
# Called when connection is closed.
|
88
|
+
# No parameters are passed to block
|
89
|
+
def onclose(&blk); super; end
|
90
|
+
|
91
|
+
# Called when error occurs.
|
92
|
+
# One parameter passed to block:
|
93
|
+
# error - string with error message
|
94
|
+
def onerror(&blk); super; end
|
95
|
+
|
96
|
+
# Called when message is received.
|
97
|
+
# Two parameters passed to block:
|
98
|
+
# message - string with received message
|
99
|
+
# type - type of message. Valid values are :text and :binary
|
100
|
+
def onmessage(&blk); super; end
|
101
|
+
|
102
|
+
# Called when ping message is received
|
103
|
+
# One parameter passed to block:
|
104
|
+
# message - string with ping message
|
105
|
+
def onping(&blk); super; end
|
106
|
+
|
107
|
+
# Called when pond message is received
|
108
|
+
# One parameter passed to block:
|
109
|
+
# message - string with pong message
|
110
|
+
def onpong(&blk); super; end
|
111
|
+
|
112
|
+
# Send data
|
113
|
+
# @param data [String] Data to send
|
114
|
+
# @param args [Hash] Arguments for send
|
115
|
+
# @option args [String] :type Type of frame to send - available types are "text", "binary", "ping", "pong" and "close"
|
116
|
+
# @option args [Integer] :code Code for close frame
|
117
|
+
# @return [Boolean] true if data was send, otherwise call on_error if needed
|
118
|
+
def send(data, args = {}); super; end
|
119
|
+
|
120
|
+
# Close connection
|
121
|
+
# @return [Boolean] true if connection is closed immediately, false if waiting for other side to close connection
|
122
|
+
def close(code = 1000, data = nil); super; end
|
123
|
+
|
124
|
+
# Send ping message
|
125
|
+
# @return [Boolean] false if protocol version is not supporting ping requests
|
126
|
+
def ping(data = ''); super; end
|
127
|
+
|
128
|
+
# Send pong message
|
129
|
+
# @return [Boolean] false if protocol version is not supporting pong requests
|
130
|
+
def pong(data = ''); super; end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "websocket/eventmachine/client/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "websocket-eventmachine-client"
|
7
|
+
s.version = WebSocket::EventMachine::Client::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Bernard Potocki"]
|
10
|
+
s.email = ["bernard.potocki@imanel.org"]
|
11
|
+
s.homepage = "http://github.com/imanel/websocket-eventmachine-client"
|
12
|
+
s.summary = %q{WebSocket client for Ruby}
|
13
|
+
s.description = %q{WebSocket client for Ruby}
|
14
|
+
|
15
|
+
s.add_dependency 'websocket-eventmachine-base', '~> 1.0'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: websocket-eventmachine-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Bernard Potocki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: websocket-eventmachine-base
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
description: WebSocket client for Ruby
|
31
|
+
email:
|
32
|
+
- bernard.potocki@imanel.org
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- CHANGELOG.md
|
39
|
+
- Gemfile
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- autobahn.json
|
43
|
+
- examples/autobahn_client.rb
|
44
|
+
- examples/echo_client.rb
|
45
|
+
- lib/websocket-eventmachine-client.rb
|
46
|
+
- lib/websocket/eventmachine/client.rb
|
47
|
+
- lib/websocket/eventmachine/client/version.rb
|
48
|
+
- websocket-eventmachine-client.gemspec
|
49
|
+
homepage: http://github.com/imanel/websocket-eventmachine-client
|
50
|
+
licenses: []
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.24
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: WebSocket client for Ruby
|
73
|
+
test_files: []
|