Class Jabber::Bytestreams::IBB
In: lib/xmpp4r/bytestreams/helper/ibb/base.rb
Parent: Object
XMPPElement ErrorResponse XMPPStanza X IqQuery Message Presence Iq JabberError ComponentAuthenticationFailure ArgumentError SOCKS5Error ServerError NoNameXmlnsRegistered ClientAuthenticationFailure Connection Client Component Client Singleton IdGenerator Comparable JID StandardError REXML::Element Stream IqQuery IqQueryRoster IqQueryBytestreams IqQueryVersion IqQueryRPC IqQueryMUCOwner IqQueryMUCAdmin IqQueryDiscoItems IqQueryDiscoInfo XRosterItem RosterXItem XMPPElement RosterItem StreamHost IqSiFile IqSiFileRange IqSi StreamHostUsed IqFeature C Body HTML UserItem XMUCUserInvite Configuration Items Item IqPubSub Publish Event IqPubSubOwner Subscription Unsubscribe Tune XDataField XDataReported XDataTitle XDataInstructions Feature Item Identity IqVcard XRoster RosterX X XMUC XMUCUser XDelay XData Iq IqCommand SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IBB IBBTarget IBBInitiator Responder SimpleResponder XMLRPC::ParserWriterChooseMixin Client Server XMLRPC::ParseContentType XMLRPC::BasicServer MUCClient SimpleMUCClient MUC::UserItem XMUCUserItem IqQueryMUCAdminItem XParent SubscriptionConfig NodeConfig OwnerNodeConfig EventItems EventItem ServiceHelper NodeHelper Base Anonymous DigestMD5 Plain PubSub::ServiceHelper Helper FileSource Base Bot CallbackList Callback StreamParser Semaphore Helper Responder SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Helper MUCBrowser NodeBrowser Helper Responder Helper lib/xmpp4r/message.rb lib/xmpp4r/connection.rb lib/xmpp4r/xmppstanza.rb lib/xmpp4r/iq.rb lib/xmpp4r/callbacks.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/stream.rb lib/xmpp4r/client.rb lib/xmpp4r/jid.rb lib/xmpp4r/x.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/semaphore.rb lib/xmpp4r/errors.rb lib/xmpp4r/component.rb lib/xmpp4r/presence.rb lib/xmpp4r/xmppelement.rb lib/xmpp4r/query.rb lib/xmpp4r/roster/x/roster.rb lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb Roster lib/xmpp4r/command/iq/command.rb lib/xmpp4r/command/helper/responder.rb Command XParent lib/xmpp4r/bytestreams/iq/si.rb lib/xmpp4r/bytestreams/helper/ibb/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb lib/xmpp4r/bytestreams/iq/bytestreams.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb lib/xmpp4r/bytestreams/helper/ibb/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb lib/xmpp4r/bytestreams/helper/ibb/base.rb Bytestreams lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb lib/xmpp4r/version/iq/version.rb Version lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/caps/helper/helper.rb lib/xmpp4r/caps/c.rb Caps lib/xmpp4r/rpc/helper/server.rb lib/xmpp4r/rpc/helper/client.rb lib/xmpp4r/rpc/iq/rpc.rb RPC lib/xmpp4r/xhtml/html.rb XHTML lib/xmpp4r/muc/iq/mucadminitem.rb lib/xmpp4r/muc/x/muc.rb lib/xmpp4r/muc/item.rb lib/xmpp4r/muc/helper/simplemucclient.rb lib/xmpp4r/muc/iq/mucadmin.rb lib/xmpp4r/muc/helper/mucbrowser.rb lib/xmpp4r/muc/x/mucuseritem.rb lib/xmpp4r/muc/x/mucuserinvite.rb lib/xmpp4r/muc/iq/mucowner.rb lib/xmpp4r/muc/helper/mucclient.rb MUC lib/xmpp4r/delay/x/delay.rb Delay lib/xmpp4r/pubsub/children/item.rb lib/xmpp4r/pubsub/children/configuration.rb lib/xmpp4r/pubsub/children/subscription.rb lib/xmpp4r/pubsub/helper/servicehelper.rb lib/xmpp4r/pubsub/children/unsubscribe.rb lib/xmpp4r/pubsub/children/publish.rb lib/xmpp4r/pubsub/children/event.rb lib/xmpp4r/pubsub/iq/pubsub.rb lib/xmpp4r/pubsub/helper/nodebrowser.rb lib/xmpp4r/pubsub/helper/nodehelper.rb lib/xmpp4r/pubsub/children/items.rb lib/xmpp4r/pubsub/children/subscription_config.rb lib/xmpp4r/pubsub/children/node_config.rb PubSub lib/xmpp4r/sasl.rb SASL lib/xmpp4r/httpbinding/client.rb HTTPBinding lib/xmpp4r/tune/helper/helper.rb lib/xmpp4r/tune/tune.rb UserTune lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/bytestreams/helper/filetransfer.rb TransferSource FileTransfer lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/helper/responder.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/framework/base.rb lib/xmpp4r/framework/bot.rb Framework lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber dot/m_99_0.png

In-Band Bytestreams (JEP-0047) implementation

Don‘t use directly, use IBBInitiator and IBBTarget

In-Band Bytestreams should only be used when transferring very small amounts of binary data, because it is slow and increases server load drastically.

Note that the constructor takes a lot of arguments. In-Band Bytestreams do not specify a way to initiate the stream, this should be done via Stream Initiation.

Methods

activate   active?   close   deactivate   flush   new   read   send_data   write  

Constants

NS_IBB = 'http://jabber.org/protocol/ibb'

Public Class methods

Create a new bytestream

Will register a <message/> callback to intercept data of this stream. This data will be buffered, you can retrieve it with receive

[Source]

    # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 30
30:       def initialize(stream, session_id, my_jid, peer_jid)
31:         @stream = stream
32:         @session_id = session_id
33:         @my_jid = (my_jid.kind_of?(String) ? JID.new(my_jid) : my_jid)
34:         @peer_jid = (peer_jid.kind_of?(String) ? JID.new(peer_jid) : peer_jid)
35: 
36:         @active = false
37:         @seq_send = 0
38:         @seq_recv = 0
39:         @queue = []
40:         @queue_lock = Mutex.new
41:         @pending = Semaphore.new
42:         @sendbuf = ''
43:         @sendbuf_lock = Mutex.new
44: 
45:         @block_size = 4096  # Recommended by JEP0047
46:       end

Public Instance methods

[Source]

    # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 48
48:       def active?
49:         @active
50:       end

Close the stream

Waits for acknowledge from peer, may throw ServerError

[Source]

     # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 128
128:       def close
129:         if active?
130:           flush
131:           deactivate
132: 
133:           iq = Iq.new(:set, @peer_jid)
134:           close = iq.add REXML::Element.new('close')
135:           close.add_namespace IBB::NS_IBB
136:           close.attributes['sid'] = @session_id
137: 
138:           @stream.send_with_id(iq)
139:         end
140:       end

Empty the send-buffer by sending remaining data

[Source]

    # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 72
72:       def flush
73:         @sendbuf_lock.synchronize {
74:           while @sendbuf.size > 0
75:             send_data(@sendbuf[0..@block_size-1])
76:             @sendbuf = @sendbuf[@block_size..-1].to_s
77:           end
78:         }
79:       end

Receive data

Will wait until the Message with the next sequence number is in the stanza queue.

[Source]

     # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 86
 86:       def read
 87:         if active?
 88:           res = nil
 89: 
 90:           while res.nil?
 91:             @queue_lock.synchronize {
 92:               @queue.each { |item|
 93:                 # Find next data
 94:                 if item.type == :data and item.seq == @seq_recv.to_s
 95:                   res = item
 96:                   break
 97:                 # No data? Find close
 98:                 elsif item.type == :close and res.nil?
 99:                   res = item
100:                 end
101:               }
102: 
103:               @queue.delete_if { |item| item == res }
104:             }
105: 
106:             # No data? Wait for next to arrive...
107:             @pending.wait unless res
108:           end
109: 
110:           if res.type == :data
111:             @seq_recv += 1
112:             @seq_recv = 0 if @seq_recv > 65535
113:             res.data
114:           elsif res.type == :close
115:             deactivate
116:             nil # Closed
117:           end
118:         else
119:           nil
120:         end
121:       end

Send data

Data is buffered to match block_size in each packet. If you need the data to be sent immediately, use flush afterwards.

buf:[String]

[Source]

    # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 59
59:       def write(buf)
60:         @sendbuf_lock.synchronize {
61:           @sendbuf += buf
62: 
63:           while @sendbuf.size >= @block_size
64:             send_data(@sendbuf[0..@block_size-1])
65:             @sendbuf = @sendbuf[@block_size..-1].to_s
66:           end
67:         }
68:       end

Private Instance methods

[Source]

     # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 180
180:       def activate
181:         unless active?
182:           @stream.add_message_callback(200, self) { |msg|
183:             data = msg.first_element('data')
184:             if msg.from == @peer_jid and msg.to == @my_jid and data and data.attributes['sid'] == @session_id
185:               if msg.type == nil
186:                 @queue_lock.synchronize {
187:                   @queue.push IBBQueueItem.new(:data, data.attributes['seq'], data.text.to_s)
188:                   @pending.run
189:                 }
190:               elsif msg.type == :error
191:                 @queue_lock.synchronize {
192:                   @queue << IBBQueueItem.new(:close)
193:                   @pending.run
194:                 }
195:               end
196:               true
197:             else
198:               false
199:             end
200:           }
201: 
202:           @stream.add_iq_callback(200, self) { |iq|
203:             close = iq.first_element('close')
204:             if iq.type == :set and close and close.attributes['sid'] == @session_id
205:               answer = iq.answer(false)
206:               answer.type = :result
207:               @stream.send(answer)
208: 
209:               @queue_lock.synchronize {
210:                 @queue << IBBQueueItem.new(:close)
211:                 @pending.run
212:               }
213:               true
214:             else
215:               false
216:             end
217:           }
218: 
219:           @active = true
220:         end
221:       end

[Source]

     # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 223
223:       def deactivate
224:         if active?
225:           @stream.delete_message_callback(self)
226:           @stream.delete_iq_callback(self)
227: 
228:           @active = false
229:         end
230:       end

Send data directly

data:[String]

[Source]

     # File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 147
147:       def send_data(databuf)
148:         if active?
149:           msg = Message.new
150:           msg.from = @my_jid
151:           msg.to = @peer_jid
152: 
153:           data = msg.add REXML::Element.new('data')
154:           data.add_namespace NS_IBB
155:           data.attributes['sid'] = @session_id
156:           data.attributes['seq'] = @seq_send.to_s
157:           data.text = Base64::encode64(databuf)
158: 
159:           # TODO: Implement AMP correctly
160:           amp = msg.add REXML::Element.new('amp')
161:           amp.add_namespace 'http://jabber.org/protocol/amp'
162:           deliver_at = amp.add REXML::Element.new('rule')
163:           deliver_at.attributes['condition'] = 'deliver-at'
164:           deliver_at.attributes['value'] = 'stored'
165:           deliver_at.attributes['action'] = 'error'
166:           match_resource = amp.add REXML::Element.new('rule')
167:           match_resource.attributes['condition'] = 'match-resource'
168:           match_resource.attributes['value'] = 'exact'
169:           match_resource.attributes['action'] = 'error'
170: 
171:           @stream.send(msg)
172: 
173:           @seq_send += 1
174:           @seq_send = 0 if @seq_send > 65535
175:         else
176:           raise 'Attempt to send data when not activated'
177:         end
178:       end

[Validate]