cameo-nomad-addon.cc 15.5 KB
Newer Older
1
2
3
4
5
6
7
#include <node.h>
#include <iostream>
#include <unistd.h>
#include <nomadaccessor.h>
#include <uv.h>
#include <thread>
#include <sstream>
8
#include <functional>
9
10
11

using namespace std;
using namespace nomad;
12
using namespace std::placeholders;
13
14
15
16
17
18

namespace nomad {

using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
legoc's avatar
legoc committed
19
using v8::Context;
20
21
22
23
24
25
26
27
28
29
30
31
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
using v8::Integer;
using v8::Boolean;
using v8::Array;
using v8::Persistent;

NomadAccessor accessor;
Isolate * v8Isolate;
legoc's avatar
legoc committed
32
v8::Local<v8::Context> context;
33
34
35
36
37
38
39
40
41

/**
 * Init function to initialise the Cameo Nomad addon.
 */
void Init(const FunctionCallbackInfo<Value>& args) {

	// Get the V8 isolate.
	v8Isolate = args.GetIsolate();

legoc's avatar
legoc committed
42
	// Local endpoint.
legoc's avatar
legoc committed
43
	v8::String::Utf8Value param1(v8Isolate, args[0]);
legoc's avatar
legoc committed
44
	string localEndpoint(*param1);
45
46

	// Initialise the Nomad accessor.
legoc's avatar
legoc committed
47
	accessor.init("vEXP", localEndpoint);
48

49
	// Nomad endpoint.
legoc's avatar
legoc committed
50
	v8::String::Utf8Value param2(v8Isolate, args[1]);
legoc's avatar
legoc committed
51
	string nomadEndpoint(*param2);
52

53
	// Connect to a nomad sim depending on the size of the args.
54
	if (args.Length() > 2) {
55
56

		// Interpret the arg 2 in string because it comes from the command line and is not a V8 integer.
legoc's avatar
legoc committed
57
		v8::String::Utf8Value param3(v8Isolate, args[3]);
legoc's avatar
legoc committed
58
		string arg3(*param3);
59

legoc's avatar
legoc committed
60
		istringstream is(arg3);
61
62
63
64

		int id;
		is >> id;

legoc's avatar
legoc committed
65
		accessor.connectNomadServerSim(nomadEndpoint, id);
66
67
	}
	else {
legoc's avatar
legoc committed
68
		accessor.connectNomadServer(nomadEndpoint);
69
	}
70
71
72
73
74
75
76
77

	args.GetReturnValue().Set(Undefined(v8Isolate));
}

/**
 * Terminate function to terminate the Cameo Nomad addon.
 */
void Terminate(const FunctionCallbackInfo<Value>& args) {
78
	cout << "terminating" << endl;
79
	accessor.terminate();
80
	cout << "terminated" << endl;	
81
82
83
84
85
86
87
}

/**
 * Gets the property id.
 */
void GetPropertyId(const FunctionCallbackInfo<Value>& args) {

legoc's avatar
legoc committed
88
	v8::String::Utf8Value param0(v8Isolate, args[0]);
89
90
	std::string servantName(*param0);

legoc's avatar
legoc committed
91
	v8::String::Utf8Value param1(v8Isolate, args[1]);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
	std::string propertyName(*param1);

	args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getPropertyId(servantName, propertyName)));
}

/**
 * Gets the float64 property value.
 */
void GetFloat64Property(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getFloat64Value(Local<Integer>::Cast(args[0])->Value())));
}

/**
 * Gets the int32 property value.
 */
void GetInt32Property(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Number::New(args.GetIsolate(), accessor.getInt32Value(Local<Integer>::Cast(args[0])->Value())));
}

/**
 * Gets the boolean property value.
 */
void GetBooleanProperty(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.getBooleanValue(Local<Integer>::Cast(args[0])->Value())));
}

/**
 * Gets the string property value.
 */
void GetStringProperty(const FunctionCallbackInfo<Value>& args) {

	string value = accessor.getStringValue(Local<Integer>::Cast(args[0])->Value());
legoc's avatar
legoc committed
124
	args.GetReturnValue().Set(String::NewFromUtf8(args.GetIsolate(), value.c_str()).ToLocalChecked());
125
126
127
128
129
130
131
}

/**
 * Gets the int32 array property value.
 */
void GetInt32ArrayProperty(const FunctionCallbackInfo<Value>& args) {

legoc's avatar
legoc committed
132
	Local<Context> context = args.GetIsolate()->GetCurrentContext();
133
	Local<Array> array = Array::New(args.GetIsolate(), 0);
134
135
136
137

	vector<int32_t> arrayValue = accessor.getInt32Array(Local<Integer>::Cast(args[0])->Value());

	for (int i = 0; i < arrayValue.size(); ++i) {
legoc's avatar
legoc committed
138
		array->Set(context, i, Integer::New(args.GetIsolate(), arrayValue[i]));
139
140
141
142
143
144
145
146
147
148
	}

	args.GetReturnValue().Set(array);
}

/**
 * Gets the float64 array property value.
 */
void GetFloat64ArrayProperty(const FunctionCallbackInfo<Value>& args) {

legoc's avatar
legoc committed
149
	Local<Context> context = args.GetIsolate()->GetCurrentContext();
150
	Local<Array> array = Array::New(args.GetIsolate(), 0);
151
152
153
154

	vector<double> arrayValue = accessor.getFloat64Array(Local<Integer>::Cast(args[0])->Value());

	for (int i = 0; i < arrayValue.size(); ++i) {
legoc's avatar
legoc committed
155
		array->Set(context, i, Number::New(args.GetIsolate(), arrayValue[i]));
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
	}

	args.GetReturnValue().Set(array);
}

/**
 * Sets the float64 property value.
 */
void SetFloat64Property(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setFloat64Value(Local<Integer>::Cast(args[0])->Value(), Local<Number>::Cast(args[1])->Value())));
}

/**
 * Sets the int32 property value.
 */
void SetInt32Property(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setInt32Value(Local<Integer>::Cast(args[0])->Value(), Local<Integer>::Cast(args[1])->Value())));
}

/**
 * Sets the boolean property value.
 */
void SetBooleanProperty(const FunctionCallbackInfo<Value>& args) {
	args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setBooleanValue(Local<Integer>::Cast(args[0])->Value(), Local<Boolean>::Cast(args[1])->Value())));
}

/**
 * Sets the string property value.
 */
void SetStringProperty(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
186
	v8::String::Utf8Value param1(v8Isolate, args[1]);
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
	std::string value(*param1);
	args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), accessor.setStringValue(Local<Integer>::Cast(args[0])->Value(), value)));
}

/**
 * Work structure is be used to pass the callback function and data
 * from the initiating function to the function which triggers the callback.
 */
template<typename Type>
struct Work {
	uv_work_t request;
	Persistent<Function> callback;
	Type result;
};

static void WorkAsync(uv_work_t *req) {
	// Do nothing.
}

/**
 * WorkAsyncComplete function is called once we are ready to trigger the callback
 * function in JS.
 */
template<typename Type, typename JSType>
static void WorkAsyncComplete(uv_work_t *req, int status) {
legoc's avatar
legoc committed
212
/*
213
214
215
216
217
218
219
220
221
222
223
224
225
	Isolate * isolate = Isolate::GetCurrent();

	v8::HandleScope handleScope(isolate);

	Work<Type> *work = static_cast<Work<Type> *>(req->data);

	// Get the result and pass it to the JS callback.
	Local<Value> argv[1] = {JSType::New(isolate, work->result)};

	// https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065
	Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv);

	work->callback.Reset();
legoc's avatar
legoc committed
226
	delete work;*/
227
228
229
230
231
232
233
234
}

/**
 * StringWorkAsyncComplete function is called once we are ready to trigger the callback
 * function in JS.
 */
static void StringWorkAsyncComplete(uv_work_t *req, int status) {

legoc's avatar
legoc committed
235
/*	Isolate * isolate = Isolate::GetCurrent();
236
237
238
239
240
241
242
243
244
245
246
247

	v8::HandleScope handleScope(isolate);

	Work<string> *work = static_cast<Work<string> *>(req->data);

	// Get the result and pass it to the JS callback.
	Local<Value> argv[1] = {String::NewFromUtf8(isolate, work->result.c_str())};

	// https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065
	Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv);

	work->callback.Reset();
legoc's avatar
legoc committed
248
	delete work;*/
249
250
}

251
252
253
254
255
/**
 * Float64ArrayWorkAsyncComplete function is called once we are ready to trigger the callback
 * function in JS.
 */
static void Float64ArrayWorkAsyncComplete(uv_work_t *req, int status) {
legoc's avatar
legoc committed
256
/*
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	Isolate * isolate = Isolate::GetCurrent();

	v8::HandleScope handleScope(isolate);

	Work<vector<double> > *work = static_cast<Work<vector<double> > *>(req->data);

	// Get the result and pass it to the JS callback.
	Local<Array> array = Array::New(isolate, 0);

	const vector<double>& arrayValue = work->result;

	for (int i = 0; i < arrayValue.size(); ++i) {
		array->Set(i, Number::New(isolate, arrayValue[i]));
	}

	Local<Value> argv[1] = {array};

	// https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065
	Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv);

	work->callback.Reset();
legoc's avatar
legoc committed
278
	delete work;*/
279
280
281
282
283
284
285
}

/**
 * Int32ArrayWorkAsyncComplete function is called once we are ready to trigger the callback
 * function in JS.
 */
static void Int32ArrayWorkAsyncComplete(uv_work_t *req, int status) {
legoc's avatar
legoc committed
286
/*
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
	Isolate * isolate = Isolate::GetCurrent();

	v8::HandleScope handleScope(isolate);

	Work<vector<int32_t> > *work = static_cast<Work<vector<int32_t> > *>(req->data);

	// Get the result and pass it to the JS callback.
	Local<Array> array = Array::New(isolate, 0);

	const vector<int32_t>& arrayValue = work->result;

	for (int i = 0; i < arrayValue.size(); ++i) {
		array->Set(i, Integer::New(isolate, arrayValue[i]));
	}

	Local<Value> argv[1] = {array};

	// https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065
	Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 1, argv);

	work->callback.Reset();
legoc's avatar
legoc committed
308
	delete work;*/
309
310
}

311
312
template<typename Type, typename JSType>
void PropertyChanged(Persistent<Function>* callback, Type value) {
legoc's avatar
legoc committed
313
/*
314
315
316
317
318
319
	Work<Type> * work = new Work<Type>();

	work->request.data = work;
	work->callback.Reset(v8Isolate, *callback);
	work->result = value;

legoc's avatar
legoc committed
320
	uv_queue_work(uv_default_loop(), &work->request, WorkAsync, WorkAsyncComplete<Type, JSType>);*/
321
322
323
}

void StringPropertyChanged(Persistent<Function>* callback, const std::string& value) {
legoc's avatar
legoc committed
324
/*
325
326
327
328
329
330
	Work<string> * work = new Work<string>();

	work->request.data = work;
	work->callback.Reset(v8Isolate, *callback);
	work->result = value;

legoc's avatar
legoc committed
331
	uv_queue_work(uv_default_loop(), &work->request, WorkAsync, StringWorkAsyncComplete);*/
332
333
}

334
void Float64ArrayPropertyChanged(Persistent<Function>* callback, const std::vector<double>& value) {
legoc's avatar
legoc committed
335
/*
336
337
338
339
340
341
	Work<std::vector<double> > * work = new Work<std::vector<double> >();

	work->request.data = work;
	work->callback.Reset(v8Isolate, *callback);
	work->result = value;

legoc's avatar
legoc committed
342
	uv_queue_work(uv_default_loop(), &work->request, WorkAsync, Float64ArrayWorkAsyncComplete);*/
343
344
345
}

void Int32ArrayPropertyChanged(Persistent<Function>* callback, const std::vector<int32_t>& value) {
legoc's avatar
legoc committed
346
/*
347
348
349
350
351
352
	Work<std::vector<int32_t> > * work = new Work<std::vector<int32_t> >();

	work->request.data = work;
	work->callback.Reset(v8Isolate, *callback);
	work->result = value;

legoc's avatar
legoc committed
353
	uv_queue_work(uv_default_loop(), &work->request, WorkAsync, Int32ArrayWorkAsyncComplete);*/
354
355
}

356
void RegisterFloat64PropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
357
/*
358
359
360
361
362
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

363
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
364
365
366
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
367
	accessor.registerFloat64PropertyChanged(propertyId, std::bind(&PropertyChanged<double, Number>, pCallback, _1));
368

legoc's avatar
legoc committed
369
	args.GetReturnValue().Set(Undefined(isolate));*/
370
371
372
}

void RegisterInt32PropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
373
/*
374
375
376
377
378
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

379
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
380
381
382
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
383
	accessor.registerInt32PropertyChanged(propertyId, std::bind(&PropertyChanged<int32_t, Integer>, pCallback, _1));
384

legoc's avatar
legoc committed
385
	args.GetReturnValue().Set(Undefined(isolate));*/
386
387
388
}

void RegisterBooleanPropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
389
/*
390
391
392
393
394
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

395
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
396
397
398
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
399
	accessor.registerBooleanPropertyChanged(propertyId, std::bind(&PropertyChanged<bool, Boolean>, pCallback, _1));
400

legoc's avatar
legoc committed
401
	args.GetReturnValue().Set(Undefined(isolate));*/
402
403
404
}

void RegisterStringPropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
405
/*
406
407
408
409
410
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

411
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
412
413
414
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
415
	accessor.registerStringPropertyChanged(propertyId, std::bind(&StringPropertyChanged, pCallback, _1));
416

legoc's avatar
legoc committed
417
	args.GetReturnValue().Set(Undefined(isolate));*/
418
419
}

420
void RegisterFloat64ArrayPropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
421
/*
422
423
424
425
426
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

427
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
428
429
430
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
431
	accessor.registerFloat64ArrayPropertyChanged(propertyId, std::bind(&Float64ArrayPropertyChanged, pCallback, _1));
432

legoc's avatar
legoc committed
433
	args.GetReturnValue().Set(Undefined(isolate));*/
434
435
436
}

void RegisterInt32ArrayPropertyChanged(const FunctionCallbackInfo<Value>& args) {
legoc's avatar
legoc committed
437
/*
438
439
440
441
442
	Isolate * isolate = args.GetIsolate();

	int propertyId = Local<Integer>::Cast(args[0])->Value();
	Local<Function> callback = Local<Function>::Cast(args[1]);

443
	// The persistent function callback is allocated (should not) to allow to use it through the std function parameter.
444
445
446
	// That could lead to a memory leak.
	Persistent<Function>* pCallback = new Persistent<Function>();
	pCallback->Reset(isolate, callback);
447
	accessor.registerInt32ArrayPropertyChanged(propertyId, std::bind(&Int32ArrayPropertyChanged, pCallback, _1));
448

legoc's avatar
legoc committed
449
	args.GetReturnValue().Set(Undefined(isolate));*/
450
451
}

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
/**
 * The init function declares what we will make visible to node.
 */
void init(Local<Object> exports) {

	// Register the functions.
	NODE_SET_METHOD(exports, "init", Init);
	NODE_SET_METHOD(exports, "terminate", Terminate);
	NODE_SET_METHOD(exports, "getPropertyId", GetPropertyId);
	NODE_SET_METHOD(exports, "getFloat64Property", GetFloat64Property);
	NODE_SET_METHOD(exports, "getInt32Property", GetInt32Property);
	NODE_SET_METHOD(exports, "getBooleanProperty", GetBooleanProperty);
	NODE_SET_METHOD(exports, "getStringProperty", GetStringProperty);
	NODE_SET_METHOD(exports, "getInt32ArrayProperty", GetInt32ArrayProperty);
	NODE_SET_METHOD(exports, "getFloat64ArrayProperty", GetFloat64ArrayProperty);
	NODE_SET_METHOD(exports, "setFloat64Property", SetFloat64Property);
	NODE_SET_METHOD(exports, "setInt32Property", SetInt32Property);
	NODE_SET_METHOD(exports, "setStringProperty", SetStringProperty);
	NODE_SET_METHOD(exports, "setBooleanProperty", SetBooleanProperty);
	NODE_SET_METHOD(exports, "registerFloat64PropertyChanged", RegisterFloat64PropertyChanged);
	NODE_SET_METHOD(exports, "registerInt32PropertyChanged", RegisterInt32PropertyChanged);
	NODE_SET_METHOD(exports, "registerBooleanPropertyChanged", RegisterBooleanPropertyChanged);
	NODE_SET_METHOD(exports, "registerStringPropertyChanged", RegisterStringPropertyChanged);
475
476
	NODE_SET_METHOD(exports, "registerFloat64ArrayPropertyChanged", RegisterFloat64ArrayPropertyChanged);
	NODE_SET_METHOD(exports, "registerInt32ArrayPropertyChanged", RegisterInt32ArrayPropertyChanged);
477
478
}

479
NODE_MODULE(addoncameonomad, init)
480
481

}