2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "HttpDriver.h"
18 The common notify function used in HTTP driver.
20 @param[in] Event The event signaled.
21 @param[in] Context The context.
31 if ((Event
== NULL
) || (Context
== NULL
)) {
35 *((BOOLEAN
*) Context
) = TRUE
;
39 The notify function associated with TxToken for Tcp4->Transmit().
41 @param[in] Context The context.
46 HttpTcpTransmitNotifyDpc (
50 HTTP_TOKEN_WRAP
*Wrap
;
52 if (Context
== NULL
) {
56 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
57 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.TxToken
.CompletionToken
.Status
;
58 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
63 if (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
64 FreePool (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
67 if (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
!= NULL
) {
68 gBS
->CloseEvent (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
);
71 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
74 // Check pending TxTokens and sent out.
76 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
81 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
83 @param Event The receive event delivered to TCP for transmit.
84 @param Context Context for the callback.
89 HttpTcpTransmitNotify (
95 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
97 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
102 The notify function associated with RxToken for Tcp4->Receive ().
104 @param[in] Context The context.
109 HttpTcpReceiveNotifyDpc (
113 HTTP_TOKEN_WRAP
*Wrap
;
117 HTTP_PROTOCOL
*HttpInstance
;
119 if (Context
== NULL
) {
123 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
124 gBS
->CloseEvent (Wrap
->TcpWrap
.RxToken
.CompletionToken
.Event
);
125 if (EFI_ERROR (Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
)) {
129 HttpInstance
= Wrap
->HttpInstance
;
132 // Check whether we receive a complete HTTP message.
134 ASSERT (HttpInstance
->MsgParser
!= NULL
);
136 Length
= (UINTN
) Wrap
->TcpWrap
.RxData
.FragmentTable
[0].FragmentLength
;
137 Status
= HttpParseMessageBody (
138 HttpInstance
->MsgParser
,
140 Wrap
->HttpToken
->Message
->Body
142 if (EFI_ERROR (Status
)) {
146 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
148 // Free the MsgParse since we already have a full HTTP message.
150 HttpFreeMsgParser (HttpInstance
->MsgParser
);
151 HttpInstance
->MsgParser
= NULL
;
154 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
155 ASSERT (HttpInstance
->CacheBody
== NULL
);
157 // We receive part of header of next HTTP msg.
159 if (HttpInstance
->NextMsg
!= NULL
) {
160 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
161 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
162 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
163 if (HttpInstance
->CacheLen
!= 0) {
164 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
165 if (HttpInstance
->CacheBody
== NULL
) {
168 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
169 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
170 HttpInstance
->CacheOffset
= 0;
174 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
176 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
180 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
181 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
;
183 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
186 // Check pending RxTokens and receive the HTTP message.
188 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
194 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
196 @param Event The receive event delivered to TCP for receive.
197 @param Context Context for the callback.
202 HttpTcpReceiveNotify (
208 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
210 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
215 Create events for the TCP4 connection token and TCP4 close token.
217 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
219 @retval EFI_SUCCESS The events are created successfully.
220 @retval others Other error as indicated.
224 HttpCreateTcp4ConnCloseEvent (
225 IN HTTP_PROTOCOL
*HttpInstance
230 // Create events for variuos asynchronous operations.
232 Status
= gBS
->CreateEvent (
236 &HttpInstance
->IsConnDone
,
237 &HttpInstance
->ConnToken
.CompletionToken
.Event
239 if (EFI_ERROR (Status
)) {
244 // Initialize CloseToken
246 Status
= gBS
->CreateEvent (
250 &HttpInstance
->IsCloseDone
,
251 &HttpInstance
->CloseToken
.CompletionToken
.Event
253 if (EFI_ERROR (Status
)) {
264 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
271 Close events in the TCP4 connection token and TCP4 close token.
273 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
277 HttpCloseTcp4ConnCloseEvent (
278 IN HTTP_PROTOCOL
*HttpInstance
281 ASSERT (HttpInstance
!= NULL
);
283 if (NULL
!= HttpInstance
->ConnToken
.CompletionToken
.Event
) {
284 gBS
->CloseEvent (HttpInstance
->ConnToken
.CompletionToken
.Event
);
285 HttpInstance
->ConnToken
.CompletionToken
.Event
= NULL
;
288 if (NULL
!= HttpInstance
->CloseToken
.CompletionToken
.Event
) {
289 gBS
->CloseEvent(HttpInstance
->CloseToken
.CompletionToken
.Event
);
290 HttpInstance
->CloseToken
.CompletionToken
.Event
= NULL
;
295 Create event for the TCP4 transmit token.
297 @param[in] Wrap Point to HTTP token's wrap data.
299 @retval EFI_SUCCESS The events is created successfully.
300 @retval others Other error as indicated.
304 HttpCreateTcp4TxEvent (
305 IN HTTP_TOKEN_WRAP
*Wrap
309 HTTP_PROTOCOL
*HttpInstance
;
310 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
312 HttpInstance
= Wrap
->HttpInstance
;
313 TcpWrap
= &Wrap
->TcpWrap
;
315 Status
= gBS
->CreateEvent (
318 HttpTcpTransmitNotify
,
320 &TcpWrap
->TxToken
.CompletionToken
.Event
322 if (EFI_ERROR (Status
)) {
326 TcpWrap
->TxData
.Push
= TRUE
;
327 TcpWrap
->TxData
.Urgent
= FALSE
;
328 TcpWrap
->TxData
.FragmentCount
= 1;
329 TcpWrap
->TxToken
.Packet
.TxData
= &Wrap
->TcpWrap
.TxData
;
330 TcpWrap
->TxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
336 Create event for the TCP4 receive token which is used to receive HTTP header.
338 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
340 @retval EFI_SUCCESS The events is created successfully.
341 @retval others Other error as indicated.
345 HttpCreateTcp4RxEventForHeader (
346 IN HTTP_PROTOCOL
*HttpInstance
352 Status
= gBS
->CreateEvent (
356 &HttpInstance
->IsRxDone
,
357 &HttpInstance
->RxToken
.CompletionToken
.Event
359 if (EFI_ERROR (Status
)) {
363 HttpInstance
->RxData
.FragmentCount
= 1;
364 HttpInstance
->RxToken
.Packet
.RxData
= &HttpInstance
->RxData
;
365 HttpInstance
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
371 Create event for the TCP4 receive token which is used to receive HTTP body.
373 @param[in] Wrap Point to HTTP token's wrap data.
375 @retval EFI_SUCCESS The events is created successfully.
376 @retval others Other error as indicated.
380 HttpCreateTcp4RxEvent (
381 IN HTTP_TOKEN_WRAP
*Wrap
385 HTTP_PROTOCOL
*HttpInstance
;
386 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
388 HttpInstance
= Wrap
->HttpInstance
;
389 TcpWrap
= &Wrap
->TcpWrap
;
391 Status
= gBS
->CreateEvent (
394 HttpTcpReceiveNotify
,
396 &TcpWrap
->RxToken
.CompletionToken
.Event
398 if (EFI_ERROR (Status
)) {
402 TcpWrap
->RxData
.FragmentCount
= 1;
403 TcpWrap
->RxToken
.Packet
.RxData
= &Wrap
->TcpWrap
.RxData
;
404 TcpWrap
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
410 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
412 @param[in] HttpSb The HTTP service private instance.
413 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
415 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
416 @retval Others Other error as indicated.
421 IN HTTP_SERVICE
*HttpSb
,
422 IN OUT HTTP_PROTOCOL
*HttpInstance
428 ASSERT ((HttpSb
!= NULL
) && (HttpInstance
!= NULL
));
430 HttpInstance
->Signature
= HTTP_PROTOCOL_SIGNATURE
;
431 CopyMem (&HttpInstance
->Http
, &mEfiHttpTemplate
, sizeof (HttpInstance
->Http
));
432 HttpInstance
->Service
= HttpSb
;
437 Status
= NetLibCreateServiceChild (
438 HttpInstance
->Service
->ControllerHandle
,
439 HttpInstance
->Service
->ImageHandle
,
440 &gEfiTcp4ServiceBindingProtocolGuid
,
441 &HttpInstance
->TcpChildHandle
444 if (EFI_ERROR (Status
)) {
448 Status
= gBS
->OpenProtocol (
449 HttpInstance
->TcpChildHandle
,
450 &gEfiTcp4ProtocolGuid
,
451 (VOID
**) &Interface
,
452 HttpInstance
->Service
->ImageHandle
,
453 HttpInstance
->Service
->ControllerHandle
,
454 EFI_OPEN_PROTOCOL_BY_DRIVER
457 if (EFI_ERROR (Status
)) {
461 Status
= gBS
->OpenProtocol (
462 HttpInstance
->TcpChildHandle
,
463 &gEfiTcp4ProtocolGuid
,
464 (VOID
**) &HttpInstance
->Tcp4
,
465 HttpInstance
->Service
->ImageHandle
,
466 HttpInstance
->Handle
,
467 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
469 if (EFI_ERROR(Status
)) {
473 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
474 if (HttpInstance
->Url
== NULL
) {
475 Status
= EFI_OUT_OF_RESOURCES
;
479 NetMapInit (&HttpInstance
->TxTokens
);
480 NetMapInit (&HttpInstance
->RxTokens
);
486 if (HttpInstance
->TcpChildHandle
!= NULL
) {
488 HttpInstance
->TcpChildHandle
,
489 &gEfiTcp4ProtocolGuid
,
490 HttpInstance
->Service
->ImageHandle
,
491 HttpInstance
->Service
->ControllerHandle
495 HttpInstance
->TcpChildHandle
,
496 &gEfiTcp4ProtocolGuid
,
497 HttpInstance
->Service
->ImageHandle
,
501 NetLibDestroyServiceChild (
502 HttpInstance
->Service
->ControllerHandle
,
503 HttpInstance
->Service
->ImageHandle
,
504 &gEfiTcp4ServiceBindingProtocolGuid
,
505 HttpInstance
->TcpChildHandle
514 Clean up the HTTP child, release all the resources used by it.
516 @param[in] HttpInstance The HTTP child to clean up.
521 IN HTTP_PROTOCOL
*HttpInstance
524 HttpCloseConnection (HttpInstance
);
526 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
528 if (HttpInstance
->CacheBody
!= NULL
) {
529 FreePool (HttpInstance
->CacheBody
);
530 HttpInstance
->CacheBody
= NULL
;
531 HttpInstance
->NextMsg
= NULL
;
534 if (HttpInstance
->RemoteHost
!= NULL
) {
535 FreePool (HttpInstance
->RemoteHost
);
536 HttpInstance
->RemoteHost
= NULL
;
539 if (HttpInstance
->MsgParser
!= NULL
) {
540 HttpFreeMsgParser (HttpInstance
->MsgParser
);
541 HttpInstance
->MsgParser
= NULL
;
544 if (HttpInstance
->Url
!= NULL
) {
545 FreePool (HttpInstance
->Url
);
546 HttpInstance
->Url
= NULL
;
549 NetMapClean (&HttpInstance
->TxTokens
);
550 NetMapClean (&HttpInstance
->RxTokens
);
552 if (HttpInstance
->TcpChildHandle
!= NULL
) {
554 HttpInstance
->TcpChildHandle
,
555 &gEfiTcp4ProtocolGuid
,
556 HttpInstance
->Service
->ImageHandle
,
557 HttpInstance
->Service
->ControllerHandle
561 HttpInstance
->TcpChildHandle
,
562 &gEfiTcp4ProtocolGuid
,
563 HttpInstance
->Service
->ImageHandle
,
567 NetLibDestroyServiceChild (
568 HttpInstance
->Service
->ControllerHandle
,
569 HttpInstance
->Service
->ImageHandle
,
570 &gEfiTcp4ServiceBindingProtocolGuid
,
571 HttpInstance
->TcpChildHandle
577 Establish TCP connection with HTTP server.
579 @param[in] HttpInstance The HTTP instance private data.
581 @retval EFI_SUCCESS The TCP connection is established.
582 @retval Others Other error as indicated.
586 HttpCreateConnection (
587 IN HTTP_PROTOCOL
*HttpInstance
593 // Create events for variuos asynchronous operations.
595 HttpInstance
->IsConnDone
= FALSE
;
598 // Connect to Http server
600 HttpInstance
->ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
601 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->ConnToken
);
602 if (EFI_ERROR (Status
)) {
603 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
607 while (!HttpInstance
->IsConnDone
) {
608 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
611 Status
= HttpInstance
->ConnToken
.CompletionToken
.Status
;
613 if (!EFI_ERROR (Status
)) {
614 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
621 Close existing TCP connection.
623 @param[in] HttpInstance The HTTP instance private data.
625 @retval EFI_SUCCESS The TCP connection is closed.
626 @retval Others Other error as indicated.
630 HttpCloseConnection (
631 IN HTTP_PROTOCOL
*HttpInstance
636 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
637 HttpInstance
->CloseToken
.AbortOnClose
= TRUE
;
638 HttpInstance
->IsCloseDone
= FALSE
;
640 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->CloseToken
);
641 if (EFI_ERROR (Status
)) {
645 while (!HttpInstance
->IsCloseDone
) {
646 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
650 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
655 Configure TCP4 protocol child.
657 @param[in] HttpInstance The HTTP instance private data.
658 @param[in] Wrap The HTTP token's wrap data.
660 @retval EFI_SUCCESS The TCP4 protocol child is configured.
661 @retval Others Other error as indicated.
666 IN HTTP_PROTOCOL
*HttpInstance
,
667 IN HTTP_TOKEN_WRAP
*Wrap
671 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
672 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
673 EFI_TCP4_OPTION
*Tcp4Option
;
674 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
676 ASSERT (HttpInstance
!= NULL
);
677 TcpWrap
= &Wrap
->TcpWrap
;
680 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
681 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
683 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
684 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
685 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
687 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
688 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
689 if (!Tcp4AP
->UseDefaultAddress
) {
690 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
691 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
694 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
695 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
696 Tcp4AP
->ActiveFlag
= TRUE
;
697 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
699 Tcp4Option
= Tcp4CfgData
->ControlOption
;
700 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
701 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
702 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
703 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
704 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
705 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
706 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
707 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
708 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
709 Tcp4Option
->EnableNagle
= TRUE
;
710 Tcp4CfgData
->ControlOption
= Tcp4Option
;
712 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
713 if (EFI_ERROR (Status
)) {
714 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
718 Status
= HttpCreateTcp4ConnCloseEvent (HttpInstance
);
719 if (EFI_ERROR (Status
)) {
723 Status
= HttpCreateTcp4TxEvent (Wrap
);
724 if (EFI_ERROR (Status
)) {
728 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
734 Check existing TCP connection, if in error state, receover TCP4 connection.
736 @param[in] HttpInstance The HTTP instance private data.
738 @retval EFI_SUCCESS The TCP connection is established.
739 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
740 @retval Others Other error as indicated.
745 IN HTTP_PROTOCOL
*HttpInstance
749 EFI_TCP4_CONNECTION_STATE Tcp4State
;
752 if (HttpInstance
->State
!= HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
753 return EFI_NOT_READY
;
756 Status
= HttpInstance
->Tcp4
->GetModeData(
764 if (EFI_ERROR(Status
)){
765 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
769 if (Tcp4State
> Tcp4StateEstablished
) {
770 HttpCloseConnection(HttpInstance
);
773 return HttpCreateConnection (HttpInstance
);
777 Send the HTTP message through TCP4.
779 @param[in] HttpInstance The HTTP instance private data.
780 @param[in] Wrap The HTTP token's wrap data.
781 @param[in] TxString Buffer containing the HTTP message string.
782 @param[in] TxStringLen Length of the HTTP message string in bytes.
784 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
785 @retval Others Other error as indicated.
790 IN HTTP_PROTOCOL
*HttpInstance
,
791 IN HTTP_TOKEN_WRAP
*Wrap
,
797 EFI_TCP4_IO_TOKEN
*TxToken
;
798 EFI_TCP4_PROTOCOL
*Tcp4
;
800 Tcp4
= HttpInstance
->Tcp4
;
801 TxToken
= &Wrap
->TcpWrap
.TxToken
;
803 TxToken
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
804 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
805 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
806 TxToken
->CompletionToken
.Status
= EFI_NOT_READY
;
808 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
809 Status
= Tcp4
->Transmit (Tcp4
, TxToken
);
810 if (EFI_ERROR (Status
)) {
811 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
819 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined
820 in UEFI 2.5 specification.
822 @param[in] StatusCode The status code value in HTTP message.
824 @return Value defined in EFI_HTTP_STATUS_CODE .
828 HttpMappingToStatusCode (
832 switch (StatusCode
) {
834 return HTTP_STATUS_100_CONTINUE
;
836 return HTTP_STATUS_101_SWITCHING_PROTOCOLS
;
838 return HTTP_STATUS_200_OK
;
840 return HTTP_STATUS_201_CREATED
;
842 return HTTP_STATUS_202_ACCEPTED
;
844 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION
;
846 return HTTP_STATUS_204_NO_CONTENT
;
848 return HTTP_STATUS_205_RESET_CONTENT
;
850 return HTTP_STATUS_206_PARTIAL_CONTENT
;
852 return HTTP_STATUS_300_MULTIPLE_CHIOCES
;
854 return HTTP_STATUS_301_MOVED_PERMANENTLY
;
856 return HTTP_STATUS_302_FOUND
;
858 return HTTP_STATUS_303_SEE_OTHER
;
860 return HTTP_STATUS_304_NOT_MODIFIED
;
862 return HTTP_STATUS_305_USE_PROXY
;
864 return HTTP_STATUS_307_TEMPORARY_REDIRECT
;
866 return HTTP_STATUS_400_BAD_REQUEST
;
868 return HTTP_STATUS_401_UNAUTHORIZED
;
870 return HTTP_STATUS_402_PAYMENT_REQUIRED
;
872 return HTTP_STATUS_403_FORBIDDEN
;
874 return HTTP_STATUS_404_NOT_FOUND
;
876 return HTTP_STATUS_405_METHOD_NOT_ALLOWED
;
878 return HTTP_STATUS_406_NOT_ACCEPTABLE
;
880 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED
;
882 return HTTP_STATUS_408_REQUEST_TIME_OUT
;
884 return HTTP_STATUS_409_CONFLICT
;
886 return HTTP_STATUS_410_GONE
;
888 return HTTP_STATUS_411_LENGTH_REQUIRED
;
890 return HTTP_STATUS_412_PRECONDITION_FAILED
;
892 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE
;
894 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE
;
896 return HTTP_STATUS_415_UNSUPPORETD_MEDIA_TYPE
;
898 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED
;
900 return HTTP_STATUS_417_EXPECTATION_FAILED
;
902 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR
;
904 return HTTP_STATUS_501_NOT_IMIPLEMENTED
;
906 return HTTP_STATUS_502_BAD_GATEWAY
;
908 return HTTP_STATUS_503_SERVICE_UNAVAILABLE
;
910 return HTTP_STATUS_504_GATEWAY_TIME_OUT
;
912 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
;
915 return HTTP_STATUS_UNSUPPORTED_STATUS
;
920 Check whether the user's token or event has already
921 been enqueue on HTTP TxToken or RxToken list.
923 @param[in] Map The container of either user's transmit or receive
925 @param[in] Item Current item to check against.
926 @param[in] Context The Token to check againist.
928 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
929 @retval EFI_SUCCESS The current item isn't the same token/event as the
937 IN NET_MAP_ITEM
*Item
,
941 EFI_HTTP_TOKEN
*Token
;
942 EFI_HTTP_TOKEN
*TokenInItem
;
944 Token
= (EFI_HTTP_TOKEN
*) Context
;
945 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
947 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
948 return EFI_ACCESS_DENIED
;
955 Check whether the HTTP message associated with TxToken is already sent out.
957 @param[in] Map The container of TxToken.
958 @param[in] Item Current item to check against.
959 @param[in] Context The Token to check againist.
961 @retval EFI_NOT_READY The HTTP message is still queued in the list.
962 @retval EFI_SUCCESS The HTTP message has been sent out.
969 IN NET_MAP_ITEM
*Item
,
973 HTTP_TOKEN_WRAP
*ValueInItem
;
975 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
977 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
978 return EFI_NOT_READY
;
985 Transmit the HTTP mssage by processing the associated HTTP token.
987 @param[in] Map The container of TxToken.
988 @param[in] Item Current item to check against.
989 @param[in] Context The Token to check againist.
991 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
992 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1000 IN NET_MAP_ITEM
*Item
,
1004 HTTP_TOKEN_WRAP
*ValueInItem
;
1009 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1010 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1015 // Parse the URI of the remote host.
1017 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1019 return EFI_OUT_OF_RESOURCES
;
1022 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1025 // Create request message.
1027 RequestStr
= HttpGenRequestString (
1028 ValueInItem
->HttpInstance
,
1029 ValueInItem
->HttpToken
->Message
,
1033 if (RequestStr
== NULL
) {
1034 return EFI_OUT_OF_RESOURCES
;
1038 // Transmit the request message.
1040 Status
= HttpTransmitTcp4 (
1041 ValueInItem
->HttpInstance
,
1043 (UINT8
*) RequestStr
,
1044 AsciiStrLen (RequestStr
)
1046 FreePool (RequestStr
);
1051 Receive the HTTP response by processing the associated HTTP token.
1053 @param[in] Map The container of RxToken.
1054 @param[in] Item Current item to check against.
1055 @param[in] Context The Token to check againist.
1057 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1059 @retval Others Other error as indicated.
1066 IN NET_MAP_ITEM
*Item
,
1071 // Process the queued HTTP response.
1073 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1077 Generate HTTP request string.
1079 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1080 @param[in] Message Pointer to storage containing HTTP message data.
1081 @param[in] Url The URL of a remote host.
1083 @return Pointer to the created HTTP request string.
1084 @return NULL if any error occured.
1088 HttpGenRequestString (
1089 IN HTTP_PROTOCOL
*HttpInstance
,
1090 IN EFI_HTTP_MESSAGE
*Message
,
1102 EFI_HTTP_HEADER
**AppendList
;
1105 ASSERT (HttpInstance
!= NULL
);
1106 ASSERT (Message
!= NULL
);
1108 DEBUG ((EFI_D_ERROR
, "HttpMethod - %x\n", Message
->Data
.Request
->Method
));
1118 AppendList
= AllocateZeroPool (sizeof (EFI_HTTP_HEADER
*) * (Message
->HeaderCount
));
1119 if (AppendList
== NULL
) {
1123 for(Index
= 0; Index
< Message
->HeaderCount
; Index
++){
1124 AppendList
[Index
] = &Message
->Headers
[Index
];
1128 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
1130 if (mHttpUtilities
== NULL
) {
1135 // Build raw unformatted HTTP headers.
1137 Status
= mHttpUtilities
->Build (
1143 Message
->HeaderCount
,
1148 FreePool (AppendList
);
1149 if (EFI_ERROR (Status
) || HttpHdr
== NULL
) {
1154 // Calculate HTTP message length.
1156 MsgSize
= Message
->BodyLength
+ HTTP_MAXIMUM_METHOD_LEN
+ AsciiStrLen (Url
) +
1157 AsciiStrLen (HTTP_VERSION_CRLF_STR
) + HttpHdrSize
;
1158 Request
= AllocateZeroPool (MsgSize
);
1159 if (Request
== NULL
) {
1163 RequestPtr
= Request
;
1165 // Construct header request
1167 switch (Message
->Data
.Request
->Method
) {
1169 StrLength
= sizeof (HTTP_GET_STR
) - 1;
1170 CopyMem (RequestPtr
, HTTP_GET_STR
, StrLength
);
1171 RequestPtr
+= StrLength
;
1173 case HttpMethodHead
:
1174 StrLength
= sizeof (HTTP_HEAD_STR
) - 1;
1175 CopyMem (RequestPtr
, HTTP_HEAD_STR
, StrLength
);
1176 RequestPtr
+= StrLength
;
1183 StrLength
= AsciiStrLen (Url
);
1184 CopyMem (RequestPtr
, Url
, StrLength
);
1185 RequestPtr
+= StrLength
;
1187 StrLength
= sizeof (HTTP_VERSION_CRLF_STR
) - 1;
1188 CopyMem (RequestPtr
, HTTP_VERSION_CRLF_STR
, StrLength
);
1189 RequestPtr
+= StrLength
;
1194 CopyMem (RequestPtr
, HttpHdr
, HttpHdrSize
);
1195 RequestPtr
+= HttpHdrSize
;
1200 if (Message
->Body
!= NULL
) {
1201 CopyMem (RequestPtr
, Message
->Body
, Message
->BodyLength
);
1202 RequestPtr
+= Message
->BodyLength
;
1214 if (Request
!= NULL
) {
1221 if (HttpHdr
!= NULL
) {
1225 return (CHAR8
*) Request
;