faye-websocket 0.1.0
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.
Potentially problematic release.
This version of faye-websocket might be problematic. Click here for more details.
- data/README.rdoc +132 -0
- data/examples/autobahn_client.rb +45 -0
- data/examples/client.rb +30 -0
- data/examples/index.html +35 -0
- data/examples/server.rb +43 -0
- data/lib/faye/thin_extensions.rb +75 -0
- data/lib/faye/websocket.rb +126 -0
- data/lib/faye/websocket/api.rb +110 -0
- data/lib/faye/websocket/client.rb +82 -0
- data/lib/faye/websocket/draft75_parser.rb +53 -0
- data/lib/faye/websocket/draft76_parser.rb +53 -0
- data/lib/faye/websocket/protocol8_parser.rb +324 -0
- data/spec/faye/websocket/client_spec.rb +146 -0
- data/spec/faye/websocket/draft75_parser_spec.rb +41 -0
- data/spec/faye/websocket/protocol8_parser_spec.rb +145 -0
- data/spec/server.crt +15 -0
- data/spec/server.key +15 -0
- data/spec/spec_helper.rb +50 -0
- metadata +109 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding=utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
WebSocketSteps = EM::RSpec.async_steps do
|
6
|
+
def server(port, secure, &callback)
|
7
|
+
@server = EchoServer.new
|
8
|
+
@server.listen(port, secure)
|
9
|
+
@port = port
|
10
|
+
EM.add_timer(0.1, &callback)
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop(&callback)
|
14
|
+
@server.stop
|
15
|
+
EM.next_tick(&callback)
|
16
|
+
end
|
17
|
+
|
18
|
+
def open_socket(url, &callback)
|
19
|
+
done = false
|
20
|
+
|
21
|
+
resume = lambda do |open|
|
22
|
+
unless done
|
23
|
+
done = true
|
24
|
+
@open = open
|
25
|
+
callback.call
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@ws = Faye::WebSocket::Client.new(url)
|
30
|
+
|
31
|
+
@ws.onopen = lambda { |e| resume.call(true) }
|
32
|
+
@ws.onclose = lambda { |e| resume.call(false) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def close_socket(&callback)
|
36
|
+
@ws.onclose = lambda do |e|
|
37
|
+
@open = false
|
38
|
+
callback.call
|
39
|
+
end
|
40
|
+
@ws.close
|
41
|
+
end
|
42
|
+
|
43
|
+
def check_open(&callback)
|
44
|
+
@open.should == true
|
45
|
+
callback.call
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_closed(&callback)
|
49
|
+
@open.should == false
|
50
|
+
callback.call
|
51
|
+
end
|
52
|
+
|
53
|
+
def listen_for_message(&callback)
|
54
|
+
@ws.onmessage = lambda { |e| @message = e.data }
|
55
|
+
callback.call
|
56
|
+
end
|
57
|
+
|
58
|
+
def send_message(&callback)
|
59
|
+
@ws.send("I expect this to be echoed")
|
60
|
+
EM.add_timer(0.1, &callback)
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_response(&callback)
|
64
|
+
@message.should == "I expect this to be echoed"
|
65
|
+
callback.call
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_no_response(&callback)
|
69
|
+
@message.should == nil
|
70
|
+
callback.call
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe Faye::WebSocket::Client do
|
75
|
+
include WebSocketSteps
|
76
|
+
|
77
|
+
let(:plain_text_url) { "ws://0.0.0.0:8000/" }
|
78
|
+
let(:secure_url) { "wss://0.0.0.0:8000/" }
|
79
|
+
|
80
|
+
before do
|
81
|
+
Thread.new { EM.run }
|
82
|
+
sleep(0.1) until EM.reactor_running?
|
83
|
+
end
|
84
|
+
|
85
|
+
shared_examples_for "socket client" do
|
86
|
+
it "can open a connection" do
|
87
|
+
open_socket(socket_url)
|
88
|
+
check_open
|
89
|
+
end
|
90
|
+
|
91
|
+
it "cannot open a connection to the wrong host" do
|
92
|
+
open_socket(blocked_url)
|
93
|
+
check_closed
|
94
|
+
end
|
95
|
+
|
96
|
+
it "can close the connection" do
|
97
|
+
open_socket(socket_url)
|
98
|
+
close_socket
|
99
|
+
check_closed
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "in the OPEN state" do
|
103
|
+
before { open_socket(socket_url) }
|
104
|
+
|
105
|
+
it "can send and receive messages" do
|
106
|
+
listen_for_message
|
107
|
+
send_message
|
108
|
+
check_response
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "in the CLOSED state" do
|
113
|
+
before do
|
114
|
+
open_socket(socket_url)
|
115
|
+
close_socket
|
116
|
+
end
|
117
|
+
|
118
|
+
it "cannot send and receive messages" do
|
119
|
+
listen_for_message
|
120
|
+
send_message
|
121
|
+
check_no_response
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "with a plain-text server" do
|
127
|
+
let(:socket_url) { plain_text_url }
|
128
|
+
let(:blocked_url) { secure_url }
|
129
|
+
|
130
|
+
before { server 8000, false }
|
131
|
+
after { sync ; stop }
|
132
|
+
|
133
|
+
it_should_behave_like "socket client"
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "with a secure server" do
|
137
|
+
let(:socket_url) { secure_url }
|
138
|
+
let(:blocked_url) { plain_text_url }
|
139
|
+
|
140
|
+
before { server 8000, true }
|
141
|
+
after { sync ; stop }
|
142
|
+
|
143
|
+
it_should_behave_like "socket client"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding=utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Faye::WebSocket::Draft75Parser do
|
6
|
+
include EncodingHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@web_socket = mock Faye::WebSocket
|
10
|
+
@parser = Faye::WebSocket::Draft75Parser.new(@web_socket)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe :parse do
|
14
|
+
it "parses text frames" do
|
15
|
+
@web_socket.should_receive(:receive).with("Hello")
|
16
|
+
parse [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "parses multibyte text frames" do
|
20
|
+
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
21
|
+
parse [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "parses fragmented frames" do
|
25
|
+
@web_socket.should_receive(:receive).with("Hello")
|
26
|
+
parse [0x00, 0x48, 0x65, 0x6c]
|
27
|
+
parse [0x6c, 0x6f, 0xff]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe :frame do
|
32
|
+
it "returns the given string formatted as a WebSocket frame" do
|
33
|
+
bytes(@parser.frame "Hello").should == [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "encodes multibyte characters correctly" do
|
37
|
+
message = encode "Apple = "
|
38
|
+
bytes(@parser.frame message).should == [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# encoding=utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Faye::WebSocket::Protocol8Parser do
|
6
|
+
include EncodingHelper
|
7
|
+
|
8
|
+
before do
|
9
|
+
@web_socket = mock Faye::WebSocket
|
10
|
+
@parser = Faye::WebSocket::Protocol8Parser.new(@web_socket)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe :parse do
|
14
|
+
let(:mask) { (1..4).map { rand 255 } }
|
15
|
+
|
16
|
+
def mask_message(*bytes)
|
17
|
+
output = []
|
18
|
+
bytes.each_with_index do |byte, i|
|
19
|
+
output[i] = byte ^ mask[i % 4]
|
20
|
+
end
|
21
|
+
output
|
22
|
+
end
|
23
|
+
|
24
|
+
it "parses unmasked text frames" do
|
25
|
+
@web_socket.should_receive(:receive).with("Hello")
|
26
|
+
parse [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "parses empty text frames" do
|
30
|
+
@web_socket.should_receive(:receive).with("")
|
31
|
+
parse [0x81, 0x00]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "parses fragmented text frames" do
|
35
|
+
@web_socket.should_receive(:receive).with("Hello")
|
36
|
+
parse [0x01, 0x03, 0x48, 0x65, 0x6c]
|
37
|
+
parse [0x80, 0x02, 0x6c, 0x6f]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "parses masked text frames" do
|
41
|
+
@web_socket.should_receive(:receive).with("Hello")
|
42
|
+
parse [0x81, 0x85] + mask + mask_message(0x48, 0x65, 0x6c, 0x6c, 0x6f)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "parses masked empty text frames" do
|
46
|
+
@web_socket.should_receive(:receive).with("")
|
47
|
+
parse [0x81, 0x80] + mask + mask_message()
|
48
|
+
end
|
49
|
+
|
50
|
+
it "parses masked fragmented text frames" do
|
51
|
+
@web_socket.should_receive(:receive).with("Hello")
|
52
|
+
parse [0x01, 0x81] + mask + mask_message(0x48)
|
53
|
+
parse [0x80, 0x84] + mask + mask_message(0x65, 0x6c, 0x6c, 0x6f)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "closes the socket if the frame has an unrecognized opcode" do
|
57
|
+
@web_socket.should_receive(:close).with(1002, nil, false)
|
58
|
+
parse [0x83, 0x00]
|
59
|
+
end
|
60
|
+
|
61
|
+
it "closes the socket if a close frame is received" do
|
62
|
+
@web_socket.should_receive(:close).with(1000, "Hello", false)
|
63
|
+
parse [0x88, 0x07, 0x03, 0xe8, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "parses unmasked multibyte text frames" do
|
67
|
+
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
68
|
+
parse [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "parses fragmented multibyte text frames" do
|
72
|
+
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
73
|
+
parse [0x01, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3]
|
74
|
+
parse [0x80, 0x01, 0xbf]
|
75
|
+
end
|
76
|
+
|
77
|
+
it "parses masked multibyte text frames" do
|
78
|
+
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
79
|
+
parse [0x81, 0x8b] + mask + mask_message(0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "parses masked fragmented multibyte text frames" do
|
83
|
+
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
84
|
+
parse [0x01, 0x8a] + mask + mask_message(0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3)
|
85
|
+
parse [0x80, 0x81] + mask + mask_message(0xbf)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "parses unmasked medium-length text frames" do
|
89
|
+
@web_socket.should_receive(:receive).with("Hello" * 40)
|
90
|
+
parse [0x81, 0x7e, 0x00, 0xc8] + [0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40
|
91
|
+
end
|
92
|
+
|
93
|
+
it "parses masked medium-length text frames" do
|
94
|
+
@web_socket.should_receive(:receive).with("Hello" * 40)
|
95
|
+
parse [0x81, 0xfe, 0x00, 0xc8] + mask + mask_message(*([0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40))
|
96
|
+
end
|
97
|
+
|
98
|
+
it "replies to pings with a pong" do
|
99
|
+
@web_socket.should_receive(:send).with([0x4f, 0x48, 0x41, 0x49], :pong)
|
100
|
+
parse [0x89, 0x04, 0x4f, 0x48, 0x41, 0x49]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe :frame do
|
105
|
+
it "returns the given string formatted as a WebSocket frame" do
|
106
|
+
bytes(@parser.frame "Hello").should == [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
107
|
+
end
|
108
|
+
|
109
|
+
it "encodes multibyte characters correctly" do
|
110
|
+
message = encode "Apple = "
|
111
|
+
bytes(@parser.frame message).should == [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "encodes medium-length strings using extra length bytes" do
|
115
|
+
message = "Hello" * 40
|
116
|
+
bytes(@parser.frame message).should == [0x81, 0x7e, 0x00, 0xc8] + [0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40
|
117
|
+
end
|
118
|
+
|
119
|
+
it "encodes long strings using extra length bytes" do
|
120
|
+
message = "Hello" * 13108
|
121
|
+
bytes(@parser.frame message).should == [0x81, 0x7f] +
|
122
|
+
[0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04] +
|
123
|
+
[0x48, 0x65, 0x6c, 0x6c, 0x6f] * 13108
|
124
|
+
end
|
125
|
+
|
126
|
+
it "encodes close frames with an error code" do
|
127
|
+
frame = @parser.frame "Hello", :close, 1002
|
128
|
+
bytes(frame).should == [0x88, 0x07, 0x03, 0xea, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
129
|
+
end
|
130
|
+
|
131
|
+
it "encodes pong frames" do
|
132
|
+
bytes(@parser.frame '', :pong).should == [0x8a, 0x00]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe :utf8 do
|
137
|
+
it "detects valid UTF-8" do
|
138
|
+
Faye::WebSocket.valid_utf8?( [72, 101, 108, 108, 111, 45, 194, 181, 64, 195, 159, 195, 182, 195, 164, 195, 188, 195, 160, 195, 161, 45, 85, 84, 70, 45, 56, 33, 33] ).should be_true
|
139
|
+
end
|
140
|
+
|
141
|
+
it "detects invalid UTF-8" do
|
142
|
+
Faye::WebSocket.valid_utf8?( [206, 186, 225, 189, 185, 207, 131, 206, 188, 206, 181, 237, 160, 128, 101, 100, 105, 116, 101, 100] ).should be_false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/spec/server.crt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICZTCCAc4CCQDxyrJZrFA0vjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJV
|
3
|
+
SzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBEZh
|
4
|
+
eWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJARYRamNvZ2xh
|
5
|
+
bkBnbWFpbC5jb20wHhcNMTEwODMwMTIzOTM2WhcNMTIwODI5MTIzOTM2WjB3MQsw
|
6
|
+
CQYDVQQGEwJVSzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTAL
|
7
|
+
BgNVBAoTBEZheWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJ
|
8
|
+
ARYRamNvZ2xhbkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
|
9
|
+
AMDjU5fAK7fvUCZIYHcGXDZD/m9bY+B/UcwGcowk0hMQGYNlLKrpiK7xXBmZpDb6
|
10
|
+
r8n+7L/epBeSumbRIm4TDzeNHhuQGYLIeGQy7JNLoPBr6GxubjuJhKOOBnCqcupR
|
11
|
+
CLGG7Zw5oL4UvtZVH6kL9XnjyokQQbxxeoV9DqtqOaHHAgMBAAEwDQYJKoZIhvcN
|
12
|
+
AQEFBQADgYEAvQjSpzE1ahaeH1CmbLwckTxvWMZfxcZOrxTruK1po3cNnDOjGqFQ
|
13
|
+
KEkNj3K5WfwTBD4QgUdYDykhDX2m6HaMz4JEbgrwQv8M8FiswIA3dyGsbOifOk8H
|
14
|
+
r3GPNKMzm4o6vrn6RGOpt9q6bsWUBUHfNpP93uU2C9QEwDua3cFjDA0=
|
15
|
+
-----END CERTIFICATE-----
|
data/spec/server.key
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICXAIBAAKBgQDA41OXwCu371AmSGB3Blw2Q/5vW2Pgf1HMBnKMJNITEBmDZSyq
|
3
|
+
6Yiu8VwZmaQ2+q/J/uy/3qQXkrpm0SJuEw83jR4bkBmCyHhkMuyTS6Dwa+hsbm47
|
4
|
+
iYSjjgZwqnLqUQixhu2cOaC+FL7WVR+pC/V548qJEEG8cXqFfQ6rajmhxwIDAQAB
|
5
|
+
AoGABlk1DiCQD8y7mZb2PdSiwlJ4lFewsNnf6lQn/v7TPzdfb5ir4LAxBHkDLACH
|
6
|
+
jBuyH3bZefMs+W2l3u5xMKhF7uJqYcUlJdH2UwRfNG54Hn4SGAjQOK3ONer99sUf
|
7
|
+
USlsWSX1HjAAFMCBwUfKxMZA3VNQfYKTPdm0jSVf85kHO1ECQQD3s6ksm3QpfD0L
|
8
|
+
eG9EoDrqmwnEfpKoWPpz1O0i5tY9VcmhmLwS5Zpd7lB1qjTqzZk4RygU73T/BseJ
|
9
|
+
azehIHK5AkEAx1mSXt+ec8RfzVi/io6oqi2vOcACXRbOG4NQmqUWPnumdwsJjsjR
|
10
|
+
RzEoDFC2lu6448p9sgEq+CkbmgVeiyp4fwJAQnmgySve/NMuvslPcyddKGD7OhSN
|
11
|
+
30ghzrwx98/jZwqC1i9bKeccimDOjwVitjD/Ea9m/ldVGqwDGMoBX+iJYQJAEIOO
|
12
|
+
CYfyw1pQKV2huGOq+zX/nwQV7go2lrbhFX55gkGR/6iNaSOfmosq6yJAje5GqLAc
|
13
|
+
i4NnQNl+7NpnA5ZIFwJBAI1+OsZyjbRI99pYkTdOpa5IPlIb3j3JbSfjAWHLxlRY
|
14
|
+
0HLvN3Q1mE9kbB+uKH6syF/S7nALgsLgq7eHYvIaE/A=
|
15
|
+
-----END RSA PRIVATE KEY-----
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require File.expand_path('../../lib/faye/websocket', __FILE__)
|
4
|
+
require File.expand_path('../../vendor/em-rspec/lib/em-rspec', __FILE__)
|
5
|
+
|
6
|
+
Thin::Logging.silent = true
|
7
|
+
|
8
|
+
module EncodingHelper
|
9
|
+
def encode(message)
|
10
|
+
message.respond_to?(:force_encoding) ?
|
11
|
+
message.force_encoding("UTF-8") :
|
12
|
+
message
|
13
|
+
end
|
14
|
+
|
15
|
+
def bytes(string)
|
16
|
+
string.bytes.to_a
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(bytes)
|
20
|
+
@parser.parse(bytes.pack('C*'))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class EchoServer
|
25
|
+
def call(env)
|
26
|
+
socket = Faye::WebSocket.new(env)
|
27
|
+
socket.onmessage = lambda do |event|
|
28
|
+
socket.send(event.data)
|
29
|
+
end
|
30
|
+
[-1, {}, []]
|
31
|
+
end
|
32
|
+
|
33
|
+
def listen(port, ssl = false)
|
34
|
+
Rack::Handler.get('thin').run(self, :Port => port) do |s|
|
35
|
+
if ssl
|
36
|
+
s.ssl = true
|
37
|
+
s.ssl_options = {
|
38
|
+
:private_key_file => File.expand_path('../server.key', __FILE__),
|
39
|
+
:cert_chain_file => File.expand_path('../server.crt', __FILE__)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
@server = s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def stop
|
47
|
+
@server.stop
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: faye-websocket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- James Coglan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: eventmachine
|
16
|
+
requirement: &2152439260 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.12.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152439260
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thin
|
27
|
+
requirement: &2152438100 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.2'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152438100
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &2152437380 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.5.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152437380
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rack
|
49
|
+
requirement: &2152436360 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152436360
|
58
|
+
description:
|
59
|
+
email: jcoglan@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files:
|
63
|
+
- README.rdoc
|
64
|
+
files:
|
65
|
+
- README.rdoc
|
66
|
+
- examples/autobahn_client.rb
|
67
|
+
- examples/client.rb
|
68
|
+
- examples/index.html
|
69
|
+
- examples/server.rb
|
70
|
+
- lib/faye/thin_extensions.rb
|
71
|
+
- lib/faye/websocket/api.rb
|
72
|
+
- lib/faye/websocket/client.rb
|
73
|
+
- lib/faye/websocket/draft75_parser.rb
|
74
|
+
- lib/faye/websocket/draft76_parser.rb
|
75
|
+
- lib/faye/websocket/protocol8_parser.rb
|
76
|
+
- lib/faye/websocket.rb
|
77
|
+
- spec/faye/websocket/client_spec.rb
|
78
|
+
- spec/faye/websocket/draft75_parser_spec.rb
|
79
|
+
- spec/faye/websocket/protocol8_parser_spec.rb
|
80
|
+
- spec/server.crt
|
81
|
+
- spec/server.key
|
82
|
+
- spec/spec_helper.rb
|
83
|
+
homepage: http://github.com/jcoglan/faye-websocket-ruby
|
84
|
+
licenses: []
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --main
|
88
|
+
- README.rdoc
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.10
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Robust general-purpose WebSocket server and client
|
109
|
+
test_files: []
|