]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg/HttpDxe: Don't free Wrap in HttpTcpReceiveNotifyDpc
[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 return ;\r
156 }\r
157\r
158 } else {\r
159 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
160 \r
161 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
162 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
163 gBS->SignalEvent (Wrap->HttpToken->Event);\r
164 return ;\r
165 }\r
166 }\r
167\r
168 //\r
169 // Check whether we receive a complete HTTP message.\r
170 //\r
171 ASSERT (HttpInstance->MsgParser != NULL);\r
172 if (UsingIpv6) {\r
173 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
174 } else {\r
175 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
176 }\r
177\r
178 Status = HttpParseMessageBody (\r
179 HttpInstance->MsgParser,\r
180 Length,\r
181 Wrap->HttpToken->Message->Body\r
182 );\r
183 if (EFI_ERROR (Status)) {\r
184 return ;\r
185 }\r
186\r
187 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {\r
188 //\r
189 // Free the MsgParse since we already have a full HTTP message.\r
190 //\r
191 HttpFreeMsgParser (HttpInstance->MsgParser);\r
192 HttpInstance->MsgParser = NULL;\r
193 }\r
194\r
195 Wrap->HttpToken->Message->BodyLength = Length;\r
196 ASSERT (HttpInstance->CacheBody == NULL);\r
197 //\r
198 // We receive part of header of next HTTP msg.\r
199 //\r
200 if (HttpInstance->NextMsg != NULL) {\r
201 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg - \r
202 (CHAR8 *) Wrap->HttpToken->Message->Body;\r
203 HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;\r
204 if (HttpInstance->CacheLen != 0) {\r
205 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);\r
206 if (HttpInstance->CacheBody == NULL) {\r
207 return ;\r
208 }\r
209 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);\r
210 HttpInstance->NextMsg = HttpInstance->CacheBody;\r
211 HttpInstance->CacheOffset = 0;\r
212 }\r
213 }\r
214\r
215 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);\r
216 if (Item != NULL) {\r
217 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
218 }\r
219\r
220\r
221 Wrap->TcpWrap.IsRxDone = TRUE;\r
222 if (UsingIpv6) {\r
223 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
224 } else {\r
225 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
226 }\r
227 \r
228\r
229 gBS->SignalEvent (Wrap->HttpToken->Event);\r
230\r
231 //\r
232 // Check pending RxTokens and receive the HTTP message.\r
233 //\r
234 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
235}\r
236\r
237/**\r
238 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.\r
239\r
240 @param Event The receive event delivered to TCP for receive.\r
241 @param Context Context for the callback.\r
242\r
243**/\r
244VOID\r
245EFIAPI\r
246HttpTcpReceiveNotify (\r
247 IN EFI_EVENT Event,\r
248 IN VOID *Context\r
249 )\r
250{\r
251 //\r
252 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
253 //\r
254 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
255}\r
256\r
257/**\r
258 Create events for the TCP connection token and TCP close token.\r
259\r
260 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
261\r
262 @retval EFI_SUCCESS The events are created successfully.\r
263 @retval others Other error as indicated.\r
264\r
265**/\r
266EFI_STATUS\r
267HttpCreateTcpConnCloseEvent (\r
268 IN HTTP_PROTOCOL *HttpInstance\r
269 )\r
270{\r
271 EFI_STATUS Status;\r
272\r
273 if (!HttpInstance->LocalAddressIsIPv6) {\r
274 //\r
275 // Create events for variuos asynchronous operations.\r
276 //\r
277 Status = gBS->CreateEvent (\r
278 EVT_NOTIFY_SIGNAL,\r
279 TPL_NOTIFY,\r
280 HttpCommonNotify,\r
281 &HttpInstance->IsTcp4ConnDone,\r
282 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
283 );\r
284 if (EFI_ERROR (Status)) {\r
285 goto ERROR;\r
286 }\r
287\r
288 //\r
289 // Initialize Tcp4CloseToken\r
290 //\r
291 Status = gBS->CreateEvent (\r
292 EVT_NOTIFY_SIGNAL,\r
293 TPL_NOTIFY,\r
294 HttpCommonNotify,\r
295 &HttpInstance->IsTcp4CloseDone,\r
296 &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
297 );\r
298 if (EFI_ERROR (Status)) {\r
299 goto ERROR;\r
300 }\r
301 \r
302 } else {\r
303 //\r
304 // Create events for variuos asynchronous operations.\r
305 //\r
306 Status = gBS->CreateEvent (\r
307 EVT_NOTIFY_SIGNAL,\r
308 TPL_NOTIFY,\r
309 HttpCommonNotify,\r
310 &HttpInstance->IsTcp6ConnDone,\r
311 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
312 );\r
313 if (EFI_ERROR (Status)) {\r
314 goto ERROR;\r
315 }\r
316\r
317 //\r
318 // Initialize Tcp6CloseToken\r
319 //\r
320 Status = gBS->CreateEvent (\r
321 EVT_NOTIFY_SIGNAL,\r
322 TPL_NOTIFY,\r
323 HttpCommonNotify,\r
324 &HttpInstance->IsTcp6CloseDone,\r
325 &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
326 );\r
327 if (EFI_ERROR (Status)) {\r
328 goto ERROR;\r
329 }\r
330 }\r
331 \r
332 return EFI_SUCCESS;\r
333\r
334ERROR:\r
335 //\r
336 // Error handling\r
337 //\r
338 HttpCloseTcpConnCloseEvent (HttpInstance);\r
339\r
340 return Status;\r
341}\r
342\r
343\r
344/**\r
345 Close events in the TCP connection token and TCP close token.\r
346\r
347 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
348\r
349**/\r
350VOID\r
351HttpCloseTcpConnCloseEvent (\r
352 IN HTTP_PROTOCOL *HttpInstance\r
353 )\r
354{\r
355 ASSERT (HttpInstance != NULL);\r
356\r
357 if (HttpInstance->LocalAddressIsIPv6) {\r
358 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
359 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
360 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
361 }\r
362\r
363 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
364 gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
365 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
366 }\r
367\r
368 } else {\r
369 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
370 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
371 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
372 }\r
373\r
374 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
375 gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
376 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
377 }\r
378 }\r
379 \r
380}\r
381\r
382/**\r
383 Create event for the TCP transmit token.\r
384\r
385 @param[in] Wrap Point to HTTP token's wrap data.\r
386\r
387 @retval EFI_SUCCESS The events is created successfully.\r
388 @retval others Other error as indicated.\r
389\r
390**/\r
391EFI_STATUS\r
392HttpCreateTcpTxEvent (\r
393 IN HTTP_TOKEN_WRAP *Wrap\r
394 )\r
395{\r
396 EFI_STATUS Status;\r
397 HTTP_PROTOCOL *HttpInstance;\r
398 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
399\r
400 HttpInstance = Wrap->HttpInstance;\r
401 TcpWrap = &Wrap->TcpWrap;\r
402\r
403 if (!HttpInstance->LocalAddressIsIPv6) {\r
404 Status = gBS->CreateEvent (\r
405 EVT_NOTIFY_SIGNAL,\r
406 TPL_NOTIFY,\r
407 HttpTcpTransmitNotify,\r
408 Wrap,\r
409 &TcpWrap->Tx4Token.CompletionToken.Event\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 return Status;\r
413 }\r
414 \r
415 TcpWrap->Tx4Data.Push = TRUE;\r
416 TcpWrap->Tx4Data.Urgent = FALSE;\r
417 TcpWrap->Tx4Data.FragmentCount = 1;\r
418 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
419 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
420\r
421 } else {\r
422 Status = gBS->CreateEvent (\r
423 EVT_NOTIFY_SIGNAL,\r
424 TPL_NOTIFY,\r
425 HttpTcpTransmitNotify,\r
426 Wrap,\r
427 &TcpWrap->Tx6Token.CompletionToken.Event\r
428 );\r
429 if (EFI_ERROR (Status)) {\r
430 return Status;\r
431 }\r
432\r
433 TcpWrap->Tx6Data.Push = TRUE;\r
434 TcpWrap->Tx6Data.Urgent = FALSE;\r
435 TcpWrap->Tx6Data.FragmentCount = 1;\r
436 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
437 TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
438 \r
439 \r
440 }\r
441 \r
442 return EFI_SUCCESS;\r
443}\r
444\r
445/**\r
446 Create event for the TCP receive token which is used to receive HTTP header.\r
447\r
448 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
449\r
450 @retval EFI_SUCCESS The events is created successfully.\r
451 @retval others Other error as indicated.\r
452\r
453**/\r
454EFI_STATUS\r
455HttpCreateTcpRxEventForHeader (\r
456 IN HTTP_PROTOCOL *HttpInstance\r
457 )\r
458{\r
459 EFI_STATUS Status;\r
460\r
461 if (!HttpInstance->LocalAddressIsIPv6) {\r
462 Status = gBS->CreateEvent (\r
463 EVT_NOTIFY_SIGNAL,\r
464 TPL_NOTIFY,\r
465 HttpCommonNotify,\r
466 &HttpInstance->IsRxDone,\r
467 &HttpInstance->Rx4Token.CompletionToken.Event\r
468 );\r
469 if (EFI_ERROR (Status)) {\r
470 return Status;\r
471 }\r
472 \r
473 HttpInstance->Rx4Data.FragmentCount = 1;\r
474 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
475 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
476\r
477 } else {\r
478 Status = gBS->CreateEvent (\r
479 EVT_NOTIFY_SIGNAL,\r
480 TPL_NOTIFY,\r
481 HttpCommonNotify,\r
482 &HttpInstance->IsRxDone,\r
483 &HttpInstance->Rx6Token.CompletionToken.Event\r
484 );\r
485 if (EFI_ERROR (Status)) {\r
486 return Status;\r
487 }\r
488\r
489 HttpInstance->Rx6Data.FragmentCount =1;\r
490 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
491 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
492 \r
493 }\r
494\r
495\r
496 return EFI_SUCCESS;\r
497}\r
498\r
499/**\r
500 Create event for the TCP receive token which is used to receive HTTP body.\r
501\r
502 @param[in] Wrap Point to HTTP token's wrap data.\r
503\r
504 @retval EFI_SUCCESS The events is created successfully.\r
505 @retval others Other error as indicated.\r
506\r
507**/\r
508EFI_STATUS\r
509HttpCreateTcpRxEvent (\r
510 IN HTTP_TOKEN_WRAP *Wrap \r
511 )\r
512{\r
513 EFI_STATUS Status;\r
514 HTTP_PROTOCOL *HttpInstance;\r
515 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
516\r
517 HttpInstance = Wrap->HttpInstance;\r
518 TcpWrap = &Wrap->TcpWrap;\r
519 if (!HttpInstance->LocalAddressIsIPv6) {\r
520 Status = gBS->CreateEvent (\r
521 EVT_NOTIFY_SIGNAL,\r
522 TPL_NOTIFY,\r
523 HttpTcpReceiveNotify,\r
524 Wrap,\r
525 &TcpWrap->Rx4Token.CompletionToken.Event\r
526 );\r
527 if (EFI_ERROR (Status)) {\r
528 return Status;\r
529 }\r
530 \r
531 TcpWrap->Rx4Data.FragmentCount = 1;\r
532 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
533 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
534\r
535 } else {\r
536 Status = gBS->CreateEvent (\r
537 EVT_NOTIFY_SIGNAL,\r
538 TPL_NOTIFY,\r
539 HttpTcpReceiveNotify,\r
540 Wrap,\r
541 &TcpWrap->Rx6Token.CompletionToken.Event\r
542 ); \r
543 if (EFI_ERROR (Status)) {\r
544 return Status;\r
545 }\r
546\r
547 TcpWrap->Rx6Data.FragmentCount = 1;\r
548 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
549 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
550 }\r
551 \r
552 return EFI_SUCCESS;\r
553}\r
554\r
555/**\r
556 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
557\r
558 @param[in] Wrap Pointer to HTTP token's wrap data.\r
559 \r
560**/\r
561VOID\r
562HttpCloseTcpRxEvent (\r
563 IN HTTP_TOKEN_WRAP *Wrap\r
564 )\r
565{\r
566 HTTP_PROTOCOL *HttpInstance;\r
567\r
568 ASSERT (Wrap != NULL);\r
569 HttpInstance = Wrap->HttpInstance;\r
570 \r
571 if (HttpInstance->LocalAddressIsIPv6) {\r
572 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
573 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
574 }\r
575\r
576 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
577 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
578 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
579 }\r
580 } else {\r
581 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
582 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
583 }\r
584 \r
585 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
586 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
587 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
588 }\r
589 }\r
590}\r
591\r
592/**\r
593 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
594\r
595 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
596 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
597\r
598 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. \r
599 @retval Others Other error as indicated.\r
600\r
601**/\r
602EFI_STATUS\r
603HttpInitProtocol (\r
604 IN OUT HTTP_PROTOCOL *HttpInstance,\r
605 IN BOOLEAN IpVersion\r
606 )\r
607{\r
608 EFI_STATUS Status;\r
609 VOID *Interface;\r
610 BOOLEAN UsingIpv6;\r
611 \r
612 ASSERT (HttpInstance != NULL);\r
613 UsingIpv6 = IpVersion;\r
614 \r
615 if (!UsingIpv6) {\r
616 //\r
617 // Create TCP4 child.\r
618 //\r
619 Status = NetLibCreateServiceChild (\r
620 HttpInstance->Service->ControllerHandle,\r
621 HttpInstance->Service->ImageHandle,\r
622 &gEfiTcp4ServiceBindingProtocolGuid,\r
623 &HttpInstance->Tcp4ChildHandle\r
624 );\r
625\r
626 if (EFI_ERROR (Status)) {\r
627 goto ON_ERROR;\r
628 }\r
629\r
630 Status = gBS->OpenProtocol (\r
631 HttpInstance->Tcp4ChildHandle,\r
632 &gEfiTcp4ProtocolGuid,\r
633 (VOID **) &Interface,\r
634 HttpInstance->Service->ImageHandle,\r
635 HttpInstance->Service->ControllerHandle,\r
636 EFI_OPEN_PROTOCOL_BY_DRIVER\r
637 );\r
638 \r
639 if (EFI_ERROR (Status)) {\r
640 goto ON_ERROR;\r
641 }\r
642\r
643 Status = gBS->OpenProtocol (\r
644 HttpInstance->Tcp4ChildHandle,\r
645 &gEfiTcp4ProtocolGuid,\r
646 (VOID **) &HttpInstance->Tcp4,\r
647 HttpInstance->Service->ImageHandle,\r
648 HttpInstance->Handle,\r
649 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
650 );\r
651 if (EFI_ERROR(Status)) {\r
652 goto ON_ERROR;\r
653 }\r
654\r
655 Status = gBS->OpenProtocol (\r
656 HttpInstance->Service->Tcp4ChildHandle,\r
657 &gEfiTcp4ProtocolGuid,\r
658 (VOID **) &Interface,\r
659 HttpInstance->Service->ImageHandle,\r
660 HttpInstance->Handle,\r
661 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
662 );\r
663 if (EFI_ERROR(Status)) {\r
664 goto ON_ERROR;\r
665 }\r
666 } else {\r
667 //\r
668 // Create TCP6 Child.\r
669 //\r
670 Status = NetLibCreateServiceChild (\r
671 HttpInstance->Service->ControllerHandle,\r
672 HttpInstance->Service->ImageHandle,\r
673 &gEfiTcp6ServiceBindingProtocolGuid,\r
674 &HttpInstance->Tcp6ChildHandle\r
675 );\r
676\r
677 if (EFI_ERROR (Status)) {\r
678 goto ON_ERROR;\r
679 }\r
680\r
681 Status = gBS->OpenProtocol (\r
682 HttpInstance->Tcp6ChildHandle,\r
683 &gEfiTcp6ProtocolGuid,\r
684 (VOID **) &Interface,\r
685 HttpInstance->Service->ImageHandle,\r
686 HttpInstance->Service->ControllerHandle,\r
687 EFI_OPEN_PROTOCOL_BY_DRIVER\r
688 );\r
689 \r
690 if (EFI_ERROR (Status)) {\r
691 goto ON_ERROR;\r
692 }\r
693\r
694 Status = gBS->OpenProtocol (\r
695 HttpInstance->Tcp6ChildHandle,\r
696 &gEfiTcp6ProtocolGuid,\r
697 (VOID **) &HttpInstance->Tcp6,\r
698 HttpInstance->Service->ImageHandle,\r
699 HttpInstance->Handle,\r
700 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
701 );\r
702 \r
703 if (EFI_ERROR(Status)) {\r
704 goto ON_ERROR;\r
705 } \r
706\r
707 Status = gBS->OpenProtocol (\r
708 HttpInstance->Service->Tcp6ChildHandle,\r
709 &gEfiTcp6ProtocolGuid,\r
710 (VOID **) &Interface,\r
711 HttpInstance->Service->ImageHandle,\r
712 HttpInstance->Handle,\r
713 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
714 );\r
715\r
716 if (EFI_ERROR(Status)) {\r
717 goto ON_ERROR;\r
718 }\r
719 }\r
720 \r
721 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
722 if (HttpInstance->Url == NULL) {\r
723 Status = EFI_OUT_OF_RESOURCES;\r
724 goto ON_ERROR;\r
725 }\r
726\r
727 return EFI_SUCCESS;\r
728\r
729ON_ERROR:\r
730 \r
731 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
732 gBS->CloseProtocol (\r
733 HttpInstance->Tcp4ChildHandle,\r
734 &gEfiTcp4ProtocolGuid,\r
735 HttpInstance->Service->ImageHandle,\r
736 HttpInstance->Service->ControllerHandle\r
737 );\r
738\r
739 gBS->CloseProtocol (\r
740 HttpInstance->Tcp4ChildHandle,\r
741 &gEfiTcp4ProtocolGuid,\r
742 HttpInstance->Service->ImageHandle,\r
743 HttpInstance->Handle\r
744 ); \r
745 \r
746 NetLibDestroyServiceChild (\r
747 HttpInstance->Service->ControllerHandle,\r
748 HttpInstance->Service->ImageHandle,\r
749 &gEfiTcp4ServiceBindingProtocolGuid,\r
750 HttpInstance->Tcp4ChildHandle\r
751 );\r
752 }\r
753 \r
754 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
755 gBS->CloseProtocol (\r
756 HttpInstance->Service->Tcp4ChildHandle,\r
757 &gEfiTcp4ProtocolGuid,\r
758 HttpInstance->Service->ImageHandle,\r
759 HttpInstance->Handle\r
760 );\r
761 }\r
762 \r
763 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
764 gBS->CloseProtocol (\r
765 HttpInstance->Tcp6ChildHandle,\r
766 &gEfiTcp6ProtocolGuid,\r
767 HttpInstance->Service->ImageHandle,\r
768 HttpInstance->Service->ControllerHandle\r
769 );\r
770\r
771 gBS->CloseProtocol (\r
772 HttpInstance->Tcp6ChildHandle,\r
773 &gEfiTcp6ProtocolGuid,\r
774 HttpInstance->Service->ImageHandle,\r
775 HttpInstance->Handle\r
776 );\r
777 \r
778 NetLibDestroyServiceChild (\r
779 HttpInstance->Service->ControllerHandle,\r
780 HttpInstance->Service->ImageHandle,\r
781 &gEfiTcp6ServiceBindingProtocolGuid,\r
782 HttpInstance->Tcp6ChildHandle\r
783 );\r
784 }\r
785 \r
786 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
787 gBS->CloseProtocol (\r
788 HttpInstance->Service->Tcp6ChildHandle,\r
789 &gEfiTcp6ProtocolGuid,\r
790 HttpInstance->Service->ImageHandle,\r
791 HttpInstance->Handle\r
792 );\r
793 }\r
794\r
795 return EFI_UNSUPPORTED;\r
796 \r
797}\r
798\r
799/**\r
800 Clean up the HTTP child, release all the resources used by it.\r
801\r
802 @param[in] HttpInstance The HTTP child to clean up.\r
803\r
804**/\r
805VOID\r
806HttpCleanProtocol (\r
807 IN HTTP_PROTOCOL *HttpInstance\r
808 )\r
809{\r
810 HttpCloseConnection (HttpInstance);\r
811 \r
812 HttpCloseTcpConnCloseEvent (HttpInstance);\r
813\r
814 if (HttpInstance->TimeoutEvent != NULL) {\r
815 gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
816 HttpInstance->TimeoutEvent = NULL;\r
817 }\r
818\r
819 if (HttpInstance->CacheBody != NULL) {\r
820 FreePool (HttpInstance->CacheBody);\r
821 HttpInstance->CacheBody = NULL;\r
822 HttpInstance->NextMsg = NULL;\r
823 }\r
824\r
825 if (HttpInstance->RemoteHost != NULL) {\r
826 FreePool (HttpInstance->RemoteHost);\r
827 HttpInstance->RemoteHost = NULL;\r
828 }\r
829\r
830 if (HttpInstance->MsgParser != NULL) {\r
831 HttpFreeMsgParser (HttpInstance->MsgParser);\r
832 HttpInstance->MsgParser = NULL;\r
833 }\r
834 \r
835 if (HttpInstance->Url != NULL) {\r
836 FreePool (HttpInstance->Url);\r
837 HttpInstance->Url = NULL;\r
838 }\r
839 \r
840 NetMapClean (&HttpInstance->TxTokens);\r
841 NetMapClean (&HttpInstance->RxTokens);\r
842\r
843 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
844 gBS->CloseProtocol (\r
845 HttpInstance->Tcp4ChildHandle,\r
846 &gEfiTcp4ProtocolGuid,\r
847 HttpInstance->Service->ImageHandle,\r
848 HttpInstance->Service->ControllerHandle\r
849 );\r
850\r
851 gBS->CloseProtocol (\r
852 HttpInstance->Tcp4ChildHandle,\r
853 &gEfiTcp4ProtocolGuid,\r
854 HttpInstance->Service->ImageHandle,\r
855 HttpInstance->Handle\r
856 );\r
857 \r
858 NetLibDestroyServiceChild (\r
859 HttpInstance->Service->ControllerHandle,\r
860 HttpInstance->Service->ImageHandle,\r
861 &gEfiTcp4ServiceBindingProtocolGuid,\r
862 HttpInstance->Tcp4ChildHandle\r
863 );\r
864 }\r
865\r
866 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
867 gBS->CloseProtocol (\r
868 HttpInstance->Service->Tcp4ChildHandle,\r
869 &gEfiTcp4ProtocolGuid,\r
870 HttpInstance->Service->ImageHandle,\r
871 HttpInstance->Handle\r
872 );\r
873 } \r
874\r
875 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
876 gBS->CloseProtocol (\r
877 HttpInstance->Tcp6ChildHandle,\r
878 &gEfiTcp6ProtocolGuid,\r
879 HttpInstance->Service->ImageHandle,\r
880 HttpInstance->Service->ControllerHandle\r
881 );\r
882\r
883 gBS->CloseProtocol (\r
884 HttpInstance->Tcp6ChildHandle,\r
885 &gEfiTcp6ProtocolGuid,\r
886 HttpInstance->Service->ImageHandle,\r
887 HttpInstance->Handle\r
888 );\r
889 \r
890 NetLibDestroyServiceChild (\r
891 HttpInstance->Service->ControllerHandle,\r
892 HttpInstance->Service->ImageHandle,\r
893 &gEfiTcp6ServiceBindingProtocolGuid,\r
894 HttpInstance->Tcp6ChildHandle\r
895 );\r
896 }\r
897 \r
898 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
899 gBS->CloseProtocol (\r
900 HttpInstance->Service->Tcp6ChildHandle,\r
901 &gEfiTcp6ProtocolGuid,\r
902 HttpInstance->Service->ImageHandle,\r
903 HttpInstance->Handle\r
904 );\r
905 }\r
906 \r
907}\r
908\r
909/**\r
910 Establish TCP connection with HTTP server.\r
911\r
912 @param[in] HttpInstance The HTTP instance private data.\r
913\r
914 @retval EFI_SUCCESS The TCP connection is established.\r
915 @retval Others Other error as indicated.\r
916\r
917**/\r
918EFI_STATUS\r
919HttpCreateConnection (\r
920 IN HTTP_PROTOCOL *HttpInstance\r
921 )\r
922{\r
923 EFI_STATUS Status;\r
924\r
925 //\r
926 // Connect to Http server\r
927 //\r
928 if (!HttpInstance->LocalAddressIsIPv6) {\r
929 HttpInstance->IsTcp4ConnDone = FALSE;\r
930 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
931 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
932 if (EFI_ERROR (Status)) {\r
933 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
934 return Status;\r
935 }\r
936 \r
937 while (!HttpInstance->IsTcp4ConnDone) {\r
938 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
939 }\r
940 \r
941 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
942 \r
943 } else {\r
944 HttpInstance->IsTcp6ConnDone = FALSE;\r
945 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
946 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
947 if (EFI_ERROR (Status)) {\r
948 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
949 return Status;\r
950 }\r
951\r
952 while(!HttpInstance->IsTcp6ConnDone) {\r
953 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
954 }\r
955\r
956 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
957 }\r
958 \r
959 if (!EFI_ERROR (Status)) {\r
960 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
961 }\r
962\r
963 return Status;\r
964}\r
965\r
966/**\r
967 Close existing TCP connection.\r
968\r
969 @param[in] HttpInstance The HTTP instance private data.\r
970\r
971 @retval EFI_SUCCESS The TCP connection is closed.\r
972 @retval Others Other error as indicated.\r
973\r
974**/\r
975EFI_STATUS\r
976HttpCloseConnection (\r
977 IN HTTP_PROTOCOL *HttpInstance\r
978 )\r
979{\r
980 EFI_STATUS Status;\r
981\r
982 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
983\r
984 if (HttpInstance->LocalAddressIsIPv6) {\r
985 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
986 HttpInstance->IsTcp6CloseDone = FALSE;\r
987 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
988 if (EFI_ERROR (Status)) {\r
989 return Status;\r
990 }\r
991\r
992 while (!HttpInstance->IsTcp6CloseDone) {\r
993 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
994 }\r
995 \r
996 } else {\r
997 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
998 HttpInstance->IsTcp4CloseDone = FALSE;\r
999 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
1000 if (EFI_ERROR (Status)) {\r
1001 return Status;\r
1002 }\r
1003\r
1004 while (!HttpInstance->IsTcp4CloseDone) {\r
1005 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1006 }\r
1007 }\r
1008\r
1009 }\r
1010\r
1011 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
1012 return EFI_SUCCESS;\r
1013}\r
1014\r
1015/**\r
1016 Configure TCP4 protocol child.\r
1017\r
1018 @param[in] HttpInstance The HTTP instance private data.\r
1019 @param[in] Wrap The HTTP token's wrap data.\r
1020\r
1021 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1022 @retval Others Other error as indicated.\r
1023\r
1024**/\r
1025EFI_STATUS\r
1026HttpConfigureTcp4 (\r
1027 IN HTTP_PROTOCOL *HttpInstance,\r
1028 IN HTTP_TOKEN_WRAP *Wrap\r
1029 )\r
1030{\r
1031 EFI_STATUS Status;\r
1032 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1033 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1034 EFI_TCP4_OPTION *Tcp4Option;\r
1035\r
1036 ASSERT (HttpInstance != NULL);\r
1037\r
1038\r
1039 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1040 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1041 \r
1042 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1043 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1044 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1045\r
1046 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1047 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1048 if (!Tcp4AP->UseDefaultAddress) {\r
1049 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1050 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1051 }\r
1052 \r
1053 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1054 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1055 Tcp4AP->ActiveFlag = TRUE;\r
1056 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1057\r
1058 Tcp4Option = Tcp4CfgData->ControlOption;\r
1059 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1060 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1061 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1062 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1063 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1064 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1065 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1066 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1067 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1068 Tcp4Option->EnableNagle = TRUE;\r
1069 Tcp4CfgData->ControlOption = Tcp4Option;\r
1070\r
1071 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1072 if (EFI_ERROR (Status)) {\r
1073 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1074 return Status;\r
1075 }\r
1076\r
1077 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1078 if (EFI_ERROR (Status)) {\r
1079 return Status;\r
1080 }\r
1081\r
1082 Status = HttpCreateTcpTxEvent (Wrap);\r
1083 if (EFI_ERROR (Status)) {\r
1084 return Status;\r
1085 }\r
1086\r
1087 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1088\r
1089 return EFI_SUCCESS;\r
1090}\r
1091\r
1092/**\r
1093 Configure TCP6 protocol child.\r
1094\r
1095 @param[in] HttpInstance The HTTP instance private data.\r
1096 @param[in] Wrap The HTTP token's wrap data.\r
1097\r
1098 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1099 @retval Others Other error as indicated.\r
1100\r
1101**/\r
1102EFI_STATUS\r
1103HttpConfigureTcp6 (\r
1104 IN HTTP_PROTOCOL *HttpInstance,\r
1105 IN HTTP_TOKEN_WRAP *Wrap\r
1106 )\r
1107{\r
1108 EFI_STATUS Status;\r
1109 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1110 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1111 EFI_TCP6_OPTION *Tcp6Option;\r
1112 \r
1113 ASSERT (HttpInstance != NULL);\r
1114 \r
1115 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1116 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1117\r
1118 Tcp6CfgData->TrafficClass = 0;\r
1119 Tcp6CfgData->HopLimit = 255;\r
1120 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
1121 \r
1122 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1123 Tcp6Ap->ActiveFlag = TRUE;\r
1124 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1125 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1126 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1127 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1128\r
1129 Tcp6Option = Tcp6CfgData->ControlOption;\r
1130 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1131 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1132 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1133 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1134 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1135 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1136 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1137 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1138 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1139 Tcp6Option->EnableNagle = TRUE;\r
1140\r
1141 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1142 if (EFI_ERROR (Status)) {\r
1143 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1144 return Status;\r
1145 }\r
1146 \r
1147 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1148 if (EFI_ERROR (Status)) {\r
1149 return Status;\r
1150 }\r
1151\r
1152 Status = HttpCreateTcpTxEvent (Wrap);\r
1153 if (EFI_ERROR (Status)) {\r
1154 return Status;\r
1155 }\r
1156\r
1157 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1158\r
1159 return EFI_SUCCESS;\r
1160 \r
1161}\r
1162\r
1163/**\r
1164 Check existing TCP connection, if in error state, recover TCP4 connection.\r
1165\r
1166 @param[in] HttpInstance The HTTP instance private data.\r
1167\r
1168 @retval EFI_SUCCESS The TCP connection is established.\r
1169 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1170 @retval Others Other error as indicated.\r
1171\r
1172**/\r
1173EFI_STATUS\r
1174HttpConnectTcp4 (\r
1175 IN HTTP_PROTOCOL *HttpInstance\r
1176 )\r
1177{\r
1178 EFI_STATUS Status;\r
1179 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1180\r
1181\r
1182 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
1183 return EFI_NOT_READY;\r
1184 }\r
1185\r
1186 Status = HttpInstance->Tcp4->GetModeData(\r
1187 HttpInstance->Tcp4, \r
1188 &Tcp4State, \r
1189 NULL,\r
1190 NULL,\r
1191 NULL,\r
1192 NULL\r
1193 );\r
1194 if (EFI_ERROR(Status)){\r
1195 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1196 return Status;\r
1197 }\r
1198\r
1199 if (Tcp4State == Tcp4StateEstablished) {\r
1200 return EFI_SUCCESS;\r
1201 } else if (Tcp4State > Tcp4StateEstablished ) {\r
1202 HttpCloseConnection(HttpInstance);\r
1203 }\r
1204\r
1205 return HttpCreateConnection (HttpInstance);\r
1206}\r
1207\r
1208/**\r
1209 Check existing TCP connection, if in error state, recover TCP6 connection.\r
1210\r
1211 @param[in] HttpInstance The HTTP instance private data.\r
1212\r
1213 @retval EFI_SUCCESS The TCP connection is established.\r
1214 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1215 @retval Others Other error as indicated.\r
1216\r
1217**/\r
1218EFI_STATUS\r
1219HttpConnectTcp6 (\r
1220 IN HTTP_PROTOCOL *HttpInstance\r
1221 )\r
1222{\r
1223 EFI_STATUS Status;\r
1224 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1225\r
1226 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
1227 return EFI_NOT_READY;\r
1228 }\r
1229\r
1230 Status = HttpInstance->Tcp6->GetModeData (\r
1231 HttpInstance->Tcp6,\r
1232 &Tcp6State,\r
1233 NULL,\r
1234 NULL,\r
1235 NULL,\r
1236 NULL\r
1237 );\r
1238 \r
1239 if (EFI_ERROR(Status)){\r
1240 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1241 return Status;\r
1242 }\r
1243\r
1244 if (Tcp6State == Tcp6StateEstablished) {\r
1245 return EFI_SUCCESS;\r
1246 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1247 HttpCloseConnection(HttpInstance);\r
1248 }\r
1249\r
1250 return HttpCreateConnection (HttpInstance);\r
1251}\r
1252\r
1253/**\r
1254 Initialize TCP related data.\r
1255\r
1256 @param[in] HttpInstance The HTTP instance private data.\r
1257 @param[in] Wrap The HTTP token's wrap data.\r
1258 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.\r
1259\r
1260 @retval EFI_SUCCESS The initialization of TCP instance is done. \r
1261 @retval Others Other error as indicated.\r
1262\r
1263**/\r
1264EFI_STATUS\r
1265HttpInitTcp (\r
1266 IN HTTP_PROTOCOL *HttpInstance,\r
1267 IN HTTP_TOKEN_WRAP *Wrap,\r
1268 IN BOOLEAN Configure\r
1269 )\r
1270{\r
1271 EFI_STATUS Status;\r
1272 ASSERT (HttpInstance != NULL);\r
1273\r
1274 if (!HttpInstance->LocalAddressIsIPv6) {\r
1275 //\r
1276 // Configure TCP instance.\r
1277 //\r
1278 if (Configure) {\r
1279 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1280 if (EFI_ERROR (Status)) {\r
1281 return Status;\r
1282 }\r
1283 }\r
1284\r
1285 //\r
1286 // Connect TCP.\r
1287 //\r
1288 Status = HttpConnectTcp4 (HttpInstance);\r
1289 if (EFI_ERROR (Status)) {\r
1290 return Status;\r
1291 }\r
1292 } else {\r
1293 //\r
1294 // Configure TCP instance.\r
1295 //\r
1296 if (Configure) {\r
1297 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1298 if (EFI_ERROR (Status)) {\r
1299 return Status;\r
1300 }\r
1301 }\r
1302\r
1303 //\r
1304 // Connect TCP.\r
1305 //\r
1306 Status = HttpConnectTcp6 (HttpInstance);\r
1307 if (EFI_ERROR (Status)) {\r
1308 return Status;\r
1309 }\r
1310 }\r
1311 \r
1312 return EFI_SUCCESS;\r
1313 \r
1314}\r
1315\r
1316/**\r
1317 Send the HTTP message through TCP4 or TCP6.\r
1318\r
1319 @param[in] HttpInstance The HTTP instance private data.\r
1320 @param[in] Wrap The HTTP token's wrap data.\r
1321 @param[in] TxString Buffer containing the HTTP message string.\r
1322 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1323\r
1324 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1325 @retval Others Other error as indicated.\r
1326\r
1327**/\r
1328EFI_STATUS\r
1329HttpTransmitTcp (\r
1330 IN HTTP_PROTOCOL *HttpInstance,\r
1331 IN HTTP_TOKEN_WRAP *Wrap,\r
1332 IN UINT8 *TxString,\r
1333 IN UINTN TxStringLen\r
1334 )\r
1335{\r
1336 EFI_STATUS Status;\r
1337 EFI_TCP4_IO_TOKEN *Tx4Token;\r
1338 EFI_TCP4_PROTOCOL *Tcp4;\r
1339 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1340 EFI_TCP6_PROTOCOL *Tcp6;\r
1341 \r
1342 if (!HttpInstance->LocalAddressIsIPv6) { \r
1343 Tcp4 = HttpInstance->Tcp4;\r
1344 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1345 \r
1346 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1347 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1348 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1349 Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
1350 \r
1351 Wrap->TcpWrap.IsTxDone = FALSE;\r
1352 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1353 if (EFI_ERROR (Status)) {\r
1354 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1355 return Status;\r
1356 }\r
1357\r
1358 } else {\r
1359 Tcp6 = HttpInstance->Tcp6;\r
1360 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
1361\r
1362 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1363 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1364 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1365 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1366\r
1367 Wrap->TcpWrap.IsTxDone = FALSE;\r
1368 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1369 if (EFI_ERROR (Status)) {\r
1370 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1371 return Status;\r
1372 }\r
1373 }\r
1374 \r
1375\r
1376 return Status;\r
1377}\r
1378\r
1379/**\r
1380 Check whether the user's token or event has already\r
1381 been enqueue on HTTP Tx or Rx Token list.\r
1382\r
1383 @param[in] Map The container of either user's transmit or receive\r
1384 token.\r
1385 @param[in] Item Current item to check against.\r
1386 @param[in] Context The Token to check againist.\r
1387\r
1388 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1389 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1390 context.\r
1391\r
1392**/\r
1393EFI_STATUS\r
1394EFIAPI\r
1395HttpTokenExist (\r
1396 IN NET_MAP *Map,\r
1397 IN NET_MAP_ITEM *Item,\r
1398 IN VOID *Context\r
1399 )\r
1400{\r
1401 EFI_HTTP_TOKEN *Token;\r
1402 EFI_HTTP_TOKEN *TokenInItem;\r
1403\r
1404 Token = (EFI_HTTP_TOKEN *) Context;\r
1405 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1406\r
1407 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1408 return EFI_ACCESS_DENIED;\r
1409 }\r
1410\r
1411 return EFI_SUCCESS;\r
1412}\r
1413\r
1414/**\r
1415 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
1416\r
1417 @param[in] Map The container of Tx4Token or Tx6Token.\r
1418 @param[in] Item Current item to check against.\r
1419 @param[in] Context The Token to check againist.\r
1420\r
1421 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1422 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1423\r
1424**/\r
1425EFI_STATUS\r
1426EFIAPI\r
1427HttpTcpNotReady (\r
1428 IN NET_MAP *Map,\r
1429 IN NET_MAP_ITEM *Item,\r
1430 IN VOID *Context\r
1431 )\r
1432{\r
1433 HTTP_TOKEN_WRAP *ValueInItem;\r
1434\r
1435 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1436\r
1437 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1438 return EFI_NOT_READY;\r
1439 }\r
1440 \r
1441 return EFI_SUCCESS;\r
1442}\r
1443\r
1444/**\r
1445 Transmit the HTTP mssage by processing the associated HTTP token.\r
1446\r
1447 @param[in] Map The container of Tx4Token or Tx6Token.\r
1448 @param[in] Item Current item to check against.\r
1449 @param[in] Context The Token to check againist.\r
1450\r
1451 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1452 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1453 queue.\r
1454\r
1455**/\r
1456EFI_STATUS\r
1457EFIAPI\r
1458HttpTcpTransmit (\r
1459 IN NET_MAP *Map,\r
1460 IN NET_MAP_ITEM *Item,\r
1461 IN VOID *Context\r
1462 )\r
1463{\r
1464 HTTP_TOKEN_WRAP *ValueInItem;\r
1465 EFI_STATUS Status;\r
1466 CHAR8 *RequestMsg;\r
1467 CHAR8 *Url;\r
1468 UINTN RequestMsgSize;\r
1469\r
1470 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1471 if (ValueInItem->TcpWrap.IsTxDone) {\r
1472 return EFI_SUCCESS;\r
1473 }\r
1474\r
1475 //\r
1476 // Parse the URI of the remote host.\r
1477 //\r
1478 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1479 if (Url == NULL) {\r
1480 return EFI_OUT_OF_RESOURCES;\r
1481 }\r
1482\r
1483 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1484\r
1485 //\r
1486 // Create request message.\r
1487 //\r
1488 Status = HttpGenRequestMessage (\r
1489 ValueInItem->HttpToken->Message,\r
1490 Url,\r
1491 &RequestMsg,\r
1492 &RequestMsgSize\r
1493 );\r
1494 FreePool (Url);\r
1495\r
1496 if (EFI_ERROR (Status)){\r
1497 return Status;\r
1498 }\r
1499\r
1500 //\r
1501 // Transmit the request message.\r
1502 //\r
1503 Status = HttpTransmitTcp (\r
1504 ValueInItem->HttpInstance,\r
1505 ValueInItem,\r
1506 (UINT8*) RequestMsg,\r
1507 RequestMsgSize\r
1508 );\r
1509 FreePool (RequestMsg);\r
1510 return Status;\r
1511}\r
1512\r
1513/**\r
1514 Receive the HTTP response by processing the associated HTTP token.\r
1515\r
1516 @param[in] Map The container of Rx4Token or Rx6Token.\r
1517 @param[in] Item Current item to check against.\r
1518 @param[in] Context The Token to check againist.\r
1519\r
1520 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1521 queue.\r
1522 @retval Others Other error as indicated.\r
1523\r
1524**/\r
1525EFI_STATUS\r
1526EFIAPI\r
1527HttpTcpReceive (\r
1528 IN NET_MAP *Map,\r
1529 IN NET_MAP_ITEM *Item,\r
1530 IN VOID *Context\r
1531 )\r
1532{\r
1533 //\r
1534 // Process the queued HTTP response.\r
1535 //\r
1536 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1537}\r
1538\r
1539/**\r
1540 Receive the HTTP header by processing the associated HTTP token.\r
1541\r
1542 @param[in] HttpInstance The HTTP instance private data.\r
1543 @param[in, out] SizeofHeaders The HTTP header length.\r
1544 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1545 @param[in] Timeout The time to wait for receiving the header packet.\r
1546 \r
1547 @retval EFI_SUCCESS The HTTP header is received. \r
1548 @retval Others Other errors as indicated.\r
1549\r
1550**/\r
1551EFI_STATUS\r
1552HttpTcpReceiveHeader (\r
1553 IN HTTP_PROTOCOL *HttpInstance,\r
1554 IN OUT UINTN *SizeofHeaders,\r
1555 IN OUT UINTN *BufferSize,\r
1556 IN EFI_EVENT Timeout\r
1557 )\r
1558{\r
1559 EFI_STATUS Status;\r
1560 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1561 EFI_TCP4_PROTOCOL *Tcp4;\r
1562 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1563 EFI_TCP6_PROTOCOL *Tcp6;\r
1564 CHAR8 **EndofHeader;\r
1565 CHAR8 **HttpHeaders;\r
1566 CHAR8 *Buffer;\r
1567\r
1568 ASSERT (HttpInstance != NULL);\r
1569\r
1570 EndofHeader = HttpInstance->EndofHeader;\r
1571 HttpHeaders = HttpInstance->HttpHeaders;\r
1572 Tcp4 = HttpInstance->Tcp4;\r
1573 Tcp6 = HttpInstance->Tcp6;\r
1574 Buffer = NULL;\r
1575 Rx4Token = NULL;\r
1576 Rx6Token = NULL;\r
1577 \r
1578 if (HttpInstance->LocalAddressIsIPv6) {\r
1579 ASSERT (Tcp6 != NULL);\r
1580 } else {\r
1581 ASSERT (Tcp4 != NULL);\r
1582 }\r
1583\r
1584 if (!HttpInstance->LocalAddressIsIPv6) {\r
1585 Rx4Token = &HttpInstance->Rx4Token;\r
1586 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1587 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1588 Status = EFI_OUT_OF_RESOURCES;\r
1589 return Status;\r
1590 }\r
1591 \r
1592 //\r
1593 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1594 //\r
1595 while (*EndofHeader == NULL) { \r
1596 HttpInstance->IsRxDone = FALSE;\r
1597 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1598 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1599 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1600 if (EFI_ERROR (Status)) {\r
1601 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1602 return Status;\r
1603 }\r
1604 \r
1605 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1606 Tcp4->Poll (Tcp4);\r
1607 }\r
1608\r
1609 if (!HttpInstance->IsRxDone) {\r
1610 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1611 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1612 }\r
1613 \r
1614 Status = Rx4Token->CompletionToken.Status;\r
1615 if (EFI_ERROR (Status)) {\r
1616 return Status;\r
1617 }\r
1618 \r
1619 //\r
1620 // Append the response string.\r
1621 //\r
1622 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1623 Buffer = AllocateZeroPool (*BufferSize);\r
1624 if (Buffer == NULL) {\r
1625 Status = EFI_OUT_OF_RESOURCES;\r
1626 return Status;\r
1627 }\r
1628 \r
1629 if (*HttpHeaders != NULL) {\r
1630 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1631 FreePool (*HttpHeaders);\r
1632 }\r
1633 \r
1634 CopyMem (\r
1635 Buffer + (*SizeofHeaders),\r
1636 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1637 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1638 );\r
1639 *HttpHeaders = Buffer;\r
1640 *SizeofHeaders = *BufferSize;\r
1641 \r
1642 //\r
1643 // Check whether we received end of HTTP headers.\r
1644 //\r
1645 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1646 }\r
1647 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1648 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1649 \r
1650 } else {\r
1651 Rx6Token = &HttpInstance->Rx6Token;\r
1652 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1653 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1654 Status = EFI_OUT_OF_RESOURCES;\r
1655 return Status;\r
1656 }\r
1657 \r
1658 //\r
1659 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1660 //\r
1661 while (*EndofHeader == NULL) { \r
1662 HttpInstance->IsRxDone = FALSE;\r
1663 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1664 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1665 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1666 if (EFI_ERROR (Status)) {\r
1667 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1668 return Status;\r
1669 }\r
1670 \r
1671 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1672 Tcp6->Poll (Tcp6);\r
1673 }\r
1674\r
1675 if (!HttpInstance->IsRxDone) {\r
1676 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1677 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1678 }\r
1679 \r
1680 Status = Rx6Token->CompletionToken.Status;\r
1681 if (EFI_ERROR (Status)) {\r
1682 return Status;\r
1683 }\r
1684 \r
1685 //\r
1686 // Append the response string.\r
1687 //\r
1688 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1689 Buffer = AllocateZeroPool (*BufferSize);\r
1690 if (Buffer == NULL) {\r
1691 Status = EFI_OUT_OF_RESOURCES;\r
1692 return Status;\r
1693 }\r
1694 \r
1695 if (*HttpHeaders != NULL) {\r
1696 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1697 FreePool (*HttpHeaders);\r
1698 }\r
1699 \r
1700 CopyMem (\r
1701 Buffer + (*SizeofHeaders),\r
1702 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1703 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1704 );\r
1705 *HttpHeaders = Buffer;\r
1706 *SizeofHeaders = *BufferSize;\r
1707 \r
1708 //\r
1709 // Check whether we received end of HTTP headers.\r
1710 //\r
1711 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1712 \r
1713 }\r
1714 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1715 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1716 } \r
1717\r
1718 //\r
1719 // Skip the CRLF after the HTTP headers.\r
1720 //\r
1721 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1722\r
1723 return EFI_SUCCESS;\r
1724}\r
1725\r
1726/**\r
1727 Receive the HTTP body by processing the associated HTTP token.\r
1728\r
1729 @param[in] Wrap The HTTP token's wrap data.\r
1730 @param[in] HttpMsg The HTTP message data.\r
1731 @param[in] Timeout The time to wait for receiving the body packet.\r
1732\r
1733 @retval EFI_SUCCESS The HTTP body is received. \r
1734 @retval Others Other error as indicated.\r
1735\r
1736**/\r
1737EFI_STATUS\r
1738HttpTcpReceiveBody (\r
1739 IN HTTP_TOKEN_WRAP *Wrap,\r
1740 IN EFI_HTTP_MESSAGE *HttpMsg,\r
1741 IN EFI_EVENT Timeout\r
1742 )\r
1743{\r
1744 EFI_STATUS Status;\r
1745 HTTP_PROTOCOL *HttpInstance;\r
1746 EFI_TCP6_PROTOCOL *Tcp6;\r
1747 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1748 EFI_TCP4_PROTOCOL *Tcp4;\r
1749 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1750 \r
1751 HttpInstance = Wrap->HttpInstance;\r
1752 Tcp4 = HttpInstance->Tcp4;\r
1753 Tcp6 = HttpInstance->Tcp6;\r
1754 Rx4Token = NULL;\r
1755 Rx6Token = NULL;\r
1756 \r
1757 if (HttpInstance->LocalAddressIsIPv6) {\r
1758 ASSERT (Tcp6 != NULL);\r
1759 } else {\r
1760 ASSERT (Tcp4 != NULL);\r
1761 }\r
1762 \r
1763 if (HttpInstance->LocalAddressIsIPv6) {\r
1764 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1765 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1766 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1767 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1768 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1769\r
1770 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1771 if (EFI_ERROR (Status)) {\r
1772 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1773 return Status;\r
1774 }\r
1775\r
1776 while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1777 Tcp6->Poll (Tcp6);\r
1778 }\r
1779\r
1780 if (!Wrap->TcpWrap.IsRxDone) {\r
1781 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1782 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1783 Wrap->HttpToken->Status = Rx6Token->CompletionToken.Status;\r
1784 gBS->SignalEvent (Wrap->HttpToken->Event);\r
1785 }\r
1786 } else {\r
1787 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1788 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1789 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1790 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1791 \r
1792 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1793 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1794 if (EFI_ERROR (Status)) {\r
1795 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1796 return Status;\r
1797 }\r
1798\r
1799 while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1800 Tcp4->Poll (Tcp4);\r
1801 }\r
1802\r
1803 if (!Wrap->TcpWrap.IsRxDone) {\r
1804 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1805 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1806 Wrap->HttpToken->Status = Rx4Token->CompletionToken.Status;\r
1807 gBS->SignalEvent (Wrap->HttpToken->Event);\r
1808 }\r
1809 }\r
1810\r
1811 return EFI_SUCCESS;\r
1812\r
1813}\r
1814\r
1815/**\r
1816 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1817\r
1818 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1819 \r
1820**/\r
1821VOID\r
1822HttpTcpTokenCleanup (\r
1823 IN HTTP_TOKEN_WRAP *Wrap\r
1824 )\r
1825{ \r
1826 HTTP_PROTOCOL *HttpInstance;\r
1827 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1828 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1829\r
1830 ASSERT (Wrap != NULL);\r
1831 HttpInstance = Wrap->HttpInstance;\r
1832 Rx4Token = NULL;\r
1833 Rx6Token = NULL;\r
1834 \r
1835 if (HttpInstance->LocalAddressIsIPv6) {\r
1836 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1837 \r
1838 if (Rx6Token->CompletionToken.Event != NULL) {\r
1839 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1840 Rx6Token->CompletionToken.Event = NULL;\r
1841 }\r
1842\r
1843 FreePool (Wrap);\r
1844\r
1845 Rx6Token = &HttpInstance->Rx6Token;\r
1846 \r
1847 if (Rx6Token->CompletionToken.Event != NULL) {\r
1848 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1849 Rx6Token->CompletionToken.Event = NULL;\r
1850 }\r
1851 \r
1852 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1853 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1854 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1855 }\r
1856 \r
1857 } else {\r
1858 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1859 \r
1860 if (Rx4Token->CompletionToken.Event != NULL) {\r
1861 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1862 Rx4Token->CompletionToken.Event = NULL;\r
1863 }\r
1864 \r
1865 FreePool (Wrap);\r
1866\r
1867 Rx4Token = &HttpInstance->Rx4Token;\r
1868\r
1869 if (Rx4Token->CompletionToken.Event != NULL) {\r
1870 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1871 Rx4Token->CompletionToken.Event = NULL;\r
1872 }\r
1873 \r
1874 \r
1875 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1876 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1877 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1878 }\r
1879 }\r
1880\r
1881}\r