fargo 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  require 'active_support/configurable'
2
2
  require 'active_support/callbacks'
3
3
 
4
- module Fargo
4
+ module Fargo
5
5
  class ConnectionError < RuntimeError; end
6
6
 
7
7
  module Connection
@@ -10,16 +10,16 @@ module Fargo
10
10
  include ActiveSupport::Configurable
11
11
  include ActiveSupport::Callbacks
12
12
  include Fargo::Publisher
13
-
13
+
14
14
  attr_accessor :socket
15
15
  define_callbacks :listen
16
-
16
+
17
17
  def initialize client
18
18
  @outgoing = Queue.new
19
19
  @client = client
20
20
  config.quit_on_disconnect = true
21
21
  end
22
-
22
+
23
23
  def connect
24
24
  Fargo.logger.info(
25
25
  "#{self}: Opening connection with #{config.address}, #{config.port}"
@@ -35,7 +35,7 @@ module Fargo
35
35
  def receive
36
36
  raise 'Implement me!'
37
37
  end
38
-
38
+
39
39
  def open_socket
40
40
  @socket ||= TCPSocket.open config.address, config.port
41
41
  rescue Errno::ECONNREFUSED
@@ -43,20 +43,21 @@ module Fargo
43
43
  end
44
44
 
45
45
  def connected?
46
- !@socket.nil?
46
+ !@socket.nil? && !@socket.closed?
47
47
  end
48
48
 
49
49
  def listen
50
50
  return unless @threads.nil? || @threads.size == 0
51
-
51
+
52
52
  run_callbacks :listen do
53
53
  @threads = []
54
+ @looping = true
54
55
 
55
56
  # Start a thread to read the socket
56
- @threads << Thread.start { loop { read_data } }
57
+ @threads << Thread.start { read_data while @looping }
57
58
 
58
59
  # Start a thread to send information from the queue
59
- @threads << Thread.start { loop { write_data @outgoing.pop } }
60
+ @threads << Thread.start { write_data @outgoing.pop while @looping }
60
61
 
61
62
  @threads.each { |t| t.abort_on_exception = true }
62
63
  end
@@ -67,8 +68,10 @@ module Fargo
67
68
 
68
69
  write "$Quit #{@client.config.nick}" if config.quit_on_disconnect
69
70
 
71
+ @looping = false
72
+
70
73
  if @threads
71
- @threads.each &:exit
74
+ @threads.each{ |t| t.exit unless t == Thread.current }
72
75
  @threads.clear
73
76
  end
74
77
 
@@ -86,48 +89,38 @@ module Fargo
86
89
  connection_type = self.class.name.split('::').last.downcase
87
90
  @client.publish :"#{connection_type}_disconnected"
88
91
  end
89
-
92
+
90
93
  def write string
91
94
  string << '|' unless string.end_with?('|')
92
95
  @outgoing << string # append this to the queue of things to be written
93
96
  true
94
97
  end
95
-
98
+
96
99
  private
97
100
 
98
101
  def read_data
99
- if @socket.closed?
100
- Fargo.logger.debug 'When reading data, socket was already closed!'
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}"
101
110
  disconnect
102
- else
103
- begin
104
- data = @socket.gets '|'
105
- raise ConnectionError.new("Received nil data!") if data.nil?
106
- rescue => e
107
- Fargo.logger.warn "#{self}: Error reading data, disconnecting: #{e}"
108
- disconnect
109
- end
110
-
111
- Fargo.logger.debug "#{self} Received: #{data.inspect}"
112
- receive data.chomp('|')
113
111
  end
114
112
  end
115
113
 
116
114
  def write_data data
117
- if @socket.closed?
118
- Fargo.logger.debug "When writing data, socket was already closed!"
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}"
119
120
  disconnect
120
- else
121
- begin
122
- Fargo.logger.debug "#{self} Sending: #{data.inspect}"
123
- @socket << data
124
- rescue
125
- @client.publish :write_error
126
- disconnect
127
- end
128
121
  end
129
122
  end
130
-
123
+
131
124
  end
132
125
  end
133
126
  end
@@ -3,24 +3,24 @@ require 'zlib'
3
3
  module Fargo
4
4
  module Connection
5
5
  class Download < Base
6
-
6
+
7
7
  include Fargo::Utils
8
8
  include Fargo::Parser
9
-
9
+
10
10
  set_callback :listen, :before, :pre_listen
11
11
  set_callback :listen, :after do |connection|
12
12
  send_lock if connection.config.first
13
13
  end
14
-
14
+
15
15
  attr_accessor :download
16
16
 
17
17
  def pre_listen
18
18
  Fargo.logger.debug "Initiating connection on: #{config.address}:#{config.port}"
19
-
19
+
20
20
  config.quit_on_disconnect = false
21
21
  @lock, @pk = generate_lock
22
22
  @handshake_step = 0
23
-
23
+
24
24
  @buffer_size = (2 << 12).freeze
25
25
  end
26
26
 
@@ -30,32 +30,38 @@ module Fargo
30
30
 
31
31
  def read_data
32
32
  # only download if we're at the correct time
33
- return super if @handshake_step != 6
33
+ return super if @handshake_step != 6
34
34
 
35
35
  @exit_time = 20 # reset our timeout time
36
-
36
+
37
37
  data = @socket.readpartial @buffer_size
38
-
38
+
39
39
  if @zlib
40
40
  @zs = Zlib::Inflate.new if @zs.nil?
41
41
  data = @zs.inflate data
42
42
  end
43
-
43
+
44
44
  @file << data
45
45
  @recvd += data.length
46
46
 
47
- if @recvd == @length
48
- download_finished!
49
- elsif @recvd > @length
47
+ if @recvd > @length
50
48
  error "#{self} #{@recvd} > #{@length}!!!"
51
49
  download_finished!
52
50
  else
53
- publish :download_progress, :percent => @recvd.to_f / @length,
54
- :file => download_path,
55
- :nick => @other_nick,
56
- :download => @download,
57
- :size => @length,
58
- :compressed => @zlib
51
+ percent = @recvd.to_f / @length
52
+ if percent - @last_published > 0.05
53
+ @file.flush
54
+ publish :download_progress, :percent => percent,
55
+ :file => download_path,
56
+ :nick => @other_nick,
57
+ :download => @download,
58
+ :size => @recvd,
59
+ :compressed => @zlib
60
+
61
+ @last_published = percent
62
+ end
63
+
64
+ download_finished! if @recvd == @length
59
65
  end
60
66
  rescue IOError => e
61
67
  error "#{self}: IOError, disconnecting #{e}"
@@ -67,7 +73,7 @@ module Fargo
67
73
  case message[:type]
68
74
  when :mynick
69
75
  if @handshake_step == 0
70
- @handshake_step = 1
76
+ @handshake_step = 1
71
77
  @other_nick = message[:nick]
72
78
 
73
79
  @client.connected_with! @other_nick
@@ -94,7 +100,7 @@ module Fargo
94
100
  else
95
101
  error 'Premature disconnect when lock received'
96
102
  end
97
-
103
+
98
104
  when :supports
99
105
  if @handshake_step == 2
100
106
  @client_extensions = message[:extensions]
@@ -102,7 +108,7 @@ module Fargo
102
108
  else
103
109
  error 'Premature disconnect when supports received'
104
110
  end
105
-
111
+
106
112
  when :direction
107
113
  if @handshake_step == 3 && message[:direction] == 'upload'
108
114
  @client_num = message[:number]
@@ -110,7 +116,7 @@ module Fargo
110
116
  else
111
117
  error 'Premature disconnect when direction received'
112
118
  end
113
-
119
+
114
120
  when :key
115
121
  if @handshake_step == 4 && generate_key(@lock) == message[:key]
116
122
 
@@ -132,9 +138,9 @@ module Fargo
132
138
 
133
139
  write "$Send" unless @client_extensions.include? 'ADCGet'
134
140
 
135
- publish :download_started, :file => download_path,
136
- :download => @download,
137
- :nick => @other_nick
141
+ publish :download_started, :file => download_path,
142
+ :download => @download,
143
+ :nick => @other_nick
138
144
  else
139
145
  error "Premature disconnect when #{message[:type]} received"
140
146
  end
@@ -142,27 +148,29 @@ module Fargo
142
148
  when :noslots
143
149
  if @download
144
150
  Fargo.logger.debug "#{self}: No Slots for #{self[:download]}"
145
-
151
+
146
152
  download_failed! 'No Slots'
147
153
  end
148
154
 
149
155
  when :error
150
- error "#{self}: Error! #{message[:message]}"
151
-
152
- # This wasn't handled by us, proxy it on up to the client
156
+ Fargo.logger.warn @last_error = "#{self}: Error! #{message[:message]}"
157
+ download_failed! message[:message]
158
+
159
+ # This wasn't handled by us, proxy it on up to the client
153
160
  else
154
161
  @client.publish message[:type], message
155
162
 
156
163
  end
157
164
  end
158
-
165
+
159
166
  def begin_download!
160
- @file = File.new download_path, File::CREAT | File::WRONLY
167
+ @file = File.open download_path, 'wb'
161
168
 
162
169
  @file.seek @download.offset
163
170
  @file.sync = true
164
171
  @socket.sync = true
165
172
  @handshake_step = 5
173
+ @last_published = 0
166
174
 
167
175
  if @download.file_list?
168
176
  if @client_extensions.include? 'XmlBZList'
@@ -177,7 +185,7 @@ module Fargo
177
185
  if @client_extensions.include? 'ADCGet'
178
186
  download_query = @download.file
179
187
  if @download.tth && @client_extensions.include?('TTHF')
180
- download_query = @download.tth.gsub ':', '/'
188
+ download_query = 'TTH/' + @download.tth
181
189
  end
182
190
 
183
191
  zlig = ''
@@ -194,66 +202,67 @@ module Fargo
194
202
  # This is the thread for the timeout of a connection. The @exit_time
195
203
  # variable is reset to 20 after every bit of information is received.
196
204
  @exit_time = 20
197
- @exit_thread = Thread.start {
205
+ @exit_thread = Thread.start {
198
206
  while @exit_time > 0
199
207
  sleep 1
200
208
  @exit_time -= 1
201
209
  Fargo.logger.debug "#{self} time out in #{@exit_time} seconds"
202
210
  end
203
211
 
204
- download_failed! 'Download timeout!'
212
+ download_failed! 'Download timeout!'
205
213
  }
206
-
214
+
207
215
  Fargo.logger.debug "#{self}: Beginning download of #{@download}"
208
216
  end
209
-
217
+
210
218
  def download_failed! msg, opts = {}
211
219
  Fargo.logger.debug "#{self}: #{msg} #{@download}"
212
-
220
+
213
221
  # cache because publishing must be at end of method and we're about to
214
222
  # clear these
215
223
  path, download = download_path, @download
216
224
 
217
225
  reset_download
218
226
 
219
- publish :download_failed, opts.merge(:nick => @other_nick,
220
- :download => download,
221
- :file => path,
227
+ publish :download_failed, opts.merge(:nick => @other_nick,
228
+ :download => download,
229
+ :file => path,
222
230
  :last_error => msg)
223
231
 
224
232
  @exit_thread = nil
225
233
  end
226
-
234
+
227
235
  def download_finished!
228
236
  Fargo.logger.debug "#{self}: Finished download of #{@download}"
229
-
237
+
230
238
  # cache because publishing must be at end of method and we're about to
231
239
  # clear these
232
240
  path, download = download_path, @download
233
-
241
+
234
242
  reset_download
235
-
236
- publish :download_finished, :file => path, :download => download,
243
+
244
+ publish :download_finished, :file => path, :download => download,
237
245
  :nick => @other_nick
246
+ disconnect if download.file_list?
238
247
  end
239
-
248
+
240
249
  def disconnect
241
250
  Fargo.logger.debug "#{self} Disconnecting from: #{@other_nick}"
242
-
251
+
243
252
  super
244
253
 
245
254
  if @download
246
255
  download_failed! @last_error, :recvd => @recvd, :length => @length
247
256
  end
248
-
257
+
249
258
  reset_download
250
259
  end
251
-
260
+
252
261
  private
253
262
  def reset_download
254
263
  @file.close unless @file.nil? || @file.closed?
255
264
  if @file_path && File.exists?(@file_path) && File.size(@file_path) == 0
256
- File.delete(@file_path)
265
+ File.delete(@file_path)
257
266
  end
258
267
 
259
268
  if @socket
@@ -262,18 +271,18 @@ module Fargo
262
271
  end
263
272
 
264
273
  # If this was called from exit thread, don't kill it
265
- if @exit_thread != Thread.current
274
+ if @exit_thread != Thread.current
266
275
  @exit_thread.exit if @exit_thread && @exit_thread.alive?
267
276
  @exit_thread = nil
268
277
  end
269
-
278
+
270
279
  # clear out these variables
271
- @zs = @file_path = @zlib = @download = @length = @recvd = nil
280
+ @zs = @file_path = @zlib = @download = @length = @recvd = nil
272
281
 
273
282
  # Go back to the get step
274
283
  @handshake_step = 5
275
284
  end
276
-
285
+
277
286
  def download_path
278
287
  return nil if @download.try(:file).nil?
279
288
 
@@ -282,10 +291,12 @@ module Fargo
282
291
  filename = File.basename @download.file.gsub("\\", '/')
283
292
  path = File.join(prefix, @other_nick, filename)
284
293
 
285
- i = 0
286
- while File.exists?(path)
287
- i += 1
288
- path = File.join(prefix, @other_nick, "#{i}-#{filename}")
294
+ unless @download.file_list?
295
+ i = 0
296
+ while File.exists?(path)
297
+ i += 1
298
+ path = File.join(prefix, @other_nick, "#{i}-#{filename}")
299
+ end
289
300
  end
290
301
 
291
302
  path
@@ -1,26 +1,42 @@
1
1
  module Fargo
2
2
  module Publisher
3
-
3
+
4
4
  attr_reader :subscribers
5
5
 
6
6
  def subscribe &subscriber
7
- raise RuntimeError.new("Need a subscription block!") if subscriber.nil?
7
+ raise RuntimeError.new('Need a subscription block!') if subscriber.nil?
8
+
8
9
  Fargo.logger.debug "#{self}: subscribing #{subscriber}"
9
10
  (@subscribers ||= []) << subscriber
10
11
  end
11
-
12
+
12
13
  def subscribed_to?
13
14
  @subscribers && @subscribers.size > 0
14
15
  end
15
-
16
+
16
17
  def unsubscribe &subscriber
17
- raise RuntimeError.new("Need a subscription block!") if subscriber.nil?
18
+ raise RuntimeError.new('Need a subscription block!') if subscriber.nil?
19
+
18
20
  Fargo.logger.debug "#{self}: unsubscribing #{subscriber}"
19
21
  (@subscribers ||= []).delete subscriber
20
22
  end
21
23
 
22
24
  def publish message_type, hash = {}
23
- @subscribers.each { |subscriber| subscriber.call message_type, hash } if @subscribers
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
24
39
  end
40
+
25
41
  end
26
42
  end
@@ -10,31 +10,48 @@ module Fargo
10
10
  file == 'files.xml.bz2'
11
11
  end
12
12
  end
13
-
13
+
14
14
  attr_reader :current_downloads, :finished_downloads, :queued_downloads,
15
15
  :failed_downloads, :open_download_slots, :trying, :timed_out,
16
16
  :download_slots
17
-
17
+
18
18
  included do
19
19
  set_callback :setup, :after, :initialize_queues
20
20
  end
21
-
21
+
22
22
  def clear_failed_downloads
23
23
  failed_downloads.clear
24
24
  end
25
-
25
+
26
26
  def clear_finished_downloads
27
27
  finished_downloads.clear
28
28
  end
29
29
 
30
- def download nick, file, tth=nil, size=-1, offset=0
30
+ def download nick, file=nil, tth=nil, size=-1, offset=0
31
31
  raise ConnectionException.new 'Not connected yet!' unless hub
32
- raise 'File cannot be nil!' if file.nil?
33
32
 
33
+ if nick.is_a?(Supports::FileList::Listing)
34
+ listing = nick
35
+ nick = listing.nick
36
+ file = listing.name
37
+ tth = listing.tth
38
+ size = listing.size
39
+ elsif nick.is_a?(Download)
40
+ dl = nick
41
+ nick = dl.nick
42
+ file = dl.file
43
+ tth = dl.tth
44
+ size = dl.size || -1
45
+ offset = dl.offset || 0
46
+ end
47
+
48
+ raise 'File must not be nil!' if file.nil?
34
49
  unless nicks.include? nick
35
- raise ConnectionException.new "User #{nick} does not exist!"
50
+ raise ConnectionException.new "User #{nick} does not exist!"
36
51
  end
37
52
 
53
+ tth = tth.gsub /^TTH:/, '' if tth
54
+
38
55
  download = Download.new nick, file, tth, size, offset
39
56
  download.percent = 0
40
57
  download.status = 'idle'
@@ -52,13 +69,13 @@ module Fargo
52
69
  Fargo.logger.warn "#{file} isn't a failed download for: #{nick}!"
53
70
  return
54
71
  end
55
-
72
+
56
73
  @failed_downloads[nick].delete dl
57
74
  download dl.nick, dl.file, dl.tth, dl.size
58
75
  end
59
76
 
60
77
  def remove_download nick, file
61
- # We need to synchronize this access, so append these arguments to a
78
+ # We need to synchronize this access, so append these arguments to a
62
79
  # queue to be processed later
63
80
  @to_remove << [nick, file]
64
81
  true
@@ -93,11 +110,11 @@ module Fargo
93
110
  @downloading_lock.synchronize {
94
111
  # Find the first nick and download list
95
112
  arr = @queued_downloads.to_a.detect{ |nick, downloads|
96
- downloads.size > 0 &&
97
- !@current_downloads.has_key?(nick) &&
98
- !@trying.include?(nick) &&
99
- !@timed_out.include?(nick) &&
100
- has_slot?(nick)
113
+ downloads.size > 0 &&
114
+ !@current_downloads.has_key?(nick) &&
115
+ !@trying.include?(nick) &&
116
+ !@timed_out.include?(nick) &&
117
+ (connection_for(nick) || has_slot?(nick))
101
118
  }
102
119
 
103
120
  return false if arr.nil? || arr.size == 0
@@ -131,7 +148,7 @@ module Fargo
131
148
  return nil
132
149
  end
133
150
 
134
- download = @queued_downloads[user].shift
151
+ download = @queued_downloads[user].shift
135
152
  @current_downloads[user] = download
136
153
  @trying.delete user
137
154
 
@@ -160,12 +177,14 @@ module Fargo
160
177
 
161
178
  download
162
179
  end
163
-
180
+
164
181
  def download_finished! user, failed
165
182
  download = nil
166
- @downloading_lock.synchronize{
183
+ @downloading_lock.synchronize{
167
184
  download = @current_downloads.delete user
168
185
  @open_download_slots += 1
186
+
187
+ # connection_for(user).disconnect if @queued_downloads[user].size == 0
169
188
  }
170
189
 
171
190
  if failed
@@ -176,7 +195,7 @@ module Fargo
176
195
 
177
196
  start_download # Start another download if possible
178
197
  end
179
-
198
+
180
199
  def connection_failed_with! nick
181
200
  @trying.delete nick
182
201
  @timed_out << nick
@@ -224,7 +243,7 @@ module Fargo
224
243
  @download_removal_thread.exit
225
244
  end
226
245
 
227
- # Both of these need access to the synchronization lock, so we use
246
+ # Both of these need access to the synchronization lock, so we use
228
247
  # separate threads to do these processes.
229
248
  def start_download_queue_threads
230
249
  @to_download = Queue.new
@@ -236,8 +255,13 @@ module Fargo
236
255
  download.status = 'timeout'
237
256
  (@failed_downloads[download.nick] ||= []) << download
238
257
  else
239
- (@queued_downloads[download.nick] ||= []) << download
240
- start_download
258
+ @queued_downloads[download.nick] ||= []
259
+
260
+ unless @queued_downloads[download.nick].include?(download) ||
261
+ @current_downloads[download.nick] == download
262
+ @queued_downloads[download.nick] << download
263
+ start_download
264
+ end
241
265
  end
242
266
  }
243
267
  }
@@ -256,6 +280,6 @@ module Fargo
256
280
  }
257
281
  end
258
282
 
259
- end # Downloads
283
+ end # Downloads
260
284
  end # Supports
261
285
  end # Fargo
@@ -4,13 +4,19 @@ require 'libxml'
4
4
  module Fargo
5
5
  module Supports
6
6
  module FileList
7
- class Listing < Struct.new(:tth, :size, :name); end
7
+ class Listing < Struct.new(:tth, :size, :name, :nick); end
8
8
 
9
9
  # Lazily load the file list for the nick. Subscribe to the client for the
10
10
  # event :file_list to get notified.
11
11
  def file_list nick
12
12
  @file_list ||= {}
13
- return parse_file_list(@file_list[nick]) if @file_list.has_key?(nick)
13
+ @getting_file_list ||= {}
14
+
15
+ if @file_list.has_key?(nick)
16
+ return parse_file_list(@file_list[nick], nick)
17
+ elsif @getting_file_list[nick]
18
+ return true
19
+ end
14
20
 
15
21
  file_gotten = lambda{ |type, map|
16
22
  case type
@@ -19,19 +25,23 @@ module Fargo
19
25
  @file_list[nick] = map[:file]
20
26
  unsubscribe &file_gotten
21
27
  publish :file_list, :nick => nick, :list => @file_list[nick]
28
+ @getting_file_list.delete nick
22
29
  end
23
30
  end
24
31
  }
25
32
 
26
33
  subscribe &file_gotten
27
34
 
35
+ @getting_file_list[nick] = true
28
36
  download nick, 'files.xml.bz2'
29
37
  end
30
38
 
31
39
  # Wait for the results to arrive, timed out after some time
32
40
  def file_list! nick, timeout = 10
33
41
  @file_list ||= {}
34
- return parse_file_list(@file_list[nick]) if @file_list.has_key?(nick)
42
+ if @file_list.has_key?(nick)
43
+ return parse_file_list(@file_list[nick], nick)
44
+ end
35
45
 
36
46
  list = nil
37
47
  list_gotten = lambda{ |type, map|
@@ -45,35 +55,37 @@ module Fargo
45
55
 
46
56
  timeout_response(timeout, list_gotten){ file_list nick }
47
57
 
48
- parse_file_list list
58
+ parse_file_list list, nick
49
59
  end
50
60
 
51
61
  private
52
62
 
53
- def parse_file_list file
63
+ def parse_file_list file, nick
54
64
  if file && File.exists?(file)
65
+ Fargo.logger.debug "Parsing file list for: '#{nick}' at '#{file}'"
55
66
  xml = Bzip2::Reader.open(file).read
56
67
  doc = LibXML::XML::Document.string xml
57
68
 
58
- construct_file_list doc.root
69
+ construct_file_list doc.root, nil, nick
59
70
  else
60
71
  nil
61
72
  end
62
73
  end
63
74
 
64
- def construct_file_list node
75
+ def construct_file_list node, prefix, nick
65
76
  list = {}
66
77
 
67
78
  node.each_element do |element|
68
- element_name = element['Name']
79
+ path = prefix ? prefix + "\\" + element['Name'] : element['Name']
80
+
69
81
  if element.name =~ /directory/i
70
- list[element_name] = construct_file_list element
82
+ list[element['Name']] = construct_file_list element, path, nick
71
83
  else
72
- list[element_name] = Listing.new(
73
- element['TTH'],
74
- element['Size'],
75
- element_name
76
- )
84
+ # Why does this consistently segfault ruby 1.8.7 when I convert
85
+ # element['Size'] to an integer before the struct is created?!
86
+ element = list[element['Name']] = Listing.new(element['TTH'],
87
+ element['Size'], path, nick)
88
+ element.size = element.size.to_i
77
89
  end
78
90
  end
79
91
 
@@ -13,30 +13,33 @@ module Fargo
13
13
 
14
14
  def connection_for nick
15
15
  c = @connection_cache.try :[], nick
16
- return c if c.nil? || c.connected?
16
+ if c.nil? || c.connected?
17
+ Fargo.logger.debug "#{self} has connection with: #{nick}: #{c}"
18
+ return c
19
+ end
17
20
 
18
21
  # If it's present and not connected, remove it from the cache
19
22
  @connection_cache.try :delete, nick
20
23
  nil
21
24
  end
22
-
25
+
23
26
  def connected_with? nick
24
27
  c = @connection_cache.try :[], nick
25
28
  c.connected? unless c.nil?
26
- end
27
-
29
+ end
30
+
28
31
  def disconnect_from nick
29
32
  c = @connection_cache.try :delete, nick
30
33
  c.disconnect unless c.nil?
31
34
  end
32
-
35
+
33
36
  def nicks_connected_with
34
37
  return [] if @connection_cache.nil?
35
38
 
36
39
  nicks = @connection_cache.keys
37
- nicks.reject{ |n| !connected_with? n }
40
+ nicks.reject{ |n| !connected_with? n }
38
41
  end
39
-
42
+
40
43
  def setup_connection_cache
41
44
  @connection_cache = {}
42
45
 
@@ -49,4 +52,4 @@ module Fargo
49
52
 
50
53
  end
51
54
  end
52
- end
55
+ end
data/lib/fargo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fargo
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fargo
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 0
9
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Alex Crichton
@@ -14,51 +15,54 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-06 00:00:00 -04:00
18
+ date: 2010-09-22 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: activesupport
22
- requirement: &id001 !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
+ hash: 7
27
28
  segments:
28
29
  - 3
29
30
  - 0
30
31
  - 0
31
32
  version: 3.0.0
33
+ requirement: *id001
32
34
  type: :runtime
35
+ name: activesupport
33
36
  prerelease: false
34
- version_requirements: *id001
35
37
  - !ruby/object:Gem::Dependency
36
- name: libxml-ruby
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
38
39
  none: false
39
40
  requirements:
40
41
  - - ">="
41
42
  - !ruby/object:Gem::Version
43
+ hash: 3
42
44
  segments:
43
45
  - 0
44
46
  version: "0"
47
+ requirement: *id002
45
48
  type: :runtime
49
+ name: libxml-ruby
46
50
  prerelease: false
47
- version_requirements: *id002
48
51
  - !ruby/object:Gem::Dependency
49
- name: bzip2-ruby
50
- requirement: &id003 !ruby/object:Gem::Requirement
52
+ version_requirements: &id003 !ruby/object:Gem::Requirement
51
53
  none: false
52
54
  requirements:
53
55
  - - ">="
54
56
  - !ruby/object:Gem::Version
57
+ hash: 3
55
58
  segments:
56
59
  - 0
57
60
  version: "0"
61
+ requirement: *id003
58
62
  type: :runtime
63
+ name: bzip2-ruby
59
64
  prerelease: false
60
- version_requirements: *id003
61
- description: DC Client
65
+ description: Direct Connect (DC) Client implemented in pure Ruby
62
66
  email: alex@alexcrichton.com
63
67
  executables: []
64
68
 
@@ -103,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
107
  requirements:
104
108
  - - ">="
105
109
  - !ruby/object:Gem::Version
106
- hash: 1373483426740815041
110
+ hash: 3
107
111
  segments:
108
112
  - 0
109
113
  version: "0"
@@ -112,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
116
  requirements:
113
117
  - - ">="
114
118
  - !ruby/object:Gem::Version
115
- hash: 1373483426740815041
119
+ hash: 3
116
120
  segments:
117
121
  - 0
118
122
  version: "0"