RedfishPkg/RedfishRestExDxe: Implementation of EFI REST EX Protocol
BZ#: 2908 https://bugzilla.tianocore.org/show_bug.cgi?id=2908 Implementation of EFI EX Protocol according to UEFI spec 2.8 Section 29.7.2 EFI REST EX Protocol. This is the network stack based EFI REST EX protocol instance. Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com> Signed-off-by: Siyuan Fu <siyuan.fu@intel.com> Signed-off-by: Fan Wang <fan.wang@intel.com> Signed-off-by: Ting Ye <ting.ye@intel.com> Signed-off-by: Abner Chang <abner.chang@hpe.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Fan Wang <fan.wang@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Nickle Wang <nickle.wang@hpe.com> Cc: Peter O'Hanley <peter.ohanley@hpe.com> Reviewed-by: Nickle Wang <nickle.wang@hpe.com>
This commit is contained in:
committed by
mergify[bot]
parent
0db89a661f
commit
10dc8c561c
157
RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
Normal file
157
RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/** @file
|
||||
RestExDxe support functions implementation.
|
||||
|
||||
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include <Uefi.h>
|
||||
#include "RedfishRestExInternal.h"
|
||||
|
||||
/**
|
||||
Create a new TLS session becuase the previous on is closed.
|
||||
status.
|
||||
|
||||
@param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
||||
REST service.
|
||||
@retval EFI_SUCCESS operation succeeded.
|
||||
@retval EFI_ERROR Other errors.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
ResetHttpTslSession (
|
||||
IN RESTEX_INSTANCE *Instance
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL session closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__));
|
||||
|
||||
Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION__));
|
||||
return Status;
|
||||
}
|
||||
Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FUNCTION__));
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
/**
|
||||
This function check
|
||||
|
||||
@param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
||||
REST service.
|
||||
@param[in] HttpIoReceiveStatus This is the status return from HttpIoRecvResponse
|
||||
|
||||
@retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
|
||||
@retval EFI_NOT_READY May need to resend the HTTP request.
|
||||
@retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
|
||||
@retval Others Other errors as indicated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RedfishCheckHttpReceiveStatus (
|
||||
IN RESTEX_INSTANCE *Instance,
|
||||
IN EFI_STATUS HttpIoReceiveStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS ReturnStatus;
|
||||
|
||||
if (!EFI_ERROR (HttpIoReceiveStatus)){
|
||||
ReturnStatus = EFI_SUCCESS;
|
||||
} else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus != EFI_CONNECTION_FIN) {
|
||||
if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) == 0) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCTION__));
|
||||
Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
|
||||
gBS->Stall (500);
|
||||
Status = ResetHttpTslSession (Instance);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
|
||||
ReturnStatus = EFI_DEVICE_ERROR;
|
||||
} else {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
} else {
|
||||
ReturnStatus = EFI_DEVICE_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
|
||||
if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even with a new TLS session.\n", __FUNCTION__));
|
||||
ReturnStatus = EFI_DEVICE_ERROR;
|
||||
}
|
||||
Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
|
||||
Status = ResetHttpTslSession (Instance);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
|
||||
ReturnStatus = EFI_DEVICE_ERROR;
|
||||
}
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Clean TLS new session retry and error try flags.
|
||||
//
|
||||
Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
|
||||
return ReturnStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
This function send the HTTP request without body to see
|
||||
if the write to URL is permitted by Redfish service. This function
|
||||
checks if the HTTP request has Content-length in HTTP header. If yes,
|
||||
set HTTP body to NULL and then send to service. Check the HTTP status
|
||||
for the firther actions.
|
||||
|
||||
@param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
|
||||
REST service.
|
||||
@param[in] RequestMessage Pointer to the HTTP request data for this resource
|
||||
@param[in] PreservedRequestHeaders The pointer to save the request headers
|
||||
@param[in] ItsWrite This is write method to URL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Improper given parameters.
|
||||
@retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
|
||||
@retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
|
||||
@retval EFI_ACCESS_DENIED Not allowed to write to this URL.
|
||||
|
||||
@retval Others Other errors as indicated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RedfishHttpAddExpectation (
|
||||
IN EFI_REST_EX_PROTOCOL *This,
|
||||
IN EFI_HTTP_MESSAGE *RequestMessage,
|
||||
IN EFI_HTTP_HEADER **PreservedRequestHeaders,
|
||||
IN BOOLEAN *ItsWrite
|
||||
)
|
||||
{
|
||||
EFI_HTTP_HEADER *NewHeaders;
|
||||
|
||||
if (This == NULL || RequestMessage == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*ItsWrite = FALSE;
|
||||
if (PreservedRequestHeaders != NULL) {
|
||||
*PreservedRequestHeaders = RequestMessage->Headers;
|
||||
}
|
||||
|
||||
if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
|
||||
(RequestMessage->Data.Request->Method != HttpMethodPatch)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
*ItsWrite = TRUE;
|
||||
|
||||
NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) * sizeof(EFI_HTTP_HEADER));
|
||||
CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
|
||||
HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
|
||||
RequestMessage->HeaderCount ++;
|
||||
RequestMessage->Headers = NewHeaders;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
Reference in New Issue
Block a user