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