troystribling-agent_xmpp 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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