class Jabber::HTTPBinding::Client

This class implements an alternative Client using HTTP Binding (JEP0124).

This class is designed to be a drop-in replacement for Jabber::Client, except for the Jabber::HTTP::Client#connect method which takes an URI as argument.

HTTP requests are buffered to not exceed the negotiated 'polling' and 'requests' parameters.

Stanzas in HTTP resonses may be delayed to arrive in the order defined by 'rid' parameters.

Debugging

Turning Jabber.debug to true will make debug output not only spit out stanzas but HTTP request/response bodies, too.

Attributes

http_content_type[RW]

Content-Type to be used for communication (you can set this to "text/html")

http_hold[RW]

The server may hold this amount of stanzas to reduce number of HTTP requests

http_wait[RW]

The server should wait this value seconds if there is no stanza to be received

Public Class Methods

new(jid) click to toggle source

Initialize

jid
JID or String
# File lib/xmpp4r/httpbinding/client.rb, line 47
def initialize(jid)
  super

  @lock = Mutex.new
  @pending_requests = 0
  @last_send = Time.at(0)
  @send_buffer = ''

  @http_requests = 1
  @http_wait = 20
  @http_hold = 1
  @http_content_type = 'text/xml; charset=utf-8'
end

Public Instance Methods

close() click to toggle source

Close the session by sending <presence type='unavailable'/>

# File lib/xmpp4r/httpbinding/client.rb, line 129
def close
  @status = DISCONNECTED
  send(Jabber::Presence.new.set_type(:unavailable))
end
connect(uri, host=nil, port=5222) click to toggle source

Set up the stream using uri as the HTTP Binding URI

You may optionally pass host and port parameters to make use of the JEP0124 'route' feature.

uri
URI::Generic or String
host
String

Optional host to route to

port
Fixnum

Port for route feature

# File lib/xmpp4r/httpbinding/client.rb, line 70
def connect(uri, host=nil, port=5222)
  uri = URI::parse(uri) unless uri.kind_of? URI::Generic
  @uri = uri

  @allow_tls = false  # Shall be done at HTTP level
  @stream_mechanisms = []
  @stream_features = {}
  @http_rid = IdGenerator.generate_id.to_i
  @pending_rid = @http_rid
  @pending_rid_lock = Semaphore.new

  req_body = REXML::Element.new('body')
  req_body.attributes['rid'] = @http_rid
  req_body.attributes['content'] = @http_content_type
  req_body.attributes['hold'] = @http_hold.to_s
  req_body.attributes['wait'] = @http_wait.to_s
  req_body.attributes['to'] = @jid.domain
  if host
    req_body.attributes['route'] = "xmpp:#{host}:#{port}"
  end
  req_body.attributes['secure'] = 'true'
  req_body.attributes['xmlns'] = 'http://jabber.org/protocol/httpbind'
  res_body = post(req_body)
  unless res_body.name == 'body'
    raise 'Response body is no <body/> element'
  end

  @streamid = res_body.attributes['authid']
  @status = CONNECTED
  @http_sid = res_body.attributes['sid']
  @http_wait = res_body.attributes['wait'].to_i if res_body.attributes['wait']
  @http_hold = res_body.attributes['hold'].to_i if res_body.attributes['hold']
  @http_inactivity = res_body.attributes['inactivity'].to_i
  @http_polling = res_body.attributes['polling'].to_i
  @http_polling = 5 if @http_polling == 0
  @http_requests = res_body.attributes['requests'].to_i
  @http_requests = 1 if @http_requests == 0

  receive_elements_with_rid(@http_rid, res_body.children)

  @features_sem.run
end
ensure_one_pending_request() click to toggle source

Ensure that there is one pending request

Will be automatically called if you've sent a stanza.

# File lib/xmpp4r/httpbinding/client.rb, line 118
def ensure_one_pending_request
  return if is_disconnected?

  if @lock.synchronize { @pending_requests } < 1
    send_data('')
  end
end