]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Clean up source files
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
CommitLineData
47f51a06
YT
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
07bd82d4 4Copyright (c) 2015 - 2018, 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
f75a7f56 19 The common notify function used in HTTP driver.\r
47f51a06
YT
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
f75a7f56 57\r
b659408b
ZL
58 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
59 HttpInstance = Wrap->HttpInstance;\r
f75a7f56 60\r
b659408b
ZL
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
f75a7f56 75\r
b659408b
ZL
76 } else {\r
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
78 gBS->SignalEvent (Wrap->HttpToken->Event);\r
f75a7f56 79\r
b659408b
ZL
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
f75a7f56 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 147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
f75a7f56 148\r
b659408b
ZL
149 if (UsingIpv6) {\r
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
30526a51 151 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
f75a7f56 152\r
b659408b 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
f75a7f56 162\r
30526a51
JW
163 FreePool (Wrap);\r
164 Wrap = NULL;\r
f75a7f56 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
f75a7f56 172\r
b659408b 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
f75a7f56 177\r
30526a51
JW
178 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
179 if (Item != NULL) {\r
180 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
181 }\r
f75a7f56 182\r
30526a51
JW
183 FreePool (Wrap);\r
184 Wrap = NULL;\r
f75a7f56 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
f75a7f56 223 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg -\r
47f51a06
YT
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
f75a7f56 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
f75a7f56 326\r
b659408b
ZL
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
f75a7f56 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
f75a7f56 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
f75a7f56 439\r
30526a51
JW
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
f75a7f56 463\r
b659408b 464 }\r
f75a7f56 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
f75a7f56 496\r
b659408b
ZL
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
f75a7f56 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
f75a7f56 534 IN HTTP_TOKEN_WRAP *Wrap\r
47f51a06
YT
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
f75a7f56 554\r
b659408b
ZL
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
f75a7f56 566 );\r
b659408b
ZL
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
f75a7f56 575\r
b659408b
ZL
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 582 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 583\r
b659408b
ZL
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
f75a7f56 594\r
b659408b 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 607 }\r
f75a7f56 608\r
b659408b
ZL
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 621\r
f75a7f56 622 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.\r
47f51a06
YT
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 634 BOOLEAN UsingIpv6;\r
f75a7f56 635\r
b659408b
ZL
636 ASSERT (HttpInstance != NULL);\r
637 UsingIpv6 = IpVersion;\r
f75a7f56 638\r
b659408b
ZL
639 if (!UsingIpv6) {\r
640 //\r
641 // Create TCP4 child.\r
642 //\r
643 Status = NetLibCreateServiceChild (\r
644 HttpInstance->Service->ControllerHandle,\r
7cf59c85 645 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
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
7cf59c85 658 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
659 HttpInstance->Service->ControllerHandle,\r
660 EFI_OPEN_PROTOCOL_BY_DRIVER\r
661 );\r
f75a7f56 662\r
b659408b
ZL
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
7cf59c85 671 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
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
7cf59c85 683 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
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
7cf59c85 696 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
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
7cf59c85 709 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
710 HttpInstance->Service->ControllerHandle,\r
711 EFI_OPEN_PROTOCOL_BY_DRIVER\r
712 );\r
f75a7f56 713\r
b659408b
ZL
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
7cf59c85 722 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
723 HttpInstance->Handle,\r
724 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
725 );\r
f75a7f56 726\r
b659408b
ZL
727 if (EFI_ERROR(Status)) {\r
728 goto ON_ERROR;\r
f75a7f56 729 }\r
b659408b
ZL
730\r
731 Status = gBS->OpenProtocol (\r
732 HttpInstance->Service->Tcp6ChildHandle,\r
733 &gEfiTcp6ProtocolGuid,\r
734 (VOID **) &Interface,\r
7cf59c85 735 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
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
f75a7f56 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
f75a7f56 754\r
b659408b 755 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 756 gBS->CloseProtocol (\r
b659408b 757 HttpInstance->Tcp4ChildHandle,\r
47f51a06 758 &gEfiTcp4ProtocolGuid,\r
7cf59c85 759 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
760 HttpInstance->Service->ControllerHandle\r
761 );\r
762\r
763 gBS->CloseProtocol (\r
b659408b 764 HttpInstance->Tcp4ChildHandle,\r
47f51a06 765 &gEfiTcp4ProtocolGuid,\r
7cf59c85 766 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 767 HttpInstance->Handle\r
f75a7f56
LG
768 );\r
769\r
47f51a06
YT
770 NetLibDestroyServiceChild (\r
771 HttpInstance->Service->ControllerHandle,\r
7cf59c85 772 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 773 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 774 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
775 );\r
776 }\r
f75a7f56 777\r
b659408b
ZL
778 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
779 gBS->CloseProtocol (\r
780 HttpInstance->Service->Tcp4ChildHandle,\r
781 &gEfiTcp4ProtocolGuid,\r
7cf59c85 782 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
783 HttpInstance->Handle\r
784 );\r
785 }\r
f75a7f56 786\r
b659408b
ZL
787 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
788 gBS->CloseProtocol (\r
789 HttpInstance->Tcp6ChildHandle,\r
790 &gEfiTcp6ProtocolGuid,\r
7cf59c85 791 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
792 HttpInstance->Service->ControllerHandle\r
793 );\r
47f51a06 794\r
b659408b
ZL
795 gBS->CloseProtocol (\r
796 HttpInstance->Tcp6ChildHandle,\r
797 &gEfiTcp6ProtocolGuid,\r
7cf59c85 798 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
799 HttpInstance->Handle\r
800 );\r
f75a7f56 801\r
b659408b
ZL
802 NetLibDestroyServiceChild (\r
803 HttpInstance->Service->ControllerHandle,\r
7cf59c85 804 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
805 &gEfiTcp6ServiceBindingProtocolGuid,\r
806 HttpInstance->Tcp6ChildHandle\r
807 );\r
808 }\r
f75a7f56 809\r
b659408b
ZL
810 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
811 gBS->CloseProtocol (\r
812 HttpInstance->Service->Tcp6ChildHandle,\r
813 &gEfiTcp6ProtocolGuid,\r
7cf59c85 814 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
815 HttpInstance->Handle\r
816 );\r
817 }\r
818\r
819 return EFI_UNSUPPORTED;\r
f75a7f56 820\r
47f51a06
YT
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
f75a7f56 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
f75a7f56 858\r
51b0450e
FS
859 if (HttpInstance->Url != NULL) {\r
860 FreePool (HttpInstance->Url);\r
861 HttpInstance->Url = NULL;\r
862 }\r
f75a7f56 863\r
47f51a06
YT
864 NetMapClean (&HttpInstance->TxTokens);\r
865 NetMapClean (&HttpInstance->RxTokens);\r
866\r
45ea8a0c
JW
867 if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) {\r
868 //\r
f75a7f56 869 // Destroy the TLS instance.\r
328141fc 870 //\r
45ea8a0c
JW
871 HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);\r
872 }\r
873\r
b659408b 874 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 875 gBS->CloseProtocol (\r
b659408b 876 HttpInstance->Tcp4ChildHandle,\r
47f51a06 877 &gEfiTcp4ProtocolGuid,\r
7cf59c85 878 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
879 HttpInstance->Service->ControllerHandle\r
880 );\r
881\r
882 gBS->CloseProtocol (\r
b659408b 883 HttpInstance->Tcp4ChildHandle,\r
47f51a06 884 &gEfiTcp4ProtocolGuid,\r
7cf59c85 885 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
886 HttpInstance->Handle\r
887 );\r
f75a7f56 888\r
47f51a06
YT
889 NetLibDestroyServiceChild (\r
890 HttpInstance->Service->ControllerHandle,\r
7cf59c85 891 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 892 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 893 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
894 );\r
895 }\r
b659408b
ZL
896\r
897 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
898 gBS->CloseProtocol (\r
899 HttpInstance->Service->Tcp4ChildHandle,\r
900 &gEfiTcp4ProtocolGuid,\r
7cf59c85 901 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
902 HttpInstance->Handle\r
903 );\r
f75a7f56 904 }\r
b659408b
ZL
905\r
906 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
907 gBS->CloseProtocol (\r
908 HttpInstance->Tcp6ChildHandle,\r
909 &gEfiTcp6ProtocolGuid,\r
7cf59c85 910 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
911 HttpInstance->Service->ControllerHandle\r
912 );\r
913\r
914 gBS->CloseProtocol (\r
915 HttpInstance->Tcp6ChildHandle,\r
916 &gEfiTcp6ProtocolGuid,\r
7cf59c85 917 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
918 HttpInstance->Handle\r
919 );\r
f75a7f56 920\r
b659408b
ZL
921 NetLibDestroyServiceChild (\r
922 HttpInstance->Service->ControllerHandle,\r
7cf59c85 923 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
924 &gEfiTcp6ServiceBindingProtocolGuid,\r
925 HttpInstance->Tcp6ChildHandle\r
926 );\r
927 }\r
f75a7f56 928\r
b659408b
ZL
929 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
930 gBS->CloseProtocol (\r
931 HttpInstance->Service->Tcp6ChildHandle,\r
932 &gEfiTcp6ProtocolGuid,\r
7cf59c85 933 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
934 HttpInstance->Handle\r
935 );\r
936 }\r
dac45de3 937\r
f75a7f56 938 TlsCloseTxRxEvent (HttpInstance);\r
47f51a06
YT
939}\r
940\r
941/**\r
942 Establish TCP connection with HTTP server.\r
943\r
944 @param[in] HttpInstance The HTTP instance private data.\r
945\r
946 @retval EFI_SUCCESS The TCP connection is established.\r
947 @retval Others Other error as indicated.\r
948\r
949**/\r
950EFI_STATUS\r
951HttpCreateConnection (\r
952 IN HTTP_PROTOCOL *HttpInstance\r
953 )\r
954{\r
955 EFI_STATUS Status;\r
956\r
47f51a06
YT
957 //\r
958 // Connect to Http server\r
959 //\r
b659408b
ZL
960 if (!HttpInstance->LocalAddressIsIPv6) {\r
961 HttpInstance->IsTcp4ConnDone = FALSE;\r
962 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
963 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
964 if (EFI_ERROR (Status)) {\r
965 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
966 return Status;\r
967 }\r
f75a7f56 968\r
b659408b
ZL
969 while (!HttpInstance->IsTcp4ConnDone) {\r
970 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
971 }\r
f75a7f56 972\r
b659408b 973 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
f75a7f56 974\r
b659408b
ZL
975 } else {\r
976 HttpInstance->IsTcp6ConnDone = FALSE;\r
977 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
978 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
979 if (EFI_ERROR (Status)) {\r
980 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
981 return Status;\r
982 }\r
47f51a06 983\r
b659408b
ZL
984 while(!HttpInstance->IsTcp6ConnDone) {\r
985 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
986 }\r
47f51a06 987\r
f75a7f56 988 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;\r
b659408b 989 }\r
f75a7f56 990\r
47f51a06
YT
991 if (!EFI_ERROR (Status)) {\r
992 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
993 }\r
994\r
995 return Status;\r
996}\r
997\r
998/**\r
999 Close existing TCP connection.\r
1000\r
1001 @param[in] HttpInstance The HTTP instance private data.\r
1002\r
1003 @retval EFI_SUCCESS The TCP connection is closed.\r
1004 @retval Others Other error as indicated.\r
1005\r
1006**/\r
1007EFI_STATUS\r
1008HttpCloseConnection (\r
1009 IN HTTP_PROTOCOL *HttpInstance\r
1010 )\r
1011{\r
1012 EFI_STATUS Status;\r
1013\r
374ecd04 1014 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
47f51a06 1015\r
b659408b
ZL
1016 if (HttpInstance->LocalAddressIsIPv6) {\r
1017 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
1018 HttpInstance->IsTcp6CloseDone = FALSE;\r
1019 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
1020 if (EFI_ERROR (Status)) {\r
1021 return Status;\r
1022 }\r
1023\r
1024 while (!HttpInstance->IsTcp6CloseDone) {\r
1025 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
1026 }\r
f75a7f56 1027\r
b659408b
ZL
1028 } else {\r
1029 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
1030 HttpInstance->IsTcp4CloseDone = FALSE;\r
1031 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
1032 if (EFI_ERROR (Status)) {\r
1033 return Status;\r
1034 }\r
1035\r
1036 while (!HttpInstance->IsTcp4CloseDone) {\r
1037 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1038 }\r
374ecd04 1039 }\r
b659408b 1040\r
47f51a06
YT
1041 }\r
1042\r
1043 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1044 return EFI_SUCCESS;\r
47f51a06
YT
1045}\r
1046\r
1047/**\r
1048 Configure TCP4 protocol child.\r
1049\r
1050 @param[in] HttpInstance The HTTP instance private data.\r
1051 @param[in] Wrap The HTTP token's wrap data.\r
1052\r
1053 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1054 @retval Others Other error as indicated.\r
1055\r
1056**/\r
1057EFI_STATUS\r
1058HttpConfigureTcp4 (\r
1059 IN HTTP_PROTOCOL *HttpInstance,\r
1060 IN HTTP_TOKEN_WRAP *Wrap\r
1061 )\r
1062{\r
1063 EFI_STATUS Status;\r
1064 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1065 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1066 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1067\r
1068 ASSERT (HttpInstance != NULL);\r
47f51a06
YT
1069\r
1070\r
1071 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1072 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
f75a7f56 1073\r
47f51a06
YT
1074 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1075 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1076 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1077\r
1078 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1079 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1080 if (!Tcp4AP->UseDefaultAddress) {\r
1081 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1082 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1083 }\r
f75a7f56 1084\r
47f51a06
YT
1085 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1086 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1087 Tcp4AP->ActiveFlag = TRUE;\r
1088 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1089\r
1090 Tcp4Option = Tcp4CfgData->ControlOption;\r
1091 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1092 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1093 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1094 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1095 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1096 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1097 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1098 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1099 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1100 Tcp4Option->EnableNagle = TRUE;\r
1101 Tcp4CfgData->ControlOption = Tcp4Option;\r
1102\r
1103 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1104 if (EFI_ERROR (Status)) {\r
1105 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1106 return Status;\r
1107 }\r
1108\r
b659408b
ZL
1109 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1110 if (EFI_ERROR (Status)) {\r
1111 return Status;\r
1112 }\r
1113\r
1114 Status = HttpCreateTcpTxEvent (Wrap);\r
1115 if (EFI_ERROR (Status)) {\r
1116 return Status;\r
1117 }\r
1118\r
1119 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1120\r
1121 return EFI_SUCCESS;\r
1122}\r
1123\r
1124/**\r
1125 Configure TCP6 protocol child.\r
1126\r
1127 @param[in] HttpInstance The HTTP instance private data.\r
1128 @param[in] Wrap The HTTP token's wrap data.\r
1129\r
1130 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1131 @retval Others Other error as indicated.\r
1132\r
1133**/\r
1134EFI_STATUS\r
1135HttpConfigureTcp6 (\r
1136 IN HTTP_PROTOCOL *HttpInstance,\r
1137 IN HTTP_TOKEN_WRAP *Wrap\r
1138 )\r
1139{\r
1140 EFI_STATUS Status;\r
1141 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1142 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1143 EFI_TCP6_OPTION *Tcp6Option;\r
f75a7f56 1144\r
b659408b 1145 ASSERT (HttpInstance != NULL);\r
f75a7f56 1146\r
b659408b
ZL
1147 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1148 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1149\r
1150 Tcp6CfgData->TrafficClass = 0;\r
1151 Tcp6CfgData->HopLimit = 255;\r
1152 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
f75a7f56 1153\r
b659408b
ZL
1154 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1155 Tcp6Ap->ActiveFlag = TRUE;\r
1156 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1157 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1158 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1159 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1160\r
1161 Tcp6Option = Tcp6CfgData->ControlOption;\r
1162 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1163 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1164 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1165 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1166 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1167 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1168 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1169 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1170 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1171 Tcp6Option->EnableNagle = TRUE;\r
1172\r
1173 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1174 if (EFI_ERROR (Status)) {\r
1175 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1176 return Status;\r
1177 }\r
f75a7f56 1178\r
b659408b 1179 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1180 if (EFI_ERROR (Status)) {\r
1181 return Status;\r
1182 }\r
1183\r
b659408b 1184 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1185 if (EFI_ERROR (Status)) {\r
1186 return Status;\r
1187 }\r
1188\r
1189 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1190\r
1191 return EFI_SUCCESS;\r
f75a7f56 1192\r
47f51a06
YT
1193}\r
1194\r
1195/**\r
f75a7f56 1196 Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
dac45de3 1197 connect one TLS session if required.\r
47f51a06
YT
1198\r
1199 @param[in] HttpInstance The HTTP instance private data.\r
1200\r
1201 @retval EFI_SUCCESS The TCP connection is established.\r
1202 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1203 @retval Others Other error as indicated.\r
1204\r
1205**/\r
1206EFI_STATUS\r
1207HttpConnectTcp4 (\r
1208 IN HTTP_PROTOCOL *HttpInstance\r
1209 )\r
1210{\r
1211 EFI_STATUS Status;\r
1212 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1213\r
1214\r
a2e61982 1215 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
47f51a06
YT
1216 return EFI_NOT_READY;\r
1217 }\r
1218\r
1219 Status = HttpInstance->Tcp4->GetModeData(\r
f75a7f56
LG
1220 HttpInstance->Tcp4,\r
1221 &Tcp4State,\r
47f51a06
YT
1222 NULL,\r
1223 NULL,\r
1224 NULL,\r
1225 NULL\r
1226 );\r
1227 if (EFI_ERROR(Status)){\r
1228 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1229 return Status;\r
1230 }\r
1231\r
a2e61982
ZL
1232 if (Tcp4State == Tcp4StateEstablished) {\r
1233 return EFI_SUCCESS;\r
1234 } else if (Tcp4State > Tcp4StateEstablished ) {\r
47f51a06 1235 HttpCloseConnection(HttpInstance);\r
a2e61982 1236 }\r
47f51a06 1237\r
dac45de3
JW
1238 Status = HttpCreateConnection (HttpInstance);\r
1239 if (EFI_ERROR(Status)){\r
1240 DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status));\r
1241 return Status;\r
1242 }\r
f75a7f56 1243\r
dac45de3
JW
1244 //\r
1245 // Tls session connection.\r
1246 //\r
1247 if (HttpInstance->UseHttps) {\r
1248 if (HttpInstance->TimeoutEvent == NULL) {\r
1249 //\r
1250 // Create TimeoutEvent for TLS connection.\r
1251 //\r
1252 Status = gBS->CreateEvent (\r
1253 EVT_TIMER,\r
1254 TPL_CALLBACK,\r
1255 NULL,\r
1256 NULL,\r
1257 &HttpInstance->TimeoutEvent\r
1258 );\r
1259 if (EFI_ERROR (Status)) {\r
1260 TlsCloseTxRxEvent (HttpInstance);\r
1261 return Status;\r
1262 }\r
1263 }\r
1264\r
1265 //\r
1266 // Start the timer, and wait Timeout seconds for connection.\r
1267 //\r
1268 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1269 if (EFI_ERROR (Status)) {\r
1270 TlsCloseTxRxEvent (HttpInstance);\r
1271 return Status;\r
1272 }\r
f75a7f56 1273\r
dac45de3
JW
1274 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
1275\r
1276 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1277\r
dac45de3
JW
1278 if (EFI_ERROR (Status)) {\r
1279 TlsCloseTxRxEvent (HttpInstance);\r
1280 return Status;\r
1281 }\r
1282 }\r
1283\r
1284 return Status;\r
47f51a06
YT
1285}\r
1286\r
1287/**\r
f75a7f56 1288 Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
dac45de3 1289 connect one TLS session if required.\r
b659408b
ZL
1290\r
1291 @param[in] HttpInstance The HTTP instance private data.\r
1292\r
1293 @retval EFI_SUCCESS The TCP connection is established.\r
1294 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1295 @retval Others Other error as indicated.\r
1296\r
1297**/\r
1298EFI_STATUS\r
1299HttpConnectTcp6 (\r
1300 IN HTTP_PROTOCOL *HttpInstance\r
1301 )\r
1302{\r
1303 EFI_STATUS Status;\r
1304 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1305\r
a2e61982 1306 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
b659408b
ZL
1307 return EFI_NOT_READY;\r
1308 }\r
1309\r
1310 Status = HttpInstance->Tcp6->GetModeData (\r
1311 HttpInstance->Tcp6,\r
1312 &Tcp6State,\r
1313 NULL,\r
1314 NULL,\r
1315 NULL,\r
1316 NULL\r
1317 );\r
f75a7f56 1318\r
b659408b
ZL
1319 if (EFI_ERROR(Status)){\r
1320 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1321 return Status;\r
1322 }\r
1323\r
a2e61982
ZL
1324 if (Tcp6State == Tcp6StateEstablished) {\r
1325 return EFI_SUCCESS;\r
1326 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1327 HttpCloseConnection(HttpInstance);\r
b659408b
ZL
1328 }\r
1329\r
dac45de3
JW
1330 Status = HttpCreateConnection (HttpInstance);\r
1331 if (EFI_ERROR(Status)){\r
1332 DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status));\r
1333 return Status;\r
1334 }\r
f75a7f56 1335\r
dac45de3
JW
1336 //\r
1337 // Tls session connection.\r
1338 //\r
1339 if (HttpInstance->UseHttps) {\r
1340 if (HttpInstance->TimeoutEvent == NULL) {\r
1341 //\r
1342 // Create TimeoutEvent for TLS connection.\r
1343 //\r
1344 Status = gBS->CreateEvent (\r
1345 EVT_TIMER,\r
1346 TPL_CALLBACK,\r
1347 NULL,\r
1348 NULL,\r
1349 &HttpInstance->TimeoutEvent\r
1350 );\r
1351 if (EFI_ERROR (Status)) {\r
1352 TlsCloseTxRxEvent (HttpInstance);\r
1353 return Status;\r
1354 }\r
1355 }\r
1356\r
1357 //\r
1358 // Start the timer, and wait Timeout seconds for connection.\r
1359 //\r
1360 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1361 if (EFI_ERROR (Status)) {\r
1362 TlsCloseTxRxEvent (HttpInstance);\r
1363 return Status;\r
1364 }\r
f75a7f56 1365\r
dac45de3
JW
1366 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
1367\r
1368 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1369\r
dac45de3
JW
1370 if (EFI_ERROR (Status)) {\r
1371 TlsCloseTxRxEvent (HttpInstance);\r
1372 return Status;\r
1373 }\r
1374 }\r
1375\r
1376 return Status;\r
b659408b
ZL
1377}\r
1378\r
1379/**\r
dac45de3 1380 Initialize Http session.\r
b659408b
ZL
1381\r
1382 @param[in] HttpInstance The HTTP instance private data.\r
1383 @param[in] Wrap The HTTP token's wrap data.\r
dac45de3
JW
1384 @param[in] Configure The Flag indicates whether need to initialize session.\r
1385 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.\r
b659408b 1386\r
f75a7f56 1387 @retval EFI_SUCCESS The initialization of session is done.\r
b659408b
ZL
1388 @retval Others Other error as indicated.\r
1389\r
1390**/\r
1391EFI_STATUS\r
dac45de3 1392HttpInitSession (\r
b659408b 1393 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982 1394 IN HTTP_TOKEN_WRAP *Wrap,\r
dac45de3
JW
1395 IN BOOLEAN Configure,\r
1396 IN BOOLEAN TlsConfigure\r
b659408b
ZL
1397 )\r
1398{\r
1399 EFI_STATUS Status;\r
1400 ASSERT (HttpInstance != NULL);\r
1401\r
dac45de3
JW
1402 //\r
1403 // Configure Tls session.\r
1404 //\r
1405 if (TlsConfigure) {\r
1406 Status = TlsConfigureSession (HttpInstance);\r
1407 if (EFI_ERROR (Status)) {\r
1408 return Status;\r
1409 }\r
1410 }\r
1411\r
b659408b
ZL
1412 if (!HttpInstance->LocalAddressIsIPv6) {\r
1413 //\r
1414 // Configure TCP instance.\r
1415 //\r
a2e61982
ZL
1416 if (Configure) {\r
1417 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1418 if (EFI_ERROR (Status)) {\r
1419 return Status;\r
1420 }\r
b659408b 1421 }\r
a2e61982 1422\r
b659408b
ZL
1423 //\r
1424 // Connect TCP.\r
1425 //\r
1426 Status = HttpConnectTcp4 (HttpInstance);\r
1427 if (EFI_ERROR (Status)) {\r
1428 return Status;\r
1429 }\r
1430 } else {\r
1431 //\r
1432 // Configure TCP instance.\r
1433 //\r
a2e61982
ZL
1434 if (Configure) {\r
1435 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1436 if (EFI_ERROR (Status)) {\r
1437 return Status;\r
1438 }\r
b659408b 1439 }\r
a2e61982 1440\r
b659408b
ZL
1441 //\r
1442 // Connect TCP.\r
1443 //\r
1444 Status = HttpConnectTcp6 (HttpInstance);\r
1445 if (EFI_ERROR (Status)) {\r
1446 return Status;\r
1447 }\r
1448 }\r
f75a7f56 1449\r
b659408b 1450 return EFI_SUCCESS;\r
f75a7f56 1451\r
b659408b
ZL
1452}\r
1453\r
1454/**\r
dac45de3 1455 Send the HTTP or HTTPS message through TCP4 or TCP6.\r
47f51a06
YT
1456\r
1457 @param[in] HttpInstance The HTTP instance private data.\r
1458 @param[in] Wrap The HTTP token's wrap data.\r
1459 @param[in] TxString Buffer containing the HTTP message string.\r
1460 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1461\r
1462 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1463 @retval Others Other error as indicated.\r
1464\r
1465**/\r
1466EFI_STATUS\r
b659408b 1467HttpTransmitTcp (\r
47f51a06
YT
1468 IN HTTP_PROTOCOL *HttpInstance,\r
1469 IN HTTP_TOKEN_WRAP *Wrap,\r
1470 IN UINT8 *TxString,\r
1471 IN UINTN TxStringLen\r
1472 )\r
1473{\r
1474 EFI_STATUS Status;\r
b659408b 1475 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1476 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1477 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1478 EFI_TCP6_PROTOCOL *Tcp6;\r
f75a7f56 1479 UINT8 *TlsRecord;\r
07bd82d4 1480 UINT16 PayloadSize;\r
dac45de3 1481 NET_FRAGMENT TempFragment;\r
07bd82d4
JW
1482 NET_FRAGMENT Fragment;\r
1483 UINTN RecordCount;\r
1484 UINTN RemainingLen;\r
dac45de3
JW
1485\r
1486 Status = EFI_SUCCESS;\r
07bd82d4
JW
1487 TlsRecord = NULL;\r
1488 PayloadSize = 0;\r
12b96a93
JW
1489 TempFragment.Len = 0;\r
1490 TempFragment.Bulk = NULL;\r
07bd82d4
JW
1491 Fragment.Len = 0;\r
1492 Fragment.Bulk = NULL;\r
1493 RecordCount = 0;\r
1494 RemainingLen = 0;\r
dac45de3
JW
1495\r
1496 //\r
1497 // Need to encrypt data.\r
1498 //\r
1499 if (HttpInstance->UseHttps) {\r
1500 //\r
07bd82d4 1501 // Allocate enough buffer for each TLS plaintext records.\r
dac45de3 1502 //\r
07bd82d4
JW
1503 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1504 if (TlsRecord == NULL) {\r
dac45de3
JW
1505 Status = EFI_OUT_OF_RESOURCES;\r
1506 return Status;\r
1507 }\r
07bd82d4 1508\r
dac45de3 1509 //\r
07bd82d4 1510 // Allocate enough buffer for all TLS ciphertext records.\r
dac45de3 1511 //\r
07bd82d4
JW
1512 RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
1513 Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
1514 if (Fragment.Bulk == NULL) {\r
1515 Status = EFI_OUT_OF_RESOURCES;\r
1516 goto ON_ERROR;\r
1517 }\r
dac45de3 1518\r
07bd82d4
JW
1519 //\r
1520 // Encrypt each TLS plaintext records.\r
1521 //\r
1522 RemainingLen = TxStringLen;\r
1523 while (RemainingLen != 0) {\r
1524 PayloadSize = (UINT16) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
f75a7f56 1525\r
07bd82d4
JW
1526 ((TLS_RECORD_HEADER *) TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
1527 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
1528 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
1529 ((TLS_RECORD_HEADER *) TlsRecord)->Length = PayloadSize;\r
1530\r
1531 CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
f75a7f56 1532\r
07bd82d4 1533 Status = TlsProcessMessage (\r
f75a7f56
LG
1534 HttpInstance,\r
1535 TlsRecord,\r
1536 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1537 EfiTlsEncrypt,\r
07bd82d4
JW
1538 &TempFragment\r
1539 );\r
1540 if (EFI_ERROR (Status)) {\r
1541 goto ON_ERROR;\r
1542 }\r
1543\r
1544 //\r
f75a7f56 1545 // Record the processed/encrypted Packet.\r
07bd82d4
JW
1546 //\r
1547 CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
1548 Fragment.Len += TempFragment.Len;\r
1549\r
1550 FreePool (TempFragment.Bulk);\r
1551 TempFragment.Len = 0;\r
1552 TempFragment.Bulk = NULL;\r
f75a7f56 1553\r
07bd82d4
JW
1554 RemainingLen -= (UINTN) PayloadSize;\r
1555 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
dac45de3 1556 }\r
07bd82d4
JW
1557\r
1558 FreePool (TlsRecord);\r
1559 TlsRecord = NULL;\r
dac45de3 1560 }\r
f75a7f56 1561\r
dac45de3 1562 if (!HttpInstance->LocalAddressIsIPv6) {\r
b659408b
ZL
1563 Tcp4 = HttpInstance->Tcp4;\r
1564 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
dac45de3
JW
1565\r
1566 if (HttpInstance->UseHttps) {\r
07bd82d4
JW
1567 Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
1568 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1569 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
dac45de3
JW
1570 } else {\r
1571 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1572 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1573 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1574 }\r
f75a7f56
LG
1575\r
1576 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1577\r
b659408b
ZL
1578 Wrap->TcpWrap.IsTxDone = FALSE;\r
1579 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1580 if (EFI_ERROR (Status)) {\r
1581 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1582 goto ON_ERROR;\r
b659408b 1583 }\r
47f51a06 1584\r
b659408b
ZL
1585 } else {\r
1586 Tcp6 = HttpInstance->Tcp6;\r
1587 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
f75a7f56 1588\r
dac45de3 1589 if (HttpInstance->UseHttps) {\r
07bd82d4
JW
1590 Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
1591 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1592 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
dac45de3
JW
1593 } else {\r
1594 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1595 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1596 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1597 }\r
f75a7f56 1598\r
b659408b
ZL
1599 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1600\r
1601 Wrap->TcpWrap.IsTxDone = FALSE;\r
1602 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1603 if (EFI_ERROR (Status)) {\r
1604 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1605 goto ON_ERROR;\r
b659408b 1606 }\r
47f51a06 1607 }\r
f75a7f56 1608\r
07bd82d4
JW
1609 return Status;\r
1610\r
1611ON_ERROR:\r
f75a7f56 1612\r
07bd82d4
JW
1613 if (HttpInstance->UseHttps) {\r
1614 if (TlsRecord != NULL) {\r
1615 FreePool (TlsRecord);\r
1616 TlsRecord = NULL;\r
1617 }\r
f75a7f56 1618\r
07bd82d4
JW
1619 if (Fragment.Bulk != NULL) {\r
1620 FreePool (Fragment.Bulk);\r
1621 Fragment.Bulk = NULL;\r
1622 }\r
1623 }\r
1624\r
47f51a06
YT
1625 return Status;\r
1626}\r
1627\r
47f51a06
YT
1628/**\r
1629 Check whether the user's token or event has already\r
b659408b 1630 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1631\r
1632 @param[in] Map The container of either user's transmit or receive\r
1633 token.\r
1634 @param[in] Item Current item to check against.\r
1635 @param[in] Context The Token to check againist.\r
1636\r
1637 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1638 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1639 context.\r
1640\r
1641**/\r
1642EFI_STATUS\r
1643EFIAPI\r
1644HttpTokenExist (\r
1645 IN NET_MAP *Map,\r
1646 IN NET_MAP_ITEM *Item,\r
1647 IN VOID *Context\r
1648 )\r
1649{\r
1650 EFI_HTTP_TOKEN *Token;\r
1651 EFI_HTTP_TOKEN *TokenInItem;\r
1652\r
1653 Token = (EFI_HTTP_TOKEN *) Context;\r
1654 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1655\r
1656 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1657 return EFI_ACCESS_DENIED;\r
1658 }\r
1659\r
1660 return EFI_SUCCESS;\r
1661}\r
1662\r
1663/**\r
b659408b 1664 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1665\r
b659408b 1666 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1667 @param[in] Item Current item to check against.\r
1668 @param[in] Context The Token to check againist.\r
1669\r
1670 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1671 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1672\r
1673**/\r
1674EFI_STATUS\r
1675EFIAPI\r
1676HttpTcpNotReady (\r
1677 IN NET_MAP *Map,\r
1678 IN NET_MAP_ITEM *Item,\r
1679 IN VOID *Context\r
1680 )\r
1681{\r
1682 HTTP_TOKEN_WRAP *ValueInItem;\r
1683\r
1684 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1685\r
1686 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1687 return EFI_NOT_READY;\r
1688 }\r
f75a7f56 1689\r
47f51a06
YT
1690 return EFI_SUCCESS;\r
1691}\r
1692\r
1693/**\r
dac45de3 1694 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.\r
47f51a06 1695\r
b659408b 1696 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06
YT
1697 @param[in] Item Current item to check against.\r
1698 @param[in] Context The Token to check againist.\r
1699\r
1700 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1701 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1702 queue.\r
1703\r
1704**/\r
1705EFI_STATUS\r
1706EFIAPI\r
1707HttpTcpTransmit (\r
1708 IN NET_MAP *Map,\r
1709 IN NET_MAP_ITEM *Item,\r
1710 IN VOID *Context\r
1711 )\r
1712{\r
1713 HTTP_TOKEN_WRAP *ValueInItem;\r
1714 EFI_STATUS Status;\r
19c25725 1715 CHAR8 *RequestMsg;\r
47f51a06 1716 CHAR8 *Url;\r
b9679cd7 1717 UINTN UrlSize;\r
19c25725 1718 UINTN RequestMsgSize;\r
47f51a06 1719\r
63f1d6a4
JW
1720 RequestMsg = NULL;\r
1721\r
47f51a06
YT
1722 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1723 if (ValueInItem->TcpWrap.IsTxDone) {\r
1724 return EFI_SUCCESS;\r
1725 }\r
1726\r
1727 //\r
1728 // Parse the URI of the remote host.\r
1729 //\r
b9679cd7
SZ
1730 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
1731 Url = AllocatePool (UrlSize);\r
47f51a06
YT
1732 if (Url == NULL) {\r
1733 return EFI_OUT_OF_RESOURCES;\r
1734 }\r
1735\r
b9679cd7 1736 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
47f51a06
YT
1737\r
1738 //\r
1739 // Create request message.\r
1740 //\r
19c25725 1741 Status = HttpGenRequestMessage (\r
47f51a06 1742 ValueInItem->HttpToken->Message,\r
f58554fc 1743 Url,\r
19c25725
NH
1744 &RequestMsg,\r
1745 &RequestMsgSize\r
47f51a06
YT
1746 );\r
1747 FreePool (Url);\r
f58554fc 1748\r
63f1d6a4 1749 if (EFI_ERROR (Status) || NULL == RequestMsg){\r
f58554fc 1750 return Status;\r
47f51a06
YT
1751 }\r
1752\r
63f1d6a4
JW
1753 ASSERT (RequestMsg != NULL);\r
1754\r
47f51a06
YT
1755 //\r
1756 // Transmit the request message.\r
1757 //\r
b659408b 1758 Status = HttpTransmitTcp (\r
47f51a06
YT
1759 ValueInItem->HttpInstance,\r
1760 ValueInItem,\r
19c25725
NH
1761 (UINT8*) RequestMsg,\r
1762 RequestMsgSize\r
47f51a06 1763 );\r
19c25725 1764 FreePool (RequestMsg);\r
47f51a06
YT
1765 return Status;\r
1766}\r
1767\r
1768/**\r
1769 Receive the HTTP response by processing the associated HTTP token.\r
1770\r
b659408b 1771 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06
YT
1772 @param[in] Item Current item to check against.\r
1773 @param[in] Context The Token to check againist.\r
1774\r
1775 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1776 queue.\r
1777 @retval Others Other error as indicated.\r
1778\r
1779**/\r
1780EFI_STATUS\r
1781EFIAPI\r
1782HttpTcpReceive (\r
1783 IN NET_MAP *Map,\r
1784 IN NET_MAP_ITEM *Item,\r
1785 IN VOID *Context\r
1786 )\r
1787{\r
1788 //\r
1789 // Process the queued HTTP response.\r
1790 //\r
1791 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1792}\r
1793\r
b659408b
ZL
1794/**\r
1795 Receive the HTTP header by processing the associated HTTP token.\r
1796\r
1797 @param[in] HttpInstance The HTTP instance private data.\r
1798 @param[in, out] SizeofHeaders The HTTP header length.\r
1799 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
b347a22a 1800 @param[in] Timeout The time to wait for receiving the header packet.\r
f75a7f56
LG
1801\r
1802 @retval EFI_SUCCESS The HTTP header is received.\r
b659408b
ZL
1803 @retval Others Other errors as indicated.\r
1804\r
1805**/\r
1806EFI_STATUS\r
1807HttpTcpReceiveHeader (\r
1808 IN HTTP_PROTOCOL *HttpInstance,\r
1809 IN OUT UINTN *SizeofHeaders,\r
b347a22a
JW
1810 IN OUT UINTN *BufferSize,\r
1811 IN EFI_EVENT Timeout\r
b659408b
ZL
1812 )\r
1813{\r
1814 EFI_STATUS Status;\r
1815 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1816 EFI_TCP4_PROTOCOL *Tcp4;\r
1817 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1818 EFI_TCP6_PROTOCOL *Tcp6;\r
1819 CHAR8 **EndofHeader;\r
1820 CHAR8 **HttpHeaders;\r
1821 CHAR8 *Buffer;\r
dac45de3 1822 NET_FRAGMENT Fragment;\r
b659408b
ZL
1823\r
1824 ASSERT (HttpInstance != NULL);\r
1825\r
1826 EndofHeader = HttpInstance->EndofHeader;\r
1827 HttpHeaders = HttpInstance->HttpHeaders;\r
1828 Tcp4 = HttpInstance->Tcp4;\r
1829 Tcp6 = HttpInstance->Tcp6;\r
1830 Buffer = NULL;\r
1831 Rx4Token = NULL;\r
1832 Rx6Token = NULL;\r
dac45de3
JW
1833 Fragment.Len = 0;\r
1834 Fragment.Bulk = NULL;\r
f75a7f56 1835\r
b659408b
ZL
1836 if (HttpInstance->LocalAddressIsIPv6) {\r
1837 ASSERT (Tcp6 != NULL);\r
1838 } else {\r
1839 ASSERT (Tcp4 != NULL);\r
1840 }\r
1841\r
dac45de3
JW
1842 if (!HttpInstance->UseHttps) {\r
1843 Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
1844 if (EFI_ERROR (Status)) {\r
b659408b
ZL
1845 return Status;\r
1846 }\r
dac45de3
JW
1847 }\r
1848\r
1849 if (!HttpInstance->LocalAddressIsIPv6) {\r
1850 if (!HttpInstance->UseHttps) {\r
1851 Rx4Token = &HttpInstance->Rx4Token;\r
1852 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1853 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1854 Status = EFI_OUT_OF_RESOURCES;\r
1855 return Status;\r
1856 }\r
1857 }\r
f75a7f56 1858\r
b659408b
ZL
1859 //\r
1860 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1861 //\r
dac45de3
JW
1862 while (*EndofHeader == NULL) {\r
1863 if (!HttpInstance->UseHttps) {\r
1864 HttpInstance->IsRxDone = FALSE;\r
1865 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1866 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1867 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1868 if (EFI_ERROR (Status)) {\r
1869 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1870 return Status;\r
1871 }\r
1872\r
1873 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1874 Tcp4->Poll (Tcp4);\r
1875 }\r
1876\r
1877 if (!HttpInstance->IsRxDone) {\r
1878 //\r
1879 // Cancle the Token before close its Event.\r
1880 //\r
1881 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);\r
1882 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1883 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1884 }\r
1885\r
1886 Status = Rx4Token->CompletionToken.Status;\r
1887 if (EFI_ERROR (Status)) {\r
1888 return Status;\r
1889 }\r
f75a7f56 1890\r
dac45de3
JW
1891 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1892 Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
1893 } else {\r
1894 if (Fragment.Bulk != NULL) {\r
1895 FreePool (Fragment.Bulk);\r
1896 Fragment.Bulk = NULL;\r
1897 }\r
f75a7f56 1898\r
dac45de3
JW
1899 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1900 if (EFI_ERROR (Status)) {\r
1901 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1902 return Status;\r
1903 }\r
b347a22a
JW
1904 }\r
1905\r
b659408b
ZL
1906 //\r
1907 // Append the response string.\r
1908 //\r
dac45de3 1909 *BufferSize = *SizeofHeaders + Fragment.Len;\r
b659408b
ZL
1910 Buffer = AllocateZeroPool (*BufferSize);\r
1911 if (Buffer == NULL) {\r
1912 Status = EFI_OUT_OF_RESOURCES;\r
1913 return Status;\r
1914 }\r
dac45de3 1915\r
b659408b 1916 if (*HttpHeaders != NULL) {\r
dac45de3 1917 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
1918 FreePool (*HttpHeaders);\r
1919 }\r
dac45de3 1920\r
b659408b 1921 CopyMem (\r
dac45de3
JW
1922 Buffer + *SizeofHeaders,\r
1923 Fragment.Bulk,\r
1924 Fragment.Len\r
b659408b 1925 );\r
dac45de3
JW
1926 *HttpHeaders = Buffer;\r
1927 *SizeofHeaders = *BufferSize;\r
1928\r
b659408b
ZL
1929 //\r
1930 // Check whether we received end of HTTP headers.\r
1931 //\r
19bd1335 1932 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
dac45de3 1933 };\r
f75a7f56 1934\r
dac45de3
JW
1935 //\r
1936 // Free the buffer.\r
1937 //\r
1938 if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1939 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1940 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1941 Fragment.Bulk = NULL;\r
1942 }\r
1943\r
1944 if (Fragment.Bulk != NULL) {\r
1945 FreePool (Fragment.Bulk);\r
1946 Fragment.Bulk = NULL;\r
f75a7f56 1947 }\r
b659408b 1948 } else {\r
dac45de3
JW
1949 if (!HttpInstance->UseHttps) {\r
1950 Rx6Token = &HttpInstance->Rx6Token;\r
1951 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1952 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1953 Status = EFI_OUT_OF_RESOURCES;\r
1954 return Status;\r
1955 }\r
b659408b 1956 }\r
f75a7f56 1957\r
b659408b
ZL
1958 //\r
1959 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1960 //\r
dac45de3
JW
1961 while (*EndofHeader == NULL) {\r
1962 if (!HttpInstance->UseHttps) {\r
1963 HttpInstance->IsRxDone = FALSE;\r
1964 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1965 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1966 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1967 if (EFI_ERROR (Status)) {\r
1968 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1969 return Status;\r
1970 }\r
1971\r
1972 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1973 Tcp6->Poll (Tcp6);\r
1974 }\r
1975\r
1976 if (!HttpInstance->IsRxDone) {\r
1977 //\r
1978 // Cancle the Token before close its Event.\r
1979 //\r
1980 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);\r
1981 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1982 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1983 }\r
1984\r
1985 Status = Rx6Token->CompletionToken.Status;\r
1986 if (EFI_ERROR (Status)) {\r
1987 return Status;\r
1988 }\r
f75a7f56 1989\r
dac45de3
JW
1990 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1991 Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
1992 } else {\r
1993 if (Fragment.Bulk != NULL) {\r
1994 FreePool (Fragment.Bulk);\r
1995 Fragment.Bulk = NULL;\r
1996 }\r
f75a7f56 1997\r
dac45de3
JW
1998 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1999 if (EFI_ERROR (Status)) {\r
2000 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
2001 return Status;\r
2002 }\r
b347a22a
JW
2003 }\r
2004\r
b659408b
ZL
2005 //\r
2006 // Append the response string.\r
2007 //\r
dac45de3 2008 *BufferSize = *SizeofHeaders + Fragment.Len;\r
b659408b
ZL
2009 Buffer = AllocateZeroPool (*BufferSize);\r
2010 if (Buffer == NULL) {\r
2011 Status = EFI_OUT_OF_RESOURCES;\r
2012 return Status;\r
2013 }\r
dac45de3 2014\r
b659408b 2015 if (*HttpHeaders != NULL) {\r
dac45de3 2016 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
2017 FreePool (*HttpHeaders);\r
2018 }\r
dac45de3 2019\r
b659408b 2020 CopyMem (\r
dac45de3
JW
2021 Buffer + *SizeofHeaders,\r
2022 Fragment.Bulk,\r
2023 Fragment.Len\r
b659408b 2024 );\r
dac45de3
JW
2025 *HttpHeaders = Buffer;\r
2026 *SizeofHeaders = *BufferSize;\r
2027\r
b659408b
ZL
2028 //\r
2029 // Check whether we received end of HTTP headers.\r
2030 //\r
f75a7f56 2031 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
dac45de3
JW
2032 };\r
2033\r
2034 //\r
2035 // Free the buffer.\r
2036 //\r
2037 if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2038 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2039 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2040 Fragment.Bulk = NULL;\r
2041 }\r
2042\r
2043 if (Fragment.Bulk != NULL) {\r
2044 FreePool (Fragment.Bulk);\r
2045 Fragment.Bulk = NULL;\r
b659408b 2046 }\r
f75a7f56 2047 }\r
b659408b
ZL
2048\r
2049 //\r
2050 // Skip the CRLF after the HTTP headers.\r
2051 //\r
b16abfcc
JW
2052 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
2053\r
2054 *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
b659408b
ZL
2055\r
2056 return EFI_SUCCESS;\r
2057}\r
2058\r
2059/**\r
2060 Receive the HTTP body by processing the associated HTTP token.\r
2061\r
2062 @param[in] Wrap The HTTP token's wrap data.\r
2063 @param[in] HttpMsg The HTTP message data.\r
2064\r
f75a7f56 2065 @retval EFI_SUCCESS The HTTP body is received.\r
b659408b
ZL
2066 @retval Others Other error as indicated.\r
2067\r
2068**/\r
2069EFI_STATUS\r
2070HttpTcpReceiveBody (\r
2071 IN HTTP_TOKEN_WRAP *Wrap,\r
30526a51 2072 IN EFI_HTTP_MESSAGE *HttpMsg\r
b659408b
ZL
2073 )\r
2074{\r
2075 EFI_STATUS Status;\r
2076 HTTP_PROTOCOL *HttpInstance;\r
2077 EFI_TCP6_PROTOCOL *Tcp6;\r
2078 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2079 EFI_TCP4_PROTOCOL *Tcp4;\r
2080 EFI_TCP4_IO_TOKEN *Rx4Token;\r
f75a7f56 2081\r
b659408b
ZL
2082 HttpInstance = Wrap->HttpInstance;\r
2083 Tcp4 = HttpInstance->Tcp4;\r
2084 Tcp6 = HttpInstance->Tcp6;\r
2085 Rx4Token = NULL;\r
2086 Rx6Token = NULL;\r
f75a7f56 2087\r
b659408b
ZL
2088 if (HttpInstance->LocalAddressIsIPv6) {\r
2089 ASSERT (Tcp6 != NULL);\r
2090 } else {\r
2091 ASSERT (Tcp4 != NULL);\r
2092 }\r
f75a7f56 2093\r
b659408b
ZL
2094 if (HttpInstance->LocalAddressIsIPv6) {\r
2095 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
6893b16f
JW
2096 Rx6Token ->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2097 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
b659408b
ZL
2098 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
2099 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
2100\r
2101 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
2102 if (EFI_ERROR (Status)) {\r
2103 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
2104 return Status;\r
2105 }\r
b659408b
ZL
2106 } else {\r
2107 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
6893b16f
JW
2108 Rx4Token->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2109 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
b659408b 2110 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
f75a7f56 2111\r
b659408b
ZL
2112 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
2113 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
2114 if (EFI_ERROR (Status)) {\r
2115 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
2116 return Status;\r
2117 }\r
2118 }\r
2119\r
2120 return EFI_SUCCESS;\r
2121\r
2122}\r
2123\r
2124/**\r
2125 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
2126\r
2127 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 2128\r
b659408b
ZL
2129**/\r
2130VOID\r
2131HttpTcpTokenCleanup (\r
2132 IN HTTP_TOKEN_WRAP *Wrap\r
2133 )\r
f75a7f56 2134{\r
b659408b
ZL
2135 HTTP_PROTOCOL *HttpInstance;\r
2136 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2137 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2138\r
1b96428d 2139 ASSERT (Wrap != NULL);\r
b659408b
ZL
2140 HttpInstance = Wrap->HttpInstance;\r
2141 Rx4Token = NULL;\r
2142 Rx6Token = NULL;\r
f75a7f56 2143\r
b659408b 2144 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d 2145 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
f75a7f56 2146\r
59844e12
JW
2147 if (Rx6Token->CompletionToken.Event != NULL) {\r
2148 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2149 Rx6Token->CompletionToken.Event = NULL;\r
b659408b
ZL
2150 }\r
2151\r
59844e12 2152 FreePool (Wrap);\r
b659408b
ZL
2153\r
2154 Rx6Token = &HttpInstance->Rx6Token;\r
f75a7f56 2155\r
59844e12
JW
2156 if (Rx6Token->CompletionToken.Event != NULL) {\r
2157 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2158 Rx6Token->CompletionToken.Event = NULL;\r
2159 }\r
f75a7f56 2160\r
b659408b
ZL
2161 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2162 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2163 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2164 }\r
f75a7f56 2165\r
b659408b 2166 } else {\r
1b96428d 2167 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
f75a7f56 2168\r
59844e12
JW
2169 if (Rx4Token->CompletionToken.Event != NULL) {\r
2170 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2171 Rx4Token->CompletionToken.Event = NULL;\r
1b96428d 2172 }\r
f75a7f56 2173\r
1b96428d
ZL
2174 FreePool (Wrap);\r
2175\r
59844e12
JW
2176 Rx4Token = &HttpInstance->Rx4Token;\r
2177\r
2178 if (Rx4Token->CompletionToken.Event != NULL) {\r
2179 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2180 Rx4Token->CompletionToken.Event = NULL;\r
b659408b 2181 }\r
f75a7f56
LG
2182\r
2183\r
b659408b
ZL
2184 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2185 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2186 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2187 }\r
2188 }\r
2189\r
2190}\r