2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
27 #include <ipxe/http.h>
28 #include <ipxe/peermux.h>
32 * Peer Content Caching and Retrieval (PeerDist) protocol
34 * This is quite possibly the ugliest protocol I have ever had the
35 * misfortune to encounter, and I've encountered multicast TFTP.
39 * Check whether or not to support PeerDist encoding for this request
41 * @v http HTTP transaction
42 * @ret supported PeerDist encoding is supported for this request
44 static int http_peerdist_supported ( struct http_transaction *http ) {
46 /* Support PeerDist encoding only if we can directly access an
47 * underlying data transfer buffer. Direct access is required
48 * in order to support decryption of data received via the
49 * retrieval protocol (which provides the AES initialisation
50 * vector only after all of the encrypted data has been
53 * This test simultaneously ensures that we do not attempt to
54 * use PeerDist encoding on a request which is itself a
55 * PeerDist individual block download, since the individual
56 * block downloads do not themselves provide direct access to
57 * an underlying data transfer buffer.
59 return ( xfer_buffer ( &http->xfer ) != NULL );
63 * Format HTTP "X-P2P-PeerDist" header
65 * @v http HTTP transaction
67 * @v len Length of buffer
68 * @ret len Length of header value, or negative error
70 static int http_format_p2p_peerdist ( struct http_transaction *http,
71 char *buf, size_t len ) {
72 int supported = http_peerdist_supported ( http );
75 /* PeerDist wants us to inform the server whenever we make a
76 * request for data that was missing from local peers
77 * (presumably for statistical purposes only). We use the
78 * heuristic of assuming that the combination of "this request
79 * may not itself use PeerDist content encoding" and "this is
80 * a range request" probably indicates that we are making a
81 * PeerDist block raw range request for missing data.
83 missing = ( http->request.range.len && ( ! supported ) );
85 /* Omit header if PeerDist encoding is not supported and we
86 * are not reporting a missing data request.
88 if ( ! ( supported || missing ) )
91 /* Construct header */
92 return snprintf ( buf, len, "Version=1.1%s",
93 ( missing ? ", MissingDataRequest=true" : "" ) );
96 /** HTTP "X-P2P-PeerDist" header */
97 struct http_request_header http_request_p2p_peerdist __http_request_header = {
98 .name = "X-P2P-PeerDist",
99 .format = http_format_p2p_peerdist,
103 * Format HTTP "X-P2P-PeerDistEx" header
105 * @v http HTTP transaction
107 * @v len Length of buffer
108 * @ret len Length of header value, or negative error
110 static int http_format_p2p_peerdistex ( struct http_transaction *http,
111 char *buf, size_t len ) {
112 int supported = http_peerdist_supported ( http );
114 /* Omit header if PeerDist encoding is not supported */
118 /* Construct header */
119 return snprintf ( buf, len, ( "MinContentInformation=1.0, "
120 "MaxContentInformation=2.0" ) );
123 /** HTTP "X-P2P-PeerDist" header */
124 struct http_request_header http_request_p2p_peerdistex __http_request_header = {
125 .name = "X-P2P-PeerDistEx",
126 .format = http_format_p2p_peerdistex,
130 * Initialise PeerDist content encoding
132 * @v http HTTP transaction
133 * @ret rc Return status code
135 static int http_peerdist_init ( struct http_transaction *http ) {
137 return peermux_filter ( &http->content, &http->transfer, http->uri );
140 /** PeerDist HTTP content encoding */
141 struct http_content_encoding peerdist_encoding __http_content_encoding = {
143 .supported = http_peerdist_supported,
144 .init = http_peerdist_init,