]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Use Http11 definitions in HttpDxe and HttpBootDxe
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
CommitLineData
47f51a06
YT
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
90f658c4 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
47f51a06
YT
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "HttpDriver.h"\r
17\r
18/**\r
19 The common notify function used in HTTP driver. \r
20\r
21 @param[in] Event The event signaled.\r
22 @param[in] Context The context.\r
23\r
24**/\r
25VOID\r
26EFIAPI\r
27HttpCommonNotify (\r
28 IN EFI_EVENT Event,\r
29 IN VOID *Context\r
30 )\r
31{\r
32 if ((Event == NULL) || (Context == NULL)) {\r
33 return ;\r
34 }\r
35\r
36 *((BOOLEAN *) Context) = TRUE;\r
37}\r
38\r
39/**\r
b659408b 40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
47f51a06 41\r
47f51a06
YT
42 @param[in] Context The context.\r
43\r
44**/\r
45VOID\r
46EFIAPI\r
49c9f74c 47HttpTcpTransmitNotifyDpc (\r
47f51a06
YT
48 IN VOID *Context\r
49 )\r
50{\r
51 HTTP_TOKEN_WRAP *Wrap;\r
b659408b 52 HTTP_PROTOCOL *HttpInstance;\r
47f51a06 53\r
49c9f74c 54 if (Context == NULL) {\r
47f51a06
YT
55 return ;\r
56 }\r
b659408b
ZL
57 \r
58 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
59 HttpInstance = Wrap->HttpInstance;\r
60 \r
61 if (!HttpInstance->LocalAddressIsIPv6) {\r
62 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
63 gBS->SignalEvent (Wrap->HttpToken->Event);\r
64\r
65 //\r
66 // Free resources.\r
67 //\r
68 if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
69 FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
70 }\r
47f51a06 71\r
b659408b
ZL
72 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
73 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
74 }\r
75 \r
76 } else {\r
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
78 gBS->SignalEvent (Wrap->HttpToken->Event);\r
79 \r
80 //\r
81 // Free resources.\r
82 //\r
83 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
84 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
85 }\r
47f51a06 86\r
b659408b
ZL
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
89 } \r
47f51a06
YT
90 }\r
91\r
47f51a06
YT
92\r
93 Wrap->TcpWrap.IsTxDone = TRUE;\r
94\r
95 //\r
96 // Check pending TxTokens and sent out.\r
97 //\r
98 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);\r
99\r
100}\r
101\r
49c9f74c
FS
102/**\r
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.\r
104\r
105 @param Event The receive event delivered to TCP for transmit.\r
106 @param Context Context for the callback.\r
107\r
108**/\r
109VOID\r
110EFIAPI\r
111HttpTcpTransmitNotify (\r
112 IN EFI_EVENT Event,\r
113 IN VOID *Context\r
114 )\r
115{\r
116 //\r
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
118 //\r
119 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
120}\r
121\r
47f51a06 122/**\r
b659408b 123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
47f51a06 124\r
47f51a06
YT
125 @param[in] Context The context.\r
126\r
127**/\r
128VOID\r
129EFIAPI\r
49c9f74c 130HttpTcpReceiveNotifyDpc (\r
47f51a06
YT
131 IN VOID *Context\r
132 )\r
133{\r
134 HTTP_TOKEN_WRAP *Wrap;\r
135 NET_MAP_ITEM *Item;\r
136 UINTN Length;\r
137 EFI_STATUS Status;\r
138 HTTP_PROTOCOL *HttpInstance;\r
b659408b 139 BOOLEAN UsingIpv6;\r
47f51a06 140\r
49c9f74c 141 if (Context == NULL) {\r
47f51a06
YT
142 return ;\r
143 }\r
144\r
145 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
47f51a06 146 HttpInstance = Wrap->HttpInstance;\r
b659408b
ZL
147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
148 \r
149 if (UsingIpv6) {\r
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
151 \r
152 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
621a618a
ZL
153 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
154 gBS->SignalEvent (Wrap->HttpToken->Event);\r
155 FreePool (Wrap);\r
b659408b
ZL
156 return ;\r
157 }\r
158\r
159 } else {\r
160 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
161 \r
162 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
621a618a
ZL
163 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
164 gBS->SignalEvent (Wrap->HttpToken->Event);\r
165 FreePool (Wrap);\r
b659408b
ZL
166 return ;\r
167 }\r
168 }\r
47f51a06
YT
169\r
170 //\r
171 // Check whether we receive a complete HTTP message.\r
172 //\r
173 ASSERT (HttpInstance->MsgParser != NULL);\r
b659408b
ZL
174 if (UsingIpv6) {\r
175 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
176 } else {\r
177 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
178 }\r
47f51a06 179\r
47f51a06
YT
180 Status = HttpParseMessageBody (\r
181 HttpInstance->MsgParser,\r
182 Length,\r
183 Wrap->HttpToken->Message->Body\r
184 );\r
185 if (EFI_ERROR (Status)) {\r
186 return ;\r
187 }\r
188\r
189 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {\r
190 //\r
191 // Free the MsgParse since we already have a full HTTP message.\r
192 //\r
193 HttpFreeMsgParser (HttpInstance->MsgParser);\r
194 HttpInstance->MsgParser = NULL;\r
195 }\r
196\r
197 Wrap->HttpToken->Message->BodyLength = Length;\r
198 ASSERT (HttpInstance->CacheBody == NULL);\r
199 //\r
200 // We receive part of header of next HTTP msg.\r
201 //\r
202 if (HttpInstance->NextMsg != NULL) {\r
203 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg - \r
204 (CHAR8 *) Wrap->HttpToken->Message->Body;\r
205 HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;\r
206 if (HttpInstance->CacheLen != 0) {\r
207 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);\r
208 if (HttpInstance->CacheBody == NULL) {\r
209 return ;\r
210 }\r
211 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);\r
212 HttpInstance->NextMsg = HttpInstance->CacheBody;\r
213 HttpInstance->CacheOffset = 0;\r
214 }\r
215 }\r
216\r
217 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);\r
218 if (Item != NULL) {\r
219 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
220 }\r
221\r
222\r
223 Wrap->TcpWrap.IsRxDone = TRUE;\r
b659408b
ZL
224 if (UsingIpv6) {\r
225 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
226 } else {\r
227 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
228 }\r
229 \r
47f51a06
YT
230\r
231 gBS->SignalEvent (Wrap->HttpToken->Event);\r
232\r
233 //\r
234 // Check pending RxTokens and receive the HTTP message.\r
235 //\r
236 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
237 \r
238 FreePool (Wrap);\r
239}\r
240\r
49c9f74c
FS
241/**\r
242 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.\r
243\r
244 @param Event The receive event delivered to TCP for receive.\r
245 @param Context Context for the callback.\r
246\r
247**/\r
248VOID\r
249EFIAPI\r
250HttpTcpReceiveNotify (\r
251 IN EFI_EVENT Event,\r
252 IN VOID *Context\r
253 )\r
254{\r
255 //\r
256 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
257 //\r
258 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
259}\r
260\r
47f51a06 261/**\r
b659408b 262 Create events for the TCP connection token and TCP close token.\r
47f51a06
YT
263\r
264 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
265\r
266 @retval EFI_SUCCESS The events are created successfully.\r
267 @retval others Other error as indicated.\r
268\r
269**/\r
270EFI_STATUS\r
b659408b 271HttpCreateTcpConnCloseEvent (\r
47f51a06
YT
272 IN HTTP_PROTOCOL *HttpInstance\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
b659408b
ZL
276\r
277 if (!HttpInstance->LocalAddressIsIPv6) {\r
47f51a06
YT
278 //\r
279 // Create events for variuos asynchronous operations.\r
280 //\r
281 Status = gBS->CreateEvent (\r
282 EVT_NOTIFY_SIGNAL,\r
283 TPL_NOTIFY,\r
284 HttpCommonNotify,\r
b659408b
ZL
285 &HttpInstance->IsTcp4ConnDone,\r
286 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
47f51a06
YT
287 );\r
288 if (EFI_ERROR (Status)) {\r
289 goto ERROR;\r
290 }\r
291\r
292 //\r
b659408b
ZL
293 // Initialize Tcp4CloseToken\r
294 //\r
295 Status = gBS->CreateEvent (\r
296 EVT_NOTIFY_SIGNAL,\r
297 TPL_NOTIFY,\r
298 HttpCommonNotify,\r
299 &HttpInstance->IsTcp4CloseDone,\r
300 &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
301 );\r
302 if (EFI_ERROR (Status)) {\r
303 goto ERROR;\r
304 }\r
305 \r
306 } else {\r
307 //\r
308 // Create events for variuos asynchronous operations.\r
47f51a06
YT
309 //\r
310 Status = gBS->CreateEvent (\r
311 EVT_NOTIFY_SIGNAL,\r
312 TPL_NOTIFY,\r
313 HttpCommonNotify,\r
b659408b
ZL
314 &HttpInstance->IsTcp6ConnDone,\r
315 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
47f51a06
YT
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 goto ERROR;\r
319 }\r
320\r
b659408b
ZL
321 //\r
322 // Initialize Tcp6CloseToken\r
323 //\r
324 Status = gBS->CreateEvent (\r
325 EVT_NOTIFY_SIGNAL,\r
326 TPL_NOTIFY,\r
327 HttpCommonNotify,\r
328 &HttpInstance->IsTcp6CloseDone,\r
329 &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
330 );\r
331 if (EFI_ERROR (Status)) {\r
332 goto ERROR;\r
333 }\r
334 }\r
335 \r
47f51a06
YT
336 return EFI_SUCCESS;\r
337\r
338ERROR:\r
339 //\r
340 // Error handling\r
341 //\r
b659408b 342 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
343\r
344 return Status;\r
345}\r
346\r
347\r
348/**\r
b659408b 349 Close events in the TCP connection token and TCP close token.\r
47f51a06
YT
350\r
351 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
352\r
353**/\r
354VOID\r
b659408b 355HttpCloseTcpConnCloseEvent (\r
47f51a06
YT
356 IN HTTP_PROTOCOL *HttpInstance\r
357 )\r
358{\r
359 ASSERT (HttpInstance != NULL);\r
360\r
b659408b
ZL
361 if (HttpInstance->LocalAddressIsIPv6) {\r
362 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
363 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
364 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
365 }\r
47f51a06 366\r
b659408b
ZL
367 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
368 gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
369 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
370 }\r
371\r
372 } else {\r
373 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
374 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
375 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
376 }\r
377\r
378 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
379 gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
380 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
381 }\r
382 }\r
383 \r
47f51a06
YT
384}\r
385\r
386/**\r
b659408b 387 Create event for the TCP transmit token.\r
47f51a06
YT
388\r
389 @param[in] Wrap Point to HTTP token's wrap data.\r
390\r
391 @retval EFI_SUCCESS The events is created successfully.\r
392 @retval others Other error as indicated.\r
393\r
394**/\r
395EFI_STATUS\r
b659408b 396HttpCreateTcpTxEvent (\r
47f51a06
YT
397 IN HTTP_TOKEN_WRAP *Wrap\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
b659408b 401 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
402 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
403\r
b659408b 404 HttpInstance = Wrap->HttpInstance;\r
47f51a06
YT
405 TcpWrap = &Wrap->TcpWrap;\r
406\r
b659408b
ZL
407 if (!HttpInstance->LocalAddressIsIPv6) {\r
408 Status = gBS->CreateEvent (\r
409 EVT_NOTIFY_SIGNAL,\r
410 TPL_NOTIFY,\r
411 HttpTcpTransmitNotify,\r
412 Wrap,\r
413 &TcpWrap->Tx4Token.CompletionToken.Event\r
414 );\r
415 if (EFI_ERROR (Status)) {\r
416 return Status;\r
417 }\r
418 \r
419 TcpWrap->Tx4Data.Push = TRUE;\r
420 TcpWrap->Tx4Data.Urgent = FALSE;\r
421 TcpWrap->Tx4Data.FragmentCount = 1;\r
422 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
423 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 424\r
b659408b
ZL
425 } else {\r
426 Status = gBS->CreateEvent (\r
427 EVT_NOTIFY_SIGNAL,\r
428 TPL_NOTIFY,\r
429 HttpTcpTransmitNotify,\r
430 Wrap,\r
431 &TcpWrap->Tx6Token.CompletionToken.Event\r
432 );\r
433 if (EFI_ERROR (Status)) {\r
434 return Status;\r
435 }\r
47f51a06 436\r
b659408b
ZL
437 TcpWrap->Tx6Data.Push = TRUE;\r
438 TcpWrap->Tx6Data.Urgent = FALSE;\r
439 TcpWrap->Tx6Data.FragmentCount = 1;\r
440 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
441 TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
442 \r
443 \r
444 }\r
445 \r
47f51a06
YT
446 return EFI_SUCCESS;\r
447}\r
448\r
449/**\r
b659408b 450 Create event for the TCP receive token which is used to receive HTTP header.\r
47f51a06
YT
451\r
452 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
453\r
454 @retval EFI_SUCCESS The events is created successfully.\r
455 @retval others Other error as indicated.\r
456\r
457**/\r
458EFI_STATUS\r
b659408b 459HttpCreateTcpRxEventForHeader (\r
47f51a06
YT
460 IN HTTP_PROTOCOL *HttpInstance\r
461 )\r
462{\r
463 EFI_STATUS Status;\r
464\r
b659408b
ZL
465 if (!HttpInstance->LocalAddressIsIPv6) {\r
466 Status = gBS->CreateEvent (\r
467 EVT_NOTIFY_SIGNAL,\r
468 TPL_NOTIFY,\r
469 HttpCommonNotify,\r
470 &HttpInstance->IsRxDone,\r
471 &HttpInstance->Rx4Token.CompletionToken.Event\r
472 );\r
473 if (EFI_ERROR (Status)) {\r
474 return Status;\r
475 }\r
476 \r
477 HttpInstance->Rx4Data.FragmentCount = 1;\r
478 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
479 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 480\r
b659408b
ZL
481 } else {\r
482 Status = gBS->CreateEvent (\r
483 EVT_NOTIFY_SIGNAL,\r
484 TPL_NOTIFY,\r
485 HttpCommonNotify,\r
486 &HttpInstance->IsRxDone,\r
487 &HttpInstance->Rx6Token.CompletionToken.Event\r
488 );\r
489 if (EFI_ERROR (Status)) {\r
490 return Status;\r
491 }\r
492\r
493 HttpInstance->Rx6Data.FragmentCount =1;\r
494 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
495 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
496 \r
47f51a06
YT
497 }\r
498\r
47f51a06
YT
499\r
500 return EFI_SUCCESS;\r
501}\r
502\r
503/**\r
b659408b 504 Create event for the TCP receive token which is used to receive HTTP body.\r
47f51a06
YT
505\r
506 @param[in] Wrap Point to HTTP token's wrap data.\r
507\r
508 @retval EFI_SUCCESS The events is created successfully.\r
509 @retval others Other error as indicated.\r
510\r
511**/\r
512EFI_STATUS\r
b659408b 513HttpCreateTcpRxEvent (\r
47f51a06
YT
514 IN HTTP_TOKEN_WRAP *Wrap \r
515 )\r
516{\r
517 EFI_STATUS Status;\r
b659408b 518 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
519 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
520\r
b659408b 521 HttpInstance = Wrap->HttpInstance;\r
47f51a06 522 TcpWrap = &Wrap->TcpWrap;\r
b659408b
ZL
523 if (!HttpInstance->LocalAddressIsIPv6) {\r
524 Status = gBS->CreateEvent (\r
525 EVT_NOTIFY_SIGNAL,\r
526 TPL_NOTIFY,\r
527 HttpTcpReceiveNotify,\r
528 Wrap,\r
529 &TcpWrap->Rx4Token.CompletionToken.Event\r
530 );\r
531 if (EFI_ERROR (Status)) {\r
532 return Status;\r
533 }\r
534 \r
535 TcpWrap->Rx4Data.FragmentCount = 1;\r
536 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
537 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 538\r
b659408b
ZL
539 } else {\r
540 Status = gBS->CreateEvent (\r
541 EVT_NOTIFY_SIGNAL,\r
542 TPL_NOTIFY,\r
543 HttpTcpReceiveNotify,\r
544 Wrap,\r
545 &TcpWrap->Rx6Token.CompletionToken.Event\r
546 ); \r
547 if (EFI_ERROR (Status)) {\r
548 return Status;\r
549 }\r
550\r
551 TcpWrap->Rx6Data.FragmentCount = 1;\r
552 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
553 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 554 }\r
b659408b
ZL
555 \r
556 return EFI_SUCCESS;\r
557}\r
47f51a06 558\r
b659408b
ZL
559/**\r
560 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
47f51a06 561\r
b659408b
ZL
562 @param[in] Wrap Pointer to HTTP token's wrap data.\r
563 \r
564**/\r
565VOID\r
566HttpCloseTcpRxEvent (\r
567 IN HTTP_TOKEN_WRAP *Wrap\r
568 )\r
569{\r
570 HTTP_PROTOCOL *HttpInstance;\r
b659408b 571\r
1b96428d 572 ASSERT (Wrap != NULL);\r
b659408b 573 HttpInstance = Wrap->HttpInstance;\r
b659408b
ZL
574 \r
575 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
576 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
577 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
b659408b
ZL
578 }\r
579\r
580 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
581 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
582 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
583 }\r
584 } else {\r
1b96428d
ZL
585 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
586 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b
ZL
587 }\r
588 \r
589 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
590 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
591 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
592 }\r
593 }\r
47f51a06
YT
594}\r
595\r
596/**\r
597 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
598\r
47f51a06 599 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
b659408b 600 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
47f51a06
YT
601\r
602 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. \r
603 @retval Others Other error as indicated.\r
604\r
605**/\r
606EFI_STATUS\r
607HttpInitProtocol (\r
b659408b
ZL
608 IN OUT HTTP_PROTOCOL *HttpInstance,\r
609 IN BOOLEAN IpVersion\r
47f51a06
YT
610 )\r
611{\r
612 EFI_STATUS Status;\r
613 VOID *Interface;\r
b659408b
ZL
614 BOOLEAN UsingIpv6;\r
615 \r
616 ASSERT (HttpInstance != NULL);\r
617 UsingIpv6 = IpVersion;\r
618 \r
619 if (!UsingIpv6) {\r
620 //\r
621 // Create TCP4 child.\r
622 //\r
623 Status = NetLibCreateServiceChild (\r
624 HttpInstance->Service->ControllerHandle,\r
625 HttpInstance->Service->ImageHandle,\r
626 &gEfiTcp4ServiceBindingProtocolGuid,\r
627 &HttpInstance->Tcp4ChildHandle\r
628 );\r
47f51a06 629\r
b659408b
ZL
630 if (EFI_ERROR (Status)) {\r
631 goto ON_ERROR;\r
632 }\r
47f51a06 633\r
b659408b
ZL
634 Status = gBS->OpenProtocol (\r
635 HttpInstance->Tcp4ChildHandle,\r
636 &gEfiTcp4ProtocolGuid,\r
637 (VOID **) &Interface,\r
638 HttpInstance->Service->ImageHandle,\r
639 HttpInstance->Service->ControllerHandle,\r
640 EFI_OPEN_PROTOCOL_BY_DRIVER\r
641 );\r
642 \r
643 if (EFI_ERROR (Status)) {\r
644 goto ON_ERROR;\r
645 }\r
47f51a06 646\r
b659408b
ZL
647 Status = gBS->OpenProtocol (\r
648 HttpInstance->Tcp4ChildHandle,\r
649 &gEfiTcp4ProtocolGuid,\r
650 (VOID **) &HttpInstance->Tcp4,\r
651 HttpInstance->Service->ImageHandle,\r
652 HttpInstance->Handle,\r
653 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
654 );\r
655 if (EFI_ERROR(Status)) {\r
656 goto ON_ERROR;\r
657 }\r
47f51a06 658\r
b659408b
ZL
659 Status = gBS->OpenProtocol (\r
660 HttpInstance->Service->Tcp4ChildHandle,\r
661 &gEfiTcp4ProtocolGuid,\r
662 (VOID **) &Interface,\r
663 HttpInstance->Service->ImageHandle,\r
664 HttpInstance->Handle,\r
665 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
666 );\r
667 if (EFI_ERROR(Status)) {\r
668 goto ON_ERROR;\r
669 }\r
670 } else {\r
671 //\r
672 // Create TCP6 Child.\r
673 //\r
674 Status = NetLibCreateServiceChild (\r
675 HttpInstance->Service->ControllerHandle,\r
676 HttpInstance->Service->ImageHandle,\r
677 &gEfiTcp6ServiceBindingProtocolGuid,\r
678 &HttpInstance->Tcp6ChildHandle\r
679 );\r
47f51a06 680\r
b659408b
ZL
681 if (EFI_ERROR (Status)) {\r
682 goto ON_ERROR;\r
683 }\r
47f51a06 684\r
b659408b
ZL
685 Status = gBS->OpenProtocol (\r
686 HttpInstance->Tcp6ChildHandle,\r
687 &gEfiTcp6ProtocolGuid,\r
688 (VOID **) &Interface,\r
689 HttpInstance->Service->ImageHandle,\r
690 HttpInstance->Service->ControllerHandle,\r
691 EFI_OPEN_PROTOCOL_BY_DRIVER\r
692 );\r
693 \r
694 if (EFI_ERROR (Status)) {\r
695 goto ON_ERROR;\r
696 }\r
697\r
698 Status = gBS->OpenProtocol (\r
699 HttpInstance->Tcp6ChildHandle,\r
700 &gEfiTcp6ProtocolGuid,\r
701 (VOID **) &HttpInstance->Tcp6,\r
702 HttpInstance->Service->ImageHandle,\r
703 HttpInstance->Handle,\r
704 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
705 );\r
706 \r
707 if (EFI_ERROR(Status)) {\r
708 goto ON_ERROR;\r
709 } \r
710\r
711 Status = gBS->OpenProtocol (\r
712 HttpInstance->Service->Tcp6ChildHandle,\r
713 &gEfiTcp6ProtocolGuid,\r
714 (VOID **) &Interface,\r
715 HttpInstance->Service->ImageHandle,\r
716 HttpInstance->Handle,\r
717 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
718 );\r
47f51a06 719\r
b659408b
ZL
720 if (EFI_ERROR(Status)) {\r
721 goto ON_ERROR;\r
722 }\r
723 }\r
724 \r
51b0450e
FS
725 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
726 if (HttpInstance->Url == NULL) {\r
727 Status = EFI_OUT_OF_RESOURCES;\r
728 goto ON_ERROR;\r
729 }\r
730\r
47f51a06
YT
731 return EFI_SUCCESS;\r
732\r
733ON_ERROR:\r
734 \r
b659408b 735 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 736 gBS->CloseProtocol (\r
b659408b 737 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
738 &gEfiTcp4ProtocolGuid,\r
739 HttpInstance->Service->ImageHandle,\r
740 HttpInstance->Service->ControllerHandle\r
741 );\r
742\r
743 gBS->CloseProtocol (\r
b659408b 744 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
745 &gEfiTcp4ProtocolGuid,\r
746 HttpInstance->Service->ImageHandle,\r
747 HttpInstance->Handle\r
b659408b 748 ); \r
47f51a06
YT
749 \r
750 NetLibDestroyServiceChild (\r
751 HttpInstance->Service->ControllerHandle,\r
752 HttpInstance->Service->ImageHandle,\r
753 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 754 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
755 );\r
756 }\r
b659408b
ZL
757 \r
758 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
759 gBS->CloseProtocol (\r
760 HttpInstance->Service->Tcp4ChildHandle,\r
761 &gEfiTcp4ProtocolGuid,\r
762 HttpInstance->Service->ImageHandle,\r
763 HttpInstance->Handle\r
764 );\r
765 }\r
766 \r
767 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
768 gBS->CloseProtocol (\r
769 HttpInstance->Tcp6ChildHandle,\r
770 &gEfiTcp6ProtocolGuid,\r
771 HttpInstance->Service->ImageHandle,\r
772 HttpInstance->Service->ControllerHandle\r
773 );\r
47f51a06 774\r
b659408b
ZL
775 gBS->CloseProtocol (\r
776 HttpInstance->Tcp6ChildHandle,\r
777 &gEfiTcp6ProtocolGuid,\r
778 HttpInstance->Service->ImageHandle,\r
779 HttpInstance->Handle\r
780 );\r
781 \r
782 NetLibDestroyServiceChild (\r
783 HttpInstance->Service->ControllerHandle,\r
784 HttpInstance->Service->ImageHandle,\r
785 &gEfiTcp6ServiceBindingProtocolGuid,\r
786 HttpInstance->Tcp6ChildHandle\r
787 );\r
788 }\r
789 \r
790 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
791 gBS->CloseProtocol (\r
792 HttpInstance->Service->Tcp6ChildHandle,\r
793 &gEfiTcp6ProtocolGuid,\r
794 HttpInstance->Service->ImageHandle,\r
795 HttpInstance->Handle\r
796 );\r
797 }\r
798\r
799 return EFI_UNSUPPORTED;\r
47f51a06
YT
800 \r
801}\r
802\r
803/**\r
804 Clean up the HTTP child, release all the resources used by it.\r
805\r
806 @param[in] HttpInstance The HTTP child to clean up.\r
807\r
808**/\r
809VOID\r
810HttpCleanProtocol (\r
811 IN HTTP_PROTOCOL *HttpInstance\r
812 )\r
813{\r
814 HttpCloseConnection (HttpInstance);\r
815 \r
b659408b 816 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
817\r
818 if (HttpInstance->CacheBody != NULL) {\r
819 FreePool (HttpInstance->CacheBody);\r
820 HttpInstance->CacheBody = NULL;\r
821 HttpInstance->NextMsg = NULL;\r
822 }\r
823\r
824 if (HttpInstance->RemoteHost != NULL) {\r
825 FreePool (HttpInstance->RemoteHost);\r
826 HttpInstance->RemoteHost = NULL;\r
827 }\r
828\r
829 if (HttpInstance->MsgParser != NULL) {\r
830 HttpFreeMsgParser (HttpInstance->MsgParser);\r
831 HttpInstance->MsgParser = NULL;\r
832 }\r
b659408b 833 \r
51b0450e
FS
834 if (HttpInstance->Url != NULL) {\r
835 FreePool (HttpInstance->Url);\r
836 HttpInstance->Url = NULL;\r
837 }\r
b659408b 838 \r
47f51a06
YT
839 NetMapClean (&HttpInstance->TxTokens);\r
840 NetMapClean (&HttpInstance->RxTokens);\r
841\r
b659408b 842 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 843 gBS->CloseProtocol (\r
b659408b 844 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
845 &gEfiTcp4ProtocolGuid,\r
846 HttpInstance->Service->ImageHandle,\r
847 HttpInstance->Service->ControllerHandle\r
848 );\r
849\r
850 gBS->CloseProtocol (\r
b659408b 851 HttpInstance->Tcp4ChildHandle,\r
47f51a06
YT
852 &gEfiTcp4ProtocolGuid,\r
853 HttpInstance->Service->ImageHandle,\r
854 HttpInstance->Handle\r
855 );\r
856 \r
857 NetLibDestroyServiceChild (\r
858 HttpInstance->Service->ControllerHandle,\r
859 HttpInstance->Service->ImageHandle,\r
860 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 861 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
862 );\r
863 }\r
b659408b
ZL
864\r
865 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
866 gBS->CloseProtocol (\r
867 HttpInstance->Service->Tcp4ChildHandle,\r
868 &gEfiTcp4ProtocolGuid,\r
869 HttpInstance->Service->ImageHandle,\r
870 HttpInstance->Handle\r
871 );\r
872 } \r
873\r
874 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
875 gBS->CloseProtocol (\r
876 HttpInstance->Tcp6ChildHandle,\r
877 &gEfiTcp6ProtocolGuid,\r
878 HttpInstance->Service->ImageHandle,\r
879 HttpInstance->Service->ControllerHandle\r
880 );\r
881\r
882 gBS->CloseProtocol (\r
883 HttpInstance->Tcp6ChildHandle,\r
884 &gEfiTcp6ProtocolGuid,\r
885 HttpInstance->Service->ImageHandle,\r
886 HttpInstance->Handle\r
887 );\r
888 \r
889 NetLibDestroyServiceChild (\r
890 HttpInstance->Service->ControllerHandle,\r
891 HttpInstance->Service->ImageHandle,\r
892 &gEfiTcp6ServiceBindingProtocolGuid,\r
893 HttpInstance->Tcp6ChildHandle\r
894 );\r
895 }\r
896 \r
897 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
898 gBS->CloseProtocol (\r
899 HttpInstance->Service->Tcp6ChildHandle,\r
900 &gEfiTcp6ProtocolGuid,\r
901 HttpInstance->Service->ImageHandle,\r
902 HttpInstance->Handle\r
903 );\r
904 }\r
905 \r
47f51a06
YT
906}\r
907\r
908/**\r
909 Establish TCP connection with HTTP server.\r
910\r
911 @param[in] HttpInstance The HTTP instance private data.\r
912\r
913 @retval EFI_SUCCESS The TCP connection is established.\r
914 @retval Others Other error as indicated.\r
915\r
916**/\r
917EFI_STATUS\r
918HttpCreateConnection (\r
919 IN HTTP_PROTOCOL *HttpInstance\r
920 )\r
921{\r
922 EFI_STATUS Status;\r
923\r
47f51a06
YT
924 //\r
925 // Connect to Http server\r
926 //\r
b659408b
ZL
927 if (!HttpInstance->LocalAddressIsIPv6) {\r
928 HttpInstance->IsTcp4ConnDone = FALSE;\r
929 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
930 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
931 if (EFI_ERROR (Status)) {\r
932 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
933 return Status;\r
934 }\r
935 \r
936 while (!HttpInstance->IsTcp4ConnDone) {\r
937 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
938 }\r
939 \r
940 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
941 \r
942 } else {\r
943 HttpInstance->IsTcp6ConnDone = FALSE;\r
944 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
945 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
946 if (EFI_ERROR (Status)) {\r
947 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
948 return Status;\r
949 }\r
47f51a06 950\r
b659408b
ZL
951 while(!HttpInstance->IsTcp6ConnDone) {\r
952 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
953 }\r
47f51a06 954\r
b659408b
ZL
955 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
956 }\r
957 \r
47f51a06
YT
958 if (!EFI_ERROR (Status)) {\r
959 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
960 }\r
961\r
962 return Status;\r
963}\r
964\r
965/**\r
966 Close existing TCP connection.\r
967\r
968 @param[in] HttpInstance The HTTP instance private data.\r
969\r
970 @retval EFI_SUCCESS The TCP connection is closed.\r
971 @retval Others Other error as indicated.\r
972\r
973**/\r
974EFI_STATUS\r
975HttpCloseConnection (\r
976 IN HTTP_PROTOCOL *HttpInstance\r
977 )\r
978{\r
979 EFI_STATUS Status;\r
980\r
374ecd04 981 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
47f51a06 982\r
b659408b
ZL
983 if (HttpInstance->LocalAddressIsIPv6) {\r
984 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
985 HttpInstance->IsTcp6CloseDone = FALSE;\r
986 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
987 if (EFI_ERROR (Status)) {\r
988 return Status;\r
989 }\r
990\r
991 while (!HttpInstance->IsTcp6CloseDone) {\r
992 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
993 }\r
994 \r
995 } else {\r
996 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
997 HttpInstance->IsTcp4CloseDone = FALSE;\r
998 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
999 if (EFI_ERROR (Status)) {\r
1000 return Status;\r
1001 }\r
1002\r
1003 while (!HttpInstance->IsTcp4CloseDone) {\r
1004 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1005 }\r
374ecd04 1006 }\r
b659408b 1007\r
47f51a06
YT
1008 }\r
1009\r
1010 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1011 return EFI_SUCCESS;\r
47f51a06
YT
1012}\r
1013\r
1014/**\r
1015 Configure TCP4 protocol child.\r
1016\r
1017 @param[in] HttpInstance The HTTP instance private data.\r
1018 @param[in] Wrap The HTTP token's wrap data.\r
1019\r
1020 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1021 @retval Others Other error as indicated.\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025HttpConfigureTcp4 (\r
1026 IN HTTP_PROTOCOL *HttpInstance,\r
1027 IN HTTP_TOKEN_WRAP *Wrap\r
1028 )\r
1029{\r
1030 EFI_STATUS Status;\r
1031 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1032 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1033 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1034\r
1035 ASSERT (HttpInstance != NULL);\r
47f51a06
YT
1036\r
1037\r
1038 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1039 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1040 \r
1041 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1042 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1043 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1044\r
1045 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1046 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1047 if (!Tcp4AP->UseDefaultAddress) {\r
1048 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1049 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1050 }\r
1051 \r
1052 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1053 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1054 Tcp4AP->ActiveFlag = TRUE;\r
1055 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1056\r
1057 Tcp4Option = Tcp4CfgData->ControlOption;\r
1058 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1059 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1060 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1061 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1062 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1063 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1064 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1065 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1066 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1067 Tcp4Option->EnableNagle = TRUE;\r
1068 Tcp4CfgData->ControlOption = Tcp4Option;\r
1069\r
1070 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1071 if (EFI_ERROR (Status)) {\r
1072 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1073 return Status;\r
1074 }\r
1075\r
b659408b
ZL
1076 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1077 if (EFI_ERROR (Status)) {\r
1078 return Status;\r
1079 }\r
1080\r
1081 Status = HttpCreateTcpTxEvent (Wrap);\r
1082 if (EFI_ERROR (Status)) {\r
1083 return Status;\r
1084 }\r
1085\r
1086 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1087\r
1088 return EFI_SUCCESS;\r
1089}\r
1090\r
1091/**\r
1092 Configure TCP6 protocol child.\r
1093\r
1094 @param[in] HttpInstance The HTTP instance private data.\r
1095 @param[in] Wrap The HTTP token's wrap data.\r
1096\r
1097 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1098 @retval Others Other error as indicated.\r
1099\r
1100**/\r
1101EFI_STATUS\r
1102HttpConfigureTcp6 (\r
1103 IN HTTP_PROTOCOL *HttpInstance,\r
1104 IN HTTP_TOKEN_WRAP *Wrap\r
1105 )\r
1106{\r
1107 EFI_STATUS Status;\r
1108 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1109 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1110 EFI_TCP6_OPTION *Tcp6Option;\r
1111 \r
1112 ASSERT (HttpInstance != NULL);\r
1113 \r
1114 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1115 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1116\r
1117 Tcp6CfgData->TrafficClass = 0;\r
1118 Tcp6CfgData->HopLimit = 255;\r
1119 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
1120 \r
1121 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1122 Tcp6Ap->ActiveFlag = TRUE;\r
1123 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1124 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1125 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1126 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1127\r
1128 Tcp6Option = Tcp6CfgData->ControlOption;\r
1129 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1130 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1131 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1132 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1133 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1134 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1135 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1136 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1137 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1138 Tcp6Option->EnableNagle = TRUE;\r
1139\r
1140 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1141 if (EFI_ERROR (Status)) {\r
1142 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1143 return Status;\r
1144 }\r
1145 \r
1146 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1147 if (EFI_ERROR (Status)) {\r
1148 return Status;\r
1149 }\r
1150\r
b659408b 1151 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1152 if (EFI_ERROR (Status)) {\r
1153 return Status;\r
1154 }\r
1155\r
1156 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1157\r
1158 return EFI_SUCCESS;\r
b659408b 1159 \r
47f51a06
YT
1160}\r
1161\r
1162/**\r
b659408b 1163 Check existing TCP connection, if in error state, recover TCP4 connection.\r
47f51a06
YT
1164\r
1165 @param[in] HttpInstance The HTTP instance private data.\r
1166\r
1167 @retval EFI_SUCCESS The TCP connection is established.\r
1168 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1169 @retval Others Other error as indicated.\r
1170\r
1171**/\r
1172EFI_STATUS\r
1173HttpConnectTcp4 (\r
1174 IN HTTP_PROTOCOL *HttpInstance\r
1175 )\r
1176{\r
1177 EFI_STATUS Status;\r
1178 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1179\r
1180\r
a2e61982 1181 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
47f51a06
YT
1182 return EFI_NOT_READY;\r
1183 }\r
1184\r
1185 Status = HttpInstance->Tcp4->GetModeData(\r
1186 HttpInstance->Tcp4, \r
1187 &Tcp4State, \r
1188 NULL,\r
1189 NULL,\r
1190 NULL,\r
1191 NULL\r
1192 );\r
1193 if (EFI_ERROR(Status)){\r
1194 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1195 return Status;\r
1196 }\r
1197\r
a2e61982
ZL
1198 if (Tcp4State == Tcp4StateEstablished) {\r
1199 return EFI_SUCCESS;\r
1200 } else if (Tcp4State > Tcp4StateEstablished ) {\r
47f51a06 1201 HttpCloseConnection(HttpInstance);\r
a2e61982 1202 }\r
47f51a06
YT
1203\r
1204 return HttpCreateConnection (HttpInstance);\r
1205}\r
1206\r
1207/**\r
b659408b
ZL
1208 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1209\r
1210 @param[in] HttpInstance The HTTP instance private data.\r
1211\r
1212 @retval EFI_SUCCESS The TCP connection is established.\r
1213 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1214 @retval Others Other error as indicated.\r
1215\r
1216**/\r
1217EFI_STATUS\r
1218HttpConnectTcp6 (\r
1219 IN HTTP_PROTOCOL *HttpInstance\r
1220 )\r
1221{\r
1222 EFI_STATUS Status;\r
1223 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1224\r
a2e61982 1225 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
b659408b
ZL
1226 return EFI_NOT_READY;\r
1227 }\r
1228\r
1229 Status = HttpInstance->Tcp6->GetModeData (\r
1230 HttpInstance->Tcp6,\r
1231 &Tcp6State,\r
1232 NULL,\r
1233 NULL,\r
1234 NULL,\r
1235 NULL\r
1236 );\r
1237 \r
1238 if (EFI_ERROR(Status)){\r
1239 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1240 return Status;\r
1241 }\r
1242\r
a2e61982
ZL
1243 if (Tcp6State == Tcp6StateEstablished) {\r
1244 return EFI_SUCCESS;\r
1245 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1246 HttpCloseConnection(HttpInstance);\r
b659408b
ZL
1247 }\r
1248\r
1249 return HttpCreateConnection (HttpInstance);\r
1250}\r
1251\r
1252/**\r
1253 Initialize TCP related data.\r
1254\r
1255 @param[in] HttpInstance The HTTP instance private data.\r
1256 @param[in] Wrap The HTTP token's wrap data.\r
a2e61982 1257 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.\r
b659408b
ZL
1258\r
1259 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1260 @retval Others Other error as indicated.\r
1261\r
1262**/\r
1263EFI_STATUS\r
1264HttpInitTcp (\r
1265 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982
ZL
1266 IN HTTP_TOKEN_WRAP *Wrap,\r
1267 IN BOOLEAN Configure\r
b659408b
ZL
1268 )\r
1269{\r
1270 EFI_STATUS Status;\r
1271 ASSERT (HttpInstance != NULL);\r
1272\r
1273 if (!HttpInstance->LocalAddressIsIPv6) {\r
1274 //\r
1275 // Configure TCP instance.\r
1276 //\r
a2e61982
ZL
1277 if (Configure) {\r
1278 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1279 if (EFI_ERROR (Status)) {\r
1280 return Status;\r
1281 }\r
b659408b 1282 }\r
a2e61982 1283\r
b659408b
ZL
1284 //\r
1285 // Connect TCP.\r
1286 //\r
1287 Status = HttpConnectTcp4 (HttpInstance);\r
1288 if (EFI_ERROR (Status)) {\r
1289 return Status;\r
1290 }\r
1291 } else {\r
1292 //\r
1293 // Configure TCP instance.\r
1294 //\r
a2e61982
ZL
1295 if (Configure) {\r
1296 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1297 if (EFI_ERROR (Status)) {\r
1298 return Status;\r
1299 }\r
b659408b 1300 }\r
a2e61982 1301\r
b659408b
ZL
1302 //\r
1303 // Connect TCP.\r
1304 //\r
1305 Status = HttpConnectTcp6 (HttpInstance);\r
1306 if (EFI_ERROR (Status)) {\r
1307 return Status;\r
1308 }\r
1309 }\r
1310 \r
1311 return EFI_SUCCESS;\r
1312 \r
1313}\r
1314\r
1315/**\r
1316 Send the HTTP message through TCP4 or TCP6.\r
47f51a06
YT
1317\r
1318 @param[in] HttpInstance The HTTP instance private data.\r
1319 @param[in] Wrap The HTTP token's wrap data.\r
1320 @param[in] TxString Buffer containing the HTTP message string.\r
1321 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1322\r
1323 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1324 @retval Others Other error as indicated.\r
1325\r
1326**/\r
1327EFI_STATUS\r
b659408b 1328HttpTransmitTcp (\r
47f51a06
YT
1329 IN HTTP_PROTOCOL *HttpInstance,\r
1330 IN HTTP_TOKEN_WRAP *Wrap,\r
1331 IN UINT8 *TxString,\r
1332 IN UINTN TxStringLen\r
1333 )\r
1334{\r
1335 EFI_STATUS Status;\r
b659408b 1336 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1337 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1338 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1339 EFI_TCP6_PROTOCOL *Tcp6;\r
47f51a06 1340 \r
b659408b
ZL
1341 if (!HttpInstance->LocalAddressIsIPv6) { \r
1342 Tcp4 = HttpInstance->Tcp4;\r
1343 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1344 \r
1345 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1346 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1347 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1348 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1349 \r
1350 Wrap->TcpWrap.IsTxDone = FALSE;\r
1351 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1352 if (EFI_ERROR (Status)) {\r
1353 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1354 return Status;\r
1355 }\r
47f51a06 1356\r
b659408b
ZL
1357 } else {\r
1358 Tcp6 = HttpInstance->Tcp6;\r
1359 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
47f51a06 1360\r
b659408b
ZL
1361 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1362 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1363 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1364 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1365\r
1366 Wrap->TcpWrap.IsTxDone = FALSE;\r
1367 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1368 if (EFI_ERROR (Status)) {\r
1369 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1370 return Status;\r
1371 }\r
47f51a06 1372 }\r
b659408b 1373 \r
47f51a06
YT
1374\r
1375 return Status;\r
1376}\r
1377\r
1378/**\r
1379 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined \r
1380 in UEFI 2.5 specification.\r
1381\r
1382 @param[in] StatusCode The status code value in HTTP message.\r
1383\r
1384 @return Value defined in EFI_HTTP_STATUS_CODE .\r
1385\r
1386**/\r
1387EFI_HTTP_STATUS_CODE\r
1388HttpMappingToStatusCode (\r
1389 IN UINTN StatusCode\r
1390 ) \r
1391{\r
1392 switch (StatusCode) {\r
1393 case 100:\r
1394 return HTTP_STATUS_100_CONTINUE;\r
1395 case 101:\r
1396 return HTTP_STATUS_101_SWITCHING_PROTOCOLS;\r
1397 case 200:\r
1398 return HTTP_STATUS_200_OK;\r
1399 case 201:\r
1400 return HTTP_STATUS_201_CREATED;\r
1401 case 202:\r
1402 return HTTP_STATUS_202_ACCEPTED;\r
1403 case 203:\r
1404 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;\r
1405 case 204:\r
1406 return HTTP_STATUS_204_NO_CONTENT;\r
1407 case 205:\r
1408 return HTTP_STATUS_205_RESET_CONTENT;\r
1409 case 206:\r
1410 return HTTP_STATUS_206_PARTIAL_CONTENT;\r
1411 case 300:\r
1412 return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
1413 case 301:\r
1414 return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
1415 case 302:\r
1416 return HTTP_STATUS_302_FOUND;\r
1417 case 303:\r
1418 return HTTP_STATUS_303_SEE_OTHER;\r
1419 case 304:\r
1420 return HTTP_STATUS_304_NOT_MODIFIED;\r
1421 case 305:\r
1422 return HTTP_STATUS_305_USE_PROXY;\r
1423 case 307:\r
1424 return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
1425 case 400:\r
1426 return HTTP_STATUS_400_BAD_REQUEST;\r
1427 case 401:\r
1428 return HTTP_STATUS_401_UNAUTHORIZED;\r
1429 case 402:\r
1430 return HTTP_STATUS_402_PAYMENT_REQUIRED;\r
1431 case 403:\r
1432 return HTTP_STATUS_403_FORBIDDEN;\r
1433 case 404:\r
1434 return HTTP_STATUS_404_NOT_FOUND;\r
1435 case 405:\r
1436 return HTTP_STATUS_405_METHOD_NOT_ALLOWED;\r
1437 case 406:\r
1438 return HTTP_STATUS_406_NOT_ACCEPTABLE;\r
1439 case 407:\r
1440 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;\r
1441 case 408:\r
1442 return HTTP_STATUS_408_REQUEST_TIME_OUT;\r
1443 case 409:\r
1444 return HTTP_STATUS_409_CONFLICT;\r
1445 case 410:\r
1446 return HTTP_STATUS_410_GONE;\r
1447 case 411:\r
1448 return HTTP_STATUS_411_LENGTH_REQUIRED;\r
1449 case 412:\r
1450 return HTTP_STATUS_412_PRECONDITION_FAILED;\r
1451 case 413:\r
1452 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;\r
1453 case 414:\r
1454 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;\r
1455 case 415:\r
8cfd008e 1456 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;\r
47f51a06
YT
1457 case 416:\r
1458 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;\r
1459 case 417:\r
1460 return HTTP_STATUS_417_EXPECTATION_FAILED;\r
1461 case 500:\r
1462 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;\r
1463 case 501:\r
8cfd008e 1464 return HTTP_STATUS_501_NOT_IMPLEMENTED;\r
47f51a06
YT
1465 case 502:\r
1466 return HTTP_STATUS_502_BAD_GATEWAY;\r
1467 case 503:\r
1468 return HTTP_STATUS_503_SERVICE_UNAVAILABLE;\r
1469 case 504:\r
1470 return HTTP_STATUS_504_GATEWAY_TIME_OUT;\r
1471 case 505:\r
1472 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;\r
1473\r
1474 default:\r
1475 return HTTP_STATUS_UNSUPPORTED_STATUS;\r
1476 }\r
1477}\r
1478\r
1479/**\r
1480 Check whether the user's token or event has already\r
b659408b 1481 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1482\r
1483 @param[in] Map The container of either user's transmit or receive\r
1484 token.\r
1485 @param[in] Item Current item to check against.\r
1486 @param[in] Context The Token to check againist.\r
1487\r
1488 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1489 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1490 context.\r
1491\r
1492**/\r
1493EFI_STATUS\r
1494EFIAPI\r
1495HttpTokenExist (\r
1496 IN NET_MAP *Map,\r
1497 IN NET_MAP_ITEM *Item,\r
1498 IN VOID *Context\r
1499 )\r
1500{\r
1501 EFI_HTTP_TOKEN *Token;\r
1502 EFI_HTTP_TOKEN *TokenInItem;\r
1503\r
1504 Token = (EFI_HTTP_TOKEN *) Context;\r
1505 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1506\r
1507 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1508 return EFI_ACCESS_DENIED;\r
1509 }\r
1510\r
1511 return EFI_SUCCESS;\r
1512}\r
1513\r
1514/**\r
b659408b 1515 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1516\r
b659408b 1517 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1518 @param[in] Item Current item to check against.\r
1519 @param[in] Context The Token to check againist.\r
1520\r
1521 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1522 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1523\r
1524**/\r
1525EFI_STATUS\r
1526EFIAPI\r
1527HttpTcpNotReady (\r
1528 IN NET_MAP *Map,\r
1529 IN NET_MAP_ITEM *Item,\r
1530 IN VOID *Context\r
1531 )\r
1532{\r
1533 HTTP_TOKEN_WRAP *ValueInItem;\r
1534\r
1535 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1536\r
1537 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1538 return EFI_NOT_READY;\r
1539 }\r
1540 \r
1541 return EFI_SUCCESS;\r
1542}\r
1543\r
1544/**\r
1545 Transmit the HTTP mssage by processing the associated HTTP token.\r
1546\r
b659408b 1547 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1548 @param[in] Item Current item to check against.\r
1549 @param[in] Context The Token to check againist.\r
1550\r
1551 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1552 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1553 queue.\r
1554\r
1555**/\r
1556EFI_STATUS\r
1557EFIAPI\r
1558HttpTcpTransmit (\r
1559 IN NET_MAP *Map,\r
1560 IN NET_MAP_ITEM *Item,\r
1561 IN VOID *Context\r
1562 )\r
1563{\r
1564 HTTP_TOKEN_WRAP *ValueInItem;\r
1565 EFI_STATUS Status;\r
1566 CHAR8 *RequestStr;\r
1567 CHAR8 *Url;\r
1568\r
1569 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1570 if (ValueInItem->TcpWrap.IsTxDone) {\r
1571 return EFI_SUCCESS;\r
1572 }\r
1573\r
1574 //\r
1575 // Parse the URI of the remote host.\r
1576 //\r
1577 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1578 if (Url == NULL) {\r
1579 return EFI_OUT_OF_RESOURCES;\r
1580 }\r
1581\r
1582 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1583\r
1584 //\r
1585 // Create request message.\r
1586 //\r
1587 RequestStr = HttpGenRequestString (\r
1588 ValueInItem->HttpInstance,\r
1589 ValueInItem->HttpToken->Message,\r
1590 Url\r
1591 );\r
1592 FreePool (Url);\r
1593 if (RequestStr == NULL) {\r
1594 return EFI_OUT_OF_RESOURCES;\r
1595 }\r
1596\r
1597 //\r
1598 // Transmit the request message.\r
1599 //\r
b659408b 1600 Status = HttpTransmitTcp (\r
47f51a06
YT
1601 ValueInItem->HttpInstance,\r
1602 ValueInItem,\r
1603 (UINT8*) RequestStr,\r
1604 AsciiStrLen (RequestStr)\r
1605 );\r
1606 FreePool (RequestStr);\r
1607 return Status;\r
1608}\r
1609\r
1610/**\r
1611 Receive the HTTP response by processing the associated HTTP token.\r
1612\r
b659408b 1613 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1614 @param[in] Item Current item to check against.\r
1615 @param[in] Context The Token to check againist.\r
1616\r
1617 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1618 queue.\r
1619 @retval Others Other error as indicated.\r
1620\r
1621**/\r
1622EFI_STATUS\r
1623EFIAPI\r
1624HttpTcpReceive (\r
1625 IN NET_MAP *Map,\r
1626 IN NET_MAP_ITEM *Item,\r
1627 IN VOID *Context\r
1628 )\r
1629{\r
1630 //\r
1631 // Process the queued HTTP response.\r
1632 //\r
1633 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1634}\r
1635\r
b659408b
ZL
1636/**\r
1637 Receive the HTTP header by processing the associated HTTP token.\r
1638\r
1639 @param[in] HttpInstance The HTTP instance private data.\r
1640 @param[in, out] SizeofHeaders The HTTP header length.\r
1641 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1642 \r
1643 @retval EFI_SUCCESS The HTTP header is received. \r
1644 @retval Others Other errors as indicated.\r
1645\r
1646**/\r
1647EFI_STATUS\r
1648HttpTcpReceiveHeader (\r
1649 IN HTTP_PROTOCOL *HttpInstance,\r
1650 IN OUT UINTN *SizeofHeaders,\r
1651 IN OUT UINTN *BufferSize\r
1652 )\r
1653{\r
1654 EFI_STATUS Status;\r
1655 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1656 EFI_TCP4_PROTOCOL *Tcp4;\r
1657 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1658 EFI_TCP6_PROTOCOL *Tcp6;\r
1659 CHAR8 **EndofHeader;\r
1660 CHAR8 **HttpHeaders;\r
1661 CHAR8 *Buffer;\r
1662\r
1663 ASSERT (HttpInstance != NULL);\r
1664\r
1665 EndofHeader = HttpInstance->EndofHeader;\r
1666 HttpHeaders = HttpInstance->HttpHeaders;\r
1667 Tcp4 = HttpInstance->Tcp4;\r
1668 Tcp6 = HttpInstance->Tcp6;\r
1669 Buffer = NULL;\r
1670 Rx4Token = NULL;\r
1671 Rx6Token = NULL;\r
1672 \r
1673 if (HttpInstance->LocalAddressIsIPv6) {\r
1674 ASSERT (Tcp6 != NULL);\r
1675 } else {\r
1676 ASSERT (Tcp4 != NULL);\r
1677 }\r
1678\r
1679 if (!HttpInstance->LocalAddressIsIPv6) {\r
1680 Rx4Token = &HttpInstance->Rx4Token;\r
1681 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1682 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1683 Status = EFI_OUT_OF_RESOURCES;\r
1684 return Status;\r
1685 }\r
1686 \r
1687 //\r
1688 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1689 //\r
1690 while (*EndofHeader == NULL) { \r
1691 HttpInstance->IsRxDone = FALSE;\r
1692 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1693 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1694 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1695 if (EFI_ERROR (Status)) {\r
1696 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1697 return Status;\r
1698 }\r
1699 \r
1700 while (!HttpInstance->IsRxDone) {\r
1701 Tcp4->Poll (Tcp4);\r
1702 } \r
1703 \r
1704 Status = Rx4Token->CompletionToken.Status;\r
1705 if (EFI_ERROR (Status)) {\r
1706 return Status;\r
1707 }\r
1708 \r
1709 //\r
1710 // Append the response string.\r
1711 //\r
1712 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1713 Buffer = AllocateZeroPool (*BufferSize);\r
1714 if (Buffer == NULL) {\r
1715 Status = EFI_OUT_OF_RESOURCES;\r
1716 return Status;\r
1717 }\r
1718 \r
1719 if (*HttpHeaders != NULL) {\r
1720 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1721 FreePool (*HttpHeaders);\r
1722 }\r
1723 \r
1724 CopyMem (\r
1725 Buffer + (*SizeofHeaders),\r
1726 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1727 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1728 );\r
1729 *HttpHeaders = Buffer;\r
1730 *SizeofHeaders = *BufferSize;\r
1731 \r
1732 //\r
1733 // Check whether we received end of HTTP headers.\r
1734 //\r
1735 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1736 }\r
1737 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1738 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1739 \r
1740 } else {\r
1741 Rx6Token = &HttpInstance->Rx6Token;\r
1742 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1743 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1744 Status = EFI_OUT_OF_RESOURCES;\r
1745 return Status;\r
1746 }\r
1747 \r
1748 //\r
1749 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1750 //\r
1751 while (*EndofHeader == NULL) { \r
1752 HttpInstance->IsRxDone = FALSE;\r
1753 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1754 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1755 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1756 if (EFI_ERROR (Status)) {\r
1757 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1758 return Status;\r
1759 }\r
1760 \r
1761 while (!HttpInstance->IsRxDone) {\r
1762 Tcp6->Poll (Tcp6);\r
1763 } \r
1764 \r
1765 Status = Rx6Token->CompletionToken.Status;\r
1766 if (EFI_ERROR (Status)) {\r
1767 return Status;\r
1768 }\r
1769 \r
1770 //\r
1771 // Append the response string.\r
1772 //\r
1773 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1774 Buffer = AllocateZeroPool (*BufferSize);\r
1775 if (Buffer == NULL) {\r
1776 Status = EFI_OUT_OF_RESOURCES;\r
1777 return Status;\r
1778 }\r
1779 \r
1780 if (*HttpHeaders != NULL) {\r
1781 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1782 FreePool (*HttpHeaders);\r
1783 }\r
1784 \r
1785 CopyMem (\r
1786 Buffer + (*SizeofHeaders),\r
1787 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1788 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1789 );\r
1790 *HttpHeaders = Buffer;\r
1791 *SizeofHeaders = *BufferSize;\r
1792 \r
1793 //\r
1794 // Check whether we received end of HTTP headers.\r
1795 //\r
1796 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1797 \r
1798 }\r
1799 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1800 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1801 } \r
1802\r
1803 //\r
1804 // Skip the CRLF after the HTTP headers.\r
1805 //\r
1806 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1807\r
1808 return EFI_SUCCESS;\r
1809}\r
1810\r
1811/**\r
1812 Receive the HTTP body by processing the associated HTTP token.\r
1813\r
1814 @param[in] Wrap The HTTP token's wrap data.\r
1815 @param[in] HttpMsg The HTTP message data.\r
1816\r
1817 @retval EFI_SUCCESS The HTTP body is received. \r
1818 @retval Others Other error as indicated.\r
1819\r
1820**/\r
1821EFI_STATUS\r
1822HttpTcpReceiveBody (\r
1823 IN HTTP_TOKEN_WRAP *Wrap,\r
1824 IN EFI_HTTP_MESSAGE *HttpMsg\r
1825 )\r
1826{\r
1827 EFI_STATUS Status;\r
1828 HTTP_PROTOCOL *HttpInstance;\r
1829 EFI_TCP6_PROTOCOL *Tcp6;\r
1830 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1831 EFI_TCP4_PROTOCOL *Tcp4;\r
1832 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1833 \r
1834 HttpInstance = Wrap->HttpInstance;\r
1835 Tcp4 = HttpInstance->Tcp4;\r
1836 Tcp6 = HttpInstance->Tcp6;\r
1837 Rx4Token = NULL;\r
1838 Rx6Token = NULL;\r
1839\r
1840 \r
1841 if (HttpInstance->LocalAddressIsIPv6) {\r
1842 ASSERT (Tcp6 != NULL);\r
1843 } else {\r
1844 ASSERT (Tcp4 != NULL);\r
1845 }\r
1846 \r
1847 if (HttpInstance->LocalAddressIsIPv6) {\r
1848 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1849 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1850 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1851 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1852 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1853\r
1854 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1855 if (EFI_ERROR (Status)) {\r
1856 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1857 return Status;\r
1858 }\r
1859 \r
1860 } else {\r
1861 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1862 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1863 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1864 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1865 \r
1866 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1867 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1868 if (EFI_ERROR (Status)) {\r
1869 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1870 return Status;\r
1871 }\r
1872 }\r
1873\r
1874 return EFI_SUCCESS;\r
1875\r
1876}\r
1877\r
1878/**\r
1879 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1880\r
1881 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1882 \r
1883**/\r
1884VOID\r
1885HttpTcpTokenCleanup (\r
1886 IN HTTP_TOKEN_WRAP *Wrap\r
1887 )\r
1888{ \r
1889 HTTP_PROTOCOL *HttpInstance;\r
1890 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1891 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1892\r
1b96428d 1893 ASSERT (Wrap != NULL);\r
b659408b
ZL
1894 HttpInstance = Wrap->HttpInstance;\r
1895 Rx4Token = NULL;\r
1896 Rx6Token = NULL;\r
1897 \r
1898 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
1899 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1900 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1901 }\r
b659408b 1902\r
1b96428d
ZL
1903 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1904 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1905 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1906 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
b659408b 1907 }\r
1b96428d 1908 FreePool (Wrap);\r
b659408b
ZL
1909\r
1910 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1911 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1912 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1913 }\r
1914\r
1915 Rx6Token = &HttpInstance->Rx6Token;\r
1916 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1917 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1918 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1919 }\r
1920 \r
1921 } else {\r
1b96428d
ZL
1922 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1923 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b 1924 }\r
1b96428d
ZL
1925 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1926 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1927 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1928 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1929 }\r
1930 FreePool (Wrap);\r
1931\r
b659408b
ZL
1932 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1933 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1934 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1935 }\r
1936 \r
1937 Rx4Token = &HttpInstance->Rx4Token;\r
1938 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1939 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1940 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1941 }\r
1942 }\r
1943\r
1944}\r
1945\r
47f51a06
YT
1946/**\r
1947 Generate HTTP request string.\r
1948\r
1949 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
1950 @param[in] Message Pointer to storage containing HTTP message data.\r
1951 @param[in] Url The URL of a remote host.\r
1952\r
1953 @return Pointer to the created HTTP request string.\r
1954 @return NULL if any error occured.\r
1955\r
1956**/\r
1957CHAR8 *\r
1958HttpGenRequestString (\r
1959 IN HTTP_PROTOCOL *HttpInstance,\r
1960 IN EFI_HTTP_MESSAGE *Message,\r
1961 IN CHAR8 *Url\r
1962 )\r
1963{\r
1964 EFI_STATUS Status;\r
1965 UINTN StrLength;\r
1966 UINT8 *Request;\r
1967 UINT8 *RequestPtr;\r
1968 UINTN HttpHdrSize;\r
1969 UINTN MsgSize;\r
1970 BOOLEAN Success;\r
1971 VOID *HttpHdr;\r
1972 EFI_HTTP_HEADER **AppendList; \r
1973 UINTN Index;\r
1974 \r
1975 ASSERT (HttpInstance != NULL);\r
1976 ASSERT (Message != NULL);\r
1977\r
1978 DEBUG ((EFI_D_ERROR, "HttpMethod - %x\n", Message->Data.Request->Method));\r
1979\r
1980 Request = NULL;\r
1981 Success = FALSE;\r
1982 HttpHdr = NULL;\r
1983 AppendList = NULL;\r
1984\r
1985 //\r
1986 // Build AppendList\r
1987 //\r
1988 AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
1989 if (AppendList == NULL) {\r
1990 return NULL;\r
1991 }\r
1992\r
1993 for(Index = 0; Index < Message->HeaderCount; Index++){\r
1994 AppendList[Index] = &Message->Headers[Index];\r
1995 }\r
1996\r
5ca29abe
JW
1997 //\r
1998 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.\r
1999 //\r
2000 if (mHttpUtilities == NULL) {\r
2001 return NULL;\r
2002 }\r
2003\r
47f51a06
YT
2004 //\r
2005 // Build raw unformatted HTTP headers.\r
5ca29abe
JW
2006 //\r
2007 Status = mHttpUtilities->Build (\r
2008 mHttpUtilities,\r
2009 0,\r
2010 NULL,\r
2011 0,\r
2012 NULL,\r
2013 Message->HeaderCount,\r
2014 AppendList,\r
2015 &HttpHdrSize,\r
2016 &HttpHdr\r
2017 );\r
47f51a06
YT
2018 FreePool (AppendList);\r
2019 if (EFI_ERROR (Status) || HttpHdr == NULL) {\r
2020 return NULL;\r
2021 }\r
2022\r
2023 //\r
2024 // Calculate HTTP message length.\r
2025 //\r
90f658c4 2026 MsgSize = Message->BodyLength + HTTP_METHOD_MAXIMUM_LEN + AsciiStrLen (Url) +\r
47f51a06
YT
2027 AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
2028 Request = AllocateZeroPool (MsgSize);\r
2029 if (Request == NULL) {\r
2030 goto Exit;\r
2031 } \r
2032\r
2033 RequestPtr = Request;\r
2034 //\r
2035 // Construct header request\r
2036 //\r
2037 switch (Message->Data.Request->Method) {\r
2038 case HttpMethodGet:\r
90f658c4
SEHM
2039 StrLength = sizeof (HTTP_METHOD_GET) - 1;\r
2040 CopyMem (RequestPtr, HTTP_METHOD_GET, StrLength);\r
47f51a06
YT
2041 RequestPtr += StrLength;\r
2042 break;\r
2043 case HttpMethodHead:\r
90f658c4
SEHM
2044 StrLength = sizeof (HTTP_METHOD_HEAD) - 1;\r
2045 CopyMem (RequestPtr, HTTP_METHOD_HEAD, StrLength);\r
47f51a06
YT
2046 RequestPtr += StrLength;\r
2047 break;\r
2048 default:\r
2049 ASSERT (FALSE);\r
2050 goto Exit;\r
2051 }\r
2052\r
90f658c4
SEHM
2053 StrLength = AsciiStrLen(" ");\r
2054 CopyMem (RequestPtr, " ", StrLength);\r
2055 RequestPtr += StrLength;\r
2056\r
47f51a06
YT
2057 StrLength = AsciiStrLen (Url);\r
2058 CopyMem (RequestPtr, Url, StrLength);\r
2059 RequestPtr += StrLength;\r
2060\r
2061 StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
2062 CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
2063 RequestPtr += StrLength;\r
2064\r
2065 //\r
2066 // Construct header\r
2067 //\r
2068 CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
2069 RequestPtr += HttpHdrSize;\r
2070\r
2071 //\r
2072 // Construct body\r
2073 //\r
2074 if (Message->Body != NULL) {\r
2075 CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
2076 RequestPtr += Message->BodyLength;\r
2077 }\r
2078\r
2079 //\r
2080 // Done\r
2081 //\r
2082 *RequestPtr = 0;\r
2083 Success = TRUE;\r
2084 \r
2085Exit:\r
2086\r
2087 if (!Success) {\r
2088 if (Request != NULL) {\r
2089 FreePool (Request);\r
2090 }\r
2091\r
2092 Request = NULL;\r
2093 }\r
2094\r
2095 if (HttpHdr != NULL) {\r
2096 FreePool (HttpHdr);\r
2097 }\r
2098\r
2099 return (CHAR8*) Request;\r
2100}\r