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.

httpcore.c 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /*
  2. * Copyright (C) 2007 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 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. FILE_LICENCE ( GPL2_OR_LATER );
  20. /**
  21. * @file
  22. *
  23. * Hyper Text Transfer Protocol (HTTP) core functionality
  24. *
  25. */
  26. #include <stdint.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <strings.h>
  31. #include <byteswap.h>
  32. #include <errno.h>
  33. #include <assert.h>
  34. #include <ipxe/uri.h>
  35. #include <ipxe/refcnt.h>
  36. #include <ipxe/iobuf.h>
  37. #include <ipxe/xfer.h>
  38. #include <ipxe/open.h>
  39. #include <ipxe/socket.h>
  40. #include <ipxe/tcpip.h>
  41. #include <ipxe/process.h>
  42. #include <ipxe/linebuf.h>
  43. #include <ipxe/base64.h>
  44. #include <ipxe/base16.h>
  45. #include <ipxe/md5.h>
  46. #include <ipxe/blockdev.h>
  47. #include <ipxe/acpi.h>
  48. #include <ipxe/http.h>
  49. /* Disambiguate the various error causes */
  50. #define EACCES_401 __einfo_error ( EINFO_EACCES_401 )
  51. #define EINFO_EACCES_401 \
  52. __einfo_uniqify ( EINFO_EACCES, 0x01, "HTTP 401 Unauthorized" )
  53. #define EIO_OTHER __einfo_error ( EINFO_EIO_OTHER )
  54. #define EINFO_EIO_OTHER \
  55. __einfo_uniqify ( EINFO_EIO, 0x01, "Unrecognised HTTP response code" )
  56. #define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH )
  57. #define EINFO_EIO_CONTENT_LENGTH \
  58. __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" )
  59. #define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE )
  60. #define EINFO_EINVAL_RESPONSE \
  61. __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" )
  62. #define EINVAL_HEADER __einfo_error ( EINFO_EINVAL_HEADER )
  63. #define EINFO_EINVAL_HEADER \
  64. __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid header" )
  65. #define EINVAL_CONTENT_LENGTH __einfo_error ( EINFO_EINVAL_CONTENT_LENGTH )
  66. #define EINFO_EINVAL_CONTENT_LENGTH \
  67. __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid content length" )
  68. #define EINVAL_CHUNK_LENGTH __einfo_error ( EINFO_EINVAL_CHUNK_LENGTH )
  69. #define EINFO_EINVAL_CHUNK_LENGTH \
  70. __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid chunk length" )
  71. #define ENOENT_404 __einfo_error ( EINFO_ENOENT_404 )
  72. #define EINFO_ENOENT_404 \
  73. __einfo_uniqify ( EINFO_ENOENT, 0x01, "HTTP 404 Not Found" )
  74. #define EPERM_403 __einfo_error ( EINFO_EPERM_403 )
  75. #define EINFO_EPERM_403 \
  76. __einfo_uniqify ( EINFO_EPERM, 0x01, "HTTP 403 Forbidden" )
  77. #define EPROTO_UNSOLICITED __einfo_error ( EINFO_EPROTO_UNSOLICITED )
  78. #define EINFO_EPROTO_UNSOLICITED \
  79. __einfo_uniqify ( EINFO_EPROTO, 0x01, "Unsolicited data" )
  80. /** Block size used for HTTP block device request */
  81. #define HTTP_BLKSIZE 512
  82. /** HTTP flags */
  83. enum http_flags {
  84. /** Request is waiting to be transmitted */
  85. HTTP_TX_PENDING = 0x0001,
  86. /** Fetch header only */
  87. HTTP_HEAD_ONLY = 0x0002,
  88. /** Client would like to keep connection alive */
  89. HTTP_CLIENT_KEEPALIVE = 0x0004,
  90. /** Server will keep connection alive */
  91. HTTP_SERVER_KEEPALIVE = 0x0008,
  92. /** Discard the current request and try again */
  93. HTTP_TRY_AGAIN = 0x0010,
  94. /** Provide Basic authentication details */
  95. HTTP_BASIC_AUTH = 0x0020,
  96. /** Provide Digest authentication details */
  97. HTTP_DIGEST_AUTH = 0x0040,
  98. };
  99. /** HTTP receive state */
  100. enum http_rx_state {
  101. HTTP_RX_RESPONSE = 0,
  102. HTTP_RX_HEADER,
  103. HTTP_RX_CHUNK_LEN,
  104. /* In HTTP_RX_DATA, it is acceptable for the server to close
  105. * the connection (unless we are in the middle of a chunked
  106. * transfer).
  107. */
  108. HTTP_RX_DATA,
  109. /* In the following states, it is acceptable for the server to
  110. * close the connection.
  111. */
  112. HTTP_RX_TRAILER,
  113. HTTP_RX_IDLE,
  114. HTTP_RX_DEAD,
  115. };
  116. /**
  117. * An HTTP request
  118. *
  119. */
  120. struct http_request {
  121. /** Reference count */
  122. struct refcnt refcnt;
  123. /** Data transfer interface */
  124. struct interface xfer;
  125. /** Partial transfer interface */
  126. struct interface partial;
  127. /** URI being fetched */
  128. struct uri *uri;
  129. /** Default port */
  130. unsigned int default_port;
  131. /** Filter (if any) */
  132. int ( * filter ) ( struct interface *xfer,
  133. const char *name,
  134. struct interface **next );
  135. /** Transport layer interface */
  136. struct interface socket;
  137. /** Flags */
  138. unsigned int flags;
  139. /** Starting offset of partial transfer (if applicable) */
  140. size_t partial_start;
  141. /** Length of partial transfer (if applicable) */
  142. size_t partial_len;
  143. /** TX process */
  144. struct process process;
  145. /** RX state */
  146. enum http_rx_state rx_state;
  147. /** Response code */
  148. unsigned int code;
  149. /** Received length */
  150. size_t rx_len;
  151. /** Length remaining (or 0 if unknown) */
  152. size_t remaining;
  153. /** HTTP is using Transfer-Encoding: chunked */
  154. int chunked;
  155. /** Current chunk length remaining (if applicable) */
  156. size_t chunk_remaining;
  157. /** Line buffer for received header lines */
  158. struct line_buffer linebuf;
  159. /** Receive data buffer (if applicable) */
  160. userptr_t rx_buffer;
  161. /** Authentication realm (if any) */
  162. char *auth_realm;
  163. /** Authentication nonce (if any) */
  164. char *auth_nonce;
  165. /** Authentication opaque string (if any) */
  166. char *auth_opaque;
  167. };
  168. /**
  169. * Free HTTP request
  170. *
  171. * @v refcnt Reference counter
  172. */
  173. static void http_free ( struct refcnt *refcnt ) {
  174. struct http_request *http =
  175. container_of ( refcnt, struct http_request, refcnt );
  176. uri_put ( http->uri );
  177. empty_line_buffer ( &http->linebuf );
  178. free ( http->auth_realm );
  179. free ( http->auth_nonce );
  180. free ( http->auth_opaque );
  181. free ( http );
  182. };
  183. /**
  184. * Close HTTP request
  185. *
  186. * @v http HTTP request
  187. * @v rc Return status code
  188. */
  189. static void http_close ( struct http_request *http, int rc ) {
  190. /* Prevent further processing of any current packet */
  191. http->rx_state = HTTP_RX_DEAD;
  192. /* Prevent reconnection */
  193. http->flags &= ~HTTP_CLIENT_KEEPALIVE;
  194. /* Remove process */
  195. process_del ( &http->process );
  196. /* Close all data transfer interfaces */
  197. intf_shutdown ( &http->socket, rc );
  198. intf_shutdown ( &http->partial, rc );
  199. intf_shutdown ( &http->xfer, rc );
  200. }
  201. /**
  202. * Open HTTP socket
  203. *
  204. * @v http HTTP request
  205. * @ret rc Return status code
  206. */
  207. static int http_socket_open ( struct http_request *http ) {
  208. struct uri *uri = http->uri;
  209. struct sockaddr_tcpip server;
  210. struct interface *socket;
  211. int rc;
  212. /* Open socket */
  213. memset ( &server, 0, sizeof ( server ) );
  214. server.st_port = htons ( uri_port ( uri, http->default_port ) );
  215. socket = &http->socket;
  216. if ( http->filter ) {
  217. if ( ( rc = http->filter ( socket, uri->host, &socket ) ) != 0 )
  218. return rc;
  219. }
  220. if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM,
  221. ( struct sockaddr * ) &server,
  222. uri->host, NULL ) ) != 0 )
  223. return rc;
  224. return 0;
  225. }
  226. /**
  227. * Mark HTTP request as completed successfully
  228. *
  229. * @v http HTTP request
  230. */
  231. static void http_done ( struct http_request *http ) {
  232. int rc;
  233. /* If we are not at an appropriate stage of the protocol
  234. * (including being in the middle of a chunked transfer),
  235. * force an error.
  236. */
  237. if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) {
  238. DBGC ( http, "HTTP %p connection closed unexpectedly in state "
  239. "%d\n", http, http->rx_state );
  240. http_close ( http, -ECONNRESET );
  241. return;
  242. }
  243. /* If we had a Content-Length, and the received content length
  244. * isn't correct, force an error
  245. */
  246. if ( http->remaining != 0 ) {
  247. DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
  248. http, http->rx_len, ( http->rx_len + http->remaining ) );
  249. http_close ( http, -EIO_CONTENT_LENGTH );
  250. return;
  251. }
  252. /* Enter idle state */
  253. http->rx_state = HTTP_RX_IDLE;
  254. http->rx_len = 0;
  255. assert ( http->remaining == 0 );
  256. assert ( http->chunked == 0 );
  257. assert ( http->chunk_remaining == 0 );
  258. /* Close partial transfer interface */
  259. if ( ! ( http->flags & HTTP_TRY_AGAIN ) )
  260. intf_restart ( &http->partial, 0 );
  261. /* Close everything unless we want to keep the connection alive */
  262. if ( ! ( http->flags & ( HTTP_CLIENT_KEEPALIVE | HTTP_TRY_AGAIN ) ) ) {
  263. http_close ( http, 0 );
  264. return;
  265. }
  266. /* If the server is not intending to keep the connection
  267. * alive, then reopen the socket.
  268. */
  269. if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) {
  270. DBGC ( http, "HTTP %p reopening connection\n", http );
  271. intf_restart ( &http->socket, 0 );
  272. if ( ( rc = http_socket_open ( http ) ) != 0 ) {
  273. http_close ( http, rc );
  274. return;
  275. }
  276. }
  277. http->flags &= ~HTTP_SERVER_KEEPALIVE;
  278. /* Retry the request if applicable */
  279. if ( http->flags & HTTP_TRY_AGAIN ) {
  280. http->flags &= ~HTTP_TRY_AGAIN;
  281. http->flags |= HTTP_TX_PENDING;
  282. http->rx_state = HTTP_RX_RESPONSE;
  283. process_add ( &http->process );
  284. }
  285. }
  286. /**
  287. * Convert HTTP response code to return status code
  288. *
  289. * @v response HTTP response code
  290. * @ret rc Return status code
  291. */
  292. static int http_response_to_rc ( unsigned int response ) {
  293. switch ( response ) {
  294. case 200:
  295. case 206:
  296. case 301:
  297. case 302:
  298. case 303:
  299. return 0;
  300. case 404:
  301. return -ENOENT_404;
  302. case 403:
  303. return -EPERM_403;
  304. case 401:
  305. return -EACCES_401;
  306. default:
  307. return -EIO_OTHER;
  308. }
  309. }
  310. /**
  311. * Handle HTTP response
  312. *
  313. * @v http HTTP request
  314. * @v response HTTP response
  315. * @ret rc Return status code
  316. */
  317. static int http_rx_response ( struct http_request *http, char *response ) {
  318. char *spc;
  319. DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
  320. /* Check response starts with "HTTP/" */
  321. if ( strncmp ( response, "HTTP/", 5 ) != 0 )
  322. return -EINVAL_RESPONSE;
  323. /* Locate and store response code */
  324. spc = strchr ( response, ' ' );
  325. if ( ! spc )
  326. return -EINVAL_RESPONSE;
  327. http->code = strtoul ( spc, NULL, 10 );
  328. /* Move to receive headers */
  329. http->rx_state = ( ( http->flags & HTTP_HEAD_ONLY ) ?
  330. HTTP_RX_TRAILER : HTTP_RX_HEADER );
  331. return 0;
  332. }
  333. /**
  334. * Handle HTTP Location header
  335. *
  336. * @v http HTTP request
  337. * @v value HTTP header value
  338. * @ret rc Return status code
  339. */
  340. static int http_rx_location ( struct http_request *http, char *value ) {
  341. int rc;
  342. /* Redirect to new location */
  343. DBGC ( http, "HTTP %p redirecting to %s\n", http, value );
  344. if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING,
  345. value ) ) != 0 ) {
  346. DBGC ( http, "HTTP %p could not redirect: %s\n",
  347. http, strerror ( rc ) );
  348. return rc;
  349. }
  350. return 0;
  351. }
  352. /**
  353. * Handle HTTP Content-Length header
  354. *
  355. * @v http HTTP request
  356. * @v value HTTP header value
  357. * @ret rc Return status code
  358. */
  359. static int http_rx_content_length ( struct http_request *http, char *value ) {
  360. struct block_device_capacity capacity;
  361. size_t content_len;
  362. char *endp;
  363. /* Parse content length */
  364. content_len = strtoul ( value, &endp, 10 );
  365. if ( *endp != '\0' ) {
  366. DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
  367. http, value );
  368. return -EINVAL_CONTENT_LENGTH;
  369. }
  370. /* If we already have an expected content length, and this
  371. * isn't it, then complain
  372. */
  373. if ( http->remaining && ( http->remaining != content_len ) ) {
  374. DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected "
  375. "%zd)\n", http, content_len, http->remaining );
  376. return -EIO_CONTENT_LENGTH;
  377. }
  378. if ( ! ( http->flags & HTTP_HEAD_ONLY ) )
  379. http->remaining = content_len;
  380. /* Do nothing more if we are retrying the request */
  381. if ( http->flags & HTTP_TRY_AGAIN )
  382. return 0;
  383. /* Use seek() to notify recipient of filesize */
  384. xfer_seek ( &http->xfer, http->remaining );
  385. xfer_seek ( &http->xfer, 0 );
  386. /* Report block device capacity if applicable */
  387. if ( http->flags & HTTP_HEAD_ONLY ) {
  388. capacity.blocks = ( content_len / HTTP_BLKSIZE );
  389. capacity.blksize = HTTP_BLKSIZE;
  390. capacity.max_count = -1U;
  391. block_capacity ( &http->partial, &capacity );
  392. }
  393. return 0;
  394. }
  395. /**
  396. * Handle HTTP Transfer-Encoding header
  397. *
  398. * @v http HTTP request
  399. * @v value HTTP header value
  400. * @ret rc Return status code
  401. */
  402. static int http_rx_transfer_encoding ( struct http_request *http, char *value ){
  403. if ( strcasecmp ( value, "chunked" ) == 0 ) {
  404. /* Mark connection as using chunked transfer encoding */
  405. http->chunked = 1;
  406. }
  407. return 0;
  408. }
  409. /**
  410. * Handle HTTP Connection header
  411. *
  412. * @v http HTTP request
  413. * @v value HTTP header value
  414. * @ret rc Return status code
  415. */
  416. static int http_rx_connection ( struct http_request *http, char *value ) {
  417. if ( strcasecmp ( value, "keep-alive" ) == 0 ) {
  418. /* Mark connection as being kept alive by the server */
  419. http->flags |= HTTP_SERVER_KEEPALIVE;
  420. }
  421. return 0;
  422. }
  423. /**
  424. * Handle WWW-Authenticate Basic header
  425. *
  426. * @v http HTTP request
  427. * @v params Parameters
  428. * @ret rc Return status code
  429. */
  430. static int http_rx_basic_auth ( struct http_request *http, char *params ) {
  431. DBGC ( http, "HTTP %p Basic authentication required (%s)\n",
  432. http, params );
  433. /* If we received a 401 Unauthorized response, then retry
  434. * using Basic authentication
  435. */
  436. if ( ( http->code == 401 ) &&
  437. ( ! ( http->flags & HTTP_BASIC_AUTH ) ) &&
  438. ( http->uri->user != NULL ) ) {
  439. http->flags |= ( HTTP_TRY_AGAIN | HTTP_BASIC_AUTH );
  440. }
  441. return 0;
  442. }
  443. /**
  444. * Parse Digest authentication parameter
  445. *
  446. * @v params Parameters
  447. * @v name Parameter name (including trailing "=\"")
  448. * @ret value Parameter value, or NULL
  449. */
  450. static char * http_digest_param ( char *params, const char *name ) {
  451. char *key;
  452. char *value;
  453. char *terminator;
  454. /* Locate parameter */
  455. key = strstr ( params, name );
  456. if ( ! key )
  457. return NULL;
  458. /* Extract value */
  459. value = ( key + strlen ( name ) );
  460. terminator = strchr ( value, '"' );
  461. if ( ! terminator )
  462. return NULL;
  463. return strndup ( value, ( terminator - value ) );
  464. }
  465. /**
  466. * Handle WWW-Authenticate Digest header
  467. *
  468. * @v http HTTP request
  469. * @v params Parameters
  470. * @ret rc Return status code
  471. */
  472. static int http_rx_digest_auth ( struct http_request *http, char *params ) {
  473. DBGC ( http, "HTTP %p Digest authentication required (%s)\n",
  474. http, params );
  475. /* If we received a 401 Unauthorized response, then retry
  476. * using Digest authentication
  477. */
  478. if ( ( http->code == 401 ) &&
  479. ( ! ( http->flags & HTTP_DIGEST_AUTH ) ) &&
  480. ( http->uri->user != NULL ) ) {
  481. /* Extract realm */
  482. free ( http->auth_realm );
  483. http->auth_realm = http_digest_param ( params, "realm=\"" );
  484. if ( ! http->auth_realm ) {
  485. DBGC ( http, "HTTP %p Digest prompt missing realm\n",
  486. http );
  487. return -EINVAL_HEADER;
  488. }
  489. /* Extract nonce */
  490. free ( http->auth_nonce );
  491. http->auth_nonce = http_digest_param ( params, "nonce=\"" );
  492. if ( ! http->auth_nonce ) {
  493. DBGC ( http, "HTTP %p Digest prompt missing nonce\n",
  494. http );
  495. return -EINVAL_HEADER;
  496. }
  497. /* Extract opaque */
  498. free ( http->auth_opaque );
  499. http->auth_opaque = http_digest_param ( params, "opaque=\"" );
  500. if ( ! http->auth_opaque ) {
  501. /* Not an error; "opaque" is optional */
  502. }
  503. http->flags |= ( HTTP_TRY_AGAIN | HTTP_DIGEST_AUTH );
  504. }
  505. return 0;
  506. }
  507. /** An HTTP WWW-Authenticate header handler */
  508. struct http_auth_header_handler {
  509. /** Scheme (e.g. "Basic") */
  510. const char *scheme;
  511. /** Handle received parameters
  512. *
  513. * @v http HTTP request
  514. * @v params Parameters
  515. * @ret rc Return status code
  516. */
  517. int ( * rx ) ( struct http_request *http, char *params );
  518. };
  519. /** List of HTTP WWW-Authenticate header handlers */
  520. static struct http_auth_header_handler http_auth_header_handlers[] = {
  521. {
  522. .scheme = "Basic",
  523. .rx = http_rx_basic_auth,
  524. },
  525. {
  526. .scheme = "Digest",
  527. .rx = http_rx_digest_auth,
  528. },
  529. { NULL, NULL },
  530. };
  531. /**
  532. * Handle HTTP WWW-Authenticate header
  533. *
  534. * @v http HTTP request
  535. * @v value HTTP header value
  536. * @ret rc Return status code
  537. */
  538. static int http_rx_www_authenticate ( struct http_request *http, char *value ) {
  539. struct http_auth_header_handler *handler;
  540. char *separator;
  541. char *scheme;
  542. char *params;
  543. int rc;
  544. /* Extract scheme */
  545. separator = strchr ( value, ' ' );
  546. if ( ! separator ) {
  547. DBGC ( http, "HTTP %p malformed WWW-Authenticate header\n",
  548. http );
  549. return -EINVAL_HEADER;
  550. }
  551. *separator = '\0';
  552. scheme = value;
  553. params = ( separator + 1 );
  554. /* Hand off to header handler, if one exists */
  555. for ( handler = http_auth_header_handlers; handler->scheme; handler++ ){
  556. if ( strcasecmp ( scheme, handler->scheme ) == 0 ) {
  557. if ( ( rc = handler->rx ( http, params ) ) != 0 )
  558. return rc;
  559. break;
  560. }
  561. }
  562. return 0;
  563. }
  564. /** An HTTP header handler */
  565. struct http_header_handler {
  566. /** Name (e.g. "Content-Length") */
  567. const char *header;
  568. /** Handle received header
  569. *
  570. * @v http HTTP request
  571. * @v value HTTP header value
  572. * @ret rc Return status code
  573. *
  574. * If an error is returned, the download will be aborted.
  575. */
  576. int ( * rx ) ( struct http_request *http, char *value );
  577. };
  578. /** List of HTTP header handlers */
  579. static struct http_header_handler http_header_handlers[] = {
  580. {
  581. .header = "Location",
  582. .rx = http_rx_location,
  583. },
  584. {
  585. .header = "Content-Length",
  586. .rx = http_rx_content_length,
  587. },
  588. {
  589. .header = "Transfer-Encoding",
  590. .rx = http_rx_transfer_encoding,
  591. },
  592. {
  593. .header = "Connection",
  594. .rx = http_rx_connection,
  595. },
  596. {
  597. .header = "WWW-Authenticate",
  598. .rx = http_rx_www_authenticate,
  599. },
  600. { NULL, NULL }
  601. };
  602. /**
  603. * Handle HTTP header
  604. *
  605. * @v http HTTP request
  606. * @v header HTTP header
  607. * @ret rc Return status code
  608. */
  609. static int http_rx_header ( struct http_request *http, char *header ) {
  610. struct http_header_handler *handler;
  611. char *separator;
  612. char *value;
  613. int rc;
  614. /* An empty header line marks the end of this phase */
  615. if ( ! header[0] ) {
  616. empty_line_buffer ( &http->linebuf );
  617. /* Handle response code */
  618. if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) {
  619. if ( ( rc = http_response_to_rc ( http->code ) ) != 0 )
  620. return rc;
  621. }
  622. /* Move to next state */
  623. if ( http->rx_state == HTTP_RX_HEADER ) {
  624. DBGC ( http, "HTTP %p start of data\n", http );
  625. http->rx_state = ( http->chunked ?
  626. HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
  627. if ( ( http->partial_len != 0 ) &&
  628. ( ! ( http->flags & HTTP_TRY_AGAIN ) ) ) {
  629. http->remaining = http->partial_len;
  630. }
  631. return 0;
  632. } else {
  633. DBGC ( http, "HTTP %p end of trailer\n", http );
  634. http_done ( http );
  635. return 0;
  636. }
  637. }
  638. DBGC ( http, "HTTP %p header \"%s\"\n", http, header );
  639. /* Split header at the ": " */
  640. separator = strstr ( header, ": " );
  641. if ( ! separator ) {
  642. DBGC ( http, "HTTP %p malformed header\n", http );
  643. return -EINVAL_HEADER;
  644. }
  645. *separator = '\0';
  646. value = ( separator + 2 );
  647. /* Hand off to header handler, if one exists */
  648. for ( handler = http_header_handlers ; handler->header ; handler++ ) {
  649. if ( strcasecmp ( header, handler->header ) == 0 ) {
  650. if ( ( rc = handler->rx ( http, value ) ) != 0 )
  651. return rc;
  652. break;
  653. }
  654. }
  655. return 0;
  656. }
  657. /**
  658. * Handle HTTP chunk length
  659. *
  660. * @v http HTTP request
  661. * @v length HTTP chunk length
  662. * @ret rc Return status code
  663. */
  664. static int http_rx_chunk_len ( struct http_request *http, char *length ) {
  665. char *endp;
  666. /* Skip blank lines between chunks */
  667. if ( length[0] == '\0' )
  668. return 0;
  669. /* Parse chunk length */
  670. http->chunk_remaining = strtoul ( length, &endp, 16 );
  671. if ( *endp != '\0' ) {
  672. DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
  673. http, length );
  674. return -EINVAL_CHUNK_LENGTH;
  675. }
  676. /* Terminate chunked encoding if applicable */
  677. if ( http->chunk_remaining == 0 ) {
  678. DBGC ( http, "HTTP %p end of chunks\n", http );
  679. http->chunked = 0;
  680. http->rx_state = HTTP_RX_TRAILER;
  681. return 0;
  682. }
  683. /* Use seek() to notify recipient of new filesize */
  684. DBGC ( http, "HTTP %p start of chunk of length %zd\n",
  685. http, http->chunk_remaining );
  686. if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) {
  687. xfer_seek ( &http->xfer,
  688. ( http->rx_len + http->chunk_remaining ) );
  689. xfer_seek ( &http->xfer, http->rx_len );
  690. }
  691. /* Start receiving data */
  692. http->rx_state = HTTP_RX_DATA;
  693. return 0;
  694. }
  695. /** An HTTP line-based data handler */
  696. struct http_line_handler {
  697. /** Handle line
  698. *
  699. * @v http HTTP request
  700. * @v line Line to handle
  701. * @ret rc Return status code
  702. */
  703. int ( * rx ) ( struct http_request *http, char *line );
  704. };
  705. /** List of HTTP line-based data handlers */
  706. static struct http_line_handler http_line_handlers[] = {
  707. [HTTP_RX_RESPONSE] = { .rx = http_rx_response },
  708. [HTTP_RX_HEADER] = { .rx = http_rx_header },
  709. [HTTP_RX_CHUNK_LEN] = { .rx = http_rx_chunk_len },
  710. [HTTP_RX_TRAILER] = { .rx = http_rx_header },
  711. };
  712. /**
  713. * Handle new data arriving via HTTP connection
  714. *
  715. * @v http HTTP request
  716. * @v iobuf I/O buffer
  717. * @v meta Data transfer metadata
  718. * @ret rc Return status code
  719. */
  720. static int http_socket_deliver ( struct http_request *http,
  721. struct io_buffer *iobuf,
  722. struct xfer_metadata *meta __unused ) {
  723. struct http_line_handler *lh;
  724. char *line;
  725. size_t data_len;
  726. ssize_t line_len;
  727. int rc = 0;
  728. while ( iobuf && iob_len ( iobuf ) ) {
  729. switch ( http->rx_state ) {
  730. case HTTP_RX_IDLE:
  731. /* Receiving any data in this state is an error */
  732. DBGC ( http, "HTTP %p received %zd bytes while %s\n",
  733. http, iob_len ( iobuf ),
  734. ( ( http->rx_state == HTTP_RX_IDLE ) ?
  735. "idle" : "dead" ) );
  736. rc = -EPROTO_UNSOLICITED;
  737. goto done;
  738. case HTTP_RX_DEAD:
  739. /* Do no further processing */
  740. goto done;
  741. case HTTP_RX_DATA:
  742. /* Pass received data to caller */
  743. data_len = iob_len ( iobuf );
  744. if ( http->chunk_remaining &&
  745. ( http->chunk_remaining < data_len ) ) {
  746. data_len = http->chunk_remaining;
  747. }
  748. if ( http->remaining &&
  749. ( http->remaining < data_len ) ) {
  750. data_len = http->remaining;
  751. }
  752. if ( http->flags & HTTP_TRY_AGAIN ) {
  753. /* Discard all received data */
  754. iob_pull ( iobuf, data_len );
  755. } else if ( http->rx_buffer != UNULL ) {
  756. /* Copy to partial transfer buffer */
  757. copy_to_user ( http->rx_buffer, http->rx_len,
  758. iobuf->data, data_len );
  759. iob_pull ( iobuf, data_len );
  760. } else if ( data_len < iob_len ( iobuf ) ) {
  761. /* Deliver partial buffer as raw data */
  762. rc = xfer_deliver_raw ( &http->xfer,
  763. iobuf->data, data_len );
  764. iob_pull ( iobuf, data_len );
  765. if ( rc != 0 )
  766. goto done;
  767. } else {
  768. /* Deliver whole I/O buffer */
  769. if ( ( rc = xfer_deliver_iob ( &http->xfer,
  770. iob_disown ( iobuf ) ) ) != 0 )
  771. goto done;
  772. }
  773. http->rx_len += data_len;
  774. if ( http->chunk_remaining ) {
  775. http->chunk_remaining -= data_len;
  776. if ( http->chunk_remaining == 0 )
  777. http->rx_state = HTTP_RX_CHUNK_LEN;
  778. }
  779. if ( http->remaining ) {
  780. http->remaining -= data_len;
  781. if ( ( http->remaining == 0 ) &&
  782. ( http->rx_state == HTTP_RX_DATA ) ) {
  783. http_done ( http );
  784. }
  785. }
  786. break;
  787. case HTTP_RX_RESPONSE:
  788. case HTTP_RX_HEADER:
  789. case HTTP_RX_CHUNK_LEN:
  790. case HTTP_RX_TRAILER:
  791. /* In the other phases, buffer and process a
  792. * line at a time
  793. */
  794. line_len = line_buffer ( &http->linebuf, iobuf->data,
  795. iob_len ( iobuf ) );
  796. if ( line_len < 0 ) {
  797. rc = line_len;
  798. DBGC ( http, "HTTP %p could not buffer line: "
  799. "%s\n", http, strerror ( rc ) );
  800. goto done;
  801. }
  802. iob_pull ( iobuf, line_len );
  803. line = buffered_line ( &http->linebuf );
  804. if ( line ) {
  805. lh = &http_line_handlers[http->rx_state];
  806. if ( ( rc = lh->rx ( http, line ) ) != 0 )
  807. goto done;
  808. }
  809. break;
  810. default:
  811. assert ( 0 );
  812. break;
  813. }
  814. }
  815. done:
  816. if ( rc )
  817. http_close ( http, rc );
  818. free_iob ( iobuf );
  819. return rc;
  820. }
  821. /**
  822. * Check HTTP socket flow control window
  823. *
  824. * @v http HTTP request
  825. * @ret len Length of window
  826. */
  827. static size_t http_socket_window ( struct http_request *http __unused ) {
  828. /* Window is always open. This is to prevent TCP from
  829. * stalling if our parent window is not currently open.
  830. */
  831. return ( ~( ( size_t ) 0 ) );
  832. }
  833. /**
  834. * Close HTTP socket
  835. *
  836. * @v http HTTP request
  837. * @v rc Reason for close
  838. */
  839. static void http_socket_close ( struct http_request *http, int rc ) {
  840. /* If we have an error, terminate */
  841. if ( rc != 0 ) {
  842. http_close ( http, rc );
  843. return;
  844. }
  845. /* Mark HTTP request as complete */
  846. http_done ( http );
  847. }
  848. /**
  849. * Generate HTTP Basic authorisation string
  850. *
  851. * @v http HTTP request
  852. * @ret auth Authorisation string, or NULL on error
  853. *
  854. * The authorisation string is dynamically allocated, and must be
  855. * freed by the caller.
  856. */
  857. static char * http_basic_auth ( struct http_request *http ) {
  858. const char *user = http->uri->user;
  859. const char *password =
  860. ( http->uri->password ? http->uri->password : "" );
  861. size_t user_pw_len =
  862. ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) );
  863. char user_pw[ user_pw_len + 1 /* NUL */ ];
  864. size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
  865. char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
  866. char *auth;
  867. int len;
  868. /* Sanity check */
  869. assert ( user != NULL );
  870. /* Make "user:password" string from decoded fields */
  871. snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password );
  872. /* Base64-encode the "user:password" string */
  873. base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 );
  874. /* Generate the authorisation string */
  875. len = asprintf ( &auth, "Authorization: Basic %s\r\n",
  876. user_pw_base64 );
  877. if ( len < 0 )
  878. return NULL;
  879. return auth;
  880. }
  881. /**
  882. * Generate HTTP Digest authorisation string
  883. *
  884. * @v http HTTP request
  885. * @v method HTTP method (e.g. "GET")
  886. * @v uri HTTP request URI (e.g. "/index.html")
  887. * @ret auth Authorisation string, or NULL on error
  888. *
  889. * The authorisation string is dynamically allocated, and must be
  890. * freed by the caller.
  891. */
  892. static char * http_digest_auth ( struct http_request *http,
  893. const char *method, const char *uri ) {
  894. const char *user = http->uri->user;
  895. const char *password =
  896. ( http->uri->password ? http->uri->password : "" );
  897. const char *realm = http->auth_realm;
  898. const char *nonce = http->auth_nonce;
  899. const char *opaque = http->auth_opaque;
  900. static const char colon = ':';
  901. uint8_t ctx[MD5_CTX_SIZE];
  902. uint8_t digest[MD5_DIGEST_SIZE];
  903. char ha1[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
  904. char ha2[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
  905. char response[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ];
  906. char *auth;
  907. int len;
  908. /* Sanity checks */
  909. assert ( user != NULL );
  910. assert ( realm != NULL );
  911. assert ( nonce != NULL );
  912. /* Generate HA1 */
  913. digest_init ( &md5_algorithm, ctx );
  914. digest_update ( &md5_algorithm, ctx, user, strlen ( user ) );
  915. digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
  916. digest_update ( &md5_algorithm, ctx, realm, strlen ( realm ) );
  917. digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
  918. digest_update ( &md5_algorithm, ctx, password, strlen ( password ) );
  919. digest_final ( &md5_algorithm, ctx, digest );
  920. base16_encode ( digest, sizeof ( digest ), ha1 );
  921. /* Generate HA2 */
  922. digest_init ( &md5_algorithm, ctx );
  923. digest_update ( &md5_algorithm, ctx, method, strlen ( method ) );
  924. digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
  925. digest_update ( &md5_algorithm, ctx, uri, strlen ( uri ) );
  926. digest_final ( &md5_algorithm, ctx, digest );
  927. base16_encode ( digest, sizeof ( digest ), ha2 );
  928. /* Generate response */
  929. digest_init ( &md5_algorithm, ctx );
  930. digest_update ( &md5_algorithm, ctx, ha1, strlen ( ha1 ) );
  931. digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
  932. digest_update ( &md5_algorithm, ctx, nonce, strlen ( nonce ) );
  933. digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) );
  934. digest_update ( &md5_algorithm, ctx, ha2, strlen ( ha2 ) );
  935. digest_final ( &md5_algorithm, ctx, digest );
  936. base16_encode ( digest, sizeof ( digest ), response );
  937. /* Generate the authorisation string */
  938. len = asprintf ( &auth, "Authorization: Digest username=\"%s\", "
  939. "realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
  940. "%s%s%sresponse=\"%s\"\r\n", user, realm, nonce, uri,
  941. ( opaque ? "opaque=\"" : "" ),
  942. ( opaque ? opaque : "" ),
  943. ( opaque ? "\", " : "" ), response );
  944. if ( len < 0 )
  945. return NULL;
  946. return auth;
  947. }
  948. /**
  949. * HTTP process
  950. *
  951. * @v http HTTP request
  952. */
  953. static void http_step ( struct http_request *http ) {
  954. size_t uri_len;
  955. char *method;
  956. char *uri;
  957. char *range;
  958. char *auth;
  959. int len;
  960. int rc;
  961. /* Do nothing if we have already transmitted the request */
  962. if ( ! ( http->flags & HTTP_TX_PENDING ) )
  963. return;
  964. /* Do nothing until socket is ready */
  965. if ( ! xfer_window ( &http->socket ) )
  966. return;
  967. /* Force a HEAD request if we have nowhere to send any received data */
  968. if ( ( xfer_window ( &http->xfer ) == 0 ) &&
  969. ( http->rx_buffer == UNULL ) ) {
  970. http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
  971. }
  972. /* Determine method */
  973. method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" );
  974. /* Construct path?query request */
  975. uri_len = ( unparse_uri ( NULL, 0, http->uri,
  976. URI_PATH_BIT | URI_QUERY_BIT )
  977. + 1 /* possible "/" */ + 1 /* NUL */ );
  978. uri = malloc ( uri_len );
  979. if ( ! uri ) {
  980. rc = -ENOMEM;
  981. goto err_uri;
  982. }
  983. unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT );
  984. if ( ! uri[0] ) {
  985. uri[0] = '/';
  986. uri[1] = '\0';
  987. }
  988. /* Calculate range request parameters if applicable */
  989. if ( http->partial_len ) {
  990. len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n",
  991. http->partial_start,
  992. ( http->partial_start + http->partial_len
  993. - 1 ) );
  994. if ( len < 0 ) {
  995. rc = len;
  996. goto err_range;
  997. }
  998. } else {
  999. range = NULL;
  1000. }
  1001. /* Construct authorisation, if applicable */
  1002. if ( http->flags & HTTP_BASIC_AUTH ) {
  1003. auth = http_basic_auth ( http );
  1004. if ( ! auth ) {
  1005. rc = -ENOMEM;
  1006. goto err_auth;
  1007. }
  1008. } else if ( http->flags & HTTP_DIGEST_AUTH ) {
  1009. auth = http_digest_auth ( http, method, uri );
  1010. if ( ! auth ) {
  1011. rc = -ENOMEM;
  1012. goto err_auth;
  1013. }
  1014. } else {
  1015. auth = NULL;
  1016. }
  1017. /* Mark request as transmitted */
  1018. http->flags &= ~HTTP_TX_PENDING;
  1019. /* Send request */
  1020. if ( ( rc = xfer_printf ( &http->socket,
  1021. "%s %s HTTP/1.1\r\n"
  1022. "User-Agent: iPXE/" VERSION "\r\n"
  1023. "Host: %s%s%s\r\n"
  1024. "%s%s%s"
  1025. "\r\n",
  1026. method, uri, http->uri->host,
  1027. ( http->uri->port ?
  1028. ":" : "" ),
  1029. ( http->uri->port ?
  1030. http->uri->port : "" ),
  1031. ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
  1032. "Connection: keep-alive\r\n" : "" ),
  1033. ( range ? range : "" ),
  1034. ( auth ? auth : "" ) ) ) != 0 ) {
  1035. goto err_xfer;
  1036. }
  1037. err_xfer:
  1038. free ( auth );
  1039. err_auth:
  1040. free ( range );
  1041. err_range:
  1042. free ( uri );
  1043. err_uri:
  1044. if ( rc != 0 )
  1045. http_close ( http, rc );
  1046. }
  1047. /**
  1048. * Check HTTP data transfer flow control window
  1049. *
  1050. * @v http HTTP request
  1051. * @ret len Length of window
  1052. */
  1053. static size_t http_xfer_window ( struct http_request *http ) {
  1054. /* New block commands may be issued only when we are idle */
  1055. return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 );
  1056. }
  1057. /**
  1058. * Initiate HTTP partial read
  1059. *
  1060. * @v http HTTP request
  1061. * @v partial Partial transfer interface
  1062. * @v offset Starting offset
  1063. * @v buffer Data buffer
  1064. * @v len Length
  1065. * @ret rc Return status code
  1066. */
  1067. static int http_partial_read ( struct http_request *http,
  1068. struct interface *partial,
  1069. size_t offset, userptr_t buffer, size_t len ) {
  1070. /* Sanity check */
  1071. if ( http_xfer_window ( http ) == 0 )
  1072. return -EBUSY;
  1073. /* Initialise partial transfer parameters */
  1074. http->rx_buffer = buffer;
  1075. http->partial_start = offset;
  1076. http->partial_len = len;
  1077. /* Schedule request */
  1078. http->rx_state = HTTP_RX_RESPONSE;
  1079. http->flags = ( HTTP_TX_PENDING | HTTP_CLIENT_KEEPALIVE );
  1080. if ( ! len )
  1081. http->flags |= HTTP_HEAD_ONLY;
  1082. process_add ( &http->process );
  1083. /* Attach to parent interface and return */
  1084. intf_plug_plug ( &http->partial, partial );
  1085. return 0;
  1086. }
  1087. /**
  1088. * Issue HTTP block device read
  1089. *
  1090. * @v http HTTP request
  1091. * @v block Block data interface
  1092. * @v lba Starting logical block address
  1093. * @v count Number of blocks to transfer
  1094. * @v buffer Data buffer
  1095. * @v len Length of data buffer
  1096. * @ret rc Return status code
  1097. */
  1098. static int http_block_read ( struct http_request *http,
  1099. struct interface *block,
  1100. uint64_t lba, unsigned int count,
  1101. userptr_t buffer, size_t len __unused ) {
  1102. return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ),
  1103. buffer, ( count * HTTP_BLKSIZE ) );
  1104. }
  1105. /**
  1106. * Read HTTP block device capacity
  1107. *
  1108. * @v http HTTP request
  1109. * @v block Block data interface
  1110. * @ret rc Return status code
  1111. */
  1112. static int http_block_read_capacity ( struct http_request *http,
  1113. struct interface *block ) {
  1114. return http_partial_read ( http, block, 0, 0, 0 );
  1115. }
  1116. /**
  1117. * Describe HTTP device in an ACPI table
  1118. *
  1119. * @v http HTTP request
  1120. * @v acpi ACPI table
  1121. * @v len Length of ACPI table
  1122. * @ret rc Return status code
  1123. */
  1124. static int http_acpi_describe ( struct http_request *http,
  1125. struct acpi_description_header *acpi,
  1126. size_t len ) {
  1127. DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
  1128. http );
  1129. ( void ) acpi;
  1130. ( void ) len;
  1131. return 0;
  1132. }
  1133. /** HTTP socket interface operations */
  1134. static struct interface_operation http_socket_operations[] = {
  1135. INTF_OP ( xfer_window, struct http_request *, http_socket_window ),
  1136. INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
  1137. INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
  1138. INTF_OP ( intf_close, struct http_request *, http_socket_close ),
  1139. };
  1140. /** HTTP socket interface descriptor */
  1141. static struct interface_descriptor http_socket_desc =
  1142. INTF_DESC_PASSTHRU ( struct http_request, socket,
  1143. http_socket_operations, xfer );
  1144. /** HTTP partial transfer interface operations */
  1145. static struct interface_operation http_partial_operations[] = {
  1146. INTF_OP ( intf_close, struct http_request *, http_close ),
  1147. };
  1148. /** HTTP partial transfer interface descriptor */
  1149. static struct interface_descriptor http_partial_desc =
  1150. INTF_DESC ( struct http_request, partial, http_partial_operations );
  1151. /** HTTP data transfer interface operations */
  1152. static struct interface_operation http_xfer_operations[] = {
  1153. INTF_OP ( xfer_window, struct http_request *, http_xfer_window ),
  1154. INTF_OP ( block_read, struct http_request *, http_block_read ),
  1155. INTF_OP ( block_read_capacity, struct http_request *,
  1156. http_block_read_capacity ),
  1157. INTF_OP ( intf_close, struct http_request *, http_close ),
  1158. INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ),
  1159. };
  1160. /** HTTP data transfer interface descriptor */
  1161. static struct interface_descriptor http_xfer_desc =
  1162. INTF_DESC_PASSTHRU ( struct http_request, xfer,
  1163. http_xfer_operations, socket );
  1164. /** HTTP process descriptor */
  1165. static struct process_descriptor http_process_desc =
  1166. PROC_DESC_ONCE ( struct http_request, process, http_step );
  1167. /**
  1168. * Initiate an HTTP connection, with optional filter
  1169. *
  1170. * @v xfer Data transfer interface
  1171. * @v uri Uniform Resource Identifier
  1172. * @v default_port Default port number
  1173. * @v filter Filter to apply to socket, or NULL
  1174. * @ret rc Return status code
  1175. */
  1176. int http_open_filter ( struct interface *xfer, struct uri *uri,
  1177. unsigned int default_port,
  1178. int ( * filter ) ( struct interface *xfer,
  1179. const char *name,
  1180. struct interface **next ) ) {
  1181. struct http_request *http;
  1182. int rc;
  1183. /* Sanity checks */
  1184. if ( ! uri->host )
  1185. return -EINVAL;
  1186. /* Allocate and populate HTTP structure */
  1187. http = zalloc ( sizeof ( *http ) );
  1188. if ( ! http )
  1189. return -ENOMEM;
  1190. ref_init ( &http->refcnt, http_free );
  1191. intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
  1192. intf_init ( &http->partial, &http_partial_desc, &http->refcnt );
  1193. http->uri = uri_get ( uri );
  1194. http->default_port = default_port;
  1195. http->filter = filter;
  1196. intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
  1197. process_init ( &http->process, &http_process_desc, &http->refcnt );
  1198. http->flags = HTTP_TX_PENDING;
  1199. /* Open socket */
  1200. if ( ( rc = http_socket_open ( http ) ) != 0 )
  1201. goto err;
  1202. /* Attach to parent interface, mortalise self, and return */
  1203. intf_plug_plug ( &http->xfer, xfer );
  1204. ref_put ( &http->refcnt );
  1205. return 0;
  1206. err:
  1207. DBGC ( http, "HTTP %p could not create request: %s\n",
  1208. http, strerror ( rc ) );
  1209. http_close ( http, rc );
  1210. ref_put ( &http->refcnt );
  1211. return rc;
  1212. }