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