]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg: Clean up source files
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
... / ...
CommitLineData
1/** @file\r
2 Miscellaneous routines for HttpDxe driver.\r
3\r
4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "HttpDriver.h"\r
17\r
18/**\r
19 The common notify function used in HTTP driver.\r
20\r
21 @param[in] Event The event signaled.\r
22 @param[in] Context The context.\r
23\r
24**/\r
25VOID\r
26EFIAPI\r
27HttpCommonNotify (\r
28 IN EFI_EVENT Event,\r
29 IN VOID *Context\r
30 )\r
31{\r
32 if ((Event == NULL) || (Context == NULL)) {\r
33 return ;\r
34 }\r
35\r
36 *((BOOLEAN *) Context) = TRUE;\r
37}\r
38\r
39/**\r
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
41\r
42 @param[in] Context The context.\r
43\r
44**/\r
45VOID\r
46EFIAPI\r
47HttpTcpTransmitNotifyDpc (\r
48 IN VOID *Context\r
49 )\r
50{\r
51 HTTP_TOKEN_WRAP *Wrap;\r
52 HTTP_PROTOCOL *HttpInstance;\r
53\r
54 if (Context == NULL) {\r
55 return ;\r
56 }\r
57\r
58 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
59 HttpInstance = Wrap->HttpInstance;\r
60\r
61 if (!HttpInstance->LocalAddressIsIPv6) {\r
62 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
63 gBS->SignalEvent (Wrap->HttpToken->Event);\r
64\r
65 //\r
66 // Free resources.\r
67 //\r
68 if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
69 FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
70 }\r
71\r
72 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
73 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
74 }\r
75\r
76 } else {\r
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
78 gBS->SignalEvent (Wrap->HttpToken->Event);\r
79\r
80 //\r
81 // Free resources.\r
82 //\r
83 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
84 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
85 }\r
86\r
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
89 }\r
90 }\r
91\r
92\r
93 Wrap->TcpWrap.IsTxDone = TRUE;\r
94\r
95 //\r
96 // Check pending TxTokens and sent out.\r
97 //\r
98 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);\r
99\r
100}\r
101\r
102/**\r
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.\r
104\r
105 @param Event The receive event delivered to TCP for transmit.\r
106 @param Context Context for the callback.\r
107\r
108**/\r
109VOID\r
110EFIAPI\r
111HttpTcpTransmitNotify (\r
112 IN EFI_EVENT Event,\r
113 IN VOID *Context\r
114 )\r
115{\r
116 //\r
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK\r
118 //\r
119 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
120}\r
121\r
122/**\r
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
124\r
125 @param[in] Context The context.\r
126\r
127**/\r
128VOID\r
129EFIAPI\r
130HttpTcpReceiveNotifyDpc (\r
131 IN VOID *Context\r
132 )\r
133{\r
134 HTTP_TOKEN_WRAP *Wrap;\r
135 NET_MAP_ITEM *Item;\r
136 UINTN Length;\r
137 EFI_STATUS Status;\r
138 HTTP_PROTOCOL *HttpInstance;\r
139 BOOLEAN UsingIpv6;\r
140\r
141 if (Context == NULL) {\r
142 return ;\r
143 }\r
144\r
145 Wrap = (HTTP_TOKEN_WRAP *) Context;\r
146 HttpInstance = Wrap->HttpInstance;\r
147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
148\r
149 if (UsingIpv6) {\r
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
151 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
152\r
153 if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
154 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status));\r
155 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
156 gBS->SignalEvent (Wrap->HttpToken->Event);\r
157\r
158 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
159 if (Item != NULL) {\r
160 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
161 }\r
162\r
163 FreePool (Wrap);\r
164 Wrap = NULL;\r
165\r
166 return ;\r
167 }\r
168\r
169 } else {\r
170 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
171 Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;\r
172\r
173 if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
174 DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status));\r
175 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
176 gBS->SignalEvent (Wrap->HttpToken->Event);\r
177\r
178 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
179 if (Item != NULL) {\r
180 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
181 }\r
182\r
183 FreePool (Wrap);\r
184 Wrap = NULL;\r
185\r
186 return ;\r
187 }\r
188 }\r
189\r
190 //\r
191 // Check whether we receive a complete HTTP message.\r
192 //\r
193 ASSERT (HttpInstance->MsgParser != NULL);\r
194 if (UsingIpv6) {\r
195 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
196 } else {\r
197 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
198 }\r
199\r
200 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 *TlsRecord;\r
1480 UINT16 PayloadSize;\r
1481 NET_FRAGMENT TempFragment;\r
1482 NET_FRAGMENT Fragment;\r
1483 UINTN RecordCount;\r
1484 UINTN RemainingLen;\r
1485\r
1486 Status = EFI_SUCCESS;\r
1487 TlsRecord = NULL;\r
1488 PayloadSize = 0;\r
1489 TempFragment.Len = 0;\r
1490 TempFragment.Bulk = NULL;\r
1491 Fragment.Len = 0;\r
1492 Fragment.Bulk = NULL;\r
1493 RecordCount = 0;\r
1494 RemainingLen = 0;\r
1495\r
1496 //\r
1497 // Need to encrypt data.\r
1498 //\r
1499 if (HttpInstance->UseHttps) {\r
1500 //\r
1501 // Allocate enough buffer for each TLS plaintext records.\r
1502 //\r
1503 TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1504 if (TlsRecord == NULL) {\r
1505 Status = EFI_OUT_OF_RESOURCES;\r
1506 return Status;\r
1507 }\r
1508\r
1509 //\r
1510 // Allocate enough buffer for all TLS ciphertext records.\r
1511 //\r
1512 RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
1513 Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
1514 if (Fragment.Bulk == NULL) {\r
1515 Status = EFI_OUT_OF_RESOURCES;\r
1516 goto ON_ERROR;\r
1517 }\r
1518\r
1519 //\r
1520 // Encrypt each TLS plaintext records.\r
1521 //\r
1522 RemainingLen = TxStringLen;\r
1523 while (RemainingLen != 0) {\r
1524 PayloadSize = (UINT16) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
1525\r
1526 ((TLS_RECORD_HEADER *) TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
1527 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
1528 ((TLS_RECORD_HEADER *) TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
1529 ((TLS_RECORD_HEADER *) TlsRecord)->Length = PayloadSize;\r
1530\r
1531 CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
1532\r
1533 Status = TlsProcessMessage (\r
1534 HttpInstance,\r
1535 TlsRecord,\r
1536 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
1537 EfiTlsEncrypt,\r
1538 &TempFragment\r
1539 );\r
1540 if (EFI_ERROR (Status)) {\r
1541 goto ON_ERROR;\r
1542 }\r
1543\r
1544 //\r
1545 // Record the processed/encrypted Packet.\r
1546 //\r
1547 CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
1548 Fragment.Len += TempFragment.Len;\r
1549\r
1550 FreePool (TempFragment.Bulk);\r
1551 TempFragment.Len = 0;\r
1552 TempFragment.Bulk = NULL;\r
1553\r
1554 RemainingLen -= (UINTN) PayloadSize;\r
1555 ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
1556 }\r
1557\r
1558 FreePool (TlsRecord);\r
1559 TlsRecord = NULL;\r
1560 }\r
1561\r
1562 if (!HttpInstance->LocalAddressIsIPv6) {\r
1563 Tcp4 = HttpInstance->Tcp4;\r
1564 Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
1565\r
1566 if (HttpInstance->UseHttps) {\r
1567 Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
1568 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1569 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
1570 } else {\r
1571 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1572 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1573 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1574 }\r
1575\r
1576 Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
1577\r
1578 Wrap->TcpWrap.IsTxDone = FALSE;\r
1579 Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
1580 if (EFI_ERROR (Status)) {\r
1581 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1582 goto ON_ERROR;\r
1583 }\r
1584\r
1585 } else {\r
1586 Tcp6 = HttpInstance->Tcp6;\r
1587 Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
1588\r
1589 if (HttpInstance->UseHttps) {\r
1590 Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
1591 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
1592 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
1593 } else {\r
1594 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
1595 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
1596 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
1597 }\r
1598\r
1599 Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
1600\r
1601 Wrap->TcpWrap.IsTxDone = FALSE;\r
1602 Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
1603 if (EFI_ERROR (Status)) {\r
1604 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
1605 goto ON_ERROR;\r
1606 }\r
1607 }\r
1608\r
1609 return Status;\r
1610\r
1611ON_ERROR:\r
1612\r
1613 if (HttpInstance->UseHttps) {\r
1614 if (TlsRecord != NULL) {\r
1615 FreePool (TlsRecord);\r
1616 TlsRecord = NULL;\r
1617 }\r
1618\r
1619 if (Fragment.Bulk != NULL) {\r
1620 FreePool (Fragment.Bulk);\r
1621 Fragment.Bulk = NULL;\r
1622 }\r
1623 }\r
1624\r
1625 return Status;\r
1626}\r
1627\r
1628/**\r
1629 Check whether the user's token or event has already\r
1630 been enqueue on HTTP Tx or Rx Token list.\r
1631\r
1632 @param[in] Map The container of either user's transmit or receive\r
1633 token.\r
1634 @param[in] Item Current item to check against.\r
1635 @param[in] Context The Token to check againist.\r
1636\r
1637 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP\r
1638 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1639 context.\r
1640\r
1641**/\r
1642EFI_STATUS\r
1643EFIAPI\r
1644HttpTokenExist (\r
1645 IN NET_MAP *Map,\r
1646 IN NET_MAP_ITEM *Item,\r
1647 IN VOID *Context\r
1648 )\r
1649{\r
1650 EFI_HTTP_TOKEN *Token;\r
1651 EFI_HTTP_TOKEN *TokenInItem;\r
1652\r
1653 Token = (EFI_HTTP_TOKEN *) Context;\r
1654 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;\r
1655\r
1656 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {\r
1657 return EFI_ACCESS_DENIED;\r
1658 }\r
1659\r
1660 return EFI_SUCCESS;\r
1661}\r
1662\r
1663/**\r
1664 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
1665\r
1666 @param[in] Map The container of Tx4Token or Tx6Token.\r
1667 @param[in] Item Current item to check against.\r
1668 @param[in] Context The Token to check againist.\r
1669\r
1670 @retval EFI_NOT_READY The HTTP message is still queued in the list.\r
1671 @retval EFI_SUCCESS The HTTP message has been sent out.\r
1672\r
1673**/\r
1674EFI_STATUS\r
1675EFIAPI\r
1676HttpTcpNotReady (\r
1677 IN NET_MAP *Map,\r
1678 IN NET_MAP_ITEM *Item,\r
1679 IN VOID *Context\r
1680 )\r
1681{\r
1682 HTTP_TOKEN_WRAP *ValueInItem;\r
1683\r
1684 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1685\r
1686 if (!ValueInItem->TcpWrap.IsTxDone) {\r
1687 return EFI_NOT_READY;\r
1688 }\r
1689\r
1690 return EFI_SUCCESS;\r
1691}\r
1692\r
1693/**\r
1694 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.\r
1695\r
1696 @param[in] Map The container of Tx4Token or Tx6Token.\r
1697 @param[in] Item Current item to check against.\r
1698 @param[in] Context The Token to check againist.\r
1699\r
1700 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
1701 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit\r
1702 queue.\r
1703\r
1704**/\r
1705EFI_STATUS\r
1706EFIAPI\r
1707HttpTcpTransmit (\r
1708 IN NET_MAP *Map,\r
1709 IN NET_MAP_ITEM *Item,\r
1710 IN VOID *Context\r
1711 )\r
1712{\r
1713 HTTP_TOKEN_WRAP *ValueInItem;\r
1714 EFI_STATUS Status;\r
1715 CHAR8 *RequestMsg;\r
1716 CHAR8 *Url;\r
1717 UINTN UrlSize;\r
1718 UINTN RequestMsgSize;\r
1719\r
1720 RequestMsg = NULL;\r
1721\r
1722 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
1723 if (ValueInItem->TcpWrap.IsTxDone) {\r
1724 return EFI_SUCCESS;\r
1725 }\r
1726\r
1727 //\r
1728 // Parse the URI of the remote host.\r
1729 //\r
1730 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
1731 Url = AllocatePool (UrlSize);\r
1732 if (Url == NULL) {\r
1733 return EFI_OUT_OF_RESOURCES;\r
1734 }\r
1735\r
1736 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
1737\r
1738 //\r
1739 // Create request message.\r
1740 //\r
1741 Status = HttpGenRequestMessage (\r
1742 ValueInItem->HttpToken->Message,\r
1743 Url,\r
1744 &RequestMsg,\r
1745 &RequestMsgSize\r
1746 );\r
1747 FreePool (Url);\r
1748\r
1749 if (EFI_ERROR (Status) || NULL == RequestMsg){\r
1750 return Status;\r
1751 }\r
1752\r
1753 ASSERT (RequestMsg != NULL);\r
1754\r
1755 //\r
1756 // Transmit the request message.\r
1757 //\r
1758 Status = HttpTransmitTcp (\r
1759 ValueInItem->HttpInstance,\r
1760 ValueInItem,\r
1761 (UINT8*) RequestMsg,\r
1762 RequestMsgSize\r
1763 );\r
1764 FreePool (RequestMsg);\r
1765 return Status;\r
1766}\r
1767\r
1768/**\r
1769 Receive the HTTP response by processing the associated HTTP token.\r
1770\r
1771 @param[in] Map The container of Rx4Token or Rx6Token.\r
1772 @param[in] Item Current item to check against.\r
1773 @param[in] Context The Token to check againist.\r
1774\r
1775 @retval EFI_SUCCESS The HTTP response is queued into TCP receive\r
1776 queue.\r
1777 @retval Others Other error as indicated.\r
1778\r
1779**/\r
1780EFI_STATUS\r
1781EFIAPI\r
1782HttpTcpReceive (\r
1783 IN NET_MAP *Map,\r
1784 IN NET_MAP_ITEM *Item,\r
1785 IN VOID *Context\r
1786 )\r
1787{\r
1788 //\r
1789 // Process the queued HTTP response.\r
1790 //\r
1791 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
1792}\r
1793\r
1794/**\r
1795 Receive the HTTP header by processing the associated HTTP token.\r
1796\r
1797 @param[in] HttpInstance The HTTP instance private data.\r
1798 @param[in, out] SizeofHeaders The HTTP header length.\r
1799 @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
1800 @param[in] Timeout The time to wait for receiving the header packet.\r
1801\r
1802 @retval EFI_SUCCESS The HTTP header is received.\r
1803 @retval Others Other errors as indicated.\r
1804\r
1805**/\r
1806EFI_STATUS\r
1807HttpTcpReceiveHeader (\r
1808 IN HTTP_PROTOCOL *HttpInstance,\r
1809 IN OUT UINTN *SizeofHeaders,\r
1810 IN OUT UINTN *BufferSize,\r
1811 IN EFI_EVENT Timeout\r
1812 )\r
1813{\r
1814 EFI_STATUS Status;\r
1815 EFI_TCP4_IO_TOKEN *Rx4Token;\r
1816 EFI_TCP4_PROTOCOL *Tcp4;\r
1817 EFI_TCP6_IO_TOKEN *Rx6Token;\r
1818 EFI_TCP6_PROTOCOL *Tcp6;\r
1819 CHAR8 **EndofHeader;\r
1820 CHAR8 **HttpHeaders;\r
1821 CHAR8 *Buffer;\r
1822 NET_FRAGMENT Fragment;\r
1823\r
1824 ASSERT (HttpInstance != NULL);\r
1825\r
1826 EndofHeader = HttpInstance->EndofHeader;\r
1827 HttpHeaders = HttpInstance->HttpHeaders;\r
1828 Tcp4 = HttpInstance->Tcp4;\r
1829 Tcp6 = HttpInstance->Tcp6;\r
1830 Buffer = NULL;\r
1831 Rx4Token = NULL;\r
1832 Rx6Token = NULL;\r
1833 Fragment.Len = 0;\r
1834 Fragment.Bulk = NULL;\r
1835\r
1836 if (HttpInstance->LocalAddressIsIPv6) {\r
1837 ASSERT (Tcp6 != NULL);\r
1838 } else {\r
1839 ASSERT (Tcp4 != NULL);\r
1840 }\r
1841\r
1842 if (!HttpInstance->UseHttps) {\r
1843 Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
1844 if (EFI_ERROR (Status)) {\r
1845 return Status;\r
1846 }\r
1847 }\r
1848\r
1849 if (!HttpInstance->LocalAddressIsIPv6) {\r
1850 if (!HttpInstance->UseHttps) {\r
1851 Rx4Token = &HttpInstance->Rx4Token;\r
1852 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1853 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1854 Status = EFI_OUT_OF_RESOURCES;\r
1855 return Status;\r
1856 }\r
1857 }\r
1858\r
1859 //\r
1860 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1861 //\r
1862 while (*EndofHeader == NULL) {\r
1863 if (!HttpInstance->UseHttps) {\r
1864 HttpInstance->IsRxDone = FALSE;\r
1865 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1866 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1867 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
1868 if (EFI_ERROR (Status)) {\r
1869 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1870 return Status;\r
1871 }\r
1872\r
1873 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1874 Tcp4->Poll (Tcp4);\r
1875 }\r
1876\r
1877 if (!HttpInstance->IsRxDone) {\r
1878 //\r
1879 // Cancle the Token before close its Event.\r
1880 //\r
1881 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);\r
1882 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
1883 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
1884 }\r
1885\r
1886 Status = Rx4Token->CompletionToken.Status;\r
1887 if (EFI_ERROR (Status)) {\r
1888 return Status;\r
1889 }\r
1890\r
1891 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1892 Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
1893 } else {\r
1894 if (Fragment.Bulk != NULL) {\r
1895 FreePool (Fragment.Bulk);\r
1896 Fragment.Bulk = NULL;\r
1897 }\r
1898\r
1899 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1900 if (EFI_ERROR (Status)) {\r
1901 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
1902 return Status;\r
1903 }\r
1904 }\r
1905\r
1906 //\r
1907 // Append the response string.\r
1908 //\r
1909 *BufferSize = *SizeofHeaders + Fragment.Len;\r
1910 Buffer = AllocateZeroPool (*BufferSize);\r
1911 if (Buffer == NULL) {\r
1912 Status = EFI_OUT_OF_RESOURCES;\r
1913 return Status;\r
1914 }\r
1915\r
1916 if (*HttpHeaders != NULL) {\r
1917 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
1918 FreePool (*HttpHeaders);\r
1919 }\r
1920\r
1921 CopyMem (\r
1922 Buffer + *SizeofHeaders,\r
1923 Fragment.Bulk,\r
1924 Fragment.Len\r
1925 );\r
1926 *HttpHeaders = Buffer;\r
1927 *SizeofHeaders = *BufferSize;\r
1928\r
1929 //\r
1930 // Check whether we received end of HTTP headers.\r
1931 //\r
1932 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
1933 };\r
1934\r
1935 //\r
1936 // Free the buffer.\r
1937 //\r
1938 if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
1939 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
1940 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
1941 Fragment.Bulk = NULL;\r
1942 }\r
1943\r
1944 if (Fragment.Bulk != NULL) {\r
1945 FreePool (Fragment.Bulk);\r
1946 Fragment.Bulk = NULL;\r
1947 }\r
1948 } else {\r
1949 if (!HttpInstance->UseHttps) {\r
1950 Rx6Token = &HttpInstance->Rx6Token;\r
1951 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
1952 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
1953 Status = EFI_OUT_OF_RESOURCES;\r
1954 return Status;\r
1955 }\r
1956 }\r
1957\r
1958 //\r
1959 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
1960 //\r
1961 while (*EndofHeader == NULL) {\r
1962 if (!HttpInstance->UseHttps) {\r
1963 HttpInstance->IsRxDone = FALSE;\r
1964 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
1965 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
1966 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
1967 if (EFI_ERROR (Status)) {\r
1968 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
1969 return Status;\r
1970 }\r
1971\r
1972 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
1973 Tcp6->Poll (Tcp6);\r
1974 }\r
1975\r
1976 if (!HttpInstance->IsRxDone) {\r
1977 //\r
1978 // Cancle the Token before close its Event.\r
1979 //\r
1980 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);\r
1981 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
1982 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
1983 }\r
1984\r
1985 Status = Rx6Token->CompletionToken.Status;\r
1986 if (EFI_ERROR (Status)) {\r
1987 return Status;\r
1988 }\r
1989\r
1990 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
1991 Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
1992 } else {\r
1993 if (Fragment.Bulk != NULL) {\r
1994 FreePool (Fragment.Bulk);\r
1995 Fragment.Bulk = NULL;\r
1996 }\r
1997\r
1998 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
1999 if (EFI_ERROR (Status)) {\r
2000 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
2001 return Status;\r
2002 }\r
2003 }\r
2004\r
2005 //\r
2006 // Append the response string.\r
2007 //\r
2008 *BufferSize = *SizeofHeaders + Fragment.Len;\r
2009 Buffer = AllocateZeroPool (*BufferSize);\r
2010 if (Buffer == NULL) {\r
2011 Status = EFI_OUT_OF_RESOURCES;\r
2012 return Status;\r
2013 }\r
2014\r
2015 if (*HttpHeaders != NULL) {\r
2016 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
2017 FreePool (*HttpHeaders);\r
2018 }\r
2019\r
2020 CopyMem (\r
2021 Buffer + *SizeofHeaders,\r
2022 Fragment.Bulk,\r
2023 Fragment.Len\r
2024 );\r
2025 *HttpHeaders = Buffer;\r
2026 *SizeofHeaders = *BufferSize;\r
2027\r
2028 //\r
2029 // Check whether we received end of HTTP headers.\r
2030 //\r
2031 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
2032 };\r
2033\r
2034 //\r
2035 // Free the buffer.\r
2036 //\r
2037 if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2038 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2039 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2040 Fragment.Bulk = NULL;\r
2041 }\r
2042\r
2043 if (Fragment.Bulk != NULL) {\r
2044 FreePool (Fragment.Bulk);\r
2045 Fragment.Bulk = NULL;\r
2046 }\r
2047 }\r
2048\r
2049 //\r
2050 // Skip the CRLF after the HTTP headers.\r
2051 //\r
2052 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
2053\r
2054 *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
2055\r
2056 return EFI_SUCCESS;\r
2057}\r
2058\r
2059/**\r
2060 Receive the HTTP body by processing the associated HTTP token.\r
2061\r
2062 @param[in] Wrap The HTTP token's wrap data.\r
2063 @param[in] HttpMsg The HTTP message data.\r
2064\r
2065 @retval EFI_SUCCESS The HTTP body is received.\r
2066 @retval Others Other error as indicated.\r
2067\r
2068**/\r
2069EFI_STATUS\r
2070HttpTcpReceiveBody (\r
2071 IN HTTP_TOKEN_WRAP *Wrap,\r
2072 IN EFI_HTTP_MESSAGE *HttpMsg\r
2073 )\r
2074{\r
2075 EFI_STATUS Status;\r
2076 HTTP_PROTOCOL *HttpInstance;\r
2077 EFI_TCP6_PROTOCOL *Tcp6;\r
2078 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2079 EFI_TCP4_PROTOCOL *Tcp4;\r
2080 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2081\r
2082 HttpInstance = Wrap->HttpInstance;\r
2083 Tcp4 = HttpInstance->Tcp4;\r
2084 Tcp6 = HttpInstance->Tcp6;\r
2085 Rx4Token = NULL;\r
2086 Rx6Token = NULL;\r
2087\r
2088 if (HttpInstance->LocalAddressIsIPv6) {\r
2089 ASSERT (Tcp6 != NULL);\r
2090 } else {\r
2091 ASSERT (Tcp4 != NULL);\r
2092 }\r
2093\r
2094 if (HttpInstance->LocalAddressIsIPv6) {\r
2095 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
2096 Rx6Token ->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2097 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2098 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
2099 Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
2100\r
2101 Status = Tcp6->Receive (Tcp6, Rx6Token);\r
2102 if (EFI_ERROR (Status)) {\r
2103 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
2104 return Status;\r
2105 }\r
2106 } else {\r
2107 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
2108 Rx4Token->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2109 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
2110 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
2111\r
2112 Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
2113 Status = Tcp4->Receive (Tcp4, Rx4Token);\r
2114 if (EFI_ERROR (Status)) {\r
2115 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
2116 return Status;\r
2117 }\r
2118 }\r
2119\r
2120 return EFI_SUCCESS;\r
2121\r
2122}\r
2123\r
2124/**\r
2125 Clean up Tcp Tokens while the Tcp transmission error occurs.\r
2126\r
2127 @param[in] Wrap Pointer to HTTP token's wrap data.\r
2128\r
2129**/\r
2130VOID\r
2131HttpTcpTokenCleanup (\r
2132 IN HTTP_TOKEN_WRAP *Wrap\r
2133 )\r
2134{\r
2135 HTTP_PROTOCOL *HttpInstance;\r
2136 EFI_TCP4_IO_TOKEN *Rx4Token;\r
2137 EFI_TCP6_IO_TOKEN *Rx6Token;\r
2138\r
2139 ASSERT (Wrap != NULL);\r
2140 HttpInstance = Wrap->HttpInstance;\r
2141 Rx4Token = NULL;\r
2142 Rx6Token = NULL;\r
2143\r
2144 if (HttpInstance->LocalAddressIsIPv6) {\r
2145 Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
2146\r
2147 if (Rx6Token->CompletionToken.Event != NULL) {\r
2148 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2149 Rx6Token->CompletionToken.Event = NULL;\r
2150 }\r
2151\r
2152 FreePool (Wrap);\r
2153\r
2154 Rx6Token = &HttpInstance->Rx6Token;\r
2155\r
2156 if (Rx6Token->CompletionToken.Event != NULL) {\r
2157 gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
2158 Rx6Token->CompletionToken.Event = NULL;\r
2159 }\r
2160\r
2161 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2162 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2163 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2164 }\r
2165\r
2166 } else {\r
2167 Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
2168\r
2169 if (Rx4Token->CompletionToken.Event != NULL) {\r
2170 gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
2171 Rx4Token->CompletionToken.Event = NULL;\r
2172 }\r
2173\r
2174 FreePool (Wrap);\r
2175\r
2176 Rx4Token = &HttpInstance->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\r
2184 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
2185 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
2186 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
2187 }\r
2188 }\r
2189\r
2190}\r