websocket 1.0.5 → 1.0.6

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.
@@ -10,3 +10,6 @@ rvm:
10
10
  - rbx-18mode
11
11
  - rbx-19mode
12
12
  - ree
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: 2.0.0
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.6
4
+
5
+ - support text frame types instead of only symbol ones
6
+ - support for sending masked frames
7
+
3
8
  ## 1.0.5
4
9
 
5
10
  - add support for close codes
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # WebSocket Ruby
2
2
 
3
3
  - Travis CI build: [![](https://travis-ci.org/imanel/websocket-ruby.png)](http://travis-ci.org/imanel/websocket-ruby)
4
- - Autobahn tests: [server](http://imanel.github.com/websocket-ruby/autobahn/server/), client
4
+ - Autobahn tests: [server](http://imanel.github.com/websocket-ruby/autobahn/server/), [client](http://imanel.github.com/websocket-ruby/autobahn/client/)
5
5
 
6
6
  Universal Ruby library to handle WebSocket protocol. It focuses on providing abstraction layer over [WebSocket API](http://dev.w3.org/html5/websockets/) instead of providing server or client functionality.
7
7
 
@@ -100,9 +100,10 @@ frame.next # "Hello"
100
100
  frame.next # "world!""
101
101
  ```
102
102
 
103
- ## Examples
103
+ ## Examples & Projects using WebSocket-Ruby
104
104
 
105
- For examples on how to use WebSocket Ruby see examples directory in the repository. Provided examples are fully working servers - they are passing full autobahn compatibility suit.
105
+ - [WebSocket-EventMachine-Client](https://github.com/imanel/websocket-eventmachine-client) - client based on EventMachine
106
+ - [WebSocket-EventMachine-Server](https://github.com/imanel/websocket-eventmachine-server) - server based on EventMachine (drop-in replacement for EM-WebSocket)
106
107
 
107
108
  ## Native extension
108
109
 
@@ -12,7 +12,7 @@ module WebSocket
12
12
  # @option args [Integer] :code Code for close frame. Supported by drafts > 05.
13
13
  # @option args [Integer] :version Version of draft. Currently supported version are 75, 76 and 00-13.
14
14
  def initialize(args = {})
15
- @type = args[:type]
15
+ @type = args[:type].to_sym if args[:type]
16
16
  @code = args[:code]
17
17
  @data = Data.new(args[:data].to_s)
18
18
  @version = args[:version] || DEFAULT_VERSION
@@ -22,19 +22,29 @@ module WebSocket
22
22
  byte1 = opcode | (fin ? 0b10000000 : 0b00000000) # since more, rsv1-3 are 0 and 0x80 for Draft 4
23
23
  frame << byte1
24
24
 
25
+ mask = outgoing_masking? ? 0b10000000 : 0b00000000
26
+
25
27
  length = @data.size
26
28
  if length <= 125
27
29
  byte2 = length # since rsv4 is 0
28
- frame << byte2
30
+ frame << (byte2 | mask)
29
31
  elsif length < 65536 # write 2 byte length
30
- frame << 126
32
+ frame << (126 | mask)
31
33
  frame << [length].pack('n')
32
34
  else # write 8 byte length
33
- frame << 127
35
+ frame << (127 | mask)
34
36
  frame << [length >> 32, length & 0xFFFFFFFF].pack("NN")
35
37
  end
36
38
 
37
- frame << @data
39
+ if outgoing_masking?
40
+ masking_key = [rand(256).chr, rand(256).chr, rand(256).chr, rand(256).chr].join
41
+ tmp_data = Data.new([masking_key, @data.to_s].join)
42
+ tmp_data.set_mask
43
+ frame << masking_key + tmp_data.getbytes(4, tmp_data.size)
44
+ else
45
+ frame << @data
46
+ end
47
+
38
48
  frame
39
49
  rescue WebSocket::Error => e
40
50
  set_error(e.message.to_sym) and return
@@ -56,7 +66,7 @@ module WebSocket
56
66
  raise(WebSocket::Error, :fragmented_control_frame) if more && control_frame?(frame_type)
57
67
  raise(WebSocket::Error, :data_frame_instead_continuation) if data_frame?(frame_type) && !@application_data_buffer.nil?
58
68
 
59
- mask = masking? && (@data.getbyte(pointer) & 0b10000000) == 0b10000000
69
+ mask = incoming_masking? && (@data.getbyte(pointer) & 0b10000000) == 0b10000000
60
70
  length = @data.getbyte(pointer) & 0b01111111
61
71
 
62
72
  raise(WebSocket::Error, :control_frame_payload_too_long) if length > 125 && control_frame?(frame_type)
@@ -3,6 +3,16 @@ module WebSocket
3
3
  class Incoming
4
4
  class Client < Incoming
5
5
 
6
+ private
7
+
8
+ def incoming_masking?
9
+ false
10
+ end
11
+
12
+ def outgoing_masking?
13
+ masking?
14
+ end
15
+
6
16
  end
7
17
  end
8
18
  end
@@ -3,6 +3,16 @@ module WebSocket
3
3
  class Incoming
4
4
  class Server < Incoming
5
5
 
6
+ private
7
+
8
+ def incoming_masking?
9
+ masking?
10
+ end
11
+
12
+ def outgoing_masking?
13
+ false
14
+ end
15
+
6
16
  end
7
17
  end
8
18
  end
@@ -3,6 +3,16 @@ module WebSocket
3
3
  class Outgoing
4
4
  class Client < Outgoing
5
5
 
6
+ private
7
+
8
+ def incoming_masking?
9
+ false
10
+ end
11
+
12
+ def outgoing_masking?
13
+ masking?
14
+ end
15
+
6
16
  end
7
17
  end
8
18
  end
@@ -3,6 +3,16 @@ module WebSocket
3
3
  class Outgoing
4
4
  class Server < Outgoing
5
5
 
6
+ private
7
+
8
+ def incoming_masking?
9
+ masking?
10
+ end
11
+
12
+ def outgoing_masking?
13
+ false
14
+ end
15
+
6
16
  end
7
17
  end
8
18
  end
@@ -1,3 +1,3 @@
1
1
  module WebSocket
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.6'
3
3
  end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Masking frame draft 07' do
4
+ it "should encode and decode masked frame correctly" do
5
+ outgoing_frame = WebSocket::Frame::Outgoing::Client.new(:data => "Hello World", :type => "text")
6
+ outgoing_frame.to_s
7
+ outgoing_frame.error.should be_nil
8
+ incoming_frame = WebSocket::Frame::Incoming::Server.new(:data => outgoing_frame.to_s).next
9
+ incoming_frame.should_not be_nil
10
+ incoming_frame.class.should eql(WebSocket::Frame::Incoming::Server)
11
+ incoming_frame.error.should be_nil
12
+ incoming_frame.decoded?.should be_true
13
+ incoming_frame.to_s.should eql('Hello World')
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module WebSocket
2
+ module Frame
3
+ class Base
4
+
5
+ private
6
+
7
+ def incoming_masking?
8
+ masking?
9
+ end
10
+
11
+ def outgoing_masking?
12
+ false
13
+ end
14
+
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websocket
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-19 00:00:00.000000000 Z
12
+ date: 2012-12-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -40,15 +40,6 @@ files:
40
40
  - Gemfile
41
41
  - README.md
42
42
  - Rakefile
43
- - autobahn-client.json
44
- - autobahn-server.json
45
- - examples/base.rb
46
- - examples/client.rb
47
- - examples/server.rb
48
- - examples/tests/autobahn_client.rb
49
- - examples/tests/autobahn_server.rb
50
- - examples/tests/echo_client.rb
51
- - examples/tests/echo_server.rb
52
43
  - lib/websocket.rb
53
44
  - lib/websocket/frame.rb
54
45
  - lib/websocket/frame/base.rb
@@ -88,6 +79,7 @@ files:
88
79
  - spec/frame/incoming_07_spec.rb
89
80
  - spec/frame/incoming_75_spec.rb
90
81
  - spec/frame/incoming_common_spec.rb
82
+ - spec/frame/masking_spec.rb
91
83
  - spec/frame/outgoing_03_spec.rb
92
84
  - spec/frame/outgoing_04_spec.rb
93
85
  - spec/frame/outgoing_05_spec.rb
@@ -103,6 +95,7 @@ files:
103
95
  - spec/spec_helper.rb
104
96
  - spec/support/all_client_drafts.rb
105
97
  - spec/support/all_server_drafts.rb
98
+ - spec/support/frames_base.rb
106
99
  - spec/support/handshake_requests.rb
107
100
  - spec/support/incoming_frames.rb
108
101
  - spec/support/outgoing_frames.rb
@@ -138,6 +131,7 @@ test_files:
138
131
  - spec/frame/incoming_07_spec.rb
139
132
  - spec/frame/incoming_75_spec.rb
140
133
  - spec/frame/incoming_common_spec.rb
134
+ - spec/frame/masking_spec.rb
141
135
  - spec/frame/outgoing_03_spec.rb
142
136
  - spec/frame/outgoing_04_spec.rb
143
137
  - spec/frame/outgoing_05_spec.rb
@@ -153,6 +147,7 @@ test_files:
153
147
  - spec/spec_helper.rb
154
148
  - spec/support/all_client_drafts.rb
155
149
  - spec/support/all_server_drafts.rb
150
+ - spec/support/frames_base.rb
156
151
  - spec/support/handshake_requests.rb
157
152
  - spec/support/incoming_frames.rb
158
153
  - spec/support/outgoing_frames.rb
@@ -1,11 +0,0 @@
1
- {
2
- "url": "ws://127.0.0.1:9001",
3
-
4
- "options": {"failByDrop": false},
5
- "outdir": "./autobahn/client",
6
- "webport": 8080,
7
-
8
- "cases": ["1.1.1"],
9
- "exclude-cases": [],
10
- "exclude-agent-cases": {}
11
- }
@@ -1,15 +0,0 @@
1
- {
2
- "options": {"failByDrop": false},
3
- "outdir": "./autobahn/server",
4
-
5
- "servers": [
6
- {"agent": "WebSocket-Ruby<br>(1.0.4 Pure)", "url": "ws://localhost:9001", "options": {"version": 18}},
7
- {"agent": "WebSocket-Ruby<br>(1.0.4 Native)", "url": "ws://localhost:9002", "options": {"version": 18}},
8
- {"agent": "Faye-WebSocket<br>(0.4.6 Thin)", "url": "ws://localhost:7000", "options": {"version": 18}},
9
- {"agent": "EM-WebSocket<br>(0.3.8)", "url": "ws://localhost:8080", "options": {"version": 18}}
10
- ],
11
-
12
- "cases": ["*"],
13
- "exclude-cases": [],
14
- "exclude-agent-cases": {}
15
- }
@@ -1,162 +0,0 @@
1
- require 'rubygems'
2
- require 'eventmachine'
3
- require "#{File.expand_path(File.dirname(__FILE__))}/../lib/websocket"
4
-
5
- module WebSocket
6
- module EventMachine
7
- class Base < ::EventMachine::Connection
8
-
9
- ###########
10
- ### API ###
11
- ###########
12
-
13
- def onopen(&blk); @onopen = blk; end # Called when connection is opened
14
- def onclose(&blk); @onclose = blk; end # Called when connection is closed
15
- def onerror(&blk); @onerror = blk; end # Called when error occurs
16
- def onmessage(&blk); @onmessage = blk; end # Called when message is received from server
17
- def onping(&blk); @onping = blk; end # Called when ping message is received from server
18
- def onpong(&blk); @onpong = blk; end # Called when pond message is received from server
19
-
20
- # Send data to client
21
- # @param data [String] Data to send
22
- # @param args [Hash] Arguments for send
23
- # @option args [String] :type Type of frame to send - available types are "text", "binary", "ping", "pong" and "close"
24
- # @return [Boolean] true if data was send, otherwise call on_error if needed
25
- def send(data, args = {})
26
- type = args[:type] || :text
27
- unless type == :plain
28
- frame = outgoing_frame.new(:version => @handshake.version, :data => data, :type => type)
29
- if !frame.supported?
30
- trigger_onerror("Frame type '#{type}' is not supported in protocol version #{@handshake.version}")
31
- return false
32
- elsif !frame.require_sending?
33
- return false
34
- end
35
- data = frame.to_s
36
- end
37
- # debug "Sending raw: ", data
38
- send_data(data)
39
- true
40
- end
41
-
42
- # Close connection
43
- # @return [Boolean] true if connection is closed immediately, false if waiting for server to close connection
44
- def close
45
- if @state == :open
46
- @state = :closing
47
- return false if send('', :type => :close)
48
- else
49
- send('', :type => :close) if @state == :closing
50
- @state = :closed
51
- end
52
- close_connection_after_writing
53
- true
54
- end
55
-
56
- # Send ping message to client
57
- # @return [Boolean] false if protocol version is not supporting ping requests
58
- def ping(data = '')
59
- send(data, :type => :ping)
60
- end
61
-
62
- # Send pong message to client
63
- # @return [Boolean] false if protocol version is not supporting pong requests
64
- def pong(data = '')
65
- send(data, :type => :pong)
66
- end
67
-
68
- ############################
69
- ### EventMachine methods ###
70
- ############################
71
-
72
- def receive_data(data)
73
- # debug "Received raw: ", data
74
- case @state
75
- when :connecting then handle_connecting(data)
76
- when :open then handle_open(data)
77
- when :closing then handle_closing(data)
78
- end
79
- end
80
-
81
- def unbind
82
- unless @state == :closed
83
- @state = :closed
84
- close
85
- trigger_onclose('')
86
- end
87
- end
88
-
89
- #######################
90
- ### Private methods ###
91
- #######################
92
-
93
- private
94
-
95
- ['onopen'].each do |m|
96
- define_method "trigger_#{m}" do
97
- callback = instance_variable_get("@#{m}")
98
- callback.call if callback
99
- end
100
- end
101
-
102
- ['onerror', 'onping', 'onpong', 'onclose'].each do |m|
103
- define_method "trigger_#{m}" do |data|
104
- callback = instance_variable_get("@#{m}")
105
- callback.call(data) if callback
106
- end
107
- end
108
-
109
- def trigger_onmessage(data, type)
110
- @onmessage.call(data, type) if @onmessage
111
- end
112
-
113
- def handle_connecting(data)
114
- @handshake << data
115
- return unless @handshake.finished?
116
- if @handshake.valid?
117
- send(@handshake.to_s, :type => :plain) if @handshake.should_respond?
118
- @frame = incoming_frame.new(:version => @handshake.version)
119
- @state = :open
120
- trigger_onopen
121
- handle_open(@handshake.leftovers) if @handshake.leftovers
122
- else
123
- trigger_onerror(@handshake.error)
124
- close
125
- end
126
- end
127
-
128
- def handle_open(data)
129
- @frame << data
130
- while frame = @frame.next
131
- case frame.type
132
- when :close
133
- @state = :closing
134
- close
135
- trigger_onclose(frame.to_s)
136
- when :ping
137
- pong(frame.to_s)
138
- trigger_onping(frame.to_s)
139
- when :pong
140
- trigger_onpong(frame.to_s)
141
- when :text
142
- trigger_onmessage(frame.to_s, :text)
143
- when :binary
144
- trigger_onmessage(frame.to_s, :binary)
145
- end
146
- end
147
- unbind if @frame.error?
148
- end
149
-
150
- def handle_closing(data)
151
- @state = :closed
152
- close
153
- trigger_onclose
154
- end
155
-
156
- def debug(description, data)
157
- puts(description + data.bytes.to_a.collect{|b| '\x' + b.to_s(16).rjust(2, '0')}.join) unless @state == :connecting
158
- end
159
-
160
- end
161
- end
162
- end
@@ -1,70 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/base"
2
- require 'uri'
3
-
4
- # Example WebSocket Client (using EventMachine)
5
- # @example
6
- # ws = WebSocket::EventMachine::Client.connect(:host => "0.0.0.0", :port => 8080)
7
- # ws.onmessage { |msg| ws.send "Pong: #{msg}" }
8
- # ws.send "data"
9
- module WebSocket
10
- module EventMachine
11
- class Client < Base
12
-
13
- # Connect to websocket server
14
- # @param args [Hash] The request arguments
15
- # @option args [String] :host The host IP/DNS name
16
- # @option args [Integer] :port The port to connect too(default = 80)
17
- # @option args [Integer] :version Version of protocol to use(default = 13)
18
- def self.connect(args = {})
19
- host = nil
20
- port = nil
21
- if args[:uri]
22
- uri = URI.parse(args[:uri])
23
- host = uri.host
24
- port = uri.port
25
- end
26
- host = args[:host] if args[:host]
27
- port = args[:port] if args[:port]
28
- port ||= 80
29
-
30
- ::EventMachine.connect host, port, self, args
31
- end
32
-
33
- # Initialize connection
34
- # @param args [Hash] Arguments for connection
35
- # @option args [String] :host The host IP/DNS name
36
- # @option args [Integer] :port The port to connect too(default = 80)
37
- # @option args [Integer] :version Version of protocol to use(default = 13)
38
- def initialize(args)
39
- @args = args
40
- end
41
-
42
- ############################
43
- ### EventMachine methods ###
44
- ############################
45
-
46
- # Called after initialize of connection, but before connecting to server
47
- def post_init
48
- @state = :connecting
49
- @handshake = WebSocket::Handshake::Client.new(@args)
50
- end
51
-
52
- # Called by EventMachine after connecting.
53
- # Sends handshake to server
54
- def connection_completed
55
- send(@handshake.to_s, :type => :plain)
56
- end
57
-
58
- private
59
-
60
- def incoming_frame
61
- WebSocket::Frame::Incoming::Client
62
- end
63
-
64
- def outgoing_frame
65
- WebSocket::Frame::Outgoing::Client
66
- end
67
-
68
- end
69
- end
70
- end
@@ -1,56 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/base"
2
-
3
- # Example WebSocket Server (using EventMachine)
4
- # @example
5
- # WebSocket::EventMachine::Server.start(:host => "0.0.0.0", :port => 8080) do |ws|
6
- # ws.onopen { ws.send "Hello Client!"}
7
- # ws.onmessage { |msg| ws.send "Pong: #{msg}" }
8
- # ws.onclose { puts "WebSocket closed" }
9
- # ws.onerror { |e| puts "Error: #{e}" }
10
- # end
11
- module WebSocket
12
- module EventMachine
13
- class Server < Base
14
-
15
- # Start server
16
- # @param options [Hash] The request arguments
17
- # @option args [String] :host The host IP/DNS name
18
- # @option args [Integer] :port The port to connect too(default = 80)
19
- def self.start(options, &block)
20
- ::EventMachine::start_server(options[:host], options[:port], self, options) do |c|
21
- block.call(c)
22
- end
23
- end
24
-
25
- # Initialize connection
26
- # @param args [Hash] Arguments for server
27
- # @option args [Boolean] :secure If true then server will run over SSL
28
- # @option args [Hash] :tls_options Options for SSL if secure = true
29
- def initialize(args)
30
- @secure = args[:secure] || false
31
- @tls_options = args[:tls_options] || {}
32
- end
33
-
34
- ############################
35
- ### Eventmachine methods ###
36
- ############################
37
-
38
- def post_init
39
- @state = :connecting
40
- @handshake = WebSocket::Handshake::Server.new(:secure => @secure)
41
- start_tls(@tls_options) if @secure
42
- end
43
-
44
- private
45
-
46
- def incoming_frame
47
- WebSocket::Frame::Incoming::Server
48
- end
49
-
50
- def outgoing_frame
51
- WebSocket::Frame::Outgoing::Server
52
- end
53
-
54
- end
55
- end
56
- end
@@ -1,52 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/../client"
2
- require 'cgi'
3
-
4
- EM.epoll
5
- EM.run do
6
-
7
- host = 'ws://localhost:9001'
8
- agent = "WebSocket-Ruby (Ruby #{RUBY_VERSION})"
9
- cases = 0
10
- skip = []
11
-
12
- ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/getCaseCount")
13
-
14
- ws.onmessage do |msg, type|
15
- puts "$ Total cases to run: #{msg}"
16
- cases = msg.to_i
17
- end
18
-
19
- ws.onclose do
20
-
21
- run_case = lambda do |n|
22
-
23
- if n > cases
24
- puts "$ Requesting report"
25
- ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/updateReports?agent=#{CGI.escape agent}")
26
- ws.onclose do
27
- EM.stop
28
- end
29
-
30
- elsif skip.include?(n)
31
- EM.next_tick { run_case.call(n+1) }
32
-
33
- else
34
- puts "$ Test number #{n}"
35
- ws = WebSocket::EventMachine::Client.connect(:uri => "#{host}/runCase?case=#{n}&agent=#{CGI.escape agent}")
36
-
37
- ws.onmessage do |msg, type|
38
- puts "Received #{msg}(#{type})"
39
- ws.send(msg, :type => type)
40
- end
41
-
42
- ws.onclose do |msg|
43
- puts("Closing: #{msg}") if msg
44
- run_case.call(n + 1)
45
- end
46
- end
47
- end
48
-
49
- run_case.call(1)
50
- end
51
-
52
- end
@@ -1,24 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/../server"
2
-
3
- EM.epoll
4
- EM.run do
5
-
6
- trap("TERM") { stop }
7
- trap("INT") { stop }
8
-
9
- WebSocket::EventMachine::Server.start(:host => "0.0.0.0", :port => 9001) do |ws|
10
-
11
- ws.onmessage do |msg, type|
12
- ws.send msg, :type => type
13
- end
14
-
15
- end
16
-
17
- puts "Server started at port 9001"
18
-
19
- def stop
20
- puts "Terminating WebSocket Server"
21
- EventMachine.stop
22
- end
23
-
24
- end
@@ -1,42 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/../client"
2
-
3
- EM.epoll
4
- EM.run do
5
-
6
- trap("TERM") { stop }
7
- trap("INT") { stop }
8
-
9
- ws = WebSocket::EventMachine::Client.connect(:host => "localhost", :port => 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
@@ -1,45 +0,0 @@
1
- require "#{File.expand_path(File.dirname(__FILE__))}/../server"
2
-
3
- EM.epoll
4
- EM.run do
5
-
6
- trap("TERM") { stop }
7
- trap("INT") { stop }
8
-
9
- WebSocket::EventMachine::Server.start(:host => "0.0.0.0", :port => 9001) do |ws|
10
-
11
- ws.onopen do
12
- puts "Client connected"
13
- end
14
-
15
- ws.onmessage do |msg, type|
16
- puts "Received message: #{msg}"
17
- ws.send msg, :type => type
18
- end
19
-
20
- ws.onclose do
21
- puts "Client disconnected"
22
- end
23
-
24
- ws.onerror do |e|
25
- puts "Error: #{e}"
26
- end
27
-
28
- ws.onping do |msg|
29
- puts "Receied ping: #{msg}"
30
- end
31
-
32
- ws.onpong do |msg|
33
- puts "Received pong: #{msg}"
34
- end
35
-
36
- end
37
-
38
- puts "Server started at port 9001"
39
-
40
- def stop
41
- puts "Terminating WebSocket Server"
42
- EventMachine.stop
43
- end
44
-
45
- end