troystribling-agent_xmpp 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.document +5 -0
  2. data/.gitignore +9 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +7 -0
  5. data/Rakefile +62 -0
  6. data/VERSION +1 -0
  7. data/agent_xmpp.gemspec +89 -0
  8. data/bin/agent_xmpp +56 -0
  9. data/lib/agent_xmpp/app/boot.rb +64 -0
  10. data/lib/agent_xmpp/app/chat_message_body_controller.rb +16 -0
  11. data/lib/agent_xmpp/app/controller.rb +44 -0
  12. data/lib/agent_xmpp/app/format.rb +41 -0
  13. data/lib/agent_xmpp/app/map.rb +45 -0
  14. data/lib/agent_xmpp/app/routes.rb +77 -0
  15. data/lib/agent_xmpp/app/view.rb +49 -0
  16. data/lib/agent_xmpp/app.rb +7 -0
  17. data/lib/agent_xmpp/client/client.rb +197 -0
  18. data/lib/agent_xmpp/client/connection.rb +314 -0
  19. data/lib/agent_xmpp/client/parser.rb +71 -0
  20. data/lib/agent_xmpp/client.rb +3 -0
  21. data/lib/agent_xmpp/patches/standard_library_patches/array.rb +40 -0
  22. data/lib/agent_xmpp/patches/standard_library_patches/float.rb +25 -0
  23. data/lib/agent_xmpp/patches/standard_library_patches/hash.rb +28 -0
  24. data/lib/agent_xmpp/patches/standard_library_patches/object.rb +30 -0
  25. data/lib/agent_xmpp/patches/standard_library_patches/string.rb +25 -0
  26. data/lib/agent_xmpp/patches/standard_library_patches.rb +5 -0
  27. data/lib/agent_xmpp/patches/xmpp4r_patches/command.rb +26 -0
  28. data/lib/agent_xmpp/patches/xmpp4r_patches/iq.rb +26 -0
  29. data/lib/agent_xmpp/patches/xmpp4r_patches/x_data.rb +116 -0
  30. data/lib/agent_xmpp/patches/xmpp4r_patches.rb +3 -0
  31. data/lib/agent_xmpp/patches.rb +3 -0
  32. data/lib/agent_xmpp/utils/logger.rb +24 -0
  33. data/lib/agent_xmpp/utils/roster.rb +23 -0
  34. data/lib/agent_xmpp/utils.rb +2 -0
  35. data/lib/agent_xmpp/version.rb +6 -0
  36. data/lib/agent_xmpp.rb +16 -0
  37. data/test/agent_xmpp_test.rb +7 -0
  38. data/test/test_helper.rb +10 -0
  39. metadata +131 -0
@@ -0,0 +1,77 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ module Routing
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class Routes
9
+
10
+ #.........................................................................................................
11
+ @map = Map.new
12
+ #.........................................................................................................
13
+
14
+ ####......................................................................................................
15
+ class << self
16
+
17
+ #.........................................................................................................
18
+ attr_reader :map
19
+ #.........................................................................................................
20
+
21
+ #.......................................................................................................
22
+ def draw
23
+ yield map
24
+ end
25
+
26
+ #.......................................................................................................
27
+ def invoke_command_response(connection, params)
28
+ route_path = "#{params[:node]}/#{params[:action]}"
29
+ field_path = fields(params)
30
+ route_path += "/#{field_path}" unless field_path.nil?
31
+ route = map[route_path]
32
+ unless route.nil?
33
+ begin
34
+ controller_class = eval("#{route[:controller].classify}Controller")
35
+ rescue NameError
36
+ AgentXmpp.logger.error "ROUTING ERROR: #{route[:controller].classify}Controller does not exist for route {:controller => '#{route[:controller]}', :node => '#{params[:node]}', :action => '#{params[:action]}'}."
37
+ else
38
+ controler_instance = controller_class.new
39
+ if controler_instance.respond_to?(route[:action])
40
+ controler_instance.handle_request(connection, route[:action], params)
41
+ else
42
+ AgentXmpp.logger.error "ROUTING ERROR: no action on #{controller_class.to_s} for route {:controller => '#{route[:controller]}', :node => '#{params[:node]}', :action => '#{params[:action]}'}."
43
+ end
44
+ end
45
+ else
46
+ AgentXmpp.logger.error "ROUTING ERROR: no route for {:node => '#{params[:node]}', :action => '#{params[:action]}'}."
47
+ end
48
+ end
49
+
50
+ #.......................................................................................................
51
+ def invoke_chat_message_body_response(connection, params)
52
+ route = map.chat_message_body_route
53
+ begin
54
+ controller_class = eval("#{route[:controller].classify}Controller")
55
+ rescue ArgumentError
56
+ AgentXmpp.logger.error "ROUTING ERROR: #{params[:node].classify}Controller inavlid for node:#{params[:node]} action:#{params[:action]}."
57
+ else
58
+ controller_class.new.handle_request(connection, route[:action], params)
59
+ end
60
+ end
61
+
62
+ #.......................................................................................................
63
+ def fields(params)
64
+ nil
65
+ end
66
+
67
+ end
68
+ ####......................................................................................................
69
+
70
+ #### Routes
71
+ end
72
+
73
+ #### Routing
74
+ end
75
+
76
+ #### AgentXmpp
77
+ end
@@ -0,0 +1,49 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class View
6
+
7
+ #---------------------------------------------------------------------------------------------------------
8
+ attr_reader :connection, :format, :params
9
+ #---------------------------------------------------------------------------------------------------------
10
+
11
+ #.........................................................................................................
12
+ def initialize(connection, format, params)
13
+ @connection = connection
14
+ @format = format
15
+ @params = params
16
+ end
17
+
18
+ #.........................................................................................................
19
+ def add_payload_to_container(payload)
20
+ container_type = case format.xmlns
21
+ when 'jabber:x:data' then :add_x_data_to_container
22
+ when 'message:chat' then :add_chat_message_body_container
23
+ end
24
+ container_type.nil? ? nil : send(container_type, payload)
25
+ end
26
+
27
+ private
28
+
29
+ #.........................................................................................................
30
+ def add_x_data_to_container(payload)
31
+ iq = Jabber::Iq.new(:result, params[:from])
32
+ iq.id = params[:id] unless params[:id].nil?
33
+ iq.command = Jabber::Command::IqCommand.new(params[:node], 'completed')
34
+ iq.command << payload
35
+ iq
36
+ end
37
+
38
+ #.........................................................................................................
39
+ def add_chat_message_body_container(payload)
40
+ message = Jabber::Message.new(params[:from], payload)
41
+ message.type = :chat
42
+ message
43
+ end
44
+
45
+ #### View
46
+ end
47
+
48
+ #### AgentXmpp
49
+ end
@@ -0,0 +1,7 @@
1
+ require 'agent_xmpp/app/boot'
2
+ require 'agent_xmpp/app/controller'
3
+ require 'agent_xmpp/app/format'
4
+ require 'agent_xmpp/app/map'
5
+ require 'agent_xmpp/app/routes'
6
+ require 'agent_xmpp/app/view'
7
+ require 'agent_xmpp/app/chat_message_body_controller'
@@ -0,0 +1,197 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class Client
6
+
7
+ #---------------------------------------------------------------------------------------------------------
8
+ attr_reader :jid, :port, :password, :roster, :connection
9
+ #---------------------------------------------------------------------------------------------------------
10
+
11
+ #.........................................................................................................
12
+ def initialize(config)
13
+ @password = config['password']
14
+ @port = config['port'] || 5222
15
+ resource = config['resource'] || Socket.gethostname
16
+ @jid = Jabber::JID.new("#{config['jid']}/#{resource}")
17
+ @roster = Roster.new(@jid, config['contacts'])
18
+ end
19
+
20
+ #.........................................................................................................
21
+ def connect
22
+ while (true)
23
+ EventMachine.run do
24
+ @connection = EventMachine.connect(jid.domain, port, Connection, self, jid, password, port)
25
+ end
26
+ sleep(10.0)
27
+ AgentXmpp.logger.warn "RESTARTING SERVER"
28
+ end
29
+ end
30
+
31
+ #.........................................................................................................
32
+ def reconnect
33
+ AgentXmpp.logger.info "RECONNECTING"
34
+ connection.reconnect(jid.domain, port)
35
+ end
36
+
37
+ #.........................................................................................................
38
+ def connected?
39
+ connection and !connection.error?
40
+ end
41
+
42
+ #.........................................................................................................
43
+ def add_delegate(delegate)
44
+ connection.add_delegate(delegate)
45
+ end
46
+
47
+ #.........................................................................................................
48
+ def remove_delegate(delegate)
49
+ connection.remove_delegate(delegate)
50
+ end
51
+
52
+ #---------------------------------------------------------------------------------------------------------
53
+ # AgentXmpp::Connection delegate
54
+ #.........................................................................................................
55
+ # connection
56
+ #.........................................................................................................
57
+ def did_connect(client_connection)
58
+ AgentXmpp.logger.info "CONNECTED"
59
+ end
60
+
61
+ #.........................................................................................................
62
+ def did_disconnect(client_connection)
63
+ AgentXmpp.logger.warn "DISCONNECTED"
64
+ EventMachine::stop_event_loop
65
+ end
66
+
67
+ #.........................................................................................................
68
+ def did_not_connect(client_connection)
69
+ AgentXmpp.logger.warn "CONNECTION FAILED"
70
+ end
71
+
72
+ #.........................................................................................................
73
+ # authentication
74
+ #.........................................................................................................
75
+ def did_authenticate(client_connection, stanza)
76
+ AgentXmpp.logger.info "AUTHENTICATED"
77
+ end
78
+
79
+ #.........................................................................................................
80
+ def did_not_authenticate(client_connection, stanza)
81
+ AgentXmpp.logger.info "AUTHENTICATION FAILED"
82
+ end
83
+
84
+ #.........................................................................................................
85
+ def did_bind(client_connection, stanza)
86
+ AgentXmpp.logger.info "BIND ACKNOWLEDGED"
87
+ end
88
+
89
+ #.........................................................................................................
90
+ # presence
91
+ #.........................................................................................................
92
+ def did_receive_presence(client_connection, presence)
93
+ from_jid = presence.from.to_s
94
+ from_bare_jid = presence.from.bare.to_s
95
+ if roster.has_key?(from_bare_jid)
96
+ roster[from_bare_jid.to_s][:resources][from_jid] = {} if roster[from_bare_jid.to_s][:resources][from_jid].nil?
97
+ roster[from_bare_jid.to_s][:resources][from_jid][:presence] = presence
98
+ client_connection.get_client_version(from_jid) if not from_jid.eql?(client_connection.jid.to_s) and presence.type.nil?
99
+ AgentXmpp.logger.info "RECEIVED PRESENCE FROM: #{from_jid}"
100
+ else
101
+ AgentXmpp.logger.info "RECEIVED PRESENCE FROM JID NOT IN CONTACT LIST: #{from_jid}"
102
+ end
103
+ end
104
+
105
+ #.........................................................................................................
106
+ def did_receive_subscribe_request(client_connection, presence)
107
+ from_jid = presence.from.to_s
108
+ if roster.has_key?(presence.from.bare.to_s )
109
+ client_connection.accept_contact_request(from_jid)
110
+ AgentXmpp.logger.info "RECEIVED SUBSCRIBE REQUEST: #{from_jid}"
111
+ else
112
+ client_connection.reject_contact_request(from_jid)
113
+ AgentXmpp.logger.info "RECEIVED SUBSCRIBE REQUEST FROM JID NOT IN CONTACT LIST: #{from_jid}"
114
+ end
115
+ end
116
+
117
+ #.........................................................................................................
118
+ def did_receive_unsubscribed_request(client_connection, presence)
119
+ from_jid = presence.from.to_s
120
+ if roster.delete(presence.from.bare.to_s )
121
+ client_connection.remove_contact(presence.from)
122
+ AgentXmpp.logger.info "RECEIVED UNSUBSCRIBED REQUEST: #{from_jid}"
123
+ else
124
+ AgentXmpp.logger.warn "RECEIVED UNSUBSCRIBED REQUEST FROM JID NOT IN CONTACT LIST: #{from_jid}"
125
+ end
126
+ end
127
+
128
+ #.........................................................................................................
129
+ # roster management
130
+ #.........................................................................................................
131
+ def did_receive_roster_item(client_connection, roster_item)
132
+ AgentXmpp.logger.info "RECEIVED ROSTER ITEM"
133
+ roster_item_jid = roster_item.jid.to_s
134
+ if roster.has_key?(roster_item_jid)
135
+ roster[roster_item_jid][:activated] = true
136
+ roster[roster_item_jid][:roster_item] = roster_item
137
+ AgentXmpp.logger.info "ACTIVATING CONTACT: #{roster_item_jid}"
138
+ else
139
+ client_connection.remove_contact(roster_item.jid)
140
+ AgentXmpp.logger.info "REMOVING CONTACT: #{roster_item_jid}"
141
+ end
142
+ end
143
+
144
+ #.........................................................................................................
145
+ def did_remove_roster_item(client_connection, roster_item)
146
+ AgentXmpp.logger.info "REMOVE ROSTER ITEM"
147
+ roster_item_jid = roster_item.jid.to_s
148
+ if roster.has_key?(roster_item_jid)
149
+ roster.delete(roster_item_jid)
150
+ AgentXmpp.logger.info "REMOVED CONTACT: #{roster_item_jid}"
151
+ end
152
+ end
153
+
154
+ #.........................................................................................................
155
+ def did_receive_all_roster_items(client_connection)
156
+ AgentXmpp.logger.info "RECEIVED ALL ROSTER ITEMS"
157
+ roster.select{|j,r| not r[:activated]}.each do |j,r|
158
+ AgentXmpp.logger.info "ADDING CONTACT: #{j}"
159
+ client_connection.add_contact(Jabber::JID.new(j))
160
+ end
161
+ end
162
+
163
+ #.........................................................................................................
164
+ def did_acknowledge_add_contact(client_connection, response, contact_jid)
165
+ AgentXmpp.logger.info "CONTACT ADD ACKNOWLEDGED: #{contact_jid.to_s}"
166
+ end
167
+
168
+ #.........................................................................................................
169
+ def did_remove_contact(client_connection, response, contact_jid)
170
+ AgentXmpp.logger.info "CONTACT REMOVED: #{contact_jid.to_s}"
171
+ end
172
+
173
+ #.........................................................................................................
174
+ def did_add_contact(client_connection, roster_item)
175
+ AgentXmpp.logger.info "CONTACT ADDED: #{roster_item.jid.to_s}"
176
+ end
177
+
178
+ #.........................................................................................................
179
+ # service discovery management
180
+ #.........................................................................................................
181
+ def did_receive_client_version_result(client_connection, from, version)
182
+ roster[from.bare.to_s][:resources][from.to_s][:version] = version \
183
+ unless roster[from.bare.to_s][:resources][from.to_s].nil?
184
+ AgentXmpp.logger.info "RECEIVED CLIENT VERSION RESULT: #{from.to_s}, #{version.iname}, #{version.version}"
185
+ end
186
+
187
+ #.........................................................................................................
188
+ def did_receive_client_version_request(client_connection, request)
189
+ client_connection.send_client_version(request)
190
+ AgentXmpp.logger.info "RECEIVED CLIENT VERSION REQUEST: #{request.from.to_s}"
191
+ end
192
+
193
+ #### Client
194
+ end
195
+
196
+ #### AgentXmpp
197
+ end
@@ -0,0 +1,314 @@
1
+ ##############################################################################################################
2
+ module AgentXmpp
3
+
4
+ #####-------------------------------------------------------------------------------------------------------
5
+ class NotConnected < Exception; end
6
+
7
+ #####-------------------------------------------------------------------------------------------------------
8
+ class Connection < EventMachine::Connection
9
+
10
+ #---------------------------------------------------------------------------------------------------------
11
+ include Parser
12
+ #---------------------------------------------------------------------------------------------------------
13
+
14
+ #---------------------------------------------------------------------------------------------------------
15
+ attr_reader :client, :jid, :port, :password, :connection_status, :delegates, :keepalive
16
+ #---------------------------------------------------------------------------------------------------------
17
+
18
+ #.........................................................................................................
19
+ def initialize(client, jid, password, port=5222)
20
+ @client, @jid, @password, @port = client, jid, password, port
21
+ @connection_status = :offline;
22
+ @id_callbacks = {}
23
+ @delegates = []
24
+ end
25
+
26
+ #.........................................................................................................
27
+ def add_delegate(delegate)
28
+ @delegates << delegate
29
+ end
30
+
31
+ #.........................................................................................................
32
+ def remove_delegate(delegate)
33
+ @delegates.delete(delegate)
34
+ end
35
+
36
+ #.........................................................................................................
37
+ def send(data, &blk)
38
+ raise NotConnected if error?
39
+ if block_given? and data.is_a? Jabber::XMPPStanza
40
+ if data.id.nil?
41
+ data.id = Jabber::IdGenerator.instance.generate_id
42
+ end
43
+ @id_callbacks[data.id] = blk
44
+ end
45
+ send_data(data.to_s)
46
+ AgentXmpp.logger.info "SEND: #{data.to_s}"
47
+ end
48
+
49
+ #---------------------------------------------------------------------------------------------------------
50
+ # EventMachine::Connection callbacks
51
+ #.........................................................................................................
52
+ def connection_completed
53
+ init_connection
54
+ @keepalive = EventMachine::PeriodicTimer.new(60) do
55
+ send_data("\n")
56
+ end
57
+ add_delegate(client)
58
+ AgentXmpp::Boot.call_after_connection_completed(self) if AgentXmpp::Boot.respond_to?(:call_after_connection_completed)
59
+ broadcast_to_delegates(:did_connect, self)
60
+ end
61
+
62
+ #.........................................................................................................
63
+ def receive_data(data)
64
+ AgentXmpp.logger.info "RECV: #{data.to_s}"
65
+ super(data)
66
+ end
67
+
68
+ #.........................................................................................................
69
+ def unbind
70
+ if @keepalive
71
+ @keepalive.cancel
72
+ @keepalive = nil
73
+ end
74
+ @connection_status = :off_line
75
+ broadcast_to_delegates(:did_disconnect, self)
76
+ end
77
+
78
+ #---------------------------------------------------------------------------------------------------------
79
+ # service discovery
80
+ #.........................................................................................................
81
+ def get_client_version(contact_jid)
82
+ iq = Jabber::Iq.new(:get, contact_jid)
83
+ iq.query = Jabber::Version::IqQueryVersion.new
84
+ send(iq) do |r|
85
+ if (r.type == :result) && r.query.kind_of?(Jabber::Version::IqQueryVersion)
86
+ broadcast_to_delegates(:did_receive_client_version_result, self, r.from, r.query)
87
+ end
88
+ end
89
+ end
90
+
91
+ #.........................................................................................................
92
+ def send_client_version(request)
93
+ iq = Jabber::Iq.new(:result, request.from.to_s)
94
+ iq.id = request.id unless request.id.nil?
95
+ iq.query = Jabber::Version::IqQueryVersion.new
96
+ iq.query.set_iname(AgentXmpp::AGENT_XMPP_NAME).set_version(AgentXmpp::VERSION).set_os(AgentXmpp::OS_VERSION)
97
+ send(iq)
98
+ end
99
+
100
+ #---------------------------------------------------------------------------------------------------------
101
+ # roster management
102
+ #.........................................................................................................
103
+ def get_roster
104
+ send(Jabber::Iq.new_rosterget) do |r|
105
+ if r.type == :result and r.query.kind_of?(Jabber::Roster::IqQueryRoster)
106
+ r.query.each_element {|i| broadcast_to_delegates(:did_receive_roster_item, self, i)}
107
+ broadcast_to_delegates(:did_receive_all_roster_items, self)
108
+ end
109
+ end
110
+ end
111
+
112
+ #.........................................................................................................
113
+ def add_contact(contact_jid)
114
+ request = Jabber::Iq.new_rosterset
115
+ request.query.add(Jabber::Roster::RosterItem.new(contact_jid))
116
+ send(request) do |r|
117
+ send(Jabber::Presence.new.set_type(:subscribe).set_to(contact_jid))
118
+ broadcast_to_delegates(:did_acknowledge_add_contact, self, r, contact_jid)
119
+ end
120
+ end
121
+
122
+ #.........................................................................................................
123
+ def remove_contact(contact_jid)
124
+ request = Jabber::Iq.new_rosterset
125
+ request.query.add(Jabber::Roster::RosterItem.new(contact_jid, nil, :remove))
126
+ send(request) do |r|
127
+ broadcast_to_delegates(:did_remove_contact, self, r, contact_jid)
128
+ end
129
+ end
130
+
131
+ #.........................................................................................................
132
+ def accept_contact_request(contact_jid)
133
+ presence = Jabber::Presence.new.set_type(:subscribed)
134
+ presence.to = contact_jid
135
+ send(presence)
136
+ end
137
+
138
+ #.........................................................................................................
139
+ def reject_contact_request(contact_jid)
140
+ presence = Jabber::Presence.new.set_type(:unsubscribed)
141
+ presence.to = contact_jid
142
+ send(presence)
143
+ end
144
+
145
+ #---------------------------------------------------------------------------------------------------------
146
+ # process commands
147
+ #.........................................................................................................
148
+ def process_command(stanza)
149
+ command = stanza.command
150
+ unless command.x.nil?
151
+ params = {:xmlns => command.x.namespace, :action => command.action, :to => stanza.from.to_s,
152
+ :from => stanza.from.to_s, :node => command.node, :id => stanza.id, :fields => {}}
153
+ Routing::Routes.invoke_command_response(self, params)
154
+ AgentXmpp.logger.info "RECEIVED COMMAND: #{command.node}, FROM: #{stanza.from.to_s}"
155
+ end
156
+ end
157
+
158
+ #---------------------------------------------------------------------------------------------------------
159
+ # process messages
160
+ #.........................................................................................................
161
+ def process_chat_message_body(stanza)
162
+ params = {:xmlns => 'message:chat', :to => stanza.from.to_s, :from => stanza.from.to_s, :id => stanza.id,
163
+ :body => stanza.body}
164
+ Routing::Routes.invoke_chat_message_body_response(self, params)
165
+ AgentXmpp.logger.info "RECEIVED MESSAGE BODY: #{stanza.body}"
166
+ end
167
+
168
+ #---------------------------------------------------------------------------------------------------------
169
+ # AgentXmpp::Parser callbacks
170
+ #.........................................................................................................
171
+ def receive(stanza)
172
+ if stanza.kind_of?(Jabber::XMPPStanza) and stanza.id and blk = @id_callbacks[stanza.id]
173
+ @id_callbacks.delete(stanza.id)
174
+ blk.call(stanza)
175
+ return
176
+ end
177
+
178
+ case stanza.xpath
179
+ when 'stream:features'
180
+ @stream_features, @stream_mechanisms = {}, []
181
+ @current.each do |e|
182
+ if e.name == 'mechanisms' and e.namespace == 'urn:ietf:params:xml:ns:xmpp-sasl'
183
+ e.each_element('mechanism') {|mech| @stream_mechanisms.push(mech.text)}
184
+ else
185
+ @stream_features[e.name] = e.namespace
186
+ end
187
+ end
188
+ if @connection_status.eql?(:offline)
189
+ authenticate
190
+ elsif @connection_status.eql?(:authenticated)
191
+ bind(stanza)
192
+ end
193
+ when 'stream:stream'
194
+ when 'success'
195
+ case connection_status
196
+ when :offline
197
+ reset_parser
198
+ init_connection(false)
199
+ @connection_status = :authenticated
200
+ end
201
+ return
202
+ when 'failure'
203
+ case connection_status
204
+ when :offline
205
+ reset_parser
206
+ broadcast_to_delegates(:did_not_authenticate, self, stanza)
207
+ end
208
+ else
209
+ demux_channel(stanza)
210
+ end
211
+
212
+ end
213
+
214
+ #---------------------------------------------------------------------------------------------------------
215
+ protected
216
+ #---------------------------------------------------------------------------------------------------------
217
+
218
+ #---------------------------------------------------------------------------------------------------------
219
+ # Process XMPP messages
220
+ #.........................................................................................................
221
+ def authenticate
222
+ begin
223
+ Jabber::SASL.new(self, 'PLAIN').auth(password)
224
+ rescue
225
+ raise ClientAuthenticationFailure.new, $!.to_s
226
+ end
227
+ end
228
+
229
+ #.........................................................................................................
230
+ def bind(stanza)
231
+ if stream_features.has_key?('bind')
232
+ iq = Jabber::Iq.new(:set)
233
+ bind = iq.add(REXML::Element.new('bind'))
234
+ bind.add_namespace(stream_features['bind'])
235
+ resource = bind.add REXML::Element.new('resource')
236
+ resource.text = jid.resource
237
+ send(iq) do |r|
238
+ if r.type == :result and full_jid = r.first_element('//jid') and full_jid.text
239
+ @connection_status = :bind
240
+ jid = Jabber::JID.new(full_jid.text) unless jid.to_s.eql?(full_jid.text)
241
+ broadcast_to_delegates(:did_bind, self, stanza)
242
+ session(stanza)
243
+ end
244
+ end
245
+ end
246
+ end
247
+
248
+ #.........................................................................................................
249
+ def session(stanza)
250
+ if stream_features.has_key?('session')
251
+ iq = Jabber::Iq.new(:set)
252
+ session = iq.add REXML::Element.new('session')
253
+ session.add_namespace stream_features['session']
254
+ send(iq) do |r|
255
+ if r.type == :result
256
+ @connection_status = :active
257
+ broadcast_to_delegates(:did_authenticate, self, stanza)
258
+ send(Jabber::Presence.new(nil, nil, 1))
259
+ get_roster
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ #.........................................................................................................
266
+ def init_connection(starting=true)
267
+ send("<?xml version='1.0' ?>") if starting
268
+ send("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' to='#{jid.domain}'>" )
269
+ end
270
+
271
+ #.........................................................................................................
272
+ def demux_channel(stanza)
273
+ stanza_class = stanza.class.to_s
274
+ #### roster update
275
+ if stanza.type == :set and stanza.query.kind_of?(Jabber::Roster::IqQueryRoster)
276
+ stanza.query.each_element do |i|
277
+ method = case i.subscription
278
+ when :remove then :did_remove_roster_item
279
+ when :none then :did_receive_roster_item
280
+ when :to then :did_add_contact
281
+ end
282
+ broadcast_to_delegates(method, self, i) unless method.nil?
283
+ end
284
+ #### presence subscription request
285
+ elsif stanza.type.eql?(:subscribe) and stanza_class.eql?('Jabber::Presence')
286
+ broadcast_to_delegates(:did_receive_subscribe_request, self, stanza)
287
+ #### presence unsubscribe
288
+ elsif stanza.type.eql?(:unsubscribed) and stanza_class.eql?('Jabber::Presence')
289
+ broadcast_to_delegates(:did_receive_unsubscribed_request, self, stanza)
290
+ #### client version request
291
+ elsif stanza.type.eql?(:get) and stanza.query.kind_of?(Jabber::Version::IqQueryVersion)
292
+ broadcast_to_delegates(:did_receive_client_version_request, self, stanza)
293
+ #### received command
294
+ elsif stanza.type.eql?(:set) and stanza.command.kind_of?(Jabber::Command::IqCommand)
295
+ process_command(stanza)
296
+ #### chat message received
297
+ elsif stanza_class.eql?('Jabber::Message') and stanza.type.eql?(:chat) and stanza.respond_to?(:body)
298
+ process_chat_message_body(stanza)
299
+ else
300
+ method = ('did_receive_' + /.*::(.*)/.match(stanza_class).to_a.last.downcase).to_sym
301
+ broadcast_to_delegates(method, self, stanza)
302
+ end
303
+ end
304
+
305
+ #.........................................................................................................
306
+ def broadcast_to_delegates(method, *args)
307
+ delegates.each{|d| d.send(method, *args) if d.respond_to?(method)}
308
+ end
309
+
310
+ #### Connection
311
+ end
312
+
313
+ #### AgentXmpp
314
+ end