]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
CommitLineData
47f51a06
YT
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
ab796d3e 4Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>\r
90f658c4 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
ecf98fbc 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
47f51a06
YT
7\r
8**/\r
9\r
10#include "HttpDriver.h"\r
11\r
12/**\r
f75a7f56 13 The common notify function used in HTTP driver.\r
47f51a06
YT
14\r
15 @param[in] Event The event signaled.\r
16 @param[in] Context The context.\r
17\r
18**/\r
19VOID\r
20EFIAPI\r
21HttpCommonNotify (\r
22 IN EFI_EVENT Event,\r
23 IN VOID *Context\r
24 )\r
25{\r
26 if ((Event == NULL) || (Context == NULL)) {\r
d1050b9d 27 return;\r
47f51a06
YT
28 }\r
29\r
d1050b9d 30 *((BOOLEAN *)Context) = TRUE;\r
47f51a06
YT
31}\r
32\r
33/**\r
b659408b 34 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
47f51a06 35\r
47f51a06
YT
36 @param[in] Context The context.\r
37\r
38**/\r
39VOID\r
40EFIAPI\r
49c9f74c 41HttpTcpTransmitNotifyDpc (\r
d1050b9d 42 IN VOID *Context\r
47f51a06
YT
43 )\r
44{\r
d1050b9d
MK
45 HTTP_TOKEN_WRAP *Wrap;\r
46 HTTP_PROTOCOL *HttpInstance;\r
47f51a06 47\r
49c9f74c 48 if (Context == NULL) {\r
d1050b9d 49 return;\r
47f51a06 50 }\r
f75a7f56 51\r
d1050b9d 52 Wrap = (HTTP_TOKEN_WRAP *)Context;\r
b659408b 53 HttpInstance = Wrap->HttpInstance;\r
f75a7f56 54\r
b659408b 55 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d
MK
56 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
57 gBS->SignalEvent (Wrap->HttpToken->Event);\r
47f51a06 58\r
d1050b9d
MK
59 //\r
60 // Free resources.\r
61 //\r
62 if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
63 FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
64 }\r
f75a7f56 65\r
d1050b9d
MK
66 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
67 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
68 }\r
b659408b
ZL
69 } else {\r
70 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
71 gBS->SignalEvent (Wrap->HttpToken->Event);\r
f75a7f56 72\r
b659408b
ZL
73 //\r
74 // Free resources.\r
75 //\r
76 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
77 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
78 }\r
47f51a06 79\r
b659408b
ZL
80 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
81 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
f75a7f56 82 }\r
47f51a06
YT
83 }\r
84\r
47f51a06
YT
85 Wrap->TcpWrap.IsTxDone = TRUE;\r
86\r
87 //\r
88 // Check pending TxTokens and sent out.\r
89 //\r
90 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);\r
47f51a06
YT
91}\r
92\r
49c9f74c
FS
93/**\r
94 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.\r
95\r
96 @param Event The receive event delivered to TCP for transmit.\r
97 @param Context Context for the callback.\r
98\r
99**/\r
100VOID\r
101EFIAPI\r
102HttpTcpTransmitNotify (\r
d1050b9d
MK
103 IN EFI_EVENT Event,\r
104 IN VOID *Context\r
49c9f74c
FS
105 )\r
106{\r
107 //\r
108 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
109 //\r
110 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
111}\r
112\r
47f51a06 113/**\r
b659408b 114 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
47f51a06 115\r
47f51a06
YT
116 @param[in] Context The context.\r
117\r
118**/\r
119VOID\r
120EFIAPI\r
49c9f74c 121HttpTcpReceiveNotifyDpc (\r
d1050b9d 122 IN VOID *Context\r
47f51a06
YT
123 )\r
124{\r
d1050b9d
MK
125 HTTP_TOKEN_WRAP *Wrap;\r
126 NET_MAP_ITEM *Item;\r
127 UINTN Length;\r
128 EFI_STATUS Status;\r
129 HTTP_PROTOCOL *HttpInstance;\r
130 BOOLEAN UsingIpv6;\r
47f51a06 131\r
49c9f74c 132 if (Context == NULL) {\r
d1050b9d 133 return;\r
47f51a06
YT
134 }\r
135\r
d1050b9d 136 Wrap = (HTTP_TOKEN_WRAP *)Context;\r
47f51a06 137 HttpInstance = Wrap->HttpInstance;\r
b659408b 138 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
f75a7f56 139\r
b659408b
ZL
140 if (UsingIpv6) {\r
141 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
30526a51 142 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
f75a7f56 143\r
b659408b 144 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
c49ca4a2 145 DEBUG ((DEBUG_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status));\r
621a618a
ZL
146 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
147 gBS->SignalEvent (Wrap->HttpToken->Event);\r
30526a51
JW
148\r
149 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
150 if (Item != NULL) {\r
151 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
152 }\r
f75a7f56 153\r
30526a51
JW
154 FreePool (Wrap);\r
155 Wrap = NULL;\r
f75a7f56 156\r
d1050b9d 157 return;\r
b659408b 158 }\r
b659408b
ZL
159 } else {\r
160 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
30526a51 161 Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;\r
f75a7f56 162\r
b659408b 163 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
c49ca4a2 164 DEBUG ((DEBUG_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status));\r
621a618a
ZL
165 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
166 gBS->SignalEvent (Wrap->HttpToken->Event);\r
f75a7f56 167\r
30526a51
JW
168 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
169 if (Item != NULL) {\r
170 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
171 }\r
f75a7f56 172\r
30526a51
JW
173 FreePool (Wrap);\r
174 Wrap = NULL;\r
f75a7f56 175\r
d1050b9d 176 return;\r
b659408b
ZL
177 }\r
178 }\r
47f51a06
YT
179\r
180 //\r
181 // Check whether we receive a complete HTTP message.\r
182 //\r
183 ASSERT (HttpInstance->MsgParser != NULL);\r
b659408b 184 if (UsingIpv6) {\r
d1050b9d 185 Length = (UINTN)Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
b659408b 186 } else {\r
d1050b9d 187 Length = (UINTN)Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
b659408b 188 }\r
47f51a06 189\r
895b87e3
JW
190 //\r
191 // Record the CallbackData data.\r
192 //\r
d1050b9d
MK
193 HttpInstance->CallbackData.Wrap = (VOID *)Wrap;\r
194 HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;\r
895b87e3
JW
195 HttpInstance->CallbackData.ParseDataLength = Length;\r
196\r
197 //\r
198 // Parse Body with CallbackData data.\r
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
d1050b9d 206 return;\r
47f51a06
YT
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
d1050b9d 224 (CHAR8 *)Wrap->HttpToken->Message->Body;\r
47f51a06
YT
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
d1050b9d 229 return;\r
47f51a06 230 }\r
d1050b9d 231\r
47f51a06 232 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);\r
d1050b9d 233 HttpInstance->NextMsg = HttpInstance->CacheBody;\r
47f51a06
YT
234 HttpInstance->CacheOffset = 0;\r
235 }\r
236 }\r
237\r
238 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);\r
239 if (Item != NULL) {\r
240 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
241 }\r
242\r
47f51a06 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 gBS->SignalEvent (Wrap->HttpToken->Event);\r
251\r
252 //\r
253 // Check pending RxTokens and receive the HTTP message.\r
254 //\r
255 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
30526a51
JW
256\r
257 FreePool (Wrap);\r
258 Wrap = NULL;\r
47f51a06
YT
259}\r
260\r
49c9f74c
FS
261/**\r
262 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.\r
263\r
264 @param Event The receive event delivered to TCP for receive.\r
265 @param Context Context for the callback.\r
266\r
267**/\r
268VOID\r
269EFIAPI\r
270HttpTcpReceiveNotify (\r
d1050b9d
MK
271 IN EFI_EVENT Event,\r
272 IN VOID *Context\r
49c9f74c
FS
273 )\r
274{\r
275 //\r
276 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
277 //\r
278 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
279}\r
280\r
47f51a06 281/**\r
b659408b 282 Create events for the TCP connection token and TCP close token.\r
47f51a06
YT
283\r
284 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
285\r
286 @retval EFI_SUCCESS The events are created successfully.\r
287 @retval others Other error as indicated.\r
288\r
289**/\r
290EFI_STATUS\r
b659408b 291HttpCreateTcpConnCloseEvent (\r
d1050b9d 292 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
293 )\r
294{\r
d1050b9d 295 EFI_STATUS Status;\r
b659408b
ZL
296\r
297 if (!HttpInstance->LocalAddressIsIPv6) {\r
47f51a06 298 //\r
ba3b642d 299 // Create events for various asynchronous operations.\r
47f51a06
YT
300 //\r
301 Status = gBS->CreateEvent (\r
302 EVT_NOTIFY_SIGNAL,\r
303 TPL_NOTIFY,\r
304 HttpCommonNotify,\r
b659408b
ZL
305 &HttpInstance->IsTcp4ConnDone,\r
306 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
47f51a06
YT
307 );\r
308 if (EFI_ERROR (Status)) {\r
309 goto ERROR;\r
310 }\r
311\r
312 //\r
b659408b
ZL
313 // Initialize Tcp4CloseToken\r
314 //\r
315 Status = gBS->CreateEvent (\r
316 EVT_NOTIFY_SIGNAL,\r
317 TPL_NOTIFY,\r
318 HttpCommonNotify,\r
319 &HttpInstance->IsTcp4CloseDone,\r
320 &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
321 );\r
322 if (EFI_ERROR (Status)) {\r
323 goto ERROR;\r
324 }\r
b659408b
ZL
325 } else {\r
326 //\r
ba3b642d 327 // Create events for various asynchronous operations.\r
47f51a06
YT
328 //\r
329 Status = gBS->CreateEvent (\r
330 EVT_NOTIFY_SIGNAL,\r
331 TPL_NOTIFY,\r
332 HttpCommonNotify,\r
b659408b
ZL
333 &HttpInstance->IsTcp6ConnDone,\r
334 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
47f51a06
YT
335 );\r
336 if (EFI_ERROR (Status)) {\r
337 goto ERROR;\r
338 }\r
339\r
b659408b
ZL
340 //\r
341 // Initialize Tcp6CloseToken\r
342 //\r
343 Status = gBS->CreateEvent (\r
344 EVT_NOTIFY_SIGNAL,\r
345 TPL_NOTIFY,\r
346 HttpCommonNotify,\r
347 &HttpInstance->IsTcp6CloseDone,\r
348 &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
349 );\r
350 if (EFI_ERROR (Status)) {\r
351 goto ERROR;\r
352 }\r
353 }\r
f75a7f56 354\r
47f51a06
YT
355 return EFI_SUCCESS;\r
356\r
357ERROR:\r
358 //\r
359 // Error handling\r
360 //\r
b659408b 361 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
362\r
363 return Status;\r
364}\r
365\r
47f51a06 366/**\r
b659408b 367 Close events in the TCP connection token and TCP close token.\r
47f51a06
YT
368\r
369 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
370\r
371**/\r
372VOID\r
b659408b 373HttpCloseTcpConnCloseEvent (\r
d1050b9d 374 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
375 )\r
376{\r
377 ASSERT (HttpInstance != NULL);\r
378\r
b659408b
ZL
379 if (HttpInstance->LocalAddressIsIPv6) {\r
380 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
381 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
382 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
383 }\r
47f51a06 384\r
b659408b 385 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
d1050b9d 386 gBS->CloseEvent (HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
b659408b
ZL
387 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
388 }\r
b659408b
ZL
389 } else {\r
390 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
391 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
392 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
393 }\r
394\r
395 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
d1050b9d 396 gBS->CloseEvent (HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
b659408b
ZL
397 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
398 }\r
399 }\r
47f51a06
YT
400}\r
401\r
402/**\r
b659408b 403 Create event for the TCP transmit token.\r
47f51a06
YT
404\r
405 @param[in] Wrap Point to HTTP token's wrap data.\r
406\r
407 @retval EFI_SUCCESS The events is created successfully.\r
408 @retval others Other error as indicated.\r
409\r
410**/\r
411EFI_STATUS\r
b659408b 412HttpCreateTcpTxEvent (\r
d1050b9d 413 IN HTTP_TOKEN_WRAP *Wrap\r
47f51a06
YT
414 )\r
415{\r
d1050b9d
MK
416 EFI_STATUS Status;\r
417 HTTP_PROTOCOL *HttpInstance;\r
418 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
47f51a06 419\r
b659408b 420 HttpInstance = Wrap->HttpInstance;\r
47f51a06
YT
421 TcpWrap = &Wrap->TcpWrap;\r
422\r
b659408b
ZL
423 if (!HttpInstance->LocalAddressIsIPv6) {\r
424 Status = gBS->CreateEvent (\r
425 EVT_NOTIFY_SIGNAL,\r
426 TPL_NOTIFY,\r
427 HttpTcpTransmitNotify,\r
428 Wrap,\r
429 &TcpWrap->Tx4Token.CompletionToken.Event\r
430 );\r
30526a51
JW
431 if (EFI_ERROR (Status)) {\r
432 return Status;\r
433 }\r
f75a7f56 434\r
d1050b9d
MK
435 TcpWrap->Tx4Data.Push = TRUE;\r
436 TcpWrap->Tx4Data.Urgent = FALSE;\r
437 TcpWrap->Tx4Data.FragmentCount = 1;\r
438 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
30526a51 439 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
b659408b
ZL
440 } else {\r
441 Status = gBS->CreateEvent (\r
442 EVT_NOTIFY_SIGNAL,\r
443 TPL_NOTIFY,\r
444 HttpTcpTransmitNotify,\r
445 Wrap,\r
446 &TcpWrap->Tx6Token.CompletionToken.Event\r
447 );\r
448 if (EFI_ERROR (Status)) {\r
449 return Status;\r
450 }\r
47f51a06 451\r
d1050b9d
MK
452 TcpWrap->Tx6Data.Push = TRUE;\r
453 TcpWrap->Tx6Data.Urgent = FALSE;\r
454 TcpWrap->Tx6Data.FragmentCount = 1;\r
455 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
456 TcpWrap->Tx6Token.CompletionToken.Status = EFI_NOT_READY;\r
b659408b 457 }\r
f75a7f56 458\r
47f51a06
YT
459 return EFI_SUCCESS;\r
460}\r
461\r
462/**\r
b659408b 463 Create event for the TCP receive token which is used to receive HTTP header.\r
47f51a06
YT
464\r
465 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
466\r
467 @retval EFI_SUCCESS The events is created successfully.\r
468 @retval others Other error as indicated.\r
469\r
470**/\r
471EFI_STATUS\r
b659408b 472HttpCreateTcpRxEventForHeader (\r
d1050b9d 473 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
474 )\r
475{\r
d1050b9d 476 EFI_STATUS Status;\r
47f51a06 477\r
b659408b
ZL
478 if (!HttpInstance->LocalAddressIsIPv6) {\r
479 Status = gBS->CreateEvent (\r
480 EVT_NOTIFY_SIGNAL,\r
481 TPL_NOTIFY,\r
482 HttpCommonNotify,\r
483 &HttpInstance->IsRxDone,\r
484 &HttpInstance->Rx4Token.CompletionToken.Event\r
485 );\r
486 if (EFI_ERROR (Status)) {\r
487 return Status;\r
488 }\r
f75a7f56 489\r
d1050b9d
MK
490 HttpInstance->Rx4Data.FragmentCount = 1;\r
491 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
b659408b 492 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
b659408b
ZL
493 } else {\r
494 Status = gBS->CreateEvent (\r
495 EVT_NOTIFY_SIGNAL,\r
496 TPL_NOTIFY,\r
497 HttpCommonNotify,\r
498 &HttpInstance->IsRxDone,\r
499 &HttpInstance->Rx6Token.CompletionToken.Event\r
500 );\r
501 if (EFI_ERROR (Status)) {\r
502 return Status;\r
503 }\r
504\r
d1050b9d
MK
505 HttpInstance->Rx6Data.FragmentCount = 1;\r
506 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
b659408b 507 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06
YT
508 }\r
509\r
47f51a06
YT
510 return EFI_SUCCESS;\r
511}\r
512\r
513/**\r
b659408b 514 Create event for the TCP receive token which is used to receive HTTP body.\r
47f51a06
YT
515\r
516 @param[in] Wrap Point to HTTP token's wrap data.\r
517\r
518 @retval EFI_SUCCESS The events is created successfully.\r
519 @retval others Other error as indicated.\r
520\r
521**/\r
522EFI_STATUS\r
b659408b 523HttpCreateTcpRxEvent (\r
d1050b9d 524 IN HTTP_TOKEN_WRAP *Wrap\r
47f51a06
YT
525 )\r
526{\r
d1050b9d
MK
527 EFI_STATUS Status;\r
528 HTTP_PROTOCOL *HttpInstance;\r
529 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
47f51a06 530\r
b659408b 531 HttpInstance = Wrap->HttpInstance;\r
47f51a06 532 TcpWrap = &Wrap->TcpWrap;\r
b659408b
ZL
533 if (!HttpInstance->LocalAddressIsIPv6) {\r
534 Status = gBS->CreateEvent (\r
535 EVT_NOTIFY_SIGNAL,\r
536 TPL_NOTIFY,\r
537 HttpTcpReceiveNotify,\r
538 Wrap,\r
539 &TcpWrap->Rx4Token.CompletionToken.Event\r
540 );\r
541 if (EFI_ERROR (Status)) {\r
542 return Status;\r
543 }\r
f75a7f56 544\r
d1050b9d
MK
545 TcpWrap->Rx4Data.FragmentCount = 1;\r
546 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
b659408b 547 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
b659408b
ZL
548 } else {\r
549 Status = gBS->CreateEvent (\r
550 EVT_NOTIFY_SIGNAL,\r
551 TPL_NOTIFY,\r
552 HttpTcpReceiveNotify,\r
553 Wrap,\r
554 &TcpWrap->Rx6Token.CompletionToken.Event\r
f75a7f56 555 );\r
b659408b
ZL
556 if (EFI_ERROR (Status)) {\r
557 return Status;\r
558 }\r
559\r
d1050b9d
MK
560 TcpWrap->Rx6Data.FragmentCount = 1;\r
561 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
b659408b 562 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 563 }\r
f75a7f56 564\r
b659408b
ZL
565 return EFI_SUCCESS;\r
566}\r
47f51a06 567\r
b659408b
ZL
568/**\r
569 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
47f51a06 570\r
b659408b 571 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 572\r
b659408b
ZL
573**/\r
574VOID\r
575HttpCloseTcpRxEvent (\r
d1050b9d 576 IN HTTP_TOKEN_WRAP *Wrap\r
b659408b
ZL
577 )\r
578{\r
d1050b9d 579 HTTP_PROTOCOL *HttpInstance;\r
b659408b 580\r
1b96428d 581 ASSERT (Wrap != NULL);\r
d1050b9d 582 HttpInstance = Wrap->HttpInstance;\r
f75a7f56 583\r
b659408b 584 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
585 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
586 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
b659408b
ZL
587 }\r
588\r
589 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
590 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
591 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
592 }\r
593 } else {\r
1b96428d
ZL
594 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
595 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b 596 }\r
f75a7f56 597\r
b659408b
ZL
598 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
599 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
600 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
601 }\r
602 }\r
47f51a06
YT
603}\r
604\r
605/**\r
ba3b642d 606 Initialize the HTTP_PROTOCOL structure to the unconfigured state.\r
47f51a06 607\r
47f51a06 608 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
b659408b 609 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
47f51a06 610\r
f75a7f56 611 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.\r
47f51a06
YT
612 @retval Others Other error as indicated.\r
613\r
614**/\r
615EFI_STATUS\r
616HttpInitProtocol (\r
d1050b9d
MK
617 IN OUT HTTP_PROTOCOL *HttpInstance,\r
618 IN BOOLEAN IpVersion\r
47f51a06
YT
619 )\r
620{\r
d1050b9d
MK
621 EFI_STATUS Status;\r
622 VOID *Interface;\r
623 BOOLEAN UsingIpv6;\r
f75a7f56 624\r
b659408b
ZL
625 ASSERT (HttpInstance != NULL);\r
626 UsingIpv6 = IpVersion;\r
f75a7f56 627\r
b659408b
ZL
628 if (!UsingIpv6) {\r
629 //\r
630 // Create TCP4 child.\r
631 //\r
632 Status = NetLibCreateServiceChild (\r
633 HttpInstance->Service->ControllerHandle,\r
7cf59c85 634 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
635 &gEfiTcp4ServiceBindingProtocolGuid,\r
636 &HttpInstance->Tcp4ChildHandle\r
637 );\r
47f51a06 638\r
b659408b
ZL
639 if (EFI_ERROR (Status)) {\r
640 goto ON_ERROR;\r
641 }\r
47f51a06 642\r
b659408b
ZL
643 Status = gBS->OpenProtocol (\r
644 HttpInstance->Tcp4ChildHandle,\r
645 &gEfiTcp4ProtocolGuid,\r
d1050b9d 646 (VOID **)&Interface,\r
7cf59c85 647 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
648 HttpInstance->Service->ControllerHandle,\r
649 EFI_OPEN_PROTOCOL_BY_DRIVER\r
650 );\r
f75a7f56 651\r
b659408b
ZL
652 if (EFI_ERROR (Status)) {\r
653 goto ON_ERROR;\r
654 }\r
47f51a06 655\r
b659408b
ZL
656 Status = gBS->OpenProtocol (\r
657 HttpInstance->Tcp4ChildHandle,\r
658 &gEfiTcp4ProtocolGuid,\r
d1050b9d 659 (VOID **)&HttpInstance->Tcp4,\r
7cf59c85 660 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
661 HttpInstance->Handle,\r
662 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
663 );\r
d1050b9d 664 if (EFI_ERROR (Status)) {\r
b659408b
ZL
665 goto ON_ERROR;\r
666 }\r
47f51a06 667\r
b659408b
ZL
668 Status = gBS->OpenProtocol (\r
669 HttpInstance->Service->Tcp4ChildHandle,\r
670 &gEfiTcp4ProtocolGuid,\r
d1050b9d 671 (VOID **)&Interface,\r
7cf59c85 672 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
673 HttpInstance->Handle,\r
674 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
675 );\r
d1050b9d 676 if (EFI_ERROR (Status)) {\r
b659408b
ZL
677 goto ON_ERROR;\r
678 }\r
679 } else {\r
680 //\r
681 // Create TCP6 Child.\r
682 //\r
683 Status = NetLibCreateServiceChild (\r
684 HttpInstance->Service->ControllerHandle,\r
7cf59c85 685 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
686 &gEfiTcp6ServiceBindingProtocolGuid,\r
687 &HttpInstance->Tcp6ChildHandle\r
688 );\r
47f51a06 689\r
b659408b
ZL
690 if (EFI_ERROR (Status)) {\r
691 goto ON_ERROR;\r
692 }\r
47f51a06 693\r
b659408b
ZL
694 Status = gBS->OpenProtocol (\r
695 HttpInstance->Tcp6ChildHandle,\r
696 &gEfiTcp6ProtocolGuid,\r
d1050b9d 697 (VOID **)&Interface,\r
7cf59c85 698 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
699 HttpInstance->Service->ControllerHandle,\r
700 EFI_OPEN_PROTOCOL_BY_DRIVER\r
701 );\r
f75a7f56 702\r
b659408b
ZL
703 if (EFI_ERROR (Status)) {\r
704 goto ON_ERROR;\r
705 }\r
706\r
707 Status = gBS->OpenProtocol (\r
708 HttpInstance->Tcp6ChildHandle,\r
709 &gEfiTcp6ProtocolGuid,\r
d1050b9d 710 (VOID **)&HttpInstance->Tcp6,\r
7cf59c85 711 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
712 HttpInstance->Handle,\r
713 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
714 );\r
f75a7f56 715\r
d1050b9d 716 if (EFI_ERROR (Status)) {\r
b659408b 717 goto ON_ERROR;\r
f75a7f56 718 }\r
b659408b
ZL
719\r
720 Status = gBS->OpenProtocol (\r
721 HttpInstance->Service->Tcp6ChildHandle,\r
722 &gEfiTcp6ProtocolGuid,\r
d1050b9d 723 (VOID **)&Interface,\r
7cf59c85 724 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
725 HttpInstance->Handle,\r
726 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
727 );\r
47f51a06 728\r
d1050b9d 729 if (EFI_ERROR (Status)) {\r
b659408b
ZL
730 goto ON_ERROR;\r
731 }\r
732 }\r
f75a7f56 733\r
51b0450e
FS
734 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
735 if (HttpInstance->Url == NULL) {\r
736 Status = EFI_OUT_OF_RESOURCES;\r
737 goto ON_ERROR;\r
738 }\r
739\r
47f51a06
YT
740 return EFI_SUCCESS;\r
741\r
742ON_ERROR:\r
f75a7f56 743\r
b659408b 744 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 745 gBS->CloseProtocol (\r
b659408b 746 HttpInstance->Tcp4ChildHandle,\r
47f51a06 747 &gEfiTcp4ProtocolGuid,\r
7cf59c85 748 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
749 HttpInstance->Service->ControllerHandle\r
750 );\r
751\r
752 gBS->CloseProtocol (\r
b659408b 753 HttpInstance->Tcp4ChildHandle,\r
47f51a06 754 &gEfiTcp4ProtocolGuid,\r
7cf59c85 755 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 756 HttpInstance->Handle\r
f75a7f56
LG
757 );\r
758\r
47f51a06
YT
759 NetLibDestroyServiceChild (\r
760 HttpInstance->Service->ControllerHandle,\r
7cf59c85 761 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 762 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 763 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
764 );\r
765 }\r
f75a7f56 766\r
b659408b
ZL
767 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
768 gBS->CloseProtocol (\r
769 HttpInstance->Service->Tcp4ChildHandle,\r
770 &gEfiTcp4ProtocolGuid,\r
7cf59c85 771 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
772 HttpInstance->Handle\r
773 );\r
774 }\r
f75a7f56 775\r
b659408b
ZL
776 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
777 gBS->CloseProtocol (\r
778 HttpInstance->Tcp6ChildHandle,\r
779 &gEfiTcp6ProtocolGuid,\r
7cf59c85 780 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
781 HttpInstance->Service->ControllerHandle\r
782 );\r
47f51a06 783\r
b659408b
ZL
784 gBS->CloseProtocol (\r
785 HttpInstance->Tcp6ChildHandle,\r
786 &gEfiTcp6ProtocolGuid,\r
7cf59c85 787 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
788 HttpInstance->Handle\r
789 );\r
f75a7f56 790\r
b659408b
ZL
791 NetLibDestroyServiceChild (\r
792 HttpInstance->Service->ControllerHandle,\r
7cf59c85 793 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
794 &gEfiTcp6ServiceBindingProtocolGuid,\r
795 HttpInstance->Tcp6ChildHandle\r
796 );\r
797 }\r
f75a7f56 798\r
b659408b
ZL
799 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
800 gBS->CloseProtocol (\r
801 HttpInstance->Service->Tcp6ChildHandle,\r
802 &gEfiTcp6ProtocolGuid,\r
7cf59c85 803 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
804 HttpInstance->Handle\r
805 );\r
806 }\r
807\r
808 return EFI_UNSUPPORTED;\r
47f51a06
YT
809}\r
810\r
811/**\r
812 Clean up the HTTP child, release all the resources used by it.\r
813\r
814 @param[in] HttpInstance The HTTP child to clean up.\r
815\r
816**/\r
817VOID\r
818HttpCleanProtocol (\r
d1050b9d 819 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
820 )\r
821{\r
822 HttpCloseConnection (HttpInstance);\r
f75a7f56 823\r
b659408b 824 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06 825\r
b347a22a
JW
826 if (HttpInstance->TimeoutEvent != NULL) {\r
827 gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
828 HttpInstance->TimeoutEvent = NULL;\r
829 }\r
830\r
47f51a06
YT
831 if (HttpInstance->CacheBody != NULL) {\r
832 FreePool (HttpInstance->CacheBody);\r
833 HttpInstance->CacheBody = NULL;\r
834 HttpInstance->NextMsg = NULL;\r
835 }\r
836\r
837 if (HttpInstance->RemoteHost != NULL) {\r
838 FreePool (HttpInstance->RemoteHost);\r
839 HttpInstance->RemoteHost = NULL;\r
840 }\r
841\r
842 if (HttpInstance->MsgParser != NULL) {\r
843 HttpFreeMsgParser (HttpInstance->MsgParser);\r
844 HttpInstance->MsgParser = NULL;\r
845 }\r
f75a7f56 846\r
51b0450e
FS
847 if (HttpInstance->Url != NULL) {\r
848 FreePool (HttpInstance->Url);\r
849 HttpInstance->Url = NULL;\r
850 }\r
f75a7f56 851\r
47f51a06
YT
852 NetMapClean (&HttpInstance->TxTokens);\r
853 NetMapClean (&HttpInstance->RxTokens);\r
854\r
d1050b9d 855 if ((HttpInstance->TlsSb != NULL) && (HttpInstance->TlsChildHandle != NULL)) {\r
45ea8a0c 856 //\r
f75a7f56 857 // Destroy the TLS instance.\r
328141fc 858 //\r
45ea8a0c 859 HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);\r
5df41311 860 HttpInstance->TlsChildHandle = NULL;\r
45ea8a0c
JW
861 }\r
862\r
b659408b 863 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 864 gBS->CloseProtocol (\r
b659408b 865 HttpInstance->Tcp4ChildHandle,\r
47f51a06 866 &gEfiTcp4ProtocolGuid,\r
7cf59c85 867 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
868 HttpInstance->Service->ControllerHandle\r
869 );\r
870\r
871 gBS->CloseProtocol (\r
b659408b 872 HttpInstance->Tcp4ChildHandle,\r
47f51a06 873 &gEfiTcp4ProtocolGuid,\r
7cf59c85 874 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
875 HttpInstance->Handle\r
876 );\r
f75a7f56 877\r
47f51a06
YT
878 NetLibDestroyServiceChild (\r
879 HttpInstance->Service->ControllerHandle,\r
7cf59c85 880 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 881 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 882 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
883 );\r
884 }\r
b659408b
ZL
885\r
886 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
887 gBS->CloseProtocol (\r
888 HttpInstance->Service->Tcp4ChildHandle,\r
889 &gEfiTcp4ProtocolGuid,\r
7cf59c85 890 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
891 HttpInstance->Handle\r
892 );\r
f75a7f56 893 }\r
b659408b
ZL
894\r
895 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
896 gBS->CloseProtocol (\r
897 HttpInstance->Tcp6ChildHandle,\r
898 &gEfiTcp6ProtocolGuid,\r
7cf59c85 899 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
900 HttpInstance->Service->ControllerHandle\r
901 );\r
902\r
903 gBS->CloseProtocol (\r
904 HttpInstance->Tcp6ChildHandle,\r
905 &gEfiTcp6ProtocolGuid,\r
7cf59c85 906 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
907 HttpInstance->Handle\r
908 );\r
f75a7f56 909\r
b659408b
ZL
910 NetLibDestroyServiceChild (\r
911 HttpInstance->Service->ControllerHandle,\r
7cf59c85 912 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
913 &gEfiTcp6ServiceBindingProtocolGuid,\r
914 HttpInstance->Tcp6ChildHandle\r
915 );\r
916 }\r
f75a7f56 917\r
b659408b
ZL
918 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
919 gBS->CloseProtocol (\r
920 HttpInstance->Service->Tcp6ChildHandle,\r
921 &gEfiTcp6ProtocolGuid,\r
7cf59c85 922 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
923 HttpInstance->Handle\r
924 );\r
925 }\r
dac45de3 926\r
f75a7f56 927 TlsCloseTxRxEvent (HttpInstance);\r
47f51a06
YT
928}\r
929\r
930/**\r
931 Establish TCP connection with HTTP server.\r
932\r
933 @param[in] HttpInstance The HTTP instance private data.\r
934\r
935 @retval EFI_SUCCESS The TCP connection is established.\r
936 @retval Others Other error as indicated.\r
937\r
938**/\r
939EFI_STATUS\r
940HttpCreateConnection (\r
d1050b9d 941 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
942 )\r
943{\r
d1050b9d 944 EFI_STATUS Status;\r
47f51a06 945\r
47f51a06
YT
946 //\r
947 // Connect to Http server\r
948 //\r
b659408b 949 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d 950 HttpInstance->IsTcp4ConnDone = FALSE;\r
b659408b 951 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
d1050b9d 952 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
ab796d3e 953 HttpNotify (HttpEventConnectTcp, Status);\r
b659408b 954 if (EFI_ERROR (Status)) {\r
c49ca4a2 955 DEBUG ((DEBUG_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
b659408b
ZL
956 return Status;\r
957 }\r
f75a7f56 958\r
b659408b
ZL
959 while (!HttpInstance->IsTcp4ConnDone) {\r
960 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
961 }\r
f75a7f56 962\r
b659408b 963 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
b659408b 964 } else {\r
d1050b9d 965 HttpInstance->IsTcp6ConnDone = FALSE;\r
b659408b 966 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
d1050b9d 967 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
ab796d3e 968 HttpNotify (HttpEventConnectTcp, Status);\r
b659408b 969 if (EFI_ERROR (Status)) {\r
c49ca4a2 970 DEBUG ((DEBUG_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
b659408b
ZL
971 return Status;\r
972 }\r
47f51a06 973\r
d1050b9d 974 while (!HttpInstance->IsTcp6ConnDone) {\r
b659408b
ZL
975 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
976 }\r
47f51a06 977\r
f75a7f56 978 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;\r
b659408b 979 }\r
f75a7f56 980\r
47f51a06
YT
981 if (!EFI_ERROR (Status)) {\r
982 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
983 }\r
984\r
985 return Status;\r
986}\r
987\r
988/**\r
989 Close existing TCP connection.\r
990\r
991 @param[in] HttpInstance The HTTP instance private data.\r
992\r
993 @retval EFI_SUCCESS The TCP connection is closed.\r
994 @retval Others Other error as indicated.\r
995\r
996**/\r
997EFI_STATUS\r
998HttpCloseConnection (\r
d1050b9d 999 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
1000 )\r
1001{\r
d1050b9d 1002 EFI_STATUS Status;\r
47f51a06 1003\r
374ecd04 1004 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
b659408b
ZL
1005 if (HttpInstance->LocalAddressIsIPv6) {\r
1006 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
1007 HttpInstance->IsTcp6CloseDone = FALSE;\r
d1050b9d 1008 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
b659408b
ZL
1009 if (EFI_ERROR (Status)) {\r
1010 return Status;\r
1011 }\r
1012\r
1013 while (!HttpInstance->IsTcp6CloseDone) {\r
1014 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
1015 }\r
b659408b
ZL
1016 } else {\r
1017 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
1018 HttpInstance->IsTcp4CloseDone = FALSE;\r
d1050b9d 1019 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
b659408b
ZL
1020 if (EFI_ERROR (Status)) {\r
1021 return Status;\r
1022 }\r
1023\r
1024 while (!HttpInstance->IsTcp4CloseDone) {\r
1025 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1026 }\r
374ecd04 1027 }\r
47f51a06
YT
1028 }\r
1029\r
1030 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1031 return EFI_SUCCESS;\r
47f51a06
YT
1032}\r
1033\r
1034/**\r
1035 Configure TCP4 protocol child.\r
1036\r
1037 @param[in] HttpInstance The HTTP instance private data.\r
1038 @param[in] Wrap The HTTP token's wrap data.\r
1039\r
1040 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1041 @retval Others Other error as indicated.\r
1042\r
1043**/\r
1044EFI_STATUS\r
1045HttpConfigureTcp4 (\r
d1050b9d
MK
1046 IN HTTP_PROTOCOL *HttpInstance,\r
1047 IN HTTP_TOKEN_WRAP *Wrap\r
47f51a06
YT
1048 )\r
1049{\r
d1050b9d
MK
1050 EFI_STATUS Status;\r
1051 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1052 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1053 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1054\r
1055 ASSERT (HttpInstance != NULL);\r
47f51a06 1056\r
47f51a06
YT
1057 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1058 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
f75a7f56 1059\r
47f51a06
YT
1060 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1061 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1062 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1063\r
d1050b9d 1064 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
47f51a06
YT
1065 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1066 if (!Tcp4AP->UseDefaultAddress) {\r
1067 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1068 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1069 }\r
f75a7f56 1070\r
47f51a06
YT
1071 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1072 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1073 Tcp4AP->ActiveFlag = TRUE;\r
1074 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1075\r
d1050b9d
MK
1076 Tcp4Option = Tcp4CfgData->ControlOption;\r
1077 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1078 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1079 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1080 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1081 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1082 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1083 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1084 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1085 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1086 Tcp4Option->EnableNagle = TRUE;\r
1087 Tcp4CfgData->ControlOption = Tcp4Option;\r
47f51a06 1088\r
38a9afd0
OS
1089 if ((HttpInstance->State == HTTP_STATE_TCP_CONNECTED) ||\r
1090 (HttpInstance->State == HTTP_STATE_TCP_CLOSED))\r
1091 {\r
1092 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, NULL);\r
1093 if (EFI_ERROR (Status)) {\r
1094 DEBUG ((DEBUG_ERROR, "HttpConfigureTcp4(NULL) - %r\n", Status));\r
1095 return Status;\r
1096 }\r
1097\r
1098 HttpInstance->State = HTTP_STATE_TCP_UNCONFIGED;\r
1099 }\r
1100\r
47f51a06
YT
1101 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1102 if (EFI_ERROR (Status)) {\r
c49ca4a2 1103 DEBUG ((DEBUG_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
47f51a06
YT
1104 return Status;\r
1105 }\r
1106\r
b659408b
ZL
1107 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1108 if (EFI_ERROR (Status)) {\r
1109 return Status;\r
1110 }\r
1111\r
1112 Status = HttpCreateTcpTxEvent (Wrap);\r
1113 if (EFI_ERROR (Status)) {\r
1114 return Status;\r
1115 }\r
1116\r
1117 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1118\r
1119 return EFI_SUCCESS;\r
1120}\r
1121\r
1122/**\r
1123 Configure TCP6 protocol child.\r
1124\r
1125 @param[in] HttpInstance The HTTP instance private data.\r
1126 @param[in] Wrap The HTTP token's wrap data.\r
1127\r
1128 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1129 @retval Others Other error as indicated.\r
1130\r
1131**/\r
1132EFI_STATUS\r
1133HttpConfigureTcp6 (\r
d1050b9d
MK
1134 IN HTTP_PROTOCOL *HttpInstance,\r
1135 IN HTTP_TOKEN_WRAP *Wrap\r
b659408b
ZL
1136 )\r
1137{\r
d1050b9d
MK
1138 EFI_STATUS Status;\r
1139 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1140 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1141 EFI_TCP6_OPTION *Tcp6Option;\r
f75a7f56 1142\r
b659408b 1143 ASSERT (HttpInstance != NULL);\r
f75a7f56 1144\r
b659408b
ZL
1145 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1146 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1147\r
1148 Tcp6CfgData->TrafficClass = 0;\r
1149 Tcp6CfgData->HopLimit = 255;\r
1150 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
f75a7f56 1151\r
d1050b9d 1152 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
b659408b
ZL
1153 Tcp6Ap->ActiveFlag = TRUE;\r
1154 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1155 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1156 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
d1050b9d
MK
1157 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress, &HttpInstance->RemoteIpv6Addr);\r
1158\r
1159 Tcp6Option = Tcp6CfgData->ControlOption;\r
1160 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1161 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1162 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1163 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1164 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1165 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1166 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1167 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1168 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1169 Tcp6Option->EnableNagle = TRUE;\r
b659408b 1170\r
3974aa53
OS
1171 if ((HttpInstance->State == HTTP_STATE_TCP_CONNECTED) ||\r
1172 (HttpInstance->State == HTTP_STATE_TCP_CLOSED))\r
1173 {\r
1174 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, NULL);\r
1175 if (EFI_ERROR (Status)) {\r
1176 DEBUG ((DEBUG_ERROR, "HttpConfigureTcp6(NULL) - %r\n", Status));\r
1177 return Status;\r
1178 }\r
1179\r
1180 HttpInstance->State = HTTP_STATE_TCP_UNCONFIGED;\r
1181 }\r
1182\r
b659408b
ZL
1183 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1184 if (EFI_ERROR (Status)) {\r
c49ca4a2 1185 DEBUG ((DEBUG_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
b659408b
ZL
1186 return Status;\r
1187 }\r
f75a7f56 1188\r
b659408b 1189 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1190 if (EFI_ERROR (Status)) {\r
1191 return Status;\r
1192 }\r
1193\r
b659408b 1194 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1195 if (EFI_ERROR (Status)) {\r
1196 return Status;\r
1197 }\r
1198\r
1199 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1200\r
1201 return EFI_SUCCESS;\r
1202}\r
1203\r
1204/**\r
f75a7f56 1205 Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
dac45de3 1206 connect one TLS session if required.\r
47f51a06
YT
1207\r
1208 @param[in] HttpInstance The HTTP instance private data.\r
1209\r
1210 @retval EFI_SUCCESS The TCP connection is established.\r
1211 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1212 @retval Others Other error as indicated.\r
1213\r
1214**/\r
1215EFI_STATUS\r
1216HttpConnectTcp4 (\r
d1050b9d 1217 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
1218 )\r
1219{\r
d1050b9d
MK
1220 EFI_STATUS Status;\r
1221 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
47f51a06 1222\r
d1050b9d 1223 if ((HttpInstance->State < HTTP_STATE_TCP_CONFIGED) || (HttpInstance->Tcp4 == NULL)) {\r
47f51a06
YT
1224 return EFI_NOT_READY;\r
1225 }\r
1226\r
d1050b9d 1227 Status = HttpInstance->Tcp4->GetModeData (\r
f75a7f56
LG
1228 HttpInstance->Tcp4,\r
1229 &Tcp4State,\r
47f51a06
YT
1230 NULL,\r
1231 NULL,\r
1232 NULL,\r
1233 NULL\r
1234 );\r
d1050b9d 1235 if (EFI_ERROR (Status)) {\r
c49ca4a2 1236 DEBUG ((DEBUG_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
47f51a06
YT
1237 return Status;\r
1238 }\r
1239\r
a2e61982
ZL
1240 if (Tcp4State == Tcp4StateEstablished) {\r
1241 return EFI_SUCCESS;\r
1242 } else if (Tcp4State > Tcp4StateEstablished ) {\r
d1050b9d 1243 HttpCloseConnection (HttpInstance);\r
a2e61982 1244 }\r
47f51a06 1245\r
dac45de3 1246 Status = HttpCreateConnection (HttpInstance);\r
d1050b9d 1247 if (EFI_ERROR (Status)) {\r
c49ca4a2 1248 DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status));\r
dac45de3
JW
1249 return Status;\r
1250 }\r
f75a7f56 1251\r
dac45de3
JW
1252 //\r
1253 // Tls session connection.\r
1254 //\r
1255 if (HttpInstance->UseHttps) {\r
1256 if (HttpInstance->TimeoutEvent == NULL) {\r
1257 //\r
1258 // Create TimeoutEvent for TLS connection.\r
1259 //\r
1260 Status = gBS->CreateEvent (\r
1261 EVT_TIMER,\r
1262 TPL_CALLBACK,\r
1263 NULL,\r
1264 NULL,\r
1265 &HttpInstance->TimeoutEvent\r
1266 );\r
1267 if (EFI_ERROR (Status)) {\r
1268 TlsCloseTxRxEvent (HttpInstance);\r
1269 return Status;\r
1270 }\r
1271 }\r
1272\r
1273 //\r
1274 // Start the timer, and wait Timeout seconds for connection.\r
1275 //\r
1276 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1277 if (EFI_ERROR (Status)) {\r
1278 TlsCloseTxRxEvent (HttpInstance);\r
1279 return Status;\r
1280 }\r
f75a7f56 1281\r
dac45de3 1282 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1283 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1284\r
1285 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1286\r
dac45de3
JW
1287 if (EFI_ERROR (Status)) {\r
1288 TlsCloseTxRxEvent (HttpInstance);\r
1289 return Status;\r
1290 }\r
1291 }\r
1292\r
1293 return Status;\r
47f51a06
YT
1294}\r
1295\r
1296/**\r
f75a7f56 1297 Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
dac45de3 1298 connect one TLS session if required.\r
b659408b
ZL
1299\r
1300 @param[in] HttpInstance The HTTP instance private data.\r
1301\r
1302 @retval EFI_SUCCESS The TCP connection is established.\r
1303 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1304 @retval Others Other error as indicated.\r
1305\r
1306**/\r
1307EFI_STATUS\r
1308HttpConnectTcp6 (\r
d1050b9d 1309 IN HTTP_PROTOCOL *HttpInstance\r
b659408b
ZL
1310 )\r
1311{\r
d1050b9d
MK
1312 EFI_STATUS Status;\r
1313 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
b659408b 1314\r
d1050b9d 1315 if ((HttpInstance->State < HTTP_STATE_TCP_CONFIGED) || (HttpInstance->Tcp6 == NULL)) {\r
b659408b
ZL
1316 return EFI_NOT_READY;\r
1317 }\r
1318\r
1319 Status = HttpInstance->Tcp6->GetModeData (\r
1320 HttpInstance->Tcp6,\r
1321 &Tcp6State,\r
1322 NULL,\r
1323 NULL,\r
1324 NULL,\r
1325 NULL\r
1326 );\r
f75a7f56 1327\r
d1050b9d
MK
1328 if (EFI_ERROR (Status)) {\r
1329 DEBUG ((DEBUG_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1330 return Status;\r
b659408b
ZL
1331 }\r
1332\r
a2e61982
ZL
1333 if (Tcp6State == Tcp6StateEstablished) {\r
1334 return EFI_SUCCESS;\r
1335 } else if (Tcp6State > Tcp6StateEstablished ) {\r
d1050b9d 1336 HttpCloseConnection (HttpInstance);\r
b659408b
ZL
1337 }\r
1338\r
dac45de3 1339 Status = HttpCreateConnection (HttpInstance);\r
d1050b9d 1340 if (EFI_ERROR (Status)) {\r
c49ca4a2 1341 DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status));\r
dac45de3
JW
1342 return Status;\r
1343 }\r
f75a7f56 1344\r
dac45de3
JW
1345 //\r
1346 // Tls session connection.\r
1347 //\r
1348 if (HttpInstance->UseHttps) {\r
1349 if (HttpInstance->TimeoutEvent == NULL) {\r
1350 //\r
1351 // Create TimeoutEvent for TLS connection.\r
1352 //\r
1353 Status = gBS->CreateEvent (\r
1354 EVT_TIMER,\r
1355 TPL_CALLBACK,\r
1356 NULL,\r
1357 NULL,\r
1358 &HttpInstance->TimeoutEvent\r
1359 );\r
1360 if (EFI_ERROR (Status)) {\r
1361 TlsCloseTxRxEvent (HttpInstance);\r
1362 return Status;\r
1363 }\r
1364 }\r
1365\r
1366 //\r
1367 // Start the timer, and wait Timeout seconds for connection.\r
1368 //\r
1369 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1370 if (EFI_ERROR (Status)) {\r
1371 TlsCloseTxRxEvent (HttpInstance);\r
1372 return Status;\r
1373 }\r
f75a7f56 1374\r
dac45de3 1375 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1376 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1377\r
1378 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1379\r
dac45de3
JW
1380 if (EFI_ERROR (Status)) {\r
1381 TlsCloseTxRxEvent (HttpInstance);\r
1382 return Status;\r
1383 }\r
1384 }\r
1385\r
1386 return Status;\r
b659408b
ZL
1387}\r
1388\r
1389/**\r
dac45de3 1390 Initialize Http session.\r
b659408b
ZL
1391\r
1392 @param[in] HttpInstance The HTTP instance private data.\r
1393 @param[in] Wrap The HTTP token's wrap data.\r
dac45de3
JW
1394 @param[in] Configure The Flag indicates whether need to initialize session.\r
1395 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.\r
b659408b 1396\r
f75a7f56 1397 @retval EFI_SUCCESS The initialization of session is done.\r
b659408b
ZL
1398 @retval Others Other error as indicated.\r
1399\r
1400**/\r
1401EFI_STATUS\r
dac45de3 1402HttpInitSession (\r
b659408b 1403 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982 1404 IN HTTP_TOKEN_WRAP *Wrap,\r
dac45de3
JW
1405 IN BOOLEAN Configure,\r
1406 IN BOOLEAN TlsConfigure\r
b659408b
ZL
1407 )\r
1408{\r
d1050b9d
MK
1409 EFI_STATUS Status;\r
1410\r
b659408b
ZL
1411 ASSERT (HttpInstance != NULL);\r
1412\r
dac45de3
JW
1413 //\r
1414 // Configure Tls session.\r
1415 //\r
1416 if (TlsConfigure) {\r
1417 Status = TlsConfigureSession (HttpInstance);\r
1418 if (EFI_ERROR (Status)) {\r
1419 return Status;\r
1420 }\r
1421 }\r
1422\r
b659408b
ZL
1423 if (!HttpInstance->LocalAddressIsIPv6) {\r
1424 //\r
1425 // Configure TCP instance.\r
1426 //\r
a2e61982
ZL
1427 if (Configure) {\r
1428 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1429 if (EFI_ERROR (Status)) {\r
1430 return Status;\r
1431 }\r
b659408b 1432 }\r
a2e61982 1433\r
b659408b
ZL
1434 //\r
1435 // Connect TCP.\r
1436 //\r
1437 Status = HttpConnectTcp4 (HttpInstance);\r
1438 if (EFI_ERROR (Status)) {\r
1439 return Status;\r
1440 }\r
1441 } else {\r
1442 //\r
1443 // Configure TCP instance.\r
1444 //\r
a2e61982
ZL
1445 if (Configure) {\r
1446 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1447 if (EFI_ERROR (Status)) {\r
1448 return Status;\r
1449 }\r
b659408b 1450 }\r
a2e61982 1451\r
b659408b
ZL
1452 //\r
1453 // Connect TCP.\r
1454 //\r
1455 Status = HttpConnectTcp6 (HttpInstance);\r
1456 if (EFI_ERROR (Status)) {\r
1457 return Status;\r
1458 }\r
1459 }\r
f75a7f56 1460\r
b659408b 1461 return EFI_SUCCESS;\r
b659408b
ZL
1462}\r
1463\r
1464/**\r
dac45de3 1465 Send the HTTP or HTTPS message through TCP4 or TCP6.\r
47f51a06
YT
1466\r
1467 @param[in] HttpInstance The HTTP instance private data.\r
1468 @param[in] Wrap The HTTP token's wrap data.\r
1469 @param[in] TxString Buffer containing the HTTP message string.\r
1470 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1471\r
1472 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1473 @retval Others Other error as indicated.\r
1474\r
1475**/\r
1476EFI_STATUS\r
b659408b 1477HttpTransmitTcp (\r
47f51a06
YT
1478 IN HTTP_PROTOCOL *HttpInstance,\r
1479 IN HTTP_TOKEN_WRAP *Wrap,\r
1480 IN UINT8 *TxString,\r
1481 IN UINTN TxStringLen\r
1482 )\r
1483{\r
d1050b9d
MK
1484 EFI_STATUS Status;\r
1485 EFI_TCP4_IO_TOKEN *Tx4Token;\r
1486 EFI_TCP4_PROTOCOL *Tcp4;\r
1487 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1488 EFI_TCP6_PROTOCOL *Tcp6;\r
1489 UINT8 *TlsRecord;\r
1490 UINT16 PayloadSize;\r
1491 NET_FRAGMENT TempFragment;\r
1492 NET_FRAGMENT Fragment;\r
1493 UINTN RecordCount;\r
1494 UINTN RemainingLen;\r
1495\r
1496 Status = EFI_SUCCESS;\r
1497 TlsRecord = NULL;\r
1498 PayloadSize = 0;\r
1499 TempFragment.Len = 0;\r
1500 TempFragment.Bulk = NULL;\r
1501 Fragment.Len = 0;\r
1502 Fragment.Bulk = NULL;\r
1503 RecordCount = 0;\r
1504 RemainingLen = 0;\r
dac45de3
JW
1505\r
1506 //\r
1507 // Need to encrypt data.\r
1508 //\r
1509 if (HttpInstance->UseHttps) {\r
1510 //\r
07bd82d4 1511 // Allocate enough buffer for each TLS plaintext records.\r
dac45de3 1512 //\r
07bd82d4
JW
1513 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1514 if (TlsRecord == NULL) {\r
dac45de3
JW
1515 Status = EFI_OUT_OF_RESOURCES;\r
1516 return Status;\r
1517 }\r
07bd82d4 1518\r
dac45de3 1519 //\r
07bd82d4 1520 // Allocate enough buffer for all TLS ciphertext records.\r
dac45de3 1521 //\r
d1050b9d 1522 RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
07bd82d4
JW
1523 Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
1524 if (Fragment.Bulk == NULL) {\r
1525 Status = EFI_OUT_OF_RESOURCES;\r
1526 goto ON_ERROR;\r
1527 }\r
dac45de3 1528\r
07bd82d4
JW
1529 //\r
1530 // Encrypt each TLS plaintext records.\r
1531 //\r
1532 RemainingLen = TxStringLen;\r
1533 while (RemainingLen != 0) {\r
d1050b9d 1534 PayloadSize = (UINT16)MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
f75a7f56 1535\r
d1050b9d
MK
1536 ((TLS_RECORD_HEADER *)TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
1537 ((TLS_RECORD_HEADER *)TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
1538 ((TLS_RECORD_HEADER *)TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
1539 ((TLS_RECORD_HEADER *)TlsRecord)->Length = PayloadSize;\r
07bd82d4
JW
1540\r
1541 CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
f75a7f56 1542\r
07bd82d4 1543 Status = TlsProcessMessage (\r
f75a7f56
LG
1544 HttpInstance,\r
1545 TlsRecord,\r
1546 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1547 EfiTlsEncrypt,\r
07bd82d4
JW
1548 &TempFragment\r
1549 );\r
1550 if (EFI_ERROR (Status)) {\r
1551 goto ON_ERROR;\r
1552 }\r
1553\r
1554 //\r
f75a7f56 1555 // Record the processed/encrypted Packet.\r
07bd82d4
JW
1556 //\r
1557 CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
1558 Fragment.Len += TempFragment.Len;\r
1559\r
1560 FreePool (TempFragment.Bulk);\r
1561 TempFragment.Len = 0;\r
1562 TempFragment.Bulk = NULL;\r
f75a7f56 1563\r
d1050b9d 1564 RemainingLen -= (UINTN)PayloadSize;\r
07bd82d4 1565 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
dac45de3 1566 }\r
07bd82d4
JW
1567\r
1568 FreePool (TlsRecord);\r
1569 TlsRecord = NULL;\r
dac45de3 1570 }\r
f75a7f56 1571\r
dac45de3 1572 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d 1573 Tcp4 = HttpInstance->Tcp4;\r
b659408b 1574 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
dac45de3
JW
1575\r
1576 if (HttpInstance->UseHttps) {\r
d1050b9d 1577 Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
07bd82d4 1578 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
d1050b9d 1579 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)Fragment.Bulk;\r
dac45de3 1580 } else {\r
d1050b9d
MK
1581 Tx4Token->Packet.TxData->DataLength = (UINT32)TxStringLen;\r
1582 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)TxStringLen;\r
1583 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)TxString;\r
dac45de3 1584 }\r
f75a7f56
LG
1585\r
1586 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1587\r
b659408b 1588 Wrap->TcpWrap.IsTxDone = FALSE;\r
d1050b9d 1589 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
b659408b 1590 if (EFI_ERROR (Status)) {\r
c49ca4a2 1591 DEBUG ((DEBUG_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1592 goto ON_ERROR;\r
b659408b 1593 }\r
b659408b 1594 } else {\r
d1050b9d 1595 Tcp6 = HttpInstance->Tcp6;\r
b659408b 1596 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
f75a7f56 1597\r
dac45de3 1598 if (HttpInstance->UseHttps) {\r
d1050b9d 1599 Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
07bd82d4 1600 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
d1050b9d 1601 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)Fragment.Bulk;\r
dac45de3 1602 } else {\r
d1050b9d
MK
1603 Tx6Token->Packet.TxData->DataLength = (UINT32)TxStringLen;\r
1604 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)TxStringLen;\r
1605 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)TxString;\r
dac45de3 1606 }\r
f75a7f56 1607\r
b659408b
ZL
1608 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1609\r
1610 Wrap->TcpWrap.IsTxDone = FALSE;\r
d1050b9d 1611 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
b659408b 1612 if (EFI_ERROR (Status)) {\r
c49ca4a2 1613 DEBUG ((DEBUG_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1614 goto ON_ERROR;\r
b659408b 1615 }\r
47f51a06 1616 }\r
f75a7f56 1617\r
07bd82d4
JW
1618 return Status;\r
1619\r
1620ON_ERROR:\r
f75a7f56 1621\r
07bd82d4
JW
1622 if (HttpInstance->UseHttps) {\r
1623 if (TlsRecord != NULL) {\r
1624 FreePool (TlsRecord);\r
1625 TlsRecord = NULL;\r
1626 }\r
f75a7f56 1627\r
07bd82d4
JW
1628 if (Fragment.Bulk != NULL) {\r
1629 FreePool (Fragment.Bulk);\r
1630 Fragment.Bulk = NULL;\r
1631 }\r
1632 }\r
1633\r
47f51a06
YT
1634 return Status;\r
1635}\r
1636\r
47f51a06
YT
1637/**\r
1638 Check whether the user's token or event has already\r
b659408b 1639 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1640\r
1641 @param[in] Map The container of either user's transmit or receive\r
1642 token.\r
1643 @param[in] Item Current item to check against.\r
ba3b642d 1644 @param[in] Context The Token to check against.\r
47f51a06
YT
1645\r
1646 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1647 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1648 context.\r
1649\r
1650**/\r
1651EFI_STATUS\r
1652EFIAPI\r
1653HttpTokenExist (\r
d1050b9d
MK
1654 IN NET_MAP *Map,\r
1655 IN NET_MAP_ITEM *Item,\r
1656 IN VOID *Context\r
47f51a06
YT
1657 )\r
1658{\r
d1050b9d
MK
1659 EFI_HTTP_TOKEN *Token;\r
1660 EFI_HTTP_TOKEN *TokenInItem;\r
47f51a06 1661\r
d1050b9d
MK
1662 Token = (EFI_HTTP_TOKEN *)Context;\r
1663 TokenInItem = (EFI_HTTP_TOKEN *)Item->Key;\r
47f51a06 1664\r
d1050b9d 1665 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
47f51a06
YT
1666 return EFI_ACCESS_DENIED;\r
1667 }\r
1668\r
1669 return EFI_SUCCESS;\r
1670}\r
1671\r
1672/**\r
b659408b 1673 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1674\r
b659408b 1675 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06 1676 @param[in] Item Current item to check against.\r
ba3b642d 1677 @param[in] Context The Token to check against.\r
47f51a06
YT
1678\r
1679 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1680 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1681\r
1682**/\r
1683EFI_STATUS\r
1684EFIAPI\r
1685HttpTcpNotReady (\r
d1050b9d
MK
1686 IN NET_MAP *Map,\r
1687 IN NET_MAP_ITEM *Item,\r
1688 IN VOID *Context\r
47f51a06
YT
1689 )\r
1690{\r
d1050b9d 1691 HTTP_TOKEN_WRAP *ValueInItem;\r
47f51a06 1692\r
d1050b9d 1693 ValueInItem = (HTTP_TOKEN_WRAP *)Item->Value;\r
47f51a06
YT
1694\r
1695 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1696 return EFI_NOT_READY;\r
1697 }\r
f75a7f56 1698\r
47f51a06
YT
1699 return EFI_SUCCESS;\r
1700}\r
1701\r
1702/**\r
ba3b642d 1703 Transmit the HTTP or HTTPS message by processing the associated HTTP token.\r
47f51a06 1704\r
b659408b 1705 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06 1706 @param[in] Item Current item to check against.\r
ba3b642d 1707 @param[in] Context The Token to check against.\r
47f51a06
YT
1708\r
1709 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1710 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1711 queue.\r
1712\r
1713**/\r
1714EFI_STATUS\r
1715EFIAPI\r
1716HttpTcpTransmit (\r
d1050b9d
MK
1717 IN NET_MAP *Map,\r
1718 IN NET_MAP_ITEM *Item,\r
1719 IN VOID *Context\r
47f51a06
YT
1720 )\r
1721{\r
d1050b9d
MK
1722 HTTP_TOKEN_WRAP *ValueInItem;\r
1723 EFI_STATUS Status;\r
1724 CHAR8 *RequestMsg;\r
1725 CHAR8 *Url;\r
1726 UINTN UrlSize;\r
1727 UINTN RequestMsgSize;\r
47f51a06 1728\r
63f1d6a4
JW
1729 RequestMsg = NULL;\r
1730\r
d1050b9d 1731 ValueInItem = (HTTP_TOKEN_WRAP *)Item->Value;\r
47f51a06
YT
1732 if (ValueInItem->TcpWrap.IsTxDone) {\r
1733 return EFI_SUCCESS;\r
1734 }\r
1735\r
1736 //\r
1737 // Parse the URI of the remote host.\r
1738 //\r
b9679cd7 1739 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
d1050b9d 1740 Url = AllocatePool (UrlSize);\r
47f51a06
YT
1741 if (Url == NULL) {\r
1742 return EFI_OUT_OF_RESOURCES;\r
1743 }\r
1744\r
b9679cd7 1745 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
47f51a06
YT
1746\r
1747 //\r
1748 // Create request message.\r
1749 //\r
19c25725 1750 Status = HttpGenRequestMessage (\r
d1050b9d
MK
1751 ValueInItem->HttpToken->Message,\r
1752 Url,\r
1753 &RequestMsg,\r
1754 &RequestMsgSize\r
1755 );\r
47f51a06 1756 FreePool (Url);\r
f58554fc 1757\r
d1050b9d 1758 if (EFI_ERROR (Status) || (NULL == RequestMsg)) {\r
f58554fc 1759 return Status;\r
47f51a06
YT
1760 }\r
1761\r
63f1d6a4
JW
1762 ASSERT (RequestMsg != NULL);\r
1763\r
47f51a06
YT
1764 //\r
1765 // Transmit the request message.\r
1766 //\r
b659408b 1767 Status = HttpTransmitTcp (\r
47f51a06
YT
1768 ValueInItem->HttpInstance,\r
1769 ValueInItem,\r
d1050b9d 1770 (UINT8 *)RequestMsg,\r
19c25725 1771 RequestMsgSize\r
47f51a06 1772 );\r
19c25725 1773 FreePool (RequestMsg);\r
47f51a06
YT
1774 return Status;\r
1775}\r
1776\r
1777/**\r
1778 Receive the HTTP response by processing the associated HTTP token.\r
1779\r
b659408b 1780 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06 1781 @param[in] Item Current item to check against.\r
ba3b642d 1782 @param[in] Context The Token to check against.\r
47f51a06
YT
1783\r
1784 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1785 queue.\r
1786 @retval Others Other error as indicated.\r
1787\r
1788**/\r
1789EFI_STATUS\r
1790EFIAPI\r
1791HttpTcpReceive (\r
d1050b9d
MK
1792 IN NET_MAP *Map,\r
1793 IN NET_MAP_ITEM *Item,\r
1794 IN VOID *Context\r
47f51a06
YT
1795 )\r
1796{\r
1797 //\r
1798 // Process the queued HTTP response.\r
1799 //\r
d1050b9d 1800 return HttpResponseWorker ((HTTP_TOKEN_WRAP *)Item->Value);\r
47f51a06
YT
1801}\r
1802\r
b659408b
ZL
1803/**\r
1804 Receive the HTTP header by processing the associated HTTP token.\r
1805\r
1806 @param[in] HttpInstance The HTTP instance private data.\r
1807 @param[in, out] SizeofHeaders The HTTP header length.\r
ba3b642d 1808 @param[in, out] BufferSize The size of buffer to cache the header message.\r
b347a22a 1809 @param[in] Timeout The time to wait for receiving the header packet.\r
f75a7f56
LG
1810\r
1811 @retval EFI_SUCCESS The HTTP header is received.\r
b659408b
ZL
1812 @retval Others Other errors as indicated.\r
1813\r
1814**/\r
1815EFI_STATUS\r
1816HttpTcpReceiveHeader (\r
d1050b9d
MK
1817 IN HTTP_PROTOCOL *HttpInstance,\r
1818 IN OUT UINTN *SizeofHeaders,\r
1819 IN OUT UINTN *BufferSize,\r
1820 IN EFI_EVENT Timeout\r
b659408b
ZL
1821 )\r
1822{\r
d1050b9d
MK
1823 EFI_STATUS Status;\r
1824 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1825 EFI_TCP4_PROTOCOL *Tcp4;\r
1826 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1827 EFI_TCP6_PROTOCOL *Tcp6;\r
1828 CHAR8 **EndofHeader;\r
1829 CHAR8 **HttpHeaders;\r
1830 CHAR8 *Buffer;\r
1831 NET_FRAGMENT Fragment;\r
b659408b
ZL
1832\r
1833 ASSERT (HttpInstance != NULL);\r
1834\r
d1050b9d
MK
1835 EndofHeader = HttpInstance->EndofHeader;\r
1836 HttpHeaders = HttpInstance->HttpHeaders;\r
1837 Tcp4 = HttpInstance->Tcp4;\r
1838 Tcp6 = HttpInstance->Tcp6;\r
1839 Buffer = NULL;\r
1840 Rx4Token = NULL;\r
1841 Rx6Token = NULL;\r
dac45de3
JW
1842 Fragment.Len = 0;\r
1843 Fragment.Bulk = NULL;\r
f75a7f56 1844\r
b659408b
ZL
1845 if (HttpInstance->LocalAddressIsIPv6) {\r
1846 ASSERT (Tcp6 != NULL);\r
1847 } else {\r
1848 ASSERT (Tcp4 != NULL);\r
1849 }\r
1850\r
dac45de3
JW
1851 if (!HttpInstance->UseHttps) {\r
1852 Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
1853 if (EFI_ERROR (Status)) {\r
b659408b
ZL
1854 return Status;\r
1855 }\r
dac45de3
JW
1856 }\r
1857\r
1858 if (!HttpInstance->LocalAddressIsIPv6) {\r
1859 if (!HttpInstance->UseHttps) {\r
d1050b9d 1860 Rx4Token = &HttpInstance->Rx4Token;\r
dac45de3
JW
1861 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1862 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1863 Status = EFI_OUT_OF_RESOURCES;\r
1864 return Status;\r
1865 }\r
1866 }\r
f75a7f56 1867\r
b659408b
ZL
1868 //\r
1869 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1870 //\r
dac45de3
JW
1871 while (*EndofHeader == NULL) {\r
1872 if (!HttpInstance->UseHttps) {\r
d1050b9d
MK
1873 HttpInstance->IsRxDone = FALSE;\r
1874 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
dac45de3 1875 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
d1050b9d 1876 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
dac45de3 1877 if (EFI_ERROR (Status)) {\r
c49ca4a2 1878 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
dac45de3
JW
1879 return Status;\r
1880 }\r
1881\r
1882 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1883 Tcp4->Poll (Tcp4);\r
1884 }\r
1885\r
1886 if (!HttpInstance->IsRxDone) {\r
1887 //\r
ba3b642d 1888 // Cancel the Token before close its Event.\r
dac45de3
JW
1889 //\r
1890 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);\r
1891 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1892 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1893 }\r
1894\r
1895 Status = Rx4Token->CompletionToken.Status;\r
1896 if (EFI_ERROR (Status)) {\r
1897 return Status;\r
1898 }\r
f75a7f56 1899\r
dac45de3 1900 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
d1050b9d 1901 Fragment.Bulk = (UINT8 *)Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
dac45de3
JW
1902 } else {\r
1903 if (Fragment.Bulk != NULL) {\r
1904 FreePool (Fragment.Bulk);\r
1905 Fragment.Bulk = NULL;\r
1906 }\r
f75a7f56 1907\r
dac45de3
JW
1908 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1909 if (EFI_ERROR (Status)) {\r
c49ca4a2 1910 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
dac45de3
JW
1911 return Status;\r
1912 }\r
b347a22a
JW
1913 }\r
1914\r
b659408b 1915 //\r
2239ea71 1916 // Append the response string along with a Null-terminator.\r
b659408b 1917 //\r
dac45de3 1918 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2239ea71 1919 Buffer = AllocatePool (*BufferSize + 1);\r
b659408b
ZL
1920 if (Buffer == NULL) {\r
1921 Status = EFI_OUT_OF_RESOURCES;\r
1922 return Status;\r
1923 }\r
dac45de3 1924\r
b659408b 1925 if (*HttpHeaders != NULL) {\r
dac45de3 1926 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
1927 FreePool (*HttpHeaders);\r
1928 }\r
dac45de3 1929\r
b659408b 1930 CopyMem (\r
dac45de3
JW
1931 Buffer + *SizeofHeaders,\r
1932 Fragment.Bulk,\r
1933 Fragment.Len\r
b659408b 1934 );\r
2239ea71 1935 *(Buffer + *BufferSize) = '\0';\r
d1050b9d
MK
1936 *HttpHeaders = Buffer;\r
1937 *SizeofHeaders = *BufferSize;\r
dac45de3 1938\r
b659408b
ZL
1939 //\r
1940 // Check whether we received end of HTTP headers.\r
1941 //\r
19bd1335 1942 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
d1050b9d 1943 }\r
f75a7f56 1944\r
dac45de3
JW
1945 //\r
1946 // Free the buffer.\r
1947 //\r
d1050b9d 1948 if ((Rx4Token != NULL) && (Rx4Token->Packet.RxData != NULL) && (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL)) {\r
dac45de3
JW
1949 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1950 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d 1951 Fragment.Bulk = NULL;\r
dac45de3
JW
1952 }\r
1953\r
1954 if (Fragment.Bulk != NULL) {\r
1955 FreePool (Fragment.Bulk);\r
1956 Fragment.Bulk = NULL;\r
f75a7f56 1957 }\r
b659408b 1958 } else {\r
dac45de3 1959 if (!HttpInstance->UseHttps) {\r
d1050b9d 1960 Rx6Token = &HttpInstance->Rx6Token;\r
dac45de3
JW
1961 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1962 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1963 Status = EFI_OUT_OF_RESOURCES;\r
1964 return Status;\r
1965 }\r
b659408b 1966 }\r
f75a7f56 1967\r
b659408b
ZL
1968 //\r
1969 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1970 //\r
dac45de3
JW
1971 while (*EndofHeader == NULL) {\r
1972 if (!HttpInstance->UseHttps) {\r
d1050b9d
MK
1973 HttpInstance->IsRxDone = FALSE;\r
1974 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
dac45de3 1975 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
d1050b9d 1976 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
dac45de3 1977 if (EFI_ERROR (Status)) {\r
c49ca4a2 1978 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
dac45de3
JW
1979 return Status;\r
1980 }\r
1981\r
1982 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1983 Tcp6->Poll (Tcp6);\r
1984 }\r
1985\r
1986 if (!HttpInstance->IsRxDone) {\r
1987 //\r
ba3b642d 1988 // Cancel the Token before close its Event.\r
dac45de3
JW
1989 //\r
1990 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);\r
1991 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1992 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1993 }\r
1994\r
1995 Status = Rx6Token->CompletionToken.Status;\r
1996 if (EFI_ERROR (Status)) {\r
1997 return Status;\r
1998 }\r
f75a7f56 1999\r
dac45de3 2000 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
d1050b9d 2001 Fragment.Bulk = (UINT8 *)Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
dac45de3
JW
2002 } else {\r
2003 if (Fragment.Bulk != NULL) {\r
2004 FreePool (Fragment.Bulk);\r
2005 Fragment.Bulk = NULL;\r
2006 }\r
f75a7f56 2007\r
dac45de3
JW
2008 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
2009 if (EFI_ERROR (Status)) {\r
c49ca4a2 2010 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
dac45de3
JW
2011 return Status;\r
2012 }\r
b347a22a
JW
2013 }\r
2014\r
b659408b 2015 //\r
2239ea71 2016 // Append the response string along with a Null-terminator.\r
b659408b 2017 //\r
dac45de3 2018 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2239ea71 2019 Buffer = AllocatePool (*BufferSize + 1);\r
b659408b
ZL
2020 if (Buffer == NULL) {\r
2021 Status = EFI_OUT_OF_RESOURCES;\r
2022 return Status;\r
2023 }\r
dac45de3 2024\r
b659408b 2025 if (*HttpHeaders != NULL) {\r
dac45de3 2026 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
2027 FreePool (*HttpHeaders);\r
2028 }\r
dac45de3 2029\r
b659408b 2030 CopyMem (\r
dac45de3
JW
2031 Buffer + *SizeofHeaders,\r
2032 Fragment.Bulk,\r
2033 Fragment.Len\r
b659408b 2034 );\r
2239ea71 2035 *(Buffer + *BufferSize) = '\0';\r
d1050b9d
MK
2036 *HttpHeaders = Buffer;\r
2037 *SizeofHeaders = *BufferSize;\r
dac45de3 2038\r
b659408b
ZL
2039 //\r
2040 // Check whether we received end of HTTP headers.\r
2041 //\r
f75a7f56 2042 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
d1050b9d 2043 }\r
dac45de3
JW
2044\r
2045 //\r
2046 // Free the buffer.\r
2047 //\r
d1050b9d 2048 if ((Rx6Token != NULL) && (Rx6Token->Packet.RxData != NULL) && (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL)) {\r
dac45de3
JW
2049 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2050 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d 2051 Fragment.Bulk = NULL;\r
dac45de3
JW
2052 }\r
2053\r
2054 if (Fragment.Bulk != NULL) {\r
2055 FreePool (Fragment.Bulk);\r
2056 Fragment.Bulk = NULL;\r
b659408b 2057 }\r
f75a7f56 2058 }\r
b659408b
ZL
2059\r
2060 //\r
2061 // Skip the CRLF after the HTTP headers.\r
2062 //\r
b16abfcc
JW
2063 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
2064\r
2065 *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
b659408b
ZL
2066\r
2067 return EFI_SUCCESS;\r
2068}\r
2069\r
2070/**\r
2071 Receive the HTTP body by processing the associated HTTP token.\r
2072\r
2073 @param[in] Wrap The HTTP token's wrap data.\r
2074 @param[in] HttpMsg The HTTP message data.\r
2075\r
f75a7f56 2076 @retval EFI_SUCCESS The HTTP body is received.\r
b659408b
ZL
2077 @retval Others Other error as indicated.\r
2078\r
2079**/\r
2080EFI_STATUS\r
2081HttpTcpReceiveBody (\r
d1050b9d
MK
2082 IN HTTP_TOKEN_WRAP *Wrap,\r
2083 IN EFI_HTTP_MESSAGE *HttpMsg\r
b659408b
ZL
2084 )\r
2085{\r
d1050b9d
MK
2086 EFI_STATUS Status;\r
2087 HTTP_PROTOCOL *HttpInstance;\r
2088 EFI_TCP6_PROTOCOL *Tcp6;\r
2089 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2090 EFI_TCP4_PROTOCOL *Tcp4;\r
2091 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2092\r
2093 HttpInstance = Wrap->HttpInstance;\r
2094 Tcp4 = HttpInstance->Tcp4;\r
2095 Tcp6 = HttpInstance->Tcp6;\r
2096 Rx4Token = NULL;\r
2097 Rx6Token = NULL;\r
f75a7f56 2098\r
b659408b
ZL
2099 if (HttpInstance->LocalAddressIsIPv6) {\r
2100 ASSERT (Tcp6 != NULL);\r
2101 } else {\r
2102 ASSERT (Tcp4 != NULL);\r
2103 }\r
f75a7f56 2104\r
b659408b 2105 if (HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d
MK
2106 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
2107 Rx6Token->Packet.RxData->DataLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2108 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2109 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *)HttpMsg->Body;\r
2110 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
b659408b
ZL
2111\r
2112 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
2113 if (EFI_ERROR (Status)) {\r
c49ca4a2 2114 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
b659408b
ZL
2115 return Status;\r
2116 }\r
b659408b 2117 } else {\r
d1050b9d
MK
2118 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
2119 Rx4Token->Packet.RxData->DataLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2120 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2121 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *)HttpMsg->Body;\r
f75a7f56 2122\r
b659408b 2123 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
d1050b9d 2124 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
b659408b 2125 if (EFI_ERROR (Status)) {\r
c49ca4a2 2126 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
b659408b
ZL
2127 return Status;\r
2128 }\r
2129 }\r
2130\r
2131 return EFI_SUCCESS;\r
b659408b
ZL
2132}\r
2133\r
2134/**\r
2135 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
2136\r
2137 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 2138\r
b659408b
ZL
2139**/\r
2140VOID\r
2141HttpTcpTokenCleanup (\r
d1050b9d 2142 IN HTTP_TOKEN_WRAP *Wrap\r
b659408b 2143 )\r
f75a7f56 2144{\r
d1050b9d
MK
2145 HTTP_PROTOCOL *HttpInstance;\r
2146 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2147 EFI_TCP6_IO_TOKEN *Rx6Token;\r
b659408b 2148\r
1b96428d 2149 ASSERT (Wrap != NULL);\r
d1050b9d
MK
2150 HttpInstance = Wrap->HttpInstance;\r
2151 Rx4Token = NULL;\r
2152 Rx6Token = NULL;\r
f75a7f56 2153\r
b659408b 2154 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d 2155 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
f75a7f56 2156\r
59844e12
JW
2157 if (Rx6Token->CompletionToken.Event != NULL) {\r
2158 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2159 Rx6Token->CompletionToken.Event = NULL;\r
b659408b
ZL
2160 }\r
2161\r
59844e12 2162 FreePool (Wrap);\r
b659408b
ZL
2163\r
2164 Rx6Token = &HttpInstance->Rx6Token;\r
f75a7f56 2165\r
59844e12
JW
2166 if (Rx6Token->CompletionToken.Event != NULL) {\r
2167 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2168 Rx6Token->CompletionToken.Event = NULL;\r
2169 }\r
f75a7f56 2170\r
b659408b
ZL
2171 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2172 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2173 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2174 }\r
b659408b 2175 } else {\r
1b96428d 2176 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
f75a7f56 2177\r
59844e12
JW
2178 if (Rx4Token->CompletionToken.Event != NULL) {\r
2179 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2180 Rx4Token->CompletionToken.Event = NULL;\r
1b96428d 2181 }\r
f75a7f56 2182\r
1b96428d
ZL
2183 FreePool (Wrap);\r
2184\r
59844e12
JW
2185 Rx4Token = &HttpInstance->Rx4Token;\r
2186\r
2187 if (Rx4Token->CompletionToken.Event != NULL) {\r
2188 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2189 Rx4Token->CompletionToken.Event = NULL;\r
b659408b 2190 }\r
f75a7f56 2191\r
b659408b
ZL
2192 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2193 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2194 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2195 }\r
2196 }\r
b659408b 2197}\r
ab796d3e
HL
2198\r
2199/**\r
2200 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.\r
2201\r
2202 @param[in] Event The event that occurs in the current state.\r
2203 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.\r
2204\r
2205**/\r
2206VOID\r
2207HttpNotify (\r
d1050b9d
MK
2208 IN EDKII_HTTP_CALLBACK_EVENT Event,\r
2209 IN EFI_STATUS EventStatus\r
ab796d3e
HL
2210 )\r
2211{\r
d1050b9d
MK
2212 EFI_STATUS Status;\r
2213 EFI_HANDLE *Handles;\r
2214 UINTN Index;\r
2215 UINTN HandleCount;\r
2216 EFI_HANDLE Handle;\r
2217 EDKII_HTTP_CALLBACK_PROTOCOL *HttpCallback;\r
ab796d3e
HL
2218\r
2219 DEBUG ((DEBUG_INFO, "HttpNotify: Event - %d, EventStatus - %r\n", Event, EventStatus));\r
2220\r
d1050b9d 2221 Handles = NULL;\r
ab796d3e 2222 HandleCount = 0;\r
d1050b9d
MK
2223 Status = gBS->LocateHandleBuffer (\r
2224 ByProtocol,\r
2225 &gEdkiiHttpCallbackProtocolGuid,\r
2226 NULL,\r
2227 &HandleCount,\r
2228 &Handles\r
2229 );\r
ab796d3e
HL
2230 if (Status == EFI_SUCCESS) {\r
2231 for (Index = 0; Index < HandleCount; Index++) {\r
2232 Handle = Handles[Index];\r
2233 Status = gBS->HandleProtocol (\r
2234 Handle,\r
2235 &gEdkiiHttpCallbackProtocolGuid,\r
d1050b9d 2236 (VOID **)&HttpCallback\r
ab796d3e
HL
2237 );\r
2238 if (Status == EFI_SUCCESS) {\r
2239 DEBUG ((DEBUG_INFO, "HttpNotify: Notifying %p\n", HttpCallback));\r
2240 HttpCallback->Callback (\r
d1050b9d
MK
2241 HttpCallback,\r
2242 Event,\r
2243 EventStatus\r
2244 );\r
ab796d3e
HL
2245 }\r
2246 }\r
d1050b9d 2247\r
ab796d3e
HL
2248 FreePool (Handles);\r
2249 }\r
2250}\r