]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg/HttpDxe: Decofigure Tcp4 before reconfiguring
[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
ZL
1170\r
1171 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1172 if (EFI_ERROR (Status)) {\r
c49ca4a2 1173 DEBUG ((DEBUG_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
b659408b
ZL
1174 return Status;\r
1175 }\r
f75a7f56 1176\r
b659408b 1177 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1178 if (EFI_ERROR (Status)) {\r
1179 return Status;\r
1180 }\r
1181\r
b659408b 1182 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1183 if (EFI_ERROR (Status)) {\r
1184 return Status;\r
1185 }\r
1186\r
1187 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1188\r
1189 return EFI_SUCCESS;\r
1190}\r
1191\r
1192/**\r
f75a7f56 1193 Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
dac45de3 1194 connect one TLS session if required.\r
47f51a06
YT
1195\r
1196 @param[in] HttpInstance The HTTP instance private data.\r
1197\r
1198 @retval EFI_SUCCESS The TCP connection is established.\r
1199 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1200 @retval Others Other error as indicated.\r
1201\r
1202**/\r
1203EFI_STATUS\r
1204HttpConnectTcp4 (\r
d1050b9d 1205 IN HTTP_PROTOCOL *HttpInstance\r
47f51a06
YT
1206 )\r
1207{\r
d1050b9d
MK
1208 EFI_STATUS Status;\r
1209 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
47f51a06 1210\r
d1050b9d 1211 if ((HttpInstance->State < HTTP_STATE_TCP_CONFIGED) || (HttpInstance->Tcp4 == NULL)) {\r
47f51a06
YT
1212 return EFI_NOT_READY;\r
1213 }\r
1214\r
d1050b9d 1215 Status = HttpInstance->Tcp4->GetModeData (\r
f75a7f56
LG
1216 HttpInstance->Tcp4,\r
1217 &Tcp4State,\r
47f51a06
YT
1218 NULL,\r
1219 NULL,\r
1220 NULL,\r
1221 NULL\r
1222 );\r
d1050b9d 1223 if (EFI_ERROR (Status)) {\r
c49ca4a2 1224 DEBUG ((DEBUG_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
47f51a06
YT
1225 return Status;\r
1226 }\r
1227\r
a2e61982
ZL
1228 if (Tcp4State == Tcp4StateEstablished) {\r
1229 return EFI_SUCCESS;\r
1230 } else if (Tcp4State > Tcp4StateEstablished ) {\r
d1050b9d 1231 HttpCloseConnection (HttpInstance);\r
a2e61982 1232 }\r
47f51a06 1233\r
dac45de3 1234 Status = HttpCreateConnection (HttpInstance);\r
d1050b9d 1235 if (EFI_ERROR (Status)) {\r
c49ca4a2 1236 DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status));\r
dac45de3
JW
1237 return Status;\r
1238 }\r
f75a7f56 1239\r
dac45de3
JW
1240 //\r
1241 // Tls session connection.\r
1242 //\r
1243 if (HttpInstance->UseHttps) {\r
1244 if (HttpInstance->TimeoutEvent == NULL) {\r
1245 //\r
1246 // Create TimeoutEvent for TLS connection.\r
1247 //\r
1248 Status = gBS->CreateEvent (\r
1249 EVT_TIMER,\r
1250 TPL_CALLBACK,\r
1251 NULL,\r
1252 NULL,\r
1253 &HttpInstance->TimeoutEvent\r
1254 );\r
1255 if (EFI_ERROR (Status)) {\r
1256 TlsCloseTxRxEvent (HttpInstance);\r
1257 return Status;\r
1258 }\r
1259 }\r
1260\r
1261 //\r
1262 // Start the timer, and wait Timeout seconds for connection.\r
1263 //\r
1264 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1265 if (EFI_ERROR (Status)) {\r
1266 TlsCloseTxRxEvent (HttpInstance);\r
1267 return Status;\r
1268 }\r
f75a7f56 1269\r
dac45de3 1270 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1271 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1272\r
1273 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1274\r
dac45de3
JW
1275 if (EFI_ERROR (Status)) {\r
1276 TlsCloseTxRxEvent (HttpInstance);\r
1277 return Status;\r
1278 }\r
1279 }\r
1280\r
1281 return Status;\r
47f51a06
YT
1282}\r
1283\r
1284/**\r
f75a7f56 1285 Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
dac45de3 1286 connect one TLS session if required.\r
b659408b
ZL
1287\r
1288 @param[in] HttpInstance The HTTP instance private data.\r
1289\r
1290 @retval EFI_SUCCESS The TCP connection is established.\r
1291 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1292 @retval Others Other error as indicated.\r
1293\r
1294**/\r
1295EFI_STATUS\r
1296HttpConnectTcp6 (\r
d1050b9d 1297 IN HTTP_PROTOCOL *HttpInstance\r
b659408b
ZL
1298 )\r
1299{\r
d1050b9d
MK
1300 EFI_STATUS Status;\r
1301 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
b659408b 1302\r
d1050b9d 1303 if ((HttpInstance->State < HTTP_STATE_TCP_CONFIGED) || (HttpInstance->Tcp6 == NULL)) {\r
b659408b
ZL
1304 return EFI_NOT_READY;\r
1305 }\r
1306\r
1307 Status = HttpInstance->Tcp6->GetModeData (\r
1308 HttpInstance->Tcp6,\r
1309 &Tcp6State,\r
1310 NULL,\r
1311 NULL,\r
1312 NULL,\r
1313 NULL\r
1314 );\r
f75a7f56 1315\r
d1050b9d
MK
1316 if (EFI_ERROR (Status)) {\r
1317 DEBUG ((DEBUG_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1318 return Status;\r
b659408b
ZL
1319 }\r
1320\r
a2e61982
ZL
1321 if (Tcp6State == Tcp6StateEstablished) {\r
1322 return EFI_SUCCESS;\r
1323 } else if (Tcp6State > Tcp6StateEstablished ) {\r
d1050b9d 1324 HttpCloseConnection (HttpInstance);\r
b659408b
ZL
1325 }\r
1326\r
dac45de3 1327 Status = HttpCreateConnection (HttpInstance);\r
d1050b9d 1328 if (EFI_ERROR (Status)) {\r
c49ca4a2 1329 DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status));\r
dac45de3
JW
1330 return Status;\r
1331 }\r
f75a7f56 1332\r
dac45de3
JW
1333 //\r
1334 // Tls session connection.\r
1335 //\r
1336 if (HttpInstance->UseHttps) {\r
1337 if (HttpInstance->TimeoutEvent == NULL) {\r
1338 //\r
1339 // Create TimeoutEvent for TLS connection.\r
1340 //\r
1341 Status = gBS->CreateEvent (\r
1342 EVT_TIMER,\r
1343 TPL_CALLBACK,\r
1344 NULL,\r
1345 NULL,\r
1346 &HttpInstance->TimeoutEvent\r
1347 );\r
1348 if (EFI_ERROR (Status)) {\r
1349 TlsCloseTxRxEvent (HttpInstance);\r
1350 return Status;\r
1351 }\r
1352 }\r
1353\r
1354 //\r
1355 // Start the timer, and wait Timeout seconds for connection.\r
1356 //\r
1357 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1358 if (EFI_ERROR (Status)) {\r
1359 TlsCloseTxRxEvent (HttpInstance);\r
1360 return Status;\r
1361 }\r
f75a7f56 1362\r
dac45de3 1363 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1364 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1365\r
1366 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1367\r
dac45de3
JW
1368 if (EFI_ERROR (Status)) {\r
1369 TlsCloseTxRxEvent (HttpInstance);\r
1370 return Status;\r
1371 }\r
1372 }\r
1373\r
1374 return Status;\r
b659408b
ZL
1375}\r
1376\r
1377/**\r
dac45de3 1378 Initialize Http session.\r
b659408b
ZL
1379\r
1380 @param[in] HttpInstance The HTTP instance private data.\r
1381 @param[in] Wrap The HTTP token's wrap data.\r
dac45de3
JW
1382 @param[in] Configure The Flag indicates whether need to initialize session.\r
1383 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.\r
b659408b 1384\r
f75a7f56 1385 @retval EFI_SUCCESS The initialization of session is done.\r
b659408b
ZL
1386 @retval Others Other error as indicated.\r
1387\r
1388**/\r
1389EFI_STATUS\r
dac45de3 1390HttpInitSession (\r
b659408b 1391 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982 1392 IN HTTP_TOKEN_WRAP *Wrap,\r
dac45de3
JW
1393 IN BOOLEAN Configure,\r
1394 IN BOOLEAN TlsConfigure\r
b659408b
ZL
1395 )\r
1396{\r
d1050b9d
MK
1397 EFI_STATUS Status;\r
1398\r
b659408b
ZL
1399 ASSERT (HttpInstance != NULL);\r
1400\r
dac45de3
JW
1401 //\r
1402 // Configure Tls session.\r
1403 //\r
1404 if (TlsConfigure) {\r
1405 Status = TlsConfigureSession (HttpInstance);\r
1406 if (EFI_ERROR (Status)) {\r
1407 return Status;\r
1408 }\r
1409 }\r
1410\r
b659408b
ZL
1411 if (!HttpInstance->LocalAddressIsIPv6) {\r
1412 //\r
1413 // Configure TCP instance.\r
1414 //\r
a2e61982
ZL
1415 if (Configure) {\r
1416 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1417 if (EFI_ERROR (Status)) {\r
1418 return Status;\r
1419 }\r
b659408b 1420 }\r
a2e61982 1421\r
b659408b
ZL
1422 //\r
1423 // Connect TCP.\r
1424 //\r
1425 Status = HttpConnectTcp4 (HttpInstance);\r
1426 if (EFI_ERROR (Status)) {\r
1427 return Status;\r
1428 }\r
1429 } else {\r
1430 //\r
1431 // Configure TCP instance.\r
1432 //\r
a2e61982
ZL
1433 if (Configure) {\r
1434 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1435 if (EFI_ERROR (Status)) {\r
1436 return Status;\r
1437 }\r
b659408b 1438 }\r
a2e61982 1439\r
b659408b
ZL
1440 //\r
1441 // Connect TCP.\r
1442 //\r
1443 Status = HttpConnectTcp6 (HttpInstance);\r
1444 if (EFI_ERROR (Status)) {\r
1445 return Status;\r
1446 }\r
1447 }\r
f75a7f56 1448\r
b659408b 1449 return EFI_SUCCESS;\r
b659408b
ZL
1450}\r
1451\r
1452/**\r
dac45de3 1453 Send the HTTP or HTTPS message through TCP4 or TCP6.\r
47f51a06
YT
1454\r
1455 @param[in] HttpInstance The HTTP instance private data.\r
1456 @param[in] Wrap The HTTP token's wrap data.\r
1457 @param[in] TxString Buffer containing the HTTP message string.\r
1458 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1459\r
1460 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1461 @retval Others Other error as indicated.\r
1462\r
1463**/\r
1464EFI_STATUS\r
b659408b 1465HttpTransmitTcp (\r
47f51a06
YT
1466 IN HTTP_PROTOCOL *HttpInstance,\r
1467 IN HTTP_TOKEN_WRAP *Wrap,\r
1468 IN UINT8 *TxString,\r
1469 IN UINTN TxStringLen\r
1470 )\r
1471{\r
d1050b9d
MK
1472 EFI_STATUS Status;\r
1473 EFI_TCP4_IO_TOKEN *Tx4Token;\r
1474 EFI_TCP4_PROTOCOL *Tcp4;\r
1475 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1476 EFI_TCP6_PROTOCOL *Tcp6;\r
1477 UINT8 *TlsRecord;\r
1478 UINT16 PayloadSize;\r
1479 NET_FRAGMENT TempFragment;\r
1480 NET_FRAGMENT Fragment;\r
1481 UINTN RecordCount;\r
1482 UINTN RemainingLen;\r
1483\r
1484 Status = EFI_SUCCESS;\r
1485 TlsRecord = NULL;\r
1486 PayloadSize = 0;\r
1487 TempFragment.Len = 0;\r
1488 TempFragment.Bulk = NULL;\r
1489 Fragment.Len = 0;\r
1490 Fragment.Bulk = NULL;\r
1491 RecordCount = 0;\r
1492 RemainingLen = 0;\r
dac45de3
JW
1493\r
1494 //\r
1495 // Need to encrypt data.\r
1496 //\r
1497 if (HttpInstance->UseHttps) {\r
1498 //\r
07bd82d4 1499 // Allocate enough buffer for each TLS plaintext records.\r
dac45de3 1500 //\r
07bd82d4
JW
1501 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1502 if (TlsRecord == NULL) {\r
dac45de3
JW
1503 Status = EFI_OUT_OF_RESOURCES;\r
1504 return Status;\r
1505 }\r
07bd82d4 1506\r
dac45de3 1507 //\r
07bd82d4 1508 // Allocate enough buffer for all TLS ciphertext records.\r
dac45de3 1509 //\r
d1050b9d 1510 RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
07bd82d4
JW
1511 Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
1512 if (Fragment.Bulk == NULL) {\r
1513 Status = EFI_OUT_OF_RESOURCES;\r
1514 goto ON_ERROR;\r
1515 }\r
dac45de3 1516\r
07bd82d4
JW
1517 //\r
1518 // Encrypt each TLS plaintext records.\r
1519 //\r
1520 RemainingLen = TxStringLen;\r
1521 while (RemainingLen != 0) {\r
d1050b9d 1522 PayloadSize = (UINT16)MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
f75a7f56 1523\r
d1050b9d
MK
1524 ((TLS_RECORD_HEADER *)TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
1525 ((TLS_RECORD_HEADER *)TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
1526 ((TLS_RECORD_HEADER *)TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
1527 ((TLS_RECORD_HEADER *)TlsRecord)->Length = PayloadSize;\r
07bd82d4
JW
1528\r
1529 CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
f75a7f56 1530\r
07bd82d4 1531 Status = TlsProcessMessage (\r
f75a7f56
LG
1532 HttpInstance,\r
1533 TlsRecord,\r
1534 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1535 EfiTlsEncrypt,\r
07bd82d4
JW
1536 &TempFragment\r
1537 );\r
1538 if (EFI_ERROR (Status)) {\r
1539 goto ON_ERROR;\r
1540 }\r
1541\r
1542 //\r
f75a7f56 1543 // Record the processed/encrypted Packet.\r
07bd82d4
JW
1544 //\r
1545 CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
1546 Fragment.Len += TempFragment.Len;\r
1547\r
1548 FreePool (TempFragment.Bulk);\r
1549 TempFragment.Len = 0;\r
1550 TempFragment.Bulk = NULL;\r
f75a7f56 1551\r
d1050b9d 1552 RemainingLen -= (UINTN)PayloadSize;\r
07bd82d4 1553 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
dac45de3 1554 }\r
07bd82d4
JW
1555\r
1556 FreePool (TlsRecord);\r
1557 TlsRecord = NULL;\r
dac45de3 1558 }\r
f75a7f56 1559\r
dac45de3 1560 if (!HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d 1561 Tcp4 = HttpInstance->Tcp4;\r
b659408b 1562 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
dac45de3
JW
1563\r
1564 if (HttpInstance->UseHttps) {\r
d1050b9d 1565 Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
07bd82d4 1566 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
d1050b9d 1567 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)Fragment.Bulk;\r
dac45de3 1568 } else {\r
d1050b9d
MK
1569 Tx4Token->Packet.TxData->DataLength = (UINT32)TxStringLen;\r
1570 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)TxStringLen;\r
1571 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)TxString;\r
dac45de3 1572 }\r
f75a7f56
LG
1573\r
1574 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1575\r
b659408b 1576 Wrap->TcpWrap.IsTxDone = FALSE;\r
d1050b9d 1577 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
b659408b 1578 if (EFI_ERROR (Status)) {\r
c49ca4a2 1579 DEBUG ((DEBUG_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1580 goto ON_ERROR;\r
b659408b 1581 }\r
b659408b 1582 } else {\r
d1050b9d 1583 Tcp6 = HttpInstance->Tcp6;\r
b659408b 1584 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
f75a7f56 1585\r
dac45de3 1586 if (HttpInstance->UseHttps) {\r
d1050b9d 1587 Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
07bd82d4 1588 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
d1050b9d 1589 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)Fragment.Bulk;\r
dac45de3 1590 } else {\r
d1050b9d
MK
1591 Tx6Token->Packet.TxData->DataLength = (UINT32)TxStringLen;\r
1592 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)TxStringLen;\r
1593 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)TxString;\r
dac45de3 1594 }\r
f75a7f56 1595\r
b659408b
ZL
1596 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1597\r
1598 Wrap->TcpWrap.IsTxDone = FALSE;\r
d1050b9d 1599 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
b659408b 1600 if (EFI_ERROR (Status)) {\r
c49ca4a2 1601 DEBUG ((DEBUG_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1602 goto ON_ERROR;\r
b659408b 1603 }\r
47f51a06 1604 }\r
f75a7f56 1605\r
07bd82d4
JW
1606 return Status;\r
1607\r
1608ON_ERROR:\r
f75a7f56 1609\r
07bd82d4
JW
1610 if (HttpInstance->UseHttps) {\r
1611 if (TlsRecord != NULL) {\r
1612 FreePool (TlsRecord);\r
1613 TlsRecord = NULL;\r
1614 }\r
f75a7f56 1615\r
07bd82d4
JW
1616 if (Fragment.Bulk != NULL) {\r
1617 FreePool (Fragment.Bulk);\r
1618 Fragment.Bulk = NULL;\r
1619 }\r
1620 }\r
1621\r
47f51a06
YT
1622 return Status;\r
1623}\r
1624\r
47f51a06
YT
1625/**\r
1626 Check whether the user's token or event has already\r
b659408b 1627 been enqueue on HTTP Tx or Rx Token list.\r
47f51a06
YT
1628\r
1629 @param[in] Map The container of either user's transmit or receive\r
1630 token.\r
1631 @param[in] Item Current item to check against.\r
ba3b642d 1632 @param[in] Context The Token to check against.\r
47f51a06
YT
1633\r
1634 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1635 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1636 context.\r
1637\r
1638**/\r
1639EFI_STATUS\r
1640EFIAPI\r
1641HttpTokenExist (\r
d1050b9d
MK
1642 IN NET_MAP *Map,\r
1643 IN NET_MAP_ITEM *Item,\r
1644 IN VOID *Context\r
47f51a06
YT
1645 )\r
1646{\r
d1050b9d
MK
1647 EFI_HTTP_TOKEN *Token;\r
1648 EFI_HTTP_TOKEN *TokenInItem;\r
47f51a06 1649\r
d1050b9d
MK
1650 Token = (EFI_HTTP_TOKEN *)Context;\r
1651 TokenInItem = (EFI_HTTP_TOKEN *)Item->Key;\r
47f51a06 1652\r
d1050b9d 1653 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
47f51a06
YT
1654 return EFI_ACCESS_DENIED;\r
1655 }\r
1656\r
1657 return EFI_SUCCESS;\r
1658}\r
1659\r
1660/**\r
b659408b 1661 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
47f51a06 1662\r
b659408b 1663 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06 1664 @param[in] Item Current item to check against.\r
ba3b642d 1665 @param[in] Context The Token to check against.\r
47f51a06
YT
1666\r
1667 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1668 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1669\r
1670**/\r
1671EFI_STATUS\r
1672EFIAPI\r
1673HttpTcpNotReady (\r
d1050b9d
MK
1674 IN NET_MAP *Map,\r
1675 IN NET_MAP_ITEM *Item,\r
1676 IN VOID *Context\r
47f51a06
YT
1677 )\r
1678{\r
d1050b9d 1679 HTTP_TOKEN_WRAP *ValueInItem;\r
47f51a06 1680\r
d1050b9d 1681 ValueInItem = (HTTP_TOKEN_WRAP *)Item->Value;\r
47f51a06
YT
1682\r
1683 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1684 return EFI_NOT_READY;\r
1685 }\r
f75a7f56 1686\r
47f51a06
YT
1687 return EFI_SUCCESS;\r
1688}\r
1689\r
1690/**\r
ba3b642d 1691 Transmit the HTTP or HTTPS message by processing the associated HTTP token.\r
47f51a06 1692\r
b659408b 1693 @param[in] Map The container of Tx4Token or Tx6Token.\r
47f51a06 1694 @param[in] Item Current item to check against.\r
ba3b642d 1695 @param[in] Context The Token to check against.\r
47f51a06
YT
1696\r
1697 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1698 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1699 queue.\r
1700\r
1701**/\r
1702EFI_STATUS\r
1703EFIAPI\r
1704HttpTcpTransmit (\r
d1050b9d
MK
1705 IN NET_MAP *Map,\r
1706 IN NET_MAP_ITEM *Item,\r
1707 IN VOID *Context\r
47f51a06
YT
1708 )\r
1709{\r
d1050b9d
MK
1710 HTTP_TOKEN_WRAP *ValueInItem;\r
1711 EFI_STATUS Status;\r
1712 CHAR8 *RequestMsg;\r
1713 CHAR8 *Url;\r
1714 UINTN UrlSize;\r
1715 UINTN RequestMsgSize;\r
47f51a06 1716\r
63f1d6a4
JW
1717 RequestMsg = NULL;\r
1718\r
d1050b9d 1719 ValueInItem = (HTTP_TOKEN_WRAP *)Item->Value;\r
47f51a06
YT
1720 if (ValueInItem->TcpWrap.IsTxDone) {\r
1721 return EFI_SUCCESS;\r
1722 }\r
1723\r
1724 //\r
1725 // Parse the URI of the remote host.\r
1726 //\r
b9679cd7 1727 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
d1050b9d 1728 Url = AllocatePool (UrlSize);\r
47f51a06
YT
1729 if (Url == NULL) {\r
1730 return EFI_OUT_OF_RESOURCES;\r
1731 }\r
1732\r
b9679cd7 1733 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
47f51a06
YT
1734\r
1735 //\r
1736 // Create request message.\r
1737 //\r
19c25725 1738 Status = HttpGenRequestMessage (\r
d1050b9d
MK
1739 ValueInItem->HttpToken->Message,\r
1740 Url,\r
1741 &RequestMsg,\r
1742 &RequestMsgSize\r
1743 );\r
47f51a06 1744 FreePool (Url);\r
f58554fc 1745\r
d1050b9d 1746 if (EFI_ERROR (Status) || (NULL == RequestMsg)) {\r
f58554fc 1747 return Status;\r
47f51a06
YT
1748 }\r
1749\r
63f1d6a4
JW
1750 ASSERT (RequestMsg != NULL);\r
1751\r
47f51a06
YT
1752 //\r
1753 // Transmit the request message.\r
1754 //\r
b659408b 1755 Status = HttpTransmitTcp (\r
47f51a06
YT
1756 ValueInItem->HttpInstance,\r
1757 ValueInItem,\r
d1050b9d 1758 (UINT8 *)RequestMsg,\r
19c25725 1759 RequestMsgSize\r
47f51a06 1760 );\r
19c25725 1761 FreePool (RequestMsg);\r
47f51a06
YT
1762 return Status;\r
1763}\r
1764\r
1765/**\r
1766 Receive the HTTP response by processing the associated HTTP token.\r
1767\r
b659408b 1768 @param[in] Map The container of Rx4Token or Rx6Token.\r
47f51a06 1769 @param[in] Item Current item to check against.\r
ba3b642d 1770 @param[in] Context The Token to check against.\r
47f51a06
YT
1771\r
1772 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1773 queue.\r
1774 @retval Others Other error as indicated.\r
1775\r
1776**/\r
1777EFI_STATUS\r
1778EFIAPI\r
1779HttpTcpReceive (\r
d1050b9d
MK
1780 IN NET_MAP *Map,\r
1781 IN NET_MAP_ITEM *Item,\r
1782 IN VOID *Context\r
47f51a06
YT
1783 )\r
1784{\r
1785 //\r
1786 // Process the queued HTTP response.\r
1787 //\r
d1050b9d 1788 return HttpResponseWorker ((HTTP_TOKEN_WRAP *)Item->Value);\r
47f51a06
YT
1789}\r
1790\r
b659408b
ZL
1791/**\r
1792 Receive the HTTP header by processing the associated HTTP token.\r
1793\r
1794 @param[in] HttpInstance The HTTP instance private data.\r
1795 @param[in, out] SizeofHeaders The HTTP header length.\r
ba3b642d 1796 @param[in, out] BufferSize The size of buffer to cache the header message.\r
b347a22a 1797 @param[in] Timeout The time to wait for receiving the header packet.\r
f75a7f56
LG
1798\r
1799 @retval EFI_SUCCESS The HTTP header is received.\r
b659408b
ZL
1800 @retval Others Other errors as indicated.\r
1801\r
1802**/\r
1803EFI_STATUS\r
1804HttpTcpReceiveHeader (\r
d1050b9d
MK
1805 IN HTTP_PROTOCOL *HttpInstance,\r
1806 IN OUT UINTN *SizeofHeaders,\r
1807 IN OUT UINTN *BufferSize,\r
1808 IN EFI_EVENT Timeout\r
b659408b
ZL
1809 )\r
1810{\r
d1050b9d
MK
1811 EFI_STATUS Status;\r
1812 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1813 EFI_TCP4_PROTOCOL *Tcp4;\r
1814 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1815 EFI_TCP6_PROTOCOL *Tcp6;\r
1816 CHAR8 **EndofHeader;\r
1817 CHAR8 **HttpHeaders;\r
1818 CHAR8 *Buffer;\r
1819 NET_FRAGMENT Fragment;\r
b659408b
ZL
1820\r
1821 ASSERT (HttpInstance != NULL);\r
1822\r
d1050b9d
MK
1823 EndofHeader = HttpInstance->EndofHeader;\r
1824 HttpHeaders = HttpInstance->HttpHeaders;\r
1825 Tcp4 = HttpInstance->Tcp4;\r
1826 Tcp6 = HttpInstance->Tcp6;\r
1827 Buffer = NULL;\r
1828 Rx4Token = NULL;\r
1829 Rx6Token = NULL;\r
dac45de3
JW
1830 Fragment.Len = 0;\r
1831 Fragment.Bulk = NULL;\r
f75a7f56 1832\r
b659408b
ZL
1833 if (HttpInstance->LocalAddressIsIPv6) {\r
1834 ASSERT (Tcp6 != NULL);\r
1835 } else {\r
1836 ASSERT (Tcp4 != NULL);\r
1837 }\r
1838\r
dac45de3
JW
1839 if (!HttpInstance->UseHttps) {\r
1840 Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
1841 if (EFI_ERROR (Status)) {\r
b659408b
ZL
1842 return Status;\r
1843 }\r
dac45de3
JW
1844 }\r
1845\r
1846 if (!HttpInstance->LocalAddressIsIPv6) {\r
1847 if (!HttpInstance->UseHttps) {\r
d1050b9d 1848 Rx4Token = &HttpInstance->Rx4Token;\r
dac45de3
JW
1849 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1850 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1851 Status = EFI_OUT_OF_RESOURCES;\r
1852 return Status;\r
1853 }\r
1854 }\r
f75a7f56 1855\r
b659408b
ZL
1856 //\r
1857 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1858 //\r
dac45de3
JW
1859 while (*EndofHeader == NULL) {\r
1860 if (!HttpInstance->UseHttps) {\r
d1050b9d
MK
1861 HttpInstance->IsRxDone = FALSE;\r
1862 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
dac45de3 1863 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
d1050b9d 1864 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
dac45de3 1865 if (EFI_ERROR (Status)) {\r
c49ca4a2 1866 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
dac45de3
JW
1867 return Status;\r
1868 }\r
1869\r
1870 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1871 Tcp4->Poll (Tcp4);\r
1872 }\r
1873\r
1874 if (!HttpInstance->IsRxDone) {\r
1875 //\r
ba3b642d 1876 // Cancel the Token before close its Event.\r
dac45de3
JW
1877 //\r
1878 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);\r
1879 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1880 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1881 }\r
1882\r
1883 Status = Rx4Token->CompletionToken.Status;\r
1884 if (EFI_ERROR (Status)) {\r
1885 return Status;\r
1886 }\r
f75a7f56 1887\r
dac45de3 1888 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
d1050b9d 1889 Fragment.Bulk = (UINT8 *)Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
dac45de3
JW
1890 } else {\r
1891 if (Fragment.Bulk != NULL) {\r
1892 FreePool (Fragment.Bulk);\r
1893 Fragment.Bulk = NULL;\r
1894 }\r
f75a7f56 1895\r
dac45de3
JW
1896 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1897 if (EFI_ERROR (Status)) {\r
c49ca4a2 1898 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
dac45de3
JW
1899 return Status;\r
1900 }\r
b347a22a
JW
1901 }\r
1902\r
b659408b 1903 //\r
2239ea71 1904 // Append the response string along with a Null-terminator.\r
b659408b 1905 //\r
dac45de3 1906 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2239ea71 1907 Buffer = AllocatePool (*BufferSize + 1);\r
b659408b
ZL
1908 if (Buffer == NULL) {\r
1909 Status = EFI_OUT_OF_RESOURCES;\r
1910 return Status;\r
1911 }\r
dac45de3 1912\r
b659408b 1913 if (*HttpHeaders != NULL) {\r
dac45de3 1914 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
1915 FreePool (*HttpHeaders);\r
1916 }\r
dac45de3 1917\r
b659408b 1918 CopyMem (\r
dac45de3
JW
1919 Buffer + *SizeofHeaders,\r
1920 Fragment.Bulk,\r
1921 Fragment.Len\r
b659408b 1922 );\r
2239ea71 1923 *(Buffer + *BufferSize) = '\0';\r
d1050b9d
MK
1924 *HttpHeaders = Buffer;\r
1925 *SizeofHeaders = *BufferSize;\r
dac45de3 1926\r
b659408b
ZL
1927 //\r
1928 // Check whether we received end of HTTP headers.\r
1929 //\r
19bd1335 1930 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
d1050b9d 1931 }\r
f75a7f56 1932\r
dac45de3
JW
1933 //\r
1934 // Free the buffer.\r
1935 //\r
d1050b9d 1936 if ((Rx4Token != NULL) && (Rx4Token->Packet.RxData != NULL) && (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL)) {\r
dac45de3
JW
1937 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1938 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d 1939 Fragment.Bulk = NULL;\r
dac45de3
JW
1940 }\r
1941\r
1942 if (Fragment.Bulk != NULL) {\r
1943 FreePool (Fragment.Bulk);\r
1944 Fragment.Bulk = NULL;\r
f75a7f56 1945 }\r
b659408b 1946 } else {\r
dac45de3 1947 if (!HttpInstance->UseHttps) {\r
d1050b9d 1948 Rx6Token = &HttpInstance->Rx6Token;\r
dac45de3
JW
1949 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1950 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1951 Status = EFI_OUT_OF_RESOURCES;\r
1952 return Status;\r
1953 }\r
b659408b 1954 }\r
f75a7f56 1955\r
b659408b
ZL
1956 //\r
1957 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1958 //\r
dac45de3
JW
1959 while (*EndofHeader == NULL) {\r
1960 if (!HttpInstance->UseHttps) {\r
d1050b9d
MK
1961 HttpInstance->IsRxDone = FALSE;\r
1962 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
dac45de3 1963 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
d1050b9d 1964 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
dac45de3 1965 if (EFI_ERROR (Status)) {\r
c49ca4a2 1966 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
dac45de3
JW
1967 return Status;\r
1968 }\r
1969\r
1970 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1971 Tcp6->Poll (Tcp6);\r
1972 }\r
1973\r
1974 if (!HttpInstance->IsRxDone) {\r
1975 //\r
ba3b642d 1976 // Cancel the Token before close its Event.\r
dac45de3
JW
1977 //\r
1978 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);\r
1979 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1980 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1981 }\r
1982\r
1983 Status = Rx6Token->CompletionToken.Status;\r
1984 if (EFI_ERROR (Status)) {\r
1985 return Status;\r
1986 }\r
f75a7f56 1987\r
dac45de3 1988 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
d1050b9d 1989 Fragment.Bulk = (UINT8 *)Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
dac45de3
JW
1990 } else {\r
1991 if (Fragment.Bulk != NULL) {\r
1992 FreePool (Fragment.Bulk);\r
1993 Fragment.Bulk = NULL;\r
1994 }\r
f75a7f56 1995\r
dac45de3
JW
1996 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1997 if (EFI_ERROR (Status)) {\r
c49ca4a2 1998 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
dac45de3
JW
1999 return Status;\r
2000 }\r
b347a22a
JW
2001 }\r
2002\r
b659408b 2003 //\r
2239ea71 2004 // Append the response string along with a Null-terminator.\r
b659408b 2005 //\r
dac45de3 2006 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2239ea71 2007 Buffer = AllocatePool (*BufferSize + 1);\r
b659408b
ZL
2008 if (Buffer == NULL) {\r
2009 Status = EFI_OUT_OF_RESOURCES;\r
2010 return Status;\r
2011 }\r
dac45de3 2012\r
b659408b 2013 if (*HttpHeaders != NULL) {\r
dac45de3 2014 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
b659408b
ZL
2015 FreePool (*HttpHeaders);\r
2016 }\r
dac45de3 2017\r
b659408b 2018 CopyMem (\r
dac45de3
JW
2019 Buffer + *SizeofHeaders,\r
2020 Fragment.Bulk,\r
2021 Fragment.Len\r
b659408b 2022 );\r
2239ea71 2023 *(Buffer + *BufferSize) = '\0';\r
d1050b9d
MK
2024 *HttpHeaders = Buffer;\r
2025 *SizeofHeaders = *BufferSize;\r
dac45de3 2026\r
b659408b
ZL
2027 //\r
2028 // Check whether we received end of HTTP headers.\r
2029 //\r
f75a7f56 2030 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
d1050b9d 2031 }\r
dac45de3
JW
2032\r
2033 //\r
2034 // Free the buffer.\r
2035 //\r
d1050b9d 2036 if ((Rx6Token != NULL) && (Rx6Token->Packet.RxData != NULL) && (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL)) {\r
dac45de3
JW
2037 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2038 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
d1050b9d 2039 Fragment.Bulk = NULL;\r
dac45de3
JW
2040 }\r
2041\r
2042 if (Fragment.Bulk != NULL) {\r
2043 FreePool (Fragment.Bulk);\r
2044 Fragment.Bulk = NULL;\r
b659408b 2045 }\r
f75a7f56 2046 }\r
b659408b
ZL
2047\r
2048 //\r
2049 // Skip the CRLF after the HTTP headers.\r
2050 //\r
b16abfcc
JW
2051 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
2052\r
2053 *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
b659408b
ZL
2054\r
2055 return EFI_SUCCESS;\r
2056}\r
2057\r
2058/**\r
2059 Receive the HTTP body by processing the associated HTTP token.\r
2060\r
2061 @param[in] Wrap The HTTP token's wrap data.\r
2062 @param[in] HttpMsg The HTTP message data.\r
2063\r
f75a7f56 2064 @retval EFI_SUCCESS The HTTP body is received.\r
b659408b
ZL
2065 @retval Others Other error as indicated.\r
2066\r
2067**/\r
2068EFI_STATUS\r
2069HttpTcpReceiveBody (\r
d1050b9d
MK
2070 IN HTTP_TOKEN_WRAP *Wrap,\r
2071 IN EFI_HTTP_MESSAGE *HttpMsg\r
b659408b
ZL
2072 )\r
2073{\r
d1050b9d
MK
2074 EFI_STATUS Status;\r
2075 HTTP_PROTOCOL *HttpInstance;\r
2076 EFI_TCP6_PROTOCOL *Tcp6;\r
2077 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2078 EFI_TCP4_PROTOCOL *Tcp4;\r
2079 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2080\r
2081 HttpInstance = Wrap->HttpInstance;\r
2082 Tcp4 = HttpInstance->Tcp4;\r
2083 Tcp6 = HttpInstance->Tcp6;\r
2084 Rx4Token = NULL;\r
2085 Rx6Token = NULL;\r
f75a7f56 2086\r
b659408b
ZL
2087 if (HttpInstance->LocalAddressIsIPv6) {\r
2088 ASSERT (Tcp6 != NULL);\r
2089 } else {\r
2090 ASSERT (Tcp4 != NULL);\r
2091 }\r
f75a7f56 2092\r
b659408b 2093 if (HttpInstance->LocalAddressIsIPv6) {\r
d1050b9d
MK
2094 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
2095 Rx6Token->Packet.RxData->DataLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2096 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2097 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *)HttpMsg->Body;\r
2098 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
b659408b
ZL
2099\r
2100 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
2101 if (EFI_ERROR (Status)) {\r
c49ca4a2 2102 DEBUG ((DEBUG_ERROR, "Tcp6 receive failed: %r\n", Status));\r
b659408b
ZL
2103 return Status;\r
2104 }\r
b659408b 2105 } else {\r
d1050b9d
MK
2106 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
2107 Rx4Token->Packet.RxData->DataLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2108 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32)MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2109 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *)HttpMsg->Body;\r
f75a7f56 2110\r
b659408b 2111 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
d1050b9d 2112 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
b659408b 2113 if (EFI_ERROR (Status)) {\r
c49ca4a2 2114 DEBUG ((DEBUG_ERROR, "Tcp4 receive failed: %r\n", Status));\r
b659408b
ZL
2115 return Status;\r
2116 }\r
2117 }\r
2118\r
2119 return EFI_SUCCESS;\r
b659408b
ZL
2120}\r
2121\r
2122/**\r
2123 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
2124\r
2125 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 2126\r
b659408b
ZL
2127**/\r
2128VOID\r
2129HttpTcpTokenCleanup (\r
d1050b9d 2130 IN HTTP_TOKEN_WRAP *Wrap\r
b659408b 2131 )\r
f75a7f56 2132{\r
d1050b9d
MK
2133 HTTP_PROTOCOL *HttpInstance;\r
2134 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2135 EFI_TCP6_IO_TOKEN *Rx6Token;\r
b659408b 2136\r
1b96428d 2137 ASSERT (Wrap != NULL);\r
d1050b9d
MK
2138 HttpInstance = Wrap->HttpInstance;\r
2139 Rx4Token = NULL;\r
2140 Rx6Token = NULL;\r
f75a7f56 2141\r
b659408b 2142 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d 2143 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
f75a7f56 2144\r
59844e12
JW
2145 if (Rx6Token->CompletionToken.Event != NULL) {\r
2146 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2147 Rx6Token->CompletionToken.Event = NULL;\r
b659408b
ZL
2148 }\r
2149\r
59844e12 2150 FreePool (Wrap);\r
b659408b
ZL
2151\r
2152 Rx6Token = &HttpInstance->Rx6Token;\r
f75a7f56 2153\r
59844e12
JW
2154 if (Rx6Token->CompletionToken.Event != NULL) {\r
2155 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2156 Rx6Token->CompletionToken.Event = NULL;\r
2157 }\r
f75a7f56 2158\r
b659408b
ZL
2159 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2160 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2161 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2162 }\r
b659408b 2163 } else {\r
1b96428d 2164 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
f75a7f56 2165\r
59844e12
JW
2166 if (Rx4Token->CompletionToken.Event != NULL) {\r
2167 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2168 Rx4Token->CompletionToken.Event = NULL;\r
1b96428d 2169 }\r
f75a7f56 2170\r
1b96428d
ZL
2171 FreePool (Wrap);\r
2172\r
59844e12
JW
2173 Rx4Token = &HttpInstance->Rx4Token;\r
2174\r
2175 if (Rx4Token->CompletionToken.Event != NULL) {\r
2176 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2177 Rx4Token->CompletionToken.Event = NULL;\r
b659408b 2178 }\r
f75a7f56 2179\r
b659408b
ZL
2180 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2181 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2182 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2183 }\r
2184 }\r
b659408b 2185}\r
ab796d3e
HL
2186\r
2187/**\r
2188 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.\r
2189\r
2190 @param[in] Event The event that occurs in the current state.\r
2191 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.\r
2192\r
2193**/\r
2194VOID\r
2195HttpNotify (\r
d1050b9d
MK
2196 IN EDKII_HTTP_CALLBACK_EVENT Event,\r
2197 IN EFI_STATUS EventStatus\r
ab796d3e
HL
2198 )\r
2199{\r
d1050b9d
MK
2200 EFI_STATUS Status;\r
2201 EFI_HANDLE *Handles;\r
2202 UINTN Index;\r
2203 UINTN HandleCount;\r
2204 EFI_HANDLE Handle;\r
2205 EDKII_HTTP_CALLBACK_PROTOCOL *HttpCallback;\r
ab796d3e
HL
2206\r
2207 DEBUG ((DEBUG_INFO, "HttpNotify: Event - %d, EventStatus - %r\n", Event, EventStatus));\r
2208\r
d1050b9d 2209 Handles = NULL;\r
ab796d3e 2210 HandleCount = 0;\r
d1050b9d
MK
2211 Status = gBS->LocateHandleBuffer (\r
2212 ByProtocol,\r
2213 &gEdkiiHttpCallbackProtocolGuid,\r
2214 NULL,\r
2215 &HandleCount,\r
2216 &Handles\r
2217 );\r
ab796d3e
HL
2218 if (Status == EFI_SUCCESS) {\r
2219 for (Index = 0; Index < HandleCount; Index++) {\r
2220 Handle = Handles[Index];\r
2221 Status = gBS->HandleProtocol (\r
2222 Handle,\r
2223 &gEdkiiHttpCallbackProtocolGuid,\r
d1050b9d 2224 (VOID **)&HttpCallback\r
ab796d3e
HL
2225 );\r
2226 if (Status == EFI_SUCCESS) {\r
2227 DEBUG ((DEBUG_INFO, "HttpNotify: Notifying %p\n", HttpCallback));\r
2228 HttpCallback->Callback (\r
d1050b9d
MK
2229 HttpCallback,\r
2230 Event,\r
2231 EventStatus\r
2232 );\r
ab796d3e
HL
2233 }\r
2234 }\r
d1050b9d 2235\r
ab796d3e
HL
2236 FreePool (Handles);\r
2237 }\r
2238}\r