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