xmpp4em 0.2.0 → 0.2.3
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.
- data/README.md +0 -2
- data/lib/xmpp4em.rb +1 -1
- data/lib/xmpp4em/base_client.rb +63 -51
- data/lib/xmpp4em/base_connection.rb +85 -66
- data/lib/xmpp4em/client.rb +81 -81
- data/lib/xmpp4em/component.rb +24 -25
- metadata +58 -68
- data/Rakefile +0 -5
- data/spec/spec_runner.rb +0 -26
- data/spec/xmpp4em_spec.rb +0 -57
data/README.md
CHANGED
data/lib/xmpp4em.rb
CHANGED
data/lib/xmpp4em/base_client.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
require 'rubygems'
|
3
3
|
|
4
|
-
require 'stringio'
|
5
|
-
require 'rexml/parsers/sax2parser'
|
6
|
-
|
7
4
|
require 'xmpp4r/idgenerator'
|
8
5
|
require 'xmpp4r/xmppstanza'
|
9
6
|
require 'xmpp4r/iq'
|
@@ -12,15 +9,15 @@ require 'xmpp4r/presence'
|
|
12
9
|
require 'resolv'
|
13
10
|
|
14
11
|
require 'eventmachine'
|
15
|
-
require 'evma_xmlpushparser'
|
16
|
-
EM.epoll
|
17
12
|
|
18
13
|
module XMPP4EM
|
19
|
-
|
14
|
+
|
20
15
|
class BaseClient
|
21
|
-
include EM::Deferrable
|
22
|
-
|
23
|
-
|
16
|
+
include ::EM::Deferrable
|
17
|
+
attr_reader :authenticated
|
18
|
+
alias :authenticated? :authenticated
|
19
|
+
|
20
|
+
def initialize(user, pass, logger=nil, opts = {})
|
24
21
|
@user = user
|
25
22
|
@pass = pass
|
26
23
|
@logger=logger
|
@@ -29,81 +26,85 @@ module XMPP4EM
|
|
29
26
|
@authenticated = false
|
30
27
|
@opts = opts
|
31
28
|
@auth_callback = nil
|
32
|
-
@id_callbacks
|
29
|
+
@id_callbacks = {}
|
33
30
|
@on_stanza=nil
|
34
31
|
@events_callbacks = {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
}
|
43
|
-
|
32
|
+
:message => [],
|
33
|
+
:presence => [],
|
34
|
+
:iq => [],
|
35
|
+
:exception => [],
|
36
|
+
:login => [],
|
37
|
+
:disconnect => [],
|
38
|
+
:connected => []
|
39
|
+
}
|
40
|
+
|
44
41
|
on(:disconnect) do
|
45
42
|
@deferred_status = nil
|
46
43
|
@authenticated=false
|
47
|
-
end
|
44
|
+
end
|
48
45
|
on(:login) do
|
49
46
|
succeed
|
50
|
-
end
|
47
|
+
end
|
51
48
|
end
|
49
|
+
|
52
50
|
attr_reader :connection, :user
|
53
|
-
|
51
|
+
|
54
52
|
def reconnect
|
55
53
|
@connection.close_connection_after_writing
|
56
54
|
@deferred_status = nil
|
57
55
|
connect
|
58
56
|
end
|
59
|
-
|
57
|
+
|
60
58
|
def connected?
|
61
59
|
@connection and !@connection.error?
|
62
60
|
end
|
63
|
-
|
64
|
-
def register_stanza &blk
|
61
|
+
|
62
|
+
def register_stanza &blk
|
65
63
|
@on_stanza = blk if block_given?
|
66
|
-
end
|
67
|
-
|
68
|
-
def send data, safe=false,
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
data.id = Jabber::IdGenerator.instance.generate_id
|
73
|
-
end
|
74
|
-
@id_callbacks[ data.id ] = blk
|
64
|
+
end
|
65
|
+
|
66
|
+
def send data, safe=false, &blk
|
67
|
+
if data.is_a? ::Jabber::XMPPStanza
|
68
|
+
data.id = ::Jabber::IdGenerator.instance.generate_id if data.id.nil?
|
69
|
+
@id_callbacks[data.id] = blk if block_given?
|
75
70
|
end
|
71
|
+
|
76
72
|
if safe
|
77
|
-
callback {
|
73
|
+
callback { @connection.send(data) }
|
78
74
|
else
|
79
75
|
@connection.send(data)
|
80
76
|
end
|
81
77
|
end
|
82
|
-
|
78
|
+
|
83
79
|
def close
|
84
80
|
@connection.close_connection_after_writing
|
85
81
|
@deferred_status = nil
|
86
82
|
@connection = nil
|
87
83
|
end
|
84
|
+
|
88
85
|
alias :disconnect :close
|
89
|
-
|
86
|
+
|
90
87
|
def receive stanza
|
91
|
-
|
88
|
+
|
89
|
+
if stanza.kind_of?(::Jabber::XMPPStanza) and stanza.id and blk = @id_callbacks[stanza.id]
|
92
90
|
@id_callbacks.delete stanza.id
|
93
91
|
blk.call(stanza)
|
94
92
|
return
|
95
93
|
end
|
96
|
-
|
97
|
-
return if receive_stanza(stanza)
|
98
|
-
return if @on_stanza && @on_stanza.call(stanza)
|
99
|
-
|
94
|
+
|
95
|
+
return if receive_stanza(stanza)
|
96
|
+
return if @on_stanza && @on_stanza.call(stanza)
|
97
|
+
|
100
98
|
case stanza
|
101
|
-
when Jabber::
|
102
|
-
|
103
|
-
when Jabber::
|
99
|
+
when Jabber::Presence then
|
100
|
+
on(:presence, stanza)
|
101
|
+
when Jabber::Iq then
|
102
|
+
on(:iq, stanza)
|
103
|
+
when Jabber::Message then
|
104
|
+
on(:message, stanza)
|
104
105
|
end
|
105
106
|
end
|
106
|
-
|
107
|
+
|
107
108
|
def on type, *args, &blk
|
108
109
|
if blk
|
109
110
|
@events_callbacks[type] << blk
|
@@ -113,10 +114,21 @@ module XMPP4EM
|
|
113
114
|
end
|
114
115
|
end
|
115
116
|
end
|
116
|
-
|
117
|
-
def add_message_callback
|
118
|
-
|
119
|
-
|
120
|
-
|
117
|
+
|
118
|
+
def add_message_callback (&blk)
|
119
|
+
on(:message, &blk);
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_presence_callback (&blk)
|
123
|
+
on(:presence, &blk);
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_iq_callback (&blk)
|
127
|
+
on(:iq, &blk);
|
128
|
+
end
|
129
|
+
|
130
|
+
def on_exception (&blk)
|
131
|
+
on(:exception, &blk);
|
132
|
+
end
|
121
133
|
end
|
122
134
|
end
|
@@ -1,129 +1,148 @@
|
|
1
1
|
#encoding: utf-8
|
2
|
-
require '
|
3
|
-
require 'rexml/parsers/sax2parser'
|
4
|
-
|
2
|
+
require 'nokogiri'
|
5
3
|
require 'xmpp4r/idgenerator'
|
6
4
|
require 'xmpp4r/xmppstanza'
|
7
5
|
require 'xmpp4r/iq'
|
8
6
|
require 'xmpp4r/message'
|
9
7
|
require 'xmpp4r/presence'
|
10
8
|
|
11
|
-
module XMPP4EM
|
12
|
-
|
13
|
-
class
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def connection_completed
|
22
|
-
@logger.debug{'connected'} if @logger
|
23
|
-
@stream_features, @stream_mechanisms = {}, []
|
24
|
-
@keepalive = EM::Timer.new(60){ send_data("\n") }
|
25
|
-
@client.on(:connected)
|
26
|
-
init
|
9
|
+
module ::XMPP4EM
|
10
|
+
|
11
|
+
class XmppPushParser < ::Nokogiri::XML::SAX::Document
|
12
|
+
|
13
|
+
attr_accessor :started
|
14
|
+
attr_accessor :current
|
15
|
+
|
16
|
+
def process(&block)
|
17
|
+
@process=block
|
27
18
|
end
|
28
|
-
|
29
|
-
|
30
|
-
include EventMachine::XmlPushParser
|
31
|
-
|
19
|
+
|
32
20
|
def encode2utf8(text)
|
33
|
-
text
|
21
|
+
text
|
34
22
|
end
|
35
|
-
|
23
|
+
|
36
24
|
def start_element name, attrs
|
37
|
-
e = REXML::Element.new(name)
|
38
|
-
attrs.each { |
|
39
|
-
|
40
|
-
|
41
|
-
|
25
|
+
e = ::REXML::Element.new(name)
|
26
|
+
attrs.each { |a|
|
27
|
+
a_name, a_value = *a
|
28
|
+
if a_name =~ /^xmlns:(.+)$/
|
29
|
+
e.add_attribute($1, a_value.to_s)
|
30
|
+
else
|
31
|
+
e.add_namespace(a_name, a_value)
|
32
|
+
end
|
33
|
+
} if attrs.length > 0
|
42
34
|
@current = @current.nil? ? e : @current.add_element(e)
|
43
|
-
|
35
|
+
|
44
36
|
if @current.name == 'stream' and not @started
|
45
37
|
@started = true
|
46
|
-
process
|
38
|
+
@process.call(@current)
|
47
39
|
@current = nil
|
48
40
|
end
|
49
41
|
end
|
50
|
-
|
42
|
+
|
51
43
|
def end_element name
|
52
|
-
if name == 'stream
|
44
|
+
if name == 'stream' and @current.nil?
|
53
45
|
@started = false
|
54
46
|
else
|
55
47
|
if @current.parent
|
56
48
|
@current = @current.parent
|
57
49
|
else
|
58
|
-
process
|
50
|
+
@process.call(@current)
|
59
51
|
@current = nil
|
60
52
|
end
|
61
53
|
end
|
62
54
|
end
|
63
|
-
|
55
|
+
|
64
56
|
def characters text
|
65
57
|
@current.text = @current.text.to_s + encode2utf8(text) if @current
|
66
58
|
end
|
67
|
-
|
59
|
+
end
|
60
|
+
|
61
|
+
class BaseConnection < ::EventMachine::Connection
|
62
|
+
|
63
|
+
def initialize host, port=5222
|
64
|
+
@host, @port = host, port
|
65
|
+
@client = nil
|
66
|
+
@pushParser=::XMPP4EM::XmppPushParser.new
|
67
|
+
@pushParser.process do |c|
|
68
|
+
process(c)
|
69
|
+
end
|
70
|
+
@parser=::Nokogiri::XML::SAX::PushParser.new(@pushParser)
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_accessor :client, :host, :port, :logger
|
74
|
+
|
75
|
+
def connection_completed
|
76
|
+
@logger.debug { 'connected' } if @logger
|
77
|
+
@stream_features, @stream_mechanisms = {}, []
|
78
|
+
@keepalive = ::EM::Timer.new(60) { send_data("\n") }
|
79
|
+
@client.on(:connected)
|
80
|
+
init
|
81
|
+
end
|
82
|
+
|
83
|
+
attr_reader :stream_features
|
84
|
+
|
68
85
|
def error *args
|
69
|
-
|
86
|
+
$stderr.puts ['error', *args]
|
70
87
|
end
|
71
|
-
|
88
|
+
|
72
89
|
def receive_data data
|
73
|
-
@logger.debug{"<< #{data}"} if @logger
|
74
|
-
|
90
|
+
@logger.debug { "<< #{data}" } if @logger
|
91
|
+
#$stdout.puts "[Receive] #{data}"
|
92
|
+
@parser.write(data)
|
75
93
|
end
|
76
|
-
|
94
|
+
|
77
95
|
def send data, &blk
|
78
|
-
@logger.debug{ ">> #{data}"} if @logger
|
79
|
-
|
96
|
+
@logger.debug { ">> #{data}" } if @logger
|
97
|
+
#$stdout.puts "[Send] #{data.to_s}"
|
98
|
+
send_data data.to_s
|
80
99
|
end
|
81
|
-
|
100
|
+
|
82
101
|
def unbind
|
83
102
|
if @keepalive
|
84
103
|
@keepalive.cancel
|
85
104
|
@keepalive = nil
|
86
105
|
end
|
87
106
|
@client.on(:disconnect)
|
88
|
-
@logger.debug{'disconnected'} if @logger
|
107
|
+
@logger.debug { 'disconnected' } if @logger
|
89
108
|
end
|
90
|
-
|
109
|
+
|
91
110
|
def reconnect host = @host, port = @port
|
92
111
|
super
|
93
112
|
end
|
94
|
-
|
113
|
+
|
95
114
|
def init
|
96
|
-
send "<?xml version='1.0' ?>" unless @started
|
97
|
-
@started = false
|
115
|
+
send "<?xml version='1.0' ?>" unless @pushParser.started
|
116
|
+
@pushParser.started = false
|
98
117
|
send "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='#{namespace;}' xml:lang='en' version='1.0' to='#{@host}'>"
|
99
118
|
end
|
100
|
-
|
119
|
+
|
101
120
|
private
|
102
|
-
|
103
|
-
def
|
104
|
-
end
|
105
|
-
|
106
|
-
def process
|
107
|
-
if
|
108
|
-
|
121
|
+
|
122
|
+
def pre_process_stanza(stanza)
|
123
|
+
end
|
124
|
+
|
125
|
+
def process(current)
|
126
|
+
if current.namespace('').to_s == '' # REXML namespaces are always strings
|
127
|
+
current.add_namespace(@streamns)
|
109
128
|
end
|
110
|
-
stanza =
|
129
|
+
stanza = current
|
111
130
|
if 'stream'==stanza.prefix
|
112
131
|
if 'stream'==stanza.name
|
113
|
-
@streamid = stanza.attributes['id']
|
132
|
+
@streamid = stanza.attributes['id']
|
114
133
|
#All connections has the same namespace
|
115
|
-
@streamns = 'jabber:client'
|
134
|
+
@streamns = 'jabber:client'
|
116
135
|
end
|
117
|
-
pre_process_stanza(stanza)
|
136
|
+
pre_process_stanza(stanza)
|
118
137
|
end
|
119
138
|
# Any stanza, classes are registered by XMPPElement::name_xmlns
|
120
139
|
begin
|
121
|
-
stanza = Jabber::XMPPStanza::import(
|
122
|
-
rescue Jabber::NoNameXmlnsRegistered
|
123
|
-
stanza =
|
140
|
+
stanza = ::Jabber::XMPPStanza::import(current)
|
141
|
+
rescue ::Jabber::NoNameXmlnsRegistered
|
142
|
+
stanza = current
|
124
143
|
end
|
125
144
|
@client.receive(stanza)
|
126
145
|
end
|
127
146
|
end
|
128
|
-
|
147
|
+
|
129
148
|
end
|
data/lib/xmpp4em/client.rb
CHANGED
@@ -3,136 +3,136 @@ require 'xmpp4r/sasl'
|
|
3
3
|
require 'resolv'
|
4
4
|
|
5
5
|
module XMPP4EM
|
6
|
-
|
6
|
+
|
7
7
|
class Client < BaseClient
|
8
|
-
|
8
|
+
|
9
9
|
def initialize user, pass, logger=nil, opts = {}
|
10
|
-
super
|
11
|
-
@opts = {
|
10
|
+
super
|
11
|
+
@opts = {:auto_register => false}.merge(opts)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def jid
|
15
|
-
@jid ||= if @user.kind_of?(Jabber::JID)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
@jid ||= if @user.kind_of?(::Jabber::JID)
|
16
|
+
@user
|
17
|
+
else
|
18
|
+
@user =~ /@/ ? ::Jabber::JID.new(@user) : ::Jabber::JID.new(@user, 'localhost')
|
19
|
+
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def connect host = jid.domain, port = 5222
|
23
23
|
if host=='localhost' || host=='127.0.0.1' || %r{^([0-9]{1,3}.){3}[0-9]{1,3}$}.match(host)
|
24
24
|
target_host, target_port= host, port
|
25
25
|
else
|
26
26
|
target_host, target_port = resolve_host(host)
|
27
27
|
end
|
28
|
-
EM.connect target_host, target_port, ClientConnection, jid.domain, port do |conn|
|
28
|
+
::EM.connect target_host, target_port, ClientConnection, jid.domain, port do |conn|
|
29
29
|
@connection = conn
|
30
30
|
conn.client = self
|
31
31
|
conn.logger=@logger
|
32
32
|
end
|
33
|
-
end
|
34
|
-
|
33
|
+
end
|
34
|
+
|
35
35
|
def resolve_host(domain)
|
36
36
|
srv = []
|
37
|
-
begin
|
38
|
-
Resolv::DNS.open { |dns|
|
37
|
+
begin
|
38
|
+
::Resolv::DNS.open { |dns|
|
39
39
|
# If ruby version is too old and SRV is unknown, this will raise a NameError
|
40
40
|
# which is catched below
|
41
41
|
#debug("RESOLVING:\n_xmpp-client._tcp.#{domain} (SRV)")
|
42
42
|
srv = dns.getresources("_xmpp-client._tcp.#{domain}", Resolv::DNS::Resource::IN::SRV)
|
43
43
|
}
|
44
44
|
rescue NameError
|
45
|
-
|
45
|
+
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
unless srv.blank?
|
49
49
|
# Sort SRV records: lowest priority first, highest weight first
|
50
|
-
srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
|
50
|
+
srv.sort! { |a, b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
|
51
51
|
#debug "USING #{srv.first.target.to_s}"
|
52
52
|
return srv.first.target.to_s, srv.first.port
|
53
53
|
else
|
54
54
|
#debug "USING #{domain}:5222"
|
55
55
|
return domain, 5222
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def login &blk
|
61
|
-
Jabber::SASL::new(self, 'PLAIN').auth(@pass)
|
61
|
+
::Jabber::SASL::new(self, 'PLAIN').auth(@pass)
|
62
62
|
@auth_callback = blk if block_given?
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def register &blk
|
66
|
-
reg = Jabber::Iq.new_register(jid.node, @pass)
|
66
|
+
reg = ::Jabber::Iq.new_register(jid.node, @pass)
|
67
67
|
reg.to = jid.domain
|
68
|
-
|
69
|
-
send(reg){ |reply|
|
70
|
-
blk.call(
|
68
|
+
|
69
|
+
send(reg) { |reply|
|
70
|
+
blk.call(reply.type == :result ? :success : reply.type)
|
71
71
|
}
|
72
|
-
end
|
73
|
-
|
72
|
+
end
|
73
|
+
|
74
74
|
def send_msg to, msg
|
75
|
-
send_safe Jabber::Message::new(to, msg).set_type(:chat)
|
75
|
+
send_safe ::Jabber::Message::new(to, msg).set_type(:chat)
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
def receive_stanza(stanza)
|
79
|
-
|
79
|
+
|
80
80
|
case stanza.name
|
81
81
|
when 'features'
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
82
|
+
unless @authenticated
|
83
|
+
login do |res|
|
84
|
+
# log ['login response', res].inspect
|
85
|
+
if res == :failure and @opts[:auto_register]
|
86
|
+
register do |res|
|
87
|
+
#p ['register response', res]
|
88
|
+
login unless res == :error
|
89
|
+
end
|
89
90
|
end
|
90
91
|
end
|
92
|
+
|
93
|
+
else
|
94
|
+
if @connection.stream_features.has_key? 'bind'
|
95
|
+
iq = ::Jabber::Iq.new(:set)
|
96
|
+
bind = iq.add ::REXML::Element.new('bind')
|
97
|
+
bind.add_namespace @connection.stream_features['bind']
|
98
|
+
resource = bind.add ::REXML::Element.new('resource')
|
99
|
+
resource.text=jid.resource
|
100
|
+
|
101
|
+
send(iq) { |reply|
|
102
|
+
if reply.type == :result and jid = reply.first_element('//jid') and jid.text
|
103
|
+
# log ['new jid is', jid.text].inspect
|
104
|
+
@jid = ::Jabber::JID.new(jid.text)
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
if @connection.stream_features.has_key? 'session'
|
110
|
+
iq = ::Jabber::Iq.new(:set)
|
111
|
+
session = iq.add ::REXML::Element.new('session')
|
112
|
+
session.add_namespace @connection.stream_features['session']
|
113
|
+
|
114
|
+
send(iq) { |reply|
|
115
|
+
if reply.type == :result
|
116
|
+
on(:login, stanza)
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
91
120
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
iq = Jabber::Iq.new(:set)
|
96
|
-
bind = iq.add REXML::Element.new('bind')
|
97
|
-
bind.add_namespace @connection.stream_features['bind']
|
98
|
-
resource = bind.add REXML::Element.new('resource')
|
99
|
-
resource.text=jid.resource
|
100
|
-
|
101
|
-
send(iq){ |reply|
|
102
|
-
if reply.type == :result and jid = reply.first_element('//jid') and jid.text
|
103
|
-
# log ['new jid is', jid.text].inspect
|
104
|
-
@jid = Jabber::JID.new(jid.text)
|
105
|
-
end
|
106
|
-
}
|
107
|
-
end
|
108
|
-
|
109
|
-
if @connection.stream_features.has_key? 'session'
|
110
|
-
iq = Jabber::Iq.new(:set)
|
111
|
-
session = iq.add REXML::Element.new('session')
|
112
|
-
session.add_namespace @connection.stream_features['session']
|
113
|
-
|
114
|
-
send(iq){ |reply|
|
115
|
-
if reply.type == :result
|
116
|
-
on(:login, stanza)
|
117
|
-
end
|
118
|
-
}
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
return true
|
123
|
-
|
121
|
+
|
122
|
+
return true
|
123
|
+
|
124
124
|
when 'success', 'failure'
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
125
|
+
if stanza.name == 'success'
|
126
|
+
@authenticated = true
|
127
|
+
@connection.reset_parser
|
128
|
+
@connection.init
|
129
|
+
end
|
130
|
+
|
131
|
+
@auth_callback.call(stanza.name.to_sym) if @auth_callback
|
132
|
+
return true
|
133
133
|
end
|
134
134
|
false
|
135
|
-
end
|
136
|
-
|
135
|
+
end
|
136
|
+
|
137
137
|
end
|
138
138
|
end
|
data/lib/xmpp4em/component.rb
CHANGED
@@ -1,45 +1,44 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
|
3
3
|
module XMPP4EM
|
4
|
-
|
5
|
-
class Component < BaseClient
|
4
|
+
|
5
|
+
class Component < BaseClient
|
6
6
|
def initialize user, pass, opts = {}
|
7
7
|
super
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def jid
|
11
|
-
@jid ||= @user.kind_of?(Jabber::JID) ? @user :
|
11
|
+
@jid ||= @user.kind_of?(::Jabber::JID) ? @user : ::Jabber::JID.new(@user)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def connect host = jid.domain, port = 5222
|
15
|
-
EM.connect host, port, ComponentConnection, jid.domain, port do |conn|
|
15
|
+
::EM.connect host, port, ComponentConnection, jid.domain, port do |conn|
|
16
16
|
@connection = conn
|
17
17
|
conn.client = self
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def receive_stanza(stanza)
|
22
|
-
|
23
22
|
case stanza.name
|
24
23
|
when 'stream'
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
when 'not-authorized'
|
32
|
-
|
33
|
-
|
34
|
-
when 'handshake'
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
|
24
|
+
if !@authenticated && jid.domain == stanza.attributes['from']
|
25
|
+
streamid = stanza.attributes['id']
|
26
|
+
hash = Digest::SHA1::hexdigest(streamid.to_s + @pass)
|
27
|
+
send("<handshake>#{hash}</handshake>")
|
28
|
+
end
|
29
|
+
return true
|
30
|
+
when 'not-authorized'
|
31
|
+
on(:error, 'not-authorized')
|
32
|
+
return true
|
33
|
+
when 'handshake'
|
34
|
+
@authenticated = true
|
35
|
+
on(:login, stanza)
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
40
39
|
false
|
41
|
-
|
40
|
+
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
end
|
45
44
|
end
|
metadata
CHANGED
@@ -1,62 +1,59 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: xmpp4em
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 2
|
8
|
-
- 0
|
9
|
-
version: 0.2.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.3
|
5
|
+
prerelease: !!null
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Aman Gupta
|
13
9
|
- Kokorin Denis
|
14
|
-
autorequire:
|
10
|
+
autorequire: !!null
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2011-09-07 00:00:00.000000000 +04:00
|
14
|
+
default_executable: !!null
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
22
17
|
name: eventmachine
|
23
|
-
|
24
|
-
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 0
|
30
|
-
- 12
|
31
|
-
- 10
|
32
|
-
version: 0.12.10
|
18
|
+
requirement: &11578068 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
33
24
|
type: :runtime
|
34
|
-
|
35
|
-
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *11578068
|
27
|
+
- !ruby/object:Gem::Dependency
|
36
28
|
name: xmpp4r
|
29
|
+
requirement: &11577696 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
37
36
|
prerelease: false
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
version_requirements: *11577696
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: nokogiri
|
40
|
+
requirement: &11577408 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
46
|
type: :runtime
|
47
|
-
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *11577408
|
48
49
|
description: Simple XMPP client and component built on EventMachine.
|
49
50
|
email: mccoder-nospam@ya.ru
|
50
51
|
executables: []
|
51
|
-
|
52
52
|
extensions: []
|
53
|
-
|
54
|
-
extra_rdoc_files: []
|
55
|
-
|
56
|
-
files:
|
53
|
+
extra_rdoc_files:
|
57
54
|
- README.md
|
58
|
-
- Rakefile
|
59
55
|
- History.txt
|
56
|
+
files:
|
60
57
|
- lib/xmpp4em/base_client.rb
|
61
58
|
- lib/xmpp4em/base_connection.rb
|
62
59
|
- lib/xmpp4em/client.rb
|
@@ -66,38 +63,31 @@ files:
|
|
66
63
|
- lib/xmpp4em.rb
|
67
64
|
- examples/component_test.rb
|
68
65
|
- examples/stress_test.rb
|
69
|
-
-
|
70
|
-
-
|
66
|
+
- README.md
|
67
|
+
- History.txt
|
71
68
|
has_rdoc: true
|
72
69
|
homepage: http://github.com/mccoder/xmpp4em
|
73
70
|
licenses: []
|
74
|
-
|
75
|
-
post_install_message:
|
71
|
+
post_install_message: !!null
|
76
72
|
rdoc_options: []
|
77
|
-
|
78
|
-
require_paths:
|
73
|
+
require_paths:
|
79
74
|
- lib
|
80
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
segments:
|
93
|
-
- 0
|
94
|
-
version: "0"
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
95
87
|
requirements: []
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
signing_key:
|
88
|
+
rubyforge_project: !!null
|
89
|
+
rubygems_version: 1.5.0
|
90
|
+
signing_key: !!null
|
100
91
|
specification_version: 3
|
101
92
|
summary: EventMachine based XMPP client and component
|
102
93
|
test_files: []
|
103
|
-
|
data/Rakefile
DELETED
data/spec/spec_runner.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'bacon'
|
2
|
-
$:.unshift File.dirname(__FILE__) + '/..'
|
3
|
-
require 'xmpp4em'
|
4
|
-
|
5
|
-
shared 'eventmachine' do
|
6
|
-
$bacon_thread = Thread.current
|
7
|
-
def wait
|
8
|
-
Thread.stop
|
9
|
-
@timer = EM::Timer.new(10) do
|
10
|
-
wake
|
11
|
-
should.flunk('waited too long')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
def wake
|
15
|
-
$bacon_thread.wakeup
|
16
|
-
@timer.cancel if @timer
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
EM.run{
|
21
|
-
Thread.new{
|
22
|
-
Thread.abort_on_exception = true
|
23
|
-
require 'xmpp4em_spec'
|
24
|
-
EM.stop_event_loop
|
25
|
-
}
|
26
|
-
}
|
data/spec/xmpp4em_spec.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
describe 'XMPP4EM' do
|
2
|
-
behaves_like 'eventmachine'
|
3
|
-
|
4
|
-
@foo = XMPP4EM::Client.new('foo@localhost', 'test', :auto_register => true)
|
5
|
-
@bar = XMPP4EM::Client.new('bar@localhost', 'test', :auto_register => true)
|
6
|
-
|
7
|
-
should 'login to an xmpp server' do
|
8
|
-
@foo.on(:login) do
|
9
|
-
@foo.send Jabber::Presence.new
|
10
|
-
wake
|
11
|
-
end
|
12
|
-
|
13
|
-
@foo.connect
|
14
|
-
wait
|
15
|
-
|
16
|
-
@foo.should.be.connected?
|
17
|
-
end
|
18
|
-
|
19
|
-
should 'send messages to others' do
|
20
|
-
@bar.on(:login) do
|
21
|
-
@bar.send Jabber::Presence.new do
|
22
|
-
wake
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
received = nil
|
27
|
-
@bar.on(:message) do |msg|
|
28
|
-
received = msg.first_element_text('//body')
|
29
|
-
wake
|
30
|
-
end
|
31
|
-
|
32
|
-
@bar.connect
|
33
|
-
wait
|
34
|
-
|
35
|
-
@foo.send_msg 'bar@localhost', 'hello'
|
36
|
-
wait
|
37
|
-
|
38
|
-
received.should == 'hello'
|
39
|
-
end
|
40
|
-
|
41
|
-
should 'fire disconnect callback and reconnect' do
|
42
|
-
user = XMPP4EM::Client.new('user@localhost', 'user', :auto_register => true)
|
43
|
-
user.on(:disconnect){ wake }
|
44
|
-
user.connect 'localhost', 5333 # invalid port
|
45
|
-
wait
|
46
|
-
|
47
|
-
user.should.not.be.connected?
|
48
|
-
|
49
|
-
user.instance_variable_get('@callbacks')[:disconnect] = []
|
50
|
-
user.connection.port = 5222
|
51
|
-
user.on(:login){ wake }
|
52
|
-
user.reconnect
|
53
|
-
wait
|
54
|
-
|
55
|
-
user.should.be.connected?
|
56
|
-
end
|
57
|
-
end
|