julien51-babylon 0.0.14 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
##
|