IPC : Node JS server communication with simple C code - c

I have a C code, that within a infinite loop waits for an input and produces an output.
#include<stdio.h>
void flush() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
int main() {
/*
* Load many files here
*/
double d = 0;
char input[1024];
while (1) {
d = d + 0.1;
scanf("%[^\n]", input);
printf("%lf\n",d);
fflush(stdout);
flush();
}
}
I need another Node JS service that will listen to on some port and send the output as response.
I have this code written
var http = require('http');
var spawn = require('child_process').spawn;
var child = spawn('./dummyNLU.out');
child.stdin.setEncoding('utf-8');
child.stdin.cork();
var buffer = new Buffer(100);
var app = http.createServer(function(req,res){
var string = buffer.write("HelloWorld!"); //this is for testing purpose
child.stdin.write(buffer);
child.stdin.end();
child.stdout.on('data', function(data) {
res.setHeader('Content-Type', 'text/plain');
res.end(data);
});
});
app.listen(3001);
This code I have doesn't seem seem working at all.
Node JS server terminates with an error and the web response consist of 283 lines of response instead of 1.
Can anyone please help me?? Some other approaches to solve the problem (reply to web request from a C executable code output) are also welcome.
Thank you in advance.

child_process.spawn
Spawn your C code binary as a child from Node (bidirectional communication)
var spawn = require('child_process').spawn
var child = spawn('main.exe')
child.stdin.end('7')
child.stdout.on('data', (data) => { console.log(data); })
child.on('close', (code) => console.log('Exit code: ' + code))
This can be tricky if its receiving multiple simultaneos requests, You will need to track the client (origin request) to do the correct response (answer to the correct requesting client)
Or make a queu and spawn a children for each request (having a maximum of X simultaneos children working at a time) so they are spawned as requested and killed once not needed (having the queu is to throttle the total number of active C process)
PoC node spawning a child command (ls) and printing the result (stdout of the spawned process)
const spawn = require('child_process').spawn
const C = spawn('ls');let r=''
C.stdout.on('data',d=>r+=d)
C.on('close', () => console.log(r));
streaming-worker
designed to give you a simple interface for sending and receiving
events/messages from a long running asynchronous C++ Node.js Addon.
Streaming data from C to Node.js

Related

How to interrupt POST data processing and respond to a client in libmicrohttpd?

Libmicrohttpd can be used to iteratively process POST data. The problem is that I cannot interrupt POST request and answer to a client until all POST data is recieved. Consider the following code snippet I copied from the docs
{
struct connection_info_struct *con_info = *con_cls;
if (0 != *upload_data_size)
{
/* Upload not yet done */
if (0 != con_info->answercode)
{
/* we already know the answer, skip rest of upload */
*upload_data_size = 0;
return MHD_YES;
}
if (MHD_YES !=
MHD_post_process (con_info->postprocessor,
upload_data,
*upload_data_size))
{
con_info->answerstring = postprocerror;
con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR;
}
*upload_data_size = 0;
return MHD_YES;
}
/* Upload finished */
if (NULL != con_info->fp)
{
fclose (con_info->fp);
con_info->fp = NULL;
}
if (0 == con_info->answercode)
{
/* No errors encountered, declare success */
con_info->answerstring = completepage;
con_info->answercode = MHD_HTTP_OK;
}
return send_page (connection,
con_info->answerstring,
con_info->answercode);
}
Here we can see that if any error occurred during post processing then we skip any data that will be send by client and then simply set upload_data_size to zero. The problem here, I suppose, is that the data size being sent by client may be exceptionally large. If I try to queue response to a client during post processing (whenever upload_data_size != 0) then MHD_queue_response() returns MHD_NO, which indicates error.
How can I interrupt POST data processing in the middle and respond to a client with an error message without receiving whole data?

Managing data to send for MQTTAsync_sendMessage

Trying to write simple MQTT application with Paho library. I'm planning to create simple fire and forget not blocking function :
void send(char* data)
{
..
}
For this purpose I'm planning to use MQTTAsync client. But how to pass data to connect event. I suppose it is not good style to define char * dataToSend globally.
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTAsync client = (MQTTAsync)context;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
printf("Successful connection\n");
opts.onSuccess = onSend;
opts.context = client;
pubmsg.payload = dataToSend;
pubmsg.payloadlen = strlen(dataToSend);
pubmsg.qos = QOS;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
I afraid of the fact that when I pass pointer of data and return from send function content of data string will not be available since the fact that it is local variable of function that calls send one.
How to build some mechanism that allocates memory for data to send, copies to it data and deallocates when send complete. User that call send are not planning to handle memory management, they will use somehing like send("Hello wrorld") ; I suppose I need something like list of data_to_send for this purpose.
You probably need to add some more context to the question, but the short answer is you don't.
You connect the client once when you launch the application and reuse the same client object for the life of the application. So when you want to send a message you should be already connected, no need to use the onConnect callback.
What you might do is use the onConnect callback to set a flag so the send function knows that the client has finished connecting if it is going to be called very soon after the application starts, just to make sure the client has finished connecting first.
It is possible to pass it using a structure in the context.
Something like:
typedef MQTTContext {
MQTTAsync client;
char* dataToSend;
};
This will allow to get buffer (and MQTTclient) from this context structure.
void onConnect(void* context, MQTTAsync_successData* response)
{
MQTTContext* ctx = (MQTTContext*)context;
// retreive client
MQTTAsync client = ctx->client;
...
// retreive message to publish
pubmsg.payload = ctx->dataToSend;
...
}
In your send function you could store message in this context structure
void send(char* data)
{
MQTTAsync client;
// store in context structure client and message to publish
MQTTContext* ctx = (MQTTContext*)malloc(sizeof(MQTTContext));
ctx->client = client;
ctx->dataToSend = strdup(data);
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
...
conn_opts.context = ctx;
MQTTAsync_connect(client, &conn_opts);
}

Flutter (Dart) ffi - Aplication freezes during processing external library methohd

I am using C library iperf3 to measure network. When I start network testing my aplication freezes and wait for results. I tried async and threads but any progress. Any advise? I'd like to run my test and asynchronously call another methods (at best, call this library again, but other methods). Is it possible?
My network.dart
final DynamicLibrary iperfLib = Platform.isAndroid
? DynamicLibrary.open("libiperf.so")
: DynamicLibrary.process();
typedef RunTestFunc = ffi.Pointer<ffi.Uint8> Function(
ffi.Pointer<ffi.Uint8> context);
typedef RunTest = ffi.Pointer<ffi.Uint8> Function(
ffi.Pointer<ffi.Uint8> context);
RunTest _run_test = iperfLib
.lookup<ffi.NativeFunction<RunTestFunc>>('run_test')
.asFunction<RunTest>();
ffi.Pointer<ffi.Uint8> runTest(ffi.Pointer<ffi.Uint8> context) {
return _run_test(context);
}
and iperf.c
Iperf* run_test(Iperf* test) {
__android_log_print( ANDROID_LOG_INFO, "DONE ", "server_hostname %s", test->server_hostname );
int cc = iperf_run_client( test ) ;
__android_log_print( ANDROID_LOG_INFO, "DONE ", " %d",cc );
iperf_free_test( test );
return test
}
Async Callbacks
The problem is that C routines called from dart are blocking and therefore congest the single existing dart isolate, consequently freezing the UI.
To work around this problem you have to open a port on the dart isolate through which your C routines can asynchronously send messages to the dart isolate. To signal to the dart compiler that this is a non-blocking operation, simply delay the completion of the function until a message on the designated port has been received.
Future<int> asyncData() async {
var receiveData;
bool receivedCallback = false;
var receivePort = ReceivePort()..listen((data) {
print('Received data from c');
receiveData = data;
receivedCallback = true;
});
var nativeSendPort = receivePort.sendPort.nativePort;
nativeTriggerFunction(nativeSendPort);
while(!receivedCallback) {
await Future.delayed(Duration(milliseconds: 100));
}
receivePort.close();
return receiveData;
}
In C, you need to create a trigger function which should ideally be as lightweight as possible, passing the port number to your C code and calling the actual function you want to execute on a different thread.
The trigger function will finish almost instantly, allowing your dart thread to do other work and as soon as the newly created thread is done, it sends its result through the native port back to the dart isolate which can pick up where it left off.
void native_trigger_function(Dart_Port port) {
pthread_t t;
Dart_Port *args = (Dart_Port *) malloc(sizeof(Dart_Port));
*args = port;
pthread_create(&t, NULL, _native_function, args);
}
void *_native_function(void *args) {
Dart_Port port = *(Dart_Port *) args;
int rc = 0;
// do some heavy work
// send return code to dart
Dart_CObject obj;
obj.type = Dart_CObject_kInt32;
obj.value.as_int32 = rc;
Dart_PostCObject_DL(port, &obj);
free(args);
pthread_exit(NULL);
}
Note: This logic relies on the native dart api to work which can be found here. Before use, the interface needs to be attached to the current dart isolate which can be achieved by calling Dart_InitializeApiDL(dart_api_data) from C where dart_api_data is a void pointer which can be obtained from your dart code using the dart:ffi package through NativeApi.initializeApiData.
Update: Thanks #fdollack for fixing the example snippets!
Thank you #Lucas Aschenbach!
This minimum example was so hard to find.
2 small additions.
First, the allocated pointer should be casted to (Dart_Port*),
and the port argument from dart has to be assigned/copied to where the pointer is at!
void native_trigger_function(Dart_Port port) {
pthread_t t;
Dart_Port *args= (Dart_Port*)malloc(sizeof(Dart_Port));
*args = port; // assign port
pthread_create(&t, NULL, _native_function, args);
}
The second thing is inside the _native_function the response to Dart has to be
Dart_PostCObject_DL(port, &obj);
instead of
Dart_PostCObject_DL(args_c.send_port, &obj);

How to call C function from nodeJS

I have some C functions that I need to call frequently from nodeJS (less than 1 second time intervals). The C function takes in an argument and returns a value, which might be an int or an array.
It can be as simple as below:
int main() {
int x = 2;
return x;
}
And I need to get the value x in nodeJS and be able to do console.log(x)
I tried using node-ffi, but I read from the internet that it has a large overhead and is thus inefficient for frequent function calls.
I also considered writing addons but it seems very troublesome (with unfamiliar V8, C++ code and all that...)
And there is not much resources regarding integration between nodeJS and C (they are mostly nodeJS with C++)
Could somebody help shed some light on this? Thanks.
change your c code to
// myProgram.c
#include <stdio.h>
int main(void){
puts("4");
return 0;
}
compile it with gcc, in the same directory as your node file
$ gcc -o myProgram myProgram.c
in your node file, require exec()
const { exec } = require("child_process");
and use it like so:
exec("./myProgram", (error, stdout, stderr) => console.log(stdout));
This works well, it spins up a new process every time.
If, on the other hand, you want to keep the child process running, and call a function in that code from node, you can do that like this:
// multiplyBy2.c
#include <stdio.h>
#include <stdlib.h>
int timesTwo(int x){
return x*2;
}
int main(void){
char buff[100];
int input,output;
while(1){
gets(buff);
input = atoi(buff);
output = timesTwo(input);
printf("%d", output);
// you must flush stdout or else node will hang!
fflush(stdout);
}
return 0;
}
compile multiplyBy2.c and then:
// myNodeApp.js
const {spawn} = require('child_process');
const __delay__ = t => new Promise(resolve=>setTimeout(()=>resolve(), t))
const ch = spawn('./multiplyBy2')
var result=undefined;
ch.stdout.on("data",(data)=>{
result = parseInt(data.toString())
})
async function multiplyBy2InC(num){
ch.stdin.write(`${num}\n`)
while(result==undefined)
await __delay__(1)
const output = result
result = undefined
return output
}
// now you could call it like this, it will print 20 to the console
multiplyBy2InC(10).then(r=>console.log(r))
Use a child process.
,.........
https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback

post and get json in c restful webservice

I read tutorial http://www.vogella.com/tutorials/REST/article.html , i wonder how to post and get json from client with C or C++ without use jerson-client library.Thanks a lot.
For C/C++ Development, You can use libcurl library for making http request. refer [here]. http://curl.haxx.se/libcurl/
For JSON, jsoncpp can be used.see here https://github.com/open-source-parsers/jsoncpp
I have 2 link for C ++ Restful
step 1: add c++ rest sdk using NUGET (name: casablanca)
https://casablanca.codeplex.com/wikipage?title=Using%20NuGet%20to%20add%20the%20C%2b%2b%20REST%20SDK%20to%20a%20VS%20project
step 2: Http Client Tutorial
http://www.codeproject.com/Articles/603810/Using-Casablanca-to-consume-a-REST-API
before test this code you need to change host (http:......) that belongs to you
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <conio.h>
#include <stdio.h>
#include <string>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
//==================GET and save in file abc.txt
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("abc.txt")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://localhost:8080/JSonJersey/rest"));
// Build request URI and start the request.
uri_builder builder(U("/getEmployee"));
// builder.append_query(U("q"), U("Casablanca CodePlex"));c
return client.request(methods::GET, builder.to_string());
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// ================POST
pplx::task<int> Post()
{
return pplx::create_task([]
{
json::value postData;
postData[L"id"] = json::value::number(13);
postData[L"firstName"] = json::value::string(L"Baseball");
postData[L"lastName"] = json::value::string(L"hello");
postData[L"age"] = json::value::number(32);
http_client client(L"http://localhost:8080/JSonJersey/rest/class");
return client.request(methods::POST, L"/PostJsonEmployee", postData.to_string().c_str(), L"application/json");
}).then([](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
return 0;
});
}
int main(int argc, char* argv[])
{
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
Post().wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
getch();
return 0;
}

Resources