Class: XMPPSimple::Client

Inherits:
Object
  • Object
show all
Includes:
Celluloid::IO
Defined in:
lib/xmpp_simple/client.rb

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ Client

Returns a new instance of Client.



6
7
8
9
10
11
12
13
14
15
# File 'lib/xmpp_simple/client.rb', line 6

def initialize(params = {})
  unless [:username, :password, :host, :port].all? { |s| params.key?(s) && params[s] }
    raise 'username, password, host and port must be set'
  end
  @username = Jid.new(params[:username], params[:host])
  @password = params[:password]
  @host = params[:host]
  @port = params[:port]
  @handler = params[:handler]
end

Instance Method Details

#authenticate(node) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/xmpp_simple/client.rb', line 62

def authenticate(node)
  mechanisms = node.xpath('/features/sasl:mechanisms/sasl:mechanism',
                          'sasl' => 'urn:ietf:params:xml:ns:xmpp-sasl')
  if mechanisms.any? { |m| m.inner_text == 'PLAIN' }
    write_data PlainAuth.create(@username, @password)
  else
    XMPPSimple.logger.info 'No authentication method provided'
    disconnect
  end
end

#close_stream_xmlObject



116
117
118
# File 'lib/xmpp_simple/client.rb', line 116

def close_stream_xml
  '</stream>'
end

#connectObject



17
18
19
20
21
22
23
24
# File 'lib/xmpp_simple/client.rb', line 17

def connect
  XMPPSimple.logger.info "Connecting to #{@host}:#{@port}"
  raw_socket = Celluloid::IO::TCPSocket.new(@host, @port)
  @socket = Celluloid::IO::SSLSocket.new(raw_socket).connect
  start
  async.run
  self
end

#disconnectObject



26
27
28
# File 'lib/xmpp_simple/client.rb', line 26

def disconnect
  write_data close_stream_xml
end

#features(node) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/xmpp_simple/client.rb', line 53

def features(node)
  XMPPSimple.logger.debug "Features: #{node.class}"
  if node.at('/features/bind:bind', 'bind' => 'urn:ietf:params:xml:ns:xmpp-bind')
    write_data Bind.create
  elsif node.at('/features/sasl:mechanisms', 'sasl' => 'urn:ietf:params:xml:ns:xmpp-sasl')
    authenticate(node)
  end
end

#finalizeObject



98
99
100
101
102
103
# File 'lib/xmpp_simple/client.rb', line 98

def finalize
  return unless defined? @socket
  return if @socket.nil?
  disconnect
  @socket.close
end

#iq(node) ⇒ Object



81
82
83
84
85
86
# File 'lib/xmpp_simple/client.rb', line 81

def iq(node)
  XMPPSimple.logger.debug "Iq: #{node.inspect}"
  return unless node.at('/iq/bind:bind', 'bind' => 'urn:ietf:params:xml:ns:xmpp-bind')
  XMPPSimple.logger.debug 'Connected!'
  @handler.connected if @handler.respond_to? :connected
end

#message(node) ⇒ Object



77
78
79
# File 'lib/xmpp_simple/client.rb', line 77

def message(node)
  @handler.message(node.to_xml) if @handler.respond_to? :message
end

#open_stream_xmlObject



105
106
107
108
109
110
111
112
113
114
# File 'lib/xmpp_simple/client.rb', line 105

def open_stream_xml
  "<stream:stream\n  xmlns:stream='http://etherx.jabber.org/streams'\n  xmlns='jabber:client'\n  to='\#{@host}'\n  xml:lang='en'\n  version='1.0'>\n  XML\nend\n"

#process(node) ⇒ Object



40
41
42
43
44
45
# File 'lib/xmpp_simple/client.rb', line 40

def process(node)
  XMPPSimple.logger.debug "Process: #{node}"
  return unless respond_to?(node.name)
  return unless %w(features success message iq).include?(node.name)
  send(node.name, node)
end

#reconnectObject



35
36
37
38
# File 'lib/xmpp_simple/client.rb', line 35

def reconnect
  finalize
  connect
end

#runObject



88
89
90
91
92
93
94
95
96
# File 'lib/xmpp_simple/client.rb', line 88

def run
  loop { @parser << @socket.readpartial(4096) }
rescue EOFError
  XMPPSimple.logger.debug 'Socket disconnected'
  @handler.disconnected if @handler.respond_to? :disconnected
rescue => e
  XMPPSimple.logger.debug "Error: #{e}"
  @handler.disconnected if @handler.respond_to? :disconnected
end

#startObject



30
31
32
33
# File 'lib/xmpp_simple/client.rb', line 30

def start
  @parser = Parser.new(self)
  write_data open_stream_xml
end

#success(_node) ⇒ Object



73
74
75
# File 'lib/xmpp_simple/client.rb', line 73

def success(_node)
  start
end

#write_data(xml) ⇒ Object



47
48
49
50
51
# File 'lib/xmpp_simple/client.rb', line 47

def write_data(xml)
  xml = xml.respond_to?(:to_xml) ? xml.to_xml : xml
  XMPPSimple.logger.debug "Sending: #{xml}"
  @socket.write xml
end