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] Event The event signaled.
42 @param[in] Context The context.
47 HttpTcpTransmitNotify (
52 HTTP_TOKEN_WRAP
*Wrap
;
54 if ((Event
== NULL
) || (Context
== NULL
)) {
58 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
59 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.TxToken
.CompletionToken
.Status
;
60 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
65 if (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
66 FreePool (Wrap
->TcpWrap
.TxToken
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
69 if (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
!= NULL
) {
70 gBS
->CloseEvent (Wrap
->TcpWrap
.TxToken
.CompletionToken
.Event
);
73 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
76 // Check pending TxTokens and sent out.
78 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
83 The notify function associated with RxToken for Tcp4->Receive ().
85 @param[in] Event The event signaled.
86 @param[in] Context The context.
91 HttpTcpReceiveNotify (
96 HTTP_TOKEN_WRAP
*Wrap
;
100 HTTP_PROTOCOL
*HttpInstance
;
102 if ((Event
== NULL
) || (Context
== NULL
)) {
106 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
107 if (EFI_ERROR (Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
)) {
111 HttpInstance
= Wrap
->HttpInstance
;
114 // Check whether we receive a complete HTTP message.
116 ASSERT (HttpInstance
->MsgParser
!= NULL
);
118 Length
= (UINTN
) Wrap
->TcpWrap
.RxData
.FragmentTable
[0].FragmentLength
;
119 Status
= HttpParseMessageBody (
120 HttpInstance
->MsgParser
,
122 Wrap
->HttpToken
->Message
->Body
124 if (EFI_ERROR (Status
)) {
128 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
130 // Free the MsgParse since we already have a full HTTP message.
132 HttpFreeMsgParser (HttpInstance
->MsgParser
);
133 HttpInstance
->MsgParser
= NULL
;
136 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
137 ASSERT (HttpInstance
->CacheBody
== NULL
);
139 // We receive part of header of next HTTP msg.
141 if (HttpInstance
->NextMsg
!= NULL
) {
142 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
143 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
144 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
145 if (HttpInstance
->CacheLen
!= 0) {
146 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
147 if (HttpInstance
->CacheBody
== NULL
) {
150 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
151 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
152 HttpInstance
->CacheOffset
= 0;
156 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
158 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
162 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
163 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.RxToken
.CompletionToken
.Status
;
165 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
168 // Check pending RxTokens and receive the HTTP message.
170 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
176 Create events for the TCP4 connection token and TCP4 close token.
178 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
180 @retval EFI_SUCCESS The events are created successfully.
181 @retval others Other error as indicated.
185 HttpCreateTcp4ConnCloseEvent (
186 IN HTTP_PROTOCOL
*HttpInstance
191 // Create events for variuos asynchronous operations.
193 Status
= gBS
->CreateEvent (
197 &HttpInstance
->IsConnDone
,
198 &HttpInstance
->ConnToken
.CompletionToken
.Event
200 if (EFI_ERROR (Status
)) {
205 // Initialize CloseToken
207 Status
= gBS
->CreateEvent (
211 &HttpInstance
->IsCloseDone
,
212 &HttpInstance
->CloseToken
.CompletionToken
.Event
214 if (EFI_ERROR (Status
)) {
225 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
232 Close events in the TCP4 connection token and TCP4 close token.
234 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
238 HttpCloseTcp4ConnCloseEvent (
239 IN HTTP_PROTOCOL
*HttpInstance
242 ASSERT (HttpInstance
!= NULL
);
244 if (NULL
!= HttpInstance
->ConnToken
.CompletionToken
.Event
) {
245 gBS
->CloseEvent (HttpInstance
->ConnToken
.CompletionToken
.Event
);
248 if (NULL
!= HttpInstance
->CloseToken
.CompletionToken
.Event
) {
249 gBS
->CloseEvent(HttpInstance
->CloseToken
.CompletionToken
.Event
);
254 Create event for the TCP4 transmit token.
256 @param[in] Wrap Point to HTTP token's wrap data.
258 @retval EFI_SUCCESS The events is created successfully.
259 @retval others Other error as indicated.
263 HttpCreateTcp4TxEvent (
264 IN HTTP_TOKEN_WRAP
*Wrap
268 HTTP_PROTOCOL
*HttpInstance
;
269 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
271 HttpInstance
= Wrap
->HttpInstance
;
272 TcpWrap
= &Wrap
->TcpWrap
;
274 Status
= gBS
->CreateEvent (
277 HttpTcpTransmitNotify
,
279 &TcpWrap
->TxToken
.CompletionToken
.Event
281 if (EFI_ERROR (Status
)) {
285 TcpWrap
->TxData
.Push
= TRUE
;
286 TcpWrap
->TxData
.Urgent
= FALSE
;
287 TcpWrap
->TxData
.FragmentCount
= 1;
288 TcpWrap
->TxToken
.Packet
.TxData
= &Wrap
->TcpWrap
.TxData
;
289 TcpWrap
->TxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
295 Create event for the TCP4 receive token which is used to receive HTTP header.
297 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
299 @retval EFI_SUCCESS The events is created successfully.
300 @retval others Other error as indicated.
304 HttpCreateTcp4RxEventForHeader (
305 IN HTTP_PROTOCOL
*HttpInstance
311 Status
= gBS
->CreateEvent (
315 &HttpInstance
->IsRxDone
,
316 &HttpInstance
->RxToken
.CompletionToken
.Event
318 if (EFI_ERROR (Status
)) {
322 HttpInstance
->RxData
.FragmentCount
= 1;
323 HttpInstance
->RxToken
.Packet
.RxData
= &HttpInstance
->RxData
;
324 HttpInstance
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
330 Create event for the TCP4 receive token which is used to receive HTTP body.
332 @param[in] Wrap Point to HTTP token's wrap data.
334 @retval EFI_SUCCESS The events is created successfully.
335 @retval others Other error as indicated.
339 HttpCreateTcp4RxEvent (
340 IN HTTP_TOKEN_WRAP
*Wrap
344 HTTP_PROTOCOL
*HttpInstance
;
345 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
347 HttpInstance
= Wrap
->HttpInstance
;
348 TcpWrap
= &Wrap
->TcpWrap
;
350 Status
= gBS
->CreateEvent (
353 HttpTcpReceiveNotify
,
355 &TcpWrap
->RxToken
.CompletionToken
.Event
357 if (EFI_ERROR (Status
)) {
361 TcpWrap
->RxData
.FragmentCount
= 1;
362 TcpWrap
->RxToken
.Packet
.RxData
= &Wrap
->TcpWrap
.RxData
;
363 TcpWrap
->RxToken
.CompletionToken
.Status
= EFI_NOT_READY
;
369 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
371 @param[in] HttpSb The HTTP service private instance.
372 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
374 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
375 @retval Others Other error as indicated.
380 IN HTTP_SERVICE
*HttpSb
,
381 IN OUT HTTP_PROTOCOL
*HttpInstance
387 ASSERT ((HttpSb
!= NULL
) && (HttpInstance
!= NULL
));
389 HttpInstance
->Signature
= HTTP_PROTOCOL_SIGNATURE
;
390 CopyMem (&HttpInstance
->Http
, &mEfiHttpTemplate
, sizeof (HttpInstance
->Http
));
391 HttpInstance
->Service
= HttpSb
;
396 Status
= NetLibCreateServiceChild (
397 HttpInstance
->Service
->ControllerHandle
,
398 HttpInstance
->Service
->ImageHandle
,
399 &gEfiTcp4ServiceBindingProtocolGuid
,
400 &HttpInstance
->TcpChildHandle
403 if (EFI_ERROR (Status
)) {
407 Status
= gBS
->OpenProtocol (
408 HttpInstance
->TcpChildHandle
,
409 &gEfiTcp4ProtocolGuid
,
410 (VOID
**) &Interface
,
411 HttpInstance
->Service
->ImageHandle
,
412 HttpInstance
->Service
->ControllerHandle
,
413 EFI_OPEN_PROTOCOL_BY_DRIVER
416 if (EFI_ERROR (Status
)) {
420 Status
= gBS
->OpenProtocol (
421 HttpInstance
->TcpChildHandle
,
422 &gEfiTcp4ProtocolGuid
,
423 (VOID
**) &HttpInstance
->Tcp4
,
424 HttpInstance
->Service
->ImageHandle
,
425 HttpInstance
->Handle
,
426 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
428 if (EFI_ERROR(Status
)) {
432 NetMapInit (&HttpInstance
->TxTokens
);
433 NetMapInit (&HttpInstance
->RxTokens
);
439 if (HttpInstance
->TcpChildHandle
!= NULL
) {
441 HttpInstance
->TcpChildHandle
,
442 &gEfiTcp4ProtocolGuid
,
443 HttpInstance
->Service
->ImageHandle
,
444 HttpInstance
->Service
->ControllerHandle
448 HttpInstance
->TcpChildHandle
,
449 &gEfiTcp4ProtocolGuid
,
450 HttpInstance
->Service
->ImageHandle
,
454 NetLibDestroyServiceChild (
455 HttpInstance
->Service
->ControllerHandle
,
456 HttpInstance
->Service
->ImageHandle
,
457 &gEfiTcp4ServiceBindingProtocolGuid
,
458 HttpInstance
->TcpChildHandle
467 Clean up the HTTP child, release all the resources used by it.
469 @param[in] HttpInstance The HTTP child to clean up.
474 IN HTTP_PROTOCOL
*HttpInstance
477 HttpCloseConnection (HttpInstance
);
479 HttpCloseTcp4ConnCloseEvent (HttpInstance
);
481 if (HttpInstance
->CacheBody
!= NULL
) {
482 FreePool (HttpInstance
->CacheBody
);
483 HttpInstance
->CacheBody
= NULL
;
484 HttpInstance
->NextMsg
= NULL
;
487 if (HttpInstance
->RemoteHost
!= NULL
) {
488 FreePool (HttpInstance
->RemoteHost
);
489 HttpInstance
->RemoteHost
= NULL
;
492 if (HttpInstance
->MsgParser
!= NULL
) {
493 HttpFreeMsgParser (HttpInstance
->MsgParser
);
494 HttpInstance
->MsgParser
= NULL
;
497 NetMapClean (&HttpInstance
->TxTokens
);
498 NetMapClean (&HttpInstance
->RxTokens
);
500 if (HttpInstance
->TcpChildHandle
!= NULL
) {
502 HttpInstance
->TcpChildHandle
,
503 &gEfiTcp4ProtocolGuid
,
504 HttpInstance
->Service
->ImageHandle
,
505 HttpInstance
->Service
->ControllerHandle
509 HttpInstance
->TcpChildHandle
,
510 &gEfiTcp4ProtocolGuid
,
511 HttpInstance
->Service
->ImageHandle
,
515 NetLibDestroyServiceChild (
516 HttpInstance
->Service
->ControllerHandle
,
517 HttpInstance
->Service
->ImageHandle
,
518 &gEfiTcp4ServiceBindingProtocolGuid
,
519 HttpInstance
->TcpChildHandle
525 Establish TCP connection with HTTP server.
527 @param[in] HttpInstance The HTTP instance private data.
529 @retval EFI_SUCCESS The TCP connection is established.
530 @retval Others Other error as indicated.
534 HttpCreateConnection (
535 IN HTTP_PROTOCOL
*HttpInstance
541 // Create events for variuos asynchronous operations.
543 HttpInstance
->IsConnDone
= FALSE
;
546 // Connect to Http server
548 HttpInstance
->ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
549 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->ConnToken
);
550 if (EFI_ERROR (Status
)) {
551 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
555 while (!HttpInstance
->IsConnDone
) {
556 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
559 Status
= HttpInstance
->ConnToken
.CompletionToken
.Status
;
561 if (!EFI_ERROR (Status
)) {
562 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
569 Close existing TCP connection.
571 @param[in] HttpInstance The HTTP instance private data.
573 @retval EFI_SUCCESS The TCP connection is closed.
574 @retval Others Other error as indicated.
578 HttpCloseConnection (
579 IN HTTP_PROTOCOL
*HttpInstance
584 HttpInstance
->CloseToken
.AbortOnClose
= TRUE
;
585 HttpInstance
->IsCloseDone
= FALSE
;
588 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->CloseToken
);
589 if (EFI_ERROR (Status
)) {
593 while (!HttpInstance
->IsCloseDone
) {
594 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
597 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
602 Configure TCP4 protocol child.
604 @param[in] HttpInstance The HTTP instance private data.
605 @param[in] Wrap The HTTP token's wrap data.
607 @retval EFI_SUCCESS The TCP4 protocol child is configured.
608 @retval Others Other error as indicated.
613 IN HTTP_PROTOCOL
*HttpInstance
,
614 IN HTTP_TOKEN_WRAP
*Wrap
618 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
619 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
620 EFI_TCP4_OPTION
*Tcp4Option
;
621 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
623 ASSERT (HttpInstance
!= NULL
);
624 TcpWrap
= &Wrap
->TcpWrap
;
627 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
628 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
630 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
631 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
632 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
634 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
635 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
636 if (!Tcp4AP
->UseDefaultAddress
) {
637 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
638 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
641 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
642 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
643 Tcp4AP
->ActiveFlag
= TRUE
;
644 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
646 Tcp4Option
= Tcp4CfgData
->ControlOption
;
647 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
648 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
649 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
650 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
651 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
652 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
653 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
654 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
655 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
656 Tcp4Option
->EnableNagle
= TRUE
;
657 Tcp4CfgData
->ControlOption
= Tcp4Option
;
659 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
660 if (EFI_ERROR (Status
)) {
661 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
665 Status
= HttpCreateTcp4ConnCloseEvent (HttpInstance
);
666 if (EFI_ERROR (Status
)) {
670 Status
= HttpCreateTcp4TxEvent (Wrap
);
671 if (EFI_ERROR (Status
)) {
675 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
681 Check existing TCP connection, if in error state, receover TCP4 connection.
683 @param[in] HttpInstance The HTTP instance private data.
685 @retval EFI_SUCCESS The TCP connection is established.
686 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
687 @retval Others Other error as indicated.
692 IN HTTP_PROTOCOL
*HttpInstance
696 EFI_TCP4_CONNECTION_STATE Tcp4State
;
699 if (HttpInstance
->State
!= HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
700 return EFI_NOT_READY
;
703 Status
= HttpInstance
->Tcp4
->GetModeData(
711 if (EFI_ERROR(Status
)){
712 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
716 if (Tcp4State
> Tcp4StateEstablished
) {
717 HttpCloseConnection(HttpInstance
);
720 return HttpCreateConnection (HttpInstance
);
724 Send the HTTP message through TCP4.
726 @param[in] HttpInstance The HTTP instance private data.
727 @param[in] Wrap The HTTP token's wrap data.
728 @param[in] TxString Buffer containing the HTTP message string.
729 @param[in] TxStringLen Length of the HTTP message string in bytes.
731 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
732 @retval Others Other error as indicated.
737 IN HTTP_PROTOCOL
*HttpInstance
,
738 IN HTTP_TOKEN_WRAP
*Wrap
,
744 EFI_TCP4_IO_TOKEN
*TxToken
;
745 EFI_TCP4_PROTOCOL
*Tcp4
;
747 Tcp4
= HttpInstance
->Tcp4
;
748 TxToken
= &Wrap
->TcpWrap
.TxToken
;
750 TxToken
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
751 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
752 TxToken
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
753 TxToken
->CompletionToken
.Status
= EFI_NOT_READY
;
755 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
756 Status
= Tcp4
->Transmit (Tcp4
, TxToken
);
757 if (EFI_ERROR (Status
)) {
758 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
766 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined
767 in UEFI 2.5 specification.
769 @param[in] StatusCode The status code value in HTTP message.
771 @return Value defined in EFI_HTTP_STATUS_CODE .
775 HttpMappingToStatusCode (
779 switch (StatusCode
) {
781 return HTTP_STATUS_100_CONTINUE
;
783 return HTTP_STATUS_101_SWITCHING_PROTOCOLS
;
785 return HTTP_STATUS_200_OK
;
787 return HTTP_STATUS_201_CREATED
;
789 return HTTP_STATUS_202_ACCEPTED
;
791 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION
;
793 return HTTP_STATUS_204_NO_CONTENT
;
795 return HTTP_STATUS_205_RESET_CONTENT
;
797 return HTTP_STATUS_206_PARTIAL_CONTENT
;
799 return HTTP_STATUS_300_MULTIPLE_CHIOCES
;
801 return HTTP_STATUS_301_MOVED_PERMANENTLY
;
803 return HTTP_STATUS_302_FOUND
;
805 return HTTP_STATUS_303_SEE_OTHER
;
807 return HTTP_STATUS_304_NOT_MODIFIED
;
809 return HTTP_STATUS_305_USE_PROXY
;
811 return HTTP_STATUS_307_TEMPORARY_REDIRECT
;
813 return HTTP_STATUS_400_BAD_REQUEST
;
815 return HTTP_STATUS_401_UNAUTHORIZED
;
817 return HTTP_STATUS_402_PAYMENT_REQUIRED
;
819 return HTTP_STATUS_403_FORBIDDEN
;
821 return HTTP_STATUS_404_NOT_FOUND
;
823 return HTTP_STATUS_405_METHOD_NOT_ALLOWED
;
825 return HTTP_STATUS_406_NOT_ACCEPTABLE
;
827 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED
;
829 return HTTP_STATUS_408_REQUEST_TIME_OUT
;
831 return HTTP_STATUS_409_CONFLICT
;
833 return HTTP_STATUS_410_GONE
;
835 return HTTP_STATUS_411_LENGTH_REQUIRED
;
837 return HTTP_STATUS_412_PRECONDITION_FAILED
;
839 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE
;
841 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE
;
843 return HTTP_STATUS_415_UNSUPPORETD_MEDIA_TYPE
;
845 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED
;
847 return HTTP_STATUS_417_EXPECTATION_FAILED
;
849 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR
;
851 return HTTP_STATUS_501_NOT_IMIPLEMENTED
;
853 return HTTP_STATUS_502_BAD_GATEWAY
;
855 return HTTP_STATUS_503_SERVICE_UNAVAILABLE
;
857 return HTTP_STATUS_504_GATEWAY_TIME_OUT
;
859 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
;
862 return HTTP_STATUS_UNSUPPORTED_STATUS
;
867 Check whether the user's token or event has already
868 been enqueue on HTTP TxToken or RxToken list.
870 @param[in] Map The container of either user's transmit or receive
872 @param[in] Item Current item to check against.
873 @param[in] Context The Token to check againist.
875 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
876 @retval EFI_SUCCESS The current item isn't the same token/event as the
884 IN NET_MAP_ITEM
*Item
,
888 EFI_HTTP_TOKEN
*Token
;
889 EFI_HTTP_TOKEN
*TokenInItem
;
891 Token
= (EFI_HTTP_TOKEN
*) Context
;
892 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
894 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
895 return EFI_ACCESS_DENIED
;
902 Check whether the HTTP message associated with TxToken is already sent out.
904 @param[in] Map The container of TxToken.
905 @param[in] Item Current item to check against.
906 @param[in] Context The Token to check againist.
908 @retval EFI_NOT_READY The HTTP message is still queued in the list.
909 @retval EFI_SUCCESS The HTTP message has been sent out.
916 IN NET_MAP_ITEM
*Item
,
920 HTTP_TOKEN_WRAP
*ValueInItem
;
922 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
924 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
925 return EFI_NOT_READY
;
932 Transmit the HTTP mssage by processing the associated HTTP token.
934 @param[in] Map The container of TxToken.
935 @param[in] Item Current item to check against.
936 @param[in] Context The Token to check againist.
938 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
939 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
947 IN NET_MAP_ITEM
*Item
,
951 HTTP_TOKEN_WRAP
*ValueInItem
;
956 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
957 if (ValueInItem
->TcpWrap
.IsTxDone
) {
962 // Parse the URI of the remote host.
964 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
966 return EFI_OUT_OF_RESOURCES
;
969 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
972 // Create request message.
974 RequestStr
= HttpGenRequestString (
975 ValueInItem
->HttpInstance
,
976 ValueInItem
->HttpToken
->Message
,
980 if (RequestStr
== NULL
) {
981 return EFI_OUT_OF_RESOURCES
;
985 // Transmit the request message.
987 Status
= HttpTransmitTcp4 (
988 ValueInItem
->HttpInstance
,
991 AsciiStrLen (RequestStr
)
993 FreePool (RequestStr
);
998 Receive the HTTP response by processing the associated HTTP token.
1000 @param[in] Map The container of RxToken.
1001 @param[in] Item Current item to check against.
1002 @param[in] Context The Token to check againist.
1004 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1006 @retval Others Other error as indicated.
1013 IN NET_MAP_ITEM
*Item
,
1018 // Process the queued HTTP response.
1020 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1024 Generate HTTP request string.
1026 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1027 @param[in] Message Pointer to storage containing HTTP message data.
1028 @param[in] Url The URL of a remote host.
1030 @return Pointer to the created HTTP request string.
1031 @return NULL if any error occured.
1035 HttpGenRequestString (
1036 IN HTTP_PROTOCOL
*HttpInstance
,
1037 IN EFI_HTTP_MESSAGE
*Message
,
1049 EFI_HTTP_HEADER
**AppendList
;
1052 ASSERT (HttpInstance
!= NULL
);
1053 ASSERT (Message
!= NULL
);
1055 DEBUG ((EFI_D_ERROR
, "HttpMethod - %x\n", Message
->Data
.Request
->Method
));
1065 AppendList
= AllocateZeroPool (sizeof (EFI_HTTP_HEADER
*) * (Message
->HeaderCount
));
1066 if (AppendList
== NULL
) {
1070 for(Index
= 0; Index
< Message
->HeaderCount
; Index
++){
1071 AppendList
[Index
] = &Message
->Headers
[Index
];
1075 // Build raw unformatted HTTP headers.
1077 Status
= HttpUtilitiesBuild (
1082 Message
->HeaderCount
,
1087 FreePool (AppendList
);
1088 if (EFI_ERROR (Status
) || HttpHdr
== NULL
) {
1093 // Calculate HTTP message length.
1095 MsgSize
= Message
->BodyLength
+ HTTP_MAXIMUM_METHOD_LEN
+ AsciiStrLen (Url
) +
1096 AsciiStrLen (HTTP_VERSION_CRLF_STR
) + HttpHdrSize
;
1097 Request
= AllocateZeroPool (MsgSize
);
1098 if (Request
== NULL
) {
1102 RequestPtr
= Request
;
1104 // Construct header request
1106 switch (Message
->Data
.Request
->Method
) {
1108 StrLength
= sizeof (HTTP_GET_STR
) - 1;
1109 CopyMem (RequestPtr
, HTTP_GET_STR
, StrLength
);
1110 RequestPtr
+= StrLength
;
1112 case HttpMethodHead
:
1113 StrLength
= sizeof (HTTP_HEAD_STR
) - 1;
1114 CopyMem (RequestPtr
, HTTP_HEAD_STR
, StrLength
);
1115 RequestPtr
+= StrLength
;
1122 StrLength
= AsciiStrLen (Url
);
1123 CopyMem (RequestPtr
, Url
, StrLength
);
1124 RequestPtr
+= StrLength
;
1126 StrLength
= sizeof (HTTP_VERSION_CRLF_STR
) - 1;
1127 CopyMem (RequestPtr
, HTTP_VERSION_CRLF_STR
, StrLength
);
1128 RequestPtr
+= StrLength
;
1133 CopyMem (RequestPtr
, HttpHdr
, HttpHdrSize
);
1134 RequestPtr
+= HttpHdrSize
;
1139 if (Message
->Body
!= NULL
) {
1140 CopyMem (RequestPtr
, Message
->Body
, Message
->BodyLength
);
1141 RequestPtr
+= Message
->BodyLength
;
1153 if (Request
!= NULL
) {
1160 if (HttpHdr
!= NULL
) {
1164 return (CHAR8
*) Request
;