fargo 0.1.1 → 0.2.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.
@@ -1,17 +1,20 @@
1
1
  module Fargo
2
2
  module Supports
3
3
  module Timeout
4
-
4
+
5
5
  def timeout_response timeout, succeed_subscription
6
6
  thread = Thread.current
7
- subscribed_block = lambda do |*args|
7
+
8
+ subscribed_block = lambda do |args|
8
9
  thread.wakeup if succeed_subscription.call(*args)
9
10
  end
10
11
 
11
- subscribe &subscribed_block
12
- yield
12
+ id = channel.subscribe subscribed_block
13
+
14
+ yield if block_given?
13
15
  sleep timeout
14
- unsubscribe &subscribed_block
16
+
17
+ channel.unsubscribe id
15
18
  end
16
19
 
17
20
  end
@@ -2,15 +2,15 @@ module Fargo
2
2
  module Supports
3
3
  module Uploads
4
4
  # TODO: write this module...
5
-
5
+
6
6
  def open_slots
7
7
  0
8
8
  end
9
-
9
+
10
10
  def share_size
11
- 5368709121 # 5 GB + 1 byte
11
+ 5368709121 # 5 GB + 1 byte
12
12
  end
13
-
13
+
14
14
  end
15
15
  end
16
- end
16
+ end
data/lib/fargo/utils.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  module Fargo
2
2
  module Utils
3
-
3
+
4
4
  # Lord knows why they're doing this...
5
5
  def generate_key lock
6
6
  lock_bytes = lock.bytes.to_a
7
7
  bytes = []
8
8
  bytes << (lock_bytes[0] ^ lock_bytes[-1] ^ lock_bytes[-2] ^ 5)
9
- (1..lock.length-1).each{ |i|
9
+
10
+ (1..lock.length-1).each{ |i|
10
11
  bytes << (lock_bytes[i] ^ lock_bytes[i - 1])
11
12
  }
12
13
 
@@ -14,7 +15,7 @@ module Fargo
14
15
  bytes.each{ |b| key << encode_char(((b << 4) | (b >> 4)) & 0xff) }
15
16
  key
16
17
  end
17
-
18
+
18
19
  # Generates a lock between 80 and 134 random characters, and a pk of 16
19
20
  # random characters. At least in theory, other clients were doing exactly
20
21
  # this, so I just mirrored them.
@@ -22,7 +23,7 @@ module Fargo
22
23
  lock = 'EXTENDEDPROTOCOL'
23
24
  [lock + ('ABC' * 6), 'ABCD' * 4]
24
25
  end
25
-
26
+
26
27
  # Watch out for those special ones...
27
28
  def encode_char c
28
29
  if [0, 5, 36, 96, 124, 126].include? c
data/lib/fargo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fargo
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/fargo.rb CHANGED
@@ -1,26 +1,26 @@
1
- require 'socket'
2
1
  require 'fileutils'
2
+ require 'eventmachine'
3
3
  require 'active_support/dependencies/autoload'
4
4
  require 'active_support/core_ext/module/attribute_accessors'
5
5
  require 'active_support/buffered_logger'
6
6
  require 'active_support/concern'
7
+ require 'active_support/configurable'
7
8
 
8
9
  module Fargo
9
10
  extend ActiveSupport::Autoload
10
11
 
11
12
  class ConnectionException < RuntimeError; end
12
-
13
+
13
14
  mattr_accessor:logger
14
15
  self.logger = ActiveSupport::BufferedLogger.new STDOUT
15
16
 
16
- autoload :Utils
17
- autoload :Publisher
17
+ autoload :Utils
18
18
  autoload :Parser
19
- autoload :Server
20
19
  autoload :Client
21
20
  autoload :Search
22
21
  autoload :SearchResult
23
22
  autoload :VERSION
23
+ autoload :TTH
24
24
 
25
25
  module Supports
26
26
  extend ActiveSupport::Autoload
@@ -35,14 +35,12 @@ module Fargo
35
35
  autoload :FileList
36
36
  end
37
37
 
38
- module Connection
38
+ module Protocol
39
39
  extend ActiveSupport::Autoload
40
40
 
41
- autoload :Base
41
+ autoload :DC
42
42
  autoload :Download
43
43
  autoload :Hub
44
- autoload :Search
45
- autoload :Upload
46
44
  end
47
45
 
48
- end
46
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fargo
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Crichton
@@ -15,11 +15,25 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-22 00:00:00 -04:00
18
+ date: 2010-09-27 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ requirement: *id001
32
+ type: :runtime
33
+ name: eventmachine
34
+ prerelease: false
35
+ - !ruby/object:Gem::Dependency
36
+ version_requirements: &id002 !ruby/object:Gem::Requirement
23
37
  none: false
24
38
  requirements:
25
39
  - - ">="
@@ -30,12 +44,12 @@ dependencies:
30
44
  - 0
31
45
  - 0
32
46
  version: 3.0.0
33
- requirement: *id001
47
+ requirement: *id002
34
48
  type: :runtime
35
49
  name: activesupport
36
50
  prerelease: false
37
51
  - !ruby/object:Gem::Dependency
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
52
+ version_requirements: &id003 !ruby/object:Gem::Requirement
39
53
  none: false
40
54
  requirements:
41
55
  - - ">="
@@ -44,12 +58,12 @@ dependencies:
44
58
  segments:
45
59
  - 0
46
60
  version: "0"
47
- requirement: *id002
61
+ requirement: *id003
48
62
  type: :runtime
49
63
  name: libxml-ruby
50
64
  prerelease: false
51
65
  - !ruby/object:Gem::Dependency
52
- version_requirements: &id003 !ruby/object:Gem::Requirement
66
+ version_requirements: &id004 !ruby/object:Gem::Requirement
53
67
  none: false
54
68
  requirements:
55
69
  - - ">="
@@ -58,7 +72,7 @@ dependencies:
58
72
  segments:
59
73
  - 0
60
74
  version: "0"
61
- requirement: *id003
75
+ requirement: *id004
62
76
  type: :runtime
63
77
  name: bzip2-ruby
64
78
  prerelease: false
@@ -66,23 +80,30 @@ description: Direct Connect (DC) Client implemented in pure Ruby
66
80
  email: alex@alexcrichton.com
67
81
  executables: []
68
82
 
69
- extensions: []
70
-
83
+ extensions:
84
+ - ext/fargo/extconf.rb
71
85
  extra_rdoc_files: []
72
86
 
73
87
  files:
88
+ - ext/fargo/base32.c
89
+ - ext/fargo/base32.h
90
+ - ext/fargo/extconf.rb
91
+ - ext/fargo/fargo_tth.c
92
+ - ext/fargo/sboxes.c
93
+ - ext/fargo/tiger.c
94
+ - ext/fargo/tiger.h
95
+ - ext/fargo/tigertree.c
96
+ - ext/fargo/tigertree.h
97
+ - ext/fargo/tth.c
98
+ - ext/fargo/tth.h
74
99
  - lib/fargo.rb
75
100
  - lib/fargo/client.rb
76
- - lib/fargo/connection/base.rb
77
- - lib/fargo/connection/download.rb
78
- - lib/fargo/connection/hub.rb
79
- - lib/fargo/connection/search.rb
80
- - lib/fargo/connection/upload.rb
81
101
  - lib/fargo/parser.rb
82
- - lib/fargo/publisher.rb
102
+ - lib/fargo/protocol/dc.rb
103
+ - lib/fargo/protocol/download.rb
104
+ - lib/fargo/protocol/hub.rb
83
105
  - lib/fargo/search.rb
84
106
  - lib/fargo/search_result.rb
85
- - lib/fargo/server.rb
86
107
  - lib/fargo/supports/chat.rb
87
108
  - lib/fargo/supports/downloads.rb
88
109
  - lib/fargo/supports/file_list.rb
@@ -102,6 +123,7 @@ rdoc_options:
102
123
  - --charset=UTF-8
103
124
  require_paths:
104
125
  - lib
126
+ - ext
105
127
  required_ruby_version: !ruby/object:Gem::Requirement
106
128
  none: false
107
129
  requirements:
@@ -1,126 +0,0 @@
1
- require 'active_support/configurable'
2
- require 'active_support/callbacks'
3
-
4
- module Fargo
5
- class ConnectionError < RuntimeError; end
6
-
7
- module Connection
8
- class Base
9
-
10
- include ActiveSupport::Configurable
11
- include ActiveSupport::Callbacks
12
- include Fargo::Publisher
13
-
14
- attr_accessor :socket
15
- define_callbacks :listen
16
-
17
- def initialize client
18
- @outgoing = Queue.new
19
- @client = client
20
- config.quit_on_disconnect = true
21
- end
22
-
23
- def connect
24
- Fargo.logger.info(
25
- "#{self}: Opening connection with #{config.address}, #{config.port}"
26
- )
27
-
28
- open_socket
29
- listen
30
-
31
- connection_type = self.class.name.split('::').last.downcase
32
- @client.publish :"#{connection_type}_connection_opened"
33
- end
34
-
35
- def receive
36
- raise 'Implement me!'
37
- end
38
-
39
- def open_socket
40
- @socket ||= TCPSocket.open config.address, config.port
41
- rescue Errno::ECONNREFUSED
42
- raise Fargo::ConnectionError.new "Couldn't open a connection to #{config.address}:#{config.port}"
43
- end
44
-
45
- def connected?
46
- !@socket.nil? && !@socket.closed?
47
- end
48
-
49
- def listen
50
- return unless @threads.nil? || @threads.size == 0
51
-
52
- run_callbacks :listen do
53
- @threads = []
54
- @looping = true
55
-
56
- # Start a thread to read the socket
57
- @threads << Thread.start { read_data while @looping }
58
-
59
- # Start a thread to send information from the queue
60
- @threads << Thread.start { write_data @outgoing.pop while @looping }
61
-
62
- @threads.each { |t| t.abort_on_exception = true }
63
- end
64
- end
65
-
66
- def disconnect
67
- Fargo.logger.debug "#{self}: Disconnecting connection"
68
-
69
- write "$Quit #{@client.config.nick}" if config.quit_on_disconnect
70
-
71
- @looping = false
72
-
73
- if @threads
74
- @threads.each{ |t| t.exit unless t == Thread.current }
75
- @threads.clear
76
- end
77
-
78
- if @socket
79
- begin
80
- @socket.close
81
- rescue => e
82
- Fargo.logger.error "Error closing socket: #{e}"
83
- end
84
- end
85
-
86
- @socket = nil
87
- @outgoing.clear
88
-
89
- connection_type = self.class.name.split('::').last.downcase
90
- @client.publish :"#{connection_type}_disconnected"
91
- end
92
-
93
- def write string
94
- string << '|' unless string.end_with?('|')
95
- @outgoing << string # append this to the queue of things to be written
96
- true
97
- end
98
-
99
- private
100
-
101
- def read_data
102
- data = @socket.gets '|'
103
- raise ConnectionError.new('Received nil data!') if data.nil?
104
-
105
- Fargo.logger.debug "#{self} Received: #{data.inspect}"
106
- receive data.chomp('|')
107
- rescue => e
108
- unless @socket.closed?
109
- Fargo.logger.warn "#{self}: Error reading data, going away: #{e}"
110
- disconnect
111
- end
112
- end
113
-
114
- def write_data data
115
- Fargo.logger.debug "#{self} Sending: #{data.inspect}"
116
- @socket << data
117
- rescue => e
118
- unless @socket.closed?
119
- Fargo.logger.warn "#{self}: Error writing data, going away: #{e}"
120
- disconnect
121
- end
122
- end
123
-
124
- end
125
- end
126
- end
@@ -1,120 +0,0 @@
1
- module Fargo
2
- module Connection
3
- class Hub < Base
4
-
5
- include Fargo::Utils
6
- include Fargo::Parser
7
-
8
- attr_reader :hubname
9
-
10
- configure do |config|
11
- config.address = '127.0.0.1'
12
- config.port = 7314
13
- end
14
-
15
- # See <http://www.teamfair.info/DC-Protocol.htm> for specifics on
16
- # the DC protocol
17
- def receive data
18
- message = parse_message data
19
-
20
- case message[:type]
21
- when :lock
22
- @validated = false
23
- write "$Key #{generate_key message[:lock]}"
24
- when :hubname
25
- @hubname = message[:name]
26
- write "$ValidateNick #{@client.config.nick}" unless @validated
27
- when :getpass
28
- write "$MyPass #{@client.password}"
29
- when :badpass, :hubfull
30
- Fargo.logger.warn "Disconnecting because of: #{message.inspect}"
31
- disconnect
32
- when :hello
33
- if message[:who] == @client.config.nick
34
- Fargo.logger.info "Connected to DC Hub #{@hubname} (#{config.address}:#{config.port})"
35
- @validated = true
36
-
37
- write '$Version 1,0091'
38
- write '$GetNickList'
39
- write "$MyINFO $ALL #{@client.config.nick} " +
40
- "#{@client.description}$ $#{@client.config.speed || 'DSL'}" +
41
- "#{@status || 1.chr}$#{@client.config.email}" +
42
- "$#{@client.share_size}$"
43
- end
44
-
45
- when :connect_to_me
46
- if !@client.nicks.include?(message[:nick])
47
- Fargo.logger.info "Invalid connect_to_me request from: #{message[:nick]}"
48
- return
49
- end
50
-
51
- @client_connections ||= []
52
-
53
- connection = Fargo::Connection::Download.new @client
54
- connection.config.address = message[:address]
55
- connection.config.port = message[:port]
56
- # we're going to initiate the download
57
- connection.config.first = true
58
-
59
- # proxy all messages from them back to the client and delete the
60
- # connection if necessary
61
- connection.subscribe { |*args|
62
- @client.publish *args
63
- @client_connections.delete connection unless connection.connected?
64
- }
65
-
66
- # establish the connection. This will also listen for data to be
67
- # read/written
68
- connection.connect
69
-
70
- # keep track of who we're downloading from
71
- @client_connections << connection
72
-
73
- when :search
74
- # Make sure we received a valid search request
75
- if message[:searcher].nil? || !@client.nicks.include?(message[:searcher])
76
- Fargo.logger.info "Invalid search request: #{message.inspect}"
77
- return
78
- end
79
-
80
- # Let the client handle the results
81
- @results = @client.search_files message
82
-
83
- # Send all the results to the peer. Take care of active/passive
84
- # connections
85
- @results.each { |r|
86
- if message[:address]
87
- r.active_send @client.config.nick, message[:ip], message[:port]
88
- else
89
- write "$SR #{@client.config.nick} #{r}"
90
- end
91
- }
92
-
93
- when :revconnect
94
- # TODO: Don't send RevConnectToMe when we're passive and
95
- # receiving is passive
96
- if @client.config.passive
97
- write "$RevConnectToMe #{@client.config.nick} #{message[:who]}"
98
- else
99
- write "$ConnectToMe #{@client.config.nick} #{@client.config.address}:#{@client.config.extport}"
100
- end
101
-
102
- # proxy this message on up the stack if we don't handle it
103
- else
104
- @client.publish message[:type], message
105
-
106
- end
107
- end
108
-
109
- def disconnect
110
- if @client_connections
111
- @client_connections.each &:disconnect
112
- @client_connections.clear
113
- end
114
-
115
- super
116
- end
117
-
118
- end # Hub
119
- end # Connection
120
- end # Fargo
@@ -1,19 +0,0 @@
1
- module Fargo
2
- module Connection
3
- class Search < Base
4
-
5
- # maybe do something special here at some point?
6
- # this is currently just receiving the search result packets over UDP
7
- # and fowarding them to the client who will handle them. This doesn't
8
- # explicitly disconnect because I'm not sure if multiple results
9
- # are sent. This connection will close itself because there will
10
- # be a read error I think...
11
- def receive data
12
- message = parse_message data
13
-
14
- @client.publish message[:type], message
15
- end
16
-
17
- end
18
- end
19
- end
@@ -1,85 +0,0 @@
1
- # TODO: actually get this class to work in some fashion
2
- module Fargo
3
- module Connection
4
- class Upload < Base
5
-
6
- include Fargo::Utils
7
- include Fargo::Parser
8
-
9
- def post_listen
10
- @lock, @pk = generate_lock
11
- write "$MyNick #{self[:nick]}|$Lock #{@lock} Pk=#{@pk}"
12
- @handshake_step = 0
13
- end
14
-
15
- def supports
16
- "$Supports BZList TTHL TTHF" # ???
17
- end
18
-
19
- def receive data
20
- message = parse_message data
21
- publish message[:type], message
22
- case message[:type]
23
- when :mynick
24
- if @handshake_step == 0
25
- @remote_nick = message[:nick]
26
- @handshake_step = 1
27
- else
28
- disconnect
29
- end
30
- when :lock
31
- if @handshake_step == 1
32
- @remote_lock = message[:lock]
33
- @handshake_step = 2
34
- else
35
- disconnect
36
- end
37
- when :supports
38
- if @handshake_step == 2
39
- @remote_extensions = message[:extensions]
40
- @handshake_step = 3
41
- else
42
- disconnect
43
- end
44
- when :direction
45
- if @handshake_step == 3 && message[:direction] == 'download'
46
- @handshake_step = 4
47
- @client_num = message[:number]
48
- else
49
- disconnect
50
- end
51
- when :key
52
- if @handshake_step == 4 && generate_key(@lock) == message[:key]
53
- write supports
54
- write "$Direction Download #{@my_num = rand 10000}"
55
- write "$Key #{generate_key @remote_lock}"
56
- @handshake_step = 5
57
- else
58
- disconnect
59
- end
60
- when :get
61
- if @handshake_step == 5
62
- @filepath = message[:path]
63
- @offset = message[:offset]
64
- write "$FileLength #{file_length}"
65
- @handshake_step = 5
66
- else
67
- disconnect
68
- end
69
- when :send
70
- write_chunk if @handshake_step == 5
71
-
72
- else
73
- # Fargo.logger.warn "Ignoring `#{data}'\n"
74
- end
75
- end
76
-
77
- def write_chunk
78
- end
79
-
80
- def file_length
81
- end
82
-
83
- end
84
- end
85
- end
@@ -1,42 +0,0 @@
1
- module Fargo
2
- module Publisher
3
-
4
- attr_reader :subscribers
5
-
6
- def subscribe &subscriber
7
- raise RuntimeError.new('Need a subscription block!') if subscriber.nil?
8
-
9
- Fargo.logger.debug "#{self}: subscribing #{subscriber}"
10
- (@subscribers ||= []) << subscriber
11
- end
12
-
13
- def subscribed_to?
14
- @subscribers && @subscribers.size > 0
15
- end
16
-
17
- def unsubscribe &subscriber
18
- raise RuntimeError.new('Need a subscription block!') if subscriber.nil?
19
-
20
- Fargo.logger.debug "#{self}: unsubscribing #{subscriber}"
21
- (@subscribers ||= []).delete subscriber
22
- end
23
-
24
- def publish message_type, hash = {}
25
- @subscribers ||= []
26
-
27
- to_remove = []
28
-
29
- @subscribers.each do |subscriber|
30
- begin
31
- subscriber.call message_type, hash
32
- rescue => e
33
- Fargo.logger.warn "#{self}: error publishing to: #{subscriber}! #{e}"
34
- to_remove << subscriber
35
- end
36
- end
37
-
38
- @subscribers -= to_remove
39
- end
40
-
41
- end
42
- end