| Class | Jabber::Connection |
| In: |
lib/xmpp4r/connection.rb
|
| Parent: | Stream |
The connection class manages the TCP connection to the Jabber server
| 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 |
Create a new connection to the given host and port
# 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
# 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!
# 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
# 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] |
# File lib/xmpp4r/connection.rb, line 182
182: def is_tls?
183: @tls
184: end
Start the parser on the previously connected socket
# 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)
# 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