From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0b-002e3701.pphosted.com (mx0b-002e3701.pphosted.com [148.163.143.35]) by mx.groups.io with SMTP id smtpd.web08.8460.1657628520087731655 for ; Tue, 12 Jul 2022 05:22:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@hpe.com header.s=pps0720 header.b=E4wCvdck; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: hpe.com, ip: 148.163.143.35, mailfrom: prvs=0192e24d61=nickle.wang@hpe.com) Received: from pps.filterd (m0134424.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 26CAacq8030611; Tue, 12 Jul 2022 12:21:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hpe.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-transfer-encoding : mime-version; s=pps0720; bh=u+ROjbfpD5TrlCZIarQWnoOywR8HfcryVLEtHfPGCtk=; b=E4wCvdckdbeiq5xqgEr0rTsW5FbA9bSgXL/4WkO9tFszfHUEqs0hzWeMsKN9aBjhqbZz IzcuaUi6LXunvm51eHoxC6Vn8WbvmvctdzxFrBa5vcCVBy8XF5NwL5EM6br/MQZlsWZs vvJrzWRBRYgtzn335H4Cb6t0uJPYvtvyAYLrPe6WMC7afp9V7Tip524mjvPsoaQx5PDF xC0dZGm9IAk8ekxBmMSme8nuJHkeTR6YooLdbAmvTtqsu/langhqjdPRVLelbPXktodQ z3VrYkG7PDI3uCzzRZoScNEaQu6g/qIyqpn7atcaKh58lDhzs+1kM4LPvr4QS0/aRzWh Hg== Received: from p1lg14881.it.hpe.com (p1lg14881.it.hpe.com [16.230.97.202]) by mx0b-002e3701.pphosted.com (PPS) with ESMTPS id 3h97bsrv15-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 12 Jul 2022 12:21:57 +0000 Received: from p1lg14885.dc01.its.hpecorp.net (unknown [10.119.18.236]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by p1lg14881.it.hpe.com (Postfix) with ESMTPS id C110A80208E; Tue, 12 Jul 2022 12:21:56 +0000 (UTC) Received: from WAFM3XJD5N.asiapacific.hpqcorp.net (unknown [16.231.227.36]) by p1lg14885.dc01.its.hpecorp.net (Postfix) with ESMTP id BC4318058D6; Tue, 12 Jul 2022 12:21:55 +0000 (UTC) From: "Nickle Wang" To: devel@edk2.groups.io Cc: Abner Chang , Yang Atom , Nick Ramirez Subject: [edk2-staging][PATCH 09/15] edk2-staging/RedfishClientPkg: Update RedfishLib Date: Tue, 12 Jul 2022 20:21:37 +0800 Message-Id: <20220712122143.1827-10-nickle.wang@hpe.com> X-Mailer: git-send-email 2.32.0.windows.2 In-Reply-To: <20220712122143.1827-1-nickle.wang@hpe.com> References: <20220712122143.1827-1-nickle.wang@hpe.com> X-Proofpoint-ORIG-GUID: rq_njWRB9qtWFqmWy_r11eHI84NrrmQv X-Proofpoint-GUID: rq_njWRB9qtWFqmWy_r11eHI84NrrmQv X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-07-12_08,2022-07-12_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 spamscore=0 mlxlogscore=999 impostorscore=0 adultscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 mlxscore=0 suspectscore=0 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2206140000 definitions=main-2207120048 Content-Transfer-Encoding: quoted-printable RedfishLib has no capability to return HTTP header in response. However, feature driver needs to know the information like "ETag" or "Location" in HTTP response header per Redfish specification. Add corresponding function to return HTTP header in response data. Signed-off-by: Nickle Wang Cc: Abner Chang Cc: Yang Atom Cc: Nick Ramirez --- .../PrivateLibrary/RedfishLib/RedfishLib.c | 12 +- .../edk2libredfish/include/redfishPayload.h | 5 +- .../edk2libredfish/include/redfishService.h | 5 +- .../RedfishLib/edk2libredfish/src/payload.c | 90 ++- .../RedfishLib/edk2libredfish/src/service.c | 554 +++++++++++++++++- 5 files changed, 657 insertions(+), 9 deletions(-) diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c b/Redf= ishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c index 18aa4646e8..b8ca493e24 100644 --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c @@ -3,7 +3,7 @@ (CRUD) Redfish resources and provide basic query.=0D =0D Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D @@ -323,7 +323,7 @@ RedfishGetByUri ( =0D ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));=0D =0D - JsonValue =3D getUriFromService (RedfishService, Uri, &RedResponse->Stat= usCode);=0D + JsonValue =3D getUriFromServiceEx (RedfishService, Uri, &RedResponse->He= aders, &RedResponse->HeaderCount, &RedResponse->StatusCode);=0D RedResponse->Payload =3D createRedfishPayload(JsonValue, RedfishService)= ;=0D =0D //=0D @@ -541,9 +541,11 @@ RedfishPatchToPayload ( =0D ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));=0D =0D - RedResponse->Payload =3D (REDFISH_PAYLOAD) patchPayload (=0D + RedResponse->Payload =3D (REDFISH_PAYLOAD) patchPayloadEx (=0D Target,=0D Payload,=0D + &RedResponse->Headers,=0D + &RedResponse->HeaderCount,=0D &(RedResponse->StatusCode)=0D );=0D =0D @@ -607,9 +609,11 @@ RedfishPostToPayload ( =0D ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));=0D =0D - RedResponse->Payload =3D (REDFISH_PAYLOAD) postPayload (=0D + RedResponse->Payload =3D (REDFISH_PAYLOAD) postPayloadEx (=0D Target,=0D Payload,=0D + &RedResponse->Headers,=0D + &RedResponse->HeaderCount,=0D &(RedResponse->StatusCode)=0D );=0D =0D diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/incl= ude/redfishPayload.h b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libre= dfish/include/redfishPayload.h index 43149f3c89..be74c64297 100644 --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/red= fishPayload.h +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/red= fishPayload.h @@ -9,7 +9,7 @@ //------------------------------------------------------------------------= ----=0D =0D Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D @@ -29,8 +29,11 @@ redfishPayload* getPayloadByIndex(redfishPayload* payloa= d, size_t index, EFI_HTT redfishPayload* getPayloadForPath(redfishPayload* payload, redPathNode* re= dpath, EFI_HTTP_STATUS_CODE** StatusCode);=0D redfishPayload* getPayloadForPathString(redfishPayload* payload, const cha= r* string, EFI_HTTP_STATUS_CODE** StatusCode);=0D redfishPayload* patchPayload(redfishPayload* target, redfishPayload* paylo= ad, EFI_HTTP_STATUS_CODE** StatusCode);=0D +redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload* pay= load, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE**= StatusCode);=0D redfishPayload* postContentToPayload(redfishPayload* target, const char* d= ata, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** Statu= sCode);=0D +redfishPayload* postContentToPayloadEx(redfishPayload* target, const char*= data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER **Headers,= UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode);=0D redfishPayload* postPayload(redfishPayload* target, redfishPayload* payloa= d, EFI_HTTP_STATUS_CODE** StatusCode);=0D +redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload* payl= oad, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** = StatusCode);=0D void cleanupPayload(redfishPayload* payload);=0D bool isPayloadCollection (redfishPayload *Payload);=0D size_t getCollectionSize(redfishPayload* payload);=0D diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/incl= ude/redfishService.h b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libre= dfish/include/redfishService.h index 0215caccfc..3d87fad85a 100644 --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/red= fishService.h +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/red= fishService.h @@ -9,7 +9,7 @@ //------------------------------------------------------------------------= ----=0D =0D Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D @@ -91,8 +91,11 @@ typedef struct { #define REDFISH_FLAG_SERVICE_NO_VERSION_DOC 0x00000001 //The Redfish Servi= ce lacks the version document (in violation of the Redfish spec)=0D redfishService* createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION= *RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication* = auth, unsigned int flags);=0D json_t* getUriFromService(redfishService* service, const char* uri, EFI_HT= TP_STATUS_CODE** StatusCode);=0D +json_t* getUriFromServiceEx(redfishService* service, const char* uri, EFI_= HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE **StatusCod= e);=0D json_t* patchUriFromService(redfishService* service, const char* uri, cons= t char* content, EFI_HTTP_STATUS_CODE** StatusCode);=0D +json_t* patchUriFromServiceEx(redfishService* service, const char* uri, co= nst char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_= STATUS_CODE** StatusCode);=0D json_t* postUriFromService(redfishService* service, const char* uri, const= char* content, size_t contentLength, const char* contentType, EFI_HTTP_STA= TUS_CODE** StatusCode);=0D +json_t* postUriFromServiceEx(redfishService* service, const char* uri, con= st char* content, size_t contentLength, const char* contentType, EFI_HTTP_H= EADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode);=0D json_t* deleteUriFromService(redfishService* service, const char* uri, EFI= _HTTP_STATUS_CODE** StatusCode);=0D redfishPayload* getRedfishServiceRoot(redfishService* service, const char*= version, EFI_HTTP_STATUS_CODE** StatusCode);=0D redfishPayload* getPayloadByPath(redfishService* service, const char* path= , EFI_HTTP_STATUS_CODE** StatusCode);=0D diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/= payload.c b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/p= ayload.c index bd8d143c4e..8b49bec0df 100644 --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload= .c +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload= .c @@ -9,7 +9,7 @@ //------------------------------------------------------------------------= ----=0D =0D Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D @@ -326,6 +326,40 @@ redfishPayload* getPayloadForPathString(redfishPayload= * payload, const char* str return ret;=0D }=0D =0D +redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload* pay= load, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE**= StatusCode)=0D +{=0D + json_t* json;=0D + char* content;=0D + char* uri;=0D +=0D + if(!target || !payload || StatusCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D +=0D + json =3D json_object_get(target->json, "@odata.id");=0D + if(json =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D + uri =3D strdup(json_string_value(json));=0D +=0D + content =3D json_dumps(payload->json, 0);=0D + json_decref(json);=0D +=0D + json =3D patchUriFromServiceEx(target->service, uri, content, Headers, H= eaderCount, StatusCode);=0D + free(uri);=0D + free(content);=0D + if(json =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + return createRedfishPayload(json, target->service);=0D +}=0D +=0D redfishPayload* patchPayload(redfishPayload* target, redfishPayload* paylo= ad, EFI_HTTP_STATUS_CODE** StatusCode)=0D {=0D json_t* json;=0D @@ -360,6 +394,38 @@ redfishPayload* patchPayload(redfishPayload* target, r= edfishPayload* payload, EF return createRedfishPayload(json, target->service);=0D }=0D =0D +redfishPayload* postContentToPayloadEx(redfishPayload* target, const char*= data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER **Headers,= UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode)=0D +{=0D + json_t* json;=0D + char* uri;=0D +=0D + if(!target || !data || StatusCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D +=0D + json =3D json_object_get(target->json, "@odata.id");=0D + if(json =3D=3D NULL)=0D + {=0D + json =3D json_object_get(target->json, "target");=0D + if(json =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D + }=0D + uri =3D strdup(json_string_value(json));=0D + json =3D postUriFromServiceEx(target->service, uri, data, dataSize, co= ntentType, Headers, HeaderCount, StatusCode);=0D + free(uri);=0D + if(json =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + return createRedfishPayload(json, target->service);=0D +}=0D +=0D redfishPayload* postContentToPayload(redfishPayload* target, const char* d= ata, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** Statu= sCode)=0D {=0D json_t* json;=0D @@ -392,6 +458,28 @@ redfishPayload* postContentToPayload(redfishPayload* t= arget, const char* data, s return createRedfishPayload(json, target->service);=0D }=0D =0D +redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload* payl= oad, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** = StatusCode)=0D +{=0D + char* content;=0D + redfishPayload* ret;=0D +=0D + if(!target || !payload || StatusCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D +=0D + if(!json_is_object(payload->json))=0D + {=0D + return NULL;=0D + }=0D + content =3D payloadToString(payload, false);=0D + ret =3D postContentToPayloadEx(target, content, strlen(content), NULL,= Headers, HeaderCount, StatusCode);=0D + free(content);=0D + return ret;=0D +}=0D +=0D redfishPayload* postPayload(redfishPayload* target, redfishPayload* payloa= d, EFI_HTTP_STATUS_CODE** StatusCode)=0D {=0D char* content;=0D diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/= service.c b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/s= ervice.c index 7713f89e6d..450fa78bbd 100644 --- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service= .c +++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service= .c @@ -9,7 +9,7 @@ //------------------------------------------------------------------------= ----=0D =0D Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D - (C) Copyright 2021 Hewlett Packard Enterprise Development LP
=0D + (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP
=0D =0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D @@ -338,6 +338,190 @@ ON_EXIT: return ret;=0D }=0D =0D +EFI_HTTP_HEADER *cloneHttpHeaders(EFI_HTTP_MESSAGE *message, UINTN *Header= Count)=0D +{=0D + EFI_HTTP_HEADER *Buffer;=0D + UINTN Index;=0D +=0D + if (message =3D=3D NULL || HeaderCount =3D=3D NULL) {=0D + return NULL;=0D + }=0D +=0D + *HeaderCount =3D message->HeaderCount;=0D + Buffer =3D AllocatePool (sizeof (EFI_HTTP_HEADER) * message->HeaderCoun= t);=0D + if (Buffer =3D=3D NULL) {=0D + return NULL;=0D + }=0D +=0D + for (Index =3D 0; Index < message->HeaderCount; Index++) {=0D + Buffer[Index].FieldName =3D AllocateCopyPool (AsciiStrSize (message->H= eaders[Index].FieldName), message->Headers[Index].FieldName);=0D + ASSERT (Buffer[Index].FieldName !=3D NULL);=0D + Buffer[Index].FieldValue =3D AllocateCopyPool (AsciiStrSize (message->= Headers[Index].FieldValue), message->Headers[Index].FieldValue);=0D + ASSERT (Buffer[Index].FieldValue !=3D NULL);=0D + }=0D +=0D + return Buffer;=0D +}=0D +=0D +json_t* getUriFromServiceEx(redfishService* service, const char* uri, EFI_= HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE **StatusCod= e)=0D +{=0D + char* url;=0D + json_t* ret;=0D + HTTP_IO_HEADER *HttpIoHeader =3D NULL;=0D + EFI_STATUS Status;=0D + EFI_HTTP_REQUEST_DATA *RequestData =3D NULL;=0D + EFI_HTTP_MESSAGE *RequestMsg =3D NULL;=0D + EFI_HTTP_MESSAGE ResponseMsg;=0D + EFI_HTTP_HEADER *ContentEncodedHeader;=0D +=0D + if(service =3D=3D NULL || uri =3D=3D NULL || Headers =3D=3D NULL || Head= erCount =3D=3D NULL ||StatusCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D + *HeaderCount =3D 0;=0D + *Headers =3D NULL;=0D +=0D + url =3D makeUrlForService(service, uri);=0D + if(!url)=0D + {=0D + return NULL;=0D + }=0D +=0D + DEBUG((DEBUG_INFO, "libredfish: getUriFromServiceEx(): %a\n", url));=0D +=0D + //=0D + // Step 1: Create HTTP request message with 4 headers:=0D + //=0D + HttpIoHeader =3D HttpIoCreateHeader ((service->sessionToken || service->= basicAuthStr) ? 6 : 5);=0D + if (HttpIoHeader =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + if(service->sessionToken)=0D + {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->ses= sionToken);=0D + ASSERT_EFI_ERROR (Status);=0D + } else if (service->basicAuthStr) {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Authorization", service->ba= sicAuthStr);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderVal= ue);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");= =0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Step 2: build the rest of HTTP request info.=0D + //=0D + RequestData =3D AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));=0D + if (RequestData =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + RequestData->Method =3D HttpMethodGet;=0D + RequestData->Url =3D C8ToC16 (url);=0D +=0D + //=0D + // Step 3: fill in EFI_HTTP_MESSAGE=0D + //=0D + RequestMsg =3D AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));=0D + if (RequestMsg =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + RequestMsg->Data.Request =3D RequestData;=0D + RequestMsg->HeaderCount =3D HttpIoHeader->HeaderCount;=0D + RequestMsg->Headers =3D HttpIoHeader->Headers;=0D +=0D + ZeroMem (&ResponseMsg, sizeof (ResponseMsg));=0D +=0D + //=0D + // Step 4: call RESTEx to get response from REST service.=0D + //=0D + Status =3D service->RestEx->SendReceive (service->RestEx, RequestMsg, &R= esponseMsg);=0D + if (EFI_ERROR (Status)) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // Step 5: Return the HTTP StatusCode and Body message.=0D + //=0D + if (ResponseMsg.Data.Response !=3D NULL) {=0D + *StatusCode =3D AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));=0D + if (*StatusCode =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // The caller shall take the responsibility to free the buffer.=0D + //=0D + **StatusCode =3D ResponseMsg.Data.Response->StatusCode;=0D + }=0D +=0D + if (ResponseMsg.Headers !=3D NULL) {=0D + *Headers =3D cloneHttpHeaders (&ResponseMsg, HeaderCount);=0D + }=0D +=0D + if (ResponseMsg.BodyLength !=3D 0 && ResponseMsg.Body !=3D NULL) {=0D + //=0D + // Check if data is encoded.=0D + //=0D + ContentEncodedHeader =3D HttpFindHeader (ResponseMsg.HeaderCount, Resp= onseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING);=0D + if (ContentEncodedHeader !=3D NULL) {=0D + //=0D + // The content is encoded.=0D + //=0D + Status =3D DecodeResponseContent (ContentEncodedHeader->FieldValue, = &ResponseMsg.Body, &ResponseMsg.BodyLength);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response conten= t %r\n.", __FUNCTION__, Status));=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D + }=0D + ret =3D json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL)= ;=0D + } else {=0D + //=0D + // There is no message body returned from server.=0D + //=0D + ret =3D NULL;=0D + }=0D +=0D +ON_EXIT:=0D + if (url !=3D NULL) {=0D + free (url);=0D + }=0D +=0D + if (HttpIoHeader !=3D NULL) {=0D + HttpIoFreeHeader (HttpIoHeader);=0D + }=0D +=0D + if (RequestData !=3D NULL) {=0D + RestConfigFreeHttpRequestData (RequestData);=0D + }=0D +=0D + if (RequestMsg !=3D NULL) {=0D + FreePool (RequestMsg);=0D + }=0D +=0D + RestConfigFreeHttpMessage (&ResponseMsg, FALSE);=0D +=0D + return ret;=0D +}=0D +=0D json_t* getUriFromService(redfishService* service, const char* uri, EFI_HT= TP_STATUS_CODE** StatusCode)=0D {=0D char* url;=0D @@ -491,7 +675,7 @@ ON_EXIT: return ret;=0D }=0D =0D -json_t* patchUriFromService(redfishService* service, const char* uri, cons= t char* content, EFI_HTTP_STATUS_CODE** StatusCode)=0D +json_t* patchUriFromServiceEx(redfishService* service, const char* uri, co= nst char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount, EFI_HTTP_= STATUS_CODE** StatusCode)=0D {=0D char* url;=0D json_t* ret;=0D @@ -632,6 +816,10 @@ json_t* patchUriFromService(redfishService* service, c= onst char* uri, const char **StatusCode =3D ResponseMsg.Data.Response->StatusCode;=0D }=0D =0D + if (ResponseMsg.Headers !=3D NULL) {=0D + *Headers =3D cloneHttpHeaders (&ResponseMsg, HeaderCount);=0D + }=0D +=0D if (EncodedContent !=3D content) {=0D FreePool (EncodedContent);=0D }=0D @@ -668,6 +856,368 @@ ON_EXIT: return ret;=0D }=0D =0D +json_t* patchUriFromService(redfishService* service, const char* uri, cons= t char* content, EFI_HTTP_STATUS_CODE** StatusCode)=0D +{=0D + char* url;=0D + json_t* ret;=0D + HTTP_IO_HEADER *HttpIoHeader =3D NULL;=0D + EFI_STATUS Status;=0D + EFI_HTTP_REQUEST_DATA *RequestData =3D NULL;=0D + EFI_HTTP_MESSAGE *RequestMsg =3D NULL;=0D + EFI_HTTP_MESSAGE ResponseMsg;=0D + CHAR8 ContentLengthStr[80];=0D + CHAR8 *EncodedContent;=0D + UINTN EncodedContentLen;=0D +=0D + if(service =3D=3D NULL || uri =3D=3D NULL || content =3D=3D NULL || Stat= usCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D +=0D + url =3D makeUrlForService(service, uri);=0D + if(!url)=0D + {=0D + return NULL;=0D + }=0D +=0D + DEBUG((DEBUG_INFO, "libredfish: patchUriFromService(): %a\n", url));=0D +=0D + //=0D + // Step 1: Create HTTP request message with 4 headers:=0D + //=0D + HttpIoHeader =3D HttpIoCreateHeader ((service->sessionToken || service->= basicAuthStr) ? 9 : 8);=0D + if (HttpIoHeader =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + if(service->sessionToken)=0D + {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->ses= sionToken);=0D + ASSERT_EFI_ERROR (Status);=0D + } else if (service->basicAuthStr) {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Authorization", service->ba= sicAuthStr);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderVal= ue);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/j= son");=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");= =0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + AsciiSPrint(=0D + ContentLengthStr,=0D + sizeof (ContentLengthStr),=0D + "%lu",=0D + (UINT64) strlen(content)=0D + );=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengt= hStr);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Step 2: build the rest of HTTP request info.=0D + //=0D + RequestData =3D AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));=0D + if (RequestData =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + RequestData->Method =3D HttpMethodPatch;=0D + RequestData->Url =3D C8ToC16 (url);=0D +=0D + //=0D + // Step 3: fill in EFI_HTTP_MESSAGE=0D + //=0D + RequestMsg =3D AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));=0D + if (RequestMsg =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + EncodedContent =3D (CHAR8 *)content;=0D + EncodedContentLen =3D strlen(content);=0D + //=0D + // We currently only support gzip Content-Encoding.=0D + //=0D + Status =3D EncodeRequestContent ((CHAR8 *)HTTP_CONTENT_ENCODING_GZIP, (C= HAR8 *)content, (VOID **)&EncodedContent, &EncodedContentLen);=0D + if (Status =3D=3D EFI_INVALID_PARAMETER) {=0D + DEBUG((DEBUG_ERROR, "%a: Error to encode content.\n", __FUNCTION__));= =0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + } else if (Status =3D=3D EFI_UNSUPPORTED) {=0D + DEBUG((DEBUG_INFO, "No content coding for %a! Use raw data instead.\n"= , HTTP_CONTENT_ENCODING_GZIP));=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CON= TENT_ENCODING_IDENTITY);=0D + ASSERT_EFI_ERROR (Status);=0D + } else {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CON= TENT_ENCODING_GZIP);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +=0D + RequestMsg->Data.Request =3D RequestData;=0D + RequestMsg->HeaderCount =3D HttpIoHeader->HeaderCount;=0D + RequestMsg->Headers =3D HttpIoHeader->Headers;=0D + RequestMsg->BodyLength =3D EncodedContentLen;=0D + RequestMsg->Body =3D (VOID*) EncodedContent;=0D +=0D + ZeroMem (&ResponseMsg, sizeof (ResponseMsg));=0D +=0D + //=0D + // Step 4: call RESTEx to get response from REST service.=0D + //=0D + Status =3D service->RestEx->SendReceive (service->RestEx, RequestMsg, &R= esponseMsg);=0D + if (EFI_ERROR (Status)) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // Step 5: Return the HTTP StatusCode and Body message.=0D + //=0D + if (ResponseMsg.Data.Response !=3D NULL) {=0D + *StatusCode =3D AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));=0D + if (*StatusCode =3D=3D NULL) {=0D + ret =3D NULL;=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // The caller shall take the responsibility to free the buffer.=0D + //=0D + **StatusCode =3D ResponseMsg.Data.Response->StatusCode;=0D + }=0D +=0D + if (EncodedContent !=3D content) {=0D + FreePool (EncodedContent);=0D + }=0D +=0D +=0D + if (ResponseMsg.BodyLength !=3D 0 && ResponseMsg.Body !=3D NULL) {=0D + ret =3D json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL)= ;=0D + } else {=0D + //=0D + // There is no message body returned from server.=0D + //=0D + ret =3D NULL;=0D + }=0D +=0D +ON_EXIT:=0D + if (url !=3D NULL) {=0D + free (url);=0D + }=0D +=0D + if (HttpIoHeader !=3D NULL) {=0D + HttpIoFreeHeader (HttpIoHeader);=0D + }=0D +=0D + if (RequestData !=3D NULL) {=0D + RestConfigFreeHttpRequestData (RequestData);=0D + }=0D +=0D + if (RequestMsg !=3D NULL) {=0D + FreePool (RequestMsg);=0D + }=0D +=0D + RestConfigFreeHttpMessage (&ResponseMsg, FALSE);=0D +=0D + return ret;=0D +}=0D +=0D +json_t* postUriFromServiceEx(redfishService* service, const char* uri, con= st char* content, size_t contentLength, const char* contentType, EFI_HTTP_H= EADER **Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode)=0D +{=0D + char* url =3D NULL;=0D + json_t* ret;=0D + HTTP_IO_HEADER *HttpIoHeader =3D NULL;=0D + EFI_STATUS Status;=0D + EFI_HTTP_REQUEST_DATA *RequestData =3D NULL;=0D + EFI_HTTP_MESSAGE *RequestMsg =3D NULL;=0D + EFI_HTTP_MESSAGE ResponseMsg;=0D + CHAR8 ContentLengthStr[80];=0D + EFI_HTTP_HEADER *HttpHeader =3D NULL;=0D +=0D + ret =3D NULL;=0D +=0D + if(service =3D=3D NULL || uri =3D=3D NULL || content =3D=3D NULL || Stat= usCode =3D=3D NULL)=0D + {=0D + return NULL;=0D + }=0D +=0D + *StatusCode =3D NULL;=0D +=0D + url =3D makeUrlForService(service, uri);=0D + if(!url)=0D + {=0D + return NULL;=0D + }=0D +=0D + DEBUG((DEBUG_INFO, "libredfish: postUriFromService(): %a\n", url));=0D +=0D + if(contentLength =3D=3D 0)=0D + {=0D + contentLength =3D strlen(content);=0D + }=0D +=0D + //=0D + // Step 1: Create HTTP request message with 4 headers:=0D + //=0D + HttpIoHeader =3D HttpIoCreateHeader ((service->sessionToken || service->= basicAuthStr) ? 8 : 7);=0D + if (HttpIoHeader =3D=3D NULL) {=0D + goto ON_EXIT;=0D + }=0D +=0D + if(service->sessionToken)=0D + {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->ses= sionToken);=0D + ASSERT_EFI_ERROR (Status);=0D + } else if (service->basicAuthStr) {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Authorization", service->ba= sicAuthStr);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +=0D + if(contentType =3D=3D NULL) {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Type", "application= /json");=0D + ASSERT_EFI_ERROR (Status);=0D + } else {=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8 *) co= ntentType);=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderVal= ue);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");= =0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");=0D + ASSERT_EFI_ERROR (Status);=0D + AsciiSPrint(=0D + ContentLengthStr,=0D + sizeof (ContentLengthStr),=0D + "%lu",=0D + (UINT64) contentLength=0D + );=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengt= hStr);=0D + ASSERT_EFI_ERROR (Status);=0D + Status =3D HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // Step 2: build the rest of HTTP request info.=0D + //=0D + RequestData =3D AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));=0D + if (RequestData =3D=3D NULL) {=0D + goto ON_EXIT;=0D + }=0D +=0D + RequestData->Method =3D HttpMethodPost;=0D + RequestData->Url =3D C8ToC16 (url);=0D +=0D + //=0D + // Step 3: fill in EFI_HTTP_MESSAGE=0D + //=0D + RequestMsg =3D AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));=0D + if (RequestMsg =3D=3D NULL) {=0D + goto ON_EXIT;=0D + }=0D +=0D + RequestMsg->Data.Request =3D RequestData;=0D + RequestMsg->HeaderCount =3D HttpIoHeader->HeaderCount;=0D + RequestMsg->Headers =3D HttpIoHeader->Headers;=0D + RequestMsg->BodyLength =3D contentLength;=0D + RequestMsg->Body =3D (VOID*) content;=0D +=0D + ZeroMem (&ResponseMsg, sizeof (ResponseMsg));=0D +=0D + //=0D + // Step 4: call RESTEx to get response from REST service.=0D + //=0D + Status =3D service->RestEx->SendReceive (service->RestEx, RequestMsg, &R= esponseMsg);=0D + if (EFI_ERROR (Status)) {=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // Step 5: Return the HTTP StatusCode and Body message.=0D + //=0D + if (ResponseMsg.Data.Response !=3D NULL) {=0D + *StatusCode =3D AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));=0D + if (*StatusCode =3D=3D NULL) {=0D + goto ON_EXIT;=0D + }=0D +=0D + //=0D + // The caller shall take the responsibility to free the buffer.=0D + //=0D + **StatusCode =3D ResponseMsg.Data.Response->StatusCode;=0D + }=0D +=0D + if (ResponseMsg.Headers !=3D NULL) {=0D + *Headers =3D cloneHttpHeaders (&ResponseMsg, HeaderCount);=0D + }=0D +=0D + if (ResponseMsg.BodyLength !=3D 0 && ResponseMsg.Body !=3D NULL) {=0D + ret =3D json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL)= ;=0D + }=0D +=0D + //=0D + // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTT= P StatusCode is correct.=0D + //=0D + if (ResponseMsg.Data.Response->StatusCode =3D=3D HTTP_STATUS_200_OK ||=0D + ResponseMsg.Data.Response->StatusCode =3D=3D HTTP_STATUS_204_NO_CONT= ENT) {=0D + HttpHeader =3D HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.He= aders, "X-Auth-Token");=0D + if (HttpHeader !=3D NULL) {=0D + if(service->sessionToken)=0D + {=0D + free(service->sessionToken);=0D + }=0D + service->sessionToken =3D AllocateCopyPool (AsciiStrSize (HttpHeader= ->FieldValue), HttpHeader->FieldValue);=0D + }=0D +=0D + /*=0D + //=0D + // Below opeation seems to be unnecessary.=0D + // Besides, the FieldValue for the Location is the full HTTP URI (Http= ://0.0.0.0:5000/XXX), so we can't use it as the=0D + // parameter of getUriFromService () directly.=0D + //=0D + HttpHeader =3D HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.He= aders, "Location");=0D + if (HttpHeader !=3D NULL) {=0D + ret =3D getUriFromService(service, HttpHeader->FieldValue);=0D + goto ON_EXIT;=0D + }=0D + */=0D + }=0D +=0D +ON_EXIT:=0D + if (url !=3D NULL) {=0D + free (url);=0D + }=0D +=0D + if (HttpIoHeader !=3D NULL) {=0D + HttpIoFreeHeader (HttpIoHeader);=0D + }=0D +=0D + if (RequestData !=3D NULL) {=0D + RestConfigFreeHttpRequestData (RequestData);=0D + }=0D +=0D + if (RequestMsg !=3D NULL) {=0D + FreePool (RequestMsg);=0D + }=0D +=0D + RestConfigFreeHttpMessage (&ResponseMsg, FALSE);=0D +=0D + return ret;=0D +}=0D +=0D json_t* postUriFromService(redfishService* service, const char* uri, const= char* content, size_t contentLength, const char* contentType, EFI_HTTP_STA= TUS_CODE** StatusCode)=0D {=0D char* url =3D NULL;=0D --=20 2.32.0.windows.2