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