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 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 soone). However, we strongly discourage any production application using a regular client.
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 them at the Lighthouse : http://babylon.lighthouseapp.com/projects/27641-babylon/overview
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 "auto-responding" features for disco-info... etc
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 : http://babylon.rubyforge.org/
33
- Please note that the documentation is probably incomplete... so if you have any problems with something that is not clear enough to you, feel free to send us questions and do not hesitate to fork the project to add your own documentation. We will be more than happy to help you help us!
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 <myapp>
42
+ $> babylon application __myapp__
45
43
 
46
44
  3. Use the generator or write your own controllers :
47
45
 
48
- $> babylon controller messages echo:10://message[@type='chat']/body,subscribed:0://presence[@type='subscribe']
46
+ $> babylon controller __messages__ __echo__:__10__:__//stream:message[@type='chat']/body__,__subscribed__:__0__:__//stream:presence[@type='subscribe']__
49
47
 
50
- This will generate a "MessagesController" class with 2 methods : echo and subscribed.
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 stanzas/echo.rb and stanzas/subscribed.rb
56
- By defining 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.
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. !!! You need to have a Jabber Component, regular clients will NOT work!!!
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 = true
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
- @@cached_views= {}
60
+ @@views= {}
46
61
  Dir.glob('app/views/*/*').each do |f|
47
- @@cached_views[f] = File.read(f)
62
+ @@views[f] = File.read(f)
48
63
  end
49
64
  end
50
65
 
51
- def self.cached_views
52
- unless self.class_variable_defined?("@@cached_views")
53
- @@cached_views= {}
66
+ def self.views
67
+ unless self.class_variable_defined?("@@views")
68
+ @@views= {}
54
69
  end
55
- @@cached_views
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
- @rendered = false
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, &block)
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
- instance_variables.each do |var|
35
- if !["@rendered", "@action_name", "@block"].include? var
36
- vars[var[1..-1]] = instance_variable_get(var)
37
- end
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
- return vars
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 = nil)
49
- return if @rendered # Avoid double rendering
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.nil? # default rendering
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.include?('/')
56
- render_for_file("app/views/#{file}.xml.builder")
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
- # Then we don't do anything.
62
+ @view = Babylon::Base::View.new()
64
63
  end
65
-
66
- # And finally, we set up rendered to be true
67
- @rendered = true
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/views", "#{self.class.name.gsub("Controller","").downcase}", file_name)
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
- return "#{action_name || @action_name}.xml.builder"
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
- @block.call(Babylon::Base::View.new(file, assigns).evaluate) if @block
84
- Babylon.logger.info("RENDERED : #{file}")
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
@@ -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
- @xml = xml
23
- parse("#{xml}")
21
+ parse(xml.to_s)
24
22
  end
25
23
  end
26
24
  end
@@ -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 :output, :view_template
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
- @output = ""
13
- @view_template = path
13
+ def initialize(path = "", assigns = {})
14
+ @view_template = path
15
+
14
16
  assigns.each do |key, value|
15
- instance_variable_set("@#{key}", value)
16
- self.class.send(:define_method, key) do # Defining accessors
17
- value
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
- str = (Babylon.cached_views && Babylon.cached_views[@view_template]) ? Babylon.cached_views[@view_template] : File.read(@view_template)
26
- xml = Nokogiri::XML::Builder.new do
27
- instance_eval(str)
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
- return xml.doc.children #we return the doc's children (to avoid the instruct)
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
- begin
29
- srv = []
30
- Resolv::DNS.open { |dns|
31
- # If ruby version is too old and SRV is unknown, this will raise a NameError
32
- # which is caught below
33
- host_from_jid = params["jid"].split("/").first.split("@").last
34
- Babylon.logger.debug("RESOLVING: _xmpp-client._tcp.#{host_from_jid} (SRV)")
35
- srv = dns.getresources("_xmpp-client._tcp.#{host_from_jid}", Resolv::DNS::Resource::IN::SRV)
36
- }
37
- # Sort SRV records: lowest priority first, highest weight first
38
- srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
39
- # And now, for each record, let's try to connect.
40
- srv.each { |record|
41
- begin
42
- params["host"] = record.target.to_s
43
- params["port"] = Integer(record.port)
44
- super(params, handler)
45
- # Success
46
- break
47
- rescue SocketError, Errno::ECONNREFUSED
48
- # Try next SRV record
49
- end
50
- }
51
- rescue NameError
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
- builder = Nokogiri::XML::Builder.new do
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 unless @success
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
- starttls = Nokogiri::XML::Node.new("starttls", @outstream)
93
- starttls["xmlns"] = "urn:ietf:params:xml:ns:xmpp-tls"
94
- send_xml(starttls)
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/[contains(mechanism,'PLAIN')]")
98
- # auth_text = "#{jid.strip}\x00#{jid.node}\x00#{password}"
99
- auth = Nokogiri::XML::Node.new("auth", @outstream)
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['xmlns'] = "urn:ietf:params:xml:ns:xmpp-sasl"
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
- @success = true
112
- @state = :wait_for_stream
122
+ @state = :wait_for_stream_authenticated
113
123
  @parser.reset
114
- send_xml @outstream.root.to_xml.split('<paste_content_here/>').first
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
- builder = Nokogiri::XML::Builder.new do
130
- iq(:type => "set", :id => @context.binding_iq_id) do
131
- bind(:xmlns => "urn:ietf:params:xml:ns:xmpp-bind") do
132
- if @context.jid.split("/").size == 2
133
- resource(@context.jid.split("/").last)
134
- else
135
- resource("babylon_client_#{@context.binding_iq_id}")
136
- end
137
- end
138
- end
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
- iq = @outstream.add_child(builder.doc.root)
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"]) == @binding_iq_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"]) == @session_iq_id && stanza.at("session")
179
+ if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) == session_iq_id
165
180
  # And now, send a presence!
166
- presence = Nokogiri::XML::Node.new("presence", @outstream)
167
- send_xml(presence)
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 @outstream.root.to_xml.split('<paste_content_here/>').first
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
  ##