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