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