Skip to content

Commit b91973c

Browse files
committed
RPC loader working properly.
1 parent fd1f0f3 commit b91973c

File tree

4 files changed

+140
-53
lines changed

4 files changed

+140
-53
lines changed

source/loaders/rpc_loader/source/rpc_loader_impl.cpp

Lines changed: 133 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,33 @@
4242
#include <algorithm>
4343
#include <sstream>
4444

45-
typedef struct loader_impl_rpc_write_data_type
46-
{
47-
std::string buffer;
48-
49-
} * loader_impl_rpc_write_data;
50-
51-
typedef struct loader_impl_rpc_function_type
45+
typedef struct loader_impl_rpc_type
5246
{
53-
std::string url;
47+
CURL * discover_curl;
48+
CURL * invoke_curl;
49+
void * allocator;
50+
std::map<type_id, type> types;
5451

55-
} * loader_impl_rpc_function;
52+
} * loader_impl_rpc;
5653

5754
typedef struct loader_impl_rpc_handle_type
5855
{
5956
std::vector<std::string> urls;
6057

6158
} * loader_impl_rpc_handle;
6259

63-
typedef struct loader_impl_rpc_type
60+
typedef struct loader_impl_rpc_function_type
6461
{
65-
CURL * curl;
66-
void * allocator;
67-
std::map<type_id, type> types;
62+
loader_impl_rpc rpc_impl;
63+
std::string url;
6864

69-
} * loader_impl_rpc;
65+
} * loader_impl_rpc_function;
66+
67+
typedef struct loader_impl_rpc_write_data_type
68+
{
69+
std::string buffer;
70+
71+
} * loader_impl_rpc_write_data;
7072

7173
static size_t rpc_loader_impl_write_data(void * buffer, size_t size, size_t nmemb, void * userp);
7274
static int rpc_loader_impl_discover_value(loader_impl_rpc rpc_impl, std::string & url, value v, context ctx);
@@ -128,14 +130,64 @@ int function_rpc_interface_create(function func, function_impl impl)
128130

129131
function_return function_rpc_interface_invoke(function func, function_impl impl, function_args args, size_t size)
130132
{
131-
/* TODO */
133+
loader_impl_rpc_function rpc_function = static_cast<loader_impl_rpc_function>(impl);
134+
loader_impl_rpc rpc_impl = rpc_function->rpc_impl;
135+
value v = metacall_value_create_array(NULL, size);
136+
size_t body_request_size = 0;
132137

133138
(void)func;
134-
(void)impl;
135-
(void)args;
136-
(void)size;
137139

138-
return NULL;
140+
if (size > 0)
141+
{
142+
void ** v_array = metacall_value_to_array(v);
143+
144+
for (size_t arg = 0; arg < size; ++arg)
145+
{
146+
v_array[arg] = args[arg];
147+
}
148+
}
149+
150+
char * buffer = metacall_serialize(metacall_serial(), v, &body_request_size, rpc_impl->allocator);
151+
152+
/* Destroy the value without destroying the contents of the array */
153+
value_destroy(v);
154+
155+
if (body_request_size == 0)
156+
{
157+
log_write("metacall", LOG_LEVEL_ERROR, "Invalid serialization of the values to the endpoint %s", rpc_function->url.c_str());
158+
return NULL;
159+
}
160+
161+
/* Execute a POST to the endpoint */
162+
loader_impl_rpc_write_data_type write_data;
163+
164+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_URL, rpc_function->url.c_str());
165+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_POSTFIELDS, buffer);
166+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_POSTFIELDSIZE, body_request_size - 1);
167+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_WRITEDATA, static_cast<loader_impl_rpc_write_data>(&write_data));
168+
169+
CURLcode res = curl_easy_perform(rpc_impl->invoke_curl);
170+
171+
/* Clear the request buffer */
172+
metacall_allocator_free(rpc_function->rpc_impl->allocator, buffer);
173+
174+
if (res != CURLE_OK)
175+
{
176+
log_write("metacall", LOG_LEVEL_ERROR, "Could not call to the API endpoint %s [%]", rpc_function->url.c_str(), curl_easy_strerror(res));
177+
return NULL;
178+
}
179+
180+
/* Deserialize the call result data */
181+
const size_t write_data_size = write_data.buffer.length() + 1;
182+
183+
void * result_value = metacall_deserialize(metacall_serial(), write_data.buffer.c_str(), write_data_size, rpc_impl->allocator);
184+
185+
if (result_value == NULL)
186+
{
187+
log_write("metacall", LOG_LEVEL_ERROR, "Could not deserialize the call result from API endpoint %s", rpc_function->url.c_str());
188+
}
189+
190+
return result_value;
139191
}
140192

141193
function_return function_rpc_interface_await(function func, function_impl impl, function_args args, size_t size, function_resolve_callback resolve_callback, function_reject_callback reject_callback, void *context)
@@ -251,11 +303,12 @@ loader_impl_data rpc_loader_impl_initialize(loader_impl impl, configuration conf
251303

252304
curl_global_init(CURL_GLOBAL_ALL);
253305

254-
rpc_impl->curl = curl_easy_init();
306+
/* Initialize discover CURL object */
307+
rpc_impl->discover_curl = curl_easy_init();
255308

256-
if (!(rpc_impl->curl != NULL && rpc_loader_impl_initialize_types(impl, rpc_impl) == 0))
309+
if (rpc_impl->discover_curl == NULL)
257310
{
258-
log_write("metacall", LOG_LEVEL_ERROR, "Could not create CURL object");
311+
log_write("metacall", LOG_LEVEL_ERROR, "Could not create CURL inspect object");
259312

260313
metacall_allocator_destroy(rpc_impl->allocator);
261314

@@ -264,9 +317,56 @@ loader_impl_data rpc_loader_impl_initialize(loader_impl impl, configuration conf
264317
return NULL;
265318
}
266319

267-
/* Set up curl general options */
268-
curl_easy_setopt(rpc_impl->curl, CURLOPT_VERBOSE, 0L);
269-
curl_easy_setopt(rpc_impl->curl, CURLOPT_HEADER, 0L);
320+
curl_easy_setopt(rpc_impl->discover_curl, CURLOPT_VERBOSE, 0L);
321+
curl_easy_setopt(rpc_impl->discover_curl, CURLOPT_HEADER, 0L);
322+
curl_easy_setopt(rpc_impl->discover_curl, CURLOPT_WRITEFUNCTION, rpc_loader_impl_write_data);
323+
324+
/* Initialize invoke CURL object */
325+
rpc_impl->invoke_curl = curl_easy_init();
326+
327+
if (rpc_impl->invoke_curl == NULL)
328+
{
329+
log_write("metacall", LOG_LEVEL_ERROR, "Could not create CURL invoke object");
330+
331+
curl_easy_cleanup(rpc_impl->discover_curl);
332+
333+
metacall_allocator_destroy(rpc_impl->allocator);
334+
335+
delete rpc_impl;
336+
337+
return NULL;
338+
}
339+
340+
static struct curl_slist * headers = NULL;
341+
342+
if (headers == NULL)
343+
{
344+
headers = curl_slist_append(headers, "Accept: application/json");
345+
headers = curl_slist_append(headers, "Content-Type: application/json");
346+
headers = curl_slist_append(headers, "charset: utf-8");
347+
}
348+
349+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_VERBOSE, 0L);
350+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_HEADER, 0L);
351+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_CUSTOMREQUEST, "POST");
352+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_HTTPHEADER, headers);
353+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_USERAGENT, "librpc_loader/0.1");
354+
curl_easy_setopt(rpc_impl->invoke_curl, CURLOPT_WRITEFUNCTION, rpc_loader_impl_write_data);
355+
356+
if (rpc_loader_impl_initialize_types(impl, rpc_impl) != 0)
357+
{
358+
log_write("metacall", LOG_LEVEL_ERROR, "Could not create CURL object");
359+
360+
curl_easy_cleanup(rpc_impl->discover_curl);
361+
362+
curl_easy_cleanup(rpc_impl->invoke_curl);
363+
364+
metacall_allocator_destroy(rpc_impl->allocator);
365+
366+
delete rpc_impl;
367+
368+
return NULL;
369+
}
270370

271371
/* Register initialization */
272372
loader_initialization_register(impl);
@@ -462,6 +562,7 @@ int rpc_loader_impl_discover_value(loader_impl_rpc rpc_impl, std::string & url,
462562
loader_impl_rpc_function rpc_func = new loader_impl_rpc_function_type();
463563

464564
rpc_func->url = url + (is_async ? "await/" : "call/") + func_name;
565+
rpc_func->rpc_impl = rpc_impl;
465566

466567
function f = function_create(func_name, args_count, rpc_func, &function_rpc_singleton);
467568

@@ -513,15 +614,14 @@ int rpc_loader_impl_discover(loader_impl impl, loader_handle handle, context ctx
513614

514615
std::string inspect_url = rpc_handle->urls[iterator] + "inspect";
515616

516-
curl_easy_setopt(rpc_impl->curl, CURLOPT_URL, inspect_url.c_str());
517-
curl_easy_setopt(rpc_impl->curl, CURLOPT_WRITEFUNCTION, rpc_loader_impl_write_data);
518-
curl_easy_setopt(rpc_impl->curl, CURLOPT_WRITEDATA, static_cast<loader_impl_rpc_write_data>(&write_data));
617+
curl_easy_setopt(rpc_impl->discover_curl, CURLOPT_URL, inspect_url.c_str());
618+
curl_easy_setopt(rpc_impl->discover_curl, CURLOPT_WRITEDATA, static_cast<loader_impl_rpc_write_data>(&write_data));
519619

520-
CURLcode res = curl_easy_perform(rpc_impl->curl);
620+
CURLcode res = curl_easy_perform(rpc_impl->discover_curl);
521621

522622
if (res != CURLE_OK)
523623
{
524-
log_write("metacall", LOG_LEVEL_ERROR, "Could not access the API endpoint %s", rpc_handle->urls[iterator].c_str());
624+
log_write("metacall", LOG_LEVEL_ERROR, "Could not access the API endpoint %s [%s]", rpc_handle->urls[iterator].c_str(), curl_easy_strerror(res));
525625
return 1;
526626
}
527627

@@ -556,7 +656,9 @@ int rpc_loader_impl_destroy(loader_impl impl)
556656

557657
metacall_allocator_destroy(rpc_impl->allocator);
558658

559-
curl_easy_cleanup(rpc_impl->curl);
659+
curl_easy_cleanup(rpc_impl->discover_curl);
660+
661+
curl_easy_cleanup(rpc_impl->invoke_curl);
560662

561663
curl_global_cleanup();
562664

source/tests/metacall_rpc_test/source/metacall_rpc_test.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,19 @@ TEST_F(metacall_rpc_test, DefaultConstructor)
7272
metacall_allocator_destroy(allocator);
7373
}
7474

75-
/*
7675
const enum metacall_value_id divide_ids[] =
7776
{
78-
METACALL_DOUBLE, METACALL_DOUBLE
77+
METACALL_FLOAT, METACALL_FLOAT
7978
};
8079

81-
void * ret = metacallt("divide", divide_ids, 50.0, 10.0);
80+
void * ret = metacallt("divide", divide_ids, 50.0f, 10.0f);
8281

8382
EXPECT_NE((void *) NULL, (void *) ret);
8483

85-
EXPECT_EQ((double) metacall_value_to_double(ret), (double) 5.0);
84+
EXPECT_EQ((float) metacall_value_to_float(ret), (float) 5.0f);
8685

8786
metacall_value_destroy(ret);
88-
*/
87+
8988
EXPECT_EQ((int) 0, (int) metacall_clear(handle));
9089

9190
static const char buffer[] = "http://localhost:6094/viferga/example/v1";

source/tests/metacall_rpc_test/source/server.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,20 @@ const server = http.createServer((req, res) => {
2828
return;
2929
} else if (req.url === '/viferga/example/v1/inspect') {
3030
const inspect = '{"py":[{"name":"example.py","scope":{"name":"global_namespace","funcs":[{"name":"divide","signature":{"ret":{"type":{"name":"float","id":6}},"args":[{"name":"left","type":{"name":"float","id":6}},{"name":"right","type":{"name":"float","id":6}}]},"async":false},{"name":"hello","signature":{"ret":{"type":{"name":"","id":18}},"args":[]},"async":false},{"name":"return_same_array","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"arr","type":{"name":"","id":18}}]},"async":false},{"name":"bytebuff","signature":{"ret":{"type":{"name":"bytes","id":8}},"args":[{"name":"input","type":{"name":"bytes","id":8}}]},"async":false},{"name":"dont_load_this_function","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"left","type":{"name":"","id":18}},{"name":"right","type":{"name":"","id":18}}]},"async":false},{"name":"sum","signature":{"ret":{"type":{"name":"int","id":4}},"args":[{"name":"left","type":{"name":"int","id":4}},{"name":"right","type":{"name":"int","id":4}}]},"async":false},{"name":"strcat","signature":{"ret":{"type":{"name":"str","id":7}},"args":[{"name":"left","type":{"name":"str","id":7}},{"name":"right","type":{"name":"str","id":7}}]},"async":false},{"name":"return_array","signature":{"ret":{"type":{"name":"","id":18}},"args":[]},"async":false},{"name":"multiply","signature":{"ret":{"type":{"name":"int","id":4}},"args":[{"name":"left","type":{"name":"int","id":4}},{"name":"right","type":{"name":"int","id":4}}]},"async":false}],"classes":[],"objects":[]}}],"rb":[{"name":"hello.rb","scope":{"name":"global_namespace","funcs":[{"name":"say_multiply","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"left","type":{"name":"Fixnum","id":3}},{"name":"right","type":{"name":"Fixnum","id":3}}]},"async":false},{"name":"get_second","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"first","type":{"name":"Fixnum","id":3}},{"name":"second","type":{"name":"Fixnum","id":3}}]},"async":false},{"name":"say_null","signature":{"ret":{"type":{"name":"","id":18}},"args":[]},"async":false},{"name":"say_hello","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"value","type":{"name":"String","id":7}}]},"async":false},{"name":"backwardsPrime","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"start","type":{"name":"","id":18}},{"name":"stop","type":{"name":"","id":18}}]},"async":false},{"name":"get_second_untyped","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"first","type":{"name":"","id":18}},{"name":"second","type":{"name":"","id":18}}]},"async":false},{"name":"say_sum_ducktyped","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"left","type":{"name":"","id":18}},{"name":"right","type":{"name":"","id":18}}]},"async":false},{"name":"say_string_without_spaces","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"value","type":{"name":"String","id":7}}]},"async":false},{"name":"say_multiply_ducktyped","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"left","type":{"name":"","id":18}},{"name":"right","type":{"name":"","id":18}}]},"async":false}],"classes":[],"objects":[]}}],"cs":[{"name":"hello.cs","scope":{"name":"global_namespace","funcs":[{"name":"Sum","signature":{"ret":{"type":{"name":"int","id":3}},"args":[{"name":"a","type":{"name":"int","id":3}},{"name":"b","type":{"name":"int","id":3}}]},"async":false},{"name":"Say","signature":{"ret":{"type":{"name":"","id":18}},"args":[{"name":"text","type":{"name":"string","id":7}}]},"async":false},{"name":"Concat","signature":{"ret":{"type":{"name":"string","id":7}},"args":[{"name":"a","type":{"name":"string","id":7}},{"name":"b","type":{"name":"string","id":7}}]},"async":false},{"name":"SayHello","signature":{"ret":{"type":{"name":"","id":18}},"args":[]},"async":false}],"classes":[],"objects":[]}}],"__metacall_host__":[],"mock":[{"name":"empty.mock","scope":{"name":"global_namespace","funcs":[{"name":"three_str","signature":{"ret":{"type":{"name":"String","id":7}},"args":[{"name":"a_str","type":{"name":"String","id":7}},{"name":"b_str","type":{"name":"String","id":7}},{"name":"c_str","type":{"name":"String","id":7}}]},"async":false},{"name":"my_empty_func_str","signature":{"ret":{"type":{"name":"String","id":7}},"args":[]},"async":false},{"name":"my_empty_func_int","signature":{"ret":{"type":{"name":"Integer","id":3}},"args":[]},"async":false},{"name":"new_args","signature":{"ret":{"type":{"name":"String","id":7}},"args":[{"name":"a_str","type":{"name":"String","id":7}}]},"async":false},{"name":"two_str","signature":{"ret":{"type":{"name":"String","id":7}},"args":[{"name":"a_str","type":{"name":"String","id":7}},{"name":"b_str","type":{"name":"String","id":7}}]},"async":false},{"name":"two_doubles","signature":{"ret":{"type":{"name":"Double","id":6}},"args":[{"name":"first_parameter","type":{"name":"Double","id":6}},{"name":"second_parameter","type":{"name":"Double","id":6}}]},"async":false},{"name":"my_empty_func","signature":{"ret":{"type":{"name":"Integer","id":3}},"args":[]},"async":false},{"name":"mixed_args","signature":{"ret":{"type":{"name":"Char","id":1}},"args":[{"name":"a_char","type":{"name":"Char","id":1}},{"name":"b_int","type":{"name":"Integer","id":3}},{"name":"c_long","type":{"name":"Long","id":4}},{"name":"d_double","type":{"name":"Double","id":6}},{"name":"e_ptr","type":{"name":"Ptr","id":11}}]},"async":false}],"classes":[],"objects":[]}}]}';
31-
res.setHeader('Content-Type', 'text/json');
31+
res.setHeader('Content-Type', 'application/json');
3232
res.end(inspect);
3333
return;
3434
}
3535
} else if (req.method === 'POST') {
3636
if (req.url === '/viferga/example/v1/call/divide') {
3737
data.then((body) => {
38+
console.log('¡Call recieved!');
3839
if (body !== '[50.0,10.0]') {
3940
console.error('Invalid body:', body);
4041
process.exit(1);
4142
}
4243
const result = '5.0';
43-
res.setHeader('Content-Type', 'text/json');
44+
res.setHeader('Content-Type', 'application/json');
4445
res.end(result);
4546
setTimeout(() => {
4647
process.exit(0);

source/tests/metacall_rpc_test/source/test.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,4 @@ process.on('uncaughtException', killTest);
8383
}
8484
process.exit(0);
8585
});
86-
87-
/*
88-
execFile(process.argv[3], (error, stdout, stderr) => {
89-
if (stdout) {
90-
console.log(stdout);
91-
}
92-
if (stderr) {
93-
console.error(stderr);
94-
}
95-
if (error) {
96-
killTest(error);
97-
}
98-
process.exit(0);
99-
});
100-
*/
10186
})();

0 commit comments

Comments
 (0)