Class: Jabber::HTTPBinding::Client

Inherits:
Client show all
Defined in:
lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb

Overview

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.

Constant Summary

Constants inherited from Stream

Stream::CONNECTED, Stream::DISCONNECTED

Instance Attribute Summary collapse

Attributes inherited from Client

#jid

Attributes inherited from Connection

#allow_tls, #features_timeout, #host, #keepalive_interval, #port, #ssl_capath, #ssl_verifycb, #use_ssl

Attributes inherited from Stream

#fd, #status

Instance Method Summary collapse

Methods inherited from Client

#auth, #auth_anonymous, #auth_anonymous_sasl, #auth_nonsasl, #auth_sasl, #password=, #register, #register_info, #remove_registration, #start, #supports_anonymous?

Methods inherited from Connection

#accept_features, #close!, #is_tls?, #start, #starttls

Methods inherited from Stream

#add_iq_callback, #add_message_callback, #add_presence_callback, #add_stanza_callback, #add_xml_callback, #close!, #delete_iq_callback, #delete_message_callback, #delete_presence_callback, #delete_stanza_callback, #delete_xml_callback, #is_connected?, #is_disconnected?, #on_exception, #parse_failure, #parser_end, #receive, #send_with_id, #start, #stop

Constructor Details

#initialize(jid) ⇒ Client

Initialize

jid
JID or String


45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 45

def initialize(jid)
  super

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

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

Instance Attribute Details

#http_content_typeObject

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



34
35
36
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 34

def http_content_type
  @http_content_type
end

#http_holdObject

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



40
41
42
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 40

def http_hold
  @http_hold
end

#http_waitObject

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



37
38
39
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 37

def http_wait
  @http_wait
end

Instance Method Details

#closeObject

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



139
140
141
142
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 139

def close
  @status = DISCONNECTED
  send(Jabber::Presence.new.set_type(:unavailable))
end

#connect(uri, host = nil, port = 5222) ⇒ Object

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 67

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 = Mutex.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_requestObject

Ensure that there is one pending request

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



128
129
130
131
132
133
134
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 128

def ensure_one_pending_request
  return if is_disconnected?

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

#send(xml, &block) ⇒ Object

Send a stanza, additionally with block

This method ensures a ‘jabber:client’ namespace for the stanza



115
116
117
118
119
120
121
# File 'lib/vendor/xmpp4r/lib/xmpp4r/httpbinding/client.rb', line 115

def send(xml, &block)
  if xml.kind_of? REXML::Element
    xml.add_namespace('jabber:client')
  end

  super
end