Class | Jabber::Bytestreams::IBB |
In: |
lib/xmpp4r/bytestreams/helper/ibb/base.rb
|
Parent: | Object |
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.
NS_IBB | = | 'http://jabber.org/protocol/ibb' |
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
# 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
Close the stream
Waits for acknowledge from peer, may throw ServerError
# 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
# 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.
# 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] |
# 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