Class Jabber::Client
In: lib/xmpp4r/client.rb
Parent: Connection
Message Presence XMPPStanza Iq XMPPElement ErrorResponse X IqQuery JabberError ComponentAuthenticationFailure ArgumentError InvalidChatState SOCKS5Error ServerError NoNameXmlnsRegistered ServerDisconnected ClientAuthenticationFailure Connection Client Component Connection Client Singleton IdGenerator Comparable JID Enumerable CallbackList Items Publish StandardError REXML::Element Stream XMPPElement Location IqFeature StreamHost IqSiFile IqSiFileRange IqSi StreamHostUsed XRosterItem RosterItem C Body HTML UserItem XMUCUserInvite Configuration Retract IqPubSub Item IqPubSubOwner Event Subscription Unsubscribe Tune XDataField XDataReported XDataTitle XDataInstructions Feature Item Identity IqVcard PubSub::ServiceHelper Helper Helper SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IqQuery IqQueryBytestreams IqQueryRoster IqQueryVersion IqQueryRPC IqQueryMUCOwner IqQueryMUCAdmin IqQueryDiscoItems IqQueryDiscoInfo IqQueryLastActivity IBB IBBTarget IBBInitiator RosterXItem XRoster RosterX X XDelay XMUC XMUCUser XData Responder SimpleResponder Iq IqCommand XMLRPC::ParserWriterChooseMixin Client Server XMLRPC::ParseContentType XMLRPC::BasicServer MUCClient SimpleMUCClient MUC::UserItem XMUCUserItem IqQueryMUCAdminItem XParent SubscriptionConfig NodeConfig OwnerNodeConfig EventItems ServiceHelper OAuthServiceHelper NodeHelper EventItem Base Anonymous DigestMD5 Plain FileSource Base Bot Callback StreamParser Semaphore SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Helper Responder Helper Listener MUCBrowser NodeBrowser ListenerMocker Helper Responder Helper Helper Helper lib/xmpp4r/message.rb lib/xmpp4r/connection.rb lib/xmpp4r/xmppstanza.rb lib/xmpp4r/iq.rb lib/xmpp4r/callbacks.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/stream.rb lib/xmpp4r/client.rb lib/xmpp4r/jid.rb lib/xmpp4r/x.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/semaphore.rb lib/xmpp4r/errors.rb lib/xmpp4r/component.rb lib/xmpp4r/presence.rb lib/xmpp4r/xmppelement.rb lib/xmpp4r/query.rb XParent lib/xmpp4r/location/helper/helper.rb lib/xmpp4r/location/location.rb UserLocation lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/bytestreams/iq/si.rb lib/xmpp4r/bytestreams/helper/ibb/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb lib/xmpp4r/bytestreams/iq/bytestreams.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb lib/xmpp4r/bytestreams/helper/ibb/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb lib/xmpp4r/bytestreams/helper/ibb/base.rb Bytestreams lib/xmpp4r/roster/x/roster.rb lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb Roster lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb lib/xmpp4r/version/iq/version.rb Version lib/xmpp4r/command/iq/command.rb lib/xmpp4r/command/helper/responder.rb Command lib/xmpp4r/caps/helper/helper.rb lib/xmpp4r/caps/c.rb Caps lib/xmpp4r/reliable.rb Reliable lib/xmpp4r/delay/x/delay.rb Delay lib/xmpp4r/xhtml/html.rb XHTML lib/xmpp4r/rpc/helper/server.rb lib/xmpp4r/rpc/helper/client.rb lib/xmpp4r/rpc/iq/rpc.rb RPC lib/xmpp4r/muc/iq/mucadminitem.rb lib/xmpp4r/muc/x/muc.rb lib/xmpp4r/muc/item.rb lib/xmpp4r/muc/helper/simplemucclient.rb lib/xmpp4r/muc/iq/mucadmin.rb lib/xmpp4r/muc/helper/mucbrowser.rb lib/xmpp4r/muc/x/mucuseritem.rb lib/xmpp4r/muc/x/mucuserinvite.rb lib/xmpp4r/muc/iq/mucowner.rb lib/xmpp4r/muc/helper/mucclient.rb MUC lib/xmpp4r/pubsub/children/item.rb lib/xmpp4r/pubsub/children/configuration.rb lib/xmpp4r/pubsub/children/subscription.rb lib/xmpp4r/pubsub/helper/servicehelper.rb lib/xmpp4r/pubsub/children/unsubscribe.rb lib/xmpp4r/pubsub/children/publish.rb lib/xmpp4r/pubsub/helper/oauth_service_helper.rb lib/xmpp4r/pubsub/children/event.rb lib/xmpp4r/pubsub/iq/pubsub.rb lib/xmpp4r/pubsub/children/retract.rb lib/xmpp4r/pubsub/helper/nodebrowser.rb lib/xmpp4r/pubsub/helper/nodehelper.rb lib/xmpp4r/pubsub/children/items.rb lib/xmpp4r/pubsub/children/subscription_config.rb lib/xmpp4r/pubsub/children/node_config.rb OAuthPubSubStreamHelper PubSub lib/xmpp4r/httpbinding/client.rb HTTPBinding lib/xmpp4r/tune/helper/helper.rb lib/xmpp4r/tune/tune.rb UserTune lib/xmpp4r/sasl.rb SASL lib/xmpp4r/test/listener_mocker.rb Test lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/discovery/helper/helper.rb lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/helper/responder.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/bytestreams/helper/filetransfer.rb TransferSource FileTransfer lib/xmpp4r/last/helper/helper.rb lib/xmpp4r/last/iq/last.rb LastActivity lib/xmpp4r/framework/base.rb lib/xmpp4r/framework/bot.rb Framework lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber dot/m_110_0.png

The client class provides everything needed to build a basic XMPP Client.

If you want your connection to survive disconnects and timeouts, catch exception in Stream#on_exception and re-call Client#connect and Client#auth. Don‘t forget to re-send initial Presence and everything else you need to setup your session.

Methods

Attributes

jid  [R]  The client‘s JID

Public Class methods

Create a new Client.

Remember to always put a resource in your JID unless the server can do SASL.

[Source]

    # File lib/xmpp4r/client.rb, line 27
27:     def initialize(jid)
28:       super()
29:       @jid = (jid.kind_of?(JID) ? jid : JID.new(jid.to_s))
30:     end

Public Instance methods

Authenticate with the server

Throws ClientAuthenticationFailure

Authentication mechanisms are used in the following preference:

password:[String]

[Source]

     # File lib/xmpp4r/client.rb, line 107
107:     def auth(password)
108:       begin
109:         if @stream_mechanisms.include? 'DIGEST-MD5'
110:           auth_sasl SASL.new(self, 'DIGEST-MD5'), password
111:         elsif @stream_mechanisms.include? 'PLAIN'
112:           auth_sasl SASL.new(self, 'PLAIN'), password
113:         else
114:           auth_nonsasl(password)
115:         end
116:       rescue
117:         Jabber::debuglog("#{$!.class}: #{$!}\n#{$!.backtrace.join("\n")}")
118:         raise ClientAuthenticationFailure.new, $!.to_s
119:       end
120:     end

See Client#auth_anonymous_sasl

[Source]

     # File lib/xmpp4r/client.rb, line 196
196:     def auth_anonymous
197:       auth_anonymous_sasl
198:     end

Shortcut for anonymous connection to server

Throws ClientAuthenticationFailure

[Source]

     # File lib/xmpp4r/client.rb, line 205
205:     def auth_anonymous_sasl
206:       if self.supports_anonymous?
207:         begin
208:           auth_sasl SASL.new(self, 'ANONYMOUS'), ""
209:         rescue
210:           Jabber::debuglog("#{$!.class}: #{$!}\n#{$!.backtrace.join("\n")}")
211:           raise ClientAuthenticationFailure, $!.to_s
212:         end
213:       else
214:         raise ClientAuthenticationFailure, 'Anonymous authentication unsupported'
215:       end
216:     end

Send auth with given password and wait for result (non-SASL)

Throws ServerError

password:[String] the password
digest:[Boolean] use Digest authentication

[Source]

     # File lib/xmpp4r/client.rb, line 234
234:     def auth_nonsasl(password, digest=true)
235:       authset = nil
236:       if digest
237:         authset = Iq.new_authset_digest(@jid, @streamid.to_s, password)
238:       else
239:         authset = Iq.new_authset(@jid, password)
240:       end
241:       send_with_id(authset)
242:       $defout.flush
243: 
244:       true
245:     end

Use a SASL authentication mechanism and bind to a resource

If there was no resource given in the jid, the jid/resource generated by the server will be accepted.

This method should not be used directly. Instead, Client#auth may look for the best mechanism suitable.

sasl:Descendant of [Jabber::SASL::Base]
password:[String]

[Source]

     # File lib/xmpp4r/client.rb, line 170
170:     def auth_sasl(sasl, password)
171:       sasl.auth(password)
172: 
173:       # Restart stream after SASL auth
174:       stop
175:       start
176:       # And wait for features - again
177:       @features_sem.wait
178: 
179:       # Resource binding (RFC3920 - 7)
180:       if @stream_features.has_key? 'bind'
181:         @jid = bind(@jid.resource)
182:       end
183: 
184:       # Session starting
185:       if @stream_features.has_key? 'session'
186:         iq = Iq.new(:set)
187:         session = iq.add REXML::Element.new('session')
188:         session.add_namespace @stream_features['session']
189: 
190:         send_with_id(iq)
191:       end
192:     end

Resource binding (RFC3920bis-06 - section 8.)

XMPP allows to bind to multiple resources

[Source]

     # File lib/xmpp4r/client.rb, line 126
126:     def bind(desired_resource=nil)
127:       iq = Iq.new(:set)
128:       bind = iq.add REXML::Element.new('bind')
129:       bind.add_namespace @stream_features['bind']
130:       if desired_resource
131:         resource = bind.add REXML::Element.new('resource')
132:         resource.text = desired_resource
133:       end
134: 
135:       jid = nil
136:       send_with_id(iq) do |reply|
137:         reply_bind = reply.first_element('bind')
138:         if reply_bind
139:           reported_jid = reply_bind.first_element('jid')
140:           if reported_jid and reported_jid.text
141:             jid = JID.new(reported_jid.text)
142:           end
143:         end
144:       end
145:       jid
146:     end

Close the connection, sends </stream:stream> tag first

[Source]

    # File lib/xmpp4r/client.rb, line 77
77:     def close
78:       if @status == CONNECTED
79:         send("</stream:stream>")
80:       end
81:       super
82:     end

connect to the server (chaining-friendly)

If you omit the optional host argument SRV records for your jid will be resolved. If none works, fallback is connecting to the domain part of the jid.

host:[String] Optional c2s host, will be extracted from jid if nil
use_ssl:[Boolean] Optional. Use (old, deprecated) SSL when connecting.
return:self

[Source]

    # File lib/xmpp4r/client.rb, line 42
42:     def connect(host = nil, port = 5222)
43:       if host.nil?
44:         begin
45:           srv = []
46:           Resolv::DNS.open { |dns|
47:             # If ruby version is too old and SRV is unknown, this will raise a NameError
48:             # which is caught below
49:             Jabber::debuglog("RESOLVING:\n_xmpp-client._tcp.#{@jid.domain} (SRV)")
50:             srv = dns.getresources("_xmpp-client._tcp.#{@jid.domain}", Resolv::DNS::Resource::IN::SRV)
51:           }
52:           # Sort SRV records: lowest priority first, highest weight first
53:           srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
54: 
55:           srv.each { |record|
56:             begin
57:               connect(record.target.to_s, record.port)
58:               # Success
59:               return self
60:             rescue SocketError, Errno::ECONNREFUSED
61:               # Try next SRV record
62:             end
63:           }
64:         rescue NameError
65:           Jabber::debuglog "Resolv::DNS does not support SRV records. Please upgrade to ruby-1.8.3 or later!"
66:         end
67:         # Fallback to normal connect method
68:       end
69: 
70:       super(host.nil? ? jid.domain : host, port)
71:       self
72:     end

Change the client‘s password

Threading is suggested, as this code waits for an answer.

Raises an exception upon error response (ServerError from Stream#send_with_id).

new_password:[String] New password

[Source]

     # File lib/xmpp4r/client.rb, line 334
334:     def password=(new_password)
335:       iq = Iq.new_query(:set, @jid.domain)
336:       iq.query.add_namespace('jabber:iq:register')
337:       iq.query.add(REXML::Element.new('username')).text = @jid.node
338:       iq.query.add(REXML::Element.new('password')).text = new_password
339: 
340:       err = nil
341:       send_with_id(iq)
342:     end

Register a new user account (may be used instead of Client#auth)

This method may raise ServerError if the registration was not successful.

password:String
fields:{String=>String} additional registration information

XEP-0077 Defines the following fields for registration information: www.xmpp.org/extensions/xep-0077.html

‘username’ => ‘Account name associated with the user’ ‘nick’ => ‘Familiar name of the user’ ‘password’ => ‘Password or secret for the user’ ‘name’ => ‘Full name of the user’ ‘first’ => ‘First name or given name of the user’ ‘last’ => ‘Last name, surname, or family name of the user’ ‘email’ => ‘Email address of the user’ ‘address’ => ‘Street portion of a physical or mailing address’ ‘city’ => ‘Locality portion of a physical or mailing address’ ‘state’ => ‘Region portion of a physical or mailing address’ ‘zip’ => ‘Postal code portion of a physical or mailing address’ ‘phone’ => ‘Telephone number of the user’ ‘url’ => ‘URL to web page describing the user’ ‘date’ => ‘Some date (e.g., birth date, hire date, sign-up date)’

[Source]

     # File lib/xmpp4r/client.rb, line 303
303:     def register(password, fields={})
304:       reg = Iq.new_register(jid.node, password)
305:       reg.to = jid.domain
306:       fields.each { |name,value|
307:         reg.query.add(REXML::Element.new(name)).text = value
308:       }
309: 
310:       send_with_id(reg)
311:     end

Get instructions and available fields for registration

return:[instructions, fields] Where instructions is a String and fields is an Array of Strings

[Source]

     # File lib/xmpp4r/client.rb, line 250
250:     def register_info
251:       instructions = nil
252:       fields = []
253: 
254:       reg = Iq.new_registerget
255:       reg.to = jid.domain
256:       send_with_id(reg) do |answer|
257:         if answer.query
258:           answer.query.each_element { |e|
259:             if e.namespace == 'jabber:iq:register'
260:               if e.name == 'instructions'
261:                 instructions = e.text.strip
262:               else
263:                 fields << e.name
264:               end
265:             end
266:           }
267:         end
268: 
269:         true
270:       end
271: 
272:       [instructions, fields]
273:     end

Remove the registration of a user account

*WARNING:* this deletes your roster and everything else stored on the server!

[Source]

     # File lib/xmpp4r/client.rb, line 318
318:     def remove_registration
319:       reg = Iq.new_register
320:       reg.to = jid.domain
321:       reg.query.add(REXML::Element.new('remove'))
322:       send_with_id(reg)
323:     end

Start the stream-parser and send the client-specific stream opening element

[Source]

    # File lib/xmpp4r/client.rb, line 86
86:     def start
87:       super
88:       send(generate_stream_start(@jid.domain)) { |e|
89:         if e.name == 'stream'
90:           true
91:         else
92:           false
93:         end
94:       }
95:     end

Reports whether or not anonymous authentication is reported by the client.

Returns true or false

[Source]

     # File lib/xmpp4r/client.rb, line 223
223:     def supports_anonymous?
224:       @stream_mechanisms.include? 'ANONYMOUS'
225:     end

Resource unbinding (RFC3920bis-06 - section 8.6.3.)

[Source]

     # File lib/xmpp4r/client.rb, line 150
150:     def unbind(desired_resource)
151:       iq = Iq.new(:set)
152:       unbind = iq.add REXML::Element.new('unbind')
153:       unbind.add_namespace @stream_features['unbind']
154:       resource = unbind.add REXML::Element.new('resource')
155:       resource.text = desired_resource
156: 
157:       send_with_id(iq)
158:     end

[Validate]