skyfallsin-ruby_bosh 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ruby_bosh.rb ADDED
@@ -0,0 +1,145 @@
1
+ require 'rest_client'
2
+ require 'builder'
3
+ require 'rexml/document'
4
+ require 'base64'
5
+ require 'hpricot'
6
+
7
+ # based on
8
+ # http://code.stanziq.com/svn/strophe/trunk/strophejs/examples/attach/boshclient.py
9
+ class RubyBOSHClient
10
+ BOSH_XMLNS = 'http://jabber.org/protocol/httpbind'
11
+ TLS_XMLNS = 'urn:ietf:params:xml:ns:xmpp-tls'
12
+ SASL_XMLNS = 'urn:ietf:params:xml:ns:xmpp-sasl'
13
+ BIND_XMLNS = 'urn:ietf:params:xml:ns:xmpp-bind'
14
+ SESSION_XMLNS = 'urn:ietf:params:xml:ns:xmpp-session'
15
+
16
+ attr_accessor :jid, :rid, :sid, :success
17
+ def initialize(jid, pw, service_url)
18
+ @service_url = service_url
19
+ @jid, @pw = jid, pw
20
+ @host = jid.split("@").last
21
+ @success = false
22
+ @headers = {"Content-Type" => "text/xml; charset=utf-8",
23
+ "Accept" => "text/xml"}
24
+ connect
25
+ end
26
+
27
+ def connect
28
+ initialize_bosh_session
29
+ if send_auth_request
30
+ send_restart_request
31
+ request_resource_binding
32
+ @success = send_session_request
33
+ end
34
+
35
+ if @success
36
+ @rid+=1 #send this directly to the browser
37
+ end
38
+ end
39
+
40
+ def initialize_bosh_session
41
+ response = deliver(construct_body(:wait => 5, :to => @host,
42
+ :hold => 3, :window => 5,
43
+ "xmpp:version" => '1.0'))
44
+ parse(response)
45
+ end
46
+
47
+ def construct_body(params={}, &block)
48
+ @rid ? @rid+=1 : @rid=rand(100000)
49
+
50
+ builder = Builder::XmlMarkup.new
51
+ parameters = {:rid => @rid, :xmlns => BOSH_XMLNS}.merge(params)
52
+
53
+ if block_given?
54
+ builder.body(parameters) {|body| yield(body)}
55
+ else
56
+ builder.body(parameters)
57
+ end
58
+ end
59
+
60
+ def send_auth_request
61
+ request = construct_body(:sid => @sid) do |body|
62
+ auth_string = "#{@jid}\x00#{@jid.split("@").first.strip}\x00#{@pw}"
63
+ body.auth(Base64.encode64(auth_string).gsub(/\s/,''),
64
+ :xmlns => SASL_XMLNS, :mechanism => 'PLAIN')
65
+ end
66
+
67
+ response = deliver(request)
68
+ # TODO: make the following more robust
69
+ response.include?("success")
70
+ end
71
+
72
+ def send_restart_request
73
+ request = construct_body(:sid => @sid, "xmpp:restart" => true, "xmlns:xmpp" => 'urn:xmpp:xbosh')
74
+ deliver(request).include?("stream:features")
75
+ end
76
+
77
+ def request_resource_binding
78
+ request = construct_body(:sid => @sid) do |body|
79
+ body.iq(:id => "bind_#{rand(100000)}", :type => "set",
80
+ :xmlns => "jabber:client") do |iq|
81
+ iq.bind(:xmlns => BIND_XMLNS) do |bind|
82
+ bind.resource('presently')
83
+ end
84
+ end
85
+ end
86
+
87
+ response = deliver(request)
88
+ response.include?("<jid>")
89
+ end
90
+
91
+ def send_session_request
92
+ request = construct_body(:sid => @sid) do |body|
93
+ body.iq(:xmlns => "jabber:client", :type => "set",
94
+ :id => "sess_#{rand(100000)}") do |iq|
95
+ iq.session(:xmlns => SESSION_XMLNS)
96
+ end
97
+ end
98
+
99
+ response = deliver(request)
100
+ response.include?("body")
101
+ end
102
+
103
+ def parse(_response)
104
+ doc = Hpricot(_response)
105
+ doc.search("//body").each do |body|
106
+ @sid = body.attributes["sid"].to_s
107
+ end
108
+ _response
109
+ end
110
+
111
+ def success?
112
+ success == true
113
+ end
114
+
115
+ private
116
+ def deliver(xml)
117
+ send(xml)
118
+ recv(RestClient.post(@service_url, xml, @headers))
119
+ end
120
+
121
+ def send(msg)
122
+ puts "Ruby-BOSH - SEND\n#{msg}"; msg
123
+ end
124
+
125
+ def recv(msg)
126
+ puts "Ruby-BOSH - RECV\n#{msg}"; msg
127
+ end
128
+ end
129
+
130
+
131
+ class RubyBOSH
132
+ def self.initialize_session(jid, pw, service_url)
133
+ conn = RubyBOSHClient.new(jid, pw, service_url)
134
+ if conn.success?
135
+ [conn.jid, conn.sid, conn.rid]
136
+ else
137
+ [nil, nil, nil]
138
+ end
139
+ end
140
+ end
141
+
142
+ if __FILE__ == $0
143
+ p RubyBOSH.initialize_session("skyfallsin@localhost", "skyfallsin",
144
+ "http://localhost:5280/http-bind")
145
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class RubyBoshTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'ruby_bosh'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skyfallsin-ruby_bosh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pradeep Elankumaran
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-18 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: TODO
17
+ email: pradeep@intridea.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - lib/ruby_bosh.rb
27
+ - test/ruby_bosh_test.rb
28
+ - test/test_helper.rb
29
+ has_rdoc: true
30
+ homepage: http://github.com/skyfallsin/ruby_bosh
31
+ post_install_message:
32
+ rdoc_options:
33
+ - --inline-source
34
+ - --charset=UTF-8
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: A BOSH session pre-initializer for Ruby web applications
56
+ test_files: []
57
+