Class: Jabber::Bytestreams::IBB
- Inherits:
-
Object
- Object
- Jabber::Bytestreams::IBB
- Defined in:
- lib/xmpp4r/bytestreams/helper/ibb/base.rb
Overview
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.
Direct Known Subclasses
Constant Summary collapse
- NS_IBB =
'http://jabber.org/protocol/ibb'
Instance Method Summary collapse
- #active? ⇒ Boolean
-
#close ⇒ Object
Close the stream.
-
#flush ⇒ Object
Empty the send-buffer by sending remaining data.
-
#initialize(stream, session_id, my_jid, peer_jid) ⇒ IBB
constructor
Create a new bytestream.
-
#read ⇒ Object
Receive data.
-
#write(buf) ⇒ Object
Send data.
Constructor Details
#initialize(stream, session_id, my_jid, peer_jid) ⇒ 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
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 30 def initialize(stream, session_id, my_jid, peer_jid) @stream = stream @session_id = session_id @my_jid = (my_jid.kind_of?(String) ? JID.new(my_jid) : my_jid) @peer_jid = (peer_jid.kind_of?(String) ? JID.new(peer_jid) : peer_jid) @active = false @seq_send = 0 @seq_recv = 0 @queue = [] @queue_lock = Mutex.new @pending = Semaphore.new @sendbuf = '' @sendbuf_lock = Mutex.new @block_size = 4096 # Recommended by JEP0047 end |
Instance Method Details
#active? ⇒ Boolean
48 49 50 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 48 def active? @active end |
#close ⇒ Object
Close the stream
Waits for acknowledge from peer, may throw ServerError
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 128 def close if active? flush deactivate iq = Iq.new(:set, @peer_jid) close = iq.add REXML::Element.new('close') close.add_namespace IBB::NS_IBB close.attributes['sid'] = @session_id @stream.send_with_id(iq) end end |
#flush ⇒ Object
Empty the send-buffer by sending remaining data
72 73 74 75 76 77 78 79 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 72 def flush @sendbuf_lock.synchronize { while @sendbuf.size > 0 send_data(@sendbuf[0..@block_size-1]) @sendbuf = @sendbuf[@block_size..-1].to_s end } end |
#read ⇒ Object
Receive data
Will wait until the Message with the next sequence number is in the stanza queue.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 86 def read if active? res = nil while res.nil? @queue_lock.synchronize { @queue.each { |item| # Find next data if item.type == :data and item.seq == @seq_recv.to_s res = item break # No data? Find close elsif item.type == :close and res.nil? res = item end } @queue.delete_if { |item| item == res } } # No data? Wait for next to arrive... @pending.wait unless res end if res.type == :data @seq_recv += 1 @seq_recv = 0 if @seq_recv > 65535 res.data elsif res.type == :close deactivate nil # Closed end else nil end end |
#write(buf) ⇒ Object
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
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/xmpp4r/bytestreams/helper/ibb/base.rb', line 59 def write(buf) @sendbuf_lock.synchronize { @sendbuf += buf while @sendbuf.size >= @block_size send_data(@sendbuf[0..@block_size-1]) @sendbuf = @sendbuf[@block_size..-1].to_s end } end |