]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg/HttpDxe: fix read memory access overflow in HTTPBoot.
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
... / ...
CommitLineData
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
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
19 The common notify function used in HTTP driver.\r
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
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
41\r
42 @param[in] Context The context.\r
43\r
44**/\r
45VOID\r
46EFIAPI\r
47HttpTcpTransmitNotifyDpc (\r
48 IN VOID *Context\r
49 )\r
50{\r
51 HTTP_TOKEN_WRAP *Wrap;\r
52 HTTP_PROTOCOL *HttpInstance;\r
53\r
54 if (Context == NULL) {\r
55 return ;\r
56 }\r
57\r
58 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
59 HttpInstance = Wrap->HttpInstance;\r
60\r
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
71\r
72 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
73 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
74 }\r
75\r
76 } else {\r
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
78 gBS->SignalEvent (Wrap->HttpToken->Event);\r
79\r
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
86\r
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
89 }\r
90 }\r
91\r
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
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
122/**\r
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
124\r
125 @param[in] Context The context.\r
126\r
127**/\r
128VOID\r
129EFIAPI\r
130HttpTcpReceiveNotifyDpc (\r
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
139 BOOLEAN UsingIpv6;\r
140\r
141 if (Context == NULL) {\r
142 return ;\r
143 }\r
144\r
145 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
146 HttpInstance = Wrap->HttpInstance;\r
147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
148\r
149 if (UsingIpv6) {\r
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
151 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
152\r
153 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
154 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status));\r
155 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
156 gBS->SignalEvent (Wrap->HttpToken->Event);\r
157\r
158 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
159 if (Item != NULL) {\r
160 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
161 }\r
162\r
163 FreePool (Wrap);\r
164 Wrap = NULL;\r
165\r
166 return ;\r
167 }\r
168\r
169 } else {\r
170 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
171 Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;\r
172\r
173 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
174 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status));\r
175 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
176 gBS->SignalEvent (Wrap->HttpToken->Event);\r
177\r
178 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
179 if (Item != NULL) {\r
180 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
181 }\r
182\r
183 FreePool (Wrap);\r
184 Wrap = NULL;\r
185\r
186 return ;\r
187 }\r
188 }\r
189\r
190 //\r
191 // Check whether we receive a complete HTTP message.\r
192 //\r
193 ASSERT (HttpInstance->MsgParser != NULL);\r
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
199\r
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
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
233 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg -\r
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
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
259\r
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
267\r
268 FreePool (Wrap);\r
269 Wrap = NULL;\r
270}\r
271\r
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
292/**\r
293 Create events for the TCP connection token and TCP close token.\r
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
302HttpCreateTcpConnCloseEvent (\r
303 IN HTTP_PROTOCOL *HttpInstance\r
304 )\r
305{\r
306 EFI_STATUS Status;\r
307\r
308 if (!HttpInstance->LocalAddressIsIPv6) {\r
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
316 &HttpInstance->IsTcp4ConnDone,\r
317 &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
318 );\r
319 if (EFI_ERROR (Status)) {\r
320 goto ERROR;\r
321 }\r
322\r
323 //\r
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
336\r
337 } else {\r
338 //\r
339 // Create events for variuos asynchronous operations.\r
340 //\r
341 Status = gBS->CreateEvent (\r
342 EVT_NOTIFY_SIGNAL,\r
343 TPL_NOTIFY,\r
344 HttpCommonNotify,\r
345 &HttpInstance->IsTcp6ConnDone,\r
346 &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
347 );\r
348 if (EFI_ERROR (Status)) {\r
349 goto ERROR;\r
350 }\r
351\r
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
366\r
367 return EFI_SUCCESS;\r
368\r
369ERROR:\r
370 //\r
371 // Error handling\r
372 //\r
373 HttpCloseTcpConnCloseEvent (HttpInstance);\r
374\r
375 return Status;\r
376}\r
377\r
378\r
379/**\r
380 Close events in the TCP connection token and TCP close token.\r
381\r
382 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
383\r
384**/\r
385VOID\r
386HttpCloseTcpConnCloseEvent (\r
387 IN HTTP_PROTOCOL *HttpInstance\r
388 )\r
389{\r
390 ASSERT (HttpInstance != NULL);\r
391\r
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
397\r
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
414\r
415}\r
416\r
417/**\r
418 Create event for the TCP transmit token.\r
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
427HttpCreateTcpTxEvent (\r
428 IN HTTP_TOKEN_WRAP *Wrap\r
429 )\r
430{\r
431 EFI_STATUS Status;\r
432 HTTP_PROTOCOL *HttpInstance;\r
433 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
434\r
435 HttpInstance = Wrap->HttpInstance;\r
436 TcpWrap = &Wrap->TcpWrap;\r
437\r
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
446 if (EFI_ERROR (Status)) {\r
447 return Status;\r
448 }\r
449\r
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
455\r
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
467\r
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
473\r
474 }\r
475\r
476 return EFI_SUCCESS;\r
477}\r
478\r
479/**\r
480 Create event for the TCP receive token which is used to receive HTTP header.\r
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
489HttpCreateTcpRxEventForHeader (\r
490 IN HTTP_PROTOCOL *HttpInstance\r
491 )\r
492{\r
493 EFI_STATUS Status;\r
494\r
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
506\r
507 HttpInstance->Rx4Data.FragmentCount = 1;\r
508 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
509 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
510\r
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
526\r
527 }\r
528\r
529\r
530 return EFI_SUCCESS;\r
531}\r
532\r
533/**\r
534 Create event for the TCP receive token which is used to receive HTTP body.\r
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
543HttpCreateTcpRxEvent (\r
544 IN HTTP_TOKEN_WRAP *Wrap\r
545 )\r
546{\r
547 EFI_STATUS Status;\r
548 HTTP_PROTOCOL *HttpInstance;\r
549 HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
550\r
551 HttpInstance = Wrap->HttpInstance;\r
552 TcpWrap = &Wrap->TcpWrap;\r
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
564\r
565 TcpWrap->Rx4Data.FragmentCount = 1;\r
566 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
567 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
568\r
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
576 );\r
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
584 }\r
585\r
586 return EFI_SUCCESS;\r
587}\r
588\r
589/**\r
590 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
591\r
592 @param[in] Wrap Pointer to HTTP token's wrap data.\r
593\r
594**/\r
595VOID\r
596HttpCloseTcpRxEvent (\r
597 IN HTTP_TOKEN_WRAP *Wrap\r
598 )\r
599{\r
600 HTTP_PROTOCOL *HttpInstance;\r
601\r
602 ASSERT (Wrap != NULL);\r
603 HttpInstance = Wrap->HttpInstance;\r
604\r
605 if (HttpInstance->LocalAddressIsIPv6) {\r
606 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
607 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
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
615 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
616 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
617 }\r
618\r
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
624}\r
625\r
626/**\r
627 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
628\r
629 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
630 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
631\r
632 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.\r
633 @retval Others Other error as indicated.\r
634\r
635**/\r
636EFI_STATUS\r
637HttpInitProtocol (\r
638 IN OUT HTTP_PROTOCOL *HttpInstance,\r
639 IN BOOLEAN IpVersion\r
640 )\r
641{\r
642 EFI_STATUS Status;\r
643 VOID *Interface;\r
644 BOOLEAN UsingIpv6;\r
645\r
646 ASSERT (HttpInstance != NULL);\r
647 UsingIpv6 = IpVersion;\r
648\r
649 if (!UsingIpv6) {\r
650 //\r
651 // Create TCP4 child.\r
652 //\r
653 Status = NetLibCreateServiceChild (\r
654 HttpInstance->Service->ControllerHandle,\r
655 HttpInstance->Service->Ip4DriverBindingHandle,\r
656 &gEfiTcp4ServiceBindingProtocolGuid,\r
657 &HttpInstance->Tcp4ChildHandle\r
658 );\r
659\r
660 if (EFI_ERROR (Status)) {\r
661 goto ON_ERROR;\r
662 }\r
663\r
664 Status = gBS->OpenProtocol (\r
665 HttpInstance->Tcp4ChildHandle,\r
666 &gEfiTcp4ProtocolGuid,\r
667 (VOID **) &Interface,\r
668 HttpInstance->Service->Ip4DriverBindingHandle,\r
669 HttpInstance->Service->ControllerHandle,\r
670 EFI_OPEN_PROTOCOL_BY_DRIVER\r
671 );\r
672\r
673 if (EFI_ERROR (Status)) {\r
674 goto ON_ERROR;\r
675 }\r
676\r
677 Status = gBS->OpenProtocol (\r
678 HttpInstance->Tcp4ChildHandle,\r
679 &gEfiTcp4ProtocolGuid,\r
680 (VOID **) &HttpInstance->Tcp4,\r
681 HttpInstance->Service->Ip4DriverBindingHandle,\r
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
688\r
689 Status = gBS->OpenProtocol (\r
690 HttpInstance->Service->Tcp4ChildHandle,\r
691 &gEfiTcp4ProtocolGuid,\r
692 (VOID **) &Interface,\r
693 HttpInstance->Service->Ip4DriverBindingHandle,\r
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
706 HttpInstance->Service->Ip6DriverBindingHandle,\r
707 &gEfiTcp6ServiceBindingProtocolGuid,\r
708 &HttpInstance->Tcp6ChildHandle\r
709 );\r
710\r
711 if (EFI_ERROR (Status)) {\r
712 goto ON_ERROR;\r
713 }\r
714\r
715 Status = gBS->OpenProtocol (\r
716 HttpInstance->Tcp6ChildHandle,\r
717 &gEfiTcp6ProtocolGuid,\r
718 (VOID **) &Interface,\r
719 HttpInstance->Service->Ip6DriverBindingHandle,\r
720 HttpInstance->Service->ControllerHandle,\r
721 EFI_OPEN_PROTOCOL_BY_DRIVER\r
722 );\r
723\r
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
732 HttpInstance->Service->Ip6DriverBindingHandle,\r
733 HttpInstance->Handle,\r
734 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
735 );\r
736\r
737 if (EFI_ERROR(Status)) {\r
738 goto ON_ERROR;\r
739 }\r
740\r
741 Status = gBS->OpenProtocol (\r
742 HttpInstance->Service->Tcp6ChildHandle,\r
743 &gEfiTcp6ProtocolGuid,\r
744 (VOID **) &Interface,\r
745 HttpInstance->Service->Ip6DriverBindingHandle,\r
746 HttpInstance->Handle,\r
747 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
748 );\r
749\r
750 if (EFI_ERROR(Status)) {\r
751 goto ON_ERROR;\r
752 }\r
753 }\r
754\r
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
761 return EFI_SUCCESS;\r
762\r
763ON_ERROR:\r
764\r
765 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
766 gBS->CloseProtocol (\r
767 HttpInstance->Tcp4ChildHandle,\r
768 &gEfiTcp4ProtocolGuid,\r
769 HttpInstance->Service->Ip4DriverBindingHandle,\r
770 HttpInstance->Service->ControllerHandle\r
771 );\r
772\r
773 gBS->CloseProtocol (\r
774 HttpInstance->Tcp4ChildHandle,\r
775 &gEfiTcp4ProtocolGuid,\r
776 HttpInstance->Service->Ip4DriverBindingHandle,\r
777 HttpInstance->Handle\r
778 );\r
779\r
780 NetLibDestroyServiceChild (\r
781 HttpInstance->Service->ControllerHandle,\r
782 HttpInstance->Service->Ip4DriverBindingHandle,\r
783 &gEfiTcp4ServiceBindingProtocolGuid,\r
784 HttpInstance->Tcp4ChildHandle\r
785 );\r
786 }\r
787\r
788 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
789 gBS->CloseProtocol (\r
790 HttpInstance->Service->Tcp4ChildHandle,\r
791 &gEfiTcp4ProtocolGuid,\r
792 HttpInstance->Service->Ip4DriverBindingHandle,\r
793 HttpInstance->Handle\r
794 );\r
795 }\r
796\r
797 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
798 gBS->CloseProtocol (\r
799 HttpInstance->Tcp6ChildHandle,\r
800 &gEfiTcp6ProtocolGuid,\r
801 HttpInstance->Service->Ip6DriverBindingHandle,\r
802 HttpInstance->Service->ControllerHandle\r
803 );\r
804\r
805 gBS->CloseProtocol (\r
806 HttpInstance->Tcp6ChildHandle,\r
807 &gEfiTcp6ProtocolGuid,\r
808 HttpInstance->Service->Ip6DriverBindingHandle,\r
809 HttpInstance->Handle\r
810 );\r
811\r
812 NetLibDestroyServiceChild (\r
813 HttpInstance->Service->ControllerHandle,\r
814 HttpInstance->Service->Ip6DriverBindingHandle,\r
815 &gEfiTcp6ServiceBindingProtocolGuid,\r
816 HttpInstance->Tcp6ChildHandle\r
817 );\r
818 }\r
819\r
820 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
821 gBS->CloseProtocol (\r
822 HttpInstance->Service->Tcp6ChildHandle,\r
823 &gEfiTcp6ProtocolGuid,\r
824 HttpInstance->Service->Ip6DriverBindingHandle,\r
825 HttpInstance->Handle\r
826 );\r
827 }\r
828\r
829 return EFI_UNSUPPORTED;\r
830\r
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
845\r
846 HttpCloseTcpConnCloseEvent (HttpInstance);\r
847\r
848 if (HttpInstance->TimeoutEvent != NULL) {\r
849 gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
850 HttpInstance->TimeoutEvent = NULL;\r
851 }\r
852\r
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
868\r
869 if (HttpInstance->Url != NULL) {\r
870 FreePool (HttpInstance->Url);\r
871 HttpInstance->Url = NULL;\r
872 }\r
873\r
874 NetMapClean (&HttpInstance->TxTokens);\r
875 NetMapClean (&HttpInstance->RxTokens);\r
876\r
877 if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) {\r
878 //\r
879 // Destroy the TLS instance.\r
880 //\r
881 HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);\r
882 }\r
883\r
884 if (HttpInstance->Tcp4ChildHandle != NULL) {\r
885 gBS->CloseProtocol (\r
886 HttpInstance->Tcp4ChildHandle,\r
887 &gEfiTcp4ProtocolGuid,\r
888 HttpInstance->Service->Ip4DriverBindingHandle,\r
889 HttpInstance->Service->ControllerHandle\r
890 );\r
891\r
892 gBS->CloseProtocol (\r
893 HttpInstance->Tcp4ChildHandle,\r
894 &gEfiTcp4ProtocolGuid,\r
895 HttpInstance->Service->Ip4DriverBindingHandle,\r
896 HttpInstance->Handle\r
897 );\r
898\r
899 NetLibDestroyServiceChild (\r
900 HttpInstance->Service->ControllerHandle,\r
901 HttpInstance->Service->Ip4DriverBindingHandle,\r
902 &gEfiTcp4ServiceBindingProtocolGuid,\r
903 HttpInstance->Tcp4ChildHandle\r
904 );\r
905 }\r
906\r
907 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
908 gBS->CloseProtocol (\r
909 HttpInstance->Service->Tcp4ChildHandle,\r
910 &gEfiTcp4ProtocolGuid,\r
911 HttpInstance->Service->Ip4DriverBindingHandle,\r
912 HttpInstance->Handle\r
913 );\r
914 }\r
915\r
916 if (HttpInstance->Tcp6ChildHandle != NULL) {\r
917 gBS->CloseProtocol (\r
918 HttpInstance->Tcp6ChildHandle,\r
919 &gEfiTcp6ProtocolGuid,\r
920 HttpInstance->Service->Ip6DriverBindingHandle,\r
921 HttpInstance->Service->ControllerHandle\r
922 );\r
923\r
924 gBS->CloseProtocol (\r
925 HttpInstance->Tcp6ChildHandle,\r
926 &gEfiTcp6ProtocolGuid,\r
927 HttpInstance->Service->Ip6DriverBindingHandle,\r
928 HttpInstance->Handle\r
929 );\r
930\r
931 NetLibDestroyServiceChild (\r
932 HttpInstance->Service->ControllerHandle,\r
933 HttpInstance->Service->Ip6DriverBindingHandle,\r
934 &gEfiTcp6ServiceBindingProtocolGuid,\r
935 HttpInstance->Tcp6ChildHandle\r
936 );\r
937 }\r
938\r
939 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
940 gBS->CloseProtocol (\r
941 HttpInstance->Service->Tcp6ChildHandle,\r
942 &gEfiTcp6ProtocolGuid,\r
943 HttpInstance->Service->Ip6DriverBindingHandle,\r
944 HttpInstance->Handle\r
945 );\r
946 }\r
947\r
948 TlsCloseTxRxEvent (HttpInstance);\r
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
967 //\r
968 // Connect to Http server\r
969 //\r
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
978\r
979 while (!HttpInstance->IsTcp4ConnDone) {\r
980 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
981 }\r
982\r
983 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
984\r
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
993\r
994 while(!HttpInstance->IsTcp6ConnDone) {\r
995 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
996 }\r
997\r
998 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;\r
999 }\r
1000\r
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
1024 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
1025\r
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
1037\r
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
1049 }\r
1050\r
1051 }\r
1052\r
1053 HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
1054 return EFI_SUCCESS;\r
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
1077\r
1078 ASSERT (HttpInstance != NULL);\r
1079\r
1080\r
1081 Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
1082 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
1083\r
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
1094\r
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
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
1154\r
1155 ASSERT (HttpInstance != NULL);\r
1156\r
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
1163\r
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
1188\r
1189 Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
1190 if (EFI_ERROR (Status)) {\r
1191 return Status;\r
1192 }\r
1193\r
1194 Status = HttpCreateTcpTxEvent (Wrap);\r
1195 if (EFI_ERROR (Status)) {\r
1196 return Status;\r
1197 }\r
1198\r
1199 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
1200\r
1201 return EFI_SUCCESS;\r
1202\r
1203}\r
1204\r
1205/**\r
1206 Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
1207 connect one TLS session if required.\r
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
1225 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
1226 return EFI_NOT_READY;\r
1227 }\r
1228\r
1229 Status = HttpInstance->Tcp4->GetModeData(\r
1230 HttpInstance->Tcp4,\r
1231 &Tcp4State,\r
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
1242 if (Tcp4State == Tcp4StateEstablished) {\r
1243 return EFI_SUCCESS;\r
1244 } else if (Tcp4State > Tcp4StateEstablished ) {\r
1245 HttpCloseConnection(HttpInstance);\r
1246 }\r
1247\r
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
1253\r
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
1283\r
1284 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
1285\r
1286 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
1287\r
1288 if (EFI_ERROR (Status)) {\r
1289 TlsCloseTxRxEvent (HttpInstance);\r
1290 return Status;\r
1291 }\r
1292 }\r
1293\r
1294 return Status;\r
1295}\r
1296\r
1297/**\r
1298 Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
1299 connect one TLS session if required.\r
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
1316 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
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
1328\r
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
1334 if (Tcp6State == Tcp6StateEstablished) {\r
1335 return EFI_SUCCESS;\r
1336 } else if (Tcp6State > Tcp6StateEstablished ) {\r
1337 HttpCloseConnection(HttpInstance);\r
1338 }\r
1339\r
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
1345\r
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
1375\r
1376 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
1377\r
1378 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
1379\r
1380 if (EFI_ERROR (Status)) {\r
1381 TlsCloseTxRxEvent (HttpInstance);\r
1382 return Status;\r
1383 }\r
1384 }\r
1385\r
1386 return Status;\r
1387}\r
1388\r
1389/**\r
1390 Initialize Http session.\r
1391\r
1392 @param[in] HttpInstance The HTTP instance private data.\r
1393 @param[in] Wrap The HTTP token's wrap data.\r
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
1396\r
1397 @retval EFI_SUCCESS The initialization of session is done.\r
1398 @retval Others Other error as indicated.\r
1399\r
1400**/\r
1401EFI_STATUS\r
1402HttpInitSession (\r
1403 IN HTTP_PROTOCOL *HttpInstance,\r
1404 IN HTTP_TOKEN_WRAP *Wrap,\r
1405 IN BOOLEAN Configure,\r
1406 IN BOOLEAN TlsConfigure\r
1407 )\r
1408{\r
1409 EFI_STATUS Status;\r
1410 ASSERT (HttpInstance != NULL);\r
1411\r
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
1422 if (!HttpInstance->LocalAddressIsIPv6) {\r
1423 //\r
1424 // Configure TCP instance.\r
1425 //\r
1426 if (Configure) {\r
1427 Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
1428 if (EFI_ERROR (Status)) {\r
1429 return Status;\r
1430 }\r
1431 }\r
1432\r
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
1444 if (Configure) {\r
1445 Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
1446 if (EFI_ERROR (Status)) {\r
1447 return Status;\r
1448 }\r
1449 }\r
1450\r
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
1459\r
1460 return EFI_SUCCESS;\r
1461\r
1462}\r
1463\r
1464/**\r
1465 Send the HTTP or HTTPS message through TCP4 or TCP6.\r
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
1477HttpTransmitTcp (\r
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
1485 EFI_TCP4_IO_TOKEN *Tx4Token;\r
1486 EFI_TCP4_PROTOCOL *Tcp4;\r
1487 EFI_TCP6_IO_TOKEN *Tx6Token;\r
1488 EFI_TCP6_PROTOCOL *Tcp6;\r
1489 UINT8 *TlsRecord;\r
1490 UINT16 PayloadSize;\r
1491 NET_FRAGMENT TempFragment;\r
1492 NET_FRAGMENT Fragment;\r
1493 UINTN RecordCount;\r
1494 UINTN RemainingLen;\r
1495\r
1496 Status = EFI_SUCCESS;\r
1497 TlsRecord = NULL;\r
1498 PayloadSize = 0;\r
1499 TempFragment.Len = 0;\r
1500 TempFragment.Bulk = NULL;\r
1501 Fragment.Len = 0;\r
1502 Fragment.Bulk = NULL;\r
1503 RecordCount = 0;\r
1504 RemainingLen = 0;\r
1505\r
1506 //\r
1507 // Need to encrypt data.\r
1508 //\r
1509 if (HttpInstance->UseHttps) {\r
1510 //\r
1511 // Allocate enough buffer for each TLS plaintext records.\r
1512 //\r
1513 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1514 if (TlsRecord == NULL) {\r
1515 Status = EFI_OUT_OF_RESOURCES;\r
1516 return Status;\r
1517 }\r
1518\r
1519 //\r
1520 // Allocate enough buffer for all TLS ciphertext records.\r
1521 //\r
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
1528\r
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
1535\r
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
1542\r
1543 Status = TlsProcessMessage (\r
1544 HttpInstance,\r
1545 TlsRecord,\r
1546 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1547 EfiTlsEncrypt,\r
1548 &TempFragment\r
1549 );\r
1550 if (EFI_ERROR (Status)) {\r
1551 goto ON_ERROR;\r
1552 }\r
1553\r
1554 //\r
1555 // Record the processed/encrypted Packet.\r
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
1563\r
1564 RemainingLen -= (UINTN) PayloadSize;\r
1565 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1566 }\r
1567\r
1568 FreePool (TlsRecord);\r
1569 TlsRecord = NULL;\r
1570 }\r
1571\r
1572 if (!HttpInstance->LocalAddressIsIPv6) {\r
1573 Tcp4 = HttpInstance->Tcp4;\r
1574 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1575\r
1576 if (HttpInstance->UseHttps) {\r
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
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
1585\r
1586 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1587\r
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
1592 goto ON_ERROR;\r
1593 }\r
1594\r
1595 } else {\r
1596 Tcp6 = HttpInstance->Tcp6;\r
1597 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
1598\r
1599 if (HttpInstance->UseHttps) {\r
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
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
1608\r
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
1615 goto ON_ERROR;\r
1616 }\r
1617 }\r
1618\r
1619 return Status;\r
1620\r
1621ON_ERROR:\r
1622\r
1623 if (HttpInstance->UseHttps) {\r
1624 if (TlsRecord != NULL) {\r
1625 FreePool (TlsRecord);\r
1626 TlsRecord = NULL;\r
1627 }\r
1628\r
1629 if (Fragment.Bulk != NULL) {\r
1630 FreePool (Fragment.Bulk);\r
1631 Fragment.Bulk = NULL;\r
1632 }\r
1633 }\r
1634\r
1635 return Status;\r
1636}\r
1637\r
1638/**\r
1639 Check whether the user's token or event has already\r
1640 been enqueue on HTTP Tx or Rx Token list.\r
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
1674 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
1675\r
1676 @param[in] Map The container of Tx4Token or Tx6Token.\r
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
1699\r
1700 return EFI_SUCCESS;\r
1701}\r
1702\r
1703/**\r
1704 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.\r
1705\r
1706 @param[in] Map The container of Tx4Token or Tx6Token.\r
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
1725 CHAR8 *RequestMsg;\r
1726 CHAR8 *Url;\r
1727 UINTN UrlSize;\r
1728 UINTN RequestMsgSize;\r
1729\r
1730 RequestMsg = NULL;\r
1731\r
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
1740 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
1741 Url = AllocatePool (UrlSize);\r
1742 if (Url == NULL) {\r
1743 return EFI_OUT_OF_RESOURCES;\r
1744 }\r
1745\r
1746 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
1747\r
1748 //\r
1749 // Create request message.\r
1750 //\r
1751 Status = HttpGenRequestMessage (\r
1752 ValueInItem->HttpToken->Message,\r
1753 Url,\r
1754 &RequestMsg,\r
1755 &RequestMsgSize\r
1756 );\r
1757 FreePool (Url);\r
1758\r
1759 if (EFI_ERROR (Status) || NULL == RequestMsg){\r
1760 return Status;\r
1761 }\r
1762\r
1763 ASSERT (RequestMsg != NULL);\r
1764\r
1765 //\r
1766 // Transmit the request message.\r
1767 //\r
1768 Status = HttpTransmitTcp (\r
1769 ValueInItem->HttpInstance,\r
1770 ValueInItem,\r
1771 (UINT8*) RequestMsg,\r
1772 RequestMsgSize\r
1773 );\r
1774 FreePool (RequestMsg);\r
1775 return Status;\r
1776}\r
1777\r
1778/**\r
1779 Receive the HTTP response by processing the associated HTTP token.\r
1780\r
1781 @param[in] Map The container of Rx4Token or Rx6Token.\r
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
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
1810 @param[in] Timeout The time to wait for receiving the header packet.\r
1811\r
1812 @retval EFI_SUCCESS The HTTP header is received.\r
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
1820 IN OUT UINTN *BufferSize,\r
1821 IN EFI_EVENT Timeout\r
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
1832 NET_FRAGMENT Fragment;\r
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
1843 Fragment.Len = 0;\r
1844 Fragment.Bulk = NULL;\r
1845\r
1846 if (HttpInstance->LocalAddressIsIPv6) {\r
1847 ASSERT (Tcp6 != NULL);\r
1848 } else {\r
1849 ASSERT (Tcp4 != NULL);\r
1850 }\r
1851\r
1852 if (!HttpInstance->UseHttps) {\r
1853 Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
1854 if (EFI_ERROR (Status)) {\r
1855 return Status;\r
1856 }\r
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
1868\r
1869 //\r
1870 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1871 //\r
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
1900\r
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
1908\r
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
1914 }\r
1915\r
1916 //\r
1917 // Append the response string along with a Null-terminator.\r
1918 //\r
1919 *BufferSize = *SizeofHeaders + Fragment.Len;\r
1920 Buffer = AllocatePool (*BufferSize + 1);\r
1921 if (Buffer == NULL) {\r
1922 Status = EFI_OUT_OF_RESOURCES;\r
1923 return Status;\r
1924 }\r
1925\r
1926 if (*HttpHeaders != NULL) {\r
1927 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
1928 FreePool (*HttpHeaders);\r
1929 }\r
1930\r
1931 CopyMem (\r
1932 Buffer + *SizeofHeaders,\r
1933 Fragment.Bulk,\r
1934 Fragment.Len\r
1935 );\r
1936 *(Buffer + *BufferSize) = '\0';\r
1937 *HttpHeaders = Buffer;\r
1938 *SizeofHeaders = *BufferSize;\r
1939\r
1940 //\r
1941 // Check whether we received end of HTTP headers.\r
1942 //\r
1943 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1944 };\r
1945\r
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
1958 }\r
1959 } else {\r
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
1967 }\r
1968\r
1969 //\r
1970 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1971 //\r
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
2000\r
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
2008\r
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
2014 }\r
2015\r
2016 //\r
2017 // Append the response string along with a Null-terminator.\r
2018 //\r
2019 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2020 Buffer = AllocatePool (*BufferSize + 1);\r
2021 if (Buffer == NULL) {\r
2022 Status = EFI_OUT_OF_RESOURCES;\r
2023 return Status;\r
2024 }\r
2025\r
2026 if (*HttpHeaders != NULL) {\r
2027 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
2028 FreePool (*HttpHeaders);\r
2029 }\r
2030\r
2031 CopyMem (\r
2032 Buffer + *SizeofHeaders,\r
2033 Fragment.Bulk,\r
2034 Fragment.Len\r
2035 );\r
2036 *(Buffer + *BufferSize) = '\0';\r
2037 *HttpHeaders = Buffer;\r
2038 *SizeofHeaders = *BufferSize;\r
2039\r
2040 //\r
2041 // Check whether we received end of HTTP headers.\r
2042 //\r
2043 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
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
2058 }\r
2059 }\r
2060\r
2061 //\r
2062 // Skip the CRLF after the HTTP headers.\r
2063 //\r
2064 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
2065\r
2066 *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
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
2077 @retval EFI_SUCCESS The HTTP body is received.\r
2078 @retval Others Other error as indicated.\r
2079\r
2080**/\r
2081EFI_STATUS\r
2082HttpTcpReceiveBody (\r
2083 IN HTTP_TOKEN_WRAP *Wrap,\r
2084 IN EFI_HTTP_MESSAGE *HttpMsg\r
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
2093\r
2094 HttpInstance = Wrap->HttpInstance;\r
2095 Tcp4 = HttpInstance->Tcp4;\r
2096 Tcp6 = HttpInstance->Tcp6;\r
2097 Rx4Token = NULL;\r
2098 Rx6Token = NULL;\r
2099\r
2100 if (HttpInstance->LocalAddressIsIPv6) {\r
2101 ASSERT (Tcp6 != NULL);\r
2102 } else {\r
2103 ASSERT (Tcp4 != NULL);\r
2104 }\r
2105\r
2106 if (HttpInstance->LocalAddressIsIPv6) {\r
2107 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
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
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
2118 } else {\r
2119 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
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
2122 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
2123\r
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
2140\r
2141**/\r
2142VOID\r
2143HttpTcpTokenCleanup (\r
2144 IN HTTP_TOKEN_WRAP *Wrap\r
2145 )\r
2146{\r
2147 HTTP_PROTOCOL *HttpInstance;\r
2148 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2149 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2150\r
2151 ASSERT (Wrap != NULL);\r
2152 HttpInstance = Wrap->HttpInstance;\r
2153 Rx4Token = NULL;\r
2154 Rx6Token = NULL;\r
2155\r
2156 if (HttpInstance->LocalAddressIsIPv6) {\r
2157 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
2158\r
2159 if (Rx6Token->CompletionToken.Event != NULL) {\r
2160 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2161 Rx6Token->CompletionToken.Event = NULL;\r
2162 }\r
2163\r
2164 FreePool (Wrap);\r
2165\r
2166 Rx6Token = &HttpInstance->Rx6Token;\r
2167\r
2168 if (Rx6Token->CompletionToken.Event != NULL) {\r
2169 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2170 Rx6Token->CompletionToken.Event = NULL;\r
2171 }\r
2172\r
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
2177\r
2178 } else {\r
2179 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
2180\r
2181 if (Rx4Token->CompletionToken.Event != NULL) {\r
2182 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2183 Rx4Token->CompletionToken.Event = NULL;\r
2184 }\r
2185\r
2186 FreePool (Wrap);\r
2187\r
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
2193 }\r
2194\r
2195\r
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