fargo 0.2.0 → 0.3.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.
- 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
|