These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / net / peerdist.c
1 /*
2  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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
17  * 02110-1301, USA.
18  *
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.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdio.h>
27 #include <ipxe/http.h>
28 #include <ipxe/peermux.h>
29
30 /** @file
31  *
32  * Peer Content Caching and Retrieval (PeerDist) protocol
33  *
34  * This is quite possibly the ugliest protocol I have ever had the
35  * misfortune to encounter, and I've encountered multicast TFTP.
36  */
37
38 /**
39  * Check whether or not to support PeerDist encoding for this request
40  *
41  * @v http              HTTP transaction
42  * @ret supported       PeerDist encoding is supported for this request
43  */
44 static int http_peerdist_supported ( struct http_transaction *http ) {
45
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
51          * received).
52          *
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.
58          */
59         return ( xfer_buffer ( &http->xfer ) != NULL );
60 }
61
62 /**
63  * Format HTTP "X-P2P-PeerDist" header
64  *
65  * @v http              HTTP transaction
66  * @v buf               Buffer
67  * @v len               Length of buffer
68  * @ret len             Length of header value, or negative error
69  */
70 static int http_format_p2p_peerdist ( struct http_transaction *http,
71                                       char *buf, size_t len ) {
72         int supported = http_peerdist_supported ( http );
73         int missing;
74
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.
82          */
83         missing = ( http->request.range.len && ( ! supported ) );
84
85         /* Omit header if PeerDist encoding is not supported and we
86          * are not reporting a missing data request.
87          */
88         if ( ! ( supported || missing ) )
89                 return 0;
90
91         /* Construct header */
92         return snprintf ( buf, len, "Version=1.1%s",
93                           ( missing ? ", MissingDataRequest=true" : "" ) );
94 }
95
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,
100 };
101
102 /**
103  * Format HTTP "X-P2P-PeerDistEx" header
104  *
105  * @v http              HTTP transaction
106  * @v buf               Buffer
107  * @v len               Length of buffer
108  * @ret len             Length of header value, or negative error
109  */
110 static int http_format_p2p_peerdistex ( struct http_transaction *http,
111                                         char *buf, size_t len ) {
112         int supported = http_peerdist_supported ( http );
113
114         /* Omit header if PeerDist encoding is not supported */
115         if ( ! supported )
116                 return 0;
117
118         /* Construct header */
119         return snprintf ( buf, len, ( "MinContentInformation=1.0, "
120                                       "MaxContentInformation=2.0" ) );
121 }
122
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,
127 };
128
129 /**
130  * Initialise PeerDist content encoding
131  *
132  * @v http              HTTP transaction
133  * @ret rc              Return status code
134  */
135 static int http_peerdist_init ( struct http_transaction *http ) {
136
137         return peermux_filter ( &http->content, &http->transfer, http->uri );
138 }
139
140 /** PeerDist HTTP content encoding */
141 struct http_content_encoding peerdist_encoding __http_content_encoding = {
142         .name = "peerdist",
143         .supported = http_peerdist_supported,
144         .init = http_peerdist_init,
145 };