Class: Jabber::Connection

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

Overview

The connection class encapsulates the connection to the Jabber service including managing the socket and controlling the parsing of the Jabber XML stream.

Constant Summary collapse

DISCONNECTED =
1
CONNECTED =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(domain, port = 5222) ⇒ Connection

Returns a new instance of Connection.



28
29
30
31
32
33
34
35
36
37
# File 'lib/jabber4r/connection.rb', line 28

def initialize(domain, port = 5222)
  @domain, @port = domain, port

  @handlers, @filters = {}, {}

  @poll_counter = 10
  @mutex = Mutex.new

  @status = DISCONNECTED
end

Instance Attribute Details

#domainObject (readonly)

Public



17
18
19
# File 'lib/jabber4r/connection.rb', line 17

def domain
  @domain
end

#filtersObject (readonly)

Internal



23
24
25
# File 'lib/jabber4r/connection.rb', line 23

def filters
  @filters
end

#handlersObject (readonly)

Internal



23
24
25
# File 'lib/jabber4r/connection.rb', line 23

def handlers
  @handlers
end

#inputObject (readonly)

Public



17
18
19
# File 'lib/jabber4r/connection.rb', line 17

def input
  @input
end

#outputObject (readonly)

Public



17
18
19
# File 'lib/jabber4r/connection.rb', line 17

def output
  @output
end

#parserObject (readonly)

Internal



26
27
28
# File 'lib/jabber4r/connection.rb', line 26

def parser
  @parser
end

#parser_threadObject (readonly)

Internal



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

def parser_thread
  @parser_thread
end

#poll_threadObject (readonly)

Internal



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

def poll_thread
  @poll_thread
end

#portObject (readonly)

Public



17
18
19
# File 'lib/jabber4r/connection.rb', line 17

def port
  @port
end

#socketObject (readonly)

Internal



26
27
28
# File 'lib/jabber4r/connection.rb', line 26

def socket
  @socket
end

#statusObject (readonly)

Public



17
18
19
# File 'lib/jabber4r/connection.rb', line 17

def status
  @status
end

Instance Method Details

#add_filter(name, &block) ⇒ Object

Public: Adds a filter block to process received XML messages

name - String the name of filter block - Block of code

Returns nothing

Raises:

  • (ArgumentError)


99
100
101
102
103
# File 'lib/jabber4r/connection.rb', line 99

def add_filter(name, &block)
  raise ArgumentError, "Expected block to be given" if block.nil?

  @filters[name] = block
end

#closeObject Also known as: disconnect

Public: Closes the connection to the Jabber service

Returns nothing



70
71
72
73
74
75
76
# File 'lib/jabber4r/connection.rb', line 70

def close
  parser_thread.kill if parser_thread # why if?
  poll_thread.kill
  socket.close if socket

  @status = DISCONNECTED
end

#connectObject

Public: Connects to the Jabber server through a TCP Socket and starts the Jabber parser.

Returns nothing



43
44
45
46
47
48
49
50
51
# File 'lib/jabber4r/connection.rb', line 43

def connect
  @socket = TCPSocket.new(@domain, @port)
  @parser = Jabber::Protocol.Parser.new(socket, self)

  register_parsing_thread
  register_polling_thread

  @status = CONNECTED
end

#connected?Boolean

Public: Returns if this connection is connected to a Jabber service

Returns boolean

Returns:

  • (Boolean)


82
83
84
# File 'lib/jabber4r/connection.rb', line 82

def connected?
  status == CONNECTED
end

#consume_xml_by_filters(xml) ⇒ Object

Internal: Processes a received ParsedXMLElement by filters

xml - ParsedXMLElement The received element

Returns boolean



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/jabber4r/connection.rb', line 200

def consume_xml_by_filters(xml)
  filters.each_value do |block|
    begin
      block.call(xml)

      return true if xml.element_consumed?
    rescue Exception => error
      puts error.to_s
      puts error.backtrace.join("\n")
    end
  end

  false
end

#consume_xml_by_handlers(xml) ⇒ Object

Internal: Processes a received ParsedXMLElement by handlers

xml - ParsedXMLElement The received element

Returns boolean



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/jabber4r/connection.rb', line 175

def consume_xml_by_handlers(xml)
  handlers.each do |thread, block|
    begin
      block.call(xml)

      if xml.element_consumed?
        handlers.delete(thread)
        thread.wakeup if thread.alive?

        return true
      end
    rescue Exception => error
      puts error.to_s
      puts error.backtrace.join("\n")
    end
  end

  false
end

#disconnected?Boolean

Public: Returns if this connection is NOT connected to a Jabber service

Returns boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/jabber4r/connection.rb', line 89

def disconnected?
  status == DISCONNECTED
end

#on_connection_exception(&block) ⇒ Object

Mounts a block to handle exceptions if they occur during the poll send. This will likely be the first indication that the socket dropped in a Jabber Session.



227
228
229
# File 'lib/jabber4r/connection.rb', line 227

def on_connection_exception(&block)
  @exception_block = block
end

#parse_failure(exception = nil) ⇒ Object



231
232
233
# File 'lib/jabber4r/connection.rb', line 231

def parse_failure(exception = nil)
  Thread.new { @exception_block.call(exception) if @exception_block }
end

#pollObject

Starts a polling thread to send “keep alive” data to prevent the Jabber connection from closing for inactivity.



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/jabber4r/connection.rb', line 243

def poll
  sleep 10
  while true
    sleep 2
    @poll_counter = @poll_counter - 1
    if @poll_counter < 0
      begin
        send("  \t  ")
      rescue
        Thread.new {@exception_block.call if @exception_block}
        break
      end
    end
  end
end

#process_xml_from_socket(xml) ⇒ Object

Internal: Processes a received ParsedXMLElement and executes registered handlers and filters against it

xml - ParsedXMLElement The received element

Returns nothing



162
163
164
165
166
167
168
# File 'lib/jabber4r/connection.rb', line 162

def process_xml_from_socket(xml)
  sleep 0.1 while wait_for_consume?

  Jabber.debug("RECEIVED:\n#{xml}")

  consume_xml_by_handlers(xml) || consume_xml_by_filters(xml)
end

#receive(xml) ⇒ Object

Public: Receiving xml element, and processing it NOTE: Synchonized by Mutex

xml_element - ParsedXMLElement the received from socket xml element

Returns nothing



132
133
134
# File 'lib/jabber4r/connection.rb', line 132

def receive(xml)
  @mutex.synchronize { process_xml_from_socket(xml) }
end

#register_parsing_threadObject

Internal: Register new parser thread

Returns nothing



56
57
58
# File 'lib/jabber4r/connection.rb', line 56

def register_parsing_thread
  @parser_thread = Thread.new { parser.parse }
end

#register_polling_threadObject

Internal: Register new polling thread

Returns nothing



63
64
65
# File 'lib/jabber4r/connection.rb', line 63

def register_polling_thread
  @poll_thread = Thread.new { poll }
end

#remove_filter(name) ⇒ Object

Public: Removes a filter block

name - String the name of filter

Returns Block of code



110
111
112
# File 'lib/jabber4r/connection.rb', line 110

def remove_filter(name)
  filters.delete(name)
end

#send(xml, proc_object = nil, &block) ⇒ Object

Public: Receiving xml element, and processing it NOTE: Synchonized by Mutex

xml - String the string containing xml proc_object - Proc the proc object to call (default: nil) block - Block of ruby code

Returns nothing



122
123
124
# File 'lib/jabber4r/connection.rb', line 122

def send(xml, proc_object = nil, &block)
  @mutex.synchronize { write_to_socket(xml, proc_object, &block) }
end

#wait_for_consume?Boolean

Internal: Should we wait for next part of socket data

Returns boolean

Returns:

  • (Boolean)


218
219
220
# File 'lib/jabber4r/connection.rb', line 218

def wait_for_consume?
  handlers.size.zero? && filters.size.zero?
end

#write_to_socket(xml, handler = nil, &block) ⇒ Object

Internal: Sends XML data to the socket and (optionally) waits to process received data. NOTE: If both habdler and block are given, handler has higher proirity

xml - String the xml data to send handler - [Proc|Lambda|#call] the proc object or labda to handle response data (optional) block - Block the block of ruby code (optional)

Returns nothing



145
146
147
148
149
150
151
152
153
154
# File 'lib/jabber4r/connection.rb', line 145

def write_to_socket(xml, handler = nil, &block)
  Jabber.debug("SENDING:\n#{xml}")

  handler = block if handler.nil?
  handlers[Thread.current] = handler unless handler.nil?

  socket.write(xml)

  @poll_counter = 10
end