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