Class: Jabber::Connection

Inherits:
Stream
  • Object
show all
Defined in:
lib/xmpp4r/connection.rb

Overview

The connection class manages the TCP connection to the Jabber server

Direct Known Subclasses

Client, Component

Constant Summary

Constants inherited from Stream

Stream::CONNECTED, Stream::DISCONNECTED

Instance Attribute Summary collapse

Attributes inherited from Stream

#fd, #status

Instance Method Summary collapse

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, #send_data, #send_with_id, #stop

Constructor Details

#initializeConnection

Create a new connection to the given host and port



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/xmpp4r/connection.rb', line 41

def initialize
  super()
  @host = nil
  @port = nil
  @allow_tls = defined? OpenSSL
  @tls = false
  @ssl_capath = nil
  @ssl_verifycb = nil
  @features_timeout = 10
  @keepalive_interval = 60
  @use_ssl = false
end

Instance Attribute Details

#allow_tlsObject

Allow TLS negotiation? Defaults to true



27
28
29
# File 'lib/xmpp4r/connection.rb', line 27

def allow_tls
  @allow_tls
end

#features_timeoutObject

How many seconds to wait for <stream:features/> before proceeding



20
21
22
# File 'lib/xmpp4r/connection.rb', line 20

def features_timeout
  @features_timeout
end

#hostObject (readonly)

Returns the value of attribute host.



16
17
18
# File 'lib/xmpp4r/connection.rb', line 16

def host
  @host
end

#keepalive_intervalObject

Keep-alive interval in seconds, defaults to 60 (see private method keepalive_loop for implementation details)



24
25
26
# File 'lib/xmpp4r/connection.rb', line 24

def keepalive_interval
  @keepalive_interval
end

#portObject (readonly)

Returns the value of attribute port.



16
17
18
# File 'lib/xmpp4r/connection.rb', line 16

def port
  @port
end

#ssl_capathObject

Optional CA-Path for TLS-handshake



30
31
32
# File 'lib/xmpp4r/connection.rb', line 30

def ssl_capath
  @ssl_capath
end

#ssl_verifycbObject

Optional callback for verification of SSL peer



33
34
35
# File 'lib/xmpp4r/connection.rb', line 33

def ssl_verifycb
  @ssl_verifycb
end

#use_sslObject

whether to use the old and deprecated SSL protocol Defaults to false



37
38
39
# File 'lib/xmpp4r/connection.rb', line 37

def use_ssl
  @use_ssl
end

Instance Method Details

#accept_featuresObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/xmpp4r/connection.rb', line 95

def accept_features
  begin
    Timeout::timeout(@features_timeout) {
      Jabber::debuglog("FEATURES: waiting...")
      @features_sem.wait
      Jabber::debuglog("FEATURES: waiting finished")
    }
  rescue Timeout::Error
    Jabber::debuglog("FEATURES: timed out when waiting, stream peer seems not XMPP compliant")
  end

  if @allow_tls and not is_tls? and @stream_features['starttls'] == 'urn:ietf:params:xml:ns:xmpp-tls'
    begin
      starttls
    rescue
      Jabber::debuglog("STARTTLS:\nFailure: #{$!}")
    end
  end
end

#close!Object

Closing connection: first kill keepaliveThread, then call Stream#close!



90
91
92
93
# File 'lib/xmpp4r/connection.rb', line 90

def close!
  @keepaliveThread.kill if @keepaliveThread and @keepaliveThread.alive?
  super
end

#connect(host, port) ⇒ Object

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



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/xmpp4r/connection.rb', line 59

def connect(host, port)
  @host = host
  @port = port
  # Reset is_tls?, so that it works when reconnecting
  @tls = false

  Jabber::debuglog("CONNECTING:\n#{@host}:#{@port}")
  @socket = TCPSocket.new(@host, @port)

  # We want to use the old and deprecated SSL protocol (usually on port 5223)
  if @use_ssl
    ssl = OpenSSL::SSL::SSLSocket.new(@socket)
    ssl.connect # start SSL session
    ssl.sync_close = true
    Jabber::debuglog("SSL connection established.")
    @socket = ssl
  end

  start

  accept_features

  @keepaliveThread = Thread.new do
    Thread.current.abort_on_exception = true
    keepalive_loop
  end
end

#is_tls?Boolean

Have we gone to TLS mode?

result
true

or [false]

Returns:

  • (Boolean)


181
182
183
# File 'lib/xmpp4r/connection.rb', line 181

def is_tls?
  @tls
end

#startObject

Start the parser on the previously connected socket



117
118
119
# File 'lib/xmpp4r/connection.rb', line 117

def start
  super(@socket)
end

#starttlsObject

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



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/xmpp4r/connection.rb', line 124

def starttls
  stls = REXML::Element.new('starttls')
  stls.add_namespace('urn:ietf:params:xml:ns:xmpp-tls')

  reply = nil
  send(stls) { |r|
    reply = r
    true
  }
  if reply.name != 'proceed'
    raise ServerError(reply.first_element('error'))
  end
  # Don't be interrupted
  stop

  begin
    error = nil

    # Context/user set-able stuff
    ctx = OpenSSL::SSL::SSLContext.new
    if @ssl_capath
      ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
      ctx.ca_path = @ssl_capath
    else
      ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
    end
    ctx.verify_callback = @ssl_verifycb

    # SSL connection establishing
    sslsocket = OpenSSL::SSL::SSLSocket.new(@socket, ctx)
    sslsocket.sync_close = true
    Jabber::debuglog("TLSv1: OpenSSL handshake in progress")
    sslsocket.connect

    # Make REXML believe it's a real socket
    class << sslsocket
      def kind_of?(o)
        o == IO ? true : super
      end
    end

    # We're done and will use it
    @tls = true
    @socket = sslsocket
  rescue
    error = $!
  ensure
    Jabber::debuglog("TLSv1: restarting parser")
    start
    accept_features
    raise error if error
  end
end