1 /*
2  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "restapi_service_context.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "rpc/http/caller/http_caller.h"
13 #include "trace.h"
14 
15 /**
16  * A service_context that represents a service instance reached via
17  * a remote REST API
18  */
19 struct restapi_service_context {
20 	struct service_context service_context;
21 	char rpc_call_url[HTTP_CALLER_MAX_URL_LEN];
22 };
23 
24 /* Concrete service_context methods */
25 static rpc_session_handle restapi_service_context_open(void *context, struct rpc_caller **caller);
26 static void restapi_service_context_close(void *context, rpc_session_handle session_handle);
27 static void restapi_service_context_relinquish(void *context);
28 
restapi_service_context_create(const char * service_url)29 struct service_context *restapi_service_context_create(const char *service_url)
30 {
31 	struct restapi_service_context *new_context =
32 		(struct restapi_service_context *)calloc(1, sizeof(struct restapi_service_context));
33 
34 	if (!new_context) {
35 		EMSG("Failed to alloc restapi_service_context");
36 		return NULL;
37 	}
38 
39 	strncpy(new_context->rpc_call_url, service_url, HTTP_CALLER_MAX_URL_LEN - 1);
40 	strncat(new_context->rpc_call_url, "call/", HTTP_CALLER_MAX_URL_LEN - 1);
41 
42 	new_context->service_context.context = new_context;
43 	new_context->service_context.open = restapi_service_context_open;
44 	new_context->service_context.close = restapi_service_context_close;
45 	new_context->service_context.relinquish = restapi_service_context_relinquish;
46 
47 	return &new_context->service_context;
48 }
49 
restapi_service_context_open(void * context,struct rpc_caller ** caller)50 static rpc_session_handle restapi_service_context_open(void *context, struct rpc_caller **caller)
51 {
52 	struct restapi_service_context *this_context = (struct restapi_service_context *)context;
53 	rpc_session_handle session_handle = NULL;
54 
55 	struct http_caller *http_caller =
56 		(struct http_caller *)calloc(1, sizeof(struct http_caller));
57 
58 	if (http_caller) {
59 		*caller = http_caller_init(http_caller);
60 
61 		int status = http_caller_open(http_caller, this_context->rpc_call_url);
62 
63 		if (status == 0) {
64 			/* Successfully opened session */
65 			session_handle = http_caller;
66 		} else {
67 			/* Failed to open session */
68 			http_caller_close(http_caller);
69 			http_caller_deinit(http_caller);
70 			free(http_caller);
71 		}
72 	}
73 
74 	return session_handle;
75 }
76 
restapi_service_context_close(void * context,rpc_session_handle session_handle)77 static void restapi_service_context_close(void *context, rpc_session_handle session_handle)
78 {
79 	struct http_caller *http_caller = (struct http_caller *)session_handle;
80 
81 	(void)context;
82 
83 	if (http_caller) {
84 		http_caller_close(http_caller);
85 		http_caller_deinit(http_caller);
86 		free(http_caller);
87 	}
88 }
89 
restapi_service_context_relinquish(void * context)90 static void restapi_service_context_relinquish(void *context)
91 {
92 	struct restapi_service_context *this_context = (struct restapi_service_context *)context;
93 
94 	free(this_context);
95 }
96