julien51-babylon 0.0.14 → 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.
- data/README.rdoc +14 -16
- data/Rakefile +1 -3
- data/lib/babylon.rb +37 -6
- data/lib/babylon/base/controller.rb +32 -24
- data/lib/babylon/base/stanza.rb +2 -4
- data/lib/babylon/base/view.rb +19 -19
- data/lib/babylon/client_connection.rb +93 -80
- data/lib/babylon/component_connection.rb +13 -9
- data/lib/babylon/generator.rb +1 -1
- data/lib/babylon/router.rb +48 -86
- data/lib/babylon/router/dsl.rb +0 -6
- data/lib/babylon/runner.rb +56 -34
- data/lib/babylon/xmpp_connection.rb +56 -46
- data/lib/babylon/xmpp_parser.rb +50 -53
- data/templates/babylon/config/boot.rb +1 -1
- data/templates/babylon/config/config.yaml +1 -3
- data/templates/babylon/config/routes.rb +1 -1
- data/templates/babylon/log/test.log +52 -0
- data/templates/babylon/script/component +36 -20
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -4,24 +4,20 @@
|
|
4
4
|
|
5
5
|
Babylon is a framework to build XMPP Applications in Ruby. The framework uses EventMachine to handle network connections.
|
6
6
|
|
7
|
-
This framework can use both an XMPP Component (XEP-0114) and an XMPP Client (and XMPP Servers should come
|
7
|
+
This framework can use both an XMPP Component (XEP-0114) and an XMPP Client (and XMPP Servers should come soon). However, we strongly discourage any production application using a regular client.
|
8
8
|
|
9
9
|
== FEATURES/PROBLEMS:
|
10
10
|
|
11
|
-
Please report/request
|
11
|
+
Please link "report/request here.":http://github.com/julien51/babylon/issues
|
12
12
|
|
13
13
|
The current version is a good candidate for version 0.1. We will probably not add any important features before that release, but we need some help with the tests and documentation.
|
14
14
|
|
15
15
|
== ROADMAP :
|
16
16
|
|
17
|
-
- Improve the Client Connection to support other authentication than PLAIN SASL
|
18
17
|
- Implement the ServerConnection for S2S
|
19
|
-
- Implement
|
20
|
-
- Use a better generator (the next version of Nokogiri should fix that)
|
21
|
-
- Implement "background" running when in production (and adjust log level)
|
18
|
+
- Implement templates for disco-info... and common XEPs
|
22
19
|
- Delete route priorities? And rely on the order only? (As Rails does)
|
23
20
|
- Review doc
|
24
|
-
- Write more spec
|
25
21
|
- Write tests
|
26
22
|
- Evangelize!
|
27
23
|
|
@@ -29,8 +25,10 @@ You can help with at least one of these points, don't turn your back on Babylon!
|
|
29
25
|
|
30
26
|
== DOCUMENTATION :
|
31
27
|
|
32
|
-
You can find it on our Rubyforge page
|
33
|
-
|
28
|
+
You can find it on our "Rubyforge page":http://babylon.rubyforge.org/
|
29
|
+
Feel free to fork the "github":http://github.com/julien51/babylon/tree/master repo and add some documentation if you think anything is missing.
|
30
|
+
|
31
|
+
__You can't be a bad coder, a bad tester and a bad documenter at the same time ;)__
|
34
32
|
|
35
33
|
== SYNOPSIS :
|
36
34
|
|
@@ -41,19 +39,19 @@ You can build applications directly with Babylon, or you can use the Babylon::Cl
|
|
41
39
|
1. Install the gem
|
42
40
|
2. The app contains a generator that will "build" a scaffold for your application.
|
43
41
|
|
44
|
-
$> babylon application
|
42
|
+
$> babylon application __myapp__
|
45
43
|
|
46
44
|
3. Use the generator or write your own controllers :
|
47
45
|
|
48
|
-
$> babylon controller
|
46
|
+
$> babylon controller __messages__ __echo__:__10__:__//stream:message[@type='chat']/body__,__subscribed__:__0__:__//stream:presence[@type='subscribe']__
|
49
47
|
|
50
|
-
This will generate a
|
48
|
+
This will generate a __MessagesController__ class with 2 methods : __echo__ and __subscribed__.
|
51
49
|
- "echo" will be called when the component receives message stanzas of type 'chat',
|
52
50
|
- "subscribed" will be called for presence stanzas of type 'subscribe'.
|
53
51
|
10 and 0 are the priority : useful when a stanza matches 2 XPath.
|
54
52
|
|
55
|
-
Each of these actions will be called with stanza objects. You have to define your own objects in
|
56
|
-
By
|
53
|
+
Each of these actions will be called with stanza objects. You have to define your own objects in __stanzas/echo.rb__ and __stanzas/subscribed.rb__
|
54
|
+
By implementing them, you can choose which elements and attributes you want to have access to. These attributes will be populated upon instantiation of the Stanza objects.
|
57
55
|
|
58
56
|
This will also generate 2 'views' used to build your responses stanzas.
|
59
57
|
|
@@ -61,7 +59,7 @@ And finally, this will write 2 routes in the config/routes.rb
|
|
61
59
|
|
62
60
|
4. Customize your controllers, stanzas and views!
|
63
61
|
|
64
|
-
5. Make sure that the XMPP settings are correct in config/config.yaml.
|
62
|
+
5. Make sure that the XMPP settings are correct in config/config.yaml.
|
65
63
|
|
66
64
|
6. And finally start the component :
|
67
65
|
|
@@ -85,7 +83,7 @@ Babylon's edge versions are located at Github : http://github.com/julien51/babyl
|
|
85
83
|
|
86
84
|
== REQUIREMENTS :
|
87
85
|
|
88
|
-
Gems : Eventmachine, nokogiri, YAML, log4r, sax-machine, templater, daemons
|
86
|
+
Gems : Eventmachine, nokogiri (please, use build from the guthub repo, since 1.2.3 is not supported by Babylon), YAML, log4r, sax-machine, templater, daemons
|
89
87
|
|
90
88
|
== LICENSE:
|
91
89
|
|
data/Rakefile
CHANGED
@@ -82,10 +82,8 @@ begin
|
|
82
82
|
Spec::Rake::SpecTask.new('spec') do |spec|
|
83
83
|
spec.spec_files = FileList['spec/**/*.rb']
|
84
84
|
spec.verbose = true
|
85
|
-
spec.warning =
|
85
|
+
spec.warning = false
|
86
86
|
spec.rcov = true
|
87
|
-
spec.rcov_opts = []
|
88
|
-
spec.rcov_opts = ['--exclude', 'spec']
|
89
87
|
end
|
90
88
|
rescue LoadError
|
91
89
|
task :spec do
|
data/lib/babylon.rb
CHANGED
@@ -39,20 +39,35 @@ module Babylon
|
|
39
39
|
@@env
|
40
40
|
end
|
41
41
|
|
42
|
+
##
|
43
|
+
# Sets up the router
|
44
|
+
def self.router=(router)
|
45
|
+
@@router = router
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Retruns the router
|
50
|
+
def self.router
|
51
|
+
unless self.class_variable_defined?("@@router")
|
52
|
+
@@router = nil
|
53
|
+
end
|
54
|
+
@@router
|
55
|
+
end
|
56
|
+
|
42
57
|
##
|
43
58
|
# Caches the view files to improve performance.
|
44
59
|
def self.cache_views
|
45
|
-
@@
|
60
|
+
@@views= {}
|
46
61
|
Dir.glob('app/views/*/*').each do |f|
|
47
|
-
@@
|
62
|
+
@@views[f] = File.read(f)
|
48
63
|
end
|
49
64
|
end
|
50
65
|
|
51
|
-
def self.
|
52
|
-
unless self.class_variable_defined?("@@
|
53
|
-
@@
|
66
|
+
def self.views
|
67
|
+
unless self.class_variable_defined?("@@views")
|
68
|
+
@@views= {}
|
54
69
|
end
|
55
|
-
@@
|
70
|
+
@@views
|
56
71
|
end
|
57
72
|
|
58
73
|
##
|
@@ -77,5 +92,21 @@ module Babylon
|
|
77
92
|
@@config
|
78
93
|
end
|
79
94
|
|
95
|
+
##
|
96
|
+
# Decodes XML special characters.
|
97
|
+
def self.decode_xml(str)
|
98
|
+
entities = {
|
99
|
+
'lt' => '<',
|
100
|
+
'gt' => '>',
|
101
|
+
'#38' => '&',
|
102
|
+
'amp' => '&',
|
103
|
+
'quot' => '"',
|
104
|
+
'#13' => "\r",
|
105
|
+
}
|
106
|
+
entities.keys.inject(str) { |string, key|
|
107
|
+
string.gsub(/&#{key};/, entities[key])
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
80
111
|
end
|
81
112
|
|
@@ -11,14 +11,13 @@ module Babylon
|
|
11
11
|
# Creates a new controller (you should not override this class) and assigns the stanza as well as any other value of the hash to instances named after the keys of the hash.
|
12
12
|
def initialize(stanza = nil)
|
13
13
|
@stanza = stanza
|
14
|
-
@
|
14
|
+
@view = nil
|
15
15
|
end
|
16
16
|
|
17
17
|
##
|
18
18
|
# Performs the action and calls back the optional block argument : you should not override this function
|
19
|
-
def perform(action
|
19
|
+
def perform(action)
|
20
20
|
@action_name = action
|
21
|
-
@block = block
|
22
21
|
begin
|
23
22
|
self.send(@action_name)
|
24
23
|
rescue
|
@@ -31,12 +30,12 @@ module Babylon
|
|
31
30
|
# Returns the list of variables assigned during the action.
|
32
31
|
def assigns
|
33
32
|
vars = Hash.new
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
instance_variables.each do |var|
|
34
|
+
if !["@view", "@action_name", "@block"].include? var
|
35
|
+
vars[var[1..-1]] = instance_variable_get(var)
|
36
|
+
end
|
38
37
|
end
|
39
|
-
|
38
|
+
vars
|
40
39
|
end
|
41
40
|
|
42
41
|
##
|
@@ -45,44 +44,53 @@ module Babylon
|
|
45
44
|
# - :file : render a specific file (can be in a different controller)
|
46
45
|
# - :action : render another action of the current controller
|
47
46
|
# - :nothing : doesn't render anything
|
48
|
-
def render(options =
|
49
|
-
return if @
|
47
|
+
def render(options = {})
|
48
|
+
return if @view and !options[:force] # Avoid double rendering, if we have already attached a view
|
50
49
|
|
51
|
-
if options
|
52
|
-
render(:file => default_template_name)
|
50
|
+
if options == {} # default rendering
|
51
|
+
result = render(:file => default_template_name)
|
53
52
|
elsif options[:file]
|
54
53
|
file = options[:file]
|
55
|
-
if file
|
56
|
-
render_for_file("app
|
54
|
+
if file =~ /^\// # Render from view root
|
55
|
+
result = render_for_file(File.join("app", "views", "#{file}.xml.builder"))
|
57
56
|
else
|
58
|
-
render_for_file(view_path(file))
|
57
|
+
result = render_for_file(view_path(file))
|
59
58
|
end
|
60
59
|
elsif action_name = options[:action]
|
61
|
-
render(:file => default_template_name(action_name.to_s))
|
60
|
+
result = render(:file => default_template_name(action_name.to_s))
|
62
61
|
elsif options[:nothing]
|
63
|
-
|
62
|
+
@view = Babylon::Base::View.new()
|
64
63
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Actually evaluates the view
|
68
|
+
def evaluate
|
69
|
+
@view.evaluate if @view
|
68
70
|
end
|
69
71
|
|
70
72
|
protected
|
71
73
|
|
74
|
+
##
|
75
|
+
# Builds the view path.
|
72
76
|
def view_path(file_name)
|
73
|
-
File.join("app
|
77
|
+
File.join("app", "views", "#{self.class.name.gsub("Controller","").downcase}", file_name)
|
74
78
|
end
|
75
79
|
|
80
|
+
##
|
76
81
|
# Default template name used to build stanzas
|
77
82
|
def default_template_name(action_name = nil)
|
78
|
-
|
83
|
+
"#{action_name || @action_name}.xml.builder"
|
79
84
|
end
|
80
85
|
|
86
|
+
##
|
81
87
|
# Creates the view and "evaluates" it to build the XML for the stanza
|
82
88
|
def render_for_file(file)
|
83
|
-
|
84
|
-
Babylon.
|
89
|
+
Babylon.logger.info("RENDERING : #{file}")
|
90
|
+
@view = Babylon::Base::View.new(file, assigns)
|
91
|
+
Babylon.logger.info(" ")
|
85
92
|
end
|
93
|
+
|
86
94
|
end
|
87
95
|
end
|
88
96
|
end
|
data/lib/babylon/base/stanza.rb
CHANGED
@@ -13,14 +13,12 @@ module Babylon
|
|
13
13
|
# element :message, :value => :id, :as => :stanza_id
|
14
14
|
# element :message, :value => :type, :as => :stanza_type
|
15
15
|
# element :message, :value => :"xml:lang", :as => :lang
|
16
|
-
|
16
|
+
#
|
17
17
|
class Stanza
|
18
|
-
|
19
18
|
include SAXMachine
|
20
19
|
|
21
20
|
def initialize(xml = nil)
|
22
|
-
|
23
|
-
parse("#{xml}")
|
21
|
+
parse(xml.to_s)
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
data/lib/babylon/base/view.rb
CHANGED
@@ -1,34 +1,34 @@
|
|
1
1
|
module Babylon
|
2
2
|
module Base
|
3
3
|
|
4
|
+
class ViewFileNotFound < Errno::ENOENT; end
|
5
|
+
|
4
6
|
##
|
5
7
|
# Your application's views (stanzas) should be descendant of this class.
|
6
8
|
class View
|
7
|
-
attr_reader :
|
9
|
+
attr_reader :view_template
|
8
10
|
|
9
11
|
##
|
10
12
|
# Instantiate a new view with the various varibales passed in assigns and the path of the template to render.
|
11
|
-
def initialize(path, assigns)
|
12
|
-
@
|
13
|
-
|
13
|
+
def initialize(path = "", assigns = {})
|
14
|
+
@view_template = path
|
15
|
+
|
14
16
|
assigns.each do |key, value|
|
15
|
-
instance_variable_set("@#{key}", value)
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
17
|
+
instance_variable_set(:"@#{key}", value)
|
18
|
+
end
|
19
|
+
end
|
21
20
|
|
22
|
-
##
|
23
|
-
# "Loads" the view file, and uses the Nokogiri Builder to build the XML stanzas that will be sent.
|
24
|
-
def evaluate
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
##
|
22
|
+
# "Loads" the view file, and uses the Nokogiri Builder to build the XML stanzas that will be sent.
|
23
|
+
def evaluate
|
24
|
+
return if @view_template == ""
|
25
|
+
raise ViewFileNotFound unless Babylon.views[@view_template]
|
26
|
+
builder = Nokogiri::XML::Builder.new
|
27
|
+
builder.stream do |xml|
|
28
|
+
eval(Babylon.views[@view_template])
|
28
29
|
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
30
|
+
builder.doc.root.children # we output the document built
|
31
|
+
end
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -25,35 +25,47 @@ module Babylon
|
|
25
25
|
return super(params, handler) if params["host"] && params["port"]
|
26
26
|
|
27
27
|
begin
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
Babylon.logger.debug "Resolv::DNS does not support SRV records. Please upgrade to ruby-1.8.3 or later! \n#{$!} : #{$!.backtrace.join("\n")}"
|
53
|
-
end
|
28
|
+
srv = []
|
29
|
+
Resolv::DNS.open { |dns|
|
30
|
+
# If ruby version is too old and SRV is unknown, this will raise a NameError
|
31
|
+
# which is caught below
|
32
|
+
host_from_jid = params["jid"].split("/").first.split("@").last
|
33
|
+
Babylon.logger.debug("RESOLVING: _xmpp-client._tcp.#{host_from_jid} (SRV)")
|
34
|
+
srv = dns.getresources("_xmpp-client._tcp.#{host_from_jid}", Resolv::DNS::Resource::IN::SRV)
|
35
|
+
}
|
36
|
+
# Sort SRV records: lowest priority first, highest weight first
|
37
|
+
srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
|
38
|
+
# And now, for each record, let's try to connect.
|
39
|
+
srv.each { |record|
|
40
|
+
begin
|
41
|
+
params["host"] = record.target.to_s
|
42
|
+
params["port"] = Integer(record.port)
|
43
|
+
super(params, handler)
|
44
|
+
# Success
|
45
|
+
break
|
46
|
+
rescue NotConnected
|
47
|
+
# Try next SRV record
|
48
|
+
end
|
49
|
+
}
|
50
|
+
rescue NameError
|
51
|
+
Babylon.logger.debug "Resolv::DNS does not support SRV records. Please upgrade to ruby-1.8.3 or later! \n#{$!} : #{$!.backtrace.join("\n")}"
|
54
52
|
end
|
55
53
|
end
|
56
54
|
|
55
|
+
##
|
56
|
+
# Builds the stream stanza for this client
|
57
|
+
def stream_stanza
|
58
|
+
doc = Nokogiri::XML::Document.new
|
59
|
+
stream = Nokogiri::XML::Node.new("stream", doc)
|
60
|
+
doc.add_child(stream)
|
61
|
+
stream.add_namespace(nil, stream_namespace())
|
62
|
+
stream.add_namespace("stream", "http://etherx.jabber.org/streams")
|
63
|
+
stream["to"] = jid.split("/").first.split("@").last
|
64
|
+
stream["version"] = "1.0"
|
65
|
+
paste_content_here = Nokogiri::XML::Node.new("paste_content_here", doc)
|
66
|
+
stream.add_child(paste_content_here)
|
67
|
+
doc.to_xml.split('<stream:paste_content_here/>').first
|
68
|
+
end
|
57
69
|
|
58
70
|
##
|
59
71
|
# Connection_completed is called when the connection (socket) has been established and is in charge of "building" the XML stream
|
@@ -61,46 +73,45 @@ module Babylon
|
|
61
73
|
# We use a "tweak" here to send only the starting tag of stream:stream
|
62
74
|
def connection_completed
|
63
75
|
super
|
64
|
-
|
65
|
-
self.send('stream:stream', {'xmlns' => @context.stream_namespace(), 'xmlns:stream' => 'http://etherx.jabber.org/streams', 'to' => @context.jid.split("/").first.split("@").last, 'version' => '1.0'}) do
|
66
|
-
paste_content_here # The stream:stream element should be cut here ;)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
@outstream = builder.doc
|
70
|
-
start_stream, stop_stream = builder.to_xml.split('<paste_content_here/>')
|
71
|
-
send_xml(start_stream)
|
76
|
+
send_xml(stream_stanza)
|
72
77
|
end
|
73
78
|
|
74
79
|
##
|
75
80
|
# Called upon stanza reception
|
76
81
|
# Marked as connected when the client has been SASLed, authenticated, biund to a resource and when the session has been created
|
77
82
|
def receive_stanza(stanza)
|
78
|
-
begin
|
79
83
|
case @state
|
80
84
|
when :connected
|
81
85
|
super # Can be dispatched
|
82
86
|
|
87
|
+
when :wait_for_stream_authenticated
|
88
|
+
if stanza.name == "stream:stream" && stanza.attributes['id']
|
89
|
+
@state = :wait_for_bind
|
90
|
+
end
|
91
|
+
|
83
92
|
when :wait_for_stream
|
84
93
|
if stanza.name == "stream:stream" && stanza.attributes['id']
|
85
|
-
@state = :wait_for_auth_mechanisms
|
86
|
-
@state = :wait_for_bind if @success
|
94
|
+
@state = :wait_for_auth_mechanisms
|
87
95
|
end
|
88
96
|
|
89
97
|
when :wait_for_auth_mechanisms
|
90
98
|
if stanza.name == "stream:features"
|
91
99
|
if stanza.at("starttls") # we shall start tls
|
92
|
-
|
93
|
-
starttls
|
94
|
-
|
100
|
+
doc = Nokogiri::XML::Document.new
|
101
|
+
starttls = Nokogiri::XML::Node.new("starttls", doc)
|
102
|
+
doc.add_child(starttls)
|
103
|
+
starttls.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-tls")
|
104
|
+
send_xml(starttls.to_s)
|
95
105
|
@state = :wait_for_proceed
|
96
106
|
elsif stanza.at("mechanisms") # tls is ok
|
97
|
-
if stanza.at("mechanisms
|
98
|
-
|
99
|
-
auth = Nokogiri::XML::Node.new("auth",
|
107
|
+
if stanza.at("mechanisms").children.map() { |m| m.text }.include? "PLAIN"
|
108
|
+
doc = Nokogiri::XML::Document.new
|
109
|
+
auth = Nokogiri::XML::Node.new("auth", doc)
|
110
|
+
doc.add_child(auth)
|
100
111
|
auth['mechanism'] = "PLAIN"
|
101
|
-
auth
|
112
|
+
auth.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-sasl")
|
102
113
|
auth.content = Base64::encode64([jid, jid.split("@").first, @password].join("\000")).gsub(/\s/, '')
|
103
|
-
send_xml(auth)
|
114
|
+
send_xml(auth.to_s)
|
104
115
|
@state = :wait_for_success
|
105
116
|
end
|
106
117
|
end
|
@@ -108,10 +119,9 @@ module Babylon
|
|
108
119
|
|
109
120
|
when :wait_for_success
|
110
121
|
if stanza.name == "success" # Yay! Success
|
111
|
-
@
|
112
|
-
@state = :wait_for_stream
|
122
|
+
@state = :wait_for_stream_authenticated
|
113
123
|
@parser.reset
|
114
|
-
send_xml
|
124
|
+
send_xml(stream_stanza)
|
115
125
|
elsif stanza.name == "failure"
|
116
126
|
if stanza.at("bad-auth") || stanza.at("not-authorized")
|
117
127
|
raise AuthenticationError
|
@@ -124,47 +134,53 @@ module Babylon
|
|
124
134
|
when :wait_for_bind
|
125
135
|
if stanza.name == "stream:features"
|
126
136
|
if stanza.at("bind")
|
137
|
+
doc = Nokogiri::XML::Document.new
|
127
138
|
# Let's build the binding_iq
|
128
139
|
@binding_iq_id = Integer(rand(10000))
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
140
|
+
iq = Nokogiri::XML::Node.new("iq", doc)
|
141
|
+
doc.add_child(iq)
|
142
|
+
iq["type"] = "set"
|
143
|
+
iq["id"] = binding_iq_id.to_s
|
144
|
+
bind = Nokogiri::XML::Node.new("bind", doc)
|
145
|
+
bind.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-bind")
|
146
|
+
iq.add_child(bind)
|
147
|
+
resource = Nokogiri::XML::Node.new("resource", doc)
|
148
|
+
if jid.split("/").size == 2
|
149
|
+
resource.content = (@jid.split("/").last)
|
150
|
+
else
|
151
|
+
resource.content = "babylon_client_#{binding_iq_id}"
|
139
152
|
end
|
140
|
-
|
141
|
-
send_xml(iq)
|
153
|
+
bind.add_child(resource)
|
154
|
+
send_xml(iq.to_s)
|
142
155
|
@state = :wait_for_confirmed_binding
|
143
156
|
end
|
144
157
|
end
|
145
158
|
|
146
159
|
when :wait_for_confirmed_binding
|
147
|
-
if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) ==
|
148
|
-
if stanza.at("jid")
|
149
|
-
jid= stanza.at("jid").text
|
160
|
+
if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) == binding_iq_id
|
161
|
+
if stanza.at("jid")
|
162
|
+
@jid = stanza.at("jid").text
|
150
163
|
end
|
164
|
+
# And now, we must initiate the session
|
165
|
+
@session_iq_id = Integer(rand(10000))
|
166
|
+
doc = Nokogiri::XML::Document.new
|
167
|
+
iq = Nokogiri::XML::Node.new("iq", doc)
|
168
|
+
doc.add_child(iq)
|
169
|
+
iq["type"] = "set"
|
170
|
+
iq["id"] = session_iq_id.to_s
|
171
|
+
session = Nokogiri::XML::Node.new("session", doc)
|
172
|
+
session.add_namespace(nil, "urn:ietf:params:xml:ns:xmpp-session")
|
173
|
+
iq.add_child(session)
|
174
|
+
send_xml(iq.to_s)
|
175
|
+
@state = :wait_for_confirmed_session
|
151
176
|
end
|
152
|
-
# And now, we must initiate the session
|
153
|
-
@session_iq_id = Integer(rand(10000))
|
154
|
-
builder = Nokogiri::XML::Builder.new do
|
155
|
-
iq(:type => "set", :id => @context.session_iq_id) do
|
156
|
-
session(:xmlns => "urn:ietf:params:xml:ns:xmpp-session")
|
157
|
-
end
|
158
|
-
end
|
159
|
-
iq = @outstream.add_child(builder.doc.root)
|
160
|
-
send_xml(iq)
|
161
|
-
@state = :wait_for_confirmed_session
|
162
177
|
|
163
178
|
when :wait_for_confirmed_session
|
164
|
-
if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) ==
|
179
|
+
if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) == session_iq_id
|
165
180
|
# And now, send a presence!
|
166
|
-
|
167
|
-
|
181
|
+
doc = Nokogiri::XML::Document.new
|
182
|
+
presence = Nokogiri::XML::Node.new("presence", doc)
|
183
|
+
send_xml(presence.to_s)
|
168
184
|
begin
|
169
185
|
@handler.on_connected(self) if @handler and @handler.respond_to?("on_connected")
|
170
186
|
rescue
|
@@ -177,11 +193,8 @@ module Babylon
|
|
177
193
|
start_tls() # starting TLS
|
178
194
|
@state = :wait_for_stream
|
179
195
|
@parser.reset
|
180
|
-
send_xml
|
196
|
+
send_xml stream_stanza
|
181
197
|
end
|
182
|
-
rescue
|
183
|
-
Babylon.logger.error("#{$!}:\n#{$!.backtrace.join("\n")}")
|
184
|
-
end
|
185
198
|
end
|
186
199
|
|
187
200
|
##
|