distribustream 0.2.0 → 0.2.1

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/CHANGES CHANGED
@@ -1,3 +1,8 @@
1
+ Version 0.2.1
2
+ * Switch HTTP client to use an EventMachine-based version, rather than net/http
3
+
4
+ * Added PDTP.version for retrieving version of the library
5
+
1
6
  Version 0.2.0
2
7
  * PDTP::Server and PDTP::Client now expose APIs intended for public consumption
3
8
  They may change slightly down the road, but will remain largely the same
data/README CHANGED
@@ -6,6 +6,11 @@ or live streaming media to be delivered at a fraction of the normal cost.
6
6
  This README covers the initial public release, known issues, and a general
7
7
  development roadmap.
8
8
 
9
+ Contents:
10
+ 1. Usage
11
+ 2. Known Issues
12
+ 3. Development Roadmap
13
+
9
14
  --
10
15
 
11
16
  Usage:
@@ -27,7 +32,7 @@ to identify as.
27
32
 
28
33
  Next, start the DistribuStream server:
29
34
 
30
- distribustream --conf myconfig.yml
35
+ dstream --conf myconfig.yml
31
36
 
32
37
  The DistribuStream server manages traffic on the peer network. It also handles
33
38
  the checksumming of files.
@@ -48,32 +53,19 @@ At this point your server is ready to go.
48
53
 
49
54
  To test your server, use the DistribuStream client:
50
55
 
51
- dsclient --url pdtp://myserver.url/file.ext
56
+ dsclient pdtp://myserver.url/file.ext
52
57
 
53
58
  This will download file.ext from your DistribuStream server.
54
59
 
55
- While you can't control the output filename at this point, the client supports
56
- non-seekable output such as pipes. To play streaming media as it downloads,
57
- you can:
60
+ The client also supports non-seekable output such as pipes. To play streaming
61
+ media as it downloads, you can:
58
62
 
59
- mkfifo file.ext
60
- dsclient --url pdtp://myserver.url/file.ext &
61
- mediaplayer file.ext
63
+ dsclient -o pdtp://myserver.url/file.ext | mediaplayer -
62
64
 
63
65
  --
64
66
 
65
67
  Known Issues:
66
68
 
67
- The client presently stores incoming data in a memory buffer. This causes
68
- the client to consume massive amounts of memory as the file downloads.
69
- Subsequent releases will fix this by improving the design of the memory
70
- buffer, moving to a disk-backed buffer and/or discarding some of the
71
- downloaded data after it's been played back.
72
-
73
- The protocol facilitates allowing clients to have a moving window of data
74
- in a stream, so they need not retain data which has already been displayed
75
- to the user.
76
-
77
69
  Seeds are presently not authenticated in any way, thus anyone can attach
78
70
  a seed and populate the server with any files of their choosing. However,
79
71
  since file checksumming is done by the server itself, this means that only
@@ -87,10 +79,6 @@ checksumming to the server <-> seed protocol.
87
79
 
88
80
  Development Roadmap:
89
81
 
90
- The immediate goal is to improve the performance of the client, which presently
91
- consumes far too much RAM for practical use with large media files. Another
92
- immediate goal is solving the above problems with seeds.
93
-
94
82
  DistribuStream uses an assemblage of various tools which do not work together
95
83
  particularly well. These include the EventMachine Ruby gem, which provides
96
84
  the I/O layer for the DistribuStream server, and the Mongrel web server, which
@@ -99,8 +87,17 @@ runs independently of EventMachine and uses threads.
99
87
  Initial work will focus on converting the existing implementation to a fully
100
88
  EventMachine-based approach which eliminates the use of threads.
101
89
 
102
- Subsequent work will focus on improving the APIs provided by the various
103
- components so that the client and server can both
90
+ Mid-term work will focus on improving the efficiency of peer-to-peer traffic
91
+ routing, by incorporating all of the following constraints:
92
+
93
+ 1. Does the potential "giver" peer have chunks the "taker" peer is requesting?
94
+ 2. Are the peers in the same prefix? (at least the same /16, if not the same /24)
95
+ 3. Are the peers firewalled? (the server could do a connect test as soon as a
96
+ client registers their listen port)
97
+ 4. What is the trust between peers? (the "random" connecting of untrusted peers
98
+ could be replaced by something that operates on the above two bits of data)
99
+ 5. Does the "giver" have enough bandwidth? (modeled over time)
100
+ 6. Are total inbound and outbound links minimized? (to improve TCP congestion)
104
101
 
105
102
  Long-term goals include a move to UDP to reduce protocol latency and overhead
106
103
  as well as encrypting all traffic to ensure privacy and security of the
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  GEMSPEC = Gem::Specification.new do |s|
4
4
  s.name = "distribustream"
5
- s.version = "0.2.0"
5
+ s.version = "0.2.1"
6
6
  s.date = "2008-10-22"
7
7
  s.summary = "DistribuStream is a fully open peercasting system allowing on-demand or live streaming media to be delivered at a fraction of the normal cost"
8
8
  s.email = "tony@clickcaster.com"
data/lib/pdtp/client.rb CHANGED
@@ -13,6 +13,7 @@ require 'eventmachine'
13
13
  require 'thread'
14
14
  require 'digest/md5'
15
15
 
16
+ require File.dirname(__FILE__) + '/common'
16
17
  require File.dirname(__FILE__) + '/client/connection'
17
18
  require File.dirname(__FILE__) + '/client/callbacks'
18
19
  require File.dirname(__FILE__) + '/client/file_service'
@@ -57,18 +57,20 @@ module PDTP
57
57
  message,
58
58
  @client.file_service
59
59
  )
60
+
61
+ transfer.run
60
62
 
61
- @@log.debug "TRANSFER STARTING"
63
+ #@@log.debug "TRANSFER STARTING"
62
64
 
63
65
  # Run each transfer in its own thread and notify the server upon completion
64
- Thread.new(transfer) do |t|
65
- begin
66
- t.run
67
- rescue Exception=>e
68
- @@log.info("Exception in dispatch_message: " + e.exception + "\n" + e.backtrace.join("\n"))
69
- end
70
- t.send_completed_message(t.hash)
71
- end
66
+ #Thread.new(transfer) do |t|
67
+ # begin
68
+ # t.run
69
+ # rescue Exception=>e
70
+ # @@log.info("Exception in dispatch_message: " + e.exception + "\n" + e.backtrace.join("\n"))
71
+ # end
72
+ # t.send_completed_message(t.hash)
73
+ #end
72
74
  when "tell_verify"
73
75
  # We are a listener, and asked for verification of a transfer from a server.
74
76
  # After asking for verification, we stopped running, and must be restarted
@@ -0,0 +1,114 @@
1
+ # $Id: httpclient.rb 518 2007-08-30 10:17:02Z blackhedd $
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 July 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ # This version of HttpClient has been modified for use in DistribuStream
27
+ # Notable changes:
28
+ # - Moved into PDTP::Client namespace
29
+ # - HTTP/1.1 switched to HTTP/1.0
30
+ # - Introduced support for HTTP ranges
31
+ # - Support for X headers
32
+
33
+ module PDTP
34
+ class Client
35
+ class HttpClient < EventMachine::Protocols::HttpClient
36
+ # Override send_request to support the additional features we need
37
+ def send_request args
38
+ args[:verb] ||= args[:method] # Support :method as an alternative to :verb.
39
+ args[:verb] ||= :get # IS THIS A GOOD IDEA, to default to GET if nothing was specified?
40
+
41
+ verb = args[:verb].to_s.upcase
42
+ unless ["GET", "POST", "PUT", "DELETE", "HEAD"].include?(verb)
43
+ set_deferred_status :failed, {:status => 0} # TODO, not signalling the error type
44
+ return # NOTE THE EARLY RETURN, we're not sending any data.
45
+ end
46
+
47
+ request = args[:request] || "/"
48
+ unless request[0,1] == "/"
49
+ request = "/" + request
50
+ end
51
+
52
+ qs = args[:query_string] || ""
53
+ if qs.length > 0 and qs[0,1] != '?'
54
+ qs = "?" + qs
55
+ end
56
+
57
+ # Allow an override for the host header if it's not the connect-string.
58
+ port = args[:port]
59
+ host = args[:host_header] || "#{args[:host]}#{port}" || "_"
60
+
61
+ # POST items.
62
+ postcontenttype = args[:contenttype] || "application/octet-stream"
63
+ postcontent = args[:content] || ""
64
+ raise "oversized content in HTTP POST" if postcontent.length > MaxPostContentLength
65
+
66
+ # ESSENTIAL for the request's line-endings to be CRLF, not LF. Some servers misbehave otherwise.
67
+ # TODO: We ASSUME the caller wants to send a 1.1 request. May not be a good assumption.
68
+ req = [
69
+ "#{verb} #{request}#{qs} HTTP/1.1",
70
+ "Host: #{host}",
71
+ "User-Agent: #{args[:agent] || 'Ruby EventMachine'}"
72
+ ]
73
+
74
+ if verb == "POST" || verb == "PUT"
75
+ req << "Content-Type: #{postcontenttype}"
76
+ req << "Content-Length: #{postcontent.length}"
77
+ end
78
+
79
+ if args[:range]
80
+ # Convert the range to an array if it isn't one already
81
+ args[:range] = [args[:range]] unless args[:range].is_a?(Array)
82
+
83
+ # Transform it to a text string
84
+ range = args[:range].map { |v| v.is_a?(Range) ? "#{v.min}-#{v.max}" : (v >= 0 ? "#{v}-" : v.to_s) }.join(',')
85
+ req << "Range: bytes=#{range}"
86
+ end
87
+
88
+ if args[:headers]
89
+ headers = case args[:headers]
90
+ when Array then args[:headers]
91
+ when String then [args[:headers]]
92
+ else raise ArgumentError, "headers must be an array or string"
93
+ end
94
+
95
+ req += headers
96
+ end
97
+
98
+ # TODO, this cookie handler assumes it's getting a single, semicolon-delimited string.
99
+ # Eventually we will want to deal intelligently with arrays and hashes.
100
+ if args[:cookie]
101
+ req << "Cookie: #{args[:cookie]}"
102
+ end
103
+
104
+ req << ""
105
+ reqstring = req.map {|l| "#{l}\r\n"}.join
106
+ send_data reqstring
107
+
108
+ if verb == "POST" || verb == "PUT"
109
+ send_data postcontent
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -8,12 +8,15 @@
8
8
  # See http://distribustream.rubyforge.org/
9
9
  #++
10
10
 
11
- require File.dirname(__FILE__) + '/file_service'
12
11
  require "thread"
13
- require "net/http"
12
+ #require "net/http"
14
13
  require "uri"
15
14
  require "digest/sha2"
16
15
 
16
+ require File.dirname(__FILE__) + '/../common'
17
+ require File.dirname(__FILE__) + '/file_service'
18
+ require File.dirname(__FILE__) + '/http_client'
19
+
17
20
  module PDTP
18
21
  class Client
19
22
  module Transfer
@@ -33,10 +36,10 @@ module PDTP
33
36
 
34
37
  # Returns true if a server message matches this transfer
35
38
  def matches_message?(message)
36
- @peer == message["peer"] and
37
- @url == message["url"] and
39
+ @peer == message["peer"] and
40
+ @url == message["url"] and
38
41
  @byte_range == message["range"] and
39
- @peer_id == message["peer_id"]
42
+ @peer_id == message["peer_id"]
40
43
  end
41
44
 
42
45
  # Takes an HTTP range and returns a ruby Range object
@@ -177,50 +180,57 @@ module PDTP
177
180
  # Implements http transfer between two peers from the connector's (client) perspective
178
181
  class Connector < Base
179
182
  def initialize(connection, message, file_service)
180
- @file_service=file_service
181
- @peer,@port=message["host"],message["port"]
182
- @method = message["method"]
183
- @url=message["url"]
184
- @byte_range=message["range"]
185
- @peer_id=message["peer_id"]
186
- @connection=connection
183
+ @connection = connection
184
+ @file_service = file_service
185
+ @peer = message["host"]
186
+ @port = message["port"]
187
+ @method = message["method"]
188
+ @url = message["url"]
189
+ @byte_range = message["range"]
190
+ @peer_id = message["peer_id"]
187
191
  end
188
192
 
189
193
  # Perform the transfer
190
194
  def run
191
- hash=nil
192
-
193
- info=@file_service.get_info(@url)
195
+ info = @file_service.get_info(@url)
194
196
 
195
197
  #compute the vhost and path
196
198
  #FIXME work with ports
197
- uri=URI.split(@url)
198
- path=uri[5]
199
- vhost=uri[2]
200
-
201
- if @method == "get"
202
- req = Net::HTTP::Get.new(path)
203
- body = nil
204
- elsif @method == "put"
205
- req = Net::HTTP::Put.new(path)
206
- body = info.read(@byte_range)
207
- else
208
- raise HTTPException.new(405,"Invalid method: #{@method}")
199
+ uri = URI.parse(@url)
200
+
201
+ options = {
202
+ :method => @method,
203
+ :host => @peer,
204
+ :host_header => uri.host,
205
+ :port => @port,
206
+ :request => uri.path,
207
+ :range => @byte_range,
208
+ :agent => "DistribuStream #{PDTP::VERSION}",
209
+ :headers => "X-PDTP-Peer-Id: #{@connection.client.client_id}"
210
+ }
211
+
212
+ case @method
213
+ when 'get'
214
+ when 'put' then options[:content] = info.read(@byte_range)
215
+ else raise HTTPException.new(405, "Invalid method: #{@method}")
216
+ end
217
+
218
+ http = HttpClient.request options
219
+ http.callback do |response|
220
+ hash = nil
221
+
222
+ if @method == 'get' and response[:status] == 206
223
+ @@log.debug("Body Downloaded: url=#{@url} range=#{@byte_range} peer=#{@peer}:#{@port}")
224
+ info.write(@byte_range.first,response[:content])
225
+ hash = Digest::SHA256.hexdigest(response[:content]) rescue nil
226
+ elsif @method == 'put' and response[:status] == 200
227
+ @@log.debug("Body Uploaded: url=#{@url} range=#{@byte_range} peer=#{@peer}:#{@port}")
228
+ else
229
+ raise RuntimeError, "Invalid method/status combination: #{@method} #{response[:status]}"
230
+ end
231
+
232
+ send_completed_message hash
209
233
  end
210
-
211
- req.add_field("Range", "bytes=#{@byte_range.begin}-#{@byte_range.end}")
212
- req.add_field("Host",vhost)
213
- req.add_field("X-PDTP-Peer-Id", @connection.client.client_id)
214
- res = Net::HTTP.start(@peer,@port) {|http| http.request(req,body) }
215
-
216
- if res.code == '206' and @method == 'get'
217
- #we are the taker
218
- @@log.debug("Body Downloaded: url=#{@url} range=#{@byte_range} peer=#{@peer}:#{@port}")
219
- info.write(@byte_range.first,res.body)
220
- @hash=Digest::SHA256.hexdigest(res.body) rescue nil
221
- else
222
- raise "HTTP RESPONSE: code=#{res.code} body=#{res.body}"
223
- end
224
234
  end
225
235
  end
226
236
  end
@@ -0,0 +1,15 @@
1
+ #--
2
+ # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
+ # All rights reserved. See COPYING for permissions.
4
+ #
5
+ # This source file is distributed as part of the
6
+ # DistribuStream file transfer system.
7
+ #
8
+ # See http://distribustream.rubyforge.org/
9
+ #++
10
+
11
+ # Namespace for all PDTP components
12
+ module PDTP
13
+ PDTP::VERSION = '0.2.1' unless defined? PDTP::VERSION
14
+ def self.version() VERSION end
15
+ end
@@ -30,7 +30,7 @@ CONFIG_TYPES = {
30
30
  :quiet => :bool,
31
31
  :chunk_size => :int,
32
32
  :request_url => :string
33
- }
33
+ } unless defined? CONFIG_TYPES
34
34
 
35
35
  #prints banner and loads config file
36
36
  def common_init(program_name, config = nil)
@@ -119,4 +119,4 @@ end
119
119
  #responds to config options that are used by both client and server
120
120
  def handle_config_options
121
121
  @@log.level=Logger::INFO if @@config[:quiet]
122
- end
122
+ end
@@ -12,58 +12,71 @@ require 'rubygems'
12
12
  require 'eventmachine'
13
13
 
14
14
  module PDTP
15
- # EventMachine connection adapter for sending and receiving frames with 16-bit length prefixes
16
- class Packet < EventMachine::Connection
17
- # Class for processing length prefixes in packet frames
15
+ # EventMachine connection adapter for length prefix framing
16
+ class LengthPrefixProtocol < EventMachine::Connection
17
+ # Class for processing size prefixes in packet frames
18
18
  class Prefix
19
- attr_reader :length
19
+ attr_reader :size, :data
20
20
 
21
- def initialize
22
- # Constant at 2 bytes, but expandable if we desire
23
- @length = 2
21
+ def initialize(size = 2)
22
+ unless size == 2 or size == 4
23
+ raise ArgumentError, 'only 2 or 4 byte prefixes are supported'
24
+ end
25
+
26
+ @size = size
24
27
  reset!
25
28
  end
26
29
 
30
+ # Has the entire prefix been read yet?
27
31
  def read?
28
- @length == @read
32
+ @size == @read
29
33
  end
30
34
 
35
+ # Append data to the prefix and return any extra
31
36
  def append(data)
32
- toread = @length - @read
37
+ toread = @size - @read
33
38
  new_data = data[0..(toread - 1)]
34
39
 
35
40
  @data << new_data
36
- @read += new_data.size
37
- return nil unless @read == @length
41
+ @read += new_data.length
42
+ return nil unless @read == @size
38
43
 
39
- @size = @data.unpack('n').first
40
- result = data[toread..data.size]
44
+ @length = @data.unpack(@size == 2 ? 'n' : 'N').first
45
+ result = data[toread..data.length]
41
46
 
42
47
  return nil if result.nil? or result.empty?
43
48
  result
44
49
  end
45
50
 
46
- def size
47
- return false unless read?
48
- @size
51
+ # Length of the payload extracted from the prefix
52
+ def length
53
+ raise RuntimeError, 'length called before prefix extracted' unless read?
54
+ @length
49
55
  end
50
56
 
51
57
  def reset!
52
- @size = nil
58
+ @length = nil
53
59
  @read = 0
54
60
  @data = ''
55
61
  end
56
62
  end
57
63
 
58
- def initialize(*args)
64
+ def initialize *args
59
65
  super
66
+
60
67
  @prefix = Prefix.new
61
68
  @buffer = ''
62
69
  end
63
70
 
71
+ def prefix_size=(size)
72
+ data = @prefix.data << @buffer
73
+ @prefix = Prefix.new size
74
+ receive_data data
75
+ end
76
+
64
77
  # Callback for processing incoming frames
65
78
  def receive_data(data)
66
- # Read data and append it to the length prefix unless it's already been read
79
+ # Read data and append it to the size prefix unless it's already been read
67
80
  data = @prefix.append(data) unless @prefix.read?
68
81
  return if data.nil?
69
82
 
@@ -71,14 +84,16 @@ module PDTP
71
84
  @buffer << data
72
85
 
73
86
  # Don't do anything until we receive the specified amount of data
74
- return unless @buffer.size >= @prefix.size
87
+ return unless @buffer.length >= @prefix.length
75
88
 
76
89
  # Extract the specified amount of data and process it
77
- data = @buffer[0..(@prefix.size - 1)]
78
- receive_packet data
90
+ data = @buffer[0..(@prefix.length - 1)]
79
91
 
80
92
  # Store any remaining data
81
- remainder = @buffer[@prefix.size..@buffer.size]
93
+ remainder = @buffer[@prefix.length..@buffer.length]
94
+
95
+ # Invoke receive_packet and allow the user to process the data
96
+ receive_packet data
82
97
 
83
98
  # Reset the prefix and buffer since we've received a whole frame
84
99
  @prefix.reset!
@@ -95,12 +110,10 @@ module PDTP
95
110
  def receive_packet(packet)
96
111
  end
97
112
 
98
- # Send a packet with a specified length prefix
113
+ # Send a packet with a specified size prefix
99
114
  def send_packet(data)
100
- length = data.size
101
- raise ArgumentError, 'oversize packet' if length >= 256**@prefix.length
102
-
103
- send_data [length].pack('n') << data
115
+ raise ArgumentError, 'packet too long for prefix length' if data.size >= 256**@prefix.size
116
+ send_data [data.size].pack(@prefix.size == 2 ? 'n' : 'N') << data
104
117
  end
105
118
  end
106
- end
119
+ end
@@ -19,10 +19,10 @@ rescue LoadError
19
19
  require 'json'
20
20
  end
21
21
 
22
- require File.dirname(__FILE__) + '/packet.rb'
22
+ require File.dirname(__FILE__) + '/length_prefix_protocol.rb'
23
23
 
24
24
  module PDTP
25
- PROTOCOL_DEBUG=true
25
+ PDTP::PROTOCOL_DEBUG = true unless defined? PDTP::PROTOCOL_DEBUG
26
26
 
27
27
  class ProtocolError < Exception
28
28
  end
@@ -31,7 +31,7 @@ module PDTP
31
31
  end
32
32
 
33
33
  # EventMachine handler class for the PDTP protocol
34
- class Protocol < PDTP::Packet
34
+ class Protocol < PDTP::LengthPrefixProtocol
35
35
  @@num_connections = 0
36
36
  @@message_params = nil
37
37
  @connection_open = false
@@ -40,10 +40,10 @@ module PDTP
40
40
  @connection_open
41
41
  end
42
42
 
43
- def initialize(data)
43
+ def initialize *args
44
44
  user_data = nil
45
45
  @mutex = Mutex.new
46
- super data
46
+ super
47
47
  end
48
48
 
49
49
  #called by EventMachine after a connection has been established
@@ -67,8 +67,8 @@ module PDTP
67
67
  #close a connection, but first send the specified error message
68
68
  def error_close_connection(error)
69
69
  if PROTOCOL_DEBUG
70
- send_message :protocol_error, :message => msg
71
- close_connection(true) # close after writing
70
+ send_message :protocol_error, :message => error
71
+ close_connection true # close after writing
72
72
  else
73
73
  close_connection
74
74
  end
@@ -105,7 +105,7 @@ module PDTP
105
105
  end
106
106
  end
107
107
 
108
- RANGENAMES = %w{chunk_range range byte_range}
108
+ PDTP::RANGENAMES = %w{chunk_range range byte_range} unless defined? PDTP::RANGENAMES
109
109
 
110
110
  #converts Ruby Range classes in the message to PDTP protocol hashes with min and max
111
111
  # 0..-1 => nil (entire file)
@@ -333,4 +333,4 @@ module PDTP
333
333
  mp
334
334
  end
335
335
  end
336
- end
336
+ end
data/lib/pdtp/server.rb CHANGED
@@ -12,6 +12,7 @@ require 'rubygems'
12
12
  require 'eventmachine'
13
13
  require 'mongrel'
14
14
 
15
+ require File.dirname(__FILE__) + '/common'
15
16
  require File.dirname(__FILE__) + '/server/dispatcher'
16
17
  require File.dirname(__FILE__) + '/server/file_service'
17
18
  require File.dirname(__FILE__) + '/server/connection'
@@ -24,14 +24,14 @@ module PDTP
24
24
  class Protocol < PDTP::Client::Connection
25
25
  attr_reader :client, :connection, :file_service, :client_id, :transfers, :lock
26
26
 
27
- def initialize(data)
27
+ def initialize *args
28
28
  @transfers = []
29
29
  @lock = Mutex.new
30
30
  @client = self
31
31
  @connection = self
32
32
  @client_id = Digest::MD5.hexdigest "#{Time.now.to_f}#{$$}"
33
33
 
34
- super data
34
+ super
35
35
  end
36
36
 
37
37
  # Called after a connection to the server has been established
@@ -113,4 +113,4 @@ module PDTP
113
113
  end
114
114
  end
115
115
  end
116
- end
116
+ end
metadata CHANGED
@@ -1,9 +1,9 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: distribustream
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.0
6
+ version: 0.2.1
7
7
  date: 2008-10-22 00:00:00 -06:00
8
8
  summary: DistribuStream is a fully open peercasting system allowing on-demand or live streaming media to be delivered at a fraction of the normal cost
9
9
  require_paths:
@@ -38,20 +38,21 @@ files:
38
38
  - bin/dstream
39
39
  - lib/pdtp
40
40
  - lib/pdtp/client
41
- - lib/pdtp/client.rb
42
- - lib/pdtp/common
43
- - lib/pdtp/server
44
- - lib/pdtp/server.rb
45
41
  - lib/pdtp/client/callbacks.rb
46
42
  - lib/pdtp/client/connection.rb
47
43
  - lib/pdtp/client/file_buffer.rb
48
44
  - lib/pdtp/client/file_service.rb
45
+ - lib/pdtp/client/http_client.rb
49
46
  - lib/pdtp/client/http_handler.rb
50
47
  - lib/pdtp/client/transfer.rb
48
+ - lib/pdtp/client.rb
49
+ - lib/pdtp/common
51
50
  - lib/pdtp/common/common_init.rb
52
51
  - lib/pdtp/common/file_service.rb
53
- - lib/pdtp/common/packet.rb
52
+ - lib/pdtp/common/length_prefix_protocol.rb
54
53
  - lib/pdtp/common/protocol.rb
54
+ - lib/pdtp/common.rb
55
+ - lib/pdtp/server
55
56
  - lib/pdtp/server/client_info.rb
56
57
  - lib/pdtp/server/connection.rb
57
58
  - lib/pdtp/server/dispatcher.rb
@@ -60,6 +61,7 @@ files:
60
61
  - lib/pdtp/server/stats_handler.rb
61
62
  - lib/pdtp/server/transfer.rb
62
63
  - lib/pdtp/server/trust.rb
64
+ - lib/pdtp/server.rb
63
65
  - conf/bigchunk.yml
64
66
  - conf/debug.yml
65
67
  - conf/example.yml