]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Avoid the indefinite wait case in HttpDxe
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
... / ...
CommitLineData
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
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
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
41\r
42 @param[in] Context The context.\r
43\r
44**/\r
45VOID\r
46EFIAPI\r
47HttpTcpTransmitNotifyDpc (\r
48 IN VOID *Context\r
49 )\r
50{\r
51 HTTP_TOKEN_WRAP *Wrap;\r
52 HTTP_PROTOCOL *HttpInstance;\r
53\r
54 if (Context == NULL) {\r
55 return ;\r
56 }\r
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
71\r
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
86\r
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
89 } \r
90 }\r
91\r
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
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
122/**\r
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
124\r
125 @param[in] Context The context.\r
126\r
127**/\r
128VOID\r
129EFIAPI\r
130HttpTcpReceiveNotifyDpc (\r
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
139 BOOLEAN UsingIpv6;\r
140\r
141 if (Context == NULL) {\r
142 return ;\r
143 }\r
144\r
145 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
146 HttpInstance = Wrap->HttpInstance;\r
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
153 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
154 gBS->SignalEvent (Wrap->HttpToken->Event);\r
155 FreePool (Wrap);\r
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
163 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
164 gBS->SignalEvent (Wrap->HttpToken->Event);\r
165 FreePool (Wrap);\r
166 return ;\r
167 }\r
168 }\r
169\r
170 //\r
171 // Check whether we receive a complete HTTP message.\r
172 //\r
173 ASSERT (HttpInstance->MsgParser != NULL);\r
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
179\r
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
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
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
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
261/**\r
262 Create events for the TCP connection token and TCP close token.\r
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
271HttpCreateTcpConnCloseEvent (\r
272 IN HTTP_PROTOCOL *HttpInstance\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276\r
277 if (!HttpInstance->LocalAddressIsIPv6) {\r
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
285 &HttpInstance->IsTcp4ConnDone,\r
286 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
287 );\r
288 if (EFI_ERROR (Status)) {\r
289 goto ERROR;\r
290 }\r
291\r
292 //\r
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
309 //\r
310 Status = gBS->CreateEvent (\r
311 EVT_NOTIFY_SIGNAL,\r
312 TPL_NOTIFY,\r
313 HttpCommonNotify,\r
314 &HttpInstance->IsTcp6ConnDone,\r
315 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 goto ERROR;\r
319 }\r
320\r
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
336 return EFI_SUCCESS;\r
337\r
338ERROR:\r
339 //\r
340 // Error handling\r
341 //\r
342 HttpCloseTcpConnCloseEvent (HttpInstance);\r
343\r
344 return Status;\r
345}\r
346\r
347\r
348/**\r
349 Close events in the TCP connection token and TCP close token.\r
350\r
351 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
352\r
353**/\r
354VOID\r
355HttpCloseTcpConnCloseEvent (\r
356 IN HTTP_PROTOCOL *HttpInstance\r
357 )\r
358{\r
359 ASSERT (HttpInstance != NULL);\r
360\r
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
366\r
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
384}\r
385\r
386/**\r
387 Create event for the TCP transmit token.\r
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
396HttpCreateTcpTxEvent (\r
397 IN HTTP_TOKEN_WRAP *Wrap\r
398 )\r
399{\r
400 EFI_STATUS Status;\r
401 HTTP_PROTOCOL *HttpInstance;\r
402 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
403\r
404 HttpInstance = Wrap->HttpInstance;\r
405 TcpWrap = &Wrap->TcpWrap;\r
406\r
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
424\r
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
436\r
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
446 return EFI_SUCCESS;\r
447}\r
448\r
449/**\r
450 Create event for the TCP receive token which is used to receive HTTP header.\r
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
459HttpCreateTcpRxEventForHeader (\r
460 IN HTTP_PROTOCOL *HttpInstance\r
461 )\r
462{\r
463 EFI_STATUS Status;\r
464\r
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
480\r
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
497 }\r
498\r
499\r
500 return EFI_SUCCESS;\r
501}\r
502\r
503/**\r
504 Create event for the TCP receive token which is used to receive HTTP body.\r
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
513HttpCreateTcpRxEvent (\r
514 IN HTTP_TOKEN_WRAP *Wrap \r
515 )\r
516{\r
517 EFI_STATUS Status;\r
518 HTTP_PROTOCOL *HttpInstance;\r
519 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
520\r
521 HttpInstance = Wrap->HttpInstance;\r
522 TcpWrap = &Wrap->TcpWrap;\r
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
538\r
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
554 }\r
555 \r
556 return EFI_SUCCESS;\r
557}\r
558\r
559/**\r
560 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
561\r
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
571\r
572 ASSERT (Wrap != NULL);\r
573 HttpInstance = Wrap->HttpInstance;\r
574 \r
575 if (HttpInstance->LocalAddressIsIPv6) {\r
576 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
577 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
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
585 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
586 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
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
594}\r
595\r
596/**\r
597 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
598\r
599 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
600 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
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
608 IN OUT HTTP_PROTOCOL *HttpInstance,\r
609 IN BOOLEAN IpVersion\r
610 )\r
611{\r
612 EFI_STATUS Status;\r
613 VOID *Interface;\r
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
629\r
630 if (EFI_ERROR (Status)) {\r
631 goto ON_ERROR;\r
632 }\r
633\r
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
646\r
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
658\r
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
680\r
681 if (EFI_ERROR (Status)) {\r
682 goto ON_ERROR;\r
683 }\r
684\r
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
719\r
720 if (EFI_ERROR(Status)) {\r
721 goto ON_ERROR;\r
722 }\r
723 }\r
724 \r
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
731 return EFI_SUCCESS;\r
732\r
733ON_ERROR:\r
734 \r
735 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
736 gBS->CloseProtocol (\r
737 HttpInstance->Tcp4ChildHandle,\r
738 &gEfiTcp4ProtocolGuid,\r
739 HttpInstance->Service->ImageHandle,\r
740 HttpInstance->Service->ControllerHandle\r
741 );\r
742\r
743 gBS->CloseProtocol (\r
744 HttpInstance->Tcp4ChildHandle,\r
745 &gEfiTcp4ProtocolGuid,\r
746 HttpInstance->Service->ImageHandle,\r
747 HttpInstance->Handle\r
748 ); \r
749 \r
750 NetLibDestroyServiceChild (\r
751 HttpInstance->Service->ControllerHandle,\r
752 HttpInstance->Service->ImageHandle,\r
753 &gEfiTcp4ServiceBindingProtocolGuid,\r
754 HttpInstance->Tcp4ChildHandle\r
755 );\r
756 }\r
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
774\r
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
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
816 HttpCloseTcpConnCloseEvent (HttpInstance);\r
817\r
818 if (HttpInstance->TimeoutEvent != NULL) {\r
819 gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
820 HttpInstance->TimeoutEvent = NULL;\r
821 }\r
822\r
823 if (HttpInstance->CacheBody != NULL) {\r
824 FreePool (HttpInstance->CacheBody);\r
825 HttpInstance->CacheBody = NULL;\r
826 HttpInstance->NextMsg = NULL;\r
827 }\r
828\r
829 if (HttpInstance->RemoteHost != NULL) {\r
830 FreePool (HttpInstance->RemoteHost);\r
831 HttpInstance->RemoteHost = NULL;\r
832 }\r
833\r
834 if (HttpInstance->MsgParser != NULL) {\r
835 HttpFreeMsgParser (HttpInstance->MsgParser);\r
836 HttpInstance->MsgParser = NULL;\r
837 }\r
838 \r
839 if (HttpInstance->Url != NULL) {\r
840 FreePool (HttpInstance->Url);\r
841 HttpInstance->Url = NULL;\r
842 }\r
843 \r
844 NetMapClean (&HttpInstance->TxTokens);\r
845 NetMapClean (&HttpInstance->RxTokens);\r
846\r
847 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
848 gBS->CloseProtocol (\r
849 HttpInstance->Tcp4ChildHandle,\r
850 &gEfiTcp4ProtocolGuid,\r
851 HttpInstance->Service->ImageHandle,\r
852 HttpInstance->Service->ControllerHandle\r
853 );\r
854\r
855 gBS->CloseProtocol (\r
856 HttpInstance->Tcp4ChildHandle,\r
857 &gEfiTcp4ProtocolGuid,\r
858 HttpInstance->Service->ImageHandle,\r
859 HttpInstance->Handle\r
860 );\r
861 \r
862 NetLibDestroyServiceChild (\r
863 HttpInstance->Service->ControllerHandle,\r
864 HttpInstance->Service->ImageHandle,\r
865 &gEfiTcp4ServiceBindingProtocolGuid,\r
866 HttpInstance->Tcp4ChildHandle\r
867 );\r
868 }\r
869\r
870 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
871 gBS->CloseProtocol (\r
872 HttpInstance->Service->Tcp4ChildHandle,\r
873 &gEfiTcp4ProtocolGuid,\r
874 HttpInstance->Service->ImageHandle,\r
875 HttpInstance->Handle\r
876 );\r
877 } \r
878\r
879 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
880 gBS->CloseProtocol (\r
881 HttpInstance->Tcp6ChildHandle,\r
882 &gEfiTcp6ProtocolGuid,\r
883 HttpInstance->Service->ImageHandle,\r
884 HttpInstance->Service->ControllerHandle\r
885 );\r
886\r
887 gBS->CloseProtocol (\r
888 HttpInstance->Tcp6ChildHandle,\r
889 &gEfiTcp6ProtocolGuid,\r
890 HttpInstance->Service->ImageHandle,\r
891 HttpInstance->Handle\r
892 );\r
893 \r
894 NetLibDestroyServiceChild (\r
895 HttpInstance->Service->ControllerHandle,\r
896 HttpInstance->Service->ImageHandle,\r
897 &gEfiTcp6ServiceBindingProtocolGuid,\r
898 HttpInstance->Tcp6ChildHandle\r
899 );\r
900 }\r
901 \r
902 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
903 gBS->CloseProtocol (\r
904 HttpInstance->Service->Tcp6ChildHandle,\r
905 &gEfiTcp6ProtocolGuid,\r
906 HttpInstance->Service->ImageHandle,\r
907 HttpInstance->Handle\r
908 );\r
909 }\r
910 \r
911}\r
912\r
913/**\r
914 Establish TCP connection with HTTP server.\r
915\r
916 @param[in] HttpInstance The HTTP instance private data.\r
917\r
918 @retval EFI_SUCCESS The TCP connection is established.\r
919 @retval Others Other error as indicated.\r
920\r
921**/\r
922EFI_STATUS\r
923HttpCreateConnection (\r
924 IN HTTP_PROTOCOL *HttpInstance\r
925 )\r
926{\r
927 EFI_STATUS Status;\r
928\r
929 //\r
930 // Connect to Http server\r
931 //\r
932 if (!HttpInstance->LocalAddressIsIPv6) {\r
933 HttpInstance->IsTcp4ConnDone = FALSE;\r
934 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
935 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
936 if (EFI_ERROR (Status)) {\r
937 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
938 return Status;\r
939 }\r
940 \r
941 while (!HttpInstance->IsTcp4ConnDone) {\r
942 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
943 }\r
944 \r
945 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
946 \r
947 } else {\r
948 HttpInstance->IsTcp6ConnDone = FALSE;\r
949 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
950 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
951 if (EFI_ERROR (Status)) {\r
952 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
953 return Status;\r
954 }\r
955\r
956 while(!HttpInstance->IsTcp6ConnDone) {\r
957 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
958 }\r
959\r
960 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
961 }\r
962 \r
963 if (!EFI_ERROR (Status)) {\r
964 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
965 }\r
966\r
967 return Status;\r
968}\r
969\r
970/**\r
971 Close existing TCP connection.\r
972\r
973 @param[in] HttpInstance The HTTP instance private data.\r
974\r
975 @retval EFI_SUCCESS The TCP connection is closed.\r
976 @retval Others Other error as indicated.\r
977\r
978**/\r
979EFI_STATUS\r
980HttpCloseConnection (\r
981 IN HTTP_PROTOCOL *HttpInstance\r
982 )\r
983{\r
984 EFI_STATUS Status;\r
985\r
986 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
987\r
988 if (HttpInstance->LocalAddressIsIPv6) {\r
989 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
990 HttpInstance->IsTcp6CloseDone = FALSE;\r
991 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
992 if (EFI_ERROR (Status)) {\r
993 return Status;\r
994 }\r
995\r
996 while (!HttpInstance->IsTcp6CloseDone) {\r
997 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
998 }\r
999 \r
1000 } else {\r
1001 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
1002 HttpInstance->IsTcp4CloseDone = FALSE;\r
1003 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
1004 if (EFI_ERROR (Status)) {\r
1005 return Status;\r
1006 }\r
1007\r
1008 while (!HttpInstance->IsTcp4CloseDone) {\r
1009 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1010 }\r
1011 }\r
1012\r
1013 }\r
1014\r
1015 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
1016 return EFI_SUCCESS;\r
1017}\r
1018\r
1019/**\r
1020 Configure TCP4 protocol child.\r
1021\r
1022 @param[in] HttpInstance The HTTP instance private data.\r
1023 @param[in] Wrap The HTTP token's wrap data.\r
1024\r
1025 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1026 @retval Others Other error as indicated.\r
1027\r
1028**/\r
1029EFI_STATUS\r
1030HttpConfigureTcp4 (\r
1031 IN HTTP_PROTOCOL *HttpInstance,\r
1032 IN HTTP_TOKEN_WRAP *Wrap\r
1033 )\r
1034{\r
1035 EFI_STATUS Status;\r
1036 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1037 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1038 EFI_TCP4_OPTION *Tcp4Option;\r
1039\r
1040 ASSERT (HttpInstance != NULL);\r
1041\r
1042\r
1043 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1044 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1045 \r
1046 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1047 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1048 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1049\r
1050 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1051 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1052 if (!Tcp4AP->UseDefaultAddress) {\r
1053 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1054 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1055 }\r
1056 \r
1057 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1058 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1059 Tcp4AP->ActiveFlag = TRUE;\r
1060 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1061\r
1062 Tcp4Option = Tcp4CfgData->ControlOption;\r
1063 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1064 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1065 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1066 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1067 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1068 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1069 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1070 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1071 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1072 Tcp4Option->EnableNagle = TRUE;\r
1073 Tcp4CfgData->ControlOption = Tcp4Option;\r
1074\r
1075 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1076 if (EFI_ERROR (Status)) {\r
1077 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1078 return Status;\r
1079 }\r
1080\r
1081 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1082 if (EFI_ERROR (Status)) {\r
1083 return Status;\r
1084 }\r
1085\r
1086 Status = HttpCreateTcpTxEvent (Wrap);\r
1087 if (EFI_ERROR (Status)) {\r
1088 return Status;\r
1089 }\r
1090\r
1091 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1092\r
1093 return EFI_SUCCESS;\r
1094}\r
1095\r
1096/**\r
1097 Configure TCP6 protocol child.\r
1098\r
1099 @param[in] HttpInstance The HTTP instance private data.\r
1100 @param[in] Wrap The HTTP token's wrap data.\r
1101\r
1102 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1103 @retval Others Other error as indicated.\r
1104\r
1105**/\r
1106EFI_STATUS\r
1107HttpConfigureTcp6 (\r
1108 IN HTTP_PROTOCOL *HttpInstance,\r
1109 IN HTTP_TOKEN_WRAP *Wrap\r
1110 )\r
1111{\r
1112 EFI_STATUS Status;\r
1113 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1114 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1115 EFI_TCP6_OPTION *Tcp6Option;\r
1116 \r
1117 ASSERT (HttpInstance != NULL);\r
1118 \r
1119 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1120 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1121\r
1122 Tcp6CfgData->TrafficClass = 0;\r
1123 Tcp6CfgData->HopLimit = 255;\r
1124 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
1125 \r
1126 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1127 Tcp6Ap->ActiveFlag = TRUE;\r
1128 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1129 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1130 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1131 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1132\r
1133 Tcp6Option = Tcp6CfgData->ControlOption;\r
1134 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1135 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1136 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1137 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1138 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1139 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1140 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1141 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1142 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1143 Tcp6Option->EnableNagle = TRUE;\r
1144\r
1145 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1146 if (EFI_ERROR (Status)) {\r
1147 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1148 return Status;\r
1149 }\r
1150 \r
1151 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1152 if (EFI_ERROR (Status)) {\r
1153 return Status;\r
1154 }\r
1155\r
1156 Status = HttpCreateTcpTxEvent (Wrap);\r
1157 if (EFI_ERROR (Status)) {\r
1158 return Status;\r
1159 }\r
1160\r
1161 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1162\r
1163 return EFI_SUCCESS;\r
1164 \r
1165}\r
1166\r
1167/**\r
1168 Check existing TCP connection, if in error state, recover TCP4 connection.\r
1169\r
1170 @param[in] HttpInstance The HTTP instance private data.\r
1171\r
1172 @retval EFI_SUCCESS The TCP connection is established.\r
1173 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1174 @retval Others Other error as indicated.\r
1175\r
1176**/\r
1177EFI_STATUS\r
1178HttpConnectTcp4 (\r
1179 IN HTTP_PROTOCOL *HttpInstance\r
1180 )\r
1181{\r
1182 EFI_STATUS Status;\r
1183 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1184\r
1185\r
1186 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
1187 return EFI_NOT_READY;\r
1188 }\r
1189\r
1190 Status = HttpInstance->Tcp4->GetModeData(\r
1191 HttpInstance->Tcp4, \r
1192 &Tcp4State, \r
1193 NULL,\r
1194 NULL,\r
1195 NULL,\r
1196 NULL\r
1197 );\r
1198 if (EFI_ERROR(Status)){\r
1199 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1200 return Status;\r
1201 }\r
1202\r
1203 if (Tcp4State == Tcp4StateEstablished) {\r
1204 return EFI_SUCCESS;\r
1205 } else if (Tcp4State > Tcp4StateEstablished ) {\r
1206 HttpCloseConnection(HttpInstance);\r
1207 }\r
1208\r
1209 return HttpCreateConnection (HttpInstance);\r
1210}\r
1211\r
1212/**\r
1213 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1214\r
1215 @param[in] HttpInstance The HTTP instance private data.\r
1216\r
1217 @retval EFI_SUCCESS The TCP connection is established.\r
1218 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1219 @retval Others Other error as indicated.\r
1220\r
1221**/\r
1222EFI_STATUS\r
1223HttpConnectTcp6 (\r
1224 IN HTTP_PROTOCOL *HttpInstance\r
1225 )\r
1226{\r
1227 EFI_STATUS Status;\r
1228 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1229\r
1230 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
1231 return EFI_NOT_READY;\r
1232 }\r
1233\r
1234 Status = HttpInstance->Tcp6->GetModeData (\r
1235 HttpInstance->Tcp6,\r
1236 &Tcp6State,\r
1237 NULL,\r
1238 NULL,\r
1239 NULL,\r
1240 NULL\r
1241 );\r
1242 \r
1243 if (EFI_ERROR(Status)){\r
1244 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1245 return Status;\r
1246 }\r
1247\r
1248 if (Tcp6State == Tcp6StateEstablished) {\r
1249 return EFI_SUCCESS;\r
1250 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1251 HttpCloseConnection(HttpInstance);\r
1252 }\r
1253\r
1254 return HttpCreateConnection (HttpInstance);\r
1255}\r
1256\r
1257/**\r
1258 Initialize TCP related data.\r
1259\r
1260 @param[in] HttpInstance The HTTP instance private data.\r
1261 @param[in] Wrap The HTTP token's wrap data.\r
1262 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.\r
1263\r
1264 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1265 @retval Others Other error as indicated.\r
1266\r
1267**/\r
1268EFI_STATUS\r
1269HttpInitTcp (\r
1270 IN HTTP_PROTOCOL *HttpInstance,\r
1271 IN HTTP_TOKEN_WRAP *Wrap,\r
1272 IN BOOLEAN Configure\r
1273 )\r
1274{\r
1275 EFI_STATUS Status;\r
1276 ASSERT (HttpInstance != NULL);\r
1277\r
1278 if (!HttpInstance->LocalAddressIsIPv6) {\r
1279 //\r
1280 // Configure TCP instance.\r
1281 //\r
1282 if (Configure) {\r
1283 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1284 if (EFI_ERROR (Status)) {\r
1285 return Status;\r
1286 }\r
1287 }\r
1288\r
1289 //\r
1290 // Connect TCP.\r
1291 //\r
1292 Status = HttpConnectTcp4 (HttpInstance);\r
1293 if (EFI_ERROR (Status)) {\r
1294 return Status;\r
1295 }\r
1296 } else {\r
1297 //\r
1298 // Configure TCP instance.\r
1299 //\r
1300 if (Configure) {\r
1301 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1302 if (EFI_ERROR (Status)) {\r
1303 return Status;\r
1304 }\r
1305 }\r
1306\r
1307 //\r
1308 // Connect TCP.\r
1309 //\r
1310 Status = HttpConnectTcp6 (HttpInstance);\r
1311 if (EFI_ERROR (Status)) {\r
1312 return Status;\r
1313 }\r
1314 }\r
1315 \r
1316 return EFI_SUCCESS;\r
1317 \r
1318}\r
1319\r
1320/**\r
1321 Send the HTTP message through TCP4 or TCP6.\r
1322\r
1323 @param[in] HttpInstance The HTTP instance private data.\r
1324 @param[in] Wrap The HTTP token's wrap data.\r
1325 @param[in] TxString Buffer containing the HTTP message string.\r
1326 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1327\r
1328 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1329 @retval Others Other error as indicated.\r
1330\r
1331**/\r
1332EFI_STATUS\r
1333HttpTransmitTcp (\r
1334 IN HTTP_PROTOCOL *HttpInstance,\r
1335 IN HTTP_TOKEN_WRAP *Wrap,\r
1336 IN UINT8 *TxString,\r
1337 IN UINTN TxStringLen\r
1338 )\r
1339{\r
1340 EFI_STATUS Status;\r
1341 EFI_TCP4_IO_TOKEN *Tx4Token;\r
1342 EFI_TCP4_PROTOCOL *Tcp4;\r
1343 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1344 EFI_TCP6_PROTOCOL *Tcp6;\r
1345 \r
1346 if (!HttpInstance->LocalAddressIsIPv6) { \r
1347 Tcp4 = HttpInstance->Tcp4;\r
1348 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1349 \r
1350 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1351 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1352 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1353 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1354 \r
1355 Wrap->TcpWrap.IsTxDone = FALSE;\r
1356 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1357 if (EFI_ERROR (Status)) {\r
1358 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1359 return Status;\r
1360 }\r
1361\r
1362 } else {\r
1363 Tcp6 = HttpInstance->Tcp6;\r
1364 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
1365\r
1366 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1367 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1368 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1369 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1370\r
1371 Wrap->TcpWrap.IsTxDone = FALSE;\r
1372 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1373 if (EFI_ERROR (Status)) {\r
1374 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1375 return Status;\r
1376 }\r
1377 }\r
1378 \r
1379\r
1380 return Status;\r
1381}\r
1382\r
1383/**\r
1384 Check whether the user's token or event has already\r
1385 been enqueue on HTTP Tx or Rx Token list.\r
1386\r
1387 @param[in] Map The container of either user's transmit or receive\r
1388 token.\r
1389 @param[in] Item Current item to check against.\r
1390 @param[in] Context The Token to check againist.\r
1391\r
1392 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1393 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1394 context.\r
1395\r
1396**/\r
1397EFI_STATUS\r
1398EFIAPI\r
1399HttpTokenExist (\r
1400 IN NET_MAP *Map,\r
1401 IN NET_MAP_ITEM *Item,\r
1402 IN VOID *Context\r
1403 )\r
1404{\r
1405 EFI_HTTP_TOKEN *Token;\r
1406 EFI_HTTP_TOKEN *TokenInItem;\r
1407\r
1408 Token = (EFI_HTTP_TOKEN *) Context;\r
1409 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1410\r
1411 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1412 return EFI_ACCESS_DENIED;\r
1413 }\r
1414\r
1415 return EFI_SUCCESS;\r
1416}\r
1417\r
1418/**\r
1419 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
1420\r
1421 @param[in] Map The container of Tx4Token or Tx6Token.\r
1422 @param[in] Item Current item to check against.\r
1423 @param[in] Context The Token to check againist.\r
1424\r
1425 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1426 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1427\r
1428**/\r
1429EFI_STATUS\r
1430EFIAPI\r
1431HttpTcpNotReady (\r
1432 IN NET_MAP *Map,\r
1433 IN NET_MAP_ITEM *Item,\r
1434 IN VOID *Context\r
1435 )\r
1436{\r
1437 HTTP_TOKEN_WRAP *ValueInItem;\r
1438\r
1439 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1440\r
1441 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1442 return EFI_NOT_READY;\r
1443 }\r
1444 \r
1445 return EFI_SUCCESS;\r
1446}\r
1447\r
1448/**\r
1449 Transmit the HTTP mssage by processing the associated HTTP token.\r
1450\r
1451 @param[in] Map The container of Tx4Token or Tx6Token.\r
1452 @param[in] Item Current item to check against.\r
1453 @param[in] Context The Token to check againist.\r
1454\r
1455 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1456 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1457 queue.\r
1458\r
1459**/\r
1460EFI_STATUS\r
1461EFIAPI\r
1462HttpTcpTransmit (\r
1463 IN NET_MAP *Map,\r
1464 IN NET_MAP_ITEM *Item,\r
1465 IN VOID *Context\r
1466 )\r
1467{\r
1468 HTTP_TOKEN_WRAP *ValueInItem;\r
1469 EFI_STATUS Status;\r
1470 CHAR8 *RequestMsg;\r
1471 CHAR8 *Url;\r
1472 UINTN RequestMsgSize;\r
1473\r
1474 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1475 if (ValueInItem->TcpWrap.IsTxDone) {\r
1476 return EFI_SUCCESS;\r
1477 }\r
1478\r
1479 //\r
1480 // Parse the URI of the remote host.\r
1481 //\r
1482 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1483 if (Url == NULL) {\r
1484 return EFI_OUT_OF_RESOURCES;\r
1485 }\r
1486\r
1487 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1488\r
1489 //\r
1490 // Create request message.\r
1491 //\r
1492 Status = HttpGenRequestMessage (\r
1493 ValueInItem->HttpToken->Message,\r
1494 Url,\r
1495 &RequestMsg,\r
1496 &RequestMsgSize\r
1497 );\r
1498 FreePool (Url);\r
1499\r
1500 if (EFI_ERROR (Status)){\r
1501 return Status;\r
1502 }\r
1503\r
1504 //\r
1505 // Transmit the request message.\r
1506 //\r
1507 Status = HttpTransmitTcp (\r
1508 ValueInItem->HttpInstance,\r
1509 ValueInItem,\r
1510 (UINT8*) RequestMsg,\r
1511 RequestMsgSize\r
1512 );\r
1513 FreePool (RequestMsg);\r
1514 return Status;\r
1515}\r
1516\r
1517/**\r
1518 Receive the HTTP response by processing the associated HTTP token.\r
1519\r
1520 @param[in] Map The container of Rx4Token or Rx6Token.\r
1521 @param[in] Item Current item to check against.\r
1522 @param[in] Context The Token to check againist.\r
1523\r
1524 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1525 queue.\r
1526 @retval Others Other error as indicated.\r
1527\r
1528**/\r
1529EFI_STATUS\r
1530EFIAPI\r
1531HttpTcpReceive (\r
1532 IN NET_MAP *Map,\r
1533 IN NET_MAP_ITEM *Item,\r
1534 IN VOID *Context\r
1535 )\r
1536{\r
1537 //\r
1538 // Process the queued HTTP response.\r
1539 //\r
1540 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1541}\r
1542\r
1543/**\r
1544 Receive the HTTP header by processing the associated HTTP token.\r
1545\r
1546 @param[in] HttpInstance The HTTP instance private data.\r
1547 @param[in, out] SizeofHeaders The HTTP header length.\r
1548 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1549 @param[in] Timeout The time to wait for receiving the header packet.\r
1550 \r
1551 @retval EFI_SUCCESS The HTTP header is received. \r
1552 @retval Others Other errors as indicated.\r
1553\r
1554**/\r
1555EFI_STATUS\r
1556HttpTcpReceiveHeader (\r
1557 IN HTTP_PROTOCOL *HttpInstance,\r
1558 IN OUT UINTN *SizeofHeaders,\r
1559 IN OUT UINTN *BufferSize,\r
1560 IN EFI_EVENT Timeout\r
1561 )\r
1562{\r
1563 EFI_STATUS Status;\r
1564 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1565 EFI_TCP4_PROTOCOL *Tcp4;\r
1566 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1567 EFI_TCP6_PROTOCOL *Tcp6;\r
1568 CHAR8 **EndofHeader;\r
1569 CHAR8 **HttpHeaders;\r
1570 CHAR8 *Buffer;\r
1571\r
1572 ASSERT (HttpInstance != NULL);\r
1573\r
1574 EndofHeader = HttpInstance->EndofHeader;\r
1575 HttpHeaders = HttpInstance->HttpHeaders;\r
1576 Tcp4 = HttpInstance->Tcp4;\r
1577 Tcp6 = HttpInstance->Tcp6;\r
1578 Buffer = NULL;\r
1579 Rx4Token = NULL;\r
1580 Rx6Token = NULL;\r
1581 \r
1582 if (HttpInstance->LocalAddressIsIPv6) {\r
1583 ASSERT (Tcp6 != NULL);\r
1584 } else {\r
1585 ASSERT (Tcp4 != NULL);\r
1586 }\r
1587\r
1588 if (!HttpInstance->LocalAddressIsIPv6) {\r
1589 Rx4Token = &HttpInstance->Rx4Token;\r
1590 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1591 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1592 Status = EFI_OUT_OF_RESOURCES;\r
1593 return Status;\r
1594 }\r
1595 \r
1596 //\r
1597 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1598 //\r
1599 while (*EndofHeader == NULL) { \r
1600 HttpInstance->IsRxDone = FALSE;\r
1601 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1602 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1603 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1604 if (EFI_ERROR (Status)) {\r
1605 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1606 return Status;\r
1607 }\r
1608 \r
1609 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1610 Tcp4->Poll (Tcp4);\r
1611 }\r
1612\r
1613 if (!HttpInstance->IsRxDone) {\r
1614 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1615 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1616 }\r
1617 \r
1618 Status = Rx4Token->CompletionToken.Status;\r
1619 if (EFI_ERROR (Status)) {\r
1620 return Status;\r
1621 }\r
1622 \r
1623 //\r
1624 // Append the response string.\r
1625 //\r
1626 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1627 Buffer = AllocateZeroPool (*BufferSize);\r
1628 if (Buffer == NULL) {\r
1629 Status = EFI_OUT_OF_RESOURCES;\r
1630 return Status;\r
1631 }\r
1632 \r
1633 if (*HttpHeaders != NULL) {\r
1634 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1635 FreePool (*HttpHeaders);\r
1636 }\r
1637 \r
1638 CopyMem (\r
1639 Buffer + (*SizeofHeaders),\r
1640 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1641 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1642 );\r
1643 *HttpHeaders = Buffer;\r
1644 *SizeofHeaders = *BufferSize;\r
1645 \r
1646 //\r
1647 // Check whether we received end of HTTP headers.\r
1648 //\r
1649 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1650 }\r
1651 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1652 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1653 \r
1654 } else {\r
1655 Rx6Token = &HttpInstance->Rx6Token;\r
1656 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1657 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1658 Status = EFI_OUT_OF_RESOURCES;\r
1659 return Status;\r
1660 }\r
1661 \r
1662 //\r
1663 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1664 //\r
1665 while (*EndofHeader == NULL) { \r
1666 HttpInstance->IsRxDone = FALSE;\r
1667 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1668 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1669 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1670 if (EFI_ERROR (Status)) {\r
1671 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1672 return Status;\r
1673 }\r
1674 \r
1675 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1676 Tcp6->Poll (Tcp6);\r
1677 }\r
1678\r
1679 if (!HttpInstance->IsRxDone) {\r
1680 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1681 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1682 }\r
1683 \r
1684 Status = Rx6Token->CompletionToken.Status;\r
1685 if (EFI_ERROR (Status)) {\r
1686 return Status;\r
1687 }\r
1688 \r
1689 //\r
1690 // Append the response string.\r
1691 //\r
1692 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1693 Buffer = AllocateZeroPool (*BufferSize);\r
1694 if (Buffer == NULL) {\r
1695 Status = EFI_OUT_OF_RESOURCES;\r
1696 return Status;\r
1697 }\r
1698 \r
1699 if (*HttpHeaders != NULL) {\r
1700 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1701 FreePool (*HttpHeaders);\r
1702 }\r
1703 \r
1704 CopyMem (\r
1705 Buffer + (*SizeofHeaders),\r
1706 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1707 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1708 );\r
1709 *HttpHeaders = Buffer;\r
1710 *SizeofHeaders = *BufferSize;\r
1711 \r
1712 //\r
1713 // Check whether we received end of HTTP headers.\r
1714 //\r
1715 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1716 \r
1717 }\r
1718 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1719 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1720 } \r
1721\r
1722 //\r
1723 // Skip the CRLF after the HTTP headers.\r
1724 //\r
1725 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1726\r
1727 return EFI_SUCCESS;\r
1728}\r
1729\r
1730/**\r
1731 Receive the HTTP body by processing the associated HTTP token.\r
1732\r
1733 @param[in] Wrap The HTTP token's wrap data.\r
1734 @param[in] HttpMsg The HTTP message data.\r
1735 @param[in] Timeout The time to wait for receiving the body packet.\r
1736\r
1737 @retval EFI_SUCCESS The HTTP body is received. \r
1738 @retval Others Other error as indicated.\r
1739\r
1740**/\r
1741EFI_STATUS\r
1742HttpTcpReceiveBody (\r
1743 IN HTTP_TOKEN_WRAP *Wrap,\r
1744 IN EFI_HTTP_MESSAGE *HttpMsg,\r
1745 IN EFI_EVENT Timeout\r
1746 )\r
1747{\r
1748 EFI_STATUS Status;\r
1749 HTTP_PROTOCOL *HttpInstance;\r
1750 EFI_TCP6_PROTOCOL *Tcp6;\r
1751 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1752 EFI_TCP4_PROTOCOL *Tcp4;\r
1753 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1754 \r
1755 HttpInstance = Wrap->HttpInstance;\r
1756 Tcp4 = HttpInstance->Tcp4;\r
1757 Tcp6 = HttpInstance->Tcp6;\r
1758 Rx4Token = NULL;\r
1759 Rx6Token = NULL;\r
1760 \r
1761 if (HttpInstance->LocalAddressIsIPv6) {\r
1762 ASSERT (Tcp6 != NULL);\r
1763 } else {\r
1764 ASSERT (Tcp4 != NULL);\r
1765 }\r
1766 \r
1767 if (HttpInstance->LocalAddressIsIPv6) {\r
1768 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1769 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1770 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1771 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1772 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1773\r
1774 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1775 if (EFI_ERROR (Status)) {\r
1776 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1777 return Status;\r
1778 }\r
1779\r
1780 while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1781 Tcp6->Poll (Tcp6);\r
1782 }\r
1783\r
1784 if (!Wrap->TcpWrap.IsRxDone) {\r
1785 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1786 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1787 Wrap->HttpToken->Status = Rx6Token->CompletionToken.Status;\r
1788 gBS->SignalEvent (Wrap->HttpToken->Event);\r
1789 }\r
1790 } else {\r
1791 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1792 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1793 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1794 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1795 \r
1796 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1797 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1798 if (EFI_ERROR (Status)) {\r
1799 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1800 return Status;\r
1801 }\r
1802\r
1803 while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1804 Tcp4->Poll (Tcp4);\r
1805 }\r
1806\r
1807 if (!Wrap->TcpWrap.IsRxDone) {\r
1808 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1809 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1810 Wrap->HttpToken->Status = Rx4Token->CompletionToken.Status;\r
1811 gBS->SignalEvent (Wrap->HttpToken->Event);\r
1812 }\r
1813 }\r
1814\r
1815 return EFI_SUCCESS;\r
1816\r
1817}\r
1818\r
1819/**\r
1820 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1821\r
1822 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1823 \r
1824**/\r
1825VOID\r
1826HttpTcpTokenCleanup (\r
1827 IN HTTP_TOKEN_WRAP *Wrap\r
1828 )\r
1829{ \r
1830 HTTP_PROTOCOL *HttpInstance;\r
1831 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1832 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1833\r
1834 ASSERT (Wrap != NULL);\r
1835 HttpInstance = Wrap->HttpInstance;\r
1836 Rx4Token = NULL;\r
1837 Rx6Token = NULL;\r
1838 \r
1839 if (HttpInstance->LocalAddressIsIPv6) {\r
1840 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1841 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1842 }\r
1843\r
1844 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1845 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1846 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1847 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1848 }\r
1849 FreePool (Wrap);\r
1850\r
1851 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1852 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1853 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1854 }\r
1855\r
1856 Rx6Token = &HttpInstance->Rx6Token;\r
1857 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1858 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1859 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1860 }\r
1861 \r
1862 } else {\r
1863 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1864 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
1865 }\r
1866 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1867 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1868 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1869 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1870 }\r
1871 FreePool (Wrap);\r
1872\r
1873 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1874 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1875 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1876 }\r
1877 \r
1878 Rx4Token = &HttpInstance->Rx4Token;\r
1879 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1880 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1881 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1882 }\r
1883 }\r
1884\r
1885}\r