2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HttpDriver.h"
19 The common notify function used in HTTP driver.
21 @param[in] Event The event signaled.
22 @param[in] Context The context.
32 if ((Event
== NULL
) || (Context
== NULL
)) {
36 *((BOOLEAN
*) Context
) = TRUE
;
40 The notify function associated with TxToken for Tcp4->Transmit().
42 @param[in] Context The context.
47 HttpTcpTransmitNotifyDpc (
51 HTTP_TOKEN_WRAP
*Wrap
;
53 if (Context
== NULL
) {
57 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
58 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.TxToken
.CompletionToken
.Status
;
59 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
64 if (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
65 FreePool (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
68 if (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
!= NULL
) {
69 gBS
->CloseEvent (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
);
72 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
75 // Check pending TxTokens and sent out.
77 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
82 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
84 @param Event The receive event delivered to TCP for transmit.
85 @param Context Context for the callback.
90 HttpTcpTransmitNotify (
96 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
98 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
103 The notify function associated with RxToken for Tcp4->Receive ().
105 @param[in] Context The context.
110 HttpTcpReceiveNotifyDpc (
114 HTTP_TOKEN_WRAP
*Wrap
;
118 HTTP_PROTOCOL
*HttpInstance
;
120 if (Context
== NULL
) {
124 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
125 gBS
->CloseEvent (Wrap
->TcpWrap
.RxToken
.CompletionToken
.Event
);
126 if (EFI_ERROR (Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
)) {
130 HttpInstance
= Wrap
->HttpInstance
;
133 // Check whether we receive a complete HTTP message.
135 ASSERT (HttpInstance
->MsgParser
!= NULL
);
137 Length
= (UINTN
) Wrap
->TcpWrap
.RxData
.FragmentTable
[0].FragmentLength
;
138 Status
= HttpParseMessageBody (
139 HttpInstance
->MsgParser
,
141 Wrap
->HttpToken
->Message
->Body
143 if (EFI_ERROR (Status
)) {
147 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
149 // Free the MsgParse since we already have a full HTTP message.
151 HttpFreeMsgParser (HttpInstance
->MsgParser
);
152 HttpInstance
->MsgParser
= NULL
;
155 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
156 ASSERT (HttpInstance
->CacheBody
== NULL
);
158 // We receive part of header of next HTTP msg.
160 if (HttpInstance
->NextMsg
!= NULL
) {
161 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
162 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
163 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
164 if (HttpInstance
->CacheLen
!= 0) {
165 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
166 if (HttpInstance
->CacheBody
== NULL
) {
169 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
170 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
171 HttpInstance
->CacheOffset
= 0;
175 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
177 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
181 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
182 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
;
184 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
187 // Check pending RxTokens and receive the HTTP message.
189 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
195 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
197 @param Event The receive event delivered to TCP for receive.
198 @param Context Context for the callback.
203 HttpTcpReceiveNotify (
209 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
211 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
216 Create events for the TCP4 connection token and TCP4 close token.
218 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
220 @retval EFI_SUCCESS The events are created successfully.
221 @retval others Other error as indicated.
225 HttpCreateTcp4ConnCloseEvent (
226 IN HTTP_PROTOCOL
*HttpInstance
231 // Create events for variuos asynchronous operations.
233 Status
= gBS
->CreateEvent (
237 &HttpInstance
->IsConnDone
,
238 &HttpInstance
->ConnToken
.CompletionToken
.Event
240 if (EFI_ERROR (Status
)) {
245 // Initialize CloseToken
247 Status
= gBS
->CreateEvent (
251 &HttpInstance
->IsCloseDone
,
252 &HttpInstance
->CloseToken
.CompletionToken
.Event
254 if (EFI_ERROR (Status
)) {
265 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
272 Close events in the TCP4 connection token and TCP4 close token.
274 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
278 HttpCloseTcp4ConnCloseEvent (
279 IN HTTP_PROTOCOL
*HttpInstance
282 ASSERT (HttpInstance
!= NULL
);
284 if (NULL
!= HttpInstance
->ConnToken
.CompletionToken
.Event
) {
285 gBS
->CloseEvent (HttpInstance
->ConnToken
.CompletionToken
.Event
);
286 HttpInstance
->ConnToken
.CompletionToken
.Event
= NULL
;
289 if (NULL
!= HttpInstance
->CloseToken
.CompletionToken
.Event
) {
290 gBS
->CloseEvent(HttpInstance
->CloseToken
.CompletionToken
.Event
);
291 HttpInstance
->CloseToken
.CompletionToken
.Event
= NULL
;
296 Create event for the TCP4 transmit token.
298 @param[in] Wrap Point to HTTP token's wrap data.
300 @retval EFI_SUCCESS The events is created successfully.
301 @retval others Other error as indicated.
305 HttpCreateTcp4TxEvent (
306 IN HTTP_TOKEN_WRAP
*Wrap
310 HTTP_PROTOCOL
*HttpInstance
;
311 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
313 HttpInstance
= Wrap
->HttpInstance
;
314 TcpWrap
= &Wrap
->TcpWrap
;
316 Status
= gBS
->CreateEvent (
319 HttpTcpTransmitNotify
,
321 &TcpWrap
->TxToken
.CompletionToken
.Event
323 if (EFI_ERROR (Status
)) {
327 TcpWrap
->TxData
.Push
= TRUE
;
328 TcpWrap
->TxData
.Urgent
= FALSE
;
329 TcpWrap
->TxData
.FragmentCount
= 1;
330 TcpWrap
->TxToken
.Packet
.TxData
= &Wrap
->TcpWrap
.TxData
;
331 TcpWrap
->TxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
337 Create event for the TCP4 receive token which is used to receive HTTP header.
339 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
341 @retval EFI_SUCCESS The events is created successfully.
342 @retval others Other error as indicated.
346 HttpCreateTcp4RxEventForHeader (
347 IN HTTP_PROTOCOL
*HttpInstance
353 Status
= gBS
->CreateEvent (
357 &HttpInstance
->IsRxDone
,
358 &HttpInstance
->RxToken
.CompletionToken
.Event
360 if (EFI_ERROR (Status
)) {
364 HttpInstance
->RxData
.FragmentCount
= 1;
365 HttpInstance
->RxToken
.Packet
.RxData
= &HttpInstance
->RxData
;
366 HttpInstance
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
372 Create event for the TCP4 receive token which is used to receive HTTP body.
374 @param[in] Wrap Point to HTTP token's wrap data.
376 @retval EFI_SUCCESS The events is created successfully.
377 @retval others Other error as indicated.
381 HttpCreateTcp4RxEvent (
382 IN HTTP_TOKEN_WRAP
*Wrap
386 HTTP_PROTOCOL
*HttpInstance
;
387 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
389 HttpInstance
= Wrap
->HttpInstance
;
390 TcpWrap
= &Wrap
->TcpWrap
;
392 Status
= gBS
->CreateEvent (
395 HttpTcpReceiveNotify
,
397 &TcpWrap
->RxToken
.CompletionToken
.Event
399 if (EFI_ERROR (Status
)) {
403 TcpWrap
->RxData
.FragmentCount
= 1;
404 TcpWrap
->RxToken
.Packet
.RxData
= &Wrap
->TcpWrap
.RxData
;
405 TcpWrap
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
411 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
413 @param[in] HttpSb The HTTP service private instance.
414 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
416 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
417 @retval Others Other error as indicated.
422 IN HTTP_SERVICE
*HttpSb
,
423 IN OUT HTTP_PROTOCOL
*HttpInstance
429 ASSERT ((HttpSb
!= NULL
) && (HttpInstance
!= NULL
));
431 HttpInstance
->Signature
= HTTP_PROTOCOL_SIGNATURE
;
432 CopyMem (&HttpInstance
->Http
, &mEfiHttpTemplate
, sizeof (HttpInstance
->Http
));
433 HttpInstance
->Service
= HttpSb
;
438 Status
= NetLibCreateServiceChild (
439 HttpInstance
->Service
->ControllerHandle
,
440 HttpInstance
->Service
->ImageHandle
,
441 &gEfiTcp4ServiceBindingProtocolGuid
,
442 &HttpInstance
->TcpChildHandle
445 if (EFI_ERROR (Status
)) {
449 Status
= gBS
->OpenProtocol (
450 HttpInstance
->TcpChildHandle
,
451 &gEfiTcp4ProtocolGuid
,
452 (VOID
**) &Interface
,
453 HttpInstance
->Service
->ImageHandle
,
454 HttpInstance
->Service
->ControllerHandle
,
455 EFI_OPEN_PROTOCOL_BY_DRIVER
458 if (EFI_ERROR (Status
)) {
462 Status
= gBS
->OpenProtocol (
463 HttpInstance
->TcpChildHandle
,
464 &gEfiTcp4ProtocolGuid
,
465 (VOID
**) &HttpInstance
->Tcp4
,
466 HttpInstance
->Service
->ImageHandle
,
467 HttpInstance
->Handle
,
468 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
470 if (EFI_ERROR(Status
)) {
474 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
475 if (HttpInstance
->Url
== NULL
) {
476 Status
= EFI_OUT_OF_RESOURCES
;
480 NetMapInit (&HttpInstance
->TxTokens
);
481 NetMapInit (&HttpInstance
->RxTokens
);
487 if (HttpInstance
->TcpChildHandle
!= NULL
) {
489 HttpInstance
->TcpChildHandle
,
490 &gEfiTcp4ProtocolGuid
,
491 HttpInstance
->Service
->ImageHandle
,
492 HttpInstance
->Service
->ControllerHandle
496 HttpInstance
->TcpChildHandle
,
497 &gEfiTcp4ProtocolGuid
,
498 HttpInstance
->Service
->ImageHandle
,
502 NetLibDestroyServiceChild (
503 HttpInstance
->Service
->ControllerHandle
,
504 HttpInstance
->Service
->ImageHandle
,
505 &gEfiTcp4ServiceBindingProtocolGuid
,
506 HttpInstance
->TcpChildHandle
515 Clean up the HTTP child, release all the resources used by it.
517 @param[in] HttpInstance The HTTP child to clean up.
522 IN HTTP_PROTOCOL
*HttpInstance
525 HttpCloseConnection (HttpInstance
);
527 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
529 if (HttpInstance
->CacheBody
!= NULL
) {
530 FreePool (HttpInstance
->CacheBody
);
531 HttpInstance
->CacheBody
= NULL
;
532 HttpInstance
->NextMsg
= NULL
;
535 if (HttpInstance
->RemoteHost
!= NULL
) {
536 FreePool (HttpInstance
->RemoteHost
);
537 HttpInstance
->RemoteHost
= NULL
;
540 if (HttpInstance
->MsgParser
!= NULL
) {
541 HttpFreeMsgParser (HttpInstance
->MsgParser
);
542 HttpInstance
->MsgParser
= NULL
;
545 if (HttpInstance
->Url
!= NULL
) {
546 FreePool (HttpInstance
->Url
);
547 HttpInstance
->Url
= NULL
;
550 NetMapClean (&HttpInstance
->TxTokens
);
551 NetMapClean (&HttpInstance
->RxTokens
);
553 if (HttpInstance
->TcpChildHandle
!= NULL
) {
555 HttpInstance
->TcpChildHandle
,
556 &gEfiTcp4ProtocolGuid
,
557 HttpInstance
->Service
->ImageHandle
,
558 HttpInstance
->Service
->ControllerHandle
562 HttpInstance
->TcpChildHandle
,
563 &gEfiTcp4ProtocolGuid
,
564 HttpInstance
->Service
->ImageHandle
,
568 NetLibDestroyServiceChild (
569 HttpInstance
->Service
->ControllerHandle
,
570 HttpInstance
->Service
->ImageHandle
,
571 &gEfiTcp4ServiceBindingProtocolGuid
,
572 HttpInstance
->TcpChildHandle
578 Establish TCP connection with HTTP server.
580 @param[in] HttpInstance The HTTP instance private data.
582 @retval EFI_SUCCESS The TCP connection is established.
583 @retval Others Other error as indicated.
587 HttpCreateConnection (
588 IN HTTP_PROTOCOL
*HttpInstance
594 // Create events for variuos asynchronous operations.
596 HttpInstance
->IsConnDone
= FALSE
;
599 // Connect to Http server
601 HttpInstance
->ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
602 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->ConnToken
);
603 if (EFI_ERROR (Status
)) {
604 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
608 while (!HttpInstance
->IsConnDone
) {
609 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
612 Status
= HttpInstance
->ConnToken
.CompletionToken
.Status
;
614 if (!EFI_ERROR (Status
)) {
615 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
622 Close existing TCP connection.
624 @param[in] HttpInstance The HTTP instance private data.
626 @retval EFI_SUCCESS The TCP connection is closed.
627 @retval Others Other error as indicated.
631 HttpCloseConnection (
632 IN HTTP_PROTOCOL
*HttpInstance
637 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
638 HttpInstance
->CloseToken
.AbortOnClose
= TRUE
;
639 HttpInstance
->IsCloseDone
= FALSE
;
641 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->CloseToken
);
642 if (EFI_ERROR (Status
)) {
646 while (!HttpInstance
->IsCloseDone
) {
647 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
651 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
656 Configure TCP4 protocol child.
658 @param[in] HttpInstance The HTTP instance private data.
659 @param[in] Wrap The HTTP token's wrap data.
661 @retval EFI_SUCCESS The TCP4 protocol child is configured.
662 @retval Others Other error as indicated.
667 IN HTTP_PROTOCOL
*HttpInstance
,
668 IN HTTP_TOKEN_WRAP
*Wrap
672 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
673 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
674 EFI_TCP4_OPTION
*Tcp4Option
;
675 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
677 ASSERT (HttpInstance
!= NULL
);
678 TcpWrap
= &Wrap
->TcpWrap
;
681 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
682 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
684 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
685 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
686 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
688 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
689 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
690 if (!Tcp4AP
->UseDefaultAddress
) {
691 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
692 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
695 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
696 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
697 Tcp4AP
->ActiveFlag
= TRUE
;
698 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
700 Tcp4Option
= Tcp4CfgData
->ControlOption
;
701 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
702 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
703 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
704 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
705 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
706 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
707 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
708 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
709 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
710 Tcp4Option
->EnableNagle
= TRUE
;
711 Tcp4CfgData
->ControlOption
= Tcp4Option
;
713 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
714 if (EFI_ERROR (Status
)) {
715 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
719 Status
= HttpCreateTcp4ConnCloseEvent (HttpInstance
);
720 if (EFI_ERROR (Status
)) {
724 Status
= HttpCreateTcp4TxEvent (Wrap
);
725 if (EFI_ERROR (Status
)) {
729 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
735 Check existing TCP connection, if in error state, receover TCP4 connection.
737 @param[in] HttpInstance The HTTP instance private data.
739 @retval EFI_SUCCESS The TCP connection is established.
740 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
741 @retval Others Other error as indicated.
746 IN HTTP_PROTOCOL
*HttpInstance
750 EFI_TCP4_CONNECTION_STATE Tcp4State
;
753 if (HttpInstance
->State
!= HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
754 return EFI_NOT_READY
;
757 Status
= HttpInstance
->Tcp4
->GetModeData(
765 if (EFI_ERROR(Status
)){
766 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
770 if (Tcp4State
> Tcp4StateEstablished
) {
771 HttpCloseConnection(HttpInstance
);
774 return HttpCreateConnection (HttpInstance
);
778 Send the HTTP message through TCP4.
780 @param[in] HttpInstance The HTTP instance private data.
781 @param[in] Wrap The HTTP token's wrap data.
782 @param[in] TxString Buffer containing the HTTP message string.
783 @param[in] TxStringLen Length of the HTTP message string in bytes.
785 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
786 @retval Others Other error as indicated.
791 IN HTTP_PROTOCOL
*HttpInstance
,
792 IN HTTP_TOKEN_WRAP
*Wrap
,
798 EFI_TCP4_IO_TOKEN
*TxToken
;
799 EFI_TCP4_PROTOCOL
*Tcp4
;
801 Tcp4
= HttpInstance
->Tcp4
;
802 TxToken
= &Wrap
->TcpWrap
.TxToken
;
804 TxToken
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
805 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
806 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
807 TxToken
->CompletionToken
.Status
= EFI_NOT_READY
;
809 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
810 Status
= Tcp4
->Transmit (Tcp4
, TxToken
);
811 if (EFI_ERROR (Status
)) {
812 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
820 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined
821 in UEFI 2.5 specification.
823 @param[in] StatusCode The status code value in HTTP message.
825 @return Value defined in EFI_HTTP_STATUS_CODE .
829 HttpMappingToStatusCode (
833 switch (StatusCode
) {
835 return HTTP_STATUS_100_CONTINUE
;
837 return HTTP_STATUS_101_SWITCHING_PROTOCOLS
;
839 return HTTP_STATUS_200_OK
;
841 return HTTP_STATUS_201_CREATED
;
843 return HTTP_STATUS_202_ACCEPTED
;
845 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION
;
847 return HTTP_STATUS_204_NO_CONTENT
;
849 return HTTP_STATUS_205_RESET_CONTENT
;
851 return HTTP_STATUS_206_PARTIAL_CONTENT
;
853 return HTTP_STATUS_300_MULTIPLE_CHIOCES
;
855 return HTTP_STATUS_301_MOVED_PERMANENTLY
;
857 return HTTP_STATUS_302_FOUND
;
859 return HTTP_STATUS_303_SEE_OTHER
;
861 return HTTP_STATUS_304_NOT_MODIFIED
;
863 return HTTP_STATUS_305_USE_PROXY
;
865 return HTTP_STATUS_307_TEMPORARY_REDIRECT
;
867 return HTTP_STATUS_400_BAD_REQUEST
;
869 return HTTP_STATUS_401_UNAUTHORIZED
;
871 return HTTP_STATUS_402_PAYMENT_REQUIRED
;
873 return HTTP_STATUS_403_FORBIDDEN
;
875 return HTTP_STATUS_404_NOT_FOUND
;
877 return HTTP_STATUS_405_METHOD_NOT_ALLOWED
;
879 return HTTP_STATUS_406_NOT_ACCEPTABLE
;
881 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED
;
883 return HTTP_STATUS_408_REQUEST_TIME_OUT
;
885 return HTTP_STATUS_409_CONFLICT
;
887 return HTTP_STATUS_410_GONE
;
889 return HTTP_STATUS_411_LENGTH_REQUIRED
;
891 return HTTP_STATUS_412_PRECONDITION_FAILED
;
893 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE
;
895 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE
;
897 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE
;
899 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED
;
901 return HTTP_STATUS_417_EXPECTATION_FAILED
;
903 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR
;
905 return HTTP_STATUS_501_NOT_IMPLEMENTED
;
907 return HTTP_STATUS_502_BAD_GATEWAY
;
909 return HTTP_STATUS_503_SERVICE_UNAVAILABLE
;
911 return HTTP_STATUS_504_GATEWAY_TIME_OUT
;
913 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
;
916 return HTTP_STATUS_UNSUPPORTED_STATUS
;
921 Check whether the user's token or event has already
922 been enqueue on HTTP TxToken or RxToken list.
924 @param[in] Map The container of either user's transmit or receive
926 @param[in] Item Current item to check against.
927 @param[in] Context The Token to check againist.
929 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
930 @retval EFI_SUCCESS The current item isn't the same token/event as the
938 IN NET_MAP_ITEM
*Item
,
942 EFI_HTTP_TOKEN
*Token
;
943 EFI_HTTP_TOKEN
*TokenInItem
;
945 Token
= (EFI_HTTP_TOKEN
*) Context
;
946 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
948 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
949 return EFI_ACCESS_DENIED
;
956 Check whether the HTTP message associated with TxToken is already sent out.
958 @param[in] Map The container of TxToken.
959 @param[in] Item Current item to check against.
960 @param[in] Context The Token to check againist.
962 @retval EFI_NOT_READY The HTTP message is still queued in the list.
963 @retval EFI_SUCCESS The HTTP message has been sent out.
970 IN NET_MAP_ITEM
*Item
,
974 HTTP_TOKEN_WRAP
*ValueInItem
;
976 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
978 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
979 return EFI_NOT_READY
;
986 Transmit the HTTP mssage by processing the associated HTTP token.
988 @param[in] Map The container of TxToken.
989 @param[in] Item Current item to check against.
990 @param[in] Context The Token to check againist.
992 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
993 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1001 IN NET_MAP_ITEM
*Item
,
1005 HTTP_TOKEN_WRAP
*ValueInItem
;
1010 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1011 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1016 // Parse the URI of the remote host.
1018 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1020 return EFI_OUT_OF_RESOURCES
;
1023 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1026 // Create request message.
1028 RequestStr
= HttpGenRequestString (
1029 ValueInItem
->HttpInstance
,
1030 ValueInItem
->HttpToken
->Message
,
1034 if (RequestStr
== NULL
) {
1035 return EFI_OUT_OF_RESOURCES
;
1039 // Transmit the request message.
1041 Status
= HttpTransmitTcp4 (
1042 ValueInItem
->HttpInstance
,
1044 (UINT8
*) RequestStr
,
1045 AsciiStrLen (RequestStr
)
1047 FreePool (RequestStr
);
1052 Receive the HTTP response by processing the associated HTTP token.
1054 @param[in] Map The container of RxToken.
1055 @param[in] Item Current item to check against.
1056 @param[in] Context The Token to check againist.
1058 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1060 @retval Others Other error as indicated.
1067 IN NET_MAP_ITEM
*Item
,
1072 // Process the queued HTTP response.
1074 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1078 Generate HTTP request string.
1080 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1081 @param[in] Message Pointer to storage containing HTTP message data.
1082 @param[in] Url The URL of a remote host.
1084 @return Pointer to the created HTTP request string.
1085 @return NULL if any error occured.
1089 HttpGenRequestString (
1090 IN HTTP_PROTOCOL
*HttpInstance
,
1091 IN EFI_HTTP_MESSAGE
*Message
,
1103 EFI_HTTP_HEADER
**AppendList
;
1106 ASSERT (HttpInstance
!= NULL
);
1107 ASSERT (Message
!= NULL
);
1109 DEBUG ((EFI_D_ERROR
, "HttpMethod - %x\n", Message
->Data
.Request
->Method
));
1119 AppendList
= AllocateZeroPool (sizeof (EFI_HTTP_HEADER
*) * (Message
->HeaderCount
));
1120 if (AppendList
== NULL
) {
1124 for(Index
= 0; Index
< Message
->HeaderCount
; Index
++){
1125 AppendList
[Index
] = &Message
->Headers
[Index
];
1129 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
1131 if (mHttpUtilities
== NULL
) {
1136 // Build raw unformatted HTTP headers.
1138 Status
= mHttpUtilities
->Build (
1144 Message
->HeaderCount
,
1149 FreePool (AppendList
);
1150 if (EFI_ERROR (Status
) || HttpHdr
== NULL
) {
1155 // Calculate HTTP message length.
1157 MsgSize
= Message
->BodyLength
+ HTTP_MAXIMUM_METHOD_LEN
+ AsciiStrLen (Url
) +
1158 AsciiStrLen (HTTP_VERSION_CRLF_STR
) + HttpHdrSize
;
1159 Request
= AllocateZeroPool (MsgSize
);
1160 if (Request
== NULL
) {
1164 RequestPtr
= Request
;
1166 // Construct header request
1168 switch (Message
->Data
.Request
->Method
) {
1170 StrLength
= sizeof (HTTP_GET_STR
) - 1;
1171 CopyMem (RequestPtr
, HTTP_GET_STR
, StrLength
);
1172 RequestPtr
+= StrLength
;
1174 case HttpMethodHead
:
1175 StrLength
= sizeof (HTTP_HEAD_STR
) - 1;
1176 CopyMem (RequestPtr
, HTTP_HEAD_STR
, StrLength
);
1177 RequestPtr
+= StrLength
;
1184 StrLength
= AsciiStrLen (Url
);
1185 CopyMem (RequestPtr
, Url
, StrLength
);
1186 RequestPtr
+= StrLength
;
1188 StrLength
= sizeof (HTTP_VERSION_CRLF_STR
) - 1;
1189 CopyMem (RequestPtr
, HTTP_VERSION_CRLF_STR
, StrLength
);
1190 RequestPtr
+= StrLength
;
1195 CopyMem (RequestPtr
, HttpHdr
, HttpHdrSize
);
1196 RequestPtr
+= HttpHdrSize
;
1201 if (Message
->Body
!= NULL
) {
1202 CopyMem (RequestPtr
, Message
->Body
, Message
->BodyLength
);
1203 RequestPtr
+= Message
->BodyLength
;
1215 if (Request
!= NULL
) {
1222 if (HttpHdr
!= NULL
) {
1226 return (CHAR8
*) Request
;