jabber4r-revive 0.9.0 → 0.10.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.
- data/.gitignore +5 -4
- data/.rspec +3 -3
- data/.travis.yml +7 -7
- data/CHANGELOG +11 -1
- data/Gemfile +3 -3
- data/README.md +29 -29
- data/Rakefile +70 -70
- data/jabber4r-revive.gemspec +25 -25
- data/lib/jabber4r.rb +38 -33
- data/lib/jabber4r/bosh.rb +21 -0
- data/lib/jabber4r/bosh/authentication.rb +13 -0
- data/lib/jabber4r/bosh/authentication/non_sasl.rb +219 -0
- data/lib/jabber4r/bosh/authentication/sasl.rb +239 -0
- data/lib/jabber4r/bosh/session.rb +144 -0
- data/lib/jabber4r/connection.rb +259 -258
- data/lib/jabber4r/debugger.rb +60 -60
- data/lib/jabber4r/jid.rb +20 -19
- data/lib/jabber4r/protocol.rb +249 -257
- data/lib/jabber4r/protocol/authentication.rb +14 -0
- data/lib/jabber4r/protocol/authentication/non_sasl.rb +138 -0
- data/lib/jabber4r/protocol/authentication/sasl.rb +88 -0
- data/lib/jabber4r/protocol/iq.rb +259 -259
- data/lib/jabber4r/protocol/message.rb +245 -245
- data/lib/jabber4r/protocol/parsed_xml_element.rb +207 -207
- data/lib/jabber4r/protocol/presence.rb +160 -160
- data/lib/jabber4r/protocol/xml_element.rb +143 -143
- data/lib/jabber4r/rexml_1.8_patch.rb +15 -15
- data/lib/jabber4r/roster.rb +38 -38
- data/lib/jabber4r/session.rb +615 -615
- data/lib/jabber4r/version.rb +10 -3
- data/spec/lib/jabber4r/bosh/authentication/non_sasl_spec.rb +79 -0
- data/spec/lib/jabber4r/bosh/authentication/sasl_spec.rb +42 -0
- data/spec/lib/jabber4r/bosh/session_spec.rb +406 -0
- data/spec/lib/jabber4r/bosh_spec.rb +0 -0
- data/spec/lib/jabber4r/connection_spec.rb +174 -174
- data/spec/lib/jabber4r/debugger_spec.rb +35 -35
- data/spec/lib/jabber4r/jid_spec.rb +197 -197
- data/spec/lib/jabber4r/protocol/authentication/non_sasl_spec.rb +79 -0
- data/spec/lib/jabber4r/protocol/authentication/sasl_spec.rb +42 -0
- data/spec/spec_helper.rb +11 -11
- data/spec/support/mocks/tcp_socket_mock.rb +8 -8
- metadata +61 -45
- data/Gemfile.lock +0 -45
- data/lib/jabber4r/bosh_session.rb +0 -224
- data/spec/lib/jabber4r/bosh_session_spec.rb +0 -150
data/lib/jabber4r/version.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# License: see LICENSE
|
4
|
+
# Jabber4R - Jabber Instant Messaging Library for Ruby
|
5
|
+
# Copyright (C) 2002 Rich Kilmer <rich@infoether.com>
|
6
|
+
# Copyright (C) 2013 Sergey Fedorov <strech_ftf@mail.ru>
|
7
|
+
|
8
|
+
module Jabber
|
9
|
+
VERSION = "0.10.0"
|
10
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Jabber::Bosh::Authentication::NonSASL::Query do
|
5
|
+
let(:jid) { Jabber::JID.new("strech@localhost/my-resource") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
context "when create plain non-sasl authentication" do
|
9
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
10
|
+
|
11
|
+
it { expect(auth.stream_id).to be_nil }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when jid is a String" do
|
15
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password") }
|
16
|
+
|
17
|
+
it { expect { auth }.not_to raise_error TypeError }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when jid is not instance of Jabber::JID or String" do
|
21
|
+
let(:auth) { described_class.new(:hello, "my-password") }
|
22
|
+
|
23
|
+
it { expect { auth }.to raise_error TypeError }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when mechanism doesn't exists" do
|
27
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :unknown) }
|
28
|
+
|
29
|
+
it { expect { auth }.to raise_error ArgumentError }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when mechanism is digest and no stream_id is given" do
|
33
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :digest) }
|
34
|
+
|
35
|
+
it { expect { auth }.to raise_error KeyError }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#plain" do
|
40
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
41
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
42
|
+
let(:correct_xml) do
|
43
|
+
'<iq xmlns="jabber:client" type="set" id="auth2"><query xmlns="jabber:iq:auth">' +
|
44
|
+
'<username>strech</username><password>my-password</password>' +
|
45
|
+
'<resource>my-resource</resource></query></iq>'
|
46
|
+
end
|
47
|
+
|
48
|
+
before { Jabber.stub(:gen_random_id).and_return "auth2" }
|
49
|
+
|
50
|
+
it { expect(auth_xml).to eq correct_xml }
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#digest" do
|
54
|
+
let(:auth) { described_class.new(jid, "my-password", stream_id: 1, mechanism: :digest) }
|
55
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
56
|
+
let(:correct_xml) do
|
57
|
+
'<iq xmlns="jabber:client" type="set" id="auth2"><query xmlns="jabber:iq:auth">' +
|
58
|
+
'<username>strech</username><digest>0123456789</digest>' +
|
59
|
+
'<resource>my-resource</resource></query></iq>'
|
60
|
+
end
|
61
|
+
|
62
|
+
before { Jabber.stub(:gen_random_id).and_return "auth2" }
|
63
|
+
before { described_class.stub(:generate_digest).and_return "0123456789" }
|
64
|
+
|
65
|
+
it { expect(auth_xml).to eq correct_xml }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#plain?" do
|
69
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
70
|
+
|
71
|
+
it { expect(auth).to be_plain }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#digest?" do
|
75
|
+
let(:auth) { described_class.new(jid, "my-password", mechanism: :digest, stream_id: 1) }
|
76
|
+
|
77
|
+
it { expect(auth).to be_digest }
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Jabber::Bosh::Authentication::SASL::Query do
|
5
|
+
let(:jid) { Jabber::JID.new("strech@localhost/my-resource") }
|
6
|
+
|
7
|
+
describe "#initialize" do
|
8
|
+
context "when jid is a String" do
|
9
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password") }
|
10
|
+
|
11
|
+
it { expect { auth }.not_to raise_error TypeError }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when jid is not instance of Jabber::JID or String" do
|
15
|
+
let(:auth) { described_class.new(:hello, "my-password") }
|
16
|
+
|
17
|
+
it { expect { auth }.to raise_error TypeError }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when mechanism doesn't exists" do
|
21
|
+
let(:auth) { described_class.new("hello@localhost/my-res", "my-password", mechanism: :unknown) }
|
22
|
+
|
23
|
+
it { expect { auth }.to raise_error ArgumentError }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#plain" do
|
28
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
29
|
+
let(:auth_xml) { auth.dump.strip.gsub(/[\r\n]+|\s{2,}/, "") }
|
30
|
+
let(:correct_xml) { '<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">0123456789</auth>' }
|
31
|
+
|
32
|
+
before { described_class.stub(:generate_plain).and_return "0123456789" }
|
33
|
+
|
34
|
+
it { expect(auth_xml).to eq correct_xml }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#plain?" do
|
38
|
+
let(:auth) { described_class.new(jid, "my-password") }
|
39
|
+
|
40
|
+
it { expect(auth).to be_plain }
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Jabber::Bosh::Session do
|
5
|
+
before { described_class.any_instance.stub(:rand).and_return 1 }
|
6
|
+
|
7
|
+
describe "#bind" do
|
8
|
+
context "when server accept sasl authentication" do
|
9
|
+
let(:bosh_session) { described_class.bind("strech@localhost/resource", "password") }
|
10
|
+
|
11
|
+
let(:successful_login) { '<body xmlns="http://jabber.org/protocol/httpbind"><success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/></body>' }
|
12
|
+
let(:successful_open_stream) do
|
13
|
+
[
|
14
|
+
'<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams"' +
|
15
|
+
'charsets="UTF-8" from="localhost" hold="1" inactivity="20" polling="5" requests="2" sid="67d63e06-4159-43e2-9cb8-544de83eae58"' +
|
16
|
+
'ver="1.6" wait="60" xmpp:version="1.0"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism>' +
|
17
|
+
'</mechanisms></stream:features></body>'
|
18
|
+
].join " "
|
19
|
+
end
|
20
|
+
let(:successful_restart) do
|
21
|
+
[
|
22
|
+
'<body xmlns="http://jabber.org/protocol/httpbind" xmlns:stream="http://etherx.jabber.org/streams">' +
|
23
|
+
'<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></stream:features></body>'
|
24
|
+
].join " "
|
25
|
+
end
|
26
|
+
let(:successful_bind) do
|
27
|
+
[
|
28
|
+
'<body xmlns="http://jabber.org/protocol/httpbind"><iq id="Jabber4R_f7e7fc2a10013070" type="result">' +
|
29
|
+
'<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>strech@localhost/resource</jid></bind></iq></body>'
|
30
|
+
].join " "
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:is_open_stream?) { ->(data) { x = Ox.parse(data); "2" == x[:rid] } }
|
34
|
+
let(:is_login?) { ->(data) { x = Ox.parse(data); "3" == x[:rid] && !x.locate("auth").empty? } }
|
35
|
+
let(:is_restart?) { ->(data) { x = Ox.parse(data); "4" == x[:rid] && x["xmpp:restart"] = "true" } }
|
36
|
+
let(:is_bind?) { ->(data) { x = Ox.parse(data); "5" == x[:rid] && !x.locate("iq/bind").empty? } }
|
37
|
+
|
38
|
+
context "when session successfuly binded" do
|
39
|
+
before do
|
40
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
41
|
+
.with(body: is_open_stream?)
|
42
|
+
.to_return(body: successful_open_stream)
|
43
|
+
|
44
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
45
|
+
.with(body: is_login?)
|
46
|
+
.to_return(body: successful_login)
|
47
|
+
|
48
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
49
|
+
.with(body: is_restart?)
|
50
|
+
.to_return(body: successful_restart)
|
51
|
+
|
52
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
53
|
+
.with(body: is_bind?)
|
54
|
+
.to_return(body: successful_bind)
|
55
|
+
end
|
56
|
+
|
57
|
+
it { expect(bosh_session).to be_alive }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when couldn't open stream" do
|
61
|
+
context "when response body missed sid attribute" do
|
62
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams"/>' }
|
63
|
+
|
64
|
+
before do
|
65
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
66
|
+
.with(body: is_open_stream?)
|
67
|
+
.to_return(body: malformed_body)
|
68
|
+
|
69
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
70
|
+
.with(body: is_login?)
|
71
|
+
|
72
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
73
|
+
.with(body: is_restart?)
|
74
|
+
|
75
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
76
|
+
.with(body: is_bind?)
|
77
|
+
end
|
78
|
+
|
79
|
+
it { expect { bosh_session }.to raise_error Jabber::XMLMalformedError, "Couldn't find <body /> attribute [sid]" }
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when response was not 200 OK" do
|
83
|
+
before do
|
84
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
85
|
+
.with(body: is_open_stream?)
|
86
|
+
.to_return(body: "Foo", status: 401)
|
87
|
+
|
88
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
89
|
+
.with(body: is_login?)
|
90
|
+
|
91
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
92
|
+
.with(body: is_restart?)
|
93
|
+
|
94
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
95
|
+
.with(body: is_bind?)
|
96
|
+
end
|
97
|
+
|
98
|
+
it { expect { bosh_session }.to raise_error Net::HTTPBadResponse }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when couldn't login in opened stream" do
|
103
|
+
context "when response has no auth mechanisms" do
|
104
|
+
let(:malformed_body) do
|
105
|
+
[
|
106
|
+
'<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams"' +
|
107
|
+
'charsets="UTF-8" from="localhost" hold="1" inactivity="20" polling="5" requests="2" sid="67d63e06-4159-43e2-9cb8-544de83eae58"' +
|
108
|
+
'ver="1.6" wait="60" xmpp:version="1.0"/>'
|
109
|
+
].join " "
|
110
|
+
end
|
111
|
+
|
112
|
+
before do
|
113
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
114
|
+
.with(body: is_open_stream?)
|
115
|
+
.to_return(body: malformed_body)
|
116
|
+
|
117
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
118
|
+
.with(body: is_login?)
|
119
|
+
|
120
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
121
|
+
.with(body: is_restart?)
|
122
|
+
|
123
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
124
|
+
.with(body: is_bind?)
|
125
|
+
end
|
126
|
+
|
127
|
+
it { expect { bosh_session }.to raise_error TypeError, "Server SASL mechanisms not include PLAIN mechanism" }
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when response has type not equal 'success'" do
|
131
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind"><error xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/></body>' }
|
132
|
+
|
133
|
+
before do
|
134
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
135
|
+
.with(body: is_open_stream?)
|
136
|
+
.to_return(body: successful_open_stream)
|
137
|
+
|
138
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
139
|
+
.with(body: is_login?)
|
140
|
+
.to_return(body: malformed_body)
|
141
|
+
|
142
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
143
|
+
.with(body: is_restart?)
|
144
|
+
|
145
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
146
|
+
.with(body: is_bind?)
|
147
|
+
end
|
148
|
+
|
149
|
+
it { expect { bosh_session }.to raise_error Jabber::AuthenticationError, "Failed to login" }
|
150
|
+
end
|
151
|
+
|
152
|
+
context "when response was not 200 OK" do
|
153
|
+
before do
|
154
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
155
|
+
.with(body: is_open_stream?)
|
156
|
+
.to_return(body: successful_open_stream)
|
157
|
+
|
158
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
159
|
+
.with(body: is_login?)
|
160
|
+
.to_return(body: "Foo", status: 401)
|
161
|
+
|
162
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
163
|
+
.with(body: is_restart?)
|
164
|
+
|
165
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
166
|
+
.with(body: is_bind?)
|
167
|
+
end
|
168
|
+
|
169
|
+
it { expect { bosh_session }.to raise_error Net::HTTPBadResponse }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context "when cann't restart opened stream" do
|
174
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind" xmlns:stream="http://etherx.jabber.org/streams"><error xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/></body>' }
|
175
|
+
|
176
|
+
before do
|
177
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
178
|
+
.with(body: is_open_stream?)
|
179
|
+
.to_return(body: successful_open_stream)
|
180
|
+
|
181
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
182
|
+
.with(body: is_login?)
|
183
|
+
.to_return(body: successful_login)
|
184
|
+
|
185
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
186
|
+
.with(body: is_restart?)
|
187
|
+
.to_return(body: malformed_body)
|
188
|
+
|
189
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
190
|
+
.with(body: is_bind?)
|
191
|
+
end
|
192
|
+
|
193
|
+
it { expect { bosh_session }.to raise_error Jabber::AuthenticationError, "Failed to login" }
|
194
|
+
end
|
195
|
+
|
196
|
+
context "when cann't bind resource on opened stream" do
|
197
|
+
context "when response is a malformed xml without IQ tag" do
|
198
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind"></body>' }
|
199
|
+
|
200
|
+
before do
|
201
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
202
|
+
.with(body: is_open_stream?)
|
203
|
+
.to_return(body: successful_open_stream)
|
204
|
+
|
205
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
206
|
+
.with(body: is_login?)
|
207
|
+
.to_return(body: successful_login)
|
208
|
+
|
209
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
210
|
+
.with(body: is_restart?)
|
211
|
+
.to_return(body: successful_restart)
|
212
|
+
|
213
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
214
|
+
.with(body: is_bind?)
|
215
|
+
.to_return(body: malformed_body)
|
216
|
+
end
|
217
|
+
|
218
|
+
it { expect { bosh_session }.to raise_error Jabber::XMLMalformedError, "Couldn't find xml tag <iq/>" }
|
219
|
+
end
|
220
|
+
|
221
|
+
context "when response has type not equal 'result'" do
|
222
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind"><iq id="Jabber4R_f7e7fc2a10013070" type="error"/></body>' }
|
223
|
+
|
224
|
+
before do
|
225
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
226
|
+
.with(body: is_open_stream?)
|
227
|
+
.to_return(body: successful_open_stream)
|
228
|
+
|
229
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
230
|
+
.with(body: is_login?)
|
231
|
+
.to_return(body: successful_login)
|
232
|
+
|
233
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
234
|
+
.with(body: is_restart?)
|
235
|
+
.to_return(body: successful_restart)
|
236
|
+
|
237
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
238
|
+
.with(body: is_bind?)
|
239
|
+
.to_return(body: malformed_body)
|
240
|
+
end
|
241
|
+
|
242
|
+
it { expect { bosh_session }.to raise_error Jabber::AuthenticationError, "Failed to login" }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# REFACTOR ALL
|
248
|
+
|
249
|
+
context "when server accept non-sasl authentication" do
|
250
|
+
let(:bosh_session) { described_class.bind("strech@localhost/resource", "password", use_sasl: false) }
|
251
|
+
|
252
|
+
let(:successful_login) { '<body xmlns="http://jabber.org/protocol/httpbind"><iq type="result" xmlns="jabber:client" id="2034"/></body>' }
|
253
|
+
let(:successful_open_stream) do
|
254
|
+
[
|
255
|
+
'<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams"',
|
256
|
+
'authid="3780309894" sid="ce21410" from="localhost" xmpp:version="1.0"',
|
257
|
+
'wait="60" requests="2" inactivity="30" maxpause="120" polling="2" ver="1.8" secure="true" />'
|
258
|
+
].join " "
|
259
|
+
end
|
260
|
+
let(:is_open_stream?) { ->(data) { x = Ox.parse(data); ["2", "localhost"] == [x[:rid], x[:to]] } }
|
261
|
+
let(:is_login?) { ->(data) { x = Ox.parse(data); ["3", "ce21410"] == [x[:rid], x[:sid]] } }
|
262
|
+
|
263
|
+
context "when session successfuly binded" do
|
264
|
+
before do
|
265
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
266
|
+
.with(body: is_open_stream?)
|
267
|
+
.to_return(body: successful_open_stream)
|
268
|
+
|
269
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
270
|
+
.with(body: is_login?)
|
271
|
+
.to_return(body: successful_login)
|
272
|
+
end
|
273
|
+
|
274
|
+
it { expect(bosh_session).to be_alive }
|
275
|
+
end
|
276
|
+
|
277
|
+
context "when couldn't open stream" do
|
278
|
+
context "when response body missed authid attribute" do
|
279
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind" sid="ce21410" />' }
|
280
|
+
|
281
|
+
before do
|
282
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
283
|
+
.with(body: is_open_stream?)
|
284
|
+
.to_return(body: malformed_body)
|
285
|
+
|
286
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
287
|
+
.with(body: is_login?)
|
288
|
+
end
|
289
|
+
|
290
|
+
it { expect { bosh_session }.to raise_error Jabber::XMLMalformedError, "Couldn't find <body /> attribute [authid]" }
|
291
|
+
end
|
292
|
+
|
293
|
+
context "when response body missed sid attribute" do
|
294
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind" authid="3780309894" />' }
|
295
|
+
|
296
|
+
before do
|
297
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
298
|
+
.with(body: is_open_stream?)
|
299
|
+
.to_return(body: malformed_body)
|
300
|
+
|
301
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
302
|
+
.with(body: is_login?)
|
303
|
+
end
|
304
|
+
|
305
|
+
it { expect { bosh_session }.to raise_error Jabber::XMLMalformedError, "Couldn't find <body /> attribute [sid]" }
|
306
|
+
end
|
307
|
+
|
308
|
+
context "when response was not 200 OK" do
|
309
|
+
before do
|
310
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
311
|
+
.with(body: is_open_stream?)
|
312
|
+
.to_return(body: "Foo", status: 401)
|
313
|
+
|
314
|
+
WebMock.should_not have_requested(:post, "http://localhost:5280/http-bind")
|
315
|
+
.with(body: is_login?)
|
316
|
+
end
|
317
|
+
|
318
|
+
it { expect { bosh_session }.to raise_error Net::HTTPBadResponse }
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context "when couldn't login in opened stream" do
|
323
|
+
context "when response is a malformed xml without IQ tag" do
|
324
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind"></body>' }
|
325
|
+
|
326
|
+
before do
|
327
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
328
|
+
.with(body: is_open_stream?)
|
329
|
+
.to_return(body: successful_open_stream)
|
330
|
+
|
331
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
332
|
+
.with(body: is_login?)
|
333
|
+
.to_return(body: malformed_body)
|
334
|
+
end
|
335
|
+
|
336
|
+
it { expect { bosh_session }.to raise_error Jabber::XMLMalformedError, "Couldn't find xml tag <iq/>" }
|
337
|
+
end
|
338
|
+
|
339
|
+
context "when response has type not equal 'result'" do
|
340
|
+
let(:malformed_body) { '<body xmlns="http://jabber.org/protocol/httpbind"><iq type="error" xmlns="jabber:client" id="2034"/></body>' }
|
341
|
+
|
342
|
+
before do
|
343
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
344
|
+
.with(body: is_open_stream?)
|
345
|
+
.to_return(body: successful_open_stream)
|
346
|
+
|
347
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
348
|
+
.with(body: is_login?)
|
349
|
+
.to_return(body: malformed_body)
|
350
|
+
end
|
351
|
+
|
352
|
+
it { expect { bosh_session }.to raise_error Jabber::AuthenticationError, "Failed to login" }
|
353
|
+
end
|
354
|
+
|
355
|
+
context "when response was not 200 OK" do
|
356
|
+
before do
|
357
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
358
|
+
.with(body: is_open_stream?)
|
359
|
+
.to_return(body: successful_open_stream)
|
360
|
+
|
361
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
362
|
+
.with(body: is_login?)
|
363
|
+
.to_return(body: "Foo", status: 401)
|
364
|
+
end
|
365
|
+
|
366
|
+
it { expect { bosh_session }.to raise_error Net::HTTPBadResponse }
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "#to_json" do
|
373
|
+
let(:bosh_session) { described_class.bind("strech@localhost/resource", "password", use_sasl: false) }
|
374
|
+
let(:successful_login) { '<body xmlns="http://jabber.org/protocol/httpbind"><iq type="result" xmlns="jabber:client" id="2034"/></body>' }
|
375
|
+
let(:successful_open_stream) do
|
376
|
+
[
|
377
|
+
'<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams"',
|
378
|
+
'authid="3780309894" sid="ce21410" from="localhost" xmpp:version="1.0"',
|
379
|
+
'wait="60" requests="2" inactivity="30" maxpause="120" polling="2" ver="1.8" secure="true" />'
|
380
|
+
].join " "
|
381
|
+
end
|
382
|
+
let(:is_open_stream?) { ->(data) { x = Ox.parse(data); ["2", "localhost"] == [x[:rid], x[:to]] } }
|
383
|
+
let(:is_login?) { ->(data) { x = Ox.parse(data); ["3", "ce21410"] == [x[:rid], x[:sid]] } }
|
384
|
+
|
385
|
+
let(:json) { JSON.parse(bosh_session.to_json) }
|
386
|
+
|
387
|
+
before do
|
388
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
389
|
+
.with(body: is_open_stream?)
|
390
|
+
.to_return(body: successful_open_stream)
|
391
|
+
|
392
|
+
|
393
|
+
stub_request(:post, "http://localhost:5280/http-bind")
|
394
|
+
.with(body: is_login?)
|
395
|
+
.to_return(body: successful_login)
|
396
|
+
end
|
397
|
+
|
398
|
+
it { expect(json).to have_key "jid" }
|
399
|
+
it { expect(json).to have_key "rid" }
|
400
|
+
it { expect(json).to have_key "sid" }
|
401
|
+
|
402
|
+
it { expect(json["jid"]).to eq "strech@localhost/resource"}
|
403
|
+
it { expect(json["rid"]).to eq 3}
|
404
|
+
it { expect(json["sid"]).to eq "ce21410"}
|
405
|
+
end
|
406
|
+
end
|