distribustream 0.2.1 → 0.3.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,11 +1,23 @@
1
1
  #--
2
2
  # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
- # All rights reserved. See COPYING for permissions.
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/>.
4
16
  #
5
17
  # This source file is distributed as part of the
6
18
  # DistribuStream file transfer system.
7
19
  #
8
- # See http://distribustream.rubyforge.org/
20
+ # See http://distribustream.org/
9
21
  #++
10
22
 
11
23
  require "uri"
@@ -55,6 +67,9 @@ module PDTP
55
67
  @default_chunk_size = 512
56
68
  end
57
69
 
70
+ # Retrieve information about a file. This should really be persistent
71
+ # FIXME the only authentication regarding registered files is performed
72
+ # by checking whether the registered file exists
58
73
  def get_info(url)
59
74
  begin
60
75
  host = URI.split(url)[2]
@@ -1,18 +1,30 @@
1
- #!/usr/bin/env ruby
2
1
  #--
3
2
  # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
4
- # All rights reserved. See COPYING for permissions.
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/>.
5
16
  #
6
17
  # This source file is distributed as part of the
7
18
  # DistribuStream file transfer system.
8
19
  #
9
- # See http://distribustream.rubyforge.org/
20
+ # See http://distribustream.org/
10
21
  #++
11
22
 
12
23
  require 'digest/md5'
13
- require 'thread'
14
24
 
25
+ require File.dirname(__FILE__) + '/../common'
15
26
  require File.dirname(__FILE__) + '/../common/protocol'
27
+ require File.dirname(__FILE__) + '/../common/http_server'
16
28
  require File.dirname(__FILE__) + '/../server/file_service'
17
29
  require File.dirname(__FILE__) + '/../client/connection'
18
30
  require File.dirname(__FILE__) + '/../client/http_handler'
@@ -26,64 +38,35 @@ module PDTP
26
38
 
27
39
  def initialize *args
28
40
  @transfers = []
29
- @lock = Mutex.new
30
41
  @client = self
31
42
  @connection = self
32
43
  @client_id = Digest::MD5.hexdigest "#{Time.now.to_f}#{$$}"
33
44
 
45
+ @listen_addr = '0.0.0.0'
46
+ @listen_port = 60860
47
+ @vhost = @listen_addr
34
48
  super
35
49
  end
36
50
 
37
51
  # Called after a connection to the server has been established
38
52
  def connection_completed
39
53
  begin
40
- @listen_addr = '0.0.0.0'
41
- @listen_port = @@config[:listen_port]
42
-
43
- #create the client
44
- #client = PDTP::Client.new
45
- #PDTP::Protocol.listener = client
46
- #client.server_connection = self
47
- #client.generate_client_id listen_port
48
-
49
- # Start a mongrel server on the specified port. If it isnt available, keep trying higher ports
50
- begin
51
- mongrel_server = Mongrel::HttpServer.new @listen_addr, @listen_port
52
- rescue Exception => e
53
- @listen_port += 1
54
- retry
55
- end
56
-
57
- #@@log.info "listening on port #{@listen_port}"
58
- @http_handler = Client::HttpHandler.new(self)
59
-
60
- @@log.info "listening on port #{@listen_port}"
61
- mongrel_server.register "/", @http_handler
62
- mongrel_server.run
54
+ @http_server.register "/", Client::HttpHandler.new(self)
63
55
 
64
56
  # Register our client_id and listen_port
65
57
  send_message :register, :listen_port => @listen_port, :client_id => @client_id
66
58
 
67
- @@log.info 'This client is providing'
68
59
  @file_service = PDTP::Server::FileService.new
69
60
  @file_service.root = @base_path
70
- #client.file_service = sfs #give this client access to all data
71
-
72
- hostname = @@config[:vhost]
73
61
 
74
62
  # Provide all the files in the root directory
75
63
  files = find_files @base_path
76
- files.each { |file| send_message :provide, :url => "http://#{hostname}/#{file}" }
64
+ files.each { |file| send_message :provide, :url => "http://#{@vhost}/#{file}" }
77
65
  rescue Exception => e
78
66
  puts "Exception in connection_completed: #{e}"
79
67
  puts e.backtrace.join("\n")
80
68
  exit
81
69
  end
82
- end
83
-
84
- def unbind
85
- super
86
- puts "Disconnected from PDTP server."
87
70
  end
88
71
 
89
72
  #########
@@ -91,6 +74,8 @@ module PDTP
91
74
  #########
92
75
 
93
76
  # Fine all suitable files in the give path
77
+ # FIXME This should really be moved to a lazy approach where we look
78
+ # for files as they're requested by clients
94
79
  def find_files(base_path)
95
80
  require 'find'
96
81
 
@@ -0,0 +1,103 @@
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 'rubygems'
24
+ require 'mongrel'
25
+ require 'erb'
26
+
27
+ require File.dirname(__FILE__) + '/../common/http_server'
28
+
29
+ module PDTP
30
+ class Server
31
+ #set up the mongrel server for serving the stats page
32
+ class StatusHandler < Mongrel::HttpHandler
33
+ def initialize(dispatcher)
34
+ @dispatcher = dispatcher
35
+ end
36
+
37
+ # process an incoming request to the admin page
38
+ def process(request, response)
39
+ response.start(200) do |head, out|
40
+ out.write begin
41
+ generate_html_stats
42
+ rescue Exception => e
43
+ "Exception: #{e}\n#{e.backtrace.join("\n")}"
44
+ end
45
+ end
46
+ end
47
+
48
+ #builds an html page with information about the server's internal workings
49
+ def generate_html_stats
50
+ s = ERB.new <<EOF
51
+ <html><head><title>DistribuStream Status</title></head>
52
+ <body>
53
+ <h1>DistribuStream Status</h1>
54
+ Time=<%= Time.now %><br> Connected Clients=<%= @dispatcher.connections.size %>
55
+ <center><table border="1">
56
+ <tr><th>Client</th><th>Transfers</th><th>Files</th></tr>
57
+ <% @dispatcher.connections.each do |c| %>
58
+ <tr><td>
59
+ <% if c.file_service? %>
60
+ <b>File Service</b>
61
+ <% else %>
62
+ <%= @dispatcher.connection_name(c) %>
63
+ <% end %>
64
+ <% host, port = c.get_peer_info %>
65
+ <br><%= host %>:<%= port %>
66
+ </td>
67
+ <td>
68
+ <%
69
+ @dispatcher.client_info(c).transfers.each do |key,t|
70
+ if c==t.giver
71
+ type="UP: "
72
+ peer=t.taker
73
+ else
74
+ type="DOWN: "
75
+ peer=t.giver
76
+ end
77
+ %>
78
+ <%= type %> id=<%= t.transfer_id %><br>
79
+ <%
80
+ end
81
+ %>
82
+ </td>
83
+ <td>
84
+ <%
85
+ @dispatcher.client_info(c).chunk_info.get_file_stats.each do |fs|
86
+ %>
87
+ <%= fs.url %> size=<%= fs.file_chunks %> req=<%= fs.chunks_requested %>
88
+ prov=<%= fs.chunks_provided %> transf=<%= fs.chunks_transferring %><br>
89
+ <%
90
+ end
91
+ %>
92
+ </td></tr>
93
+ <%
94
+ end
95
+ %>
96
+ </table>
97
+ </body></html>
98
+ EOF
99
+ s.result binding
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,11 +1,23 @@
1
1
  #--
2
2
  # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
- # All rights reserved. See COPYING for permissions.
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/>.
4
16
  #
5
17
  # This source file is distributed as part of the
6
18
  # DistribuStream file transfer system.
7
19
  #
8
- # See http://distribustream.rubyforge.org/
20
+ # See http://distribustream.org/
9
21
  #++
10
22
 
11
23
  module PDTP
@@ -18,6 +30,13 @@ module PDTP
18
30
  attr_accessor :creation_time
19
31
  attr_accessor :verification_asked
20
32
 
33
+ #generates a transfer id based on 2 client ids, a url, and a byte range
34
+ def self.gen_transfer_id(id1,id2,url,byte_range)
35
+ a = id1<id2 ? id1 : id2
36
+ b = id1<id2 ? id2 : id1
37
+ "#{a}$#{b}$#{url}$#{byte_range}"
38
+ end
39
+
21
40
  def initialize(taker,giver,url,chunkid,byte_range,connector_receives=true)
22
41
  @taker,@giver,@url,@chunkid,@byte_range=taker,giver,url,chunkid,byte_range
23
42
 
@@ -41,13 +60,6 @@ module PDTP
41
60
  @transfer_id=Transfer::gen_transfer_id(id1,id2,@url,@byte_range)
42
61
  end
43
62
 
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
63
  def to_s
52
64
  "taker=#{@taker}, giver=#{@giver}, connector=#{@connector}, acceptor=#{@acceptor}, url=#{@url}, chunk_id=#{@chunkid} range=#{@byte_range}"
53
65
  end
@@ -1,11 +1,23 @@
1
1
  #--
2
2
  # Copyright (C) 2006-07 ClickCaster, Inc. (info@clickcaster.com)
3
- # All rights reserved. See COPYING for permissions.
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/>.
4
16
  #
5
17
  # This source file is distributed as part of the
6
18
  # DistribuStream file transfer system.
7
19
  #
8
- # See http://distribustream.rubyforge.org/
20
+ # See http://distribustream.org/
9
21
  #++
10
22
 
11
23
  module PDTP
@@ -0,0 +1,831 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE rfc SYSTEM "http://xml.resource.org/authoring/rfc2629.dtd">
3
+ <?rfc toc='yes' ?>
4
+ <rfc docName="draft-distribustream-pdtp-rfcs-01" ipr="full3978">
5
+ <front>
6
+ <title abbrev="PDTP Specification">Peer Distributed Transfer Protocol Specification</title>
7
+
8
+ <author fullname="Tony Arcieri" initials="T.A." surname="Arcieri">
9
+ <organization>ClickCaster, Inc.</organization>
10
+
11
+ <address>
12
+ <email>tony@clickcaster.com</email>
13
+ </address>
14
+ </author>
15
+
16
+ <author fullname="Ashvin Mysore" initials="A.M." surname="Mysore">
17
+ <organization>ClickCaster, Inc.</organization>
18
+
19
+ <address>
20
+ <email>ashvin@clickcaster.com</email>
21
+ </address>
22
+ </author>
23
+
24
+ <author fullname="Galen Pahlke" initials="G.P." surname="Pahlke">
25
+ <organization>ClickCaster, Inc.</organization>
26
+
27
+ <address>
28
+ <email>galen@clickcaster.com</email>
29
+ </address>
30
+ </author>
31
+
32
+ <author fullname="James Sanders" initials="J.S." surname="Sanders">
33
+ <organization>University of Colorado</organization>
34
+
35
+ <address>
36
+ <email>sanderjd@gmail.com</email>
37
+ </address>
38
+ </author>
39
+
40
+ <author fullname="Tom Stapleton" initials="T.S." surname="Stapleton">
41
+ <organization>University of Colorado</organization>
42
+
43
+ <address>
44
+ <email>tstapleton@gmail.com</email>
45
+ </address>
46
+ </author>
47
+
48
+ <date month="November" year="2007" />
49
+
50
+ <area>Internet</area>
51
+
52
+ <keyword>I-D</keyword>
53
+
54
+ <keyword>Internet-Draft</keyword>
55
+
56
+ <keyword>PDTP</keyword>
57
+
58
+ <keyword>DistribuStream</keyword>
59
+
60
+ <abstract>
61
+ <t>Peer Distributed Transfer Protocol is a high performance peer-to-peer
62
+ file distribution system that provides streaming downloads of files
63
+ originating from a central server. The files are then shared over a peer
64
+ network, allowing the aggregate bandwidth of the network to scale with
65
+ the number of clients.</t>
66
+ </abstract>
67
+ </front>
68
+
69
+ <middle>
70
+ <section title="Introduction">
71
+ <t>This document describes version 2 of PDTP, an enhancement of <xref
72
+ target="refs.PDTP">PDTP version 1</xref>. PDTP currently only allows for
73
+ operation on IPv4 networks, though support for IPv6 networks is
74
+ planned.</t>
75
+
76
+ <t>PDTP is based on an extensible set of asynchronous messages. These
77
+ messages are comprised of a type, and a sequence of key-value pairs. The
78
+ possible data types are described in Appendix A. Due to the structure of
79
+ PDTP, protocol messages can be grouped into two distinct categories:
80
+ <list style="symbols">
81
+ <t><xref target="server-to-client-messages">Server to client
82
+ messages</xref> manage the file transfer process and provide
83
+ infomation of files requested by the client.</t>
84
+
85
+ <t><xref target="client-to-server-messages">Client to server
86
+ messages</xref> handle requests for files by the client, inform the
87
+ server of files the client can provide, and report the status of
88
+ transfers.</t>
89
+
90
+ <t><xref target="client-to-client-communication">Client to client
91
+ communication</xref> makes use of the standard <xref
92
+ target="refs.HTTP">HTTP 1.1</xref> protocol</t>
93
+ </list></t>
94
+ </section>
95
+
96
+ <section title="Message Format">
97
+ <t>All <xref target="client-to-server-messages">client to server</xref>
98
+ and <xref target="server-to-client-messages">server to client</xref>
99
+ communication utilizes a lightweight form of asynchronous messaging over
100
+ TCP with <xref target="refs.JSON">JavaScript Object Notation (JSON)</xref>
101
+ providing underlying data serialization format. Messages are
102
+ length-prefix framed with a JSON message body. The IANA approved TCP
103
+ port for all PDTP client/server intercommunication is 6086.</t>
104
+
105
+ <t>Each frame consists of a 16-bit unsigned integer in network byte order
106
+ representing the length of the message body, followed by the message
107
+ body itself. Because the length prefix is 16-bit, the maximum allowed
108
+ length of the message body is 65,535 bytes, with a maximum frame size
109
+ of 65,537 bytes including the header. Messages are sent in succession
110
+ over a persistent TCP connection.</t>
111
+
112
+ <t>Message bodies consist of JSON messages in the following format:</t>
113
+
114
+ <figure>
115
+ <artwork>["type", {"arg1": "value1", "arg2": "value2", ..., "argN": "valueN"}]</artwork>
116
+ </figure>
117
+
118
+ <t>Each message is composed of an outer JSON array with two members.
119
+ The first member is a string which represents the message type. The second
120
+ member is a JSON object which contains a message-specific collection of
121
+ arguments. Unless otherwise specified, all members are represented as JSON strings.
122
+ </t>
123
+
124
+ <t>To improve the readability of the protocol on the wire, it is recommended that
125
+ CRLF be appended to the end of the JSON message. This is ignored as whitespace by
126
+ JSON parsers, but meaningful to humans who may be reading wire dumps. However, this
127
+ is not an explicit requirement of the protocol, nor should its presence be required
128
+ by any implementation.</t>
129
+ </section>
130
+
131
+ <section anchor="server-to-client-messages"
132
+ title="Server to Client Messages">
133
+ <section title="Overview">
134
+ <t>These messages are sent from the server to the client to respond to
135
+ information requests by the client and manage the file transfer
136
+ process. <list style="symbols">
137
+ <t><xref target="tellinfo">TELLINFO</xref> provides the client
138
+ with information about the object located at the specified
139
+ URL.</t>
140
+
141
+ <t><xref target="transfer">TRANSFER</xref> tells the client to
142
+ initiate a peer-to-peer data transfer.</t>
143
+
144
+ <t><xref target="tellverify">TELLVERIFY</xref> tells the client
145
+ whether the specified transfer is authorized.</t>
146
+
147
+ <t><xref target="hashverify">HASHVERIFY</xref> informs the client
148
+ whether the successful transfer had the correct file hash.</t>
149
+ </list></t>
150
+ </section>
151
+
152
+ <section anchor="tellinfo" title="TELLINFO">
153
+ <figure>
154
+ <artwork>tell_info url [size] [chunkSize] [streaming]</artwork>
155
+ </figure>
156
+
157
+ <t>The tell_info datagram is the expected response from the ask_info
158
+ datagram, and contains information that the client can use to
159
+ determine its chunk request policy and the manner in which a file is
160
+ handled. Since the server only arranges for chunks to be sent when
161
+ they are explicitly requested, a client must know how many chunks are
162
+ in a file so that it knows how many to request. In order to determine
163
+ the number of chunks in a file, the size of each chunk and the total
164
+ size of the file are sent. The number of chunks is then the 'fileSize'
165
+ divided by the 'chunkSize', rounded up to the first integer. The
166
+ 'chunkSize' could also be used to determine a policy on caching or
167
+ memory management and the 'fileSize' could be used to alleviate
168
+ complications arising from the case of incomplete final chunks, and
169
+ perhaps other things.</t>
170
+
171
+ <t>Fields:</t>
172
+
173
+ <figure>
174
+ <artwork>url: String</artwork>
175
+
176
+ <postamble>A unique file identifier. The server uses this field to
177
+ specify which file it is sending information about.</postamble>
178
+ </figure>
179
+
180
+ <figure>
181
+ <artwork>size: Integer (Optional)</artwork>
182
+
183
+ <postamble>The exact size in bytes of the file. Since the last chunk
184
+ in the file might not be completely filled, it is necessary to know
185
+ the total file size as well as the chunk size and the chunk
186
+ count.</postamble>
187
+ </figure>
188
+
189
+ <figure>
190
+ <artwork>chunkSize: Integer (Optional)</artwork>
191
+
192
+ <postamble>The size in bytes of each chunk in the file.</postamble>
193
+ </figure>
194
+
195
+ <figure>
196
+ <artwork>streaming: Boolean (Optional)</artwork>
197
+
198
+ <postamble>If true, the file is assumed to be a streaming media file
199
+ and chunks near the beginning will be sent first. If false, chunks
200
+ from all over the file will have equal priority. Default is
201
+ false.</postamble>
202
+ </figure>
203
+ </section>
204
+
205
+ <section anchor="transfer" title="TRANSFER">
206
+ <figure>
207
+ <artwork>transfer peer port method url range peer_id</artwork>
208
+ </figure>
209
+
210
+ <t>The server controls all data flowing over the network. It uses the
211
+ transfer message to initiate a chunk transfer between two peers. The
212
+ transfer message is always sent to the peer that should initiate the
213
+ connection to the other peer.</t>
214
+
215
+ <t>When a client receives a transfer message, it should connect to the
216
+ specified peer and carry out the transfer as specified in <xref
217
+ target="client-to-client-communication">Section 4</xref> and reply to
218
+ the server with a <xref target="completed">completed</xref> message
219
+ upon success.</t>
220
+
221
+ <t>Fields:</t>
222
+
223
+ <figure>
224
+ <artwork>peer: String</artwork>
225
+
226
+ <postamble>This is the network address of the peer with which the
227
+ transfer should take place.</postamble>
228
+ </figure>
229
+
230
+ <figure>
231
+ <artwork>port: Integer</artwork>
232
+
233
+ <postamble>The port on the peer to connect to.</postamble>
234
+ </figure>
235
+
236
+ <figure>
237
+ <artwork>method: Enumeration</artwork>
238
+
239
+ <postamble>The HTTP method to be used for this transfer. Possible
240
+ values are GET and PUT, with the same semantics as in the HTTP
241
+ protocol. That is, if method is GET, this client is receiving data
242
+ from a peer, and if method is PUT, this client is sending data to a
243
+ peer.</postamble>
244
+ </figure>
245
+
246
+ <figure>
247
+ <artwork>url: String</artwork>
248
+
249
+ <postamble>This is a unique file identifier for the file to
250
+ transfer.</postamble>
251
+ </figure>
252
+
253
+ <figure>
254
+ <artwork>range: Range</artwork>
255
+
256
+ <postamble>This is the byte range being transferred. This, combined
257
+ with the url, provides a unique identifier for the data to
258
+ transfer.</postamble>
259
+ </figure>
260
+
261
+ <figure>
262
+ <artwork>peer_id: Integer</artwork>
263
+
264
+ <postamble>The unique id of the peer in this transfer.</postamble>
265
+ </figure>
266
+ </section>
267
+
268
+ <section anchor="tellverify" title="TELLVERIFY">
269
+ <figure>
270
+ <artwork>tell_verify peer url range peer_id authorized</artwork>
271
+ </figure>
272
+
273
+ <t>The tell_verify datagram is sent to the client in response to an
274
+ <xref target="askverify">ask_verify</xref> message to inform it of the
275
+ authorization status of a transfer.</t>
276
+
277
+ <t>Fields:</t>
278
+
279
+ <figure>
280
+ <artwork>peer: IP Address</artwork>
281
+
282
+ <postamble>The address of the connecting peer.</postamble>
283
+ </figure>
284
+
285
+ <figure>
286
+ <artwork>url: String</artwork>
287
+
288
+ <postamble>A unique file identifier.</postamble>
289
+ </figure>
290
+
291
+ <figure>
292
+ <artwork>range: Range</artwork>
293
+
294
+ <postamble>The byte range to verify.</postamble>
295
+ </figure>
296
+
297
+ <figure>
298
+ <artwork>peer_id: String</artwork>
299
+
300
+ <postamble>The unique identifier of the peer.</postamble>
301
+ </figure>
302
+
303
+ <figure>
304
+ <artwork>authorized: Boolean</artwork>
305
+
306
+ <postamble>A boolean value specifying whether or not the transfer is
307
+ authorized.</postamble>
308
+ </figure>
309
+ </section>
310
+
311
+ <section anchor="hashverify" title="HASHVERIFY">
312
+ <figure>
313
+ <artwork>hash_verify url range hash_ok</artwork>
314
+ </figure>
315
+
316
+ <t>The hash_verify message is sent to a client after a completed
317
+ message with a hash has been received. The value of hash_ok denotes
318
+ whether or not the hash sent in the completed message matches the
319
+ expected hash of the chunk containing the specified range.</t>
320
+
321
+ <t>Fields:</t>
322
+
323
+ <figure>
324
+ <artwork>url: String</artwork>
325
+
326
+ <postamble>The url of the file being transferred.</postamble>
327
+ </figure>
328
+
329
+ <figure>
330
+ <artwork>range: Range</artwork>
331
+
332
+ <postamble>The byte range of the file, which this message refers
333
+ to.</postamble>
334
+ </figure>
335
+
336
+ <figure>
337
+ <artwork>hash_ok: Boolean</artwork>
338
+
339
+ <postamble>If true, the has sent in the completed message matched
340
+ the expected hash of the byte range it referred to.</postamble>
341
+ </figure>
342
+ </section>
343
+
344
+ <section anchor="protocolerror" title="PROTOCOLERROR">
345
+ <figure>
346
+ <artwork>protocol_error message</artwork>
347
+ </figure>
348
+
349
+ <t>The protocol_error message is sent to a client whenever a protocol
350
+ error has occurred. The message field is meant to be read by a human
351
+ to determine what went wrong. In most cases, the error is due to a
352
+ programming error and is fatal. One notable exception to this is the
353
+ case when a client generates a Peer Id that is not unique.</t>
354
+
355
+ <t>Fields:</t>
356
+
357
+ <figure>
358
+ <artwork>message: String</artwork>
359
+
360
+ <postamble>An error message. This error message is not meant to be
361
+ parsed programmatically, but rather to be logged and read as an aid
362
+ to debugging.</postamble>
363
+ </figure>
364
+ </section>
365
+ </section>
366
+
367
+ <section anchor="client-to-server-messages"
368
+ title="Client to Server Messages">
369
+ <section title="Overview">
370
+ <t>These messages are sent from the client to the server to request
371
+ files, inform the server of completed transfers and handle files the
372
+ client can provide to the network. <list style="symbols">
373
+ <t><xref target="register">REGISTER</xref> informs the server
374
+ that the client exists and provides the server with information
375
+ about itself.</t>
376
+
377
+ <t><xref target="request">REQUEST</xref> informs the server that
378
+ the client wants the specified object range.</t>
379
+
380
+ <t><xref target="request">UNREQUEST</xref> informs the server that
381
+ the client no longer needs the specified object range.</t>
382
+
383
+ <t><xref target="provide">PROVIDE</xref> informs the server that
384
+ the client has the specified object range and can provide it to
385
+ peers.</t>
386
+
387
+ <t><xref target="provide">UNPROVIDE</xref> informs the server that
388
+ the client no longer has the specified object range, and therefore
389
+ cannot provide it.</t>
390
+
391
+ <t><xref target="askinfo">ASKINFO</xref> requests information from
392
+ the server about the specified URL.</t>
393
+
394
+ <t><xref target="askverify">ASKVERIFY</xref> asks the server
395
+ whether the specified transfer is authorized.</t>
396
+
397
+ <t><xref target="completed">COMPLETED</xref> informs the server
398
+ that a transfer has successfully completed.</t>
399
+ </list></t>
400
+ </section>
401
+
402
+ <section anchor="register" title="REGISTER">
403
+ <figure>
404
+ <artwork>register client_id listen_port</artwork>
405
+ </figure>
406
+
407
+ <t>The register message is the first message a client sends to the
408
+ server. The client must send this message to alert the server of its
409
+ presence so that it may be included in the server's actions.</t>
410
+
411
+ <t>Fields:</t>
412
+
413
+ <figure>
414
+ <artwork>client_id: String</artwork>
415
+
416
+ <postamble>A unique identifier, which the client generates. The
417
+ server will identify this client on the network based on this
418
+ identifier. The identifier must be a string less than 4 KB in
419
+ length. It is the client's responsibility to generate an identifier
420
+ that is unique. The server should respond with a <xref
421
+ target="protocolerror">protocol_error</xref> message if the
422
+ identifier is too long or not unique.</postamble>
423
+ </figure>
424
+
425
+ <figure>
426
+ <artwork>listen_port: Integer</artwork>
427
+
428
+ <postamble>The port on which the client will listen for incoming
429
+ connections from other peers. The server will pass this information
430
+ along to other clients wishing to connect to this client for peer to
431
+ peer chunk transfers.</postamble>
432
+ </figure>
433
+ </section>
434
+
435
+ <section anchor="request" title="REQUEST and UNREQUEST">
436
+ <figure>
437
+ <artwork>request url [range] unrequest url [range]</artwork>
438
+ </figure>
439
+
440
+ <t>The request and unrequest messages are used by the client to
441
+ indicate what data it needs to receive. A request datagram indicates
442
+ that the client needs the specified object bytes; an unrequest
443
+ datagram indicates that the client no longer needs the specified
444
+ bytes. The completed and provide messages may also be used to cancel a
445
+ request, though they carry additional semantics.</t>
446
+
447
+ <t>If the range of a request or unrequest message isn't specified, it
448
+ is assumed to include all bytes in the file.</t>
449
+
450
+ <t>The server is expected to continuously arrange for the data in the
451
+ client's request set to be delivered to the client through peer to
452
+ peer transfer channels. A request set is informally the set of chunks
453
+ that a client wants. Formally, we may say that a given unique chunk C
454
+ with the URL L and the id K is in a client's request set if and only
455
+ if: <list style="symbols">
456
+ <t>The client has sent at least one request message with a URL
457
+ equivalent to L and a byte range containing chunk K.</t>
458
+
459
+ <t>Since the last such message was sent, the client has not sent
460
+ an unrequest message with a URL equivalent to L and a byte range
461
+ containing chunk K,</t>
462
+
463
+ <t>...nor has it sent a completed message with a URL equivalent to
464
+ L and a byte range containing chunk K,</t>
465
+
466
+ <t>...nor has it sent a provide message with a URL equivalent to L
467
+ and a byte range containing chunk K.</t>
468
+ </list></t>
469
+
470
+ <t>In short, requests are standing and additive; unrequests are
471
+ transient and subtractive. The server is expected to handle any
472
+ possible combination of requests and unrequests that clients can send.
473
+ (For example, a client may request a URL in its entirety, and then
474
+ later unrequest certain parts of the URL. This is useful if, say, a
475
+ client needs to complete a partial download, repair a damaged file, or
476
+ optimize its network usage in response to user actions.)</t>
477
+
478
+ <t>Fields:</t>
479
+
480
+ <figure>
481
+ <artwork>url: String</artwork>
482
+
483
+ <postamble>The object being requested. The server may discard
484
+ requests for URLs it does not understand.</postamble>
485
+ </figure>
486
+
487
+ <figure>
488
+ <artwork>range: Range (Optional)</artwork>
489
+
490
+ <postamble>The range of bytes being requested, inclusive. If
491
+ unspecified, it is taken to be the complete range of bytes in the
492
+ file.</postamble>
493
+ </figure>
494
+ </section>
495
+
496
+ <section anchor="provide" title="PROVIDE and UNPROVIDE">
497
+ <figure>
498
+ <artwork>provide url [range] unprovide url [range]</artwork>
499
+ </figure>
500
+
501
+ <t>The provide and unprovide datagrams are used to tell the server
502
+ which chunks of a file it is able to provide to peers. Each client in
503
+ the system can have a cache of file chunks that it has already
504
+ downloaded and depending on the client's individual capabilities, this
505
+ cache may or may not be empty on startup. If a client has data in a
506
+ cache on startup, the provide message can be used to inform the
507
+ server. If the cache is empty on startup, the provide message is never
508
+ needed because the server is expected to keep track of each chunk that
509
+ has been transferred. On the other hand, if a client evicts one or
510
+ more chunks from its cache, it should immediately send an unprovide
511
+ message. Although there is no firm requirement on a client to send
512
+ appropriate unprovide datagrams, it is in the client's best interest
513
+ to do so, as it could lose standing in the network if it were asked to
514
+ send a chunk it did not have.</t>
515
+
516
+ <t>A client can send as many provide messages as necessary to inform
517
+ the server of its entire chunk cache. These messages should be
518
+ interpreted by the server additively. That is, if a client first sends
519
+ a message specifying that it provides byte range A to B and then
520
+ another specifying that it provides byte range C to D, the server
521
+ should conclude that it has byte range A to B and byte range C to D.
522
+ Furthermore, a client can send provide and unprovide messages for
523
+ multiple files, as specified by the url field.</t>
524
+
525
+ <t>If the range in a provide or unprovide message isn't specified, it
526
+ is taken to include the entire range of bytes in the file specified by
527
+ the url field.</t>
528
+
529
+ <t>Fields:</t>
530
+
531
+ <figure>
532
+ <artwork>url: String</artwork>
533
+
534
+ <postamble>A unique file identifier. The client uses this field to
535
+ specify a file in its cache.</postamble>
536
+ </figure>
537
+
538
+ <figure>
539
+ <artwork>range: Range (Optional)</artwork>
540
+
541
+ <postamble>The range of relevant bytes, inclusive. If unspecified,
542
+ it is taken to be the complete range of chunks in the
543
+ file.</postamble>
544
+ </figure>
545
+ </section>
546
+
547
+ <section anchor="askinfo" title="ASKINFO">
548
+ <figure>
549
+ <artwork>ask_info url</artwork>
550
+ </figure>
551
+
552
+ <t>The ask_info datagram is sent to the server when a client wants
553
+ information about a file. Specifically, the client needs information
554
+ about the file type, the file size, the number of chunks, and the size
555
+ of each chunk in order to successfully receive a file. This
556
+ information is used to determine when a file is finished transferring
557
+ and how to handle a file, among other things.</t>
558
+
559
+ <t>It is expected that the server will always respond to an ask_info
560
+ datagram with a <xref target="tellinfo">tell_info</xref> datagram.</t>
561
+
562
+ <t>Fields:</t>
563
+
564
+ <figure>
565
+ <artwork>url: String</artwork>
566
+
567
+ <postamble>A unique file identifier. The client uses this field to
568
+ specify which file it would like information about.</postamble>
569
+ </figure>
570
+ </section>
571
+
572
+ <section anchor="askverify" title="ASKVERIFY">
573
+ <figure>
574
+ <artwork>ask_verify peer url range peer_id</artwork>
575
+ </figure>
576
+
577
+ <t>The ask_verify datagram is sent to the server when a client wants
578
+ to know whether a transfer is authorized. This is sent upon receipt of
579
+ a put or get from a peer.</t>
580
+
581
+ <t>It is expected that the server will always respond to an ask_verify
582
+ datagram with a <xref target="tellverify">tell_verify</xref>
583
+ datagram.</t>
584
+
585
+ <t>Fields:</t>
586
+
587
+ <figure>
588
+ <artwork>peer: String</artwork>
589
+
590
+ <postamble>The network address of the connecting peer.</postamble>
591
+ </figure>
592
+
593
+ <figure>
594
+ <artwork>url: String</artwork>
595
+
596
+ <postamble>A unique file identifier. The client uses this field to
597
+ specify which file it would like information about.</postamble>
598
+ </figure>
599
+
600
+ <figure>
601
+ <artwork>range: Range</artwork>
602
+
603
+ <postamble>The range of bytes in the file referred to by the url for
604
+ which we are asking verification.</postamble>
605
+ </figure>
606
+
607
+ <figure>
608
+ <artwork>peer_id: String</artwork>
609
+
610
+ <postamble>The unique identifier of the peer.</postamble>
611
+ </figure>
612
+ </section>
613
+
614
+ <section anchor="completed" title="COMPLETED">
615
+ <figure>
616
+ <artwork>completed peer url range peer_id [hash]</artwork>
617
+ </figure>
618
+
619
+ <t>The completed message is used by the client to indicate that a
620
+ transfer has completed in either success or failure. Upon success, a
621
+ completed message will include a hash of the chunk that it has
622
+ received. The lack of a hash field denotes transfer failure. The
623
+ server may use this information to inform its network optimization, so
624
+ the appropriate use of completed messages is highly recommended.
625
+ (Specifically, it is likely that the server will initiate another
626
+ transfer after it has been informed that one has completed.)</t>
627
+
628
+ <t>Fields:</t>
629
+
630
+ <figure>
631
+ <artwork>peer: String</artwork>
632
+
633
+ <postamble>The network address of the peer associated with this
634
+ transfer.</postamble>
635
+ </figure>
636
+
637
+ <figure>
638
+ <artwork>url: String</artwork>
639
+
640
+ <postamble>The url of the transferred chunk.</postamble>
641
+ </figure>
642
+
643
+ <figure>
644
+ <artwork>range: Range</artwork>
645
+
646
+ <postamble>The byte range of the completed transfer.</postamble>
647
+ </figure>
648
+
649
+ <figure>
650
+ <artwork>peer_id: String</artwork>
651
+
652
+ <postamble>A unique identifier of the peer associated with the
653
+ transfer.</postamble>
654
+ </figure>
655
+
656
+ <figure>
657
+ <artwork>hash: String (Optional)</artwork>
658
+
659
+ <postamble>A hash of the transferred chunk. Denotes failure if
660
+ blank.</postamble>
661
+ </figure>
662
+ </section>
663
+ </section>
664
+
665
+ <section anchor="client-to-client-communication"
666
+ title="Client to Client Communication">
667
+ <section title="Overview">
668
+ <t>All client to client communication is done using the <xref
669
+ target="refs.HTTP">HTTP 1.1</xref> protocol. Each client is both an
670
+ HTTP client and server. During a transfer, the connecting peer for
671
+ that particular transfer acts as the client and the listening peer
672
+ acts as the server. While full HTTP functionality may be implemented
673
+ and implementation-specifically desirable, only the subset of the HTTP
674
+ protocol that includes the GET and PUT requests and the full range of
675
+ responses is strictly required for the PDTP protocol.</t>
676
+
677
+ <t>The listening client is truly an HTTP server and the connecting
678
+ client is truly an HTTP client. By this we mean simply that not only
679
+ the syntax but also the semantics of the GET and PUT requests and any
680
+ responses received are identical to that of the HTTP protocol.</t>
681
+
682
+ <t>A connecting peer will include the following information in the
683
+ request sent to a listening peer:</t>
684
+
685
+ <t><list style="symbols">
686
+ <t>A compliant <xref target="refs.HTTP">HTTP</xref> Request-Line
687
+ for either a GET or PUT request. The method to use should be taken
688
+ from the method parameter of the <xref
689
+ target="transfer">transfer</xref> message received from the
690
+ server. Similarly, the Request-URI portion of the Request-Line is
691
+ taken from the url field from the server.</t>
692
+
693
+ <t>A Host header, identifying the host in the url specified by the
694
+ server. This host should be recognized as a virtual host on the
695
+ listening peer. It is important to note that this field does not
696
+ necessarily represent any identifier associated with the listening
697
+ peer, but rather the host in the url field from the server.</t>
698
+
699
+ <t>A Range header, identifying the byte range to be transferred,
700
+ taken from the range field in the transfer message.</t>
701
+
702
+ <t>An X-PDTP-Peer-Id header. The value of this header is the Peer
703
+ Id of the connecting client. That is, it is the Peer Id of the
704
+ client sending this request. It is important to note that this is
705
+ not the peer_id field from the transfer message, which represents
706
+ the Peer Id of the listening peer and is necessary when notifying
707
+ the server of transfer completion.</t>
708
+
709
+ <t>If the method is PUT, a body containing the data is also
710
+ sent</t>
711
+ </list></t>
712
+
713
+ <t>Upon receiving a request from a connecting peer, a listening peer
714
+ processes the request in an appropriate manner and sends an
715
+ appropriate response. The listening client may choose to ask the
716
+ server for verification of this transfer using the <xref
717
+ target="askverify">ask_verify</xref> message. If verification fails, a
718
+ 403 Forbidden response should be sent. Similarly, if the file cannot
719
+ be found, or the range is unsatisfiable, the 404 File Not Found or 416
720
+ Requested Range Unsatisfiable responses should be sent. Upon success,
721
+ either 206 Partial Content, 200 OK, or 201 Created should be sent,
722
+ depending on the situation.</t>
723
+ </section>
724
+ </section>
725
+ </middle>
726
+
727
+ <back>
728
+ <references>
729
+ <reference anchor="refs.PDTP"
730
+ target="http://pdtp.org/specification/draft-arcieri-peer-distributed-transfer-protocol.html">
731
+ <front>
732
+ <title>Peer Distributed Transfer Protocol</title>
733
+
734
+ <author fullname="Anthony Arcieri" initials="A.A." surname="Arcieri">
735
+ <organization>ClickCaster.com</organization>
736
+ </author>
737
+
738
+ <date day="30" month="November" year="2005" />
739
+ </front>
740
+ </reference>
741
+
742
+ <reference anchor="refs.HTTP">
743
+ <front>
744
+ <title>Hypertext Transfer Protocol - HTTP/1.1</title>
745
+
746
+ <author fullname="" initials="R.F." surname="Fielding">
747
+ <organization>UC Irvine</organization>
748
+ </author>
749
+
750
+ <author fullname="" initials="J.G." surname="Gettys">
751
+ <organization>Compaq/W3C</organization>
752
+ </author>
753
+
754
+ <author fullname="" initials="J.M." surname="Mogul">
755
+ <organization>Compaq</organization>
756
+ </author>
757
+
758
+ <author fullname="" initials="H.F." surname="Frystyk">
759
+ <organization>W3C/MIT</organization>
760
+ </author>
761
+
762
+ <author fullname="" initials="L.M." surname="Masinter">
763
+ <organization>Xerox</organization>
764
+ </author>
765
+
766
+ <author fullname="" initials="P.L." surname="Fielding">
767
+ <organization>Microsoft</organization>
768
+ </author>
769
+
770
+ <author fullname="" initials="T.B." surname="Berners-Lee">
771
+ <organization>W3C/MIT</organization>
772
+ </author>
773
+
774
+ <date month="June" year="1999" />
775
+ </front>
776
+
777
+ <seriesInfo name="RFC" value="2616" />
778
+ </reference>
779
+
780
+ <reference anchor="refs.JSON">
781
+ <front>
782
+ <title>The application/json Media Type for JavaScript Object
783
+ Notation (JSON)</title>
784
+
785
+ <author initials="D.C." surname="Crockford">
786
+ <organization>JSON.org</organization>
787
+ </author>
788
+
789
+ <date month="July" year="2006" />
790
+ </front>
791
+
792
+ <seriesInfo name="RFC" value="4627" />
793
+ </reference>
794
+ </references>
795
+
796
+ <section title="Glossary">
797
+ <t><list style="symbols">
798
+ <t>Client: a system that accesses a service on a remote computer via
799
+ a network, equivalent to a 'peer'.</t>
800
+
801
+ <t>Connecting peer: The peer that initiates the connection over
802
+ which a transfer takes place.</t>
803
+
804
+ <t>Enumeration: a set of acceptable values.</t>
805
+
806
+ <t>Integer: a unsigned integer field.</t>
807
+
808
+ <t>Listening peer: The peer that accepts the connection over which a
809
+ transfer takes place.</t>
810
+
811
+ <t>Peer: a system that accesses a service on a remote computer via a
812
+ network, equivalent to a 'client'.</t>
813
+
814
+ <t>Peer Id: a unique identifier generated by a client and sent to
815
+ the server, uniquely identifying the client on the network.</t>
816
+
817
+ <t>Range: a representation of a sequence of indices implemented as a
818
+ tuple containing Integer values for minimum and maximum values. All
819
+ ranges referred to in this document are inclusive.</t>
820
+
821
+ <t>Request Set: the set of all chunks that a client has requested
822
+ and not subsequently unrequested.</t>
823
+
824
+ <t>Server: the system that manages the network and distribution of
825
+ information among clients.</t>
826
+
827
+ <t>String: a string of ASCII characters.</t>
828
+ </list></t>
829
+ </section>
830
+ </back>
831
+ </rfc>