TianoCore EDK2 master
Loading...
Searching...
No Matches
HttpImpl.c
Go to the documentation of this file.
1
12#include "HttpDriver.h"
13
14EFI_HTTP_PROTOCOL mEfiHttpTemplate = {
21};
22
47EFIAPI
50 OUT EFI_HTTP_CONFIG_DATA *HttpConfigData
51 )
52{
53 HTTP_PROTOCOL *HttpInstance;
54
55 //
56 // Check input parameters.
57 //
58 if ((This == NULL) || (HttpConfigData == NULL)) {
59 return EFI_INVALID_PARAMETER;
60 }
61
62 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
63
64 if ((HttpConfigData->AccessPoint.IPv6Node == NULL) ||
65 (HttpConfigData->AccessPoint.IPv4Node == NULL))
66 {
67 return EFI_INVALID_PARAMETER;
68 }
69
70 if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
71 return EFI_NOT_STARTED;
72 }
73
74 HttpConfigData->HttpVersion = HttpInstance->HttpVersion;
75 HttpConfigData->TimeOutMillisec = HttpInstance->TimeOutMillisec;
76 HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;
77
78 if (HttpInstance->LocalAddressIsIPv6) {
79 CopyMem (
80 HttpConfigData->AccessPoint.IPv6Node,
81 &HttpInstance->Ipv6Node,
82 sizeof (HttpInstance->Ipv6Node)
83 );
84 } else {
85 CopyMem (
86 HttpConfigData->AccessPoint.IPv4Node,
87 &HttpInstance->IPv4Node,
88 sizeof (HttpInstance->IPv4Node)
89 );
90 }
91
92 return EFI_SUCCESS;
93}
94
127EFIAPI
129 IN EFI_HTTP_PROTOCOL *This,
130 IN EFI_HTTP_CONFIG_DATA *HttpConfigData OPTIONAL
131 )
132{
133 HTTP_PROTOCOL *HttpInstance;
134 EFI_STATUS Status;
135
136 //
137 // Check input parameters.
138 //
139 if ((This == NULL) ||
140 ((HttpConfigData != NULL) &&
141 ((HttpConfigData->LocalAddressIsIPv6 && (HttpConfigData->AccessPoint.IPv6Node == NULL)) ||
142 (!HttpConfigData->LocalAddressIsIPv6 && (HttpConfigData->AccessPoint.IPv4Node == NULL)))))
143 {
144 return EFI_INVALID_PARAMETER;
145 }
146
147 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
148 ASSERT (HttpInstance->Service != NULL);
149
150 if (HttpConfigData != NULL) {
151 if (HttpConfigData->HttpVersion >= HttpVersionUnsupported) {
152 return EFI_UNSUPPORTED;
153 }
154
155 //
156 // Now configure this HTTP instance.
157 //
158 if (HttpInstance->State != HTTP_STATE_UNCONFIGED) {
159 return EFI_ALREADY_STARTED;
160 }
161
162 HttpInstance->HttpVersion = HttpConfigData->HttpVersion;
163 HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;
164 HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
165 HttpInstance->ConnectionClose = FALSE;
166
167 if (HttpConfigData->LocalAddressIsIPv6) {
168 CopyMem (
169 &HttpInstance->Ipv6Node,
170 HttpConfigData->AccessPoint.IPv6Node,
171 sizeof (HttpInstance->Ipv6Node)
172 );
173 } else {
174 CopyMem (
175 &HttpInstance->IPv4Node,
176 HttpConfigData->AccessPoint.IPv4Node,
177 sizeof (HttpInstance->IPv4Node)
178 );
179 }
180
181 //
182 // Creat Tcp child
183 //
184 Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);
185 if (EFI_ERROR (Status)) {
186 return Status;
187 }
188
189 HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;
190 return EFI_SUCCESS;
191 } else {
192 //
193 // Reset all the resources related to HttpInstance.
194 //
195 HttpCleanProtocol (HttpInstance);
196 HttpInstance->State = HTTP_STATE_UNCONFIGED;
197 return EFI_SUCCESS;
198 }
199}
200
228EFIAPI
230 IN EFI_HTTP_PROTOCOL *This,
231 IN EFI_HTTP_TOKEN *Token
232 )
233{
234 EFI_HTTP_MESSAGE *HttpMsg;
235 EFI_HTTP_REQUEST_DATA *Request;
236 VOID *UrlParser;
237 EFI_STATUS Status;
238 CHAR8 *HostName;
239 UINTN HostNameSize;
240 UINT16 RemotePort;
241 HTTP_PROTOCOL *HttpInstance;
242 BOOLEAN Configure;
243 BOOLEAN ReConfigure;
244 BOOLEAN TlsConfigure;
245 CHAR8 *RequestMsg;
246 CHAR8 *Url;
247 UINTN UrlLen;
248 CHAR16 *HostNameStr;
249 HTTP_TOKEN_WRAP *Wrap;
250 CHAR8 *FileUrl;
251 UINTN RequestMsgSize;
252
253 //
254 // Initializations
255 //
256 Url = NULL;
257 UrlParser = NULL;
258 RemotePort = 0;
259 HostName = NULL;
260 RequestMsg = NULL;
261 HostNameStr = NULL;
262 Wrap = NULL;
263 FileUrl = NULL;
264 TlsConfigure = FALSE;
265
266 if ((This == NULL) || (Token == NULL)) {
267 return EFI_INVALID_PARAMETER;
268 }
269
270 HttpMsg = Token->Message;
271 if (HttpMsg == NULL) {
272 return EFI_INVALID_PARAMETER;
273 }
274
275 Request = HttpMsg->Data.Request;
276
277 //
278 // Only support GET, HEAD, DELETE, PATCH, PUT and POST method in current implementation.
279 //
280 if ((Request != NULL) && (Request->Method != HttpMethodGet) &&
281 (Request->Method != HttpMethodHead) && (Request->Method != HttpMethodDelete) &&
282 (Request->Method != HttpMethodPut) && (Request->Method != HttpMethodPost) &&
283 (Request->Method != HttpMethodPatch))
284 {
285 return EFI_UNSUPPORTED;
286 }
287
288 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
289
290 //
291 // Capture the method into HttpInstance.
292 //
293 if (Request != NULL) {
294 HttpInstance->Method = Request->Method;
295 }
296
297 if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
298 return EFI_NOT_STARTED;
299 }
300
301 if (Request == NULL) {
302 //
303 // Request would be NULL only for PUT/POST/PATCH operation (in the current implementation)
304 //
305 if ((HttpInstance->Method != HttpMethodPut) &&
306 (HttpInstance->Method != HttpMethodPost) &&
307 (HttpInstance->Method != HttpMethodPatch))
308 {
309 return EFI_INVALID_PARAMETER;
310 }
311
312 //
313 // For PUT/POST/PATCH, we need to have the TCP already configured. Bail out if it is not!
314 //
315 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED) {
316 return EFI_INVALID_PARAMETER;
317 }
318
319 //
320 // We need to have the Message Body for sending the HTTP message across in these cases.
321 //
322 if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) {
323 return EFI_INVALID_PARAMETER;
324 }
325
326 //
327 // Use existing TCP instance to transmit the packet.
328 //
329 Configure = FALSE;
330 ReConfigure = FALSE;
331 } else {
332 //
333 // Check whether the token already existed.
334 //
335 if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) {
336 return EFI_ACCESS_DENIED;
337 }
338
339 //
340 // Parse the URI of the remote host.
341 //
342 Url = HttpInstance->Url;
343 UrlLen = StrLen (Request->Url) + 1;
344 if (UrlLen > HttpInstance->UrlLen) {
345 Url = AllocateZeroPool (UrlLen);
346 if (Url == NULL) {
347 return EFI_OUT_OF_RESOURCES;
348 }
349
350 if (HttpInstance->Url != NULL) {
351 FreePool (HttpInstance->Url);
352 }
353
354 HttpInstance->Url = Url;
355 HttpInstance->UrlLen = UrlLen;
356 }
357
358 UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen);
359
360 //
361 // From the information in Url, the HTTP instance will
362 // be able to determine whether to use http or https.
363 //
364 HttpInstance->UseHttps = IsHttpsUrl (Url);
365
366 //
367 // HTTP is disabled, return directly if the URI is not HTTPS.
368 //
369 if (!PcdGetBool (PcdAllowHttpConnections) && !(HttpInstance->UseHttps)) {
370 DEBUG ((DEBUG_ERROR, "EfiHttpRequest: HTTP is disabled.\n"));
371
372 return EFI_ACCESS_DENIED;
373 }
374
375 //
376 // Check whether we need to create Tls child and open the TLS protocol.
377 //
378 if (HttpInstance->UseHttps && !HttpInstance->TlsAlreadyCreated) {
379 // Create TLS child for this HTTP instance.
380 Status = TlsCreateChild (HttpInstance);
381 if (EFI_ERROR (Status)) {
382 return EFI_DEVICE_ERROR;
383 }
384
385 TlsConfigure = TRUE;
386 }
387
388 UrlParser = NULL;
389 Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
390 if (EFI_ERROR (Status)) {
391 goto Error1;
392 }
393
394 Status = HttpUrlGetHostName (Url, UrlParser, &HostName);
395 if (EFI_ERROR (Status)) {
396 goto Error1;
397 }
398
399 if (HttpInstance->LocalAddressIsIPv6) {
400 HostNameSize = AsciiStrSize (HostName);
401
402 if ((HostNameSize > 2) && (HostName[0] == '[') && (HostName[HostNameSize - 2] == ']')) {
403 //
404 // HostName format is expressed as IPv6, so, remove '[' and ']'.
405 //
406 HostNameSize -= 2;
407 CopyMem (HostName, HostName + 1, HostNameSize - 1);
408 HostName[HostNameSize - 1] = '\0';
409 }
410 }
411
412 Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
413 if (EFI_ERROR (Status)) {
414 if (HttpInstance->UseHttps) {
415 RemotePort = HTTPS_DEFAULT_PORT;
416 } else {
417 RemotePort = HTTP_DEFAULT_PORT;
418 }
419 }
420
421 //
422 // If Configure is TRUE, it indicates the first time to call Request();
423 // If ReConfigure is TRUE, it indicates the request URL is not same
424 // with the previous call to Request();
425 //
426 Configure = TRUE;
427 ReConfigure = TRUE;
428
429 if (HttpInstance->RemoteHost == NULL) {
430 //
431 // Request() is called the first time.
432 //
433 ReConfigure = FALSE;
434 } else {
435 if ((HttpInstance->ConnectionClose == FALSE) &&
436 (HttpInstance->RemotePort == RemotePort) &&
437 (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0) &&
438 (!HttpInstance->UseHttps || (HttpInstance->UseHttps &&
439 !TlsConfigure &&
440 (HttpInstance->TlsSessionState == EfiTlsSessionDataTransferring))))
441 {
442 //
443 // Host Name and port number of the request URL are the same with previous call to Request().
444 // If Https protocol used, the corresponding SessionState is EfiTlsSessionDataTransferring.
445 // Check whether previous TCP packet sent out.
446 //
447
448 if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) {
449 //
450 // Wrap the HTTP token in HTTP_TOKEN_WRAP
451 //
452 Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
453 if (Wrap == NULL) {
454 Status = EFI_OUT_OF_RESOURCES;
455 goto Error1;
456 }
457
458 Wrap->HttpToken = Token;
459 Wrap->HttpInstance = HttpInstance;
460
461 Status = HttpCreateTcpTxEvent (Wrap);
462 if (EFI_ERROR (Status)) {
463 goto Error1;
464 }
465
466 Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
467 if (EFI_ERROR (Status)) {
468 goto Error1;
469 }
470
471 Wrap->TcpWrap.Method = Request->Method;
472
473 FreePool (HostName);
474
475 HttpUrlFreeParser (UrlParser);
476
477 //
478 // Queue the HTTP token and return.
479 //
480 return EFI_SUCCESS;
481 } else {
482 //
483 // Use existing TCP instance to transmit the packet.
484 //
485 Configure = FALSE;
486 ReConfigure = FALSE;
487 }
488 } else {
489 //
490 // Need close existing TCP instance and create a new TCP instance for data transmit.
491 //
492 if (HttpInstance->RemoteHost != NULL) {
493 FreePool (HttpInstance->RemoteHost);
494 HttpInstance->RemoteHost = NULL;
495 HttpInstance->RemotePort = 0;
496 }
497 }
498 }
499 }
500
501 if (Configure) {
502 //
503 // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.
504 //
505 if (!HttpInstance->LocalAddressIsIPv6) {
506 Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
507 } else {
508 Status = HttpUrlGetIp6 (Url, UrlParser, &HttpInstance->RemoteIpv6Addr);
509 }
510
511 if (EFI_ERROR (Status)) {
512 HostNameSize = AsciiStrSize (HostName);
513 HostNameStr = AllocateZeroPool (HostNameSize * sizeof (CHAR16));
514 if (HostNameStr == NULL) {
515 Status = EFI_OUT_OF_RESOURCES;
516 goto Error1;
517 }
518
519 AsciiStrToUnicodeStrS (HostName, HostNameStr, HostNameSize);
520 if (!HttpInstance->LocalAddressIsIPv6) {
521 Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);
522 } else {
523 Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);
524 }
525
526 HttpNotify (HttpEventDns, Status);
527
528 FreePool (HostNameStr);
529 if (EFI_ERROR (Status)) {
530 DEBUG ((DEBUG_ERROR, "Error: Could not retrieve the host address from DNS server.\n"));
531 goto Error1;
532 }
533 }
534
535 //
536 // Save the RemotePort and RemoteHost.
537 //
538 ASSERT (HttpInstance->RemoteHost == NULL);
539 HttpInstance->RemotePort = RemotePort;
540 HttpInstance->RemoteHost = HostName;
541 HostName = NULL;
542 }
543
544 if (ReConfigure) {
545 //
546 // The request URL is different from previous calls to Request(), close existing TCP instance.
547 //
548 if (!HttpInstance->LocalAddressIsIPv6) {
549 ASSERT (HttpInstance->Tcp4 != NULL);
550 } else {
551 ASSERT (HttpInstance->Tcp6 != NULL);
552 }
553
554 if (HttpInstance->UseHttps && !TlsConfigure) {
555 Status = TlsCloseSession (HttpInstance);
556 if (EFI_ERROR (Status)) {
557 goto Error1;
558 }
559
560 TlsCloseTxRxEvent (HttpInstance);
561 }
562
563 HttpCloseConnection (HttpInstance);
564 EfiHttpCancel (This, NULL);
565 }
566
567 //
568 // Wrap the HTTP token in HTTP_TOKEN_WRAP
569 //
570 Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
571 if (Wrap == NULL) {
572 Status = EFI_OUT_OF_RESOURCES;
573 goto Error1;
574 }
575
576 Wrap->HttpToken = Token;
577 Wrap->HttpInstance = HttpInstance;
578 if (Request != NULL) {
579 Wrap->TcpWrap.Method = Request->Method;
580 }
581
582 Status = HttpInitSession (
583 HttpInstance,
584 Wrap,
585 Configure || ReConfigure,
586 TlsConfigure
587 );
589 if (EFI_ERROR (Status)) {
590 goto Error2;
591 }
592
593 if (!Configure && !ReConfigure && !TlsConfigure) {
594 //
595 // For the new HTTP token, create TX TCP token events.
596 //
597 Status = HttpCreateTcpTxEvent (Wrap);
598 if (EFI_ERROR (Status)) {
599 goto Error1;
600 }
601 }
602
603 //
604 // Create request message.
605 //
606 FileUrl = Url;
607 if ((Url != NULL) && (*FileUrl != '/')) {
608 //
609 // Convert the absolute-URI to the absolute-path
610 //
611 while (*FileUrl != ':') {
612 FileUrl++;
613 }
614
615 if ((*(FileUrl+1) == '/') && (*(FileUrl+2) == '/')) {
616 FileUrl += 3;
617 while (*FileUrl != '/') {
618 FileUrl++;
619 }
620 } else {
621 Status = EFI_INVALID_PARAMETER;
622 goto Error3;
623 }
624 }
625
626 Status = HttpGenRequestMessage (HttpMsg, FileUrl, &RequestMsg, &RequestMsgSize);
627
628 if (EFI_ERROR (Status) || (NULL == RequestMsg)) {
629 goto Error3;
630 }
631
632 //
633 // Every request we insert a TxToken and a response call would remove the TxToken.
634 // In cases of PUT/POST/PATCH, after an initial request-response pair, we would do a
635 // continuous request without a response call. So, in such cases, where Request
636 // structure is NULL, we would not insert a TxToken.
637 //
638 if (Request != NULL) {
639 Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
640 if (EFI_ERROR (Status)) {
641 goto Error4;
642 }
643 }
644
645 HttpInstance->ConnectionClose = FALSE;
646
647 //
648 // Transmit the request message.
649 //
650 Status = HttpTransmitTcp (
651 HttpInstance,
652 Wrap,
653 (UINT8 *)RequestMsg,
654 RequestMsgSize
655 );
656 if (EFI_ERROR (Status)) {
657 goto Error5;
658 }
659
660 DispatchDpc ();
661
662 if (HostName != NULL) {
663 FreePool (HostName);
664 }
665
666 if (UrlParser != NULL) {
667 HttpUrlFreeParser (UrlParser);
668 }
669
670 return EFI_SUCCESS;
671
672Error5:
673 //
674 // We would have inserted a TxToken only if Request structure is not NULL.
675 // Hence check before we do a remove in this error case.
676 //
677 if (Request != NULL) {
678 NetMapRemoveTail (&HttpInstance->TxTokens, NULL);
679 }
680
681Error4:
682 if (RequestMsg != NULL) {
683 FreePool (RequestMsg);
684 }
685
686Error3:
687 if (HttpInstance->UseHttps) {
688 TlsCloseSession (HttpInstance);
689 TlsCloseTxRxEvent (HttpInstance);
690 }
691
692Error2:
693 HttpCloseConnection (HttpInstance);
694
695 HttpCloseTcpConnCloseEvent (HttpInstance);
696 if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {
697 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
698 Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;
699 }
700
701 if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {
702 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
703 Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;
704 }
705
706Error1:
707 if (HostName != NULL) {
708 FreePool (HostName);
709 }
710
711 if (Wrap != NULL) {
712 FreePool (Wrap);
713 }
714
715 if (UrlParser != NULL) {
716 HttpUrlFreeParser (UrlParser);
717 }
718
719 return Status;
720}
721
734EFIAPI
736 IN NET_MAP *Map,
737 IN NET_MAP_ITEM *Item,
738 IN VOID *Context
739 )
740{
741 EFI_HTTP_TOKEN *Token;
742 HTTP_TOKEN_WRAP *Wrap;
743 HTTP_PROTOCOL *HttpInstance;
744
745 Token = (EFI_HTTP_TOKEN *)Context;
746
747 //
748 // Return EFI_SUCCESS to check the next item in the map if
749 // this one doesn't match.
750 //
751 if ((Token != NULL) && (Token != Item->Key)) {
752 return EFI_SUCCESS;
753 }
754
755 Wrap = (HTTP_TOKEN_WRAP *)Item->Value;
756 ASSERT (Wrap != NULL);
757 HttpInstance = Wrap->HttpInstance;
758
759 if (!HttpInstance->LocalAddressIsIPv6) {
760 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
761 //
762 // Cancel the Token before close its Event.
763 //
764 HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &Wrap->TcpWrap.Rx4Token.CompletionToken);
765
766 //
767 // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
768 //
769 DispatchDpc ();
770 }
771 } else {
772 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
773 //
774 // Cancel the Token before close its Event.
775 //
776 HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &Wrap->TcpWrap.Rx6Token.CompletionToken);
777
778 //
779 // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
780 //
781 DispatchDpc ();
782 }
783 }
784
785 //
786 // If only one item is to be cancel, return EFI_ABORTED to stop
787 // iterating the map any more.
788 //
789 if (Token != NULL) {
790 return EFI_ABORTED;
791 }
792
793 return EFI_SUCCESS;
794}
795
812 IN HTTP_PROTOCOL *HttpInstance,
813 IN EFI_HTTP_TOKEN *Token
814 )
815{
816 EFI_STATUS Status;
817
818 //
819 // First check the tokens queued by EfiHttpRequest().
820 //
821 Status = NetMapIterate (&HttpInstance->TxTokens, HttpCancelTokens, Token);
822 if (EFI_ERROR (Status)) {
823 if (Token != NULL) {
824 if (Status == EFI_ABORTED) {
825 return EFI_SUCCESS;
826 }
827 } else {
828 return Status;
829 }
830 }
831
832 if (!HttpInstance->UseHttps) {
833 //
834 // Then check the tokens queued by EfiHttpResponse(), except for Https.
835 //
836 Status = NetMapIterate (&HttpInstance->RxTokens, HttpCancelTokens, Token);
837 if (EFI_ERROR (Status)) {
838 if (Token != NULL) {
839 if (Status == EFI_ABORTED) {
840 return EFI_SUCCESS;
841 } else {
842 return EFI_NOT_FOUND;
843 }
844 } else {
845 return Status;
846 }
847 }
848 } else {
849 if (!HttpInstance->LocalAddressIsIPv6) {
850 HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken.CompletionToken);
851 } else {
852 HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken.CompletionToken);
853 }
854 }
855
856 return EFI_SUCCESS;
857}
858
882EFIAPI
884 IN EFI_HTTP_PROTOCOL *This,
885 IN EFI_HTTP_TOKEN *Token
886 )
887{
888 HTTP_PROTOCOL *HttpInstance;
889
890 if (This == NULL) {
891 return EFI_INVALID_PARAMETER;
892 }
893
894 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
895
896 if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
897 return EFI_NOT_STARTED;
898 }
899
900 return HttpCancel (HttpInstance, Token);
901}
902
918EFIAPI
920 IN HTTP_BODY_PARSE_EVENT EventType,
921 IN CHAR8 *Data,
922 IN UINTN Length,
923 IN VOID *Context
924 )
925{
926 HTTP_CALLBACK_DATA *CallbackData;
927 HTTP_TOKEN_WRAP *Wrap;
928 UINTN BodyLength;
929 CHAR8 *Body;
930
931 if (EventType != BodyParseEventOnComplete) {
932 return EFI_SUCCESS;
933 }
934
935 if ((Data == NULL) || (Length != 0) || (Context == NULL)) {
936 return EFI_SUCCESS;
937 }
938
939 CallbackData = (HTTP_CALLBACK_DATA *)Context;
940
941 Wrap = (HTTP_TOKEN_WRAP *)(CallbackData->Wrap);
942 Body = CallbackData->ParseData;
943 BodyLength = CallbackData->ParseDataLength;
944
945 if (Data < Body + BodyLength) {
946 Wrap->HttpInstance->NextMsg = Data;
947 } else {
948 Wrap->HttpInstance->NextMsg = NULL;
949 }
950
951 return EFI_SUCCESS;
952}
953
967 IN HTTP_TOKEN_WRAP *Wrap
968 )
969{
970 EFI_STATUS Status;
971 EFI_HTTP_MESSAGE *HttpMsg;
972 CHAR8 *EndofHeader;
973 CHAR8 *HttpHeaders;
974 UINTN SizeofHeaders;
975 UINTN BufferSize;
976 UINTN StatusCode;
977 CHAR8 *Tmp;
978 CHAR8 *HeaderTmp;
979 CHAR8 *StatusCodeStr;
980 UINTN BodyLen;
981 HTTP_PROTOCOL *HttpInstance;
982 EFI_HTTP_TOKEN *Token;
983 NET_MAP_ITEM *Item;
984 HTTP_TOKEN_WRAP *ValueInItem;
985 UINTN HdrLen;
986 NET_FRAGMENT Fragment;
987 UINT32 TimeoutValue;
988 UINTN Index;
989
990 if ((Wrap == NULL) || (Wrap->HttpInstance == NULL)) {
991 return EFI_INVALID_PARAMETER;
992 }
993
994 HttpInstance = Wrap->HttpInstance;
995 Token = Wrap->HttpToken;
996 HttpMsg = Token->Message;
997
998 HttpInstance->EndofHeader = NULL;
999 HttpInstance->HttpHeaders = NULL;
1000 HttpMsg->Headers = NULL;
1001 HttpHeaders = NULL;
1002 SizeofHeaders = 0;
1003 BufferSize = 0;
1004 EndofHeader = NULL;
1005 ValueInItem = NULL;
1006 Fragment.Len = 0;
1007 Fragment.Bulk = NULL;
1008
1009 if (HttpMsg->Data.Response != NULL) {
1010 //
1011 // Check whether we have cached header from previous call.
1012 //
1013 if ((HttpInstance->CacheBody != NULL) && (HttpInstance->NextMsg != NULL)) {
1014 //
1015 // The data is stored at [NextMsg, CacheBody + CacheLen].
1016 //
1017 HdrLen = HttpInstance->CacheBody + HttpInstance->CacheLen - HttpInstance->NextMsg;
1018 HttpHeaders = AllocateZeroPool (HdrLen);
1019 if (HttpHeaders == NULL) {
1020 Status = EFI_OUT_OF_RESOURCES;
1021 goto Error;
1022 }
1023
1024 CopyMem (HttpHeaders, HttpInstance->NextMsg, HdrLen);
1025 FreePool (HttpInstance->CacheBody);
1026 HttpInstance->CacheBody = NULL;
1027 HttpInstance->NextMsg = NULL;
1028 HttpInstance->CacheOffset = 0;
1029 SizeofHeaders = HdrLen;
1030 BufferSize = HttpInstance->CacheLen;
1031
1032 //
1033 // Check whether we cached the whole HTTP headers.
1034 //
1035 EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR);
1036 }
1037
1038 HttpInstance->EndofHeader = &EndofHeader;
1039 HttpInstance->HttpHeaders = &HttpHeaders;
1040
1041 if (HttpInstance->TimeoutEvent == NULL) {
1042 //
1043 // Create TimeoutEvent for response
1044 //
1045 Status = gBS->CreateEvent (
1046 EVT_TIMER,
1047 TPL_CALLBACK,
1048 NULL,
1049 NULL,
1050 &HttpInstance->TimeoutEvent
1051 );
1052 if (EFI_ERROR (Status)) {
1053 goto Error;
1054 }
1055 }
1056
1057 //
1058 // Get HTTP timeout value
1059 //
1060 TimeoutValue = PcdGet32 (PcdHttpIoTimeout);
1061
1062 //
1063 // Start the timer, and wait Timeout seconds to receive the header packet.
1064 //
1065 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, TimeoutValue * TICKS_PER_MS);
1066 if (EFI_ERROR (Status)) {
1067 goto Error;
1068 }
1069
1070 Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize, HttpInstance->TimeoutEvent);
1071
1072 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
1073
1074 if (EFI_ERROR (Status)) {
1075 goto Error;
1076 }
1077
1078 ASSERT (HttpHeaders != NULL);
1079
1080 //
1081 // Cache the part of body.
1082 //
1083 BodyLen = BufferSize - (EndofHeader - HttpHeaders);
1084 if (BodyLen > 0) {
1085 if (HttpInstance->CacheBody != NULL) {
1086 FreePool (HttpInstance->CacheBody);
1087 }
1088
1089 HttpInstance->CacheBody = AllocateZeroPool (BodyLen);
1090 if (HttpInstance->CacheBody == NULL) {
1091 Status = EFI_OUT_OF_RESOURCES;
1092 goto Error;
1093 }
1094
1095 CopyMem (HttpInstance->CacheBody, EndofHeader, BodyLen);
1096 HttpInstance->CacheLen = BodyLen;
1097 }
1098
1099 //
1100 // Check server's HTTP version.
1101 //
1102 if (AsciiStrnCmp (HttpHeaders, "HTTP/1.0", sizeof ("HTTP/1.0") - 1) == 0) {
1103 DEBUG ((DEBUG_VERBOSE, "HTTP: Server version is 1.0. Setting Connection close.\n"));
1104 HttpInstance->ConnectionClose = TRUE;
1105 }
1106
1107 //
1108 // Search for Status Code.
1109 //
1110 StatusCodeStr = HttpHeaders + AsciiStrLen (HTTP_VERSION_STR) + 1;
1111 if (StatusCodeStr == NULL) {
1112 Status = EFI_NOT_READY;
1113 goto Error;
1114 }
1115
1116 StatusCode = AsciiStrDecimalToUintn (StatusCodeStr);
1117
1118 //
1119 // Remove the first line of HTTP message, e.g. "HTTP/1.1 200 OK\r\n".
1120 //
1121 Tmp = AsciiStrStr (HttpHeaders, HTTP_CRLF_STR);
1122 if (Tmp == NULL) {
1123 Status = EFI_NOT_READY;
1124 goto Error;
1125 }
1126
1127 //
1128 // We could have response with just a HTTP message and no headers. For Example,
1129 // "100 Continue". In such cases, we would not want to unnecessarily call a Parse
1130 // method. A "\r\n" following Tmp string again would indicate an end. Compare and
1131 // set SizeofHeaders to 0.
1132 //
1133 Tmp = Tmp + AsciiStrLen (HTTP_CRLF_STR);
1134 if (CompareMem (Tmp, HTTP_CRLF_STR, AsciiStrLen (HTTP_CRLF_STR)) == 0) {
1135 SizeofHeaders = 0;
1136 } else {
1137 SizeofHeaders = SizeofHeaders - (Tmp - HttpHeaders);
1138 }
1139
1140 HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode);
1141 HttpInstance->StatusCode = StatusCode;
1142
1143 Status = EFI_NOT_READY;
1144 ValueInItem = NULL;
1145
1146 //
1147 // In cases of PUT/POST/PATCH, after an initial request-response pair, we would do a
1148 // continuous request without a response call. So, we would not do an insert of
1149 // TxToken. After we have sent the complete file, we will call a response to get
1150 // a final response from server. In such a case, we would not have any TxTokens.
1151 // Hence, check that case before doing a NetMapRemoveHead.
1152 //
1153 if (!NetMapIsEmpty (&HttpInstance->TxTokens)) {
1154 NetMapRemoveHead (&HttpInstance->TxTokens, (VOID **)&ValueInItem);
1155 if (ValueInItem == NULL) {
1156 goto Error;
1157 }
1158
1159 //
1160 // The first Tx Token not transmitted yet, insert back and return error.
1161 //
1162 if (!ValueInItem->TcpWrap.IsTxDone) {
1163 goto Error2;
1164 }
1165 }
1166
1167 if (SizeofHeaders != 0) {
1168 HeaderTmp = AllocateZeroPool (SizeofHeaders);
1169 if (HeaderTmp == NULL) {
1170 Status = EFI_OUT_OF_RESOURCES;
1171 goto Error2;
1172 }
1173
1174 CopyMem (HeaderTmp, Tmp, SizeofHeaders);
1175 FreePool (HttpHeaders);
1176 HttpHeaders = HeaderTmp;
1177
1178 //
1179 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
1180 //
1181 if (mHttpUtilities == NULL) {
1182 Status = EFI_NOT_READY;
1183 goto Error2;
1184 }
1185
1186 //
1187 // Parse the HTTP header into array of key/value pairs.
1188 //
1189 Status = mHttpUtilities->Parse (
1190 mHttpUtilities,
1191 HttpHeaders,
1192 SizeofHeaders,
1193 &HttpMsg->Headers,
1194 &HttpMsg->HeaderCount
1195 );
1196 if (EFI_ERROR (Status)) {
1197 goto Error2;
1198 }
1199
1200 FreePool (HttpHeaders);
1201 HttpHeaders = NULL;
1202
1203 for (Index = 0; Index < HttpMsg->HeaderCount; ++Index) {
1204 if ((AsciiStriCmp ("Connection", HttpMsg->Headers[Index].FieldName) == 0) &&
1205 (AsciiStriCmp ("close", HttpMsg->Headers[Index].FieldValue) == 0))
1206 {
1207 DEBUG ((DEBUG_VERBOSE, "Http: 'Connection: close' header received.\n"));
1208 HttpInstance->ConnectionClose = TRUE;
1209 break;
1210 }
1211 }
1212
1213 //
1214 // Init message-body parser by header information.
1215 //
1216 Status = HttpInitMsgParser (
1217 HttpInstance->Method,
1218 HttpMsg->Data.Response->StatusCode,
1219 HttpMsg->HeaderCount,
1220 HttpMsg->Headers,
1222 (VOID *)(&HttpInstance->CallbackData),
1223 &HttpInstance->MsgParser
1224 );
1225 if (EFI_ERROR (Status)) {
1226 goto Error2;
1227 }
1228
1229 //
1230 // Check whether we received a complete HTTP message.
1231 //
1232 if (HttpInstance->CacheBody != NULL) {
1233 //
1234 // Record the CallbackData data.
1235 //
1236 HttpInstance->CallbackData.Wrap = (VOID *)Wrap;
1237 HttpInstance->CallbackData.ParseData = (VOID *)HttpInstance->CacheBody;
1238 HttpInstance->CallbackData.ParseDataLength = HttpInstance->CacheLen;
1239
1240 //
1241 // Parse message with CallbackData data.
1242 //
1243 Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
1244 if (EFI_ERROR (Status)) {
1245 goto Error2;
1246 }
1247 }
1248
1249 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
1250 //
1251 // Free the MsgParse since we already have a full HTTP message.
1252 //
1253 HttpFreeMsgParser (HttpInstance->MsgParser);
1254 HttpInstance->MsgParser = NULL;
1255 }
1256 }
1257
1258 if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) {
1259 Status = EFI_SUCCESS;
1260 goto Exit;
1261 }
1262 }
1263
1264 //
1265 // Receive the response body.
1266 //
1267 BodyLen = 0;
1268
1269 //
1270 // First check whether we cached some data.
1271 //
1272 if (HttpInstance->CacheBody != NULL) {
1273 //
1274 // Calculate the length of the cached data.
1275 //
1276 if (HttpInstance->NextMsg != NULL) {
1277 //
1278 // We have a cached HTTP message which includes a part of HTTP header of next message.
1279 //
1280 BodyLen = HttpInstance->NextMsg - (HttpInstance->CacheBody + HttpInstance->CacheOffset);
1281 } else {
1282 BodyLen = HttpInstance->CacheLen - HttpInstance->CacheOffset;
1283 }
1284
1285 if (BodyLen > 0) {
1286 //
1287 // We have some cached data. Just copy the data and return.
1288 //
1289 if (HttpMsg->BodyLength < BodyLen) {
1290 CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, HttpMsg->BodyLength);
1291 HttpInstance->CacheOffset = HttpInstance->CacheOffset + HttpMsg->BodyLength;
1292 } else {
1293 //
1294 // Copy all cached data out.
1295 //
1296 CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, BodyLen);
1297 HttpInstance->CacheOffset = BodyLen + HttpInstance->CacheOffset;
1298 HttpMsg->BodyLength = BodyLen;
1299
1300 if (HttpInstance->NextMsg == NULL) {
1301 //
1302 // There is no HTTP header of next message. Just free the cache buffer.
1303 //
1304 FreePool (HttpInstance->CacheBody);
1305 HttpInstance->CacheBody = NULL;
1306 HttpInstance->NextMsg = NULL;
1307 HttpInstance->CacheOffset = 0;
1308 }
1309 }
1310
1311 //
1312 // Return since we already received required data.
1313 //
1314 Status = EFI_SUCCESS;
1315 goto Exit;
1316 }
1317
1318 if ((BodyLen == 0) && (HttpInstance->MsgParser == NULL)) {
1319 //
1320 // We received a complete HTTP message, and we don't have more data to return to caller.
1321 //
1322 HttpMsg->BodyLength = 0;
1323 Status = EFI_SUCCESS;
1324 goto Exit;
1325 }
1326 }
1327
1328 ASSERT (HttpInstance->MsgParser != NULL);
1329
1330 //
1331 // We still need receive more data when there is no cache data and MsgParser is not NULL;
1332 //
1333 if (!HttpInstance->UseHttps) {
1334 Status = HttpTcpReceiveBody (Wrap, HttpMsg);
1335
1336 if (EFI_ERROR (Status)) {
1337 goto Error2;
1338 }
1339 } else {
1340 if (HttpInstance->TimeoutEvent == NULL) {
1341 //
1342 // Create TimeoutEvent for response
1343 //
1344 Status = gBS->CreateEvent (
1345 EVT_TIMER,
1346 TPL_CALLBACK,
1347 NULL,
1348 NULL,
1349 &HttpInstance->TimeoutEvent
1350 );
1351 if (EFI_ERROR (Status)) {
1352 goto Error2;
1353 }
1354 }
1355
1356 //
1357 // Get HTTP timeout value
1358 //
1359 TimeoutValue = PcdGet32 (PcdHttpIoTimeout);
1360
1361 //
1362 // Start the timer, and wait Timeout seconds to receive the body packet.
1363 //
1364 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, TimeoutValue * TICKS_PER_MS);
1365 if (EFI_ERROR (Status)) {
1366 goto Error2;
1367 }
1368
1369 Status = HttpsReceive (HttpInstance, &Fragment, HttpInstance->TimeoutEvent);
1370
1371 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
1372
1373 if (EFI_ERROR (Status)) {
1374 goto Error2;
1375 }
1376
1377 //
1378 // Process the received the body packet.
1379 //
1380 HttpMsg->BodyLength = MIN ((UINTN)Fragment.Len, HttpMsg->BodyLength);
1381
1382 CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
1383
1384 //
1385 // Record the CallbackData data.
1386 //
1387 HttpInstance->CallbackData.Wrap = (VOID *)Wrap;
1388 HttpInstance->CallbackData.ParseData = HttpMsg->Body;
1389 HttpInstance->CallbackData.ParseDataLength = HttpMsg->BodyLength;
1390
1391 //
1392 // Parse Body with CallbackData data.
1393 //
1394 Status = HttpParseMessageBody (
1395 HttpInstance->MsgParser,
1396 HttpMsg->BodyLength,
1397 HttpMsg->Body
1398 );
1399 if (EFI_ERROR (Status)) {
1400 goto Error2;
1401 }
1402
1403 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
1404 //
1405 // Free the MsgParse since we already have a full HTTP message.
1406 //
1407 HttpFreeMsgParser (HttpInstance->MsgParser);
1408 HttpInstance->MsgParser = NULL;
1409 }
1410
1411 //
1412 // Check whether there is the next message header in the HttpMsg->Body.
1413 //
1414 if (HttpInstance->NextMsg != NULL) {
1415 HttpMsg->BodyLength = HttpInstance->NextMsg - (CHAR8 *)HttpMsg->Body;
1416 }
1417
1418 HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
1419 if (HttpInstance->CacheLen != 0) {
1420 if (HttpInstance->CacheBody != NULL) {
1421 FreePool (HttpInstance->CacheBody);
1422 }
1423
1424 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
1425 if (HttpInstance->CacheBody == NULL) {
1426 Status = EFI_OUT_OF_RESOURCES;
1427 goto Error2;
1428 }
1429
1430 CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
1431 HttpInstance->CacheOffset = 0;
1432 if (HttpInstance->NextMsg != NULL) {
1433 HttpInstance->NextMsg = HttpInstance->CacheBody;
1434 }
1435 }
1436
1437 if (Fragment.Bulk != NULL) {
1438 FreePool (Fragment.Bulk);
1439 Fragment.Bulk = NULL;
1440 }
1441
1442 goto Exit;
1443 }
1444
1445 return Status;
1446
1447Exit:
1448 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);
1449 if (Item != NULL) {
1450 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);
1451 }
1452
1453 if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) {
1454 Token->Status = EFI_HTTP_ERROR;
1455 } else {
1456 Token->Status = Status;
1457 }
1458
1459 gBS->SignalEvent (Token->Event);
1460 HttpCloseTcpRxEvent (Wrap);
1461 FreePool (Wrap);
1462 return Status;
1463
1464Error2:
1465 if (ValueInItem != NULL) {
1466 NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);
1467 }
1468
1469Error:
1470 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);
1471 if (Item != NULL) {
1472 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);
1473 }
1474
1475 if (!HttpInstance->UseHttps) {
1476 HttpTcpTokenCleanup (Wrap);
1477 } else {
1478 FreePool (Wrap);
1479 }
1480
1481 if (HttpHeaders != NULL) {
1482 FreePool (HttpHeaders);
1483 HttpHeaders = NULL;
1484 }
1485
1486 if (Fragment.Bulk != NULL) {
1487 FreePool (Fragment.Bulk);
1488 Fragment.Bulk = NULL;
1489 }
1490
1491 if (HttpMsg->Headers != NULL) {
1492 FreePool (HttpMsg->Headers);
1493 HttpMsg->Headers = NULL;
1494 }
1495
1496 if (HttpInstance->CacheBody != NULL) {
1497 FreePool (HttpInstance->CacheBody);
1498 HttpInstance->CacheBody = NULL;
1499 }
1500
1501 if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) {
1502 Token->Status = EFI_HTTP_ERROR;
1503 } else {
1504 Token->Status = Status;
1505 }
1506
1507 gBS->SignalEvent (Token->Event);
1508
1509 return Status;
1510}
1511
1560EFIAPI
1562 IN EFI_HTTP_PROTOCOL *This,
1563 IN EFI_HTTP_TOKEN *Token
1564 )
1565{
1566 EFI_STATUS Status;
1567 EFI_HTTP_MESSAGE *HttpMsg;
1568 HTTP_PROTOCOL *HttpInstance;
1569 HTTP_TOKEN_WRAP *Wrap;
1570
1571 if ((This == NULL) || (Token == NULL)) {
1572 return EFI_INVALID_PARAMETER;
1573 }
1574
1575 HttpMsg = Token->Message;
1576 if (HttpMsg == NULL) {
1577 return EFI_INVALID_PARAMETER;
1578 }
1579
1580 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
1581
1582 if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
1583 return EFI_NOT_STARTED;
1584 }
1585
1586 //
1587 // Check whether the token already existed.
1588 //
1589 if (EFI_ERROR (NetMapIterate (&HttpInstance->RxTokens, HttpTokenExist, Token))) {
1590 return EFI_ACCESS_DENIED;
1591 }
1592
1593 Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
1594 if (Wrap == NULL) {
1595 return EFI_OUT_OF_RESOURCES;
1596 }
1597
1598 Wrap->HttpInstance = HttpInstance;
1599 Wrap->HttpToken = Token;
1600
1601 //
1602 // Notes: For Https, receive token wrapped in HTTP_TOKEN_WRAP is not used to
1603 // receive the https response. A special TlsRxToken is used for receiving TLS
1604 // related messages. It should be a blocking response.
1605 //
1606 if (!HttpInstance->UseHttps) {
1607 Status = HttpCreateTcpRxEvent (Wrap);
1608 if (EFI_ERROR (Status)) {
1609 goto Error;
1610 }
1611 }
1612
1613 Status = NetMapInsertTail (&HttpInstance->RxTokens, Token, Wrap);
1614 if (EFI_ERROR (Status)) {
1615 goto Error;
1616 }
1617
1618 //
1619 // If already have pending RxTokens, return directly.
1620 //
1621 if (NetMapGetCount (&HttpInstance->RxTokens) > 1) {
1622 return EFI_SUCCESS;
1623 }
1624
1625 return HttpResponseWorker (Wrap);
1626
1627Error:
1628 if (Wrap != NULL) {
1629 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
1630 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
1631 }
1632
1633 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
1634 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
1635 }
1636
1637 FreePool (Wrap);
1638 }
1639
1640 return Status;
1641}
1642
1664EFIAPI
1666 IN EFI_HTTP_PROTOCOL *This
1667 )
1668{
1669 EFI_STATUS Status;
1670 HTTP_PROTOCOL *HttpInstance;
1671
1672 if (This == NULL) {
1673 return EFI_INVALID_PARAMETER;
1674 }
1675
1676 HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
1677
1678 if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
1679 return EFI_NOT_STARTED;
1680 }
1681
1682 if (HttpInstance->LocalAddressIsIPv6) {
1683 if (HttpInstance->Tcp6 == NULL) {
1684 return EFI_NOT_STARTED;
1685 }
1686
1687 Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
1688 } else {
1689 if (HttpInstance->Tcp4 == NULL) {
1690 return EFI_NOT_STARTED;
1691 }
1692
1693 Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
1694 }
1695
1696 DispatchDpc ();
1697
1698 return Status;
1699}
UINT64 UINTN
INTN EFIAPI AsciiStriCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:814
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
INTN EFIAPI AsciiStrnCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString, IN UINTN Length)
Definition: String.c:872
RETURN_STATUS EFIAPI UnicodeStrToAsciiStrS(IN CONST CHAR16 *Source, OUT CHAR8 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2650
UINTN EFIAPI AsciiStrDecimalToUintn(IN CONST CHAR8 *String)
Definition: String.c:1006
RETURN_STATUS EFIAPI AsciiStrToUnicodeStrS(IN CONST CHAR8 *Source, OUT CHAR16 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2873
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR8 *EFIAPI AsciiStrStr(IN CONST CHAR8 *String, IN CONST CHAR8 *SearchString)
Definition: String.c:931
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI DispatchDpc(VOID)
Definition: DpcLib.c:86
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
@ HttpEventInitSession
Definition: HttpCallback.h:59
@ HttpEventDns
Definition: HttpCallback.h:31
EFI_STATUS HttpDns4(IN HTTP_PROTOCOL *HttpInstance, IN CHAR16 *HostName, OUT EFI_IPv4_ADDRESS *IpAddress)
Definition: HttpDns.c:25
EFI_STATUS HttpDns6(IN HTTP_PROTOCOL *HttpInstance, IN CHAR16 *HostName, OUT EFI_IPv6_ADDRESS *IpAddress)
Definition: HttpDns.c:234
EFI_STATUS EFIAPI EfiHttpConfigure(IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_CONFIG_DATA *HttpConfigData OPTIONAL)
Definition: HttpImpl.c:128
EFI_STATUS EFIAPI EfiHttpGetModeData(IN EFI_HTTP_PROTOCOL *This, OUT EFI_HTTP_CONFIG_DATA *HttpConfigData)
Definition: HttpImpl.c:48
EFI_STATUS EFIAPI EfiHttpCancel(IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_TOKEN *Token)
Definition: HttpImpl.c:883
EFI_STATUS HttpResponseWorker(IN HTTP_TOKEN_WRAP *Wrap)
Definition: HttpImpl.c:966
EFI_STATUS EFIAPI HttpCancelTokens(IN NET_MAP *Map, IN NET_MAP_ITEM *Item, IN VOID *Context)
Definition: HttpImpl.c:735
EFI_STATUS EFIAPI EfiHttpResponse(IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_TOKEN *Token)
Definition: HttpImpl.c:1561
EFI_STATUS EFIAPI EfiHttpPoll(IN EFI_HTTP_PROTOCOL *This)
Definition: HttpImpl.c:1665
EFI_STATUS EFIAPI EfiHttpRequest(IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_TOKEN *Token)
Definition: HttpImpl.c:229
EFI_STATUS HttpCancel(IN HTTP_PROTOCOL *HttpInstance, IN EFI_HTTP_TOKEN *Token)
Definition: HttpImpl.c:811
EFI_STATUS EFIAPI HttpBodyParserCallback(IN HTTP_BODY_PARSE_EVENT EventType, IN CHAR8 *Data, IN UINTN Length, IN VOID *Context)
Definition: HttpImpl.c:919
EFI_STATUS EFIAPI HttpUrlGetHostName(IN CHAR8 *Url, IN VOID *UrlParser, OUT CHAR8 **HostName)
Definition: DxeHttpLib.c:506
EFI_STATUS EFIAPI HttpInitMsgParser(IN EFI_HTTP_METHOD Method, IN EFI_HTTP_STATUS_CODE StatusCode, IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN HTTP_BODY_PARSER_CALLBACK Callback, IN VOID *Context, OUT VOID **MsgParser)
Definition: DxeHttpLib.c:1050
EFI_STATUS EFIAPI HttpUrlGetPort(IN CHAR8 *Url, IN VOID *UrlParser, OUT UINT16 *Port)
Definition: DxeHttpLib.c:702
EFI_STATUS EFIAPI HttpUrlGetIp6(IN CHAR8 *Url, IN VOID *UrlParser, OUT EFI_IPv6_ADDRESS *Ip6Address)
Definition: DxeHttpLib.c:626
EFI_STATUS EFIAPI HttpGenRequestMessage(IN CONST EFI_HTTP_MESSAGE *Message, IN CONST CHAR8 *Url, OUT CHAR8 **RequestMsg, OUT UINTN *RequestMsgSize)
Definition: DxeHttpLib.c:1775
EFI_STATUS EFIAPI HttpParseMessageBody(IN OUT VOID *MsgParser, IN UINTN BodyLength, IN CHAR8 *Body)
Definition: DxeHttpLib.c:1131
VOID EFIAPI HttpFreeMsgParser(IN VOID *MsgParser)
Definition: DxeHttpLib.c:1474
VOID EFIAPI HttpUrlFreeParser(IN VOID *UrlParser)
Definition: DxeHttpLib.c:836
EFI_STATUS EFIAPI HttpParseUrl(IN CHAR8 *Url, IN UINT32 Length, IN BOOLEAN IsConnectMethod, OUT VOID **UrlParser)
Definition: DxeHttpLib.c:370
BOOLEAN EFIAPI HttpIsMessageComplete(IN VOID *MsgParser)
Definition: DxeHttpLib.c:1411
EFI_HTTP_STATUS_CODE EFIAPI HttpMappingToStatusCode(IN UINTN StatusCode)
Definition: DxeHttpLib.c:2008
VOID HttpTcpTokenCleanup(IN HTTP_TOKEN_WRAP *Wrap)
Definition: HttpProto.c:2147
EFI_STATUS HttpCreateTcpRxEvent(IN HTTP_TOKEN_WRAP *Wrap)
Definition: HttpProto.c:524
EFI_STATUS HttpInitSession(IN HTTP_PROTOCOL *HttpInstance, IN HTTP_TOKEN_WRAP *Wrap, IN BOOLEAN Configure, IN BOOLEAN TlsConfigure)
Definition: HttpProto.c:1407
EFI_STATUS EFIAPI HttpTokenExist(IN NET_MAP *Map, IN NET_MAP_ITEM *Item, IN VOID *Context)
Definition: HttpProto.c:1659
EFI_STATUS HttpInitProtocol(IN OUT HTTP_PROTOCOL *HttpInstance, IN BOOLEAN IpVersion)
Definition: HttpProto.c:617
VOID HttpCleanProtocol(IN HTTP_PROTOCOL *HttpInstance)
Definition: HttpProto.c:820
EFI_STATUS HttpTcpReceiveBody(IN HTTP_TOKEN_WRAP *Wrap, IN EFI_HTTP_MESSAGE *HttpMsg)
Definition: HttpProto.c:2087
EFI_STATUS HttpCloseConnection(IN HTTP_PROTOCOL *HttpInstance)
Definition: HttpProto.c:1001
VOID HttpNotify(IN EDKII_HTTP_CALLBACK_EVENT Event, IN EFI_STATUS EventStatus)
Definition: HttpProto.c:2213
EFI_STATUS HttpTransmitTcp(IN HTTP_PROTOCOL *HttpInstance, IN HTTP_TOKEN_WRAP *Wrap, IN UINT8 *TxString, IN UINTN TxStringLen)
Definition: HttpProto.c:1483
EFI_STATUS HttpTcpReceiveHeader(IN HTTP_PROTOCOL *HttpInstance, IN OUT UINTN *SizeofHeaders, IN OUT UINTN *BufferSize, IN EFI_EVENT Timeout)
Definition: HttpProto.c:1822
EFI_STATUS EFIAPI HttpTcpNotReady(IN NET_MAP *Map, IN NET_MAP_ITEM *Item, IN VOID *Context)
Definition: HttpProto.c:1691
VOID HttpCloseTcpConnCloseEvent(IN HTTP_PROTOCOL *HttpInstance)
Definition: HttpProto.c:374
EFI_STATUS HttpCreateTcpTxEvent(IN HTTP_TOKEN_WRAP *Wrap)
Definition: HttpProto.c:413
VOID HttpCloseTcpRxEvent(IN HTTP_TOKEN_WRAP *Wrap)
Definition: HttpProto.c:576
EFI_STATUS EFIAPI HttpsReceive(IN HTTP_PROTOCOL *HttpInstance, IN OUT NET_FRAGMENT *Fragment, IN EFI_EVENT Timeout)
EFI_STATUS EFIAPI TlsCreateChild(IN HTTP_PROTOCOL *HttpInstance)
Definition: HttpsSupport.c:148
BOOLEAN IsHttpsUrl(IN CHAR8 *Url)
Definition: HttpsSupport.c:119
VOID EFIAPI TlsCloseTxRxEvent(IN HTTP_PROTOCOL *HttpInstance)
Definition: HttpsSupport.c:344
EFI_STATUS EFIAPI TlsCloseSession(IN HTTP_PROTOCOL *HttpInstance)
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI NetMapRemoveTail(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1754
EFI_STATUS EFIAPI NetLibAsciiStrToIp4(IN CONST CHAR8 *String, OUT EFI_IPv4_ADDRESS *Ip4Address)
Definition: DxeNetLib.c:3068
NET_MAP_ITEM *EFIAPI NetMapFindKey(IN NET_MAP *Map, IN VOID *Key)
Definition: DxeNetLib.c:1629
EFI_STATUS EFIAPI NetMapInsertHead(IN OUT NET_MAP *Map, IN VOID *Key, IN VOID *Value OPTIONAL)
Definition: DxeNetLib.c:1512
BOOLEAN EFIAPI NetMapIsEmpty(IN NET_MAP *Map)
Definition: DxeNetLib.c:1413
VOID *EFIAPI NetMapRemoveItem(IN OUT NET_MAP *Map, IN OUT NET_MAP_ITEM *Item, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1671
VOID *EFIAPI NetMapRemoveHead(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1710
EFI_STATUS EFIAPI NetMapInsertTail(IN OUT NET_MAP *Map, IN VOID *Key, IN VOID *Value OPTIONAL)
Definition: DxeNetLib.c:1556
EFI_STATUS EFIAPI NetMapIterate(IN NET_MAP *Map, IN NET_MAP_CALLBACK CallBack, IN VOID *Arg OPTIONAL)
Definition: DxeNetLib.c:1800
UINTN EFIAPI NetMapGetCount(IN NET_MAP *Map)
Definition: DxeNetLib.c:1433
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
@ EfiTlsSessionDataTransferring
Definition: Tls.h:291
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
CHAR8 * FieldValue
Definition: Http.h:220
CHAR8 * FieldName
Definition: Http.h:215
UINTN BodyLength
Definition: Http.h:257
EFI_HTTP_HEADER * Headers
Definition: Http.h:253
union EFI_HTTP_MESSAGE::@577 Data
UINTN HeaderCount
Definition: Http.h:246
VOID * Body
Definition: Http.h:262
EFI_HTTP_RESPONSE_DATA * Response
Definition: Http.h:240
EFI_HTTP_REQUEST_DATA * Request
Definition: Http.h:235
CHAR16 * Url
Definition: Http.h:194
EFI_HTTP_METHOD Method
Definition: Http.h:187
EFI_HTTP_STATUS_CODE StatusCode
Definition: Http.h:204
EFI_EVENT Event
Definition: Http.h:274
EFI_HTTP_MESSAGE * Message
Definition: Http.h:290
EFI_STATUS Status
Definition: Http.h:286
EFI_TCP4_COMPLETION_TOKEN CompletionToken
Definition: Tcp4.h:205
EFI_TCP6_COMPLETION_TOKEN CompletionToken
Definition: Tcp6.h:434