Gemfile 🔗
@@ -9,3 +9,5 @@ gem 'redis', '>= 3.2.0'
gem 'goliath'
gem 'log4r'
+
+gem 'uuid'
Denver Gingerich created
Gemfile | 2
sgx-catapult.rb | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 145 insertions(+), 2 deletions(-)
@@ -9,3 +9,5 @@ gem 'redis', '>= 3.2.0'
gem 'goliath'
gem 'log4r'
+
+gem 'uuid'
@@ -23,6 +23,7 @@ require 'json'
require 'net/http'
require 'redis/connection/hiredis'
require 'uri'
+require 'uuid'
require 'goliath/api'
require 'goliath/server'
@@ -39,6 +40,9 @@ end
module SGXcatapult
extend Blather::DSL
+ @jingle_sids = Hash.new
+ @uuid_gen = UUID.new
+
def self.run
client.run
end
@@ -132,8 +136,17 @@ module SGXcatapult
end
def self.user_cap_features()
- # TODO: add more features
- ["urn:xmpp:receipts"]
+ [
+ "urn:xmpp:receipts",
+ "urn:xmpp:jingle:1", "urn:xmpp:jingle:transports:ibb:1",
+
+ # TODO: eventually add more efficient file transfer mechanisms
+ #"urn:xmpp:jingle:transports:s5b:1",
+
+ # TODO: MUST add all relevant/reasonable vers of file-transfer
+ #"urn:xmpp:jingle:apps:file-transfer:4"
+ "urn:xmpp:jingle:apps:file-transfer:3"
+ ]
end
presence :subscribe? do |p|
@@ -165,6 +178,134 @@ module SGXcatapult
write_to_stream msg
end
+ iq '/iq/ns:jingle', :ns => 'urn:xmpp:jingle:1' do |i, jn|
+ puts "IQj: #{i.inspect}"
+
+ if jn[0]['action'] == 'transport-accept'
+ puts "REPLY0: #{i.reply.inspect}"
+ write_to_stream i.reply
+ next
+ elsif jn[0]['action'] == 'session-terminate'
+ # TODO: unexpected (usually we do this; handle?)
+ puts "TERMINATED"
+ next
+ elsif jn[0]['action'] == 'transport-info'
+ # TODO: unexpected, but should handle in a nice way
+ puts "FAIL!!!"
+ next
+ elsif i.type == :error
+ # TODO: do something, maybe terminating the connection
+ puts 'ERROR!!!'
+ next
+ end
+
+ # TODO: should probably confirm we got session-initiate here
+
+ write_to_stream i.reply
+ puts "RESPONSE8: #{i.reply.inspect}"
+
+ msg = Blather::Stanza::Iq.new :set
+ msg.to = i.from
+ msg.from = i.to
+
+ cn = jn.children.find { |v| v.element_name == "content" }
+ puts 'CN-name: ' + cn['name']
+ puts 'JN-sid: ' + jn[0]['sid']
+
+ ibb_found = false
+ last_sid = ''
+ for child in cn.children
+ if child.element_name == 'transport'
+ puts 'TPORT: ' + child.namespace.href
+ last_sid = child['sid']
+ if 'urn:xmpp:jingle:transports:ibb:1' ==
+ child.namespace.href
+
+ ibb_found = true
+ break
+ end
+ end
+ end
+
+ j = Nokogiri::XML::Node.new 'jingle',msg.document
+ j['xmlns'] = 'urn:xmpp:jingle:1'
+ j['sid'] = jn[0]['sid']
+ msg.add_child(j)
+
+ content = Nokogiri::XML::Node.new 'content',msg.document
+ content['name'] = cn['name']
+ content['creator'] = 'initiator'
+ j.add_child(content)
+
+ transport = Nokogiri::XML::Node.new 'transport',msg.document
+ # TODO: make block-size more variable and/or dependent on sender
+ transport['block-size'] = '4096'
+ transport['xmlns'] = 'urn:xmpp:jingle:transports:ibb:1'
+ if ibb_found
+ transport['sid'] = last_sid
+ j['action'] = 'session-accept'
+ j['responder'] = i.from
+
+ dsc = Nokogiri::XML::Node.new 'description',msg.document
+ dsc['xmlns'] = 'urn:xmpp:jingle:apps:file-transfer:3'
+ content.add_child(dsc)
+ else
+ # for Conversations - it tries s5b even if caps ibb-only
+ transport['sid'] = @uuid_gen.generate
+ j['action'] = 'transport-replace'
+ j['initiator'] = i.from
+ end
+ content.add_child(transport)
+
+ @jingle_sids[transport['sid']] = jn[0]['sid']
+
+ puts "RESPONSE9: #{msg.inspect}"
+ write_to_stream msg
+ end
+
+ iq '/iq/ns:open', :ns =>
+ 'http://jabber.org/protocol/ibb' do |i, xpath_result|
+
+ puts "IQo: #{i.inspect}"
+ write_to_stream i.reply
+ end
+
+ iq '/iq/ns:data', :ns =>
+ 'http://jabber.org/protocol/ibb' do |i, dn|
+
+ # TODO: decode and save partial data so can upload it when done
+ puts "IQd: #{i.inspect}"
+ write_to_stream i.reply
+ end
+
+ iq '/iq/ns:close', :ns =>
+ 'http://jabber.org/protocol/ibb' do |i, cn|
+
+ puts "IQc: #{i.inspect}"
+ write_to_stream i.reply
+
+ # TODO: upload cached data to server (do before success reply)
+
+ # received the complete file so now close the stream
+ msg = Blather::Stanza::Iq.new :set
+ msg.to = i.from
+ msg.from = i.to
+
+ j = Nokogiri::XML::Node.new 'jingle',msg.document
+ j['xmlns'] = 'urn:xmpp:jingle:1'
+ j['action'] = 'session-terminate'
+ j['sid'] = @jingle_sids[cn[0]['sid']]
+ msg.add_child(j)
+
+ r = Nokogiri::XML::Node.new 'reason',msg.document
+ s = Nokogiri::XML::Node.new 'success',msg.document
+ r.add_child(s)
+ j.add_child(r)
+
+ puts 'RESPONSE1: ' + msg.inspect
+ write_to_stream msg
+ end
+
iq '/iq/ns:query', :ns =>
'http://jabber.org/protocol/disco#items' do |i, xpath_result|