vines 0.3.2 → 0.4.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/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