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