fargo 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +61 -0
- data/ext/fargo/extconf.rb +1 -1
- data/ext/fargo/fargo_tth.c +0 -2
- data/lib/fargo/client.rb +30 -24
- data/lib/fargo/parser.rb +90 -59
- data/lib/fargo/protocol/dc.rb +24 -8
- data/lib/fargo/protocol/hub.rb +41 -20
- data/lib/fargo/protocol/peer.rb +114 -0
- data/lib/fargo/protocol/{download.rb → peer_download.rb} +51 -115
- data/lib/fargo/protocol/peer_upload.rb +160 -0
- data/lib/fargo/search.rb +38 -5
- data/lib/fargo/supports/downloads.rb +17 -17
- data/lib/fargo/supports/local_file_list.rb +164 -0
- data/lib/fargo/supports/nick_list.rb +18 -5
- data/lib/fargo/supports/persistence.rb +2 -2
- data/lib/fargo/supports/{file_list.rb → remote_file_list.rb} +4 -5
- data/lib/fargo/supports/searches.rb +5 -12
- data/lib/fargo/supports/uploads.rb +24 -5
- data/lib/fargo/version.rb +1 -1
- data/lib/fargo.rb +12 -3
- data/spec/fargo/parser_spec.rb +198 -0
- data/spec/fargo/protocol/dc_spec.rb +77 -0
- data/spec/fargo/protocol/hub_spec.rb +155 -0
- data/spec/fargo/protocol/peer_download_spec.rb +104 -0
- data/spec/fargo/protocol/peer_spec.rb +58 -0
- data/spec/fargo/protocol/peer_upload_spec.rb +128 -0
- data/spec/fargo/search_spec.rb +107 -0
- data/spec/fargo/supports/chat_spec.rb +33 -0
- data/spec/fargo/supports/local_file_list_spec.rb +70 -0
- data/spec/fargo/supports/nick_list_spec.rb +35 -0
- data/spec/fargo/utils_spec.rb +26 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/matchers.rb +17 -0
- metadata +37 -9
- data/lib/fargo/search_result.rb +0 -31
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Fargo
|
2
|
+
|
3
|
+
This gem is an implementation of the [Direct Connect (DC) protocol](http://en.wikipedia.org/wiki/Direct_Connect_\(file_sharing\)) in ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
`gem install fargo`
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
<pre>
|
12
|
+
require 'fargo'
|
13
|
+
|
14
|
+
client = Fargo::Client.new
|
15
|
+
|
16
|
+
client.configure do |config|
|
17
|
+
config.hub_address = [address of the hub] # Defaults to 127.0.0.1
|
18
|
+
config.hub_port = [port of the hub] # Defaults to 7314
|
19
|
+
config.passive = true # Defaults to false
|
20
|
+
config.address = '1.2.3.4' # Defaults to machine IP
|
21
|
+
config.active_port = [port to listen on] # Defaults to 7315
|
22
|
+
config.search_port = [port to listen on] # Defaults to 7316
|
23
|
+
end
|
24
|
+
|
25
|
+
EventMachine.run {
|
26
|
+
client.connect
|
27
|
+
|
28
|
+
client.nicks # list of nicks registered
|
29
|
+
client.download nick, file # download a file from a user
|
30
|
+
client.file_list nick # get a list of files from a user
|
31
|
+
|
32
|
+
client.channel.subscribe do |type, message|
|
33
|
+
# type is the type of message
|
34
|
+
# message is a hash of what was received
|
35
|
+
end
|
36
|
+
}
|
37
|
+
</pre>
|
38
|
+
|
39
|
+
See `lib/fargo/client.rb` for a full list of configuration options
|
40
|
+
|
41
|
+
## MIT License
|
42
|
+
|
43
|
+
Copyright (c) 2010 Alex Crichton
|
44
|
+
|
45
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
46
|
+
of this software and associated documentation files (the "Software"), to deal
|
47
|
+
in the Software without restriction, including without limitation the rights
|
48
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
49
|
+
copies of the Software, and to permit persons to whom the Software is
|
50
|
+
furnished to do so, subject to the following conditions:
|
51
|
+
|
52
|
+
The above copyright notice and this permission notice shall be included in
|
53
|
+
all copies or substantial portions of the Software.
|
54
|
+
|
55
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
56
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
57
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
58
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
59
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
60
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
61
|
+
THE SOFTWARE.
|
data/ext/fargo/extconf.rb
CHANGED
data/ext/fargo/fargo_tth.c
CHANGED
data/lib/fargo/client.rb
CHANGED
@@ -8,19 +8,21 @@ module Fargo
|
|
8
8
|
include ActiveSupport::Configurable
|
9
9
|
include ActiveSupport::Callbacks
|
10
10
|
|
11
|
-
define_callbacks :initialization
|
12
|
-
|
13
|
-
include
|
14
|
-
include
|
15
|
-
include
|
16
|
-
include
|
17
|
-
include
|
18
|
-
include
|
19
|
-
include
|
20
|
-
include
|
11
|
+
define_callbacks :initialization, :connect
|
12
|
+
|
13
|
+
include Supports::Chat
|
14
|
+
include Supports::Uploads
|
15
|
+
include Supports::NickList
|
16
|
+
include Supports::Searches
|
17
|
+
include Supports::Downloads
|
18
|
+
include Supports::Persistence
|
19
|
+
include Supports::Timeout
|
20
|
+
include Supports::RemoteFileList
|
21
|
+
include Supports::LocalFileList
|
21
22
|
|
22
23
|
configure do |config|
|
23
24
|
config.download_dir = '/tmp/fargo/downloads'
|
25
|
+
config.config_dir = '/tmp/fargo/config'
|
24
26
|
config.address = IPSocket.getaddress(Socket.gethostname)
|
25
27
|
config.passive = false
|
26
28
|
config.nick = 'fargo'
|
@@ -33,6 +35,8 @@ module Fargo
|
|
33
35
|
config.password = ''
|
34
36
|
config.speed = 'DSL'
|
35
37
|
config.email = nil
|
38
|
+
|
39
|
+
config.override_share_size = 5368709121 # 5 GB + 1 byte
|
36
40
|
end
|
37
41
|
|
38
42
|
attr_reader :hub, :channel
|
@@ -54,21 +58,23 @@ module Fargo
|
|
54
58
|
Fargo.logger.debug e.backtrace.join("\n")
|
55
59
|
}
|
56
60
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
unless config.passive
|
64
|
-
EventMachine.start_server '0.0.0.0', config.active_port,
|
65
|
-
Fargo::Protocol::Download do |conn|
|
66
|
-
conn.client = self
|
61
|
+
run_callbacks :connect do
|
62
|
+
EventMachine.connect config.hub_address, config.hub_port,
|
63
|
+
Protocol::Hub do |conn|
|
64
|
+
@hub = conn
|
65
|
+
@hub.client = self
|
67
66
|
end
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
unless config.passive
|
69
|
+
EventMachine.start_server '0.0.0.0', config.active_port,
|
70
|
+
Protocol::Peer do |conn|
|
71
|
+
conn.client = self
|
72
|
+
end
|
73
|
+
|
74
|
+
EventMachine.open_datagram_socket '0.0.0.0', config.search_port,
|
75
|
+
Protocol::DC do |conn|
|
76
|
+
conn.client = self
|
77
|
+
end
|
72
78
|
end
|
73
79
|
end
|
74
80
|
end
|
@@ -83,7 +89,7 @@ module Fargo
|
|
83
89
|
end
|
84
90
|
|
85
91
|
def description
|
86
|
-
"<fargo V:#{
|
92
|
+
"<fargo V:#{VERSION},M:#{config.passive ? 'P' : 'A'},H:1/0/0,S:#{open_upload_slots},Dt:1.2.6/W>"
|
87
93
|
end
|
88
94
|
|
89
95
|
end
|
data/lib/fargo/parser.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Fargo
|
2
2
|
module Parser
|
3
|
-
|
3
|
+
|
4
4
|
#
|
5
5
|
# See <http://www.teamfair.info/DC-Protocol.htm> for more information
|
6
6
|
#
|
7
|
-
@@commandmatch =
|
7
|
+
@@commandmatch = /^\$(.*)$/
|
8
8
|
@@messagematch = /^<(.*?)> (.*)$/
|
9
|
-
|
9
|
+
|
10
10
|
# TODO: Supports, UserIP, ops command
|
11
11
|
# Client - hub commands
|
12
12
|
@@validatedenied = /^ValidateDenide/
|
@@ -24,35 +24,39 @@ module Fargo
|
|
24
24
|
@@hubto = /^To: (.*?) From: Hub \$(.*)$/
|
25
25
|
@@ctm = /^ConnectToMe (.*?) (.*?):(.*?)$/
|
26
26
|
@@nicklist = /^NickList (.*?)$/
|
27
|
-
@@psr = /^SR (.*?) (.*?)\005(.*?) (.*?)\/(.*?)\005(.*?) \((.*?):(.*?)\)
|
27
|
+
@@psr = /^SR (.*?) (.*?)\005(.*?) (.*?)\/(.*?)\005(.*?) \((.*?):(.*?)\)(?:\005.*)?$/
|
28
|
+
@@psrd = /^SR (.*?) (.*?) (.*?)\/(.*?)\005(.*?) \((.*?):(.*?)\)(?:\005.*)?$/
|
28
29
|
@@psearch = /^Search Hub:(.*) (.)\?(.)\?(.*)\?(.)\?(.*)$/
|
29
30
|
@@search = /^Search (.*):(.*) (.)\?(.)\?(.*)\?(.)\?(.*)$/
|
30
31
|
@@oplist = /^OpList (.*?)$/
|
31
32
|
@@botlist = /^BotList (.*?)$/
|
32
33
|
@@quit = /^Quit (.*)$/
|
33
|
-
@@sr = /^SR (.*?) (.*?)\005(.*?) (.*?)\/(.*?)\005(.*?) (.*?):(.*?)$/
|
34
34
|
@@rctm = /^RevConnectToMe (.*?) (.*?)$/
|
35
|
-
|
35
|
+
|
36
36
|
# Client to client commands
|
37
|
-
@@mynick
|
38
|
-
@@key
|
39
|
-
@@direction
|
40
|
-
@@get
|
41
|
-
@@
|
42
|
-
@@
|
43
|
-
@@
|
44
|
-
@@
|
45
|
-
@@
|
46
|
-
@@
|
47
|
-
@@
|
48
|
-
@@
|
49
|
-
@@
|
50
|
-
|
37
|
+
@@mynick = /^MyNick (.*)$/
|
38
|
+
@@key = /^Key (.*)$/
|
39
|
+
@@direction = /^Direction (Download|Upload) (\d+)$/
|
40
|
+
@@get = /^Get (.*)\$(\d+)$/
|
41
|
+
@@getzblock = /^U?GetZBlock (.*?) (.*?) (.*?)$/
|
42
|
+
@@send = /^Send$/
|
43
|
+
@@filelength = /^FileLength (.*?)$/
|
44
|
+
@@getlistlen = /^GetListLen$/
|
45
|
+
@@maxedout = /^MaxedOut$/
|
46
|
+
@@supports = /^Supports (.*)$/
|
47
|
+
@@error = /^Error (.*)$/
|
48
|
+
@@cancel = /^Cancel$/
|
49
|
+
@@canceled = /^Canceled$/
|
50
|
+
@@failed = /^Failed (.*)$/
|
51
|
+
@@sending = /^Sending (.*)$/
|
52
|
+
@@getblock = /^U?GetBlock (.*?) (.*?) (.*)$/
|
53
|
+
@@adcsnd = /^ADCSND (.*?) (.*?) (.*?) (.*?)( ZL1)?$/
|
54
|
+
@@adcget = /^ADCGET (.*?) (.*?) (.*?) (.*?)( ZL1)?$/
|
55
|
+
|
51
56
|
def parse_message text
|
52
57
|
case text
|
53
58
|
when @@commandmatch then parse_command_message $1
|
54
59
|
when @@messagematch then {:type => :chat, :from => $1, :text => $2}
|
55
|
-
when '' then {:type => :garbage}
|
56
60
|
else {:type => :mystery, :text => text}
|
57
61
|
end
|
58
62
|
end
|
@@ -64,58 +68,85 @@ module Fargo
|
|
64
68
|
when @@badpass then {:type => :badpass}
|
65
69
|
when @@lock then {:type => :lock, :lock => $1}
|
66
70
|
when @@hubname then {:type => :hubname, :name => $1}
|
67
|
-
when @@
|
71
|
+
when @@hubfull then {:type => :hubfull}
|
68
72
|
when @@hubtopic then {:type => :hubtopic, :topic => $1}
|
69
|
-
when @@hello then {:type => :hello, :
|
70
|
-
when @@myinfo then {:type => :myinfo, :nick => $1,
|
73
|
+
when @@hello then {:type => :hello, :nick => $1}
|
74
|
+
when @@myinfo then {:type => :myinfo, :nick => $1,
|
75
|
+
:interest => $2, :speed => $3,
|
71
76
|
:email => $4, :sharesize => $5.to_i}
|
72
|
-
when @@myinfo2 then {:type => :myinfo, :nick=> $1,
|
73
|
-
|
74
|
-
when @@
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
when @@
|
79
|
-
:
|
80
|
-
|
77
|
+
when @@myinfo2 then {:type => :myinfo, :nick=> $1,
|
78
|
+
:interest => $2, :sharesize => 0}
|
79
|
+
when @@to then {:type => :privmsg, :to => $1, :from => $2,
|
80
|
+
:text => $3}
|
81
|
+
when @@hubto then {:type => :privmsg, :to => $1,
|
82
|
+
:from => 'Hub', :text => $2}
|
83
|
+
when @@ctm then {:type => :connect_to_me, :nick => $1,
|
84
|
+
:address => $2, :port => $3.to_i}
|
85
|
+
when @@nicklist then {:type => :nick_list,
|
86
|
+
:nicks => $1.split('$$')}
|
87
|
+
when @@psr then {:type => :search_result, :nick => $1,
|
88
|
+
:file => $2, :size => $3.to_i,
|
89
|
+
:open_slots => $4.to_i, :slots => $5.to_i,
|
90
|
+
:hub => $6, :address => $7,
|
81
91
|
:port => $8.to_i}
|
82
|
-
when @@
|
83
|
-
:
|
92
|
+
when @@psrd then {:type => :search_result, :nick => $1,
|
93
|
+
:dir => $2,
|
94
|
+
:open_slots => $3.to_i, :slots => $4.to_i,
|
95
|
+
:hub => $5, :address => $6,
|
96
|
+
:port => $7.to_i}
|
97
|
+
when @@psearch then {:type => :search, :searcher => $1,
|
98
|
+
:restrict_size => $2 == 'T',
|
99
|
+
:is_minimum_size => $3 == 'F',
|
100
|
+
:size => $4.to_i, :filetype => $5.to_i,
|
84
101
|
:pattern => $6}
|
85
|
-
when @@search then {:type => :search, :address => $1,
|
86
|
-
:
|
87
|
-
:
|
88
|
-
:
|
89
|
-
|
90
|
-
|
91
|
-
when @@
|
92
|
-
|
93
|
-
|
94
|
-
:
|
102
|
+
when @@search then {:type => :search, :address => $1,
|
103
|
+
:port => $2.to_i,
|
104
|
+
:restrict_size => $3 == 'T',
|
105
|
+
:is_minimum_size => $4 == 'F',
|
106
|
+
:size => $5.to_i,
|
107
|
+
:filetype => $6.to_i, :pattern => $7}
|
108
|
+
when @@oplist then {:type => :op_list,
|
109
|
+
:nicks => $1.split('$$')}
|
110
|
+
when @@oplist then {:type => :bot_list,
|
111
|
+
:nicks => $1.split('$$')}
|
112
|
+
when @@quit then {:type => :quit, :nick => $1}
|
95
113
|
when @@rctm then {:type => :revconnect, :who => $1}
|
96
|
-
|
114
|
+
|
97
115
|
when @@mynick then {:type => :mynick, :nick => $1}
|
98
116
|
when @@key then {:type => :key, :key => $1}
|
99
|
-
when @@direction then {:type => :direction,
|
100
|
-
|
117
|
+
when @@direction then {:type => :direction,
|
118
|
+
:direction => $1.downcase,
|
119
|
+
:number => $3.to_i}
|
120
|
+
when @@get then {:type => :get, :file => $1,
|
121
|
+
:offset => $2.to_i - 1, :size => -1}
|
101
122
|
when @@send then {:type => :send}
|
102
123
|
when @@filelength then {:type => :file_length, :size => $1.to_i}
|
103
124
|
when @@getlistlen then {:type => :getlistlen}
|
104
125
|
when @@maxedout then {:type => :noslots}
|
105
|
-
when @@supports then {:type => :supports,
|
126
|
+
when @@supports then {:type => :supports,
|
127
|
+
:extensions => $1.split(' ')}
|
106
128
|
when @@error then {:type => :error, :message => $1}
|
107
|
-
when @@
|
108
|
-
|
109
|
-
when @@
|
110
|
-
|
111
|
-
when @@
|
112
|
-
:
|
113
|
-
|
129
|
+
when @@failed then {:type => :error, :message => $1}
|
130
|
+
when @@cancel then {:type => :cancel}
|
131
|
+
when @@canceled then {:type => :canceled}
|
132
|
+
when @@sending then {:type => :sending, :size => $1.to_i}
|
133
|
+
when @@adcsnd then {:type => :adcsnd, :kind => $1, :file => $2,
|
134
|
+
:offset => $3.to_i, :size => $4.to_i,
|
135
|
+
:zlib => !$5.nil?}
|
136
|
+
when @@adcget then {:type => :adcget, :kind => $1, :file => $2,
|
137
|
+
:offset => $3.to_i, :size => $4.to_i,
|
138
|
+
:zlib => !$5.nil?}
|
139
|
+
when @@getzblock then {:type => :getblock, :file => $3,
|
140
|
+
:size => $2.to_i, :offset => $1.to_i,
|
141
|
+
:zlib => true}
|
142
|
+
when @@getblock then {:type => :getblock, :start => $1.to_i,
|
143
|
+
:size => $2.to_i, :file => $3}
|
144
|
+
when @@userip then
|
114
145
|
h = {:type => :userip, :users => {}}
|
115
|
-
$1.split(
|
146
|
+
$1.split('$$').map{ |s| h[:users][s.split(' ')[0]] = s.split(' ')[1]}
|
116
147
|
h
|
117
|
-
else {:type => :mystery, :text => text}
|
148
|
+
else {:type => :mystery, :text => '$' + text}
|
118
149
|
end
|
119
150
|
end
|
120
151
|
end
|
121
|
-
end
|
152
|
+
end
|
data/lib/fargo/protocol/dc.rb
CHANGED
@@ -2,7 +2,7 @@ module Fargo
|
|
2
2
|
module Protocol
|
3
3
|
module DC
|
4
4
|
|
5
|
-
include
|
5
|
+
include Parser
|
6
6
|
attr_accessor :client
|
7
7
|
|
8
8
|
def post_init
|
@@ -24,14 +24,27 @@ module Fargo
|
|
24
24
|
send_data data
|
25
25
|
end
|
26
26
|
|
27
|
+
def receive_data_chunk chunk
|
28
|
+
chunk.chomp! '|'
|
29
|
+
Fargo.logger.debug "#{self}: Received: #{chunk.inspect}"
|
30
|
+
hash = parse_message chunk
|
31
|
+
receive_message hash[:type], hash
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_data?
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
27
38
|
def receive_data data
|
28
|
-
|
39
|
+
if parse_data?
|
40
|
+
@received_data << data
|
29
41
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
42
|
+
while parse_data? && chunk = @received_data.slice!(/[^\|]+\|/)
|
43
|
+
receive_data_chunk chunk
|
44
|
+
end
|
45
|
+
else
|
46
|
+
receive_data_chunk @received_data + data
|
47
|
+
@received_data = ''
|
35
48
|
end
|
36
49
|
end
|
37
50
|
|
@@ -39,9 +52,12 @@ module Fargo
|
|
39
52
|
{}
|
40
53
|
end
|
41
54
|
|
55
|
+
def connection_type
|
56
|
+
:dc
|
57
|
+
end
|
58
|
+
|
42
59
|
def unbind
|
43
60
|
if client
|
44
|
-
connection_type = self.class.name.split('::').last.downcase
|
45
61
|
args = [:"#{connection_type}_disconnected", publish_args]
|
46
62
|
client.channel << args
|
47
63
|
end
|
data/lib/fargo/protocol/hub.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
module Fargo
|
2
2
|
module Protocol
|
3
|
-
|
3
|
+
module Hub
|
4
4
|
|
5
|
-
include
|
6
|
-
include
|
5
|
+
include Utils
|
6
|
+
include Protocol::DC
|
7
7
|
|
8
8
|
attr_reader :hubname
|
9
9
|
|
10
|
+
def connection_type
|
11
|
+
:hub
|
12
|
+
end
|
13
|
+
|
10
14
|
# See <http://www.teamfair.info/DC-Protocol.htm> for specifics on
|
11
15
|
# the DC protocol
|
12
16
|
def receive_message type, message
|
@@ -20,10 +24,10 @@ module Fargo
|
|
20
24
|
when :getpass
|
21
25
|
send_message 'MyPass', @client.config.password
|
22
26
|
when :badpass, :hubfull
|
23
|
-
Fargo.logger.
|
27
|
+
Fargo.logger.info "Disconnecting because of: #{message.inspect}"
|
24
28
|
close_connection_after_writing
|
25
29
|
when :hello
|
26
|
-
if message[:
|
30
|
+
if message[:nick] == @client.config.nick
|
27
31
|
Fargo.logger.info "Connected to DC Hub #{@hubname}"
|
28
32
|
@validated = true
|
29
33
|
|
@@ -36,37 +40,54 @@ module Fargo
|
|
36
40
|
end
|
37
41
|
|
38
42
|
when :connect_to_me
|
39
|
-
if !@client.nicks.include?(message[:nick])
|
40
|
-
Fargo.logger.info "Invalid connect_to_me request from: #{message[:nick]}"
|
41
|
-
return
|
42
|
-
end
|
43
|
-
|
44
43
|
EventMachine.connect message[:address], message[:port],
|
45
|
-
|
44
|
+
Protocol::Peer do |conn|
|
46
45
|
conn.client = @client
|
47
46
|
conn.send_lock # We connect first, we send lock first
|
48
47
|
end
|
49
48
|
|
50
49
|
when :search
|
51
50
|
# Let the client handle the results
|
52
|
-
|
51
|
+
search = Search.new message
|
52
|
+
@listings = @client.search_local_listings search
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
r.active_send @client.config.nick, message[:ip], message[:port]
|
54
|
+
@results = @listings.map do |l|
|
55
|
+
file = l.name.gsub '/', "\\"
|
56
|
+
if File.directory? l.name
|
57
|
+
s = file
|
59
58
|
else
|
60
|
-
|
59
|
+
s = "#{file}\005#{l.size}"
|
61
60
|
end
|
62
|
-
|
61
|
+
|
62
|
+
s + sprintf(" %d/%d\005%s (%s:%d)", @client.open_upload_slots,
|
63
|
+
@client.config.upload_slots,
|
64
|
+
'TTH:' + l.tth,
|
65
|
+
@client.config.hub_address,
|
66
|
+
@client.config.hub_port)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Send all the results to the peer. Take care of active/passive
|
70
|
+
# connections
|
71
|
+
if message[:address]
|
72
|
+
socket = EventMachine.open_datagram_socket '0.0.0.0', 0
|
73
|
+
@results.each{ |r|
|
74
|
+
socket.send_datagram "$SR #{@client.config.nick} #{r}|",
|
75
|
+
message[:address], message[:port]
|
76
|
+
}
|
77
|
+
socket.close_connection_after_writing
|
78
|
+
else
|
79
|
+
@results.each{ |r|
|
80
|
+
send_message 'SR',
|
81
|
+
"#{@client.config.nick} #{r}\005#{message[:searcher]}"
|
82
|
+
}
|
83
|
+
end
|
63
84
|
|
64
85
|
when :revconnect
|
65
86
|
if @client.config.passive
|
66
87
|
send_message 'RevConnectToMe',
|
67
88
|
"#{@client.config.nick} #{message[:who]}"
|
68
89
|
else
|
69
|
-
send_message 'ConnectToMe', "#{
|
90
|
+
send_message 'ConnectToMe', "#{message[:who]} #{@client.config.address}:#{@client.config.active_port}"
|
70
91
|
end
|
71
92
|
|
72
93
|
# proxy this message on up the stack if we don't handle it
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
|
3
|
+
module Fargo
|
4
|
+
module Protocol
|
5
|
+
module Peer
|
6
|
+
|
7
|
+
include Utils
|
8
|
+
include Protocol::DC
|
9
|
+
include PeerDownload
|
10
|
+
include PeerUpload
|
11
|
+
|
12
|
+
attr_accessor :client
|
13
|
+
|
14
|
+
def connection_type
|
15
|
+
:peer
|
16
|
+
end
|
17
|
+
|
18
|
+
def post_init
|
19
|
+
super
|
20
|
+
|
21
|
+
set_comm_inactivity_timeout 20
|
22
|
+
|
23
|
+
@lock, @pk = generate_lock
|
24
|
+
@handshake_step = 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_lock
|
28
|
+
@lock_sent = true
|
29
|
+
send_message 'MyNick', @client.config.nick
|
30
|
+
send_message 'Lock', "#{@lock} Pk=#{@pk}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def supports
|
34
|
+
'MiniSlots XmlBZList ADCGet TTHF ZLIG GetZBlock'
|
35
|
+
end
|
36
|
+
|
37
|
+
def receive_message type, message
|
38
|
+
case type
|
39
|
+
when :mynick
|
40
|
+
if @handshake_step == 0
|
41
|
+
@handshake_step = 1
|
42
|
+
@other_nick = message[:nick]
|
43
|
+
|
44
|
+
client.channel << [:download_opened,
|
45
|
+
publish_args.merge(:connection => self)]
|
46
|
+
@download = @client.lock_next_download! @other_nick, self
|
47
|
+
|
48
|
+
@direction = @download.nil? ? 'Upload' : 'Download'
|
49
|
+
else
|
50
|
+
error 'Premature disconnect when mynick received'
|
51
|
+
end
|
52
|
+
|
53
|
+
when :lock
|
54
|
+
if @handshake_step == 1
|
55
|
+
@remote_lock = message[:lock]
|
56
|
+
@handshake_step = 2
|
57
|
+
|
58
|
+
send_lock unless @lock_sent
|
59
|
+
|
60
|
+
send_message 'Supports', supports
|
61
|
+
send_message 'Direction', "#{@direction} #{@my_num = rand(10000)}"
|
62
|
+
send_message 'Key', generate_key(@remote_lock)
|
63
|
+
else
|
64
|
+
error 'Premature disconnect when lock received'
|
65
|
+
end
|
66
|
+
|
67
|
+
when :supports
|
68
|
+
if @handshake_step == 2
|
69
|
+
@client_extensions = message[:extensions]
|
70
|
+
@handshake_step = 3
|
71
|
+
else
|
72
|
+
error 'Premature disconnect when supports received'
|
73
|
+
end
|
74
|
+
|
75
|
+
when :direction
|
76
|
+
if @handshake_step == 3
|
77
|
+
@client_num = message[:number]
|
78
|
+
@handshake_step = 4
|
79
|
+
else
|
80
|
+
error 'Premature disconnect when direction received'
|
81
|
+
end
|
82
|
+
|
83
|
+
when :key
|
84
|
+
if @handshake_step == 4 && generate_key(@lock) == message[:key]
|
85
|
+
@handshake_step = 5
|
86
|
+
|
87
|
+
begin_download! if @direction == 'Download'
|
88
|
+
|
89
|
+
else
|
90
|
+
error 'Premature disconnect when key received'
|
91
|
+
end
|
92
|
+
|
93
|
+
# This wasn't handled by us, proxy it on up to the client
|
94
|
+
else
|
95
|
+
super
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def publish_args
|
101
|
+
{:nick => @other_nick}
|
102
|
+
end
|
103
|
+
|
104
|
+
protected
|
105
|
+
|
106
|
+
def error message
|
107
|
+
Fargo.logger.warn @last_error = message
|
108
|
+
|
109
|
+
close_connection
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|