distribustream 0.1.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.
@@ -0,0 +1,89 @@
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
+ require "uri"
12
+ require "pathname"
13
+ require "digest/sha2"
14
+ require File.dirname(__FILE__) + '/../common/file_service.rb'
15
+
16
+ module PDTP
17
+ class Server
18
+ #The server specific file utilities
19
+ class FileInfo < PDTP::FileInfo
20
+ attr_accessor :path
21
+
22
+ #Return a raw string of chunk data. The range parameter is local to this chunk
23
+ #and zero based
24
+ def chunk_data(chunkid, range = nil)
25
+ begin
26
+ range = 0..chunk_size(chunkid) - 1 if range.nil? # full range of chunk if range isnt specified
27
+ raise if range.first < 0 or range.last >= chunk_size(chunkid)
28
+ start = range.first + chunkid * @base_chunk_size
29
+ size = range.last-range.first + 1
30
+ file = open @path
31
+ file.pos = start
32
+ file.read size
33
+ rescue nil
34
+ end
35
+ end
36
+
37
+ #reads the specified byte range from the file and returns it as a string
38
+ def read(range)
39
+ #puts "READING: range=#{range}"
40
+ begin
41
+ file = open @path
42
+ file.pos = range.first
43
+ file.read range.last - range.first + 1
44
+ rescue nil
45
+ end
46
+ end
47
+ end
48
+
49
+ #The file service provides utilities for determining various information about files.
50
+ class FileService < PDTP::FileService
51
+ attr_accessor :root,:default_chunk_size
52
+
53
+ def initialize
54
+ @root = ''
55
+ @default_chunk_size = 512
56
+ end
57
+
58
+ def get_info(url)
59
+ begin
60
+ host = URI.split(url)[2]
61
+ #FIXME we should check host against a list of known hosts here
62
+ info = FileInfo.new
63
+ info.streaming = false
64
+ info.base_chunk_size = @default_chunk_size
65
+ info.path = get_local_path(url)
66
+ raise if File.directory?(info.path)
67
+ info.file_size = File.size?(info.path)
68
+ return nil if info.file_size == 0 or info.file_size.nil?
69
+ rescue
70
+ return nil
71
+ end
72
+
73
+ info
74
+ end
75
+
76
+ #returns the path of this file on the local filesystem
77
+ def get_local_path(url)
78
+ path = URI.split(url)[5]
79
+ path = path[1..path.size-1] #remove leading /
80
+ (Pathname.new(@root) + path).to_s
81
+ end
82
+
83
+ #returns the SHA256 hash of the specified chunk
84
+ def get_chunk_hash(url,chunk_id)
85
+ Digest::SHA256.hexdigest(get_info(url).chunk_data(chunk_id)) rescue nil
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,62 @@
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
+ module PDTP
12
+ class Server
13
+ #stores information for the server about a specific transfer
14
+ class Transfer
15
+ attr_reader :taker, :giver, :url, :chunkid
16
+ attr_reader :connector, :acceptor, :byte_range
17
+ attr_accessor :transfer_id
18
+ attr_accessor :creation_time
19
+ attr_accessor :verification_asked
20
+
21
+ def initialize(taker,giver,url,chunkid,byte_range,connector_receives=true)
22
+ @taker,@giver,@url,@chunkid,@byte_range=taker,giver,url,chunkid,byte_range
23
+
24
+ @verification_asked = false
25
+ @creation_time = Time.now
26
+ if connector_receives
27
+ @connector=@taker
28
+ @acceptor=@giver
29
+ else
30
+ @connector=@giver
31
+ @acceptor=@taker
32
+ end
33
+
34
+ recompute_transfer_id
35
+ end
36
+
37
+ #calculates the transfer id for this transfer based on the local data
38
+ def recompute_transfer_id
39
+ id1=connector.user_data.client_id
40
+ id2=acceptor.user_data.client_id
41
+ @transfer_id=Transfer::gen_transfer_id(id1,id2,@url,@byte_range)
42
+ end
43
+
44
+ #generates a transfer id based on 2 client ids, a url, and a byte range
45
+ def self.gen_transfer_id(id1,id2,url,byte_range)
46
+ a = id1<id2 ? id1 : id2
47
+ b = id1<id2 ? id2 : id1
48
+ "#{a}$#{b}$#{url}$#{byte_range}"
49
+ end
50
+
51
+ def to_s
52
+ "taker=#{@taker}, giver=#{@giver}, connector=#{@connector}, acceptor=#{@acceptor}, url=#{@url}, chunk_id=#{@chunkid} range=#{@byte_range}"
53
+ end
54
+
55
+ def debug_str
56
+ str = ''
57
+ str << "to_s=#{to_s}"
58
+ str << " taker_id=#{@taker.user_data.client_id} giver_id=#{@giver.user_data.client_id}"
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,88 @@
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
+ module PDTP
12
+ #maintains trust information for a single client
13
+ class Trust
14
+ #struct for storing a single trust relationship
15
+ class Edge
16
+ attr_accessor :trust, :success, :transfers
17
+
18
+ def initialize(trust = 1.0, success = 1.0, transfers = 1.0)
19
+ @trust = trust
20
+ @success = success
21
+ @transfers = transfers
22
+ end
23
+ end
24
+
25
+ attr_reader :outgoing, :implicit
26
+
27
+ def initialize(incoming = {}, outgoing = {}, implicit = {})
28
+ @incoming = incoming
29
+ @outgoing = outgoing
30
+ @implicit = implicit
31
+ end
32
+
33
+ #I have successfully downloaded a chunk from 'node'
34
+ def success(node)
35
+ if @outgoing[node].nil?
36
+ @outgoing[node] = Edge.new
37
+ else
38
+ @outgoing[node].success += 1.0
39
+ @outgoing[node].transfers += 1.0
40
+ end
41
+ normalize
42
+ end
43
+
44
+ #I have failed to download a chunk from 'node'
45
+ def failure(node)
46
+ @outgoing[node] = Edge.new if @outgoing[node].nil?
47
+ @outgoing[node].transfers += 1.0
48
+ normalize
49
+ end
50
+
51
+ #returns a number from 0 to 1 saying how much I trust 'node'
52
+ def weight(node)
53
+ return @outgoing[node].trust unless @outgoing[node].nil?
54
+ return @implicit[node].trust unless @implicit[node].nil?
55
+ 0
56
+ end
57
+
58
+ # brings all trust values between 0 and 1
59
+ def normalize
60
+ total_success = 0
61
+ total_transfers = 0
62
+
63
+ @outgoing.each do |_, link|
64
+ total_success += link.success
65
+ total_transfers += link.transfers
66
+ end
67
+
68
+ @outgoing.each { |_, link| link.trust = link.success / total_transfers }
69
+ @outgoing.each do |target, link|
70
+ [target.outgoing, target.implicit].each do |links|
71
+ links.each do |nextlinkedge|
72
+ nextlinktarget = nextlinkedge[0]
73
+ nextlink = nextlinkedge[1]
74
+ next unless outgoing[nextlinktarget].nil?
75
+
76
+ if implicit[nextlinktarget].nil? || implicit[nextlinktarget].trust < (link.trust * nextlink.trust)
77
+ implicit[nextlinktarget] = Edge.new(
78
+ link.trust * nextlink.trust,
79
+ nextlink.success,
80
+ nextlink.transfers
81
+ )
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,40 @@
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
+ require File.dirname(__FILE__) + '/trust'
12
+
13
+ describe 'A new trust node' do
14
+ before(:each) do
15
+ @node = PDTP::Trust.new
16
+ @other = PDTP::Trust.new
17
+ @distant = PDTP::Trust.new
18
+ end
19
+
20
+ it 'should be empty' do
21
+ @node.outgoing.should be_empty
22
+ @node.implicit.should be_empty
23
+ end
24
+
25
+ it 'should trust a node after a good transfer' do
26
+ @node.success(@other)
27
+ @node.outgoing.should_not be_empty
28
+ end
29
+
30
+ it 'should normalize trusts across outgoing edges' do
31
+ @node.success(@other)
32
+ trust = @node.weight(@other)
33
+
34
+ @node.success(@distant)
35
+ @node.outgoing.size.should == 2
36
+
37
+ @node.weight(@other).should < trust
38
+ (@node.weight(@other) + @node.weight(@distant)).should be_close(1.0, 0.00001)
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: distribustream
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2008-10-11 00:00:00 -06:00
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
+ require_paths:
10
+ - lib
11
+ email: tony@clickcaster.com
12
+ homepage: http://distribustream.rubyforge.org
13
+ rubyforge_project: distribustream
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Tony Arcieri
31
+ - Ashvin Mysore
32
+ - Galen Pahlke
33
+ - James Sanders
34
+ - Tom Stapleton
35
+ files:
36
+ - bin/distribustream
37
+ - bin/dsclient
38
+ - bin/dsseed
39
+ - lib/pdtp
40
+ - lib/pdtp/client
41
+ - lib/pdtp/client.rb
42
+ - lib/pdtp/common
43
+ - lib/pdtp/server
44
+ - lib/pdtp/server.rb
45
+ - lib/pdtp/client/file_buffer.rb
46
+ - lib/pdtp/client/file_buffer_spec.rb
47
+ - lib/pdtp/client/file_service.rb
48
+ - lib/pdtp/client/protocol.rb
49
+ - lib/pdtp/client/transfer.rb
50
+ - lib/pdtp/common/common_init.rb
51
+ - lib/pdtp/common/file_service.rb
52
+ - lib/pdtp/common/file_service_spec.rb
53
+ - lib/pdtp/common/protocol.rb
54
+ - lib/pdtp/common/protocol_spec.rb
55
+ - lib/pdtp/server/client_info.rb
56
+ - lib/pdtp/server/file_service.rb
57
+ - lib/pdtp/server/transfer.rb
58
+ - lib/pdtp/server/trust.rb
59
+ - lib/pdtp/server/trust_spec.rb
60
+ - conf/bigchunk.yml
61
+ - conf/debug.yml
62
+ - conf/example.yml
63
+ - Rakefile
64
+ - distribustream.gemspec
65
+ - COPYING
66
+ - README
67
+ - CHANGES
68
+ test_files: []
69
+
70
+ rdoc_options:
71
+ - --exclude
72
+ - definitions
73
+ - --exclude
74
+ - indexes
75
+ extra_rdoc_files:
76
+ - COPYING
77
+ - README
78
+ - CHANGES
79
+ executables:
80
+ - distribustream
81
+ - dsseed
82
+ - dsclient
83
+ extensions: []
84
+
85
+ requirements: []
86
+
87
+ dependencies:
88
+ - !ruby/object:Gem::Dependency
89
+ name: eventmachine
90
+ version_requirement:
91
+ version_requirements: !ruby/object:Gem::Version::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 0.9.0
96
+ version:
97
+ - !ruby/object:Gem::Dependency
98
+ name: mongrel
99
+ version_requirement:
100
+ version_requirements: !ruby/object:Gem::Version::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 1.0.1
105
+ version:
106
+ - !ruby/object:Gem::Dependency
107
+ name: json
108
+ version_requirement:
109
+ version_requirements: !ruby/object:Gem::Version::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: 1.1.0
114
+ version: