]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Use the New Functions from HttpLib
[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
1465 CHAR8 *RequestStr;\r
1466 CHAR8 *Url;\r
1467\r
1468 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1469 if (ValueInItem->TcpWrap.IsTxDone) {\r
1470 return EFI_SUCCESS;\r
1471 }\r
1472\r
1473 //\r
1474 // Parse the URI of the remote host.\r
1475 //\r
1476 Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
1477 if (Url == NULL) {\r
1478 return EFI_OUT_OF_RESOURCES;\r
1479 }\r
1480\r
1481 UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
1482\r
1483 //\r
1484 // Create request message.\r
1485 //\r
f58554fc 1486 Status = HttpGenRequestString (\r
47f51a06 1487 ValueInItem->HttpToken->Message,\r
f58554fc
GB
1488 Url,\r
1489 &RequestStr\r
47f51a06
YT
1490 );\r
1491 FreePool (Url);\r
f58554fc
GB
1492\r
1493 if (EFI_ERROR (Status)){\r
1494 return Status;\r
47f51a06
YT
1495 }\r
1496\r
1497 //\r
1498 // Transmit the request message.\r
1499 //\r
b659408b 1500 Status = HttpTransmitTcp (\r
47f51a06
YT
1501 ValueInItem->HttpInstance,\r
1502 ValueInItem,\r
1503 (UINT8*) RequestStr,\r
1504 AsciiStrLen (RequestStr)\r
1505 );\r
1506 FreePool (RequestStr);\r
1507 return Status;\r
1508}\r
1509\r
1510/**\r
1511 Receive the HTTP response by processing the associated HTTP token.\r
1512\r
b659408b 1513 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1514 @param[in] Item Current item to check against.\r
1515 @param[in] Context The Token to check againist.\r
1516\r
1517 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1518 queue.\r
1519 @retval Others Other error as indicated.\r
1520\r
1521**/\r
1522EFI_STATUS\r
1523EFIAPI\r
1524HttpTcpReceive (\r
1525 IN NET_MAP *Map,\r
1526 IN NET_MAP_ITEM *Item,\r
1527 IN VOID *Context\r
1528 )\r
1529{\r
1530 //\r
1531 // Process the queued HTTP response.\r
1532 //\r
1533 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1534}\r
1535\r
b659408b
ZL
1536/**\r
1537 Receive the HTTP header by processing the associated HTTP token.\r
1538\r
1539 @param[in] HttpInstance The HTTP instance private data.\r
1540 @param[in, out] SizeofHeaders The HTTP header length.\r
1541 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1542 \r
1543 @retval EFI_SUCCESS The HTTP header is received. \r
1544 @retval Others Other errors as indicated.\r
1545\r
1546**/\r
1547EFI_STATUS\r
1548HttpTcpReceiveHeader (\r
1549 IN HTTP_PROTOCOL *HttpInstance,\r
1550 IN OUT UINTN *SizeofHeaders,\r
1551 IN OUT UINTN *BufferSize\r
1552 )\r
1553{\r
1554 EFI_STATUS Status;\r
1555 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1556 EFI_TCP4_PROTOCOL *Tcp4;\r
1557 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1558 EFI_TCP6_PROTOCOL *Tcp6;\r
1559 CHAR8 **EndofHeader;\r
1560 CHAR8 **HttpHeaders;\r
1561 CHAR8 *Buffer;\r
1562\r
1563 ASSERT (HttpInstance != NULL);\r
1564\r
1565 EndofHeader = HttpInstance->EndofHeader;\r
1566 HttpHeaders = HttpInstance->HttpHeaders;\r
1567 Tcp4 = HttpInstance->Tcp4;\r
1568 Tcp6 = HttpInstance->Tcp6;\r
1569 Buffer = NULL;\r
1570 Rx4Token = NULL;\r
1571 Rx6Token = NULL;\r
1572 \r
1573 if (HttpInstance->LocalAddressIsIPv6) {\r
1574 ASSERT (Tcp6 != NULL);\r
1575 } else {\r
1576 ASSERT (Tcp4 != NULL);\r
1577 }\r
1578\r
1579 if (!HttpInstance->LocalAddressIsIPv6) {\r
1580 Rx4Token = &HttpInstance->Rx4Token;\r
1581 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1582 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1583 Status = EFI_OUT_OF_RESOURCES;\r
1584 return Status;\r
1585 }\r
1586 \r
1587 //\r
1588 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1589 //\r
1590 while (*EndofHeader == NULL) { \r
1591 HttpInstance->IsRxDone = FALSE;\r
1592 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1593 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1594 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1595 if (EFI_ERROR (Status)) {\r
1596 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1597 return Status;\r
1598 }\r
1599 \r
1600 while (!HttpInstance->IsRxDone) {\r
1601 Tcp4->Poll (Tcp4);\r
1602 } \r
1603 \r
1604 Status = Rx4Token->CompletionToken.Status;\r
1605 if (EFI_ERROR (Status)) {\r
1606 return Status;\r
1607 }\r
1608 \r
1609 //\r
1610 // Append the response string.\r
1611 //\r
1612 *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1613 Buffer = AllocateZeroPool (*BufferSize);\r
1614 if (Buffer == NULL) {\r
1615 Status = EFI_OUT_OF_RESOURCES;\r
1616 return Status;\r
1617 }\r
1618 \r
1619 if (*HttpHeaders != NULL) {\r
1620 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1621 FreePool (*HttpHeaders);\r
1622 }\r
1623 \r
1624 CopyMem (\r
1625 Buffer + (*SizeofHeaders),\r
1626 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1627 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1628 );\r
1629 *HttpHeaders = Buffer;\r
1630 *SizeofHeaders = *BufferSize;\r
1631 \r
1632 //\r
1633 // Check whether we received end of HTTP headers.\r
1634 //\r
1635 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
1636 }\r
1637 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1638 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1639 \r
1640 } else {\r
1641 Rx6Token = &HttpInstance->Rx6Token;\r
1642 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1643 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1644 Status = EFI_OUT_OF_RESOURCES;\r
1645 return Status;\r
1646 }\r
1647 \r
1648 //\r
1649 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1650 //\r
1651 while (*EndofHeader == NULL) { \r
1652 HttpInstance->IsRxDone = FALSE;\r
1653 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1654 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1655 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1656 if (EFI_ERROR (Status)) {\r
1657 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1658 return Status;\r
1659 }\r
1660 \r
1661 while (!HttpInstance->IsRxDone) {\r
1662 Tcp6->Poll (Tcp6);\r
1663 } \r
1664 \r
1665 Status = Rx6Token->CompletionToken.Status;\r
1666 if (EFI_ERROR (Status)) {\r
1667 return Status;\r
1668 }\r
1669 \r
1670 //\r
1671 // Append the response string.\r
1672 //\r
1673 *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1674 Buffer = AllocateZeroPool (*BufferSize);\r
1675 if (Buffer == NULL) {\r
1676 Status = EFI_OUT_OF_RESOURCES;\r
1677 return Status;\r
1678 }\r
1679 \r
1680 if (*HttpHeaders != NULL) {\r
1681 CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
1682 FreePool (*HttpHeaders);\r
1683 }\r
1684 \r
1685 CopyMem (\r
1686 Buffer + (*SizeofHeaders),\r
1687 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
1688 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength\r
1689 );\r
1690 *HttpHeaders = Buffer;\r
1691 *SizeofHeaders = *BufferSize;\r
1692 \r
1693 //\r
1694 // Check whether we received end of HTTP headers.\r
1695 //\r
1696 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1697 \r
1698 }\r
1699 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1700 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; \r
1701 } \r
1702\r
1703 //\r
1704 // Skip the CRLF after the HTTP headers.\r
1705 //\r
1706 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); \r
1707\r
1708 return EFI_SUCCESS;\r
1709}\r
1710\r
1711/**\r
1712 Receive the HTTP body by processing the associated HTTP token.\r
1713\r
1714 @param[in] Wrap The HTTP token's wrap data.\r
1715 @param[in] HttpMsg The HTTP message data.\r
1716\r
1717 @retval EFI_SUCCESS The HTTP body is received. \r
1718 @retval Others Other error as indicated.\r
1719\r
1720**/\r
1721EFI_STATUS\r
1722HttpTcpReceiveBody (\r
1723 IN HTTP_TOKEN_WRAP *Wrap,\r
1724 IN EFI_HTTP_MESSAGE *HttpMsg\r
1725 )\r
1726{\r
1727 EFI_STATUS Status;\r
1728 HTTP_PROTOCOL *HttpInstance;\r
1729 EFI_TCP6_PROTOCOL *Tcp6;\r
1730 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1731 EFI_TCP4_PROTOCOL *Tcp4;\r
1732 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1733 \r
1734 HttpInstance = Wrap->HttpInstance;\r
1735 Tcp4 = HttpInstance->Tcp4;\r
1736 Tcp6 = HttpInstance->Tcp6;\r
1737 Rx4Token = NULL;\r
1738 Rx6Token = NULL;\r
1739\r
1740 \r
1741 if (HttpInstance->LocalAddressIsIPv6) {\r
1742 ASSERT (Tcp6 != NULL);\r
1743 } else {\r
1744 ASSERT (Tcp4 != NULL);\r
1745 }\r
1746 \r
1747 if (HttpInstance->LocalAddressIsIPv6) {\r
1748 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1749 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1750 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1751 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1752 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1753\r
1754 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1755 if (EFI_ERROR (Status)) {\r
1756 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1757 return Status;\r
1758 }\r
1759 \r
1760 } else {\r
1761 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1762 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
1763 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
1764 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
1765 \r
1766 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1767 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1768 if (EFI_ERROR (Status)) {\r
1769 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1770 return Status;\r
1771 }\r
1772 }\r
1773\r
1774 return EFI_SUCCESS;\r
1775\r
1776}\r
1777\r
1778/**\r
1779 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
1780\r
1781 @param[in] Wrap Pointer to HTTP token's wrap data.\r
1782 \r
1783**/\r
1784VOID\r
1785HttpTcpTokenCleanup (\r
1786 IN HTTP_TOKEN_WRAP *Wrap\r
1787 )\r
1788{ \r
1789 HTTP_PROTOCOL *HttpInstance;\r
1790 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1791 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1792\r
1b96428d 1793 ASSERT (Wrap != NULL);\r
b659408b
ZL
1794 HttpInstance = Wrap->HttpInstance;\r
1795 Rx4Token = NULL;\r
1796 Rx6Token = NULL;\r
1797 \r
1798 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
1799 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
1800 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
1801 }\r
b659408b 1802\r
1b96428d
ZL
1803 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
1804 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1805 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1806 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
b659408b 1807 }\r
1b96428d 1808 FreePool (Wrap);\r
b659408b
ZL
1809\r
1810 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
1811 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
1812 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
1813 }\r
1814\r
1815 Rx6Token = &HttpInstance->Rx6Token;\r
1816 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1817 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1818 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1819 }\r
1820 \r
1821 } else {\r
1b96428d
ZL
1822 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
1823 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b 1824 }\r
1b96428d
ZL
1825 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
1826 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1827 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1828 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1829 }\r
1830 FreePool (Wrap);\r
1831\r
b659408b
ZL
1832 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
1833 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
1834 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
1835 }\r
1836 \r
1837 Rx4Token = &HttpInstance->Rx4Token;\r
1838 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1839 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1840 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1841 }\r
1842 }\r
1843\r
1844}\r