]>
Commit | Line | Data |
---|---|---|
4751a48a AC |
1 | /** @file\r |
2 | This file is cloned from DMTF libredfish library tag v1.0.0 and maintained\r | |
3 | by EDKII.\r | |
4 | \r | |
5 | //----------------------------------------------------------------------------\r | |
6 | // Copyright Notice:\r | |
7 | // Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.\r | |
8 | // License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md\r | |
9 | //----------------------------------------------------------------------------\r | |
10 | \r | |
11 | Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r | |
12 | (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r | |
13 | \r | |
14 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
15 | \r | |
16 | **/\r | |
17 | \r | |
18 | #include <redfishService.h>\r | |
19 | #include <redfishPayload.h>\r | |
20 | #include <redpath.h>\r | |
21 | \r | |
39de741e MK |
22 | static int\r |
23 | initRest (\r | |
24 | redfishService *service,\r | |
25 | void *restProtocol\r | |
26 | );\r | |
27 | \r | |
28 | static redfishService *\r | |
29 | createServiceEnumeratorNoAuth (\r | |
30 | const char *host,\r | |
31 | const char *rootUri,\r | |
32 | bool enumerate,\r | |
33 | unsigned int flags,\r | |
34 | void *restProtocol\r | |
35 | );\r | |
36 | \r | |
37 | static redfishService *\r | |
38 | createServiceEnumeratorBasicAuth (\r | |
39 | const char *host,\r | |
40 | const char *rootUri,\r | |
41 | const char *username,\r | |
42 | const char *password,\r | |
43 | unsigned int flags,\r | |
44 | void *restProtocol\r | |
45 | );\r | |
46 | \r | |
47 | static redfishService *\r | |
48 | createServiceEnumeratorSessionAuth (\r | |
49 | const char *host,\r | |
50 | const char *rootUri,\r | |
51 | const char *username,\r | |
52 | const char *password,\r | |
53 | unsigned int flags,\r | |
54 | void *restProtocol\r | |
55 | );\r | |
56 | \r | |
57 | static char *\r | |
58 | makeUrlForService (\r | |
59 | redfishService *service,\r | |
60 | const char *uri\r | |
61 | );\r | |
62 | \r | |
63 | static json_t *\r | |
64 | getVersions (\r | |
65 | redfishService *service,\r | |
66 | const char *rootUri\r | |
67 | );\r | |
68 | \r | |
69 | static void\r | |
70 | addStringToJsonObject (\r | |
71 | json_t *object,\r | |
72 | const char *key,\r | |
73 | const char *value\r | |
74 | );\r | |
75 | \r | |
76 | CHAR16 *\r | |
77 | C8ToC16 (\r | |
78 | CHAR8 *AsciiStr\r | |
79 | )\r | |
4751a48a | 80 | {\r |
39de741e | 81 | CHAR16 *Str;\r |
4751a48a AC |
82 | UINTN BufLen;\r |
83 | \r | |
84 | BufLen = (AsciiStrLen (AsciiStr) + 1) * 2;\r | |
39de741e | 85 | Str = AllocatePool (BufLen);\r |
4751a48a AC |
86 | ASSERT (Str != NULL);\r |
87 | \r | |
88 | AsciiStrToUnicodeStrS (AsciiStr, Str, AsciiStrLen (AsciiStr) + 1);\r | |
89 | \r | |
90 | return Str;\r | |
91 | }\r | |
92 | \r | |
93 | VOID\r | |
94 | RestConfigFreeHttpRequestData (\r | |
39de741e | 95 | IN EFI_HTTP_REQUEST_DATA *RequestData\r |
4751a48a AC |
96 | )\r |
97 | {\r | |
98 | if (RequestData == NULL) {\r | |
39de741e | 99 | return;\r |
4751a48a AC |
100 | }\r |
101 | \r | |
102 | if (RequestData->Url != NULL) {\r | |
103 | FreePool (RequestData->Url);\r | |
104 | }\r | |
105 | \r | |
106 | FreePool (RequestData);\r | |
107 | }\r | |
108 | \r | |
109 | VOID\r | |
110 | RestConfigFreeHttpMessage (\r | |
39de741e MK |
111 | IN EFI_HTTP_MESSAGE *Message,\r |
112 | IN BOOLEAN IsRequest\r | |
4751a48a AC |
113 | )\r |
114 | {\r | |
115 | if (Message == NULL) {\r | |
39de741e | 116 | return;\r |
4751a48a AC |
117 | }\r |
118 | \r | |
119 | if (IsRequest) {\r | |
120 | RestConfigFreeHttpRequestData (Message->Data.Request);\r | |
121 | Message->Data.Request = NULL;\r | |
122 | } else {\r | |
123 | if (Message->Data.Response != NULL) {\r | |
124 | FreePool (Message->Data.Response);\r | |
125 | Message->Data.Response = NULL;\r | |
126 | }\r | |
127 | }\r | |
128 | \r | |
129 | if (Message->Headers != NULL) {\r | |
130 | FreePool (Message->Headers);\r | |
131 | Message->Headers = NULL;\r | |
132 | }\r | |
39de741e | 133 | \r |
4751a48a AC |
134 | if (Message->Body != NULL) {\r |
135 | FreePool (Message->Body);\r | |
136 | Message->Body = NULL;\r | |
137 | }\r | |
138 | }\r | |
139 | \r | |
140 | /**\r | |
141 | Converts the Unicode string to ASCII string to a new allocated buffer.\r | |
142 | \r | |
143 | @param[in] String Unicode string to be converted.\r | |
144 | \r | |
145 | @return Buffer points to ASCII string, or NULL if error happens.\r | |
146 | \r | |
147 | **/\r | |
4751a48a AC |
148 | CHAR8 *\r |
149 | UnicodeStrDupToAsciiStr (\r | |
39de741e | 150 | CONST CHAR16 *String\r |
4751a48a AC |
151 | )\r |
152 | {\r | |
39de741e MK |
153 | CHAR8 *AsciiStr;\r |
154 | UINTN BufLen;\r | |
155 | EFI_STATUS Status;\r | |
4751a48a | 156 | \r |
39de741e | 157 | BufLen = StrLen (String) + 1;\r |
4751a48a AC |
158 | AsciiStr = AllocatePool (BufLen);\r |
159 | if (AsciiStr == NULL) {\r | |
160 | return NULL;\r | |
161 | }\r | |
162 | \r | |
163 | Status = UnicodeStrToAsciiStrS (String, AsciiStr, BufLen);\r | |
164 | if (EFI_ERROR (Status)) {\r | |
165 | return NULL;\r | |
166 | }\r | |
167 | \r | |
168 | return AsciiStr;\r | |
169 | }\r | |
39de741e | 170 | \r |
4751a48a AC |
171 | /**\r |
172 | This function encodes the content.\r | |
173 | \r | |
174 | @param[in] ContentEncodedValue HTTP conent encoded value.\r | |
175 | @param[in] OriginalContent Original content.\r | |
176 | @param[out] EncodedContent Pointer to receive encoded content.\r | |
177 | @param[out] EncodedContentLength Length of encoded content.\r | |
178 | \r | |
179 | @retval EFI_SUCCESS Content encoded successfully.\r | |
180 | @retval EFI_UNSUPPORTED No source encoding funciton,\r | |
181 | @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.\r | |
182 | \r | |
183 | **/\r | |
184 | EFI_STATUS\r | |
185 | EncodeRequestContent (\r | |
39de741e MK |
186 | IN CHAR8 *ContentEncodedValue,\r |
187 | IN CHAR8 *OriginalContent,\r | |
188 | OUT VOID **EncodedContent,\r | |
189 | OUT UINTN *EncodedContentLength\r | |
190 | )\r | |
4751a48a | 191 | {\r |
39de741e MK |
192 | EFI_STATUS Status;\r |
193 | VOID *EncodedPointer;\r | |
194 | UINTN EncodedLength;\r | |
4751a48a | 195 | \r |
39de741e | 196 | if ((OriginalContent == NULL) || (EncodedContent == NULL) || (EncodedContentLength == NULL)) {\r |
4751a48a AC |
197 | return EFI_INVALID_PARAMETER;\r |
198 | }\r | |
39de741e MK |
199 | \r |
200 | Status = RedfishContentEncode (\r | |
4751a48a AC |
201 | ContentEncodedValue,\r |
202 | OriginalContent,\r | |
203 | AsciiStrLen (OriginalContent),\r | |
204 | &EncodedPointer,\r | |
205 | &EncodedLength\r | |
39de741e | 206 | );\r |
4751a48a | 207 | if (Status == EFI_SUCCESS) {\r |
39de741e | 208 | *EncodedContent = EncodedPointer;\r |
4751a48a AC |
209 | *EncodedContentLength = EncodedLength;\r |
210 | return EFI_SUCCESS;\r | |
211 | }\r | |
39de741e | 212 | \r |
4751a48a AC |
213 | return Status;\r |
214 | }\r | |
215 | \r | |
216 | /**\r | |
217 | This function decodes the content. The Memory block pointed by\r | |
218 | ContentPointer would be freed and replaced with the cooked Redfish\r | |
219 | payload.\r | |
220 | \r | |
221 | @param[in] ContentEncodedValue HTTP conent encoded value.\r | |
222 | @param[in, out] ContentPointer Pointer to encoded content.\r | |
223 | Pointer of decoded content when out.\r | |
224 | @param[in, out] ContentLength Pointer to the length of encoded content.\r | |
225 | Length of decoded content when out.\r | |
226 | \r | |
227 | @retval EFI_SUCCESS Functinos found.\r | |
228 | @retval EFI_UNSUPPORTED No functions found.\r | |
229 | @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.\r | |
230 | \r | |
231 | **/\r | |
232 | EFI_STATUS\r | |
233 | DecodeResponseContent (\r | |
39de741e MK |
234 | IN CHAR8 *ContentEncodedValue,\r |
235 | IN OUT VOID **ContentPointer,\r | |
236 | IN OUT UINTN *ContentLength\r | |
237 | )\r | |
4751a48a | 238 | {\r |
39de741e MK |
239 | EFI_STATUS Status;\r |
240 | VOID *DecodedPointer;\r | |
241 | UINTN DecodedLength;\r | |
4751a48a AC |
242 | \r |
243 | if (ContentEncodedValue == NULL) {\r | |
244 | return EFI_INVALID_PARAMETER;\r | |
245 | }\r | |
39de741e | 246 | \r |
4751a48a | 247 | Status = RedfishContentDecode (\r |
39de741e MK |
248 | ContentEncodedValue,\r |
249 | *ContentPointer,\r | |
250 | *ContentLength,\r | |
251 | &DecodedPointer,\r | |
252 | &DecodedLength\r | |
253 | );\r | |
4751a48a AC |
254 | if (Status == EFI_SUCCESS) {\r |
255 | FreePool (*ContentPointer);\r | |
256 | *ContentPointer = DecodedPointer;\r | |
39de741e | 257 | *ContentLength = DecodedLength;\r |
4751a48a | 258 | }\r |
39de741e | 259 | \r |
4751a48a AC |
260 | return Status;\r |
261 | }\r | |
262 | \r | |
263 | /**\r | |
264 | Create a HTTP URL string for specific Redfish resource.\r | |
265 | \r | |
266 | This function build a URL string from the Redfish Host interface record and caller specified\r | |
267 | relative path of the resource.\r | |
268 | \r | |
269 | Callers are responsible for freeing the returned string storage pointed by HttpUrl.\r | |
270 | \r | |
271 | @param[in] RedfishData Redfish network host interface record.\r | |
272 | @param[in] RelativePath Relative path of a resource.\r | |
273 | @param[out] HttpUrl The pointer to store the returned URL string.\r | |
274 | \r | |
275 | @retval EFI_SUCCESS Build the URL string successfully.\r | |
276 | @retval EFI_INVALID_PARAMETER RedfishData or HttpUrl is NULL.\r | |
277 | @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.\r | |
278 | \r | |
279 | **/\r | |
280 | EFI_STATUS\r | |
281 | RedfishBuildUrl (\r | |
39de741e MK |
282 | IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,\r |
283 | IN CHAR16 *RelativePath OPTIONAL,\r | |
284 | OUT CHAR16 **HttpUrl\r | |
4751a48a AC |
285 | )\r |
286 | {\r | |
39de741e MK |
287 | CHAR16 *Url;\r |
288 | CHAR16 *UrlHead;\r | |
289 | UINTN UrlLength;\r | |
290 | UINTN PathLen;\r | |
4751a48a AC |
291 | \r |
292 | if ((RedfishConfigServiceInfo == NULL) || (HttpUrl == NULL)) {\r | |
293 | return EFI_INVALID_PARAMETER;\r | |
294 | }\r | |
295 | \r | |
296 | //\r | |
297 | // RFC2616: http_URL = "http(s):" "//" host [ ":" port ] [ abs_path [ "?" query ]]\r | |
298 | //\r | |
299 | if (RelativePath == NULL) {\r | |
300 | PathLen = 0;\r | |
301 | } else {\r | |
302 | PathLen = StrLen (RelativePath);\r | |
303 | }\r | |
39de741e MK |
304 | \r |
305 | UrlLength = StrLen (HTTPS_FLAG) + StrLen (REDFISH_FIRST_URL) + 1 + StrLen (RedfishConfigServiceInfo->RedfishServiceLocation) + PathLen;\r | |
306 | Url = AllocateZeroPool (UrlLength * sizeof (CHAR16));\r | |
4751a48a AC |
307 | if (Url == NULL) {\r |
308 | return EFI_OUT_OF_RESOURCES;\r | |
309 | }\r | |
310 | \r | |
311 | UrlHead = Url;\r | |
312 | //\r | |
313 | // Copy "http://" or "https://" according RedfishServiceIpPort.\r | |
314 | //\r | |
315 | if (!RedfishConfigServiceInfo->RedfishServiceUseHttps) {\r | |
316 | StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTP_FLAG);\r | |
317 | Url = Url + StrLen (HTTP_FLAG);\r | |
318 | } else {\r | |
319 | StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTPS_FLAG);\r | |
320 | Url = Url + StrLen (HTTPS_FLAG);\r | |
321 | }\r | |
322 | \r | |
323 | StrCpyS (Url, StrLen (RedfishConfigServiceInfo->RedfishServiceLocation) + 1, RedfishConfigServiceInfo->RedfishServiceLocation);\r | |
324 | Url = Url + StrLen (RedfishConfigServiceInfo->RedfishServiceLocation);\r | |
325 | \r | |
326 | //\r | |
327 | // Copy abs_path\r | |
328 | //\r | |
39de741e | 329 | if ((RelativePath != NULL) && (PathLen != 0)) {\r |
4751a48a AC |
330 | StrnCpyS (Url, UrlLength, RelativePath, PathLen);\r |
331 | }\r | |
39de741e | 332 | \r |
4751a48a AC |
333 | *HttpUrl = UrlHead;\r |
334 | return EFI_SUCCESS;\r | |
335 | }\r | |
336 | \r | |
39de741e MK |
337 | redfishService *\r |
338 | createServiceEnumerator (\r | |
339 | REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,\r | |
340 | const char *rootUri,\r | |
341 | enumeratorAuthentication *auth,\r | |
342 | unsigned int flags\r | |
343 | )\r | |
4751a48a | 344 | {\r |
39de741e MK |
345 | EFI_STATUS Status;\r |
346 | CHAR16 *HttpUrl;\r | |
347 | CHAR8 *AsciiHost;\r | |
348 | EFI_REST_EX_PROTOCOL *RestEx;\r | |
349 | redfishService *ret;\r | |
4751a48a | 350 | \r |
39de741e | 351 | HttpUrl = NULL;\r |
4751a48a | 352 | AsciiHost = NULL;\r |
39de741e MK |
353 | RestEx = NULL;\r |
354 | ret = NULL;\r | |
4751a48a AC |
355 | \r |
356 | if (RedfishConfigServiceInfo->RedfishServiceRestExHandle == NULL) {\r | |
357 | goto ON_EXIT;\r | |
358 | }\r | |
39de741e MK |
359 | \r |
360 | Status = RedfishBuildUrl (RedfishConfigServiceInfo, NULL, &HttpUrl);\r | |
4751a48a AC |
361 | if (EFI_ERROR (Status)) {\r |
362 | goto ON_EXIT;\r | |
363 | }\r | |
364 | \r | |
365 | ASSERT (HttpUrl != NULL);\r | |
366 | \r | |
367 | AsciiHost = UnicodeStrDupToAsciiStr (HttpUrl);\r | |
368 | if (AsciiHost == NULL) {\r | |
369 | goto ON_EXIT;\r | |
370 | }\r | |
371 | \r | |
372 | Status = gBS->HandleProtocol (\r | |
39de741e MK |
373 | RedfishConfigServiceInfo->RedfishServiceRestExHandle,\r |
374 | &gEfiRestExProtocolGuid,\r | |
375 | (VOID **)&RestEx\r | |
376 | );\r | |
4751a48a AC |
377 | if (EFI_ERROR (Status)) {\r |
378 | goto ON_EXIT;\r | |
379 | }\r | |
39de741e MK |
380 | \r |
381 | if (auth == NULL) {\r | |
382 | ret = createServiceEnumeratorNoAuth (AsciiHost, rootUri, true, flags, RestEx);\r | |
383 | } else if (auth->authType == REDFISH_AUTH_BASIC) {\r | |
384 | ret = createServiceEnumeratorBasicAuth (AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);\r | |
385 | } else if (auth->authType == REDFISH_AUTH_SESSION) {\r | |
386 | ret = createServiceEnumeratorSessionAuth (AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);\r | |
4751a48a AC |
387 | } else {\r |
388 | goto ON_EXIT;\r | |
389 | }\r | |
390 | \r | |
391 | ret->RestEx = RestEx;\r | |
392 | ON_EXIT:\r | |
393 | if (HttpUrl != NULL) {\r | |
394 | FreePool (HttpUrl);\r | |
395 | }\r | |
396 | \r | |
397 | if (AsciiHost != NULL) {\r | |
398 | FreePool (AsciiHost);\r | |
399 | }\r | |
400 | \r | |
401 | return ret;\r | |
402 | }\r | |
403 | \r | |
39de741e MK |
404 | json_t *\r |
405 | getUriFromService (\r | |
406 | redfishService *service,\r | |
407 | const char *uri,\r | |
408 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
409 | )\r | |
4751a48a | 410 | {\r |
39de741e MK |
411 | char *url;\r |
412 | json_t *ret;\r | |
413 | HTTP_IO_HEADER *HttpIoHeader = NULL;\r | |
414 | EFI_STATUS Status;\r | |
415 | EFI_HTTP_REQUEST_DATA *RequestData = NULL;\r | |
416 | EFI_HTTP_MESSAGE *RequestMsg = NULL;\r | |
417 | EFI_HTTP_MESSAGE ResponseMsg;\r | |
418 | EFI_HTTP_HEADER *ContentEncodedHeader;\r | |
419 | \r | |
420 | if ((service == NULL) || (uri == NULL) || (StatusCode == NULL)) {\r | |
421 | return NULL;\r | |
4751a48a AC |
422 | }\r |
423 | \r | |
424 | *StatusCode = NULL;\r | |
425 | \r | |
39de741e MK |
426 | url = makeUrlForService (service, uri);\r |
427 | if (!url) {\r | |
428 | return NULL;\r | |
4751a48a AC |
429 | }\r |
430 | \r | |
39de741e | 431 | DEBUG ((DEBUG_INFO, "libredfish: getUriFromService(): %a\n", url));\r |
4751a48a AC |
432 | \r |
433 | //\r | |
434 | // Step 1: Create HTTP request message with 4 headers:\r | |
435 | //\r | |
436 | HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 6 : 5);\r | |
437 | if (HttpIoHeader == NULL) {\r | |
438 | ret = NULL;\r | |
439 | goto ON_EXIT;\r | |
440 | }\r | |
441 | \r | |
39de741e | 442 | if (service->sessionToken) {\r |
4751a48a AC |
443 | Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);\r |
444 | ASSERT_EFI_ERROR (Status);\r | |
445 | } else if (service->basicAuthStr) {\r | |
446 | Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);\r | |
447 | ASSERT_EFI_ERROR (Status);\r | |
448 | }\r | |
449 | \r | |
450 | Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);\r | |
451 | ASSERT_EFI_ERROR (Status);\r | |
452 | Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");\r | |
453 | ASSERT_EFI_ERROR (Status);\r | |
454 | Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");\r | |
455 | ASSERT_EFI_ERROR (Status);\r | |
456 | Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");\r | |
457 | ASSERT_EFI_ERROR (Status);\r | |
458 | Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");\r | |
459 | ASSERT_EFI_ERROR (Status);\r | |
460 | \r | |
461 | //\r | |
462 | // Step 2: build the rest of HTTP request info.\r | |
463 | //\r | |
464 | RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));\r | |
465 | if (RequestData == NULL) {\r | |
466 | ret = NULL;\r | |
467 | goto ON_EXIT;\r | |
468 | }\r | |
469 | \r | |
470 | RequestData->Method = HttpMethodGet;\r | |
39de741e | 471 | RequestData->Url = C8ToC16 (url);\r |
4751a48a AC |
472 | \r |
473 | //\r | |
474 | // Step 3: fill in EFI_HTTP_MESSAGE\r | |
475 | //\r | |
476 | RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));\r | |
477 | if (RequestMsg == NULL) {\r | |
478 | ret = NULL;\r | |
479 | goto ON_EXIT;\r | |
480 | }\r | |
481 | \r | |
482 | RequestMsg->Data.Request = RequestData;\r | |
483 | RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;\r | |
484 | RequestMsg->Headers = HttpIoHeader->Headers;\r | |
485 | \r | |
486 | ZeroMem (&ResponseMsg, sizeof (ResponseMsg));\r | |
487 | \r | |
488 | //\r | |
489 | // Step 4: call RESTEx to get response from REST service.\r | |
490 | //\r | |
491 | Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);\r | |
492 | if (EFI_ERROR (Status)) {\r | |
493 | ret = NULL;\r | |
494 | goto ON_EXIT;\r | |
495 | }\r | |
496 | \r | |
497 | //\r | |
498 | // Step 5: Return the HTTP StatusCode and Body message.\r | |
499 | //\r | |
500 | if (ResponseMsg.Data.Response != NULL) {\r | |
501 | *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));\r | |
502 | if (*StatusCode == NULL) {\r | |
503 | ret = NULL;\r | |
504 | goto ON_EXIT;\r | |
505 | }\r | |
506 | \r | |
507 | //\r | |
508 | // The caller shall take the responsibility to free the buffer.\r | |
509 | //\r | |
510 | **StatusCode = ResponseMsg.Data.Response->StatusCode;\r | |
511 | }\r | |
512 | \r | |
39de741e | 513 | if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {\r |
4751a48a AC |
514 | //\r |
515 | // Check if data is encoded.\r | |
516 | //\r | |
517 | ContentEncodedHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING);\r | |
518 | if (ContentEncodedHeader != NULL) {\r | |
519 | //\r | |
520 | // The content is encoded.\r | |
521 | //\r | |
522 | Status = DecodeResponseContent (ContentEncodedHeader->FieldValue, &ResponseMsg.Body, &ResponseMsg.BodyLength);\r | |
523 | if (EFI_ERROR (Status)) {\r | |
524 | DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response content %r\n.", __FUNCTION__, Status));\r | |
525 | ret = NULL;\r | |
526 | goto ON_EXIT;\r | |
527 | }\r | |
528 | }\r | |
39de741e | 529 | \r |
4751a48a AC |
530 | ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);\r |
531 | } else {\r | |
532 | //\r | |
533 | // There is no message body returned from server.\r | |
534 | //\r | |
535 | ret = NULL;\r | |
536 | }\r | |
537 | \r | |
538 | ON_EXIT:\r | |
539 | if (url != NULL) {\r | |
540 | free (url);\r | |
541 | }\r | |
542 | \r | |
543 | if (HttpIoHeader != NULL) {\r | |
544 | HttpIoFreeHeader (HttpIoHeader);\r | |
545 | }\r | |
546 | \r | |
547 | if (RequestData != NULL) {\r | |
548 | RestConfigFreeHttpRequestData (RequestData);\r | |
549 | }\r | |
550 | \r | |
551 | if (RequestMsg != NULL) {\r | |
552 | FreePool (RequestMsg);\r | |
553 | }\r | |
554 | \r | |
555 | RestConfigFreeHttpMessage (&ResponseMsg, FALSE);\r | |
556 | \r | |
557 | return ret;\r | |
558 | }\r | |
559 | \r | |
39de741e MK |
560 | json_t *\r |
561 | patchUriFromService (\r | |
562 | redfishService *service,\r | |
563 | const char *uri,\r | |
564 | const char *content,\r | |
565 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
566 | )\r | |
4751a48a | 567 | {\r |
39de741e MK |
568 | char *url;\r |
569 | json_t *ret;\r | |
570 | HTTP_IO_HEADER *HttpIoHeader = NULL;\r | |
571 | EFI_STATUS Status;\r | |
572 | EFI_HTTP_REQUEST_DATA *RequestData = NULL;\r | |
573 | EFI_HTTP_MESSAGE *RequestMsg = NULL;\r | |
574 | EFI_HTTP_MESSAGE ResponseMsg;\r | |
575 | CHAR8 ContentLengthStr[80];\r | |
576 | CHAR8 *EncodedContent;\r | |
577 | UINTN EncodedContentLen;\r | |
578 | \r | |
579 | if ((service == NULL) || (uri == NULL) || (content == NULL) || (StatusCode == NULL)) {\r | |
580 | return NULL;\r | |
4751a48a AC |
581 | }\r |
582 | \r | |
583 | *StatusCode = NULL;\r | |
584 | \r | |
39de741e MK |
585 | url = makeUrlForService (service, uri);\r |
586 | if (!url) {\r | |
587 | return NULL;\r | |
4751a48a AC |
588 | }\r |
589 | \r | |
39de741e | 590 | DEBUG ((DEBUG_INFO, "libredfish: patchUriFromService(): %a\n", url));\r |
4751a48a AC |
591 | \r |
592 | //\r | |
593 | // Step 1: Create HTTP request message with 4 headers:\r | |
594 | //\r | |
595 | HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 9 : 8);\r | |
596 | if (HttpIoHeader == NULL) {\r | |
597 | ret = NULL;\r | |
598 | goto ON_EXIT;\r | |
599 | }\r | |
600 | \r | |
39de741e | 601 | if (service->sessionToken) {\r |
4751a48a AC |
602 | Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);\r |
603 | ASSERT_EFI_ERROR (Status);\r | |
604 | } else if (service->basicAuthStr) {\r | |
605 | Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);\r | |
606 | ASSERT_EFI_ERROR (Status);\r | |
607 | }\r | |
608 | \r | |
609 | Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);\r | |
610 | ASSERT_EFI_ERROR (Status);\r | |
611 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");\r | |
612 | ASSERT_EFI_ERROR (Status);\r | |
613 | Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");\r | |
614 | ASSERT_EFI_ERROR (Status);\r | |
615 | Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");\r | |
616 | ASSERT_EFI_ERROR (Status);\r | |
617 | Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");\r | |
618 | ASSERT_EFI_ERROR (Status);\r | |
619 | \r | |
39de741e | 620 | AsciiSPrint (\r |
4751a48a AC |
621 | ContentLengthStr,\r |
622 | sizeof (ContentLengthStr),\r | |
623 | "%lu",\r | |
39de741e | 624 | (UINT64)strlen (content)\r |
4751a48a AC |
625 | );\r |
626 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr);\r | |
627 | ASSERT_EFI_ERROR (Status);\r | |
628 | Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");\r | |
629 | ASSERT_EFI_ERROR (Status);\r | |
630 | \r | |
631 | //\r | |
632 | // Step 2: build the rest of HTTP request info.\r | |
633 | //\r | |
634 | RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));\r | |
635 | if (RequestData == NULL) {\r | |
636 | ret = NULL;\r | |
637 | goto ON_EXIT;\r | |
638 | }\r | |
639 | \r | |
640 | RequestData->Method = HttpMethodPatch;\r | |
39de741e | 641 | RequestData->Url = C8ToC16 (url);\r |
4751a48a AC |
642 | \r |
643 | //\r | |
644 | // Step 3: fill in EFI_HTTP_MESSAGE\r | |
645 | //\r | |
646 | RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));\r | |
647 | if (RequestMsg == NULL) {\r | |
648 | ret = NULL;\r | |
649 | goto ON_EXIT;\r | |
650 | }\r | |
651 | \r | |
39de741e MK |
652 | EncodedContent = (CHAR8 *)content;\r |
653 | EncodedContentLen = strlen (content);\r | |
4751a48a AC |
654 | //\r |
655 | // We currently only support gzip Content-Encoding.\r | |
656 | //\r | |
657 | Status = EncodeRequestContent ((CHAR8 *)HTTP_CONTENT_ENCODING_GZIP, (CHAR8 *)content, (VOID **)&EncodedContent, &EncodedContentLen);\r | |
658 | if (Status == EFI_INVALID_PARAMETER) {\r | |
39de741e | 659 | DEBUG ((DEBUG_ERROR, "%a: Error to encode content.\n", __FUNCTION__));\r |
4751a48a AC |
660 | ret = NULL;\r |
661 | goto ON_EXIT;\r | |
662 | } else if (Status == EFI_UNSUPPORTED) {\r | |
39de741e | 663 | DEBUG ((DEBUG_INFO, "No content coding for %a! Use raw data instead.\n", HTTP_CONTENT_ENCODING_GZIP));\r |
4751a48a AC |
664 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CONTENT_ENCODING_IDENTITY);\r |
665 | ASSERT_EFI_ERROR (Status);\r | |
666 | } else {\r | |
667 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CONTENT_ENCODING_GZIP);\r | |
668 | ASSERT_EFI_ERROR (Status);\r | |
669 | }\r | |
670 | \r | |
671 | RequestMsg->Data.Request = RequestData;\r | |
672 | RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;\r | |
673 | RequestMsg->Headers = HttpIoHeader->Headers;\r | |
674 | RequestMsg->BodyLength = EncodedContentLen;\r | |
39de741e | 675 | RequestMsg->Body = (VOID *)EncodedContent;\r |
4751a48a AC |
676 | \r |
677 | ZeroMem (&ResponseMsg, sizeof (ResponseMsg));\r | |
678 | \r | |
679 | //\r | |
680 | // Step 4: call RESTEx to get response from REST service.\r | |
681 | //\r | |
682 | Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);\r | |
683 | if (EFI_ERROR (Status)) {\r | |
684 | ret = NULL;\r | |
685 | goto ON_EXIT;\r | |
686 | }\r | |
687 | \r | |
688 | //\r | |
689 | // Step 5: Return the HTTP StatusCode and Body message.\r | |
690 | //\r | |
691 | if (ResponseMsg.Data.Response != NULL) {\r | |
692 | *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));\r | |
693 | if (*StatusCode == NULL) {\r | |
694 | ret = NULL;\r | |
695 | goto ON_EXIT;\r | |
696 | }\r | |
697 | \r | |
698 | //\r | |
699 | // The caller shall take the responsibility to free the buffer.\r | |
700 | //\r | |
701 | **StatusCode = ResponseMsg.Data.Response->StatusCode;\r | |
702 | }\r | |
703 | \r | |
704 | if (EncodedContent != content) {\r | |
705 | FreePool (EncodedContent);\r | |
706 | }\r | |
707 | \r | |
39de741e | 708 | if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {\r |
4751a48a AC |
709 | ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);\r |
710 | } else {\r | |
711 | //\r | |
712 | // There is no message body returned from server.\r | |
713 | //\r | |
714 | ret = NULL;\r | |
715 | }\r | |
716 | \r | |
717 | ON_EXIT:\r | |
718 | if (url != NULL) {\r | |
719 | free (url);\r | |
720 | }\r | |
721 | \r | |
722 | if (HttpIoHeader != NULL) {\r | |
723 | HttpIoFreeHeader (HttpIoHeader);\r | |
724 | }\r | |
725 | \r | |
726 | if (RequestData != NULL) {\r | |
727 | RestConfigFreeHttpRequestData (RequestData);\r | |
728 | }\r | |
729 | \r | |
730 | if (RequestMsg != NULL) {\r | |
731 | FreePool (RequestMsg);\r | |
732 | }\r | |
733 | \r | |
734 | RestConfigFreeHttpMessage (&ResponseMsg, FALSE);\r | |
735 | \r | |
736 | return ret;\r | |
737 | }\r | |
738 | \r | |
39de741e MK |
739 | json_t *\r |
740 | postUriFromService (\r | |
741 | redfishService *service,\r | |
742 | const char *uri,\r | |
743 | const char *content,\r | |
744 | size_t contentLength,\r | |
745 | const char *contentType,\r | |
746 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
747 | )\r | |
4751a48a | 748 | {\r |
39de741e MK |
749 | char *url = NULL;\r |
750 | json_t *ret;\r | |
751 | HTTP_IO_HEADER *HttpIoHeader = NULL;\r | |
752 | EFI_STATUS Status;\r | |
753 | EFI_HTTP_REQUEST_DATA *RequestData = NULL;\r | |
754 | EFI_HTTP_MESSAGE *RequestMsg = NULL;\r | |
755 | EFI_HTTP_MESSAGE ResponseMsg;\r | |
756 | CHAR8 ContentLengthStr[80];\r | |
757 | EFI_HTTP_HEADER *HttpHeader = NULL;\r | |
4751a48a AC |
758 | \r |
759 | ret = NULL;\r | |
760 | \r | |
39de741e MK |
761 | if ((service == NULL) || (uri == NULL) || (content == NULL) || (StatusCode == NULL)) {\r |
762 | return NULL;\r | |
4751a48a AC |
763 | }\r |
764 | \r | |
765 | *StatusCode = NULL;\r | |
766 | \r | |
39de741e MK |
767 | url = makeUrlForService (service, uri);\r |
768 | if (!url) {\r | |
769 | return NULL;\r | |
4751a48a AC |
770 | }\r |
771 | \r | |
39de741e | 772 | DEBUG ((DEBUG_INFO, "libredfish: postUriFromService(): %a\n", url));\r |
4751a48a | 773 | \r |
39de741e MK |
774 | if (contentLength == 0) {\r |
775 | contentLength = strlen (content);\r | |
4751a48a AC |
776 | }\r |
777 | \r | |
778 | //\r | |
779 | // Step 1: Create HTTP request message with 4 headers:\r | |
780 | //\r | |
781 | HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 8 : 7);\r | |
782 | if (HttpIoHeader == NULL) {\r | |
783 | goto ON_EXIT;\r | |
784 | }\r | |
785 | \r | |
39de741e | 786 | if (service->sessionToken) {\r |
4751a48a AC |
787 | Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);\r |
788 | ASSERT_EFI_ERROR (Status);\r | |
789 | } else if (service->basicAuthStr) {\r | |
790 | Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);\r | |
791 | ASSERT_EFI_ERROR (Status);\r | |
792 | }\r | |
793 | \r | |
39de741e | 794 | if (contentType == NULL) {\r |
4751a48a AC |
795 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");\r |
796 | ASSERT_EFI_ERROR (Status);\r | |
797 | } else {\r | |
39de741e | 798 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8 *)contentType);\r |
4751a48a AC |
799 | ASSERT_EFI_ERROR (Status);\r |
800 | }\r | |
39de741e | 801 | \r |
4751a48a AC |
802 | Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);\r |
803 | ASSERT_EFI_ERROR (Status);\r | |
804 | Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");\r | |
805 | ASSERT_EFI_ERROR (Status);\r | |
806 | Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");\r | |
807 | ASSERT_EFI_ERROR (Status);\r | |
808 | Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");\r | |
809 | ASSERT_EFI_ERROR (Status);\r | |
39de741e | 810 | AsciiSPrint (\r |
4751a48a AC |
811 | ContentLengthStr,\r |
812 | sizeof (ContentLengthStr),\r | |
813 | "%lu",\r | |
39de741e | 814 | (UINT64)contentLength\r |
4751a48a AC |
815 | );\r |
816 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr);\r | |
817 | ASSERT_EFI_ERROR (Status);\r | |
818 | Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");\r | |
819 | ASSERT_EFI_ERROR (Status);\r | |
820 | \r | |
821 | //\r | |
822 | // Step 2: build the rest of HTTP request info.\r | |
823 | //\r | |
824 | RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));\r | |
825 | if (RequestData == NULL) {\r | |
826 | goto ON_EXIT;\r | |
827 | }\r | |
828 | \r | |
829 | RequestData->Method = HttpMethodPost;\r | |
39de741e | 830 | RequestData->Url = C8ToC16 (url);\r |
4751a48a AC |
831 | \r |
832 | //\r | |
833 | // Step 3: fill in EFI_HTTP_MESSAGE\r | |
834 | //\r | |
835 | RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));\r | |
836 | if (RequestMsg == NULL) {\r | |
837 | goto ON_EXIT;\r | |
838 | }\r | |
839 | \r | |
840 | RequestMsg->Data.Request = RequestData;\r | |
841 | RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;\r | |
842 | RequestMsg->Headers = HttpIoHeader->Headers;\r | |
843 | RequestMsg->BodyLength = contentLength;\r | |
39de741e | 844 | RequestMsg->Body = (VOID *)content;\r |
4751a48a AC |
845 | \r |
846 | ZeroMem (&ResponseMsg, sizeof (ResponseMsg));\r | |
847 | \r | |
848 | //\r | |
849 | // Step 4: call RESTEx to get response from REST service.\r | |
850 | //\r | |
851 | Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);\r | |
852 | if (EFI_ERROR (Status)) {\r | |
853 | goto ON_EXIT;\r | |
854 | }\r | |
855 | \r | |
856 | //\r | |
857 | // Step 5: Return the HTTP StatusCode and Body message.\r | |
858 | //\r | |
859 | if (ResponseMsg.Data.Response != NULL) {\r | |
860 | *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));\r | |
861 | if (*StatusCode == NULL) {\r | |
862 | goto ON_EXIT;\r | |
863 | }\r | |
864 | \r | |
865 | //\r | |
866 | // The caller shall take the responsibility to free the buffer.\r | |
867 | //\r | |
868 | **StatusCode = ResponseMsg.Data.Response->StatusCode;\r | |
869 | }\r | |
870 | \r | |
39de741e | 871 | if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {\r |
4751a48a AC |
872 | ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);\r |
873 | }\r | |
874 | \r | |
875 | //\r | |
876 | // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP StatusCode is correct.\r | |
877 | //\r | |
39de741e MK |
878 | if ((ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK) ||\r |
879 | (ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_204_NO_CONTENT))\r | |
880 | {\r | |
4751a48a AC |
881 | HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, "X-Auth-Token");\r |
882 | if (HttpHeader != NULL) {\r | |
39de741e MK |
883 | if (service->sessionToken) {\r |
884 | free (service->sessionToken);\r | |
4751a48a | 885 | }\r |
39de741e | 886 | \r |
4751a48a AC |
887 | service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader->FieldValue), HttpHeader->FieldValue);\r |
888 | }\r | |
889 | \r | |
890 | /*\r | |
891 | //\r | |
892 | // Below opeation seems to be unnecessary.\r | |
893 | // 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\r | |
894 | // parameter of getUriFromService () directly.\r | |
895 | //\r | |
896 | HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, "Location");\r | |
897 | if (HttpHeader != NULL) {\r | |
898 | ret = getUriFromService(service, HttpHeader->FieldValue);\r | |
899 | goto ON_EXIT;\r | |
900 | }\r | |
901 | */\r | |
902 | }\r | |
903 | \r | |
904 | ON_EXIT:\r | |
905 | if (url != NULL) {\r | |
906 | free (url);\r | |
907 | }\r | |
908 | \r | |
909 | if (HttpIoHeader != NULL) {\r | |
910 | HttpIoFreeHeader (HttpIoHeader);\r | |
911 | }\r | |
912 | \r | |
913 | if (RequestData != NULL) {\r | |
914 | RestConfigFreeHttpRequestData (RequestData);\r | |
915 | }\r | |
916 | \r | |
917 | if (RequestMsg != NULL) {\r | |
918 | FreePool (RequestMsg);\r | |
919 | }\r | |
920 | \r | |
921 | RestConfigFreeHttpMessage (&ResponseMsg, FALSE);\r | |
922 | \r | |
923 | return ret;\r | |
924 | }\r | |
925 | \r | |
39de741e | 926 | json_t *\r |
f2bf043a | 927 | deleteUriFromServiceEx (\r |
39de741e MK |
928 | redfishService *service,\r |
929 | const char *uri,\r | |
f2bf043a | 930 | const char *content,\r |
39de741e MK |
931 | EFI_HTTP_STATUS_CODE **StatusCode\r |
932 | )\r | |
4751a48a | 933 | {\r |
39de741e MK |
934 | char *url;\r |
935 | json_t *ret;\r | |
936 | HTTP_IO_HEADER *HttpIoHeader = NULL;\r | |
937 | EFI_STATUS Status;\r | |
938 | EFI_HTTP_REQUEST_DATA *RequestData = NULL;\r | |
939 | EFI_HTTP_MESSAGE *RequestMsg = NULL;\r | |
940 | EFI_HTTP_MESSAGE ResponseMsg;\r | |
f2bf043a AC |
941 | CHAR8 ContentLengthStr[80];\r |
942 | size_t contentLength;\r | |
4751a48a AC |
943 | \r |
944 | ret = NULL;\r | |
945 | \r | |
39de741e MK |
946 | if ((service == NULL) || (uri == NULL) || (StatusCode == NULL)) {\r |
947 | return NULL;\r | |
4751a48a AC |
948 | }\r |
949 | \r | |
950 | *StatusCode = NULL;\r | |
951 | \r | |
39de741e MK |
952 | url = makeUrlForService (service, uri);\r |
953 | if (!url) {\r | |
954 | return NULL;\r | |
4751a48a AC |
955 | }\r |
956 | \r | |
39de741e | 957 | DEBUG ((DEBUG_INFO, "libredfish: deleteUriFromService(): %a\n", url));\r |
4751a48a AC |
958 | \r |
959 | //\r | |
960 | // Step 1: Create HTTP request message with 4 headers:\r | |
961 | //\r | |
f2bf043a | 962 | HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 8 : 7);\r |
4751a48a AC |
963 | if (HttpIoHeader == NULL) {\r |
964 | ret = NULL;\r | |
965 | goto ON_EXIT;\r | |
966 | }\r | |
967 | \r | |
39de741e | 968 | if (service->sessionToken) {\r |
4751a48a AC |
969 | Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);\r |
970 | ASSERT_EFI_ERROR (Status);\r | |
971 | } else if (service->basicAuthStr) {\r | |
972 | Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);\r | |
973 | ASSERT_EFI_ERROR (Status);\r | |
974 | }\r | |
39de741e | 975 | \r |
4751a48a AC |
976 | Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);\r |
977 | ASSERT_EFI_ERROR (Status);\r | |
978 | Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");\r | |
979 | ASSERT_EFI_ERROR (Status);\r | |
980 | Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");\r | |
981 | ASSERT_EFI_ERROR (Status);\r | |
982 | Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");\r | |
983 | ASSERT_EFI_ERROR (Status);\r | |
984 | \r | |
f2bf043a AC |
985 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");\r |
986 | ASSERT_EFI_ERROR (Status);\r | |
987 | \r | |
988 | if (content != NULL) {\r | |
989 | contentLength = strlen (content);\r | |
990 | AsciiSPrint (\r | |
991 | ContentLengthStr,\r | |
992 | sizeof (ContentLengthStr),\r | |
993 | "%lu",\r | |
994 | (UINT64)contentLength\r | |
995 | );\r | |
996 | Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr);\r | |
997 | ASSERT_EFI_ERROR (Status);\r | |
998 | Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");\r | |
999 | ASSERT_EFI_ERROR (Status);\r | |
1000 | }\r | |
1001 | \r | |
4751a48a AC |
1002 | //\r |
1003 | // Step 2: build the rest of HTTP request info.\r | |
1004 | //\r | |
1005 | RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));\r | |
1006 | if (RequestData == NULL) {\r | |
1007 | ret = NULL;\r | |
1008 | goto ON_EXIT;\r | |
1009 | }\r | |
1010 | \r | |
1011 | RequestData->Method = HttpMethodDelete;\r | |
39de741e | 1012 | RequestData->Url = C8ToC16 (url);\r |
4751a48a AC |
1013 | \r |
1014 | //\r | |
1015 | // Step 3: fill in EFI_HTTP_MESSAGE\r | |
1016 | //\r | |
1017 | RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));\r | |
1018 | if (RequestMsg == NULL) {\r | |
1019 | ret = NULL;\r | |
1020 | goto ON_EXIT;\r | |
1021 | }\r | |
1022 | \r | |
1023 | RequestMsg->Data.Request = RequestData;\r | |
1024 | RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;\r | |
1025 | RequestMsg->Headers = HttpIoHeader->Headers;\r | |
1026 | \r | |
f2bf043a AC |
1027 | if (content != NULL) {\r |
1028 | RequestMsg->BodyLength = contentLength;\r | |
1029 | RequestMsg->Body = (VOID *)content;\r | |
1030 | }\r | |
1031 | \r | |
4751a48a AC |
1032 | ZeroMem (&ResponseMsg, sizeof (ResponseMsg));\r |
1033 | \r | |
1034 | //\r | |
1035 | // Step 4: call RESTEx to get response from REST service.\r | |
1036 | //\r | |
1037 | Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);\r | |
1038 | if (EFI_ERROR (Status)) {\r | |
1039 | ret = NULL;\r | |
1040 | goto ON_EXIT;\r | |
1041 | }\r | |
1042 | \r | |
1043 | //\r | |
1044 | // Step 5: Return the HTTP StatusCode and Body message.\r | |
1045 | //\r | |
1046 | if (ResponseMsg.Data.Response != NULL) {\r | |
1047 | *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));\r | |
1048 | if (*StatusCode == NULL) {\r | |
1049 | ret = NULL;\r | |
1050 | goto ON_EXIT;\r | |
1051 | }\r | |
1052 | \r | |
1053 | //\r | |
1054 | // The caller shall take the responsibility to free the buffer.\r | |
1055 | //\r | |
1056 | **StatusCode = ResponseMsg.Data.Response->StatusCode;\r | |
1057 | }\r | |
1058 | \r | |
39de741e | 1059 | if ((ResponseMsg.BodyLength != 0) && (ResponseMsg.Body != NULL)) {\r |
4751a48a AC |
1060 | ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);\r |
1061 | }\r | |
1062 | \r | |
1063 | ON_EXIT:\r | |
1064 | if (url != NULL) {\r | |
1065 | free (url);\r | |
1066 | }\r | |
1067 | \r | |
1068 | if (HttpIoHeader != NULL) {\r | |
1069 | HttpIoFreeHeader (HttpIoHeader);\r | |
1070 | }\r | |
1071 | \r | |
1072 | if (RequestData != NULL) {\r | |
1073 | RestConfigFreeHttpRequestData (RequestData);\r | |
1074 | }\r | |
1075 | \r | |
1076 | if (RequestMsg != NULL) {\r | |
1077 | FreePool (RequestMsg);\r | |
1078 | }\r | |
1079 | \r | |
1080 | RestConfigFreeHttpMessage (&ResponseMsg, FALSE);\r | |
1081 | \r | |
1082 | return ret;\r | |
1083 | }\r | |
1084 | \r | |
f2bf043a AC |
1085 | json_t *\r |
1086 | deleteUriFromService (\r | |
1087 | redfishService *service,\r | |
1088 | const char *uri,\r | |
1089 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
1090 | )\r | |
1091 | {\r | |
1092 | return deleteUriFromServiceEx (service, uri, NULL, StatusCode);\r | |
1093 | }\r | |
1094 | \r | |
39de741e MK |
1095 | redfishPayload *\r |
1096 | getRedfishServiceRoot (\r | |
1097 | redfishService *service,\r | |
1098 | const char *version,\r | |
1099 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
1100 | )\r | |
4751a48a | 1101 | {\r |
39de741e MK |
1102 | json_t *value;\r |
1103 | json_t *versionNode;\r | |
1104 | const char *verUrl;\r | |
4751a48a | 1105 | \r |
39de741e MK |
1106 | if (version == NULL) {\r |
1107 | versionNode = json_object_get (service->versions, "v1");\r | |
1108 | } else {\r | |
1109 | versionNode = json_object_get (service->versions, version);\r | |
1110 | }\r | |
1111 | \r | |
1112 | if (versionNode == NULL) {\r | |
1113 | return NULL;\r | |
1114 | }\r | |
1115 | \r | |
1116 | verUrl = json_string_value (versionNode);\r | |
1117 | if (verUrl == NULL) {\r | |
1118 | return NULL;\r | |
1119 | }\r | |
1120 | \r | |
1121 | value = getUriFromService (service, verUrl, StatusCode);\r | |
1122 | if (value == NULL) {\r | |
1123 | if ((service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC) == 0) {\r | |
1124 | json_decref (versionNode);\r | |
4751a48a | 1125 | }\r |
39de741e MK |
1126 | \r |
1127 | return NULL;\r | |
1128 | }\r | |
1129 | \r | |
1130 | return createRedfishPayload (value, service);\r | |
4751a48a AC |
1131 | }\r |
1132 | \r | |
39de741e MK |
1133 | redfishPayload *\r |
1134 | getPayloadByPath (\r | |
1135 | redfishService *service,\r | |
1136 | const char *path,\r | |
1137 | EFI_HTTP_STATUS_CODE **StatusCode\r | |
1138 | )\r | |
4751a48a | 1139 | {\r |
39de741e MK |
1140 | redPathNode *redpath;\r |
1141 | redfishPayload *root;\r | |
1142 | redfishPayload *ret;\r | |
4751a48a | 1143 | \r |
39de741e MK |
1144 | if (!service || !path || (StatusCode == NULL)) {\r |
1145 | return NULL;\r | |
1146 | }\r | |
4751a48a | 1147 | \r |
39de741e | 1148 | *StatusCode = NULL;\r |
4751a48a | 1149 | \r |
39de741e MK |
1150 | redpath = parseRedPath (path);\r |
1151 | if (!redpath) {\r | |
1152 | return NULL;\r | |
1153 | }\r | |
4751a48a | 1154 | \r |
39de741e MK |
1155 | if (!redpath->isRoot) {\r |
1156 | cleanupRedPath (redpath);\r | |
1157 | return NULL;\r | |
1158 | }\r | |
4751a48a | 1159 | \r |
39de741e MK |
1160 | root = getRedfishServiceRoot (service, redpath->version, StatusCode);\r |
1161 | if ((*StatusCode == NULL) || (**StatusCode < HTTP_STATUS_200_OK) || (**StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)) {\r | |
1162 | cleanupRedPath (redpath);\r | |
1163 | return root;\r | |
1164 | }\r | |
4751a48a | 1165 | \r |
39de741e MK |
1166 | if (redpath->next == NULL) {\r |
1167 | cleanupRedPath (redpath);\r | |
1168 | return root;\r | |
1169 | }\r | |
1170 | \r | |
1171 | FreePool (*StatusCode);\r | |
1172 | *StatusCode = NULL;\r | |
1173 | \r | |
1174 | ret = getPayloadForPath (root, redpath->next, StatusCode);\r | |
1175 | if ((*StatusCode == NULL) && (ret != NULL)) {\r | |
1176 | //\r | |
1177 | // In such a case, the Redfish resource is parsed from the input payload (root) directly.\r | |
1178 | // So, we still return HTTP_STATUS_200_OK.\r | |
1179 | //\r | |
1180 | *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));\r | |
1181 | if (*StatusCode == NULL) {\r | |
1182 | ret = NULL;\r | |
1183 | } else {\r | |
1184 | **StatusCode = HTTP_STATUS_200_OK;\r | |
4751a48a | 1185 | }\r |
39de741e MK |
1186 | }\r |
1187 | \r | |
1188 | cleanupPayload (root);\r | |
1189 | cleanupRedPath (redpath);\r | |
1190 | return ret;\r | |
4751a48a AC |
1191 | }\r |
1192 | \r | |
39de741e MK |
1193 | void\r |
1194 | cleanupServiceEnumerator (\r | |
1195 | redfishService *service\r | |
1196 | )\r | |
4751a48a | 1197 | {\r |
39de741e MK |
1198 | if (!service) {\r |
1199 | return;\r | |
4751a48a | 1200 | }\r |
39de741e MK |
1201 | \r |
1202 | free (service->host);\r | |
1203 | json_decref (service->versions);\r | |
1204 | if (service->sessionToken != NULL) {\r | |
1205 | ZeroMem (service->sessionToken, (UINTN)strlen (service->sessionToken));\r | |
1206 | FreePool (service->sessionToken);\r | |
4751a48a | 1207 | }\r |
39de741e | 1208 | \r |
4751a48a | 1209 | if (service->basicAuthStr != NULL) {\r |
39de741e MK |
1210 | ZeroMem (service->basicAuthStr, (UINTN)strlen (service->basicAuthStr));\r |
1211 | FreePool (service->basicAuthStr);\r | |
4751a48a | 1212 | }\r |
39de741e MK |
1213 | \r |
1214 | free (service);\r | |
4751a48a AC |
1215 | }\r |
1216 | \r | |
39de741e MK |
1217 | static int\r |
1218 | initRest (\r | |
1219 | redfishService *service,\r | |
1220 | void *restProtocol\r | |
1221 | )\r | |
4751a48a AC |
1222 | {\r |
1223 | service->RestEx = restProtocol;\r | |
1224 | return 0;\r | |
1225 | }\r | |
1226 | \r | |
39de741e MK |
1227 | static redfishService *\r |
1228 | createServiceEnumeratorNoAuth (\r | |
1229 | const char *host,\r | |
1230 | const char *rootUri,\r | |
1231 | bool enumerate,\r | |
1232 | unsigned int flags,\r | |
1233 | void *restProtocol\r | |
1234 | )\r | |
4751a48a | 1235 | {\r |
39de741e MK |
1236 | redfishService *ret;\r |
1237 | char *HostStart;\r | |
1238 | \r | |
1239 | ret = (redfishService *)calloc (1, sizeof (redfishService));\r | |
1240 | ZeroMem (ret, sizeof (redfishService));\r | |
1241 | if (initRest (ret, restProtocol) != 0) {\r | |
1242 | free (ret);\r | |
1243 | return NULL;\r | |
1244 | }\r | |
1245 | \r | |
1246 | ret->host = AllocateCopyPool (AsciiStrSize (host), host);\r | |
1247 | ret->flags = flags;\r | |
1248 | if (enumerate) {\r | |
1249 | ret->versions = getVersions (ret, rootUri);\r | |
1250 | }\r | |
4751a48a | 1251 | \r |
39de741e MK |
1252 | HostStart = strstr (ret->host, "//");\r |
1253 | if ((HostStart != NULL) && (*(HostStart + 2) != '\0')) {\r | |
1254 | ret->HostHeaderValue = HostStart + 2;\r | |
1255 | }\r | |
1256 | \r | |
1257 | return ret;\r | |
4751a48a AC |
1258 | }\r |
1259 | \r | |
1260 | EFI_STATUS\r | |
1261 | createBasicAuthStr (\r | |
39de741e MK |
1262 | IN redfishService *service,\r |
1263 | IN CONST CHAR8 *UserId,\r | |
1264 | IN CONST CHAR8 *Password\r | |
4751a48a AC |
1265 | )\r |
1266 | {\r | |
39de741e MK |
1267 | EFI_STATUS Status;\r |
1268 | CHAR8 *RawAuthValue;\r | |
1269 | UINTN RawAuthBufSize;\r | |
1270 | CHAR8 *EnAuthValue;\r | |
1271 | UINTN EnAuthValueSize;\r | |
1272 | CHAR8 *BasicWithEnAuthValue;\r | |
1273 | UINTN BasicBufSize;\r | |
4751a48a AC |
1274 | \r |
1275 | EnAuthValue = NULL;\r | |
1276 | EnAuthValueSize = 0;\r | |
1277 | \r | |
1278 | RawAuthBufSize = AsciiStrLen (UserId) + AsciiStrLen (Password) + 2;\r | |
39de741e | 1279 | RawAuthValue = AllocatePool (RawAuthBufSize);\r |
4751a48a AC |
1280 | if (RawAuthValue == NULL) {\r |
1281 | return EFI_OUT_OF_RESOURCES;\r | |
1282 | }\r | |
1283 | \r | |
1284 | //\r | |
1285 | // Build raw AuthValue (UserId:Password).\r | |
1286 | //\r | |
1287 | AsciiSPrint (\r | |
1288 | RawAuthValue,\r | |
1289 | RawAuthBufSize,\r | |
1290 | "%a:%a",\r | |
1291 | UserId,\r | |
1292 | Password\r | |
1293 | );\r | |
1294 | \r | |
1295 | //\r | |
1296 | // Encoding RawAuthValue into Base64 format.\r | |
1297 | //\r | |
1298 | Status = Base64Encode (\r | |
39de741e | 1299 | (CONST UINT8 *)RawAuthValue,\r |
4751a48a AC |
1300 | AsciiStrLen (RawAuthValue),\r |
1301 | EnAuthValue,\r | |
1302 | &EnAuthValueSize\r | |
1303 | );\r | |
1304 | if (Status == EFI_BUFFER_TOO_SMALL) {\r | |
39de741e | 1305 | EnAuthValue = (CHAR8 *)AllocateZeroPool (EnAuthValueSize);\r |
4751a48a AC |
1306 | if (EnAuthValue == NULL) {\r |
1307 | Status = EFI_OUT_OF_RESOURCES;\r | |
1308 | return Status;\r | |
1309 | }\r | |
1310 | \r | |
1311 | Status = Base64Encode (\r | |
39de741e | 1312 | (CONST UINT8 *)RawAuthValue,\r |
4751a48a AC |
1313 | AsciiStrLen (RawAuthValue),\r |
1314 | EnAuthValue,\r | |
1315 | &EnAuthValueSize\r | |
1316 | );\r | |
1317 | }\r | |
1318 | \r | |
1319 | if (EFI_ERROR (Status)) {\r | |
1320 | goto Exit;\r | |
1321 | }\r | |
1322 | \r | |
39de741e | 1323 | BasicBufSize = AsciiStrLen ("Basic ") + AsciiStrLen (EnAuthValue) + 2;\r |
4751a48a AC |
1324 | BasicWithEnAuthValue = AllocatePool (BasicBufSize);\r |
1325 | if (BasicWithEnAuthValue == NULL) {\r | |
1326 | Status = EFI_OUT_OF_RESOURCES;\r | |
1327 | goto Exit;\r | |
1328 | }\r | |
1329 | \r | |
1330 | //\r | |
1331 | // Build encoded EnAuthValue with Basic (Basic EnAuthValue).\r | |
1332 | //\r | |
1333 | AsciiSPrint (\r | |
1334 | BasicWithEnAuthValue,\r | |
1335 | BasicBufSize,\r | |
1336 | "%a %a",\r | |
1337 | "Basic",\r | |
1338 | EnAuthValue\r | |
1339 | );\r | |
1340 | \r | |
1341 | service->basicAuthStr = BasicWithEnAuthValue;\r | |
1342 | \r | |
1343 | Exit:\r | |
1344 | if (RawAuthValue != NULL) {\r | |
1345 | ZeroMem (RawAuthValue, RawAuthBufSize);\r | |
1346 | FreePool (RawAuthValue);\r | |
1347 | }\r | |
1348 | \r | |
1349 | if (EnAuthValue != NULL) {\r | |
1350 | ZeroMem (EnAuthValue, EnAuthValueSize);\r | |
1351 | FreePool (EnAuthValue);\r | |
1352 | }\r | |
1353 | \r | |
1354 | return Status;\r | |
1355 | }\r | |
1356 | \r | |
39de741e MK |
1357 | static redfishService *\r |
1358 | createServiceEnumeratorBasicAuth (\r | |
1359 | const char *host,\r | |
1360 | const char *rootUri,\r | |
1361 | const char *username,\r | |
1362 | const char *password,\r | |
1363 | unsigned int flags,\r | |
1364 | void *restProtocol\r | |
1365 | )\r | |
4751a48a | 1366 | {\r |
39de741e MK |
1367 | redfishService *ret;\r |
1368 | EFI_STATUS Status;\r | |
4751a48a | 1369 | \r |
39de741e | 1370 | ret = createServiceEnumeratorNoAuth (host, rootUri, false, flags, restProtocol);\r |
4751a48a | 1371 | \r |
39de741e MK |
1372 | // add basic auth str\r |
1373 | Status = createBasicAuthStr (ret, username, password);\r | |
1374 | if (EFI_ERROR (Status)) {\r | |
1375 | cleanupServiceEnumerator (ret);\r | |
1376 | return NULL;\r | |
1377 | }\r | |
4751a48a | 1378 | \r |
39de741e MK |
1379 | ret->versions = getVersions (ret, rootUri);\r |
1380 | return ret;\r | |
4751a48a AC |
1381 | }\r |
1382 | \r | |
39de741e MK |
1383 | static redfishService *\r |
1384 | createServiceEnumeratorSessionAuth (\r | |
1385 | const char *host,\r | |
1386 | const char *rootUri,\r | |
1387 | const char *username,\r | |
1388 | const char *password,\r | |
1389 | unsigned int flags,\r | |
1390 | void *restProtocol\r | |
1391 | )\r | |
4751a48a | 1392 | {\r |
39de741e MK |
1393 | redfishService *ret;\r |
1394 | redfishPayload *payload;\r | |
1395 | redfishPayload *links;\r | |
1396 | json_t *sessionPayload;\r | |
1397 | json_t *session;\r | |
1398 | json_t *odataId;\r | |
1399 | const char *uri;\r | |
1400 | json_t *post;\r | |
1401 | char *content;\r | |
1402 | EFI_HTTP_STATUS_CODE *StatusCode;\r | |
1403 | \r | |
1404 | content = NULL;\r | |
1405 | StatusCode = NULL;\r | |
1406 | \r | |
1407 | ret = createServiceEnumeratorNoAuth (host, rootUri, true, flags, restProtocol);\r | |
1408 | if (ret == NULL) {\r | |
1409 | return NULL;\r | |
1410 | }\r | |
4751a48a | 1411 | \r |
39de741e MK |
1412 | payload = getRedfishServiceRoot (ret, NULL, &StatusCode);\r |
1413 | if ((StatusCode == NULL) || (*StatusCode < HTTP_STATUS_200_OK) || (*StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)) {\r | |
4751a48a AC |
1414 | if (StatusCode != NULL) {\r |
1415 | FreePool (StatusCode);\r | |
4751a48a AC |
1416 | }\r |
1417 | \r | |
39de741e MK |
1418 | if (payload != NULL) {\r |
1419 | cleanupPayload (payload);\r | |
4751a48a AC |
1420 | }\r |
1421 | \r | |
39de741e MK |
1422 | cleanupServiceEnumerator (ret);\r |
1423 | return NULL;\r | |
1424 | }\r | |
1425 | \r | |
1426 | if (StatusCode != NULL) {\r | |
1427 | FreePool (StatusCode);\r | |
1428 | StatusCode = NULL;\r | |
1429 | }\r | |
1430 | \r | |
1431 | links = getPayloadByNodeName (payload, "Links", &StatusCode);\r | |
1432 | cleanupPayload (payload);\r | |
1433 | if (links == NULL) {\r | |
1434 | cleanupServiceEnumerator (ret);\r | |
1435 | return NULL;\r | |
1436 | }\r | |
4751a48a | 1437 | \r |
39de741e MK |
1438 | session = json_object_get (links->json, "Sessions");\r |
1439 | if (session == NULL) {\r | |
1440 | cleanupPayload (links);\r | |
1441 | cleanupServiceEnumerator (ret);\r | |
1442 | return NULL;\r | |
1443 | }\r | |
4751a48a | 1444 | \r |
39de741e MK |
1445 | odataId = json_object_get (session, "@odata.id");\r |
1446 | if (odataId == NULL) {\r | |
1447 | cleanupPayload (links);\r | |
1448 | cleanupServiceEnumerator (ret);\r | |
1449 | return NULL;\r | |
1450 | }\r | |
1451 | \r | |
1452 | uri = json_string_value (odataId);\r | |
1453 | post = json_object ();\r | |
1454 | addStringToJsonObject (post, "UserName", username);\r | |
1455 | addStringToJsonObject (post, "Password", password);\r | |
1456 | content = json_dumps (post, 0);\r | |
1457 | json_decref (post);\r | |
1458 | sessionPayload = postUriFromService (ret, uri, content, 0, NULL, &StatusCode);\r | |
1459 | \r | |
1460 | if (content != NULL) {\r | |
1461 | ZeroMem (content, (UINTN)strlen (content));\r | |
1462 | free (content);\r | |
1463 | }\r | |
1464 | \r | |
1465 | if ((sessionPayload == NULL) || (StatusCode == NULL) || (*StatusCode < HTTP_STATUS_200_OK) || (*StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)) {\r | |
1466 | // Failed to create session!\r | |
4751a48a | 1467 | \r |
39de741e MK |
1468 | cleanupPayload (links);\r |
1469 | cleanupServiceEnumerator (ret);\r | |
4751a48a | 1470 | \r |
39de741e MK |
1471 | if (StatusCode != NULL) {\r |
1472 | FreePool (StatusCode);\r | |
4751a48a | 1473 | }\r |
39de741e MK |
1474 | \r |
1475 | if (sessionPayload != NULL) {\r | |
1476 | json_decref (sessionPayload);\r | |
1477 | }\r | |
1478 | \r | |
1479 | return NULL;\r | |
1480 | }\r | |
1481 | \r | |
1482 | json_decref (sessionPayload);\r | |
1483 | cleanupPayload (links);\r | |
1484 | FreePool (StatusCode);\r | |
1485 | return ret;\r | |
4751a48a AC |
1486 | }\r |
1487 | \r | |
39de741e MK |
1488 | static char *\r |
1489 | makeUrlForService (\r | |
1490 | redfishService *service,\r | |
1491 | const char *uri\r | |
1492 | )\r | |
4751a48a | 1493 | {\r |
39de741e MK |
1494 | char *url;\r |
1495 | \r | |
1496 | if (service->host == NULL) {\r | |
1497 | return NULL;\r | |
1498 | }\r | |
1499 | \r | |
1500 | url = (char *)malloc (strlen (service->host)+strlen (uri)+1);\r | |
1501 | strcpy (url, service->host);\r | |
1502 | strcat (url, uri);\r | |
1503 | return url;\r | |
4751a48a AC |
1504 | }\r |
1505 | \r | |
39de741e MK |
1506 | static json_t *\r |
1507 | getVersions (\r | |
1508 | redfishService *service,\r | |
1509 | const char *rootUri\r | |
1510 | )\r | |
4751a48a | 1511 | {\r |
39de741e MK |
1512 | json_t *ret = NULL;\r |
1513 | EFI_HTTP_STATUS_CODE *StatusCode = NULL;\r | |
4751a48a | 1514 | \r |
39de741e MK |
1515 | if (service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC) {\r |
1516 | service->versions = json_object ();\r | |
1517 | if (service->versions == NULL) {\r | |
1518 | return NULL;\r | |
4751a48a AC |
1519 | }\r |
1520 | \r | |
39de741e MK |
1521 | addStringToJsonObject (service->versions, "v1", "/redfish/v1");\r |
1522 | return service->versions;\r | |
1523 | }\r | |
1524 | \r | |
1525 | if (rootUri != NULL) {\r | |
1526 | ret = getUriFromService (service, rootUri, &StatusCode);\r | |
1527 | } else {\r | |
1528 | ret = getUriFromService (service, "/redfish", &StatusCode);\r | |
1529 | }\r | |
1530 | \r | |
1531 | if ((ret == NULL) || (StatusCode == NULL) || (*StatusCode < HTTP_STATUS_200_OK) || (*StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)) {\r | |
1532 | if (ret != NULL) {\r | |
1533 | json_decref (ret);\r | |
4751a48a AC |
1534 | }\r |
1535 | \r | |
39de741e MK |
1536 | ret = NULL;\r |
1537 | }\r | |
1538 | \r | |
1539 | if (StatusCode != NULL) {\r | |
1540 | FreePool (StatusCode);\r | |
1541 | }\r | |
1542 | \r | |
1543 | return ret;\r | |
4751a48a AC |
1544 | }\r |
1545 | \r | |
39de741e MK |
1546 | static void\r |
1547 | addStringToJsonObject (\r | |
1548 | json_t *object,\r | |
1549 | const char *key,\r | |
1550 | const char *value\r | |
1551 | )\r | |
4751a48a | 1552 | {\r |
39de741e | 1553 | json_t *jValue = json_string (value);\r |
4751a48a | 1554 | \r |
39de741e | 1555 | json_object_set (object, key, jValue);\r |
4751a48a | 1556 | \r |
39de741e | 1557 | json_decref (jValue);\r |
4751a48a | 1558 | }\r |