You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

peerdist.c 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdio.h>
  25. #include <ipxe/http.h>
  26. #include <ipxe/peermux.h>
  27. /** @file
  28. *
  29. * Peer Content Caching and Retrieval (PeerDist) protocol
  30. *
  31. * This is quite possibly the ugliest protocol I have ever had the
  32. * misfortune to encounter, and I've encountered multicast TFTP.
  33. */
  34. /**
  35. * Check whether or not to support PeerDist encoding for this request
  36. *
  37. * @v http HTTP transaction
  38. * @ret supported PeerDist encoding is supported for this request
  39. */
  40. static int http_peerdist_supported ( struct http_transaction *http ) {
  41. /* Support PeerDist encoding only if we can directly access an
  42. * underlying data transfer buffer. Direct access is required
  43. * in order to support decryption of data received via the
  44. * retrieval protocol (which provides the AES initialisation
  45. * vector only after all of the encrypted data has been
  46. * received).
  47. *
  48. * This test simultaneously ensures that we do not attempt to
  49. * use PeerDist encoding on a request which is itself a
  50. * PeerDist individual block download, since the individual
  51. * block downloads do not themselves provide direct access to
  52. * an underlying data transfer buffer.
  53. */
  54. return ( xfer_buffer ( &http->xfer ) != NULL );
  55. }
  56. /**
  57. * Format HTTP "X-P2P-PeerDist" header
  58. *
  59. * @v http HTTP transaction
  60. * @v buf Buffer
  61. * @v len Length of buffer
  62. * @ret len Length of header value, or negative error
  63. */
  64. static int http_format_p2p_peerdist ( struct http_transaction *http,
  65. char *buf, size_t len ) {
  66. int supported = http_peerdist_supported ( http );
  67. int missing;
  68. /* PeerDist wants us to inform the server whenever we make a
  69. * request for data that was missing from local peers
  70. * (presumably for statistical purposes only). We use the
  71. * heuristic of assuming that the combination of "this request
  72. * may not itself use PeerDist content encoding" and "this is
  73. * a range request" probably indicates that we are making a
  74. * PeerDist block raw range request for missing data.
  75. */
  76. missing = ( http->request.range.len && ( ! supported ) );
  77. /* Omit header if PeerDist encoding is not supported and we
  78. * are not reporting a missing data request.
  79. */
  80. if ( ! ( supported || missing ) )
  81. return 0;
  82. /* Construct header */
  83. return snprintf ( buf, len, "Version=1.1%s",
  84. ( missing ? ", MissingDataRequest=true" : "" ) );
  85. }
  86. /** HTTP "X-P2P-PeerDist" header */
  87. struct http_request_header http_request_p2p_peerdist __http_request_header = {
  88. .name = "X-P2P-PeerDist",
  89. .format = http_format_p2p_peerdist,
  90. };
  91. /**
  92. * Format HTTP "X-P2P-PeerDistEx" header
  93. *
  94. * @v http HTTP transaction
  95. * @v buf Buffer
  96. * @v len Length of buffer
  97. * @ret len Length of header value, or negative error
  98. */
  99. static int http_format_p2p_peerdistex ( struct http_transaction *http,
  100. char *buf, size_t len ) {
  101. int supported = http_peerdist_supported ( http );
  102. /* Omit header if PeerDist encoding is not supported */
  103. if ( ! supported )
  104. return 0;
  105. /* Construct header */
  106. return snprintf ( buf, len, ( "MinContentInformation=1.0, "
  107. "MaxContentInformation=2.0" ) );
  108. }
  109. /** HTTP "X-P2P-PeerDist" header */
  110. struct http_request_header http_request_p2p_peerdistex __http_request_header = {
  111. .name = "X-P2P-PeerDistEx",
  112. .format = http_format_p2p_peerdistex,
  113. };
  114. /**
  115. * Initialise PeerDist content encoding
  116. *
  117. * @v http HTTP transaction
  118. * @ret rc Return status code
  119. */
  120. static int http_peerdist_init ( struct http_transaction *http ) {
  121. return peermux_filter ( &http->content, &http->transfer, http->uri );
  122. }
  123. /** PeerDist HTTP content encoding */
  124. struct http_content_encoding peerdist_encoding __http_content_encoding = {
  125. .name = "peerdist",
  126. .supported = http_peerdist_supported,
  127. .init = http_peerdist_init,
  128. };