Class Jabber::Connection
In: lib/xmpp4r/connection.rb
Parent: Stream

The connection class manages the TCP connection to the Jabber server

Methods

accept_features   close!   connect   is_tls?   new   start   starttls  

Attributes

allow_tls  [RW]  Allow TLS negotiation? Defaults to true
features_timeout  [RW]  How many seconds to wait for <stream:features/> before proceeding
host  [R] 
keepalive_interval  [RW]  Keep-alive interval in seconds, defaults to 60 (see private method keepalive_loop for implementation details)
port  [R] 
ssl_capath  [RW]  Optional CA-Path for TLS-handshake
ssl_verifycb  [RW]  Optional callback for verification of SSL peer
use_ssl  [RW]  whether to use the old and deprecated SSL protocol Defaults to false

Public Class methods

Create a new connection to the given host and port

[Source]

    # File lib/xmpp4r/connection.rb, line 41
41:     def initialize
42:       super()
43:       @host = nil
44:       @port = nil
45:       @allow_tls = defined? OpenSSL
46:       @tls = false
47:       @ssl_capath = nil
48:       @ssl_verifycb = nil
49:       @features_timeout = 10
50:       @keepalive_interval = 60
51:       @use_ssl = false
52:     end

Public Instance methods

[Source]

     # File lib/xmpp4r/connection.rb, line 96
 96:     def accept_features
 97:       begin
 98:         Timeout::timeout(@features_timeout) {
 99:           Jabber::debuglog("FEATURES: waiting...")
100:           @features_sem.wait
101:           Jabber::debuglog("FEATURES: waiting finished")
102:         }
103:       rescue Timeout::Error
104:         Jabber::debuglog("FEATURES: timed out when waiting, stream peer seems not XMPP compliant")
105:       end
106: 
107:       if @allow_tls and not is_tls? and @stream_features['starttls'] == 'urn:ietf:params:xml:ns:xmpp-tls'
108:         begin
109:           starttls
110:         rescue
111:           Jabber::debuglog("STARTTLS:\nFailure: #{$!}")
112:         end
113:       end
114:     end

Closing connection: first kill keepaliveThread (but only if it‘s not me), then call Stream#close!

[Source]

    # File lib/xmpp4r/connection.rb, line 90
90:     def close!
91:       @keepaliveThread.kill if @keepaliveThread and @keepaliveThread.alive? and @keepaliveThread != Thread.current
92:       super
93:       @keepaliveThread.kill if @keepaliveThread and @keepaliveThread.alive?
94:     end

Connect to the Jabber server through a TCP Socket, start the Jabber parser, invoke to accept_features to wait for TLS, start the keep-alive thread

[Source]

    # File lib/xmpp4r/connection.rb, line 59
59:     def connect(host, port)
60:       @host = host
61:       @port = port
62:       # Reset is_tls?, so that it works when reconnecting
63:       @tls = false
64: 
65:       Jabber::debuglog("CONNECTING:\n#{@host}:#{@port}")
66:       @socket = TCPSocket.new(@host, @port)
67: 
68:       # We want to use the old and deprecated SSL protocol (usually on port 5223)
69:       if @use_ssl
70:         ssl = OpenSSL::SSL::SSLSocket.new(@socket)
71:         ssl.connect # start SSL session
72:         ssl.sync_close = true
73:         Jabber::debuglog("SSL connection established.")
74:         @socket = ssl
75:       end
76: 
77:       start
78: 
79:       accept_features
80: 
81:       @keepaliveThread = Thread.new do
82:         Thread.current.abort_on_exception = true
83:         keepalive_loop
84:       end
85:     end

Have we gone to TLS mode?

result:[true] or [false]

[Source]

     # File lib/xmpp4r/connection.rb, line 182
182:     def is_tls?
183:       @tls
184:     end

Start the parser on the previously connected socket

[Source]

     # File lib/xmpp4r/connection.rb, line 118
118:     def start
119:       super(@socket)
120:     end

Do a <starttls/> (will be automatically done by connect if stream peer supports this)

[Source]

     # File lib/xmpp4r/connection.rb, line 125
125:     def starttls
126:       stls = REXML::Element.new('starttls')
127:       stls.add_namespace('urn:ietf:params:xml:ns:xmpp-tls')
128: 
129:       reply = nil
130:       send(stls) { |r|
131:         reply = r
132:         true
133:       }
134:       if reply.name != 'proceed'
135:         raise ServerError.new(reply.first_element('error'))
136:       end
137:       # Don't be interrupted
138:       stop
139: 
140:       begin
141:         error = nil
142: 
143:         # Context/user set-able stuff
144:         ctx = OpenSSL::SSL::SSLContext.new
145:         if @ssl_capath
146:           ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
147:           ctx.ca_path = @ssl_capath
148:         else
149:           ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
150:         end
151:         ctx.verify_callback = @ssl_verifycb
152: 
153:         # SSL connection establishing
154:         sslsocket = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
155:         sslsocket.sync_close = true
156:         Jabber::debuglog("TLSv1: OpenSSL handshake in progress")
157:         sslsocket.connect
158: 
159:         # Make REXML believe it's a real socket
160:         class << sslsocket
161:           def kind_of?(o)
162:             o == IO ? true : super
163:           end
164:         end
165: 
166:         # We're done and will use it
167:         @tls = true
168:         @socket = sslsocket
169:       rescue
170:         error = $!
171:       ensure
172:         Jabber::debuglog("TLSv1: restarting parser")
173:         start
174:         accept_features
175:         raise error if error
176:       end
177:     end

[Validate]