iPXE
peerdist.c
Go to the documentation of this file.
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 FILE_SECBOOT ( PERMITTED );
26 
27 #include <stdio.h>
28 #include <ipxe/http.h>
29 #include <ipxe/settings.h>
30 #include <ipxe/peermux.h>
31 
32 /** @file
33  *
34  * Peer Content Caching and Retrieval (PeerDist) protocol
35  *
36  * This is quite possibly the ugliest protocol I have ever had the
37  * misfortune to encounter, and I've encountered multicast TFTP.
38  */
39 
40 /** PeerDist is globally enabled */
41 static long peerdist_enabled = 1;
42 
43 /**
44  * Check whether or not to support PeerDist encoding for this request
45  *
46  * @v http HTTP transaction
47  * @ret supported PeerDist encoding is supported for this request
48  */
49 static int http_peerdist_supported ( struct http_transaction *http ) {
50 
51  /* Allow PeerDist to be globally enabled/disabled */
52  if ( ! peerdist_enabled )
53  return 0;
54 
55  /* Support PeerDist encoding only if we can directly access an
56  * underlying data transfer buffer. Direct access is required
57  * in order to support decryption of data received via the
58  * retrieval protocol (which provides the AES initialisation
59  * vector only after all of the encrypted data has been
60  * received).
61  *
62  * This test simultaneously ensures that we do not attempt to
63  * use PeerDist encoding on a request which is itself a
64  * PeerDist individual block download, since the individual
65  * block downloads do not themselves provide direct access to
66  * an underlying data transfer buffer.
67  */
68  return ( xfer_buffer ( &http->xfer ) != NULL );
69 }
70 
71 /**
72  * Format HTTP "X-P2P-PeerDist" header
73  *
74  * @v http HTTP transaction
75  * @v buf Buffer
76  * @v len Length of buffer
77  * @ret len Length of header value, or negative error
78  */
79 static int http_format_p2p_peerdist ( struct http_transaction *http,
80  char *buf, size_t len ) {
81  int supported = http_peerdist_supported ( http );
82  int missing;
83 
84  /* PeerDist wants us to inform the server whenever we make a
85  * request for data that was missing from local peers
86  * (presumably for statistical purposes only). We use the
87  * heuristic of assuming that the combination of "this request
88  * may not itself use PeerDist content encoding" and "this is
89  * a range request" probably indicates that we are making a
90  * PeerDist block raw range request for missing data.
91  */
92  missing = ( http->request.range.len && ( ! supported ) );
93 
94  /* Omit header if PeerDist encoding is not supported and we
95  * are not reporting a missing data request.
96  */
97  if ( ! ( supported || missing ) )
98  return 0;
99 
100  /* Construct header */
101  return snprintf ( buf, len, "Version=1.1%s",
102  ( missing ? ", MissingDataRequest=true" : "" ) );
103 }
104 
105 /** HTTP "X-P2P-PeerDist" header */
106 struct http_request_header http_request_p2p_peerdist __http_request_header = {
107  .name = "X-P2P-PeerDist",
108  .format = http_format_p2p_peerdist,
109 };
110 
111 /**
112  * Format HTTP "X-P2P-PeerDistEx" header
113  *
114  * @v http HTTP transaction
115  * @v buf Buffer
116  * @v len Length of buffer
117  * @ret len Length of header value, or negative error
118  */
120  char *buf, size_t len ) {
121  int supported = http_peerdist_supported ( http );
122 
123  /* Omit header if PeerDist encoding is not supported */
124  if ( ! supported )
125  return 0;
126 
127  /* Construct header */
128  return snprintf ( buf, len, ( "MinContentInformation=1.0, "
129  "MaxContentInformation=2.0" ) );
130 }
131 
132 /** HTTP "X-P2P-PeerDist" header */
133 struct http_request_header http_request_p2p_peerdistex __http_request_header = {
134  .name = "X-P2P-PeerDistEx",
135  .format = http_format_p2p_peerdistex,
136 };
137 
138 /**
139  * Initialise PeerDist content encoding
140  *
141  * @v http HTTP transaction
142  * @ret rc Return status code
143  */
144 static int http_peerdist_init ( struct http_transaction *http ) {
145 
146  return peermux_filter ( &http->content, &http->transfer, http->uri );
147 }
148 
149 /** PeerDist HTTP content encoding */
150 struct http_content_encoding peerdist_encoding __http_content_encoding = {
151  .name = "peerdist",
152  .supported = http_peerdist_supported,
153  .init = http_peerdist_init,
154 };
155 
156 /** PeerDist enabled setting */
157 const struct setting peerdist_setting __setting ( SETTING_MISC, peerdist ) = {
158  .name = "peerdist",
159  .description = "PeerDist enabled",
160  .type = &setting_type_int8,
161 };
162 
163 /**
164  * Apply PeerDist settings
165  *
166  * @ret rc Return status code
167  */
168 static int apply_peerdist_settings ( void ) {
169 
170  /* Fetch global PeerDist enabled setting */
171  if ( fetch_int_setting ( NULL, &peerdist_setting,
172  &peerdist_enabled ) < 0 ) {
173  peerdist_enabled = 1;
174  }
175  DBGC ( &peerdist_enabled, "PEERDIST is %s\n",
176  ( peerdist_enabled ? "enabled" : "disabled" ) );
177 
178  return 0;
179 }
180 
181 /** PeerDist settings applicator */
182 struct settings_applicator peerdist_applicator __settings_applicator = {
184 };
struct interface xfer
Data transfer interface.
Definition: http.h:420
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int apply_peerdist_settings(void)
Apply PeerDist settings.
Definition: peerdist.c:168
static int http_format_p2p_peerdist(struct http_transaction *http, char *buf, size_t len)
Format HTTP "X-P2P-PeerDist" header.
Definition: peerdist.c:79
int peermux_filter(struct interface *xfer, struct interface *info, struct uri *uri)
Add PeerDist content-encoding filter.
Definition: peermux.c:413
A data transfer buffer.
Definition: xferbuf.h:19
const char * name
Header name (e.g.
Definition: http.h:229
#define DBGC(...)
Definition: compiler.h:505
struct uri * uri
Request URI.
Definition: http.h:435
struct http_request_header http_request_p2p_peerdist __http_request_header
HTTP "X-P2P-PeerDist" header.
Definition: peerdist.c:106
A settings applicator.
Definition: settings.h:252
static long peerdist_enabled
PeerDist is globally enabled.
Definition: peerdist.c:41
#define SETTING_MISC
Miscellaneous settings.
Definition: settings.h:81
An HTTP request header.
Definition: http.h:227
int fetch_int_setting(struct settings *settings, const struct setting *setting, long *value)
Fetch value of signed integer setting.
Definition: settings.c:1024
An HTTP content encoding.
Definition: http.h:487
struct http_request_range range
Range descriptor.
Definition: http.h:219
struct http_request request
Request.
Definition: http.h:437
const char * name
Name.
Definition: settings.h:29
An HTTP transaction.
Definition: http.h:416
Hyper Text Transport Protocol.
Peer Content Caching and Retrieval (PeerDist) protocol multiplexer.
ring len
Length.
Definition: dwmac.h:231
const char * name
Name.
Definition: http.h:489
Configuration settings.
struct interface content
Content-decoded interface.
Definition: http.h:422
struct interface transfer
Transfer-decoded interface.
Definition: http.h:424
FILE_SECBOOT(PERMITTED)
A setting.
Definition: settings.h:24
size_t len
Range length, or zero for no range request.
Definition: http.h:140
static int http_format_p2p_peerdistex(struct http_transaction *http, char *buf, size_t len)
Format HTTP "X-P2P-PeerDistEx" header.
Definition: peerdist.c:119
static int http_peerdist_init(struct http_transaction *http)
Initialise PeerDist content encoding.
Definition: peerdist.c:144
struct http_content_encoding peerdist_encoding __http_content_encoding
PeerDist HTTP content encoding.
Definition: peerdist.c:150
int(* apply)(void)
Apply updated settings.
Definition: settings.h:257
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383
static int http_peerdist_supported(struct http_transaction *http)
Check whether or not to support PeerDist encoding for this request.
Definition: peerdist.c:49
uint16_t supported
Bitmask of supported option values.
Definition: ena.h:12
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
struct settings_applicator peerdist_applicator __settings_applicator
PeerDist settings applicator.
Definition: peerdist.c:182
const struct setting peerdist_setting __setting(SETTING_MISC, peerdist)
PeerDist enabled setting.