Parent

Class/Module Index [+]

Quicksearch

Jabber::Bytestreams::IBB

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.

Constants

NS_IBB

Public Class Methods

new(stream, session_id, my_jid, peer_jid) click to toggle source

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
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

Public Instance Methods

active?() click to toggle source
# File lib/xmpp4r/bytestreams/helper/ibb/base.rb, line 48
def active?
  @active
end
close() click to toggle source

Close the stream

Waits for acknowledge from peer, may throw ServerError

# 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() click to toggle source

Empty the send-buffer by sending remaining data

# 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() click to toggle source

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
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) click to toggle source

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
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

[Validate]

Generated with the Darkfish Rdoc Generator 2.