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(host, port = 5222) ⇒ Connection

Returns a new instance of Connection.



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

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

  @handlers, @filters = {}, {}

  @poll_counter = 10
  @mutex = Mutex.new

  @status = DISCONNECTED
end

Instance Attribute Details

#filtersObject (readonly)

Internal



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

def filters
  @filters
end

#handlersObject (readonly)

Internal



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

def handlers
  @handlers
end

#hostObject (readonly)

Public



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

def host
  @host
end

#inputObject (readonly)

Public



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

def input
  @input
end

#outputObject (readonly)

Public



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

def output
  @output
end

#parserObject (readonly)

Internal



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

def parser
  @parser
end

#parser_threadObject (readonly)

Internal



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

def parser_thread
  @parser_thread
end

#poll_threadObject (readonly)

Internal



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

def poll_thread
  @poll_thread
end

#portObject (readonly)

Public



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

def port
  @port
end

#socketObject (readonly)

Internal



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

def socket
  @socket
end

#statusObject (readonly)

Public



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

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)


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

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



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

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



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

def connect
  @socket = TCPSocket.new(@host, @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)


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

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



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

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



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

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)


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

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.



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

def on_connection_exception(&block)
  @exception_block = block
end

#parse_failure(exception = nil) ⇒ Object



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

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.



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

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



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

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



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

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

#register_parsing_threadObject

Internal: Register new parser thread

Returns nothing



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

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

#register_polling_threadObject

Internal: Register new polling thread

Returns nothing



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

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



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

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



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

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)


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

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



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

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