blather 0.4.14 → 0.4.15
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/blather.rb +8 -0
- data/lib/blather/client/client.rb +9 -1
- data/lib/blather/client/dsl/pubsub.rb +2 -2
- data/lib/blather/core_ext/active_support.rb +1 -0
- data/lib/blather/core_ext/eventmachine.rb +122 -0
- data/lib/blather/errors/stanza_error.rb +1 -0
- data/lib/blather/file_transfer.rb +100 -0
- data/lib/blather/file_transfer/ibb.rb +68 -0
- data/lib/blather/file_transfer/s5b.rb +104 -0
- data/lib/blather/roster_item.rb +2 -2
- data/lib/blather/stanza/disco/disco_info.rb +17 -2
- data/lib/blather/stanza/iq/ibb.rb +83 -0
- data/lib/blather/stanza/iq/s5b.rb +205 -0
- data/lib/blather/stanza/iq/si.rb +410 -0
- data/lib/blather/stanza/iq/vcard.rb +147 -0
- data/lib/blather/stanza/message.rb +10 -2
- data/lib/blather/stanza/presence/status.rb +11 -3
- data/lib/blather/stanza/pubsub.rb +3 -1
- data/lib/blather/stanza/pubsub/event.rb +18 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +4 -2
- data/lib/blather/stanza/pubsub/unsubscribe.rb +17 -1
- data/lib/blather/stanza/x.rb +12 -2
- data/lib/blather/stream/parser.rb +1 -0
- data/lib/test.rb +55 -0
- data/spec/blather/client/client_spec.rb +18 -4
- data/spec/blather/client/dsl/pubsub_spec.rb +12 -2
- data/spec/blather/client/dsl_spec.rb +1 -1
- data/spec/blather/core_ext/nokogiri_spec.rb +1 -1
- data/spec/blather/errors/sasl_error_spec.rb +1 -1
- data/spec/blather/errors/stanza_error_spec.rb +1 -1
- data/spec/blather/errors/stream_error_spec.rb +1 -1
- data/spec/blather/errors_spec.rb +1 -1
- data/spec/blather/file_transfer_spec.rb +100 -0
- data/spec/blather/jid_spec.rb +1 -1
- data/spec/blather/roster_item_spec.rb +32 -2
- data/spec/blather/roster_spec.rb +1 -1
- data/spec/blather/stanza/discos/disco_info_spec.rb +12 -3
- data/spec/blather/stanza/discos/disco_items_spec.rb +1 -1
- data/spec/blather/stanza/iq/command_spec.rb +1 -1
- data/spec/blather/stanza/iq/ibb_spec.rb +136 -0
- data/spec/blather/stanza/iq/query_spec.rb +1 -1
- data/spec/blather/stanza/iq/roster_spec.rb +1 -1
- data/spec/blather/stanza/iq/s5b_spec.rb +60 -0
- data/spec/blather/stanza/iq/si_spec.rb +101 -0
- data/spec/blather/stanza/iq/vcard_spec.rb +96 -0
- data/spec/blather/stanza/iq_spec.rb +1 -1
- data/spec/blather/stanza/message_spec.rb +48 -2
- data/spec/blather/stanza/presence/status_spec.rb +1 -1
- data/spec/blather/stanza/presence/subscription_spec.rb +1 -1
- data/spec/blather/stanza/presence_spec.rb +1 -1
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/create_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/event_spec.rb +16 -2
- data/spec/blather/stanza/pubsub/items_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/publish_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/retract_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscription_spec.rb +2 -2
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +3 -3
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +15 -2
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_owner_spec.rb +2 -2
- data/spec/blather/stanza/pubsub_spec.rb +14 -2
- data/spec/blather/stanza/x_spec.rb +1 -1
- data/spec/blather/stanza_spec.rb +1 -1
- data/spec/blather/stream/client_spec.rb +1 -1
- data/spec/blather/stream/component_spec.rb +1 -1
- data/spec/blather/stream/parser_spec.rb +11 -1
- data/spec/blather/xmpp_node_spec.rb +1 -1
- data/spec/fixtures/pubsub.rb +2 -2
- data/spec/spec_helper.rb +27 -0
- metadata +85 -23
data/lib/blather.rb
CHANGED
@@ -8,12 +8,16 @@
|
|
8
8
|
logger
|
9
9
|
|
10
10
|
blather/core_ext/active_support
|
11
|
+
blather/core_ext/eventmachine
|
11
12
|
blather/core_ext/nokogiri
|
12
13
|
|
13
14
|
blather/errors
|
14
15
|
blather/errors/sasl_error
|
15
16
|
blather/errors/stanza_error
|
16
17
|
blather/errors/stream_error
|
18
|
+
blather/file_transfer
|
19
|
+
blather/file_transfer/ibb
|
20
|
+
blather/file_transfer/s5b
|
17
21
|
blather/jid
|
18
22
|
blather/roster
|
19
23
|
blather/roster_item
|
@@ -24,6 +28,10 @@
|
|
24
28
|
blather/stanza/iq/query
|
25
29
|
blather/stanza/iq/command
|
26
30
|
blather/stanza/iq/roster
|
31
|
+
blather/stanza/iq/ibb
|
32
|
+
blather/stanza/iq/s5b
|
33
|
+
blather/stanza/iq/si
|
34
|
+
blather/stanza/iq/vcard
|
27
35
|
blather/stanza/disco
|
28
36
|
blather/stanza/disco/disco_info
|
29
37
|
blather/stanza/disco/disco_items
|
@@ -112,9 +112,17 @@ module Blather
|
|
112
112
|
@tmp_handlers[id.to_s] = handler
|
113
113
|
end
|
114
114
|
|
115
|
+
# Clear handlers with given guards
|
116
|
+
#
|
117
|
+
# @param [Symbol, nil] type remove filters for a specific handler
|
118
|
+
# @param [guards] guards take a look at the guards documentation
|
119
|
+
def clear_handlers(type, *guards)
|
120
|
+
@handlers[type].delete_if { |g, _| g == guards }
|
121
|
+
end
|
122
|
+
|
115
123
|
# Register a handler
|
116
124
|
#
|
117
|
-
# @param [Symbol, nil]
|
125
|
+
# @param [Symbol, nil] type set the filter on a specific handler
|
118
126
|
# @param [guards] guards take a look at the guards documentation
|
119
127
|
# @yield [Blather::Stanza] stanza the incomming stanza
|
120
128
|
def register_handler(type, *guards, &handler)
|
@@ -87,9 +87,9 @@ module DSL
|
|
87
87
|
# Defaults to the stripped current JID
|
88
88
|
# @param [#to_s] host the PubSub host (defaults to the initialized host)
|
89
89
|
# @yield [Blather::Stanza] stanza the reply stanza
|
90
|
-
def unsubscribe(node, jid = nil, host = nil)
|
90
|
+
def unsubscribe(node, jid = nil, subid = nil, host = nil)
|
91
91
|
jid ||= client.jid.stripped
|
92
|
-
stanza = Stanza::PubSub::Unsubscribe.new(:set, send_to(host), node, jid)
|
92
|
+
stanza = Stanza::PubSub::Unsubscribe.new(:set, send_to(host), node, jid, subid)
|
93
93
|
request(stanza) { |n| yield n if block_given? }
|
94
94
|
end
|
95
95
|
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module EventMachine
|
2
|
+
module Protocols
|
3
|
+
# Basic SOCKS v5 client implementation
|
4
|
+
#
|
5
|
+
# Use as you would any regular connection:
|
6
|
+
#
|
7
|
+
# class MyConn < EM::P::Socks5
|
8
|
+
# def post_init
|
9
|
+
# send_data("sup")
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# def receive_data(data)
|
13
|
+
# send_data("you said: #{data}")
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# EM.connect socks_host, socks_port, MyConn, host, port
|
18
|
+
#
|
19
|
+
class Socks5 < Connection
|
20
|
+
def initialize(host, port)
|
21
|
+
@host = host
|
22
|
+
@port = port
|
23
|
+
@socks_error_code = nil
|
24
|
+
@buffer = ''
|
25
|
+
@socks_state = :method_negotiation
|
26
|
+
@socks_methods = [0] # TODO: other authentication methods
|
27
|
+
setup_methods
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_methods
|
31
|
+
class << self
|
32
|
+
def post_init; socks_post_init; end
|
33
|
+
def receive_data(*a); socks_receive_data(*a); end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def restore_methods
|
38
|
+
class << self
|
39
|
+
remove_method :post_init
|
40
|
+
remove_method :receive_data
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def socks_post_init
|
45
|
+
packet = [5, @socks_methods.size].pack('CC') + @socks_methods.pack('C*')
|
46
|
+
send_data(packet)
|
47
|
+
end
|
48
|
+
|
49
|
+
def socks_receive_data(data)
|
50
|
+
@buffer << data
|
51
|
+
|
52
|
+
if @socks_state == :method_negotiation
|
53
|
+
return if @buffer.size < 2
|
54
|
+
|
55
|
+
header_resp = @buffer.slice! 0, 2
|
56
|
+
_, method_code = header_resp.unpack("cc")
|
57
|
+
|
58
|
+
if @socks_methods.include?(method_code)
|
59
|
+
@socks_state = :connecting
|
60
|
+
packet = [5, 1, 0].pack("C*")
|
61
|
+
|
62
|
+
if @host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ # IPv4
|
63
|
+
packet << [1, $1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*")
|
64
|
+
elsif @host.include?(":") # IPv6
|
65
|
+
l, r = if @host =~ /^(.*)::(.*)$/
|
66
|
+
[$1,$2].map {|i| i.split ":"}
|
67
|
+
else
|
68
|
+
[@host.split(":"),[]]
|
69
|
+
end
|
70
|
+
dec_groups = (l + Array.new(8-l.size-r.size, '0') + r).map {|i| i.hex}
|
71
|
+
packet << ([4] + dec_groups).pack("Cn8")
|
72
|
+
else # Domain
|
73
|
+
packet << [3, @host.length, @host].pack("CCA*")
|
74
|
+
end
|
75
|
+
packet << [@port].pack("n")
|
76
|
+
|
77
|
+
send_data packet
|
78
|
+
else
|
79
|
+
@socks_state = :invalid
|
80
|
+
@socks_error_code = method_code
|
81
|
+
close_connection
|
82
|
+
return
|
83
|
+
end
|
84
|
+
elsif @socks_state == :connecting
|
85
|
+
return if @buffer.size < 4
|
86
|
+
|
87
|
+
header_resp = @buffer.slice! 0, 4
|
88
|
+
_, response_code, _, address_type = header_resp.unpack("C*")
|
89
|
+
|
90
|
+
if response_code == 0
|
91
|
+
case address_type
|
92
|
+
when 1
|
93
|
+
@buffer.slice! 0, 4
|
94
|
+
when 3
|
95
|
+
len = @buffer.slice! 0, 1
|
96
|
+
@buffer.slice! 0, len.unpack("C").first
|
97
|
+
when 4
|
98
|
+
@buffer.slice! 0, 16
|
99
|
+
else
|
100
|
+
@socks_state = :invalid
|
101
|
+
@socks_error_code = address_type
|
102
|
+
close_connection
|
103
|
+
return
|
104
|
+
end
|
105
|
+
@buffer.slice! 0, 2
|
106
|
+
|
107
|
+
@socks_state = :connected
|
108
|
+
restore_methods
|
109
|
+
|
110
|
+
post_init
|
111
|
+
receive_data(@buffer) unless @buffer.empty?
|
112
|
+
else
|
113
|
+
@socks_state = :invalid
|
114
|
+
@socks_error_code = response_code
|
115
|
+
close_connection
|
116
|
+
return
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Blather
|
2
|
+
# File Transfer helper
|
3
|
+
# Takes care of accepting, declining and offering file transfers through the stream
|
4
|
+
class FileTransfer
|
5
|
+
|
6
|
+
# Set this to false if you don't want to use In-Band Bytestreams
|
7
|
+
attr_accessor :allow_ibb
|
8
|
+
|
9
|
+
# Set this to false if you don't want to use SOCKS5 Bytestreams
|
10
|
+
attr_accessor :allow_s5b
|
11
|
+
|
12
|
+
# Create a new FileTransfer
|
13
|
+
#
|
14
|
+
# @param [Blather::Stream] stream the stream the file transfer should use
|
15
|
+
# @param [Blather::Stanza::Iq::Si] iq a si iq used to stream-initiation
|
16
|
+
def initialize(stream, iq = nil)
|
17
|
+
@stream = stream
|
18
|
+
@allow_s5b = true
|
19
|
+
@allow_ibb = true
|
20
|
+
|
21
|
+
@iq = iq
|
22
|
+
end
|
23
|
+
|
24
|
+
# Accept an incoming file-transfer
|
25
|
+
#
|
26
|
+
# @param [module] handler the handler for incoming data, see Blather::FileTransfer::SimpleFileReceiver for an example
|
27
|
+
# @param [Array] params the params to be passed into the handler
|
28
|
+
def accept(handler, *params)
|
29
|
+
answer = @iq.reply
|
30
|
+
|
31
|
+
answer.si.feature.x.type = :submit
|
32
|
+
|
33
|
+
supported_methods = @iq.si.feature.x.field("stream-method").options.map(&:value)
|
34
|
+
if supported_methods.include?(Stanza::Iq::S5b::NS_S5B) and @allow_s5b
|
35
|
+
answer.si.feature.x.fields = {:var => 'stream-method', :value => Stanza::Iq::S5b::NS_S5B}
|
36
|
+
|
37
|
+
@stream.register_handler :s5b_open, :from => @iq.from do |iq|
|
38
|
+
transfer = Blather::FileTransfer::S5b.new(@stream, iq)
|
39
|
+
transfer.allow_ibb_fallback = true if @allow_ibb
|
40
|
+
transfer.accept(handler, *params)
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
@stream.write answer
|
45
|
+
elsif supported_methods.include?(Stanza::Iq::Ibb::NS_IBB) and @allow_ibb
|
46
|
+
answer.si.feature.x.fields = {:var => 'stream-method', :value => Stanza::Iq::Ibb::NS_IBB}
|
47
|
+
|
48
|
+
@stream.register_handler :ibb_open, :from => @iq.from do |iq|
|
49
|
+
transfer = Blather::FileTransfer::Ibb.new(@stream, iq)
|
50
|
+
transfer.accept(handler, *params)
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
@stream.write answer
|
55
|
+
else
|
56
|
+
reason = XMPPNode.new('no-valid-streams')
|
57
|
+
reason.namespace = Blather::Stanza::Iq::Si::NS_SI
|
58
|
+
|
59
|
+
@stream.write StanzaError.new(@iq, 'bad-request', 'cancel', nil, [reason]).to_node
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Decline an incoming file-transfer
|
64
|
+
def decline
|
65
|
+
answer = StanzaError.new(@iq, 'forbidden', 'cancel', 'Offer declined').to_node
|
66
|
+
|
67
|
+
@stream.write answer
|
68
|
+
end
|
69
|
+
|
70
|
+
# Offer a file to somebody, not implemented yet
|
71
|
+
def offer
|
72
|
+
# TODO: implement
|
73
|
+
end
|
74
|
+
|
75
|
+
# Simple handler for incoming file transfers
|
76
|
+
#
|
77
|
+
# You can define your own handler and pass it to the accept method.
|
78
|
+
module SimpleFileReceiver
|
79
|
+
def initialize(path, size)
|
80
|
+
@path = path
|
81
|
+
@size = size
|
82
|
+
@transferred = 0
|
83
|
+
end
|
84
|
+
|
85
|
+
def post_init
|
86
|
+
@file = File.open(@path, "w")
|
87
|
+
end
|
88
|
+
|
89
|
+
def receive_data(data)
|
90
|
+
@transferred += data.size
|
91
|
+
@file.write data
|
92
|
+
end
|
93
|
+
|
94
|
+
def unbind
|
95
|
+
@file.close
|
96
|
+
File.delete(@path) unless @transferred == @size
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module Blather
|
4
|
+
class FileTransfer
|
5
|
+
# In-Band Bytestreams Transfer helper
|
6
|
+
# Takes care of accepting, declining and offering file transfers through the stream
|
7
|
+
class Ibb
|
8
|
+
def initialize(stream, iq)
|
9
|
+
@stream = stream
|
10
|
+
@iq = iq
|
11
|
+
@seq = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
# Accept an incoming file-transfer
|
15
|
+
#
|
16
|
+
# @param [module] handler the handler for incoming data, see Blather::FileTransfer::SimpleFileReceiver for an example
|
17
|
+
# @param [Array] params the params to be passed into the handler
|
18
|
+
def accept(handler, *params)
|
19
|
+
@io_read, @io_write = IO.pipe
|
20
|
+
EM::attach @io_read, handler, *params
|
21
|
+
|
22
|
+
@stream.register_handler :ibb_data, :from => @iq.from, :sid => @iq.sid do |iq|
|
23
|
+
if iq.data['seq'] == @seq.to_s
|
24
|
+
begin
|
25
|
+
@io_write << Base64.decode64(iq.data.content)
|
26
|
+
|
27
|
+
@stream.write iq.reply
|
28
|
+
|
29
|
+
@seq += 1
|
30
|
+
@seq = 0 if @seq > 65535
|
31
|
+
rescue Errno::EPIPE => e
|
32
|
+
@stream.write StanzaError.new(iq, 'not-acceptable', :cancel).to_node
|
33
|
+
end
|
34
|
+
else
|
35
|
+
@stream.write StanzaError.new(iq, 'unexpected-request', :wait).to_node
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
@stream.register_handler :ibb_close, :from => @iq.from, :sid => @iq.sid do |iq|
|
41
|
+
@stream.write iq.reply
|
42
|
+
@stream.clear_handlers :ibb_data, :from => @iq.from, :sid => @iq.sid
|
43
|
+
@stream.clear_handlers :ibb_close, :from => @iq.from, :sid => @iq.sid
|
44
|
+
|
45
|
+
@io_write.close
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
@stream.clear_handlers :ibb_open, :from => @iq.from
|
50
|
+
@stream.clear_handlers :ibb_open, :from => @iq.from, :sid => @iq.sid
|
51
|
+
@stream.write @iq.reply
|
52
|
+
end
|
53
|
+
|
54
|
+
# Decline an incoming file-transfer
|
55
|
+
def decline
|
56
|
+
@stream.clear_handlers :ibb_open, :from => @iq.from
|
57
|
+
@stream.clear_handlers :ibb_data, :from => @iq.from, :sid => @iq.sid
|
58
|
+
@stream.clear_handlers :ibb_close, :from => @iq.from, :sid => @iq.sid
|
59
|
+
@stream.write StanzaError.new(@iq, 'not-acceptable', :cancel).to_node
|
60
|
+
end
|
61
|
+
|
62
|
+
# Offer a file to somebody, not implemented yet
|
63
|
+
def offer
|
64
|
+
# TODO: implement
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Blather
|
2
|
+
class FileTransfer
|
3
|
+
# SOCKS5 Bytestreams Transfer helper
|
4
|
+
# Takes care of accepting, declining and offering file transfers through the stream
|
5
|
+
class S5b
|
6
|
+
|
7
|
+
# Set this to false if you don't want to fallback to In-Band Bytestreams
|
8
|
+
attr_accessor :allow_ibb_fallback
|
9
|
+
|
10
|
+
def initialize(stream, iq)
|
11
|
+
@stream = stream
|
12
|
+
@iq = iq
|
13
|
+
@allow_ibb_fallback = true
|
14
|
+
end
|
15
|
+
|
16
|
+
# Accept an incoming file-transfer
|
17
|
+
#
|
18
|
+
# @param [module] handler the handler for incoming data, see Blather::FileTransfer::SimpleFileReceiver for an example
|
19
|
+
# @param [Array] params the params to be passed into the handler
|
20
|
+
def accept(handler, *params)
|
21
|
+
@streamhosts = @iq.streamhosts
|
22
|
+
@socket_address = Digest::SHA1.hexdigest("#{@iq.sid}#{@iq.from}#{@iq.to}")
|
23
|
+
|
24
|
+
@handler = handler
|
25
|
+
@params = params
|
26
|
+
|
27
|
+
connect_next_streamhost
|
28
|
+
@stream.clear_handlers :s5b_open, :from => @iq.from
|
29
|
+
end
|
30
|
+
|
31
|
+
# Decline an incoming file-transfer
|
32
|
+
def decline
|
33
|
+
@stream.clear_handlers :s5b_open, :from => @iq.from
|
34
|
+
@stream.write StanzaError.new(@iq, 'not-acceptable', :auth).to_node
|
35
|
+
end
|
36
|
+
|
37
|
+
# Offer a file to somebody, not implemented yet
|
38
|
+
def offer
|
39
|
+
# TODO: implement
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def connect_next_streamhost
|
45
|
+
if streamhost = @streamhosts.shift
|
46
|
+
connect(streamhost)
|
47
|
+
else
|
48
|
+
if @allow_ibb_fallback
|
49
|
+
@stream.register_handler :ibb_open, :from => @iq.from, :sid => @iq.sid do |iq|
|
50
|
+
transfer = Blather::FileTransfer::Ibb.new(@stream, iq)
|
51
|
+
transfer.accept(@handler, *@params)
|
52
|
+
true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@stream.write StanzaError.new(@iq, 'item-not-found', :cancel).to_node
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def connect(streamhost)
|
61
|
+
begin
|
62
|
+
socket = EM.connect streamhost.host, streamhost.port, SocketConnection, @socket_address, 0, @handler, *@params
|
63
|
+
|
64
|
+
socket.callback do
|
65
|
+
answer = @iq.reply
|
66
|
+
answer.streamhosts = nil
|
67
|
+
answer.streamhost_used = streamhost.jid
|
68
|
+
|
69
|
+
@stream.write answer
|
70
|
+
end
|
71
|
+
|
72
|
+
socket.errback do
|
73
|
+
connect_next_streamhost
|
74
|
+
end
|
75
|
+
rescue EventMachine::ConnectionError => e
|
76
|
+
connect_next_streamhost
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class SocketConnection < EM::P::Socks5
|
81
|
+
include EM::Deferrable
|
82
|
+
|
83
|
+
def initialize(host, port, handler, *params)
|
84
|
+
super(host, port)
|
85
|
+
@@handler = handler
|
86
|
+
@params = params
|
87
|
+
end
|
88
|
+
|
89
|
+
def post_init
|
90
|
+
self.succeed
|
91
|
+
class << self
|
92
|
+
include @@handler
|
93
|
+
end
|
94
|
+
send(:initialize, *@params)
|
95
|
+
post_init
|
96
|
+
end
|
97
|
+
|
98
|
+
def unbind
|
99
|
+
self.fail if @socks_state != :connected
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|