websocket 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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