]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Add HTTP Additional Event Notifications
[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
27 return ;\r
28 }\r
29\r
30 *((BOOLEAN *) Context) = TRUE;\r
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
47f51a06
YT
42 IN VOID *Context\r
43 )\r
44{\r
45 HTTP_TOKEN_WRAP *Wrap;\r
b659408b 46 HTTP_PROTOCOL *HttpInstance;\r
47f51a06 47\r
49c9f74c 48 if (Context == NULL) {\r
47f51a06
YT
49 return ;\r
50 }\r
f75a7f56 51\r
b659408b
ZL
52 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
53 HttpInstance = Wrap->HttpInstance;\r
f75a7f56 54\r
b659408b
ZL
55 if (!HttpInstance->LocalAddressIsIPv6) {\r
56 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
57 gBS->SignalEvent (Wrap->HttpToken->Event);\r
58\r
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
47f51a06 65\r
b659408b
ZL
66 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
67 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
68 }\r
f75a7f56 69\r
b659408b
ZL
70 } else {\r
71 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
72 gBS->SignalEvent (Wrap->HttpToken->Event);\r
f75a7f56 73\r
b659408b
ZL
74 //\r
75 // Free resources.\r
76 //\r
77 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
78 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
79 }\r
47f51a06 80\r
b659408b
ZL
81 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
82 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
f75a7f56 83 }\r
47f51a06
YT
84 }\r
85\r
47f51a06
YT
86\r
87 Wrap->TcpWrap.IsTxDone = TRUE;\r
88\r
89 //\r
90 // Check pending TxTokens and sent out.\r
91 //\r
92 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);\r
93\r
94}\r
95\r
49c9f74c
FS
96/**\r
97 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.\r
98\r
99 @param Event The receive event delivered to TCP for transmit.\r
100 @param Context Context for the callback.\r
101\r
102**/\r
103VOID\r
104EFIAPI\r
105HttpTcpTransmitNotify (\r
106 IN EFI_EVENT Event,\r
107 IN VOID *Context\r
108 )\r
109{\r
110 //\r
111 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
112 //\r
113 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
114}\r
115\r
47f51a06 116/**\r
b659408b 117 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
47f51a06 118\r
47f51a06
YT
119 @param[in] Context The context.\r
120\r
121**/\r
122VOID\r
123EFIAPI\r
49c9f74c 124HttpTcpReceiveNotifyDpc (\r
47f51a06
YT
125 IN VOID *Context\r
126 )\r
127{\r
128 HTTP_TOKEN_WRAP *Wrap;\r
129 NET_MAP_ITEM *Item;\r
130 UINTN Length;\r
131 EFI_STATUS Status;\r
132 HTTP_PROTOCOL *HttpInstance;\r
b659408b 133 BOOLEAN UsingIpv6;\r
47f51a06 134\r
49c9f74c 135 if (Context == NULL) {\r
47f51a06
YT
136 return ;\r
137 }\r
138\r
139 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
47f51a06 140 HttpInstance = Wrap->HttpInstance;\r
b659408b 141 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
f75a7f56 142\r
b659408b
ZL
143 if (UsingIpv6) {\r
144 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
30526a51 145 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
f75a7f56 146\r
b659408b 147 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
30526a51 148 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status));\r
621a618a
ZL
149 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
150 gBS->SignalEvent (Wrap->HttpToken->Event);\r
30526a51
JW
151\r
152 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
153 if (Item != NULL) {\r
154 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
155 }\r
f75a7f56 156\r
30526a51
JW
157 FreePool (Wrap);\r
158 Wrap = NULL;\r
f75a7f56 159\r
b659408b
ZL
160 return ;\r
161 }\r
162\r
163 } else {\r
164 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
30526a51 165 Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;\r
f75a7f56 166\r
b659408b 167 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
30526a51 168 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status));\r
621a618a
ZL
169 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
170 gBS->SignalEvent (Wrap->HttpToken->Event);\r
f75a7f56 171\r
30526a51
JW
172 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
173 if (Item != NULL) {\r
174 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
175 }\r
f75a7f56 176\r
30526a51
JW
177 FreePool (Wrap);\r
178 Wrap = NULL;\r
f75a7f56 179\r
b659408b
ZL
180 return ;\r
181 }\r
182 }\r
47f51a06
YT
183\r
184 //\r
185 // Check whether we receive a complete HTTP message.\r
186 //\r
187 ASSERT (HttpInstance->MsgParser != NULL);\r
b659408b
ZL
188 if (UsingIpv6) {\r
189 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
190 } else {\r
191 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
192 }\r
47f51a06 193\r
895b87e3
JW
194 //\r
195 // Record the CallbackData data.\r
196 //\r
197 HttpInstance->CallbackData.Wrap = (VOID *) Wrap;\r
198 HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;\r
199 HttpInstance->CallbackData.ParseDataLength = Length;\r
200\r
201 //\r
202 // Parse Body with CallbackData data.\r
203 //\r
47f51a06
YT
204 Status = HttpParseMessageBody (\r
205 HttpInstance->MsgParser,\r
206 Length,\r
207 Wrap->HttpToken->Message->Body\r
208 );\r
209 if (EFI_ERROR (Status)) {\r
210 return ;\r
211 }\r
212\r
213 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {\r
214 //\r
215 // Free the MsgParse since we already have a full HTTP message.\r
216 //\r
217 HttpFreeMsgParser (HttpInstance->MsgParser);\r
218 HttpInstance->MsgParser = NULL;\r
219 }\r
220\r
221 Wrap->HttpToken->Message->BodyLength = Length;\r
222 ASSERT (HttpInstance->CacheBody == NULL);\r
223 //\r
224 // We receive part of header of next HTTP msg.\r
225 //\r
226 if (HttpInstance->NextMsg != NULL) {\r
f75a7f56 227 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg -\r
47f51a06
YT
228 (CHAR8 *) Wrap->HttpToken->Message->Body;\r
229 HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;\r
230 if (HttpInstance->CacheLen != 0) {\r
231 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);\r
232 if (HttpInstance->CacheBody == NULL) {\r
233 return ;\r
234 }\r
235 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);\r
236 HttpInstance->NextMsg = HttpInstance->CacheBody;\r
237 HttpInstance->CacheOffset = 0;\r
238 }\r
239 }\r
240\r
241 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);\r
242 if (Item != NULL) {\r
243 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
244 }\r
245\r
246\r
247 Wrap->TcpWrap.IsRxDone = TRUE;\r
b659408b
ZL
248 if (UsingIpv6) {\r
249 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
250 } else {\r
251 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
252 }\r
f75a7f56 253\r
47f51a06
YT
254\r
255 gBS->SignalEvent (Wrap->HttpToken->Event);\r
256\r
257 //\r
258 // Check pending RxTokens and receive the HTTP message.\r
259 //\r
260 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
30526a51
JW
261\r
262 FreePool (Wrap);\r
263 Wrap = NULL;\r
47f51a06
YT
264}\r
265\r
49c9f74c
FS
266/**\r
267 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.\r
268\r
269 @param Event The receive event delivered to TCP for receive.\r
270 @param Context Context for the callback.\r
271\r
272**/\r
273VOID\r
274EFIAPI\r
275HttpTcpReceiveNotify (\r
276 IN EFI_EVENT Event,\r
277 IN VOID *Context\r
278 )\r
279{\r
280 //\r
281 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
282 //\r
283 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
284}\r
285\r
47f51a06 286/**\r
b659408b 287 Create events for the TCP connection token and TCP close token.\r
47f51a06
YT
288\r
289 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
290\r
291 @retval EFI_SUCCESS The events are created successfully.\r
292 @retval others Other error as indicated.\r
293\r
294**/\r
295EFI_STATUS\r
b659408b 296HttpCreateTcpConnCloseEvent (\r
47f51a06
YT
297 IN HTTP_PROTOCOL *HttpInstance\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
b659408b
ZL
301\r
302 if (!HttpInstance->LocalAddressIsIPv6) {\r
47f51a06 303 //\r
ba3b642d 304 // Create events for various asynchronous operations.\r
47f51a06
YT
305 //\r
306 Status = gBS->CreateEvent (\r
307 EVT_NOTIFY_SIGNAL,\r
308 TPL_NOTIFY,\r
309 HttpCommonNotify,\r
b659408b
ZL
310 &HttpInstance->IsTcp4ConnDone,\r
311 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
47f51a06
YT
312 );\r
313 if (EFI_ERROR (Status)) {\r
314 goto ERROR;\r
315 }\r
316\r
317 //\r
b659408b
ZL
318 // Initialize Tcp4CloseToken\r
319 //\r
320 Status = gBS->CreateEvent (\r
321 EVT_NOTIFY_SIGNAL,\r
322 TPL_NOTIFY,\r
323 HttpCommonNotify,\r
324 &HttpInstance->IsTcp4CloseDone,\r
325 &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
326 );\r
327 if (EFI_ERROR (Status)) {\r
328 goto ERROR;\r
329 }\r
f75a7f56 330\r
b659408b
ZL
331 } else {\r
332 //\r
ba3b642d 333 // Create events for various asynchronous operations.\r
47f51a06
YT
334 //\r
335 Status = gBS->CreateEvent (\r
336 EVT_NOTIFY_SIGNAL,\r
337 TPL_NOTIFY,\r
338 HttpCommonNotify,\r
b659408b
ZL
339 &HttpInstance->IsTcp6ConnDone,\r
340 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
47f51a06
YT
341 );\r
342 if (EFI_ERROR (Status)) {\r
343 goto ERROR;\r
344 }\r
345\r
b659408b
ZL
346 //\r
347 // Initialize Tcp6CloseToken\r
348 //\r
349 Status = gBS->CreateEvent (\r
350 EVT_NOTIFY_SIGNAL,\r
351 TPL_NOTIFY,\r
352 HttpCommonNotify,\r
353 &HttpInstance->IsTcp6CloseDone,\r
354 &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
355 );\r
356 if (EFI_ERROR (Status)) {\r
357 goto ERROR;\r
358 }\r
359 }\r
f75a7f56 360\r
47f51a06
YT
361 return EFI_SUCCESS;\r
362\r
363ERROR:\r
364 //\r
365 // Error handling\r
366 //\r
b659408b 367 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
368\r
369 return Status;\r
370}\r
371\r
372\r
373/**\r
b659408b 374 Close events in the TCP connection token and TCP close token.\r
47f51a06
YT
375\r
376 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
377\r
378**/\r
379VOID\r
b659408b 380HttpCloseTcpConnCloseEvent (\r
47f51a06
YT
381 IN HTTP_PROTOCOL *HttpInstance\r
382 )\r
383{\r
384 ASSERT (HttpInstance != NULL);\r
385\r
b659408b
ZL
386 if (HttpInstance->LocalAddressIsIPv6) {\r
387 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
388 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
389 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
390 }\r
47f51a06 391\r
b659408b
ZL
392 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
393 gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
394 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
395 }\r
396\r
397 } else {\r
398 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
399 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
400 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
401 }\r
402\r
403 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
404 gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
405 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
406 }\r
407 }\r
f75a7f56 408\r
47f51a06
YT
409}\r
410\r
411/**\r
b659408b 412 Create event for the TCP transmit token.\r
47f51a06
YT
413\r
414 @param[in] Wrap Point to HTTP token's wrap data.\r
415\r
416 @retval EFI_SUCCESS The events is created successfully.\r
417 @retval others Other error as indicated.\r
418\r
419**/\r
420EFI_STATUS\r
b659408b 421HttpCreateTcpTxEvent (\r
47f51a06
YT
422 IN HTTP_TOKEN_WRAP *Wrap\r
423 )\r
424{\r
425 EFI_STATUS Status;\r
b659408b 426 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
427 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
428\r
b659408b 429 HttpInstance = Wrap->HttpInstance;\r
47f51a06
YT
430 TcpWrap = &Wrap->TcpWrap;\r
431\r
b659408b
ZL
432 if (!HttpInstance->LocalAddressIsIPv6) {\r
433 Status = gBS->CreateEvent (\r
434 EVT_NOTIFY_SIGNAL,\r
435 TPL_NOTIFY,\r
436 HttpTcpTransmitNotify,\r
437 Wrap,\r
438 &TcpWrap->Tx4Token.CompletionToken.Event\r
439 );\r
30526a51
JW
440 if (EFI_ERROR (Status)) {\r
441 return Status;\r
442 }\r
f75a7f56 443\r
30526a51
JW
444 TcpWrap->Tx4Data.Push = TRUE;\r
445 TcpWrap->Tx4Data.Urgent = FALSE;\r
446 TcpWrap->Tx4Data.FragmentCount = 1;\r
447 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
448 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 449\r
b659408b
ZL
450 } else {\r
451 Status = gBS->CreateEvent (\r
452 EVT_NOTIFY_SIGNAL,\r
453 TPL_NOTIFY,\r
454 HttpTcpTransmitNotify,\r
455 Wrap,\r
456 &TcpWrap->Tx6Token.CompletionToken.Event\r
457 );\r
458 if (EFI_ERROR (Status)) {\r
459 return Status;\r
460 }\r
47f51a06 461\r
b659408b
ZL
462 TcpWrap->Tx6Data.Push = TRUE;\r
463 TcpWrap->Tx6Data.Urgent = FALSE;\r
464 TcpWrap->Tx6Data.FragmentCount = 1;\r
465 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
466 TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
f75a7f56 467\r
b659408b 468 }\r
f75a7f56 469\r
47f51a06
YT
470 return EFI_SUCCESS;\r
471}\r
472\r
473/**\r
b659408b 474 Create event for the TCP receive token which is used to receive HTTP header.\r
47f51a06
YT
475\r
476 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
477\r
478 @retval EFI_SUCCESS The events is created successfully.\r
479 @retval others Other error as indicated.\r
480\r
481**/\r
482EFI_STATUS\r
b659408b 483HttpCreateTcpRxEventForHeader (\r
47f51a06
YT
484 IN HTTP_PROTOCOL *HttpInstance\r
485 )\r
486{\r
487 EFI_STATUS Status;\r
488\r
b659408b
ZL
489 if (!HttpInstance->LocalAddressIsIPv6) {\r
490 Status = gBS->CreateEvent (\r
491 EVT_NOTIFY_SIGNAL,\r
492 TPL_NOTIFY,\r
493 HttpCommonNotify,\r
494 &HttpInstance->IsRxDone,\r
495 &HttpInstance->Rx4Token.CompletionToken.Event\r
496 );\r
497 if (EFI_ERROR (Status)) {\r
498 return Status;\r
499 }\r
f75a7f56 500\r
b659408b
ZL
501 HttpInstance->Rx4Data.FragmentCount = 1;\r
502 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
503 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 504\r
b659408b
ZL
505 } else {\r
506 Status = gBS->CreateEvent (\r
507 EVT_NOTIFY_SIGNAL,\r
508 TPL_NOTIFY,\r
509 HttpCommonNotify,\r
510 &HttpInstance->IsRxDone,\r
511 &HttpInstance->Rx6Token.CompletionToken.Event\r
512 );\r
513 if (EFI_ERROR (Status)) {\r
514 return Status;\r
515 }\r
516\r
517 HttpInstance->Rx6Data.FragmentCount =1;\r
518 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
519 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
f75a7f56 520\r
47f51a06
YT
521 }\r
522\r
47f51a06
YT
523\r
524 return EFI_SUCCESS;\r
525}\r
526\r
527/**\r
b659408b 528 Create event for the TCP receive token which is used to receive HTTP body.\r
47f51a06
YT
529\r
530 @param[in] Wrap Point to HTTP token's wrap data.\r
531\r
532 @retval EFI_SUCCESS The events is created successfully.\r
533 @retval others Other error as indicated.\r
534\r
535**/\r
536EFI_STATUS\r
b659408b 537HttpCreateTcpRxEvent (\r
f75a7f56 538 IN HTTP_TOKEN_WRAP *Wrap\r
47f51a06
YT
539 )\r
540{\r
541 EFI_STATUS Status;\r
b659408b 542 HTTP_PROTOCOL *HttpInstance;\r
47f51a06
YT
543 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
544\r
b659408b 545 HttpInstance = Wrap->HttpInstance;\r
47f51a06 546 TcpWrap = &Wrap->TcpWrap;\r
b659408b
ZL
547 if (!HttpInstance->LocalAddressIsIPv6) {\r
548 Status = gBS->CreateEvent (\r
549 EVT_NOTIFY_SIGNAL,\r
550 TPL_NOTIFY,\r
551 HttpTcpReceiveNotify,\r
552 Wrap,\r
553 &TcpWrap->Rx4Token.CompletionToken.Event\r
554 );\r
555 if (EFI_ERROR (Status)) {\r
556 return Status;\r
557 }\r
f75a7f56 558\r
b659408b
ZL
559 TcpWrap->Rx4Data.FragmentCount = 1;\r
560 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
561 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 562\r
b659408b
ZL
563 } else {\r
564 Status = gBS->CreateEvent (\r
565 EVT_NOTIFY_SIGNAL,\r
566 TPL_NOTIFY,\r
567 HttpTcpReceiveNotify,\r
568 Wrap,\r
569 &TcpWrap->Rx6Token.CompletionToken.Event\r
f75a7f56 570 );\r
b659408b
ZL
571 if (EFI_ERROR (Status)) {\r
572 return Status;\r
573 }\r
574\r
575 TcpWrap->Rx6Data.FragmentCount = 1;\r
576 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
577 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
47f51a06 578 }\r
f75a7f56 579\r
b659408b
ZL
580 return EFI_SUCCESS;\r
581}\r
47f51a06 582\r
b659408b
ZL
583/**\r
584 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
47f51a06 585\r
b659408b 586 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 587\r
b659408b
ZL
588**/\r
589VOID\r
590HttpCloseTcpRxEvent (\r
591 IN HTTP_TOKEN_WRAP *Wrap\r
592 )\r
593{\r
594 HTTP_PROTOCOL *HttpInstance;\r
b659408b 595\r
1b96428d 596 ASSERT (Wrap != NULL);\r
b659408b 597 HttpInstance = Wrap->HttpInstance;\r
f75a7f56 598\r
b659408b 599 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d
ZL
600 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
601 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
b659408b
ZL
602 }\r
603\r
604 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
605 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
606 HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
607 }\r
608 } else {\r
1b96428d
ZL
609 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
610 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
b659408b 611 }\r
f75a7f56 612\r
b659408b
ZL
613 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
614 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
615 HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
616 }\r
617 }\r
47f51a06
YT
618}\r
619\r
620/**\r
ba3b642d 621 Initialize the HTTP_PROTOCOL structure to the unconfigured state.\r
47f51a06 622\r
47f51a06 623 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
b659408b 624 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
47f51a06 625\r
f75a7f56 626 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.\r
47f51a06
YT
627 @retval Others Other error as indicated.\r
628\r
629**/\r
630EFI_STATUS\r
631HttpInitProtocol (\r
b659408b
ZL
632 IN OUT HTTP_PROTOCOL *HttpInstance,\r
633 IN BOOLEAN IpVersion\r
47f51a06
YT
634 )\r
635{\r
636 EFI_STATUS Status;\r
637 VOID *Interface;\r
b659408b 638 BOOLEAN UsingIpv6;\r
f75a7f56 639\r
b659408b
ZL
640 ASSERT (HttpInstance != NULL);\r
641 UsingIpv6 = IpVersion;\r
f75a7f56 642\r
b659408b
ZL
643 if (!UsingIpv6) {\r
644 //\r
645 // Create TCP4 child.\r
646 //\r
647 Status = NetLibCreateServiceChild (\r
648 HttpInstance->Service->ControllerHandle,\r
7cf59c85 649 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
650 &gEfiTcp4ServiceBindingProtocolGuid,\r
651 &HttpInstance->Tcp4ChildHandle\r
652 );\r
47f51a06 653\r
b659408b
ZL
654 if (EFI_ERROR (Status)) {\r
655 goto ON_ERROR;\r
656 }\r
47f51a06 657\r
b659408b
ZL
658 Status = gBS->OpenProtocol (\r
659 HttpInstance->Tcp4ChildHandle,\r
660 &gEfiTcp4ProtocolGuid,\r
661 (VOID **) &Interface,\r
7cf59c85 662 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
663 HttpInstance->Service->ControllerHandle,\r
664 EFI_OPEN_PROTOCOL_BY_DRIVER\r
665 );\r
f75a7f56 666\r
b659408b
ZL
667 if (EFI_ERROR (Status)) {\r
668 goto ON_ERROR;\r
669 }\r
47f51a06 670\r
b659408b
ZL
671 Status = gBS->OpenProtocol (\r
672 HttpInstance->Tcp4ChildHandle,\r
673 &gEfiTcp4ProtocolGuid,\r
674 (VOID **) &HttpInstance->Tcp4,\r
7cf59c85 675 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
676 HttpInstance->Handle,\r
677 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
678 );\r
679 if (EFI_ERROR(Status)) {\r
680 goto ON_ERROR;\r
681 }\r
47f51a06 682\r
b659408b
ZL
683 Status = gBS->OpenProtocol (\r
684 HttpInstance->Service->Tcp4ChildHandle,\r
685 &gEfiTcp4ProtocolGuid,\r
686 (VOID **) &Interface,\r
7cf59c85 687 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
688 HttpInstance->Handle,\r
689 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
690 );\r
691 if (EFI_ERROR(Status)) {\r
692 goto ON_ERROR;\r
693 }\r
694 } else {\r
695 //\r
696 // Create TCP6 Child.\r
697 //\r
698 Status = NetLibCreateServiceChild (\r
699 HttpInstance->Service->ControllerHandle,\r
7cf59c85 700 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
701 &gEfiTcp6ServiceBindingProtocolGuid,\r
702 &HttpInstance->Tcp6ChildHandle\r
703 );\r
47f51a06 704\r
b659408b
ZL
705 if (EFI_ERROR (Status)) {\r
706 goto ON_ERROR;\r
707 }\r
47f51a06 708\r
b659408b
ZL
709 Status = gBS->OpenProtocol (\r
710 HttpInstance->Tcp6ChildHandle,\r
711 &gEfiTcp6ProtocolGuid,\r
712 (VOID **) &Interface,\r
7cf59c85 713 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
714 HttpInstance->Service->ControllerHandle,\r
715 EFI_OPEN_PROTOCOL_BY_DRIVER\r
716 );\r
f75a7f56 717\r
b659408b
ZL
718 if (EFI_ERROR (Status)) {\r
719 goto ON_ERROR;\r
720 }\r
721\r
722 Status = gBS->OpenProtocol (\r
723 HttpInstance->Tcp6ChildHandle,\r
724 &gEfiTcp6ProtocolGuid,\r
725 (VOID **) &HttpInstance->Tcp6,\r
7cf59c85 726 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
727 HttpInstance->Handle,\r
728 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
729 );\r
f75a7f56 730\r
b659408b
ZL
731 if (EFI_ERROR(Status)) {\r
732 goto ON_ERROR;\r
f75a7f56 733 }\r
b659408b
ZL
734\r
735 Status = gBS->OpenProtocol (\r
736 HttpInstance->Service->Tcp6ChildHandle,\r
737 &gEfiTcp6ProtocolGuid,\r
738 (VOID **) &Interface,\r
7cf59c85 739 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
740 HttpInstance->Handle,\r
741 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
742 );\r
47f51a06 743\r
b659408b
ZL
744 if (EFI_ERROR(Status)) {\r
745 goto ON_ERROR;\r
746 }\r
747 }\r
f75a7f56 748\r
51b0450e
FS
749 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
750 if (HttpInstance->Url == NULL) {\r
751 Status = EFI_OUT_OF_RESOURCES;\r
752 goto ON_ERROR;\r
753 }\r
754\r
47f51a06
YT
755 return EFI_SUCCESS;\r
756\r
757ON_ERROR:\r
f75a7f56 758\r
b659408b 759 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 760 gBS->CloseProtocol (\r
b659408b 761 HttpInstance->Tcp4ChildHandle,\r
47f51a06 762 &gEfiTcp4ProtocolGuid,\r
7cf59c85 763 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
764 HttpInstance->Service->ControllerHandle\r
765 );\r
766\r
767 gBS->CloseProtocol (\r
b659408b 768 HttpInstance->Tcp4ChildHandle,\r
47f51a06 769 &gEfiTcp4ProtocolGuid,\r
7cf59c85 770 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 771 HttpInstance->Handle\r
f75a7f56
LG
772 );\r
773\r
47f51a06
YT
774 NetLibDestroyServiceChild (\r
775 HttpInstance->Service->ControllerHandle,\r
7cf59c85 776 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 777 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 778 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
779 );\r
780 }\r
f75a7f56 781\r
b659408b
ZL
782 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
783 gBS->CloseProtocol (\r
784 HttpInstance->Service->Tcp4ChildHandle,\r
785 &gEfiTcp4ProtocolGuid,\r
7cf59c85 786 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
787 HttpInstance->Handle\r
788 );\r
789 }\r
f75a7f56 790\r
b659408b
ZL
791 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
792 gBS->CloseProtocol (\r
793 HttpInstance->Tcp6ChildHandle,\r
794 &gEfiTcp6ProtocolGuid,\r
7cf59c85 795 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
796 HttpInstance->Service->ControllerHandle\r
797 );\r
47f51a06 798\r
b659408b
ZL
799 gBS->CloseProtocol (\r
800 HttpInstance->Tcp6ChildHandle,\r
801 &gEfiTcp6ProtocolGuid,\r
7cf59c85 802 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
803 HttpInstance->Handle\r
804 );\r
f75a7f56 805\r
b659408b
ZL
806 NetLibDestroyServiceChild (\r
807 HttpInstance->Service->ControllerHandle,\r
7cf59c85 808 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
809 &gEfiTcp6ServiceBindingProtocolGuid,\r
810 HttpInstance->Tcp6ChildHandle\r
811 );\r
812 }\r
f75a7f56 813\r
b659408b
ZL
814 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
815 gBS->CloseProtocol (\r
816 HttpInstance->Service->Tcp6ChildHandle,\r
817 &gEfiTcp6ProtocolGuid,\r
7cf59c85 818 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
819 HttpInstance->Handle\r
820 );\r
821 }\r
822\r
823 return EFI_UNSUPPORTED;\r
f75a7f56 824\r
47f51a06
YT
825}\r
826\r
827/**\r
828 Clean up the HTTP child, release all the resources used by it.\r
829\r
830 @param[in] HttpInstance The HTTP child to clean up.\r
831\r
832**/\r
833VOID\r
834HttpCleanProtocol (\r
835 IN HTTP_PROTOCOL *HttpInstance\r
836 )\r
837{\r
838 HttpCloseConnection (HttpInstance);\r
f75a7f56 839\r
b659408b 840 HttpCloseTcpConnCloseEvent (HttpInstance);\r
47f51a06 841\r
b347a22a
JW
842 if (HttpInstance->TimeoutEvent != NULL) {\r
843 gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
844 HttpInstance->TimeoutEvent = NULL;\r
845 }\r
846\r
47f51a06
YT
847 if (HttpInstance->CacheBody != NULL) {\r
848 FreePool (HttpInstance->CacheBody);\r
849 HttpInstance->CacheBody = NULL;\r
850 HttpInstance->NextMsg = NULL;\r
851 }\r
852\r
853 if (HttpInstance->RemoteHost != NULL) {\r
854 FreePool (HttpInstance->RemoteHost);\r
855 HttpInstance->RemoteHost = NULL;\r
856 }\r
857\r
858 if (HttpInstance->MsgParser != NULL) {\r
859 HttpFreeMsgParser (HttpInstance->MsgParser);\r
860 HttpInstance->MsgParser = NULL;\r
861 }\r
f75a7f56 862\r
51b0450e
FS
863 if (HttpInstance->Url != NULL) {\r
864 FreePool (HttpInstance->Url);\r
865 HttpInstance->Url = NULL;\r
866 }\r
f75a7f56 867\r
47f51a06
YT
868 NetMapClean (&HttpInstance->TxTokens);\r
869 NetMapClean (&HttpInstance->RxTokens);\r
870\r
45ea8a0c
JW
871 if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) {\r
872 //\r
f75a7f56 873 // Destroy the TLS instance.\r
328141fc 874 //\r
45ea8a0c 875 HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);\r
5df41311 876 HttpInstance->TlsChildHandle = NULL;\r
45ea8a0c
JW
877 }\r
878\r
b659408b 879 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
47f51a06 880 gBS->CloseProtocol (\r
b659408b 881 HttpInstance->Tcp4ChildHandle,\r
47f51a06 882 &gEfiTcp4ProtocolGuid,\r
7cf59c85 883 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
884 HttpInstance->Service->ControllerHandle\r
885 );\r
886\r
887 gBS->CloseProtocol (\r
b659408b 888 HttpInstance->Tcp4ChildHandle,\r
47f51a06 889 &gEfiTcp4ProtocolGuid,\r
7cf59c85 890 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06
YT
891 HttpInstance->Handle\r
892 );\r
f75a7f56 893\r
47f51a06
YT
894 NetLibDestroyServiceChild (\r
895 HttpInstance->Service->ControllerHandle,\r
7cf59c85 896 HttpInstance->Service->Ip4DriverBindingHandle,\r
47f51a06 897 &gEfiTcp4ServiceBindingProtocolGuid,\r
b659408b 898 HttpInstance->Tcp4ChildHandle\r
47f51a06
YT
899 );\r
900 }\r
b659408b
ZL
901\r
902 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
903 gBS->CloseProtocol (\r
904 HttpInstance->Service->Tcp4ChildHandle,\r
905 &gEfiTcp4ProtocolGuid,\r
7cf59c85 906 HttpInstance->Service->Ip4DriverBindingHandle,\r
b659408b
ZL
907 HttpInstance->Handle\r
908 );\r
f75a7f56 909 }\r
b659408b
ZL
910\r
911 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
912 gBS->CloseProtocol (\r
913 HttpInstance->Tcp6ChildHandle,\r
914 &gEfiTcp6ProtocolGuid,\r
7cf59c85 915 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
916 HttpInstance->Service->ControllerHandle\r
917 );\r
918\r
919 gBS->CloseProtocol (\r
920 HttpInstance->Tcp6ChildHandle,\r
921 &gEfiTcp6ProtocolGuid,\r
7cf59c85 922 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
923 HttpInstance->Handle\r
924 );\r
f75a7f56 925\r
b659408b
ZL
926 NetLibDestroyServiceChild (\r
927 HttpInstance->Service->ControllerHandle,\r
7cf59c85 928 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
929 &gEfiTcp6ServiceBindingProtocolGuid,\r
930 HttpInstance->Tcp6ChildHandle\r
931 );\r
932 }\r
f75a7f56 933\r
b659408b
ZL
934 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
935 gBS->CloseProtocol (\r
936 HttpInstance->Service->Tcp6ChildHandle,\r
937 &gEfiTcp6ProtocolGuid,\r
7cf59c85 938 HttpInstance->Service->Ip6DriverBindingHandle,\r
b659408b
ZL
939 HttpInstance->Handle\r
940 );\r
941 }\r
dac45de3 942\r
f75a7f56 943 TlsCloseTxRxEvent (HttpInstance);\r
47f51a06
YT
944}\r
945\r
946/**\r
947 Establish TCP connection with HTTP server.\r
948\r
949 @param[in] HttpInstance The HTTP instance private data.\r
950\r
951 @retval EFI_SUCCESS The TCP connection is established.\r
952 @retval Others Other error as indicated.\r
953\r
954**/\r
955EFI_STATUS\r
956HttpCreateConnection (\r
957 IN HTTP_PROTOCOL *HttpInstance\r
958 )\r
959{\r
960 EFI_STATUS Status;\r
961\r
47f51a06
YT
962 //\r
963 // Connect to Http server\r
964 //\r
b659408b
ZL
965 if (!HttpInstance->LocalAddressIsIPv6) {\r
966 HttpInstance->IsTcp4ConnDone = FALSE;\r
967 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
968 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
ab796d3e 969 HttpNotify (HttpEventConnectTcp, Status);\r
b659408b
ZL
970 if (EFI_ERROR (Status)) {\r
971 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
972 return Status;\r
973 }\r
f75a7f56 974\r
b659408b
ZL
975 while (!HttpInstance->IsTcp4ConnDone) {\r
976 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
977 }\r
f75a7f56 978\r
b659408b 979 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
f75a7f56 980\r
b659408b
ZL
981 } else {\r
982 HttpInstance->IsTcp6ConnDone = FALSE;\r
983 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
984 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
ab796d3e 985 HttpNotify (HttpEventConnectTcp, Status);\r
b659408b
ZL
986 if (EFI_ERROR (Status)) {\r
987 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
988 return Status;\r
989 }\r
47f51a06 990\r
b659408b
ZL
991 while(!HttpInstance->IsTcp6ConnDone) {\r
992 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
993 }\r
47f51a06 994\r
f75a7f56 995 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;\r
b659408b 996 }\r
f75a7f56 997\r
47f51a06
YT
998 if (!EFI_ERROR (Status)) {\r
999 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
1000 }\r
1001\r
1002 return Status;\r
1003}\r
1004\r
1005/**\r
1006 Close existing TCP connection.\r
1007\r
1008 @param[in] HttpInstance The HTTP instance private data.\r
1009\r
1010 @retval EFI_SUCCESS The TCP connection is closed.\r
1011 @retval Others Other error as indicated.\r
1012\r
1013**/\r
1014EFI_STATUS\r
1015HttpCloseConnection (\r
1016 IN HTTP_PROTOCOL *HttpInstance\r
1017 )\r
1018{\r
1019 EFI_STATUS Status;\r
1020\r
374ecd04 1021 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
47f51a06 1022\r
b659408b
ZL
1023 if (HttpInstance->LocalAddressIsIPv6) {\r
1024 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
1025 HttpInstance->IsTcp6CloseDone = FALSE;\r
1026 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
1027 if (EFI_ERROR (Status)) {\r
1028 return Status;\r
1029 }\r
1030\r
1031 while (!HttpInstance->IsTcp6CloseDone) {\r
1032 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
1033 }\r
f75a7f56 1034\r
b659408b
ZL
1035 } else {\r
1036 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
1037 HttpInstance->IsTcp4CloseDone = FALSE;\r
1038 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
1039 if (EFI_ERROR (Status)) {\r
1040 return Status;\r
1041 }\r
1042\r
1043 while (!HttpInstance->IsTcp4CloseDone) {\r
1044 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
1045 }\r
374ecd04 1046 }\r
b659408b 1047\r
47f51a06
YT
1048 }\r
1049\r
1050 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
374ecd04 1051 return EFI_SUCCESS;\r
47f51a06
YT
1052}\r
1053\r
1054/**\r
1055 Configure TCP4 protocol child.\r
1056\r
1057 @param[in] HttpInstance The HTTP instance private data.\r
1058 @param[in] Wrap The HTTP token's wrap data.\r
1059\r
1060 @retval EFI_SUCCESS The TCP4 protocol child is configured.\r
1061 @retval Others Other error as indicated.\r
1062\r
1063**/\r
1064EFI_STATUS\r
1065HttpConfigureTcp4 (\r
1066 IN HTTP_PROTOCOL *HttpInstance,\r
1067 IN HTTP_TOKEN_WRAP *Wrap\r
1068 )\r
1069{\r
1070 EFI_STATUS Status;\r
1071 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;\r
1072 EFI_TCP4_ACCESS_POINT *Tcp4AP;\r
1073 EFI_TCP4_OPTION *Tcp4Option;\r
47f51a06
YT
1074\r
1075 ASSERT (HttpInstance != NULL);\r
47f51a06
YT
1076\r
1077\r
1078 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1079 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
f75a7f56 1080\r
47f51a06
YT
1081 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
1082 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;\r
1083 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
1084\r
1085 Tcp4AP = &Tcp4CfgData->AccessPoint;\r
1086 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;\r
1087 if (!Tcp4AP->UseDefaultAddress) {\r
1088 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
1089 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
1090 }\r
f75a7f56 1091\r
47f51a06
YT
1092 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
1093 Tcp4AP->RemotePort = HttpInstance->RemotePort;\r
1094 Tcp4AP->ActiveFlag = TRUE;\r
1095 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);\r
1096\r
1097 Tcp4Option = Tcp4CfgData->ControlOption;\r
1098 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1099 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1100 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1101 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1102 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;\r
1103 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1104 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1105 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1106 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1107 Tcp4Option->EnableNagle = TRUE;\r
1108 Tcp4CfgData->ControlOption = Tcp4Option;\r
1109\r
1110 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);\r
1111 if (EFI_ERROR (Status)) {\r
1112 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));\r
1113 return Status;\r
1114 }\r
1115\r
b659408b
ZL
1116 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1117 if (EFI_ERROR (Status)) {\r
1118 return Status;\r
1119 }\r
1120\r
1121 Status = HttpCreateTcpTxEvent (Wrap);\r
1122 if (EFI_ERROR (Status)) {\r
1123 return Status;\r
1124 }\r
1125\r
1126 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1127\r
1128 return EFI_SUCCESS;\r
1129}\r
1130\r
1131/**\r
1132 Configure TCP6 protocol child.\r
1133\r
1134 @param[in] HttpInstance The HTTP instance private data.\r
1135 @param[in] Wrap The HTTP token's wrap data.\r
1136\r
1137 @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
1138 @retval Others Other error as indicated.\r
1139\r
1140**/\r
1141EFI_STATUS\r
1142HttpConfigureTcp6 (\r
1143 IN HTTP_PROTOCOL *HttpInstance,\r
1144 IN HTTP_TOKEN_WRAP *Wrap\r
1145 )\r
1146{\r
1147 EFI_STATUS Status;\r
1148 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
1149 EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
1150 EFI_TCP6_OPTION *Tcp6Option;\r
f75a7f56 1151\r
b659408b 1152 ASSERT (HttpInstance != NULL);\r
f75a7f56 1153\r
b659408b
ZL
1154 Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
1155 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
1156\r
1157 Tcp6CfgData->TrafficClass = 0;\r
1158 Tcp6CfgData->HopLimit = 255;\r
1159 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
f75a7f56 1160\r
b659408b
ZL
1161 Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
1162 Tcp6Ap->ActiveFlag = TRUE;\r
1163 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
1164 Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
1165 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
1166 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
1167\r
1168 Tcp6Option = Tcp6CfgData->ControlOption;\r
1169 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1170 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
1171 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
1172 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
1173 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
1174 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
1175 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
1176 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
1177 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
1178 Tcp6Option->EnableNagle = TRUE;\r
1179\r
1180 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
1181 if (EFI_ERROR (Status)) {\r
1182 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
1183 return Status;\r
1184 }\r
f75a7f56 1185\r
b659408b 1186 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
47f51a06
YT
1187 if (EFI_ERROR (Status)) {\r
1188 return Status;\r
1189 }\r
1190\r
b659408b 1191 Status = HttpCreateTcpTxEvent (Wrap);\r
47f51a06
YT
1192 if (EFI_ERROR (Status)) {\r
1193 return Status;\r
1194 }\r
1195\r
1196 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1197\r
1198 return EFI_SUCCESS;\r
f75a7f56 1199\r
47f51a06
YT
1200}\r
1201\r
1202/**\r
f75a7f56 1203 Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
dac45de3 1204 connect one TLS session if required.\r
47f51a06
YT
1205\r
1206 @param[in] HttpInstance The HTTP instance private data.\r
1207\r
1208 @retval EFI_SUCCESS The TCP connection is established.\r
1209 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.\r
1210 @retval Others Other error as indicated.\r
1211\r
1212**/\r
1213EFI_STATUS\r
1214HttpConnectTcp4 (\r
1215 IN HTTP_PROTOCOL *HttpInstance\r
1216 )\r
1217{\r
1218 EFI_STATUS Status;\r
1219 EFI_TCP4_CONNECTION_STATE Tcp4State;\r
1220\r
1221\r
a2e61982 1222 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
47f51a06
YT
1223 return EFI_NOT_READY;\r
1224 }\r
1225\r
1226 Status = HttpInstance->Tcp4->GetModeData(\r
f75a7f56
LG
1227 HttpInstance->Tcp4,\r
1228 &Tcp4State,\r
47f51a06
YT
1229 NULL,\r
1230 NULL,\r
1231 NULL,\r
1232 NULL\r
1233 );\r
1234 if (EFI_ERROR(Status)){\r
1235 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));\r
1236 return Status;\r
1237 }\r
1238\r
a2e61982
ZL
1239 if (Tcp4State == Tcp4StateEstablished) {\r
1240 return EFI_SUCCESS;\r
1241 } else if (Tcp4State > Tcp4StateEstablished ) {\r
47f51a06 1242 HttpCloseConnection(HttpInstance);\r
a2e61982 1243 }\r
47f51a06 1244\r
dac45de3
JW
1245 Status = HttpCreateConnection (HttpInstance);\r
1246 if (EFI_ERROR(Status)){\r
1247 DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status));\r
1248 return Status;\r
1249 }\r
f75a7f56 1250\r
dac45de3
JW
1251 //\r
1252 // Tls session connection.\r
1253 //\r
1254 if (HttpInstance->UseHttps) {\r
1255 if (HttpInstance->TimeoutEvent == NULL) {\r
1256 //\r
1257 // Create TimeoutEvent for TLS connection.\r
1258 //\r
1259 Status = gBS->CreateEvent (\r
1260 EVT_TIMER,\r
1261 TPL_CALLBACK,\r
1262 NULL,\r
1263 NULL,\r
1264 &HttpInstance->TimeoutEvent\r
1265 );\r
1266 if (EFI_ERROR (Status)) {\r
1267 TlsCloseTxRxEvent (HttpInstance);\r
1268 return Status;\r
1269 }\r
1270 }\r
1271\r
1272 //\r
1273 // Start the timer, and wait Timeout seconds for connection.\r
1274 //\r
1275 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1276 if (EFI_ERROR (Status)) {\r
1277 TlsCloseTxRxEvent (HttpInstance);\r
1278 return Status;\r
1279 }\r
f75a7f56 1280\r
dac45de3 1281 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1282 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1283\r
1284 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1285\r
dac45de3
JW
1286 if (EFI_ERROR (Status)) {\r
1287 TlsCloseTxRxEvent (HttpInstance);\r
1288 return Status;\r
1289 }\r
1290 }\r
1291\r
1292 return Status;\r
47f51a06
YT
1293}\r
1294\r
1295/**\r
f75a7f56 1296 Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
dac45de3 1297 connect one TLS session if required.\r
b659408b
ZL
1298\r
1299 @param[in] HttpInstance The HTTP instance private data.\r
1300\r
1301 @retval EFI_SUCCESS The TCP connection is established.\r
1302 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
1303 @retval Others Other error as indicated.\r
1304\r
1305**/\r
1306EFI_STATUS\r
1307HttpConnectTcp6 (\r
1308 IN HTTP_PROTOCOL *HttpInstance\r
1309 )\r
1310{\r
1311 EFI_STATUS Status;\r
1312 EFI_TCP6_CONNECTION_STATE Tcp6State;\r
1313\r
a2e61982 1314 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
b659408b
ZL
1315 return EFI_NOT_READY;\r
1316 }\r
1317\r
1318 Status = HttpInstance->Tcp6->GetModeData (\r
1319 HttpInstance->Tcp6,\r
1320 &Tcp6State,\r
1321 NULL,\r
1322 NULL,\r
1323 NULL,\r
1324 NULL\r
1325 );\r
f75a7f56 1326\r
b659408b
ZL
1327 if (EFI_ERROR(Status)){\r
1328 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
1329 return Status;\r
1330 }\r
1331\r
a2e61982
ZL
1332 if (Tcp6State == Tcp6StateEstablished) {\r
1333 return EFI_SUCCESS;\r
1334 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1335 HttpCloseConnection(HttpInstance);\r
b659408b
ZL
1336 }\r
1337\r
dac45de3
JW
1338 Status = HttpCreateConnection (HttpInstance);\r
1339 if (EFI_ERROR(Status)){\r
1340 DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status));\r
1341 return Status;\r
1342 }\r
f75a7f56 1343\r
dac45de3
JW
1344 //\r
1345 // Tls session connection.\r
1346 //\r
1347 if (HttpInstance->UseHttps) {\r
1348 if (HttpInstance->TimeoutEvent == NULL) {\r
1349 //\r
1350 // Create TimeoutEvent for TLS connection.\r
1351 //\r
1352 Status = gBS->CreateEvent (\r
1353 EVT_TIMER,\r
1354 TPL_CALLBACK,\r
1355 NULL,\r
1356 NULL,\r
1357 &HttpInstance->TimeoutEvent\r
1358 );\r
1359 if (EFI_ERROR (Status)) {\r
1360 TlsCloseTxRxEvent (HttpInstance);\r
1361 return Status;\r
1362 }\r
1363 }\r
1364\r
1365 //\r
1366 // Start the timer, and wait Timeout seconds for connection.\r
1367 //\r
1368 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
1369 if (EFI_ERROR (Status)) {\r
1370 TlsCloseTxRxEvent (HttpInstance);\r
1371 return Status;\r
1372 }\r
f75a7f56 1373\r
dac45de3 1374 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
ab796d3e 1375 HttpNotify (HttpEventTlsConnectSession, Status);\r
dac45de3
JW
1376\r
1377 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
f75a7f56 1378\r
dac45de3
JW
1379 if (EFI_ERROR (Status)) {\r
1380 TlsCloseTxRxEvent (HttpInstance);\r
1381 return Status;\r
1382 }\r
1383 }\r
1384\r
1385 return Status;\r
b659408b
ZL
1386}\r
1387\r
1388/**\r
dac45de3 1389 Initialize Http session.\r
b659408b
ZL
1390\r
1391 @param[in] HttpInstance The HTTP instance private data.\r
1392 @param[in] Wrap The HTTP token's wrap data.\r
dac45de3
JW
1393 @param[in] Configure The Flag indicates whether need to initialize session.\r
1394 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.\r
b659408b 1395\r
f75a7f56 1396 @retval EFI_SUCCESS The initialization of session is done.\r
b659408b
ZL
1397 @retval Others Other error as indicated.\r
1398\r
1399**/\r
1400EFI_STATUS\r
dac45de3 1401HttpInitSession (\r
b659408b 1402 IN HTTP_PROTOCOL *HttpInstance,\r
a2e61982 1403 IN HTTP_TOKEN_WRAP *Wrap,\r
dac45de3
JW
1404 IN BOOLEAN Configure,\r
1405 IN BOOLEAN TlsConfigure\r
b659408b
ZL
1406 )\r
1407{\r
1408 EFI_STATUS Status;\r
1409 ASSERT (HttpInstance != NULL);\r
1410\r
dac45de3
JW
1411 //\r
1412 // Configure Tls session.\r
1413 //\r
1414 if (TlsConfigure) {\r
1415 Status = TlsConfigureSession (HttpInstance);\r
1416 if (EFI_ERROR (Status)) {\r
1417 return Status;\r
1418 }\r
1419 }\r
1420\r
b659408b
ZL
1421 if (!HttpInstance->LocalAddressIsIPv6) {\r
1422 //\r
1423 // Configure TCP instance.\r
1424 //\r
a2e61982
ZL
1425 if (Configure) {\r
1426 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1427 if (EFI_ERROR (Status)) {\r
1428 return Status;\r
1429 }\r
b659408b 1430 }\r
a2e61982 1431\r
b659408b
ZL
1432 //\r
1433 // Connect TCP.\r
1434 //\r
1435 Status = HttpConnectTcp4 (HttpInstance);\r
1436 if (EFI_ERROR (Status)) {\r
1437 return Status;\r
1438 }\r
1439 } else {\r
1440 //\r
1441 // Configure TCP instance.\r
1442 //\r
a2e61982
ZL
1443 if (Configure) {\r
1444 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1445 if (EFI_ERROR (Status)) {\r
1446 return Status;\r
1447 }\r
b659408b 1448 }\r
a2e61982 1449\r
b659408b
ZL
1450 //\r
1451 // Connect TCP.\r
1452 //\r
1453 Status = HttpConnectTcp6 (HttpInstance);\r
1454 if (EFI_ERROR (Status)) {\r
1455 return Status;\r
1456 }\r
1457 }\r
f75a7f56 1458\r
b659408b 1459 return EFI_SUCCESS;\r
f75a7f56 1460\r
b659408b
ZL
1461}\r
1462\r
1463/**\r
dac45de3 1464 Send the HTTP or HTTPS message through TCP4 or TCP6.\r
47f51a06
YT
1465\r
1466 @param[in] HttpInstance The HTTP instance private data.\r
1467 @param[in] Wrap The HTTP token's wrap data.\r
1468 @param[in] TxString Buffer containing the HTTP message string.\r
1469 @param[in] TxStringLen Length of the HTTP message string in bytes.\r
1470\r
1471 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.\r
1472 @retval Others Other error as indicated.\r
1473\r
1474**/\r
1475EFI_STATUS\r
b659408b 1476HttpTransmitTcp (\r
47f51a06
YT
1477 IN HTTP_PROTOCOL *HttpInstance,\r
1478 IN HTTP_TOKEN_WRAP *Wrap,\r
1479 IN UINT8 *TxString,\r
1480 IN UINTN TxStringLen\r
1481 )\r
1482{\r
1483 EFI_STATUS Status;\r
b659408b 1484 EFI_TCP4_IO_TOKEN *Tx4Token;\r
47f51a06 1485 EFI_TCP4_PROTOCOL *Tcp4;\r
b659408b
ZL
1486 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1487 EFI_TCP6_PROTOCOL *Tcp6;\r
f75a7f56 1488 UINT8 *TlsRecord;\r
07bd82d4 1489 UINT16 PayloadSize;\r
dac45de3 1490 NET_FRAGMENT TempFragment;\r
07bd82d4
JW
1491 NET_FRAGMENT Fragment;\r
1492 UINTN RecordCount;\r
1493 UINTN RemainingLen;\r
dac45de3
JW
1494\r
1495 Status = EFI_SUCCESS;\r
07bd82d4
JW
1496 TlsRecord = NULL;\r
1497 PayloadSize = 0;\r
12b96a93
JW
1498 TempFragment.Len = 0;\r
1499 TempFragment.Bulk = NULL;\r
07bd82d4
JW
1500 Fragment.Len = 0;\r
1501 Fragment.Bulk = NULL;\r
1502 RecordCount = 0;\r
1503 RemainingLen = 0;\r
dac45de3
JW
1504\r
1505 //\r
1506 // Need to encrypt data.\r
1507 //\r
1508 if (HttpInstance->UseHttps) {\r
1509 //\r
07bd82d4 1510 // Allocate enough buffer for each TLS plaintext records.\r
dac45de3 1511 //\r
07bd82d4
JW
1512 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1513 if (TlsRecord == NULL) {\r
dac45de3
JW
1514 Status = EFI_OUT_OF_RESOURCES;\r
1515 return Status;\r
1516 }\r
07bd82d4 1517\r
dac45de3 1518 //\r
07bd82d4 1519 // Allocate enough buffer for all TLS ciphertext records.\r
dac45de3 1520 //\r
07bd82d4
JW
1521 RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
1522 Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
1523 if (Fragment.Bulk == NULL) {\r
1524 Status = EFI_OUT_OF_RESOURCES;\r
1525 goto ON_ERROR;\r
1526 }\r
dac45de3 1527\r
07bd82d4
JW
1528 //\r
1529 // Encrypt each TLS plaintext records.\r
1530 //\r
1531 RemainingLen = TxStringLen;\r
1532 while (RemainingLen != 0) {\r
1533 PayloadSize = (UINT16) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
f75a7f56 1534\r
07bd82d4
JW
1535 ((TLS_RECORD_HEADER *) TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
1536 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
1537 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
1538 ((TLS_RECORD_HEADER *) TlsRecord)->Length = PayloadSize;\r
1539\r
1540 CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
f75a7f56 1541\r
07bd82d4 1542 Status = TlsProcessMessage (\r
f75a7f56
LG
1543 HttpInstance,\r
1544 TlsRecord,\r
1545 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1546 EfiTlsEncrypt,\r
07bd82d4
JW
1547 &TempFragment\r
1548 );\r
1549 if (EFI_ERROR (Status)) {\r
1550 goto ON_ERROR;\r
1551 }\r
1552\r
1553 //\r
f75a7f56 1554 // Record the processed/encrypted Packet.\r
07bd82d4
JW
1555 //\r
1556 CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
1557 Fragment.Len += TempFragment.Len;\r
1558\r
1559 FreePool (TempFragment.Bulk);\r
1560 TempFragment.Len = 0;\r
1561 TempFragment.Bulk = NULL;\r
f75a7f56 1562\r
07bd82d4
JW
1563 RemainingLen -= (UINTN) PayloadSize;\r
1564 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
dac45de3 1565 }\r
07bd82d4
JW
1566\r
1567 FreePool (TlsRecord);\r
1568 TlsRecord = NULL;\r
dac45de3 1569 }\r
f75a7f56 1570\r
dac45de3 1571 if (!HttpInstance->LocalAddressIsIPv6) {\r
b659408b
ZL
1572 Tcp4 = HttpInstance->Tcp4;\r
1573 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
dac45de3
JW
1574\r
1575 if (HttpInstance->UseHttps) {\r
07bd82d4
JW
1576 Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
1577 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1578 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
dac45de3
JW
1579 } else {\r
1580 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1581 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1582 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1583 }\r
f75a7f56
LG
1584\r
1585 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1586\r
b659408b
ZL
1587 Wrap->TcpWrap.IsTxDone = FALSE;\r
1588 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1589 if (EFI_ERROR (Status)) {\r
1590 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
07bd82d4 1591 goto ON_ERROR;\r
b659408b 1592 }\r
47f51a06 1593\r
b659408b
ZL
1594 } else {\r
1595 Tcp6 = HttpInstance->Tcp6;\r
1596 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
f75a7f56 1597\r
dac45de3 1598 if (HttpInstance->UseHttps) {\r
07bd82d4
JW
1599 Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
1600 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1601 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
dac45de3
JW
1602 } else {\r
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
1606 }\r
f75a7f56 1607\r
b659408b
ZL
1608 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1609\r
1610 Wrap->TcpWrap.IsTxDone = FALSE;\r
1611 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1612 if (EFI_ERROR (Status)) {\r
1613 DEBUG ((EFI_D_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
1654 IN NET_MAP *Map,\r
1655 IN NET_MAP_ITEM *Item,\r
1656 IN VOID *Context\r
1657 )\r
1658{\r
1659 EFI_HTTP_TOKEN *Token;\r
1660 EFI_HTTP_TOKEN *TokenInItem;\r
1661\r
1662 Token = (EFI_HTTP_TOKEN *) Context;\r
1663 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1664\r
1665 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
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
1686 IN NET_MAP *Map,\r
1687 IN NET_MAP_ITEM *Item,\r
1688 IN VOID *Context\r
1689 )\r
1690{\r
1691 HTTP_TOKEN_WRAP *ValueInItem;\r
1692\r
1693 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
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
1717 IN NET_MAP *Map,\r
1718 IN NET_MAP_ITEM *Item,\r
1719 IN VOID *Context\r
1720 )\r
1721{\r
1722 HTTP_TOKEN_WRAP *ValueInItem;\r
1723 EFI_STATUS Status;\r
19c25725 1724 CHAR8 *RequestMsg;\r
47f51a06 1725 CHAR8 *Url;\r
b9679cd7 1726 UINTN UrlSize;\r
19c25725 1727 UINTN RequestMsgSize;\r
47f51a06 1728\r
63f1d6a4
JW
1729 RequestMsg = NULL;\r
1730\r
47f51a06
YT
1731 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
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
SZ
1739 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
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
47f51a06 1751 ValueInItem->HttpToken->Message,\r
f58554fc 1752 Url,\r
19c25725
NH
1753 &RequestMsg,\r
1754 &RequestMsgSize\r
47f51a06
YT
1755 );\r
1756 FreePool (Url);\r
f58554fc 1757\r
63f1d6a4 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
19c25725
NH
1770 (UINT8*) RequestMsg,\r
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
1792 IN NET_MAP *Map,\r
1793 IN NET_MAP_ITEM *Item,\r
1794 IN VOID *Context\r
1795 )\r
1796{\r
1797 //\r
1798 // Process the queued HTTP response.\r
1799 //\r
1800 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
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
1817 IN HTTP_PROTOCOL *HttpInstance,\r
1818 IN OUT UINTN *SizeofHeaders,\r
b347a22a
JW
1819 IN OUT UINTN *BufferSize,\r
1820 IN EFI_EVENT Timeout\r
b659408b
ZL
1821 )\r
1822{\r
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
dac45de3 1831 NET_FRAGMENT Fragment;\r
b659408b
ZL
1832\r
1833 ASSERT (HttpInstance != NULL);\r
1834\r
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
1860 Rx4Token = &HttpInstance->Rx4Token;\r
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
1873 HttpInstance->IsRxDone = FALSE;\r
1874 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1875 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1876 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1877 if (EFI_ERROR (Status)) {\r
1878 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
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
JW
1900 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1901 Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
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
1910 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
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
dac45de3
JW
1936 *HttpHeaders = Buffer;\r
1937 *SizeofHeaders = *BufferSize;\r
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
dac45de3 1943 };\r
f75a7f56 1944\r
dac45de3
JW
1945 //\r
1946 // Free the buffer.\r
1947 //\r
1948 if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1949 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1950 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1951 Fragment.Bulk = NULL;\r
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
JW
1959 if (!HttpInstance->UseHttps) {\r
1960 Rx6Token = &HttpInstance->Rx6Token;\r
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
1973 HttpInstance->IsRxDone = FALSE;\r
1974 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1975 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1976 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1977 if (EFI_ERROR (Status)) {\r
1978 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
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
JW
2000 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
2001 Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
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
2010 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
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
dac45de3
JW
2036 *HttpHeaders = Buffer;\r
2037 *SizeofHeaders = *BufferSize;\r
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
dac45de3
JW
2043 };\r
2044\r
2045 //\r
2046 // Free the buffer.\r
2047 //\r
2048 if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2049 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2050 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2051 Fragment.Bulk = NULL;\r
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
2082 IN HTTP_TOKEN_WRAP *Wrap,\r
30526a51 2083 IN EFI_HTTP_MESSAGE *HttpMsg\r
b659408b
ZL
2084 )\r
2085{\r
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
f75a7f56 2092\r
b659408b
ZL
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
ZL
2105 if (HttpInstance->LocalAddressIsIPv6) {\r
2106 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
6893b16f
JW
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
b659408b
ZL
2109 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
2110 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
2111\r
2112 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
2113 if (EFI_ERROR (Status)) {\r
2114 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
2115 return Status;\r
2116 }\r
b659408b
ZL
2117 } else {\r
2118 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
6893b16f
JW
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
b659408b 2121 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
f75a7f56 2122\r
b659408b
ZL
2123 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
2124 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
2125 if (EFI_ERROR (Status)) {\r
2126 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
2127 return Status;\r
2128 }\r
2129 }\r
2130\r
2131 return EFI_SUCCESS;\r
2132\r
2133}\r
2134\r
2135/**\r
2136 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
2137\r
2138 @param[in] Wrap Pointer to HTTP token's wrap data.\r
f75a7f56 2139\r
b659408b
ZL
2140**/\r
2141VOID\r
2142HttpTcpTokenCleanup (\r
2143 IN HTTP_TOKEN_WRAP *Wrap\r
2144 )\r
f75a7f56 2145{\r
b659408b
ZL
2146 HTTP_PROTOCOL *HttpInstance;\r
2147 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2148 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2149\r
1b96428d 2150 ASSERT (Wrap != NULL);\r
b659408b
ZL
2151 HttpInstance = Wrap->HttpInstance;\r
2152 Rx4Token = NULL;\r
2153 Rx6Token = NULL;\r
f75a7f56 2154\r
b659408b 2155 if (HttpInstance->LocalAddressIsIPv6) {\r
1b96428d 2156 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
f75a7f56 2157\r
59844e12
JW
2158 if (Rx6Token->CompletionToken.Event != NULL) {\r
2159 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2160 Rx6Token->CompletionToken.Event = NULL;\r
b659408b
ZL
2161 }\r
2162\r
59844e12 2163 FreePool (Wrap);\r
b659408b
ZL
2164\r
2165 Rx6Token = &HttpInstance->Rx6Token;\r
f75a7f56 2166\r
59844e12
JW
2167 if (Rx6Token->CompletionToken.Event != NULL) {\r
2168 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2169 Rx6Token->CompletionToken.Event = NULL;\r
2170 }\r
f75a7f56 2171\r
b659408b
ZL
2172 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2173 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2174 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2175 }\r
f75a7f56 2176\r
b659408b 2177 } else {\r
1b96428d 2178 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
f75a7f56 2179\r
59844e12
JW
2180 if (Rx4Token->CompletionToken.Event != NULL) {\r
2181 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2182 Rx4Token->CompletionToken.Event = NULL;\r
1b96428d 2183 }\r
f75a7f56 2184\r
1b96428d
ZL
2185 FreePool (Wrap);\r
2186\r
59844e12
JW
2187 Rx4Token = &HttpInstance->Rx4Token;\r
2188\r
2189 if (Rx4Token->CompletionToken.Event != NULL) {\r
2190 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2191 Rx4Token->CompletionToken.Event = NULL;\r
b659408b 2192 }\r
f75a7f56
LG
2193\r
2194\r
b659408b
ZL
2195 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2196 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2197 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2198 }\r
2199 }\r
2200\r
2201}\r
ab796d3e
HL
2202\r
2203/**\r
2204 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.\r
2205\r
2206 @param[in] Event The event that occurs in the current state.\r
2207 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.\r
2208\r
2209**/\r
2210VOID\r
2211HttpNotify (\r
2212 IN EDKII_HTTP_CALLBACK_EVENT Event,\r
2213 IN EFI_STATUS EventStatus\r
2214 )\r
2215{\r
2216 EFI_STATUS Status;\r
2217 EFI_HANDLE *Handles;\r
2218 UINTN Index;\r
2219 UINTN HandleCount;\r
2220 EFI_HANDLE Handle;\r
2221 EDKII_HTTP_CALLBACK_PROTOCOL *HttpCallback;\r
2222\r
2223 DEBUG ((DEBUG_INFO, "HttpNotify: Event - %d, EventStatus - %r\n", Event, EventStatus));\r
2224\r
2225 Handles = NULL;\r
2226 HandleCount = 0;\r
2227 Status = gBS->LocateHandleBuffer (\r
2228 ByProtocol,\r
2229 &gEdkiiHttpCallbackProtocolGuid,\r
2230 NULL,\r
2231 &HandleCount,\r
2232 &Handles\r
2233 );\r
2234 if (Status == EFI_SUCCESS) {\r
2235 for (Index = 0; Index < HandleCount; Index++) {\r
2236 Handle = Handles[Index];\r
2237 Status = gBS->HandleProtocol (\r
2238 Handle,\r
2239 &gEdkiiHttpCallbackProtocolGuid,\r
2240 (VOID **) &HttpCallback\r
2241 );\r
2242 if (Status == EFI_SUCCESS) {\r
2243 DEBUG ((DEBUG_INFO, "HttpNotify: Notifying %p\n", HttpCallback));\r
2244 HttpCallback->Callback (\r
2245 HttpCallback,\r
2246 Event,\r
2247 EventStatus\r
2248 );\r
2249 }\r
2250 }\r
2251 FreePool (Handles);\r
2252 }\r
2253}\r