vines 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +5 -9
- data/Rakefile +11 -9
- data/conf/config.rb +30 -4
- data/lib/vines/cluster/connection.rb +26 -0
- data/lib/vines/cluster/publisher.rb +55 -0
- data/lib/vines/cluster/pubsub.rb +92 -0
- data/lib/vines/cluster/sessions.rb +125 -0
- data/lib/vines/cluster/subscriber.rb +108 -0
- data/lib/vines/cluster.rb +246 -0
- data/lib/vines/command/init.rb +21 -24
- data/lib/vines/config/host.rb +48 -8
- data/lib/vines/config/port.rb +5 -0
- data/lib/vines/config/pubsub.rb +108 -0
- data/lib/vines/config.rb +74 -20
- data/lib/vines/jid.rb +14 -0
- data/lib/vines/router.rb +69 -55
- data/lib/vines/stanza/iq/disco_info.rb +22 -9
- data/lib/vines/stanza/iq/disco_items.rb +6 -3
- data/lib/vines/stanza/iq/ping.rb +1 -1
- data/lib/vines/stanza/iq/private_storage.rb +4 -8
- data/lib/vines/stanza/iq/roster.rb +6 -14
- data/lib/vines/stanza/iq/session.rb +2 -7
- data/lib/vines/stanza/iq/vcard.rb +4 -6
- data/lib/vines/stanza/iq/version.rb +1 -1
- data/lib/vines/stanza/iq.rb +8 -10
- data/lib/vines/stanza/presence/subscribe.rb +3 -11
- data/lib/vines/stanza/presence/subscribed.rb +16 -29
- data/lib/vines/stanza/presence/unsubscribe.rb +3 -15
- data/lib/vines/stanza/presence/unsubscribed.rb +3 -16
- data/lib/vines/stanza/presence.rb +30 -0
- data/lib/vines/stanza/pubsub/create.rb +39 -0
- data/lib/vines/stanza/pubsub/delete.rb +41 -0
- data/lib/vines/stanza/pubsub/publish.rb +66 -0
- data/lib/vines/stanza/pubsub/subscribe.rb +44 -0
- data/lib/vines/stanza/pubsub/unsubscribe.rb +30 -0
- data/lib/vines/stanza/pubsub.rb +22 -0
- data/lib/vines/stanza.rb +72 -22
- data/lib/vines/storage/couchdb.rb +46 -65
- data/lib/vines/storage/local.rb +20 -14
- data/lib/vines/storage/mongodb.rb +132 -0
- data/lib/vines/storage/null.rb +39 -0
- data/lib/vines/storage/redis.rb +61 -68
- data/lib/vines/storage/sql.rb +73 -69
- data/lib/vines/storage.rb +1 -1
- data/lib/vines/stream/client/bind.rb +2 -2
- data/lib/vines/stream/client/session.rb +71 -16
- data/lib/vines/stream/component/handshake.rb +1 -0
- data/lib/vines/stream/component/ready.rb +2 -2
- data/lib/vines/stream/http/session.rb +2 -0
- data/lib/vines/stream/http.rb +0 -6
- data/lib/vines/stream/server/final_restart.rb +1 -0
- data/lib/vines/stream/server/outbound/final_features.rb +1 -0
- data/lib/vines/stream/server/ready.rb +6 -2
- data/lib/vines/stream/server.rb +4 -3
- data/lib/vines/stream.rb +10 -6
- data/lib/vines/version.rb +1 -1
- data/lib/vines.rb +48 -22
- data/test/cluster/publisher_test.rb +45 -0
- data/test/cluster/sessions_test.rb +54 -0
- data/test/cluster/subscriber_test.rb +94 -0
- data/test/config/host_test.rb +100 -21
- data/test/config/pubsub_test.rb +181 -0
- data/test/config_test.rb +225 -43
- data/test/jid_test.rb +7 -0
- data/test/router_test.rb +181 -9
- data/test/stanza/iq/disco_info_test.rb +8 -6
- data/test/stanza/iq/disco_items_test.rb +3 -3
- data/test/stanza/iq/private_storage_test.rb +8 -19
- data/test/stanza/iq/roster_test.rb +1 -1
- data/test/stanza/iq/session_test.rb +3 -6
- data/test/stanza/iq/vcard_test.rb +6 -2
- data/test/stanza/iq/version_test.rb +3 -2
- data/test/stanza/iq_test.rb +5 -5
- data/test/stanza/message_test.rb +3 -2
- data/test/stanza/presence/probe_test.rb +2 -1
- data/test/stanza/pubsub/create_test.rb +138 -0
- data/test/stanza/pubsub/delete_test.rb +142 -0
- data/test/stanza/pubsub/publish_test.rb +373 -0
- data/test/stanza/pubsub/subscribe_test.rb +186 -0
- data/test/stanza/pubsub/unsubscribe_test.rb +179 -0
- data/test/stanza_test.rb +2 -1
- data/test/storage/local_test.rb +26 -25
- data/test/storage/mock_mongo.rb +40 -0
- data/test/storage/mock_redis.rb +98 -0
- data/test/storage/mongodb_test.rb +81 -0
- data/test/storage/null_test.rb +30 -0
- data/test/storage/redis_test.rb +3 -36
- data/test/stream/component/handshake_test.rb +4 -0
- data/test/stream/component/ready_test.rb +2 -1
- data/test/stream/server/ready_test.rb +7 -1
- data/web/404.html +5 -3
- data/web/chat/coffeescripts/chat.coffee +9 -5
- data/web/chat/javascripts/app.js +1 -1
- data/web/chat/javascripts/chat.js +14 -8
- data/web/chat/stylesheets/chat.css +4 -1
- data/web/lib/coffeescripts/button.coffee +9 -5
- data/web/lib/coffeescripts/filter.coffee +1 -1
- data/web/lib/coffeescripts/login.coffee +14 -1
- data/web/lib/coffeescripts/session.coffee +8 -11
- data/web/lib/images/dark-gray.png +0 -0
- data/web/lib/images/light-gray.png +0 -0
- data/web/lib/images/logo-large.png +0 -0
- data/web/lib/images/logo-small.png +0 -0
- data/web/lib/images/white.png +0 -0
- data/web/lib/javascripts/base.js +9 -8
- data/web/lib/javascripts/button.js +20 -12
- data/web/lib/javascripts/filter.js +1 -1
- data/web/lib/javascripts/icons.js +7 -1
- data/web/lib/javascripts/jquery.js +4 -4
- data/web/lib/javascripts/login.js +16 -2
- data/web/lib/javascripts/raphael.js +5 -7
- data/web/lib/javascripts/session.js +10 -14
- data/web/lib/stylesheets/base.css +7 -11
- data/web/lib/stylesheets/login.css +31 -27
- metadata +100 -34
data/lib/vines/storage/sql.rb
CHANGED
@@ -13,8 +13,24 @@ module Vines
|
|
13
13
|
end
|
14
14
|
class Group < ActiveRecord::Base; end
|
15
15
|
class User < ActiveRecord::Base
|
16
|
-
has_many :contacts
|
17
|
-
has_many :fragments
|
16
|
+
has_many :contacts, :dependent => :destroy
|
17
|
+
has_many :fragments, :dependent => :delete_all
|
18
|
+
end
|
19
|
+
|
20
|
+
# Wrap the method with ActiveRecord connection pool logic, so we properly
|
21
|
+
# return connections to the pool when we're finished with them. This also
|
22
|
+
# defers the original method by pushing it onto the EM thread pool because
|
23
|
+
# ActiveRecord uses blocking IO.
|
24
|
+
def self.with_connection(method, args={})
|
25
|
+
deferrable = args.key?(:defer) ? args[:defer] : true
|
26
|
+
old = "_with_connection_#{method}"
|
27
|
+
alias_method old, method
|
28
|
+
define_method method do |*args|
|
29
|
+
ActiveRecord::Base.connection_pool.with_connection do
|
30
|
+
method(old).call(*args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
defer(method) if deferrable
|
18
34
|
end
|
19
35
|
|
20
36
|
%w[adapter host port database username password pool].each do |name|
|
@@ -38,30 +54,26 @@ module Vines
|
|
38
54
|
end
|
39
55
|
|
40
56
|
def find_user(jid)
|
41
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
42
|
-
|
43
57
|
jid = JID.new(jid).bare.to_s
|
44
58
|
return if jid.empty?
|
45
59
|
xuser = user_by_jid(jid)
|
46
|
-
return Vines::User.new(:
|
60
|
+
return Vines::User.new(jid: jid).tap do |user|
|
47
61
|
user.name, user.password = xuser.name, xuser.password
|
48
62
|
xuser.contacts.each do |contact|
|
49
63
|
groups = contact.groups.map {|group| group.name }
|
50
64
|
user.roster << Vines::Contact.new(
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
65
|
+
jid: contact.jid,
|
66
|
+
name: contact.name,
|
67
|
+
subscription: contact.subscription,
|
68
|
+
ask: contact.ask,
|
69
|
+
groups: groups)
|
56
70
|
end
|
57
71
|
end if xuser
|
58
72
|
end
|
59
|
-
|
73
|
+
with_connection :find_user
|
60
74
|
|
61
75
|
def save_user(user)
|
62
|
-
|
63
|
-
|
64
|
-
xuser = user_by_jid(user.jid) || Sql::User.new(:jid => user.jid.bare.to_s)
|
76
|
+
xuser = user_by_jid(user.jid) || Sql::User.new(jid: user.jid.bare.to_s)
|
65
77
|
xuser.name = user.name
|
66
78
|
xuser.password = user.password
|
67
79
|
|
@@ -74,10 +86,10 @@ module Vines
|
|
74
86
|
xuser.contacts.each do |contact|
|
75
87
|
fresh = user.contact(contact.jid)
|
76
88
|
contact.update_attributes(
|
77
|
-
:
|
78
|
-
:
|
79
|
-
:
|
80
|
-
:
|
89
|
+
name: fresh.name,
|
90
|
+
ask: fresh.ask,
|
91
|
+
subscription: fresh.subscription,
|
92
|
+
groups: groups(fresh))
|
81
93
|
end
|
82
94
|
|
83
95
|
# add new contacts to roster
|
@@ -85,112 +97,104 @@ module Vines
|
|
85
97
|
user.roster.select {|contact| !jids.include?(contact.jid.bare.to_s) }
|
86
98
|
.each do |contact|
|
87
99
|
xuser.contacts.build(
|
88
|
-
:
|
89
|
-
:
|
90
|
-
:
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
100
|
+
user: xuser,
|
101
|
+
jid: contact.jid.bare.to_s,
|
102
|
+
name: contact.name,
|
103
|
+
ask: contact.ask,
|
104
|
+
subscription: contact.subscription,
|
105
|
+
groups: groups(contact))
|
94
106
|
end
|
95
107
|
xuser.save
|
96
108
|
end
|
97
|
-
|
109
|
+
with_connection :save_user
|
98
110
|
|
99
111
|
def find_vcard(jid)
|
100
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
101
|
-
|
102
112
|
jid = JID.new(jid).bare.to_s
|
103
113
|
return if jid.empty?
|
104
114
|
if xuser = user_by_jid(jid)
|
105
115
|
Nokogiri::XML(xuser.vcard).root rescue nil
|
106
116
|
end
|
107
117
|
end
|
108
|
-
|
118
|
+
with_connection :find_vcard
|
109
119
|
|
110
120
|
def save_vcard(jid, card)
|
111
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
112
|
-
|
113
121
|
xuser = user_by_jid(jid)
|
114
122
|
if xuser
|
115
123
|
xuser.vcard = card.to_xml
|
116
124
|
xuser.save
|
117
125
|
end
|
118
126
|
end
|
119
|
-
|
127
|
+
with_connection :save_vcard
|
120
128
|
|
121
129
|
def find_fragment(jid, node)
|
122
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
123
|
-
|
124
130
|
jid = JID.new(jid).bare.to_s
|
125
131
|
return if jid.empty?
|
126
132
|
if fragment = fragment_by_jid(jid, node)
|
127
133
|
Nokogiri::XML(fragment.xml).root rescue nil
|
128
134
|
end
|
129
135
|
end
|
130
|
-
|
136
|
+
with_connection :find_fragment
|
131
137
|
|
132
138
|
def save_fragment(jid, node)
|
133
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
134
|
-
|
135
139
|
jid = JID.new(jid).bare.to_s
|
136
140
|
fragment = fragment_by_jid(jid, node) ||
|
137
141
|
Sql::Fragment.new(
|
138
|
-
:
|
139
|
-
:
|
140
|
-
:
|
142
|
+
user: user_by_jid(jid),
|
143
|
+
root: node.name,
|
144
|
+
namespace: node.namespace.href)
|
141
145
|
fragment.xml = node.to_xml
|
142
146
|
fragment.save
|
143
147
|
end
|
144
|
-
|
148
|
+
with_connection :save_fragment
|
145
149
|
|
146
150
|
# Create the tables and indexes used by this storage engine.
|
147
151
|
def create_schema(args={})
|
148
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
149
|
-
|
150
152
|
args[:force] ||= false
|
151
153
|
|
152
154
|
ActiveRecord::Schema.define do
|
153
|
-
create_table :users, :
|
154
|
-
t.string :jid, :
|
155
|
-
t.string :name, :
|
156
|
-
t.string :password, :
|
157
|
-
t.text :vcard, :
|
155
|
+
create_table :users, force: args[:force] do |t|
|
156
|
+
t.string :jid, limit: 512, null: false
|
157
|
+
t.string :name, limit: 256, null: true
|
158
|
+
t.string :password, limit: 256, null: true
|
159
|
+
t.text :vcard, null: true
|
158
160
|
end
|
159
|
-
add_index :users, :jid, :
|
160
|
-
|
161
|
-
create_table :contacts, :
|
162
|
-
t.integer :user_id, :
|
163
|
-
t.string :jid, :
|
164
|
-
t.string :name, :
|
165
|
-
t.string :ask, :
|
166
|
-
t.string :subscription, :
|
161
|
+
add_index :users, :jid, unique: true
|
162
|
+
|
163
|
+
create_table :contacts, force: args[:force] do |t|
|
164
|
+
t.integer :user_id, null: false
|
165
|
+
t.string :jid, limit: 512, null: false
|
166
|
+
t.string :name, limit: 256, null: true
|
167
|
+
t.string :ask, limit: 128, null: true
|
168
|
+
t.string :subscription, limit: 128, null: false
|
167
169
|
end
|
168
|
-
add_index :contacts, [:user_id, :jid], :
|
170
|
+
add_index :contacts, [:user_id, :jid], unique: true
|
169
171
|
|
170
|
-
create_table :groups, :
|
171
|
-
t.string :name, :
|
172
|
+
create_table :groups, force: args[:force] do |t|
|
173
|
+
t.string :name, limit: 256, null: false
|
172
174
|
end
|
173
|
-
add_index :groups, :name, :
|
175
|
+
add_index :groups, :name, unique: true
|
174
176
|
|
175
|
-
create_table :contacts_groups, :
|
176
|
-
t.integer :contact_id, :
|
177
|
-
t.integer :group_id, :
|
177
|
+
create_table :contacts_groups, id: false, force: args[:force] do |t|
|
178
|
+
t.integer :contact_id, null: false
|
179
|
+
t.integer :group_id, null: false
|
178
180
|
end
|
179
|
-
add_index :contacts_groups, [:contact_id, :group_id], :
|
181
|
+
add_index :contacts_groups, [:contact_id, :group_id], unique: true
|
180
182
|
|
181
|
-
create_table :fragments, :
|
182
|
-
t.integer :user_id, :
|
183
|
-
t.string :root, :
|
184
|
-
t.string :namespace, :
|
185
|
-
t.text :xml, :
|
183
|
+
create_table :fragments, force: args[:force] do |t|
|
184
|
+
t.integer :user_id, null: false
|
185
|
+
t.string :root, limit: 256, null: false
|
186
|
+
t.string :namespace, limit: 256, null: false
|
187
|
+
t.text :xml, null: false
|
186
188
|
end
|
187
|
-
add_index :fragments, [:user_id, :root, :namespace], :
|
189
|
+
add_index :fragments, [:user_id, :root, :namespace], unique: true
|
188
190
|
end
|
189
191
|
end
|
192
|
+
with_connection :create_schema, defer: false
|
190
193
|
|
191
194
|
private
|
192
195
|
|
193
196
|
def establish_connection
|
197
|
+
ActiveRecord::Base.logger = Logger.new('/dev/null')
|
194
198
|
ActiveRecord::Base.establish_connection(@config)
|
195
199
|
# has_and_belongs_to_many requires a connection so configure the
|
196
200
|
# associations here rather than in the class definitions above.
|
data/lib/vines/storage.rb
CHANGED
@@ -22,7 +22,7 @@ module Vines
|
|
22
22
|
|
23
23
|
# Wrap a blocking IO method in a new method that pushes the original method
|
24
24
|
# onto EventMachine's thread pool using EM#defer. Storage classes implemented
|
25
|
-
# with blocking IO don't need to worry about threading or blocking the
|
25
|
+
# with blocking IO don't need to worry about threading or blocking the
|
26
26
|
# EventMachine reactor thread if they wrap their methods with this one.
|
27
27
|
#
|
28
28
|
# For example:
|
@@ -17,7 +17,8 @@ module Vines
|
|
17
17
|
raise StreamErrors::NotAuthorized unless bind?(node)
|
18
18
|
raise StreamErrors::PolicyViolation.new('max bind attempts reached') if @attempts > MAX_ATTEMPTS
|
19
19
|
raise StanzaErrors::ResourceConstraint.new(node, 'wait') if resource_limit_reached?
|
20
|
-
|
20
|
+
|
21
|
+
stream.bind!(resource(node))
|
21
22
|
doc = Document.new
|
22
23
|
result = doc.create_element('iq', 'id' => node['id'], 'type' => 'result') do |el|
|
23
24
|
el << doc.create_element('bind') do |bind|
|
@@ -25,7 +26,6 @@ module Vines
|
|
25
26
|
bind << doc.create_element('jid', stream.user.jid.to_s)
|
26
27
|
end
|
27
28
|
end
|
28
|
-
|
29
29
|
stream.write(result)
|
30
30
|
send_empty_features
|
31
31
|
advance
|
@@ -10,10 +10,11 @@ module Vines
|
|
10
10
|
class Session
|
11
11
|
include Comparable
|
12
12
|
|
13
|
-
attr_accessor :domain, :
|
14
|
-
attr_reader :id, :state
|
13
|
+
attr_accessor :domain, :user
|
14
|
+
attr_reader :id, :last_broadcast_presence, :state
|
15
15
|
|
16
16
|
def initialize(stream)
|
17
|
+
@stream = stream
|
17
18
|
@id = Kit.uuid
|
18
19
|
@config = stream.config
|
19
20
|
@state = Client::Start.new(stream)
|
@@ -45,8 +46,12 @@ module Vines
|
|
45
46
|
!@user.nil?
|
46
47
|
end
|
47
48
|
|
49
|
+
# Notify the session that the client has sent an initial presence
|
50
|
+
# broadcast and is now considered to be an "available" resource.
|
51
|
+
# Available resources are sent presence subscription stanzas.
|
48
52
|
def available!
|
49
53
|
@available = true
|
54
|
+
save_to_cluster
|
50
55
|
end
|
51
56
|
|
52
57
|
# An available resource has sent initial presence and can
|
@@ -55,6 +60,15 @@ module Vines
|
|
55
60
|
@available && connected?
|
56
61
|
end
|
57
62
|
|
63
|
+
# Complete resource binding with the given resource name, provided by the
|
64
|
+
# client or generated by the server. Once resource binding is completed,
|
65
|
+
# the stream is considered to be "connected" and ready for traffic.
|
66
|
+
def bind!(resource)
|
67
|
+
@user.jid.resource = resource
|
68
|
+
router << self
|
69
|
+
save_to_cluster
|
70
|
+
end
|
71
|
+
|
58
72
|
# A connected resource has authenticated and bound a resource
|
59
73
|
# identifier.
|
60
74
|
def connected?
|
@@ -67,22 +81,38 @@ module Vines
|
|
67
81
|
@requested_roster && connected?
|
68
82
|
end
|
69
83
|
|
84
|
+
def last_broadcast_presence=(node)
|
85
|
+
@last_broadcast_presence = node
|
86
|
+
save_to_cluster
|
87
|
+
end
|
88
|
+
|
70
89
|
def ready?
|
71
90
|
@state.class == Client::Ready
|
72
91
|
end
|
73
92
|
|
93
|
+
# Notify the session that the client has requested its roster and is now
|
94
|
+
# considered to be an "interested" resource. Interested resources are sent
|
95
|
+
# roster pushes when changes are made to their contacts.
|
74
96
|
def requested_roster!
|
75
97
|
@requested_roster = true
|
98
|
+
save_to_cluster
|
76
99
|
end
|
77
100
|
|
78
101
|
def stream_type
|
79
102
|
:client
|
80
103
|
end
|
81
104
|
|
82
|
-
|
105
|
+
def write(data)
|
106
|
+
@stream.write(data)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Called by the stream when it's disconnected from the client. The stream
|
83
110
|
# passes itself to this method in case multiple streams are accessing this
|
84
|
-
# session.
|
111
|
+
# session (e.g. BOSH/HTTP).
|
85
112
|
def unbind!(stream)
|
113
|
+
router.delete(self)
|
114
|
+
delete_from_cluster
|
115
|
+
unsubscribe_pubsub
|
86
116
|
@unbound = true
|
87
117
|
@available = false
|
88
118
|
broadcast_unavailable
|
@@ -123,20 +153,22 @@ module Vines
|
|
123
153
|
|
124
154
|
def broadcast_unavailable
|
125
155
|
return unless authenticated?
|
126
|
-
|
156
|
+
Fiber.new do
|
157
|
+
broadcast(unavailable, available_subscribers)
|
158
|
+
broadcast(unavailable, router.available_resources(@user.jid, @user.jid))
|
159
|
+
remote_subscribers.each do |contact|
|
160
|
+
node = unavailable
|
161
|
+
node['to'] = contact.jid.bare.to_s
|
162
|
+
router.route(node) rescue nil # ignore RemoteServerNotFound
|
163
|
+
end
|
164
|
+
end.resume
|
165
|
+
end
|
166
|
+
|
167
|
+
def unavailable
|
127
168
|
doc = Nokogiri::XML::Document.new
|
128
|
-
|
169
|
+
doc.create_element('presence',
|
129
170
|
'from' => @user.jid.to_s,
|
130
171
|
'type' => 'unavailable')
|
131
|
-
|
132
|
-
broadcast(el, available_subscribers)
|
133
|
-
broadcast(el, router.available_resources(@user.jid, @user.jid))
|
134
|
-
|
135
|
-
remote_subscribers.each do |contact|
|
136
|
-
node = el.clone
|
137
|
-
node['to'] = contact.jid.bare.to_s
|
138
|
-
router.route(node) rescue nil # ignore RemoteServerNotFound
|
139
|
-
end
|
140
172
|
end
|
141
173
|
|
142
174
|
def broadcast(stanza, recipients)
|
@@ -147,7 +179,30 @@ module Vines
|
|
147
179
|
end
|
148
180
|
|
149
181
|
def router
|
150
|
-
|
182
|
+
@config.router
|
183
|
+
end
|
184
|
+
|
185
|
+
def save_to_cluster
|
186
|
+
if @config.cluster?
|
187
|
+
@config.cluster.save_session(@user.jid, to_hash)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def delete_from_cluster
|
192
|
+
if connected? && @config.cluster?
|
193
|
+
@config.cluster.delete_session(@user.jid)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def unsubscribe_pubsub
|
198
|
+
if connected?
|
199
|
+
@config.vhosts[@user.jid.domain].unsubscribe_pubsub(@user.jid)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def to_hash
|
204
|
+
presence = @last_broadcast_presence ? @last_broadcast_presence.to_s : nil
|
205
|
+
{available: @available, interested: @requested_roster, presence: presence.to_s}
|
151
206
|
end
|
152
207
|
end
|
153
208
|
end
|
@@ -10,8 +10,8 @@ module Vines
|
|
10
10
|
to, from = stanza.validate_to, stanza.validate_from
|
11
11
|
raise StreamErrors::ImproperAddressing unless to && from
|
12
12
|
raise StreamErrors::InvalidFrom unless from.domain == stream.remote_domain
|
13
|
-
stream.user = User.new(:
|
14
|
-
if stanza.local?
|
13
|
+
stream.user = User.new(jid: from)
|
14
|
+
if stanza.local? || stanza.to_pubsub_domain?
|
15
15
|
stanza.process
|
16
16
|
else
|
17
17
|
stanza.route
|
data/lib/vines/stream/http.rb
CHANGED
@@ -10,11 +10,6 @@ module Vines
|
|
10
10
|
@session = Http::Session.new(self)
|
11
11
|
end
|
12
12
|
|
13
|
-
def post_init
|
14
|
-
super
|
15
|
-
router.delete(self)
|
16
|
-
end
|
17
|
-
|
18
13
|
# Override +Stream#create_parser+ to provide an HTTP parser rather than
|
19
14
|
# a Nokogiri XML parser.
|
20
15
|
def create_parser
|
@@ -96,7 +91,6 @@ module Vines
|
|
96
91
|
raise StreamErrors::InvalidNamespace unless node.namespaces['xmlns'] == NAMESPACES[:http_bind]
|
97
92
|
|
98
93
|
Sessions[@session.id] = @session
|
99
|
-
router << @session
|
100
94
|
send_stream_header
|
101
95
|
end
|
102
96
|
|
@@ -11,8 +11,12 @@ module Vines
|
|
11
11
|
raise StreamErrors::ImproperAddressing unless to && from
|
12
12
|
raise StreamErrors::InvalidFrom unless from.domain == stream.remote_domain
|
13
13
|
raise StreamErrors::HostUnknown unless to.domain == stream.domain
|
14
|
-
stream.user = User.new(:
|
15
|
-
stanza.
|
14
|
+
stream.user = User.new(jid: from)
|
15
|
+
if stanza.local? || stanza.to_pubsub_domain?
|
16
|
+
stanza.process
|
17
|
+
else
|
18
|
+
stanza.route
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
data/lib/vines/stream/server.rb
CHANGED
@@ -35,7 +35,8 @@ module Vines
|
|
35
35
|
|
36
36
|
def self.connect(config, to, from, srv, callback)
|
37
37
|
if srv.empty?
|
38
|
-
|
38
|
+
# fiber so storage calls work properly
|
39
|
+
Fiber.new { callback.call(nil) }.resume
|
39
40
|
else
|
40
41
|
begin
|
41
42
|
rr = srv.shift
|
@@ -108,8 +109,8 @@ module Vines
|
|
108
109
|
send_stream_header
|
109
110
|
raise StreamErrors::UnsupportedVersion unless node['version'] == '1.0'
|
110
111
|
raise StreamErrors::ImproperAddressing unless valid_address?(@domain) && valid_address?(@remote_domain)
|
111
|
-
raise StreamErrors::HostUnknown unless config.vhost?(@domain)
|
112
|
-
raise StreamErrors::NotAuthorized unless config.s2s?(@remote_domain)
|
112
|
+
raise StreamErrors::HostUnknown unless config.vhost?(@domain) || config.pubsub?(@domain) || config.component?(@domain)
|
113
|
+
raise StreamErrors::NotAuthorized unless config.s2s?(@remote_domain) && config.allowed?(@domain, @remote_domain)
|
113
114
|
raise StreamErrors::InvalidNamespace unless node.namespaces['xmlns'] == NAMESPACES[:server]
|
114
115
|
raise StreamErrors::InvalidNamespace unless node.namespaces['xmlns:stream'] == NAMESPACES[:stream]
|
115
116
|
end
|
data/lib/vines/stream.rb
CHANGED
@@ -18,7 +18,6 @@ module Vines
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def post_init
|
21
|
-
router << self
|
22
21
|
@remote_addr, @local_addr = addresses
|
23
22
|
@user, @closed, @stanza_size = nil, false, 0
|
24
23
|
@bucket = TokenBucket.new(100, 10)
|
@@ -67,8 +66,12 @@ module Vines
|
|
67
66
|
# Returns the storage system for the domain. If no domain is given,
|
68
67
|
# the stream's storage mechanism is returned.
|
69
68
|
def storage(domain=nil)
|
70
|
-
|
71
|
-
|
69
|
+
@config.storage(domain || self.domain)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the Vines::Config::Host virtual host for the stream's domain.
|
73
|
+
def vhost
|
74
|
+
@config.vhosts[domain]
|
72
75
|
end
|
73
76
|
|
74
77
|
# Reload the user's information into their active connections. Call this
|
@@ -156,7 +159,7 @@ module Vines
|
|
156
159
|
end
|
157
160
|
|
158
161
|
def router
|
159
|
-
|
162
|
+
@config.router
|
160
163
|
end
|
161
164
|
|
162
165
|
private
|
@@ -236,9 +239,10 @@ module Vines
|
|
236
239
|
%w[crt key].map {|ext| File.join(VINES_ROOT, 'conf', 'certs', "#{domain}.#{ext}") }
|
237
240
|
end
|
238
241
|
|
242
|
+
# Return true if this is a valid domain-only JID that can be used in
|
243
|
+
# stream initiation stanza headers.
|
239
244
|
def valid_address?(jid)
|
240
|
-
|
241
|
-
jid && !jid.empty?
|
245
|
+
JID.new(jid).domain? rescue false
|
242
246
|
end
|
243
247
|
end
|
244
248
|
end
|
data/lib/vines/version.rb
CHANGED