distribustream 0.4.1 → 0.5.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,146 @@
1
+ #--
2
+ # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # This source file is distributed as part of the
18
+ # DistribuStream file transfer system.
19
+ #
20
+ # See http://distribustream.org/
21
+ #++
22
+
23
+ require File.dirname(__FILE__) + '/transfer'
24
+
25
+ module PDTP
26
+ class Server
27
+ # Decision-making logic for initiating peer-to-peer transfers
28
+ class TransferManager
29
+ def initialize(connections, file_service)
30
+ @connections, @file_service = connections, file_service
31
+ @updated_clients = []
32
+ end
33
+
34
+ # Add client to list of ones needing updates
35
+ def process_client(client)
36
+ @updated_clients << client
37
+ end
38
+
39
+ # Creates new transfers for all clients that have been updated
40
+ def spawn_all_transfers
41
+ @updated_clients.each { |client| spawn_transfers_for_client(client) }
42
+ @updated_clients.clear
43
+ end
44
+
45
+ #########
46
+ protected
47
+ #########
48
+
49
+ # Spawns uploads and downloads for this client.
50
+ # Should be called every time there is a change that would affect
51
+ # what this client has or wants
52
+ def spawn_transfers_for_client(connection)
53
+ while connection.wants_download? do
54
+ break unless spawn_download_for_client(connection)
55
+ end
56
+
57
+ while connection.wants_upload? do
58
+ break unless spawn_upload_for_client(connection)
59
+ end
60
+ end
61
+
62
+ # Creates a single download for the specified client
63
+ # Returns true on success, false on failure
64
+ def spawn_download_for_client(connection)
65
+ feasible_peers = []
66
+
67
+ begin
68
+ url, chunkid = connection.chunk_info.high_priority_chunk
69
+ rescue
70
+ return false
71
+ end
72
+
73
+ @connections.each do |c2|
74
+ next if connection == c2
75
+ next unless c2.wants_upload?
76
+ if c2.chunk_info.provided?(url, chunkid)
77
+ feasible_peers << c2
78
+ break if feasible_peers.size > 5
79
+ end
80
+ end
81
+
82
+ # we now have a list of clients that have the requested chunk.
83
+ # pick one and start the transfer
84
+ if feasible_peers.size > 0
85
+ #FIXME base this on the trust model
86
+ giver = feasible_peers[rand(feasible_peers.size)]
87
+ return begin_transfer(connection,giver,url,chunkid)
88
+ #FIXME should we try again if begin_transfer fails?
89
+ end
90
+
91
+ false
92
+ end
93
+
94
+ # Creates a single upload for the specified client
95
+ # Returns true on success, false on failure
96
+ def spawn_upload_for_client(connection)
97
+ @connections.each do |c2|
98
+ next if connection == c2
99
+ next unless c2.wants_download?
100
+
101
+ begin
102
+ url, chunkid = c2.chunk_info.high_priority_chunk
103
+ rescue
104
+ next
105
+ end
106
+
107
+ if connection.chunk_info.provided?(url, chunkid)
108
+ return begin_transfer(c2, connection, url, chunkid)
109
+ end
110
+ end
111
+
112
+ false
113
+ end
114
+
115
+ # Creates a new transfer between two peers
116
+ # Returns true on success, or false if the specified transfer is already in progress
117
+ def begin_transfer(taker, giver, url, chunkid)
118
+ byte_range = @file_service.get_info(url).chunk_range(chunkid)
119
+ t = Transfer.new(taker, giver, url, chunkid, byte_range)
120
+
121
+ #make sure this transfer doesnt already exist
122
+ t1 = taker.transfers[t.transfer_id]
123
+ t2 = giver.transfers[t.transfer_id]
124
+ return false unless t1.nil? and t2.nil?
125
+
126
+ taker.chunk_info.transfer(url, chunkid..chunkid)
127
+ taker.transfers[t.transfer_id] = t
128
+ giver.transfers[t.transfer_id] = t
129
+
130
+ #send transfer message to the connector
131
+ addr, port = t.acceptor.get_peer_info
132
+
133
+ t.connector.send_message(:transfer,
134
+ :host => addr,
135
+ :port => t.acceptor.listen_port,
136
+ :method => t.connector == t.taker ? "get" : "put",
137
+ :url => url,
138
+ :range => byte_range,
139
+ :peer_id => t.acceptor.client_id
140
+ )
141
+
142
+ true
143
+ end
144
+ end
145
+ end
146
+ end
data/status/index.erb CHANGED
@@ -12,24 +12,38 @@
12
12
  </div>
13
13
  <center>
14
14
  <table border="0" cellpadding="0" cellspacing="0">
15
- <tr><th>Client</th><th>Transfers</th><th>Files</th></tr>
15
+ <tr>
16
+ <th>Client</th>
17
+ <th>Bandwidth</th>
18
+ <th>Transfers</th>
19
+ <th>Files</th>
20
+ </tr>
21
+
16
22
  <% each_peer do |peer| %>
17
- <tr class="row<%= cycle(' row_alternate', '') %>"><td>
18
- <%= peer_name(peer) %><br />
19
- <%= peer_address(peer) %>
20
- </td>
21
- <td>
22
- <% each_transfer(peer) do |transfer| %>
23
- <%= transfer_info(peer, transfer) %><br />
24
- <% end %>
25
- </td>
26
- <td>
27
- <% each_file(peer) do |file| %>
28
- <%= file_path(file) %>
29
- (<%= chunks_completed(file) %>/<%= chunks_active(file) %>,
30
- <%= percent_complete(file) %>%)<br />
31
- <% end %>
32
- </td></tr>
23
+ <tr class="row<%= cycle(' row_alternate', '') %>">
24
+ <td>
25
+ <%= peer_name(peer) %><br />
26
+ <%= peer_address(peer) %>
27
+ </td>
28
+ <td>
29
+ Upstream: <%= upstream_bandwidth(peer) %><br />
30
+ <% unless peer.file_service? %>
31
+ Downstream: <%= downstream_bandwidth(peer) %>
32
+ <% end %>
33
+ </td>
34
+ <td>
35
+ <% each_transfer(peer) do |transfer| %>
36
+ <%= transfer_info(peer, transfer) %><br />
37
+ <% end %>
38
+ </td>
39
+ <td>
40
+ <% each_file(peer) do |file| %>
41
+ <%= file_path(file) %>
42
+ (<%= chunks_completed(file) %>/<%= chunks_active(file) %>,
43
+ <%= percent_complete(file) %>%)<br />
44
+ <% end %>
45
+ </td>
46
+ </tr>
33
47
  <% end %>
34
48
  </table>
35
49
  </center>
@@ -38,5 +38,5 @@ td {
38
38
  }
39
39
 
40
40
  .row_alternate {
41
- background: #EEEEEE;
41
+ background: #E0E0E0;
42
42
  }
metadata CHANGED
@@ -1,10 +1,10 @@
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.4.1
7
- date: 2008-11-15 00:00:00 -07:00
6
+ version: 0.5.0
7
+ date: 2008-11-27 00:00:00 -07: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:
10
10
  - lib
@@ -33,43 +33,45 @@ authors:
33
33
  - James Sanders
34
34
  - Tom Stapleton
35
35
  files:
36
- - bin/dstream
37
36
  - bin/dsclient
37
+ - bin/dstream
38
38
  - lib/pdtp
39
- - lib/pdtp/server
40
- - lib/pdtp/common.rb
41
39
  - lib/pdtp/client
42
- - lib/pdtp/common
43
- - lib/pdtp/client.rb
44
- - lib/pdtp/server.rb
45
- - lib/pdtp/server/file_service_protocol.rb
46
- - lib/pdtp/server/status_handler.rb
47
- - lib/pdtp/server/trust.rb
48
- - lib/pdtp/server/status_helper.rb
49
- - lib/pdtp/server/transfer.rb
50
- - lib/pdtp/server/client_info.rb
51
- - lib/pdtp/server/connection.rb
52
- - lib/pdtp/server/file_service.rb
53
- - lib/pdtp/server/dispatcher.rb
40
+ - lib/pdtp/client/callbacks.rb
41
+ - lib/pdtp/client/connection.rb
54
42
  - lib/pdtp/client/file_buffer.rb
43
+ - lib/pdtp/client/file_service.rb
55
44
  - lib/pdtp/client/http_client.rb
56
45
  - lib/pdtp/client/http_handler.rb
57
- - lib/pdtp/client/callbacks.rb
58
46
  - lib/pdtp/client/transfer.rb
59
- - lib/pdtp/client/connection.rb
60
- - lib/pdtp/client/file_service.rb
61
- - lib/pdtp/common/length_prefix_protocol.rb
47
+ - lib/pdtp/client.rb
48
+ - lib/pdtp/common
49
+ - lib/pdtp/common/file_service.rb
62
50
  - lib/pdtp/common/http_server.rb
51
+ - lib/pdtp/common/length_prefix_protocol.rb
63
52
  - lib/pdtp/common/protocol.rb
64
- - lib/pdtp/common/file_service.rb
65
- - conf/example.yml
53
+ - lib/pdtp/common.rb
54
+ - lib/pdtp/server
55
+ - lib/pdtp/server/bandwidth_estimator.rb
56
+ - lib/pdtp/server/chunk_info.rb
57
+ - lib/pdtp/server/connection.rb
58
+ - lib/pdtp/server/dispatcher.rb
59
+ - lib/pdtp/server/file_service.rb
60
+ - lib/pdtp/server/file_service_protocol.rb
61
+ - lib/pdtp/server/status_handler.rb
62
+ - lib/pdtp/server/status_helper.rb
63
+ - lib/pdtp/server/transfer.rb
64
+ - lib/pdtp/server/transfer_manager.rb
65
+ - lib/pdtp/server/trust.rb
66
+ - lib/pdtp/server.rb
66
67
  - conf/bigchunk.yml
67
68
  - conf/debug.yml
68
- - status/stylesheets
69
+ - conf/example.yml
69
70
  - status/images
71
+ - status/images/logo.png
70
72
  - status/index.erb
73
+ - status/stylesheets
71
74
  - status/stylesheets/style.css
72
- - status/images/logo.png
73
75
  - Rakefile
74
76
  - distribustream.gemspec
75
77
  - COPYING
@@ -79,10 +81,11 @@ files:
79
81
  test_files: []
80
82
 
81
83
  rdoc_options:
82
- - --exclude
83
- - definitions
84
- - --exclude
85
- - indexes
84
+ - --title
85
+ - PDTP
86
+ - --main
87
+ - README
88
+ - --line-numbers
86
89
  extra_rdoc_files:
87
90
  - COPYING
88
91
  - README
@@ -1,154 +0,0 @@
1
- #--
2
- # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
- #
4
- # This program is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- #
17
- # This source file is distributed as part of the
18
- # DistribuStream file transfer system.
19
- #
20
- # See http://distribustream.org/
21
- #++
22
-
23
- require File.dirname(__FILE__) + '/trust'
24
-
25
- module PDTP
26
- class Server
27
- #stores information about a single connected client
28
- class ClientInfo
29
- attr_accessor :chunk_info, :trust
30
- attr_accessor :listen_port, :client_id
31
- attr_accessor :transfers
32
-
33
- def initialize
34
- @chunk_info=ChunkInfo.new
35
- @listen_port=6000 #default
36
- @trust=Trust.new
37
- @transfers=Hash.new
38
- end
39
-
40
- # returns true if this client wants the server to spawn a transfer for it
41
- def wants_download?
42
- transfer_state_allowed=5
43
- total_allowed=10
44
- transferring=0
45
- @transfers.each do |key, t|
46
- transferring=transferring+1 if t.verification_asked
47
- return false if transferring >= transfer_state_allowed
48
- end
49
-
50
- @transfers.size < total_allowed
51
- end
52
-
53
- #this could have a different definition, but it works fine to use wants_download?
54
- alias_method :wants_upload?, :wants_download?
55
-
56
- #returns a list of all the stalled transfers this client is a part of
57
- def get_stalled_transfers
58
- stalled=[]
59
- timeout=20.0
60
- now=Time.now
61
- @transfers.each do |key,t|
62
- #only delete if we are the acceptor to prevent race conditions
63
- next if t.acceptor.user_data != self
64
- if now-t.creation_time > timeout and not t.verification_asked
65
- stalled << t
66
- end
67
- end
68
- stalled
69
- end
70
- end
71
-
72
- #stores information about the chunks requested or provided by a client
73
- class ChunkInfo
74
- def initialize
75
- @files={}
76
- end
77
-
78
- #each chunk can either be provided, requested, transfer, or none
79
- def provide(filename,range); set(filename,range,:provided) ; end
80
- def unprovide(filename,range); set(filename,range, :none); end
81
- def request(filename,range); set(filename,range, :requested); end
82
- def unrequest(filename,range); set(filename,range, :none); end
83
- def transfer(filename,range); set(filename,range, :transfer); end
84
-
85
- def provided?(filename,chunk); get(filename,chunk) == :provided; end
86
- def requested?(filename,chunk); get(filename,chunk) == :requested; end
87
-
88
- #returns a high priority requested chunk
89
- def high_priority_chunk
90
- #right now return any chunk
91
- @files.each do |name,file|
92
- file.each_index do |i|
93
- return [name,i] if file[i]==:requested
94
- end
95
- end
96
-
97
- nil
98
- end
99
-
100
- #calls a block for each chunk of the specified type
101
- def each_chunk_of_type(type)
102
- @files.each do |name,file|
103
- file.each_index do |i|
104
- yield(name,i) if file[i]==type
105
- end
106
- end
107
- end
108
-
109
- class FileStats
110
- attr_accessor :file_chunks, :chunks_requested,:url
111
- attr_accessor :chunks_provided, :chunks_transferring
112
-
113
- def initialize
114
- @url=""
115
- @file_chunks=0
116
- @chunks_requested=0
117
- @chunks_provided=0
118
- @chunks_transferring=0
119
- end
120
- end
121
-
122
- #returns an array of FileStats objects for debug output
123
- def get_file_stats
124
- stats=[]
125
- @files.each do |name,file|
126
- fs=FileStats.new
127
- fs.file_chunks=file.size
128
- fs.url=name
129
- file.each do |chunk|
130
- fs.chunks_requested+=1 if chunk==:requested
131
- fs.chunks_provided+=1 if chunk==:provided
132
- fs.chunks_transferring+=1 if chunk==:transfer
133
- end
134
- stats << fs
135
- end
136
-
137
- stats
138
- end
139
-
140
- #########
141
- protected
142
- #########
143
-
144
- def get(filename,chunk)
145
- @files[filename][chunk] rescue :neither
146
- end
147
-
148
- def set(filename,range,state)
149
- chunks=@files[filename]||=Array.new
150
- range.each { |i| chunks[i]=state }
151
- end
152
- end
153
- end
154
- end