Subversion Repositories HomeAutomation

Rev

Rev 1402 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1402 Rev 1405
1
/***************************************************************************
1
/***************************************************************************
2
 *   Copyright (C) December 10, 2008 by Mattias Runge                             *
2
 *   Copyright (C) December 10, 2008 by Mattias Runge                             *
3
 *   mattias@runge.se                                                      *
3
 *   mattias@runge.se                                                      *
4
 *   virtualmachine.cpp                                            *
4
 *   virtualmachine.cpp                                            *
5
 *                                                                         *
5
 *                                                                         *
6
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   This program is free software; you can redistribute it and/or modify  *
7
 *   it under the terms of the GNU General Public License as published by  *
7
 *   it under the terms of the GNU General Public License as published by  *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 *   (at your option) any later version.                                   *
9
 *   (at your option) any later version.                                   *
10
 *                                                                         *
10
 *                                                                         *
11
 *   This program is distributed in the hope that it will be useful,       *
11
 *   This program is distributed in the hope that it will be useful,       *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU General Public License for more details.                          *
14
 *   GNU General Public License for more details.                          *
15
 *                                                                         *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU General Public License     *
16
 *   You should have received a copy of the GNU General Public License     *
17
 *   along with this program; if not, write to the                         *
17
 *   along with this program; if not, write to the                         *
18
 *   Free Software Foundation, Inc.,                                       *
18
 *   Free Software Foundation, Inc.,                                       *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20
 ***************************************************************************/
20
 ***************************************************************************/
21
 
21
 
22
#include "virtualmachine.h"
22
#include "virtualmachine.h"
23
 
23
 
24
VirtualMachine* VirtualMachine::myInstance = NULL;
24
VirtualMachine* VirtualMachine::myInstance = NULL;
25
 
25
 
26
VirtualMachine& VirtualMachine::getInstance()
26
VirtualMachine& VirtualMachine::getInstance()
27
{
27
{
28
    if (myInstance == NULL)
28
    if (myInstance == NULL)
29
    {
29
    {
30
        myInstance = new VirtualMachine();
30
        myInstance = new VirtualMachine();
31
    }
31
    }
32
 
32
 
33
    return *myInstance;
33
    return *myInstance;
34
}
34
}
35
 
35
 
36
void VirtualMachine::deleteInstance()
36
void VirtualMachine::deleteInstance()
37
{
37
{
38
    if (myInstance != NULL)
38
    if (myInstance != NULL)
39
    {
39
    {
40
        delete myInstance;
40
        delete myInstance;
41
        myInstance = NULL;
41
        myInstance = NULL;
42
    }
42
    }
43
}
43
}
44
 
44
 
45
VirtualMachine::VirtualMachine()
45
VirtualMachine::VirtualMachine()
46
{
46
{
47
}
47
}
48
 
48
 
49
VirtualMachine::~VirtualMachine()
49
VirtualMachine::~VirtualMachine()
50
{
50
{
51
    stop();
51
    stop();
52
 
52
 
53
    myCommandThread.stop();
53
    myCommandThread.stop();
54
 
54
 
55
    ///FIXME: Verify that this works and does not cause segfaults
55
    ///FIXME: Verify that this works and does not cause segfaults
56
    for (map<unsigned long int, SocketThread*>::iterator iter = mySocketThreads.begin(); iter != mySocketThreads.end(); iter++)
56
    for (map<unsigned long int, SocketThread*>::iterator iter = mySocketThreads.begin(); iter != mySocketThreads.end(); iter++)
57
    {
57
    {
58
        iter->second->stop();
58
        iter->second->stop();
59
        delete iter->second;
59
        delete iter->second;
60
        //mySocketThreads.erase(iter);
60
        //mySocketThreads.erase(iter);
61
    }
61
    }
62
 
62
 
63
    mySocketThreads.clear();
63
    mySocketThreads.clear();
64
 
64
 
65
    for (map<int, IntervalThread*>::iterator iter = myIntervalThreads.begin(); iter != myIntervalThreads.end(); iter++)
65
    for (map<int, IntervalThread*>::iterator iter = myIntervalThreads.begin(); iter != myIntervalThreads.end(); iter++)
66
    {
66
    {
67
        iter->second->stop();
67
        iter->second->stop();
68
        delete iter->second;
68
        delete iter->second;
69
        //myIntervalThreads.erase(iter);
69
        //myIntervalThreads.erase(iter);
70
    }
70
    }
71
 
71
 
72
    myIntervalThreads.clear();
72
    myIntervalThreads.clear();
73
}
73
}
74
 
74
 
75
void VirtualMachine::run()
75
void VirtualMachine::run()
76
{
76
{
77
    myGlobal = ObjectTemplate::New();
77
    myGlobal = ObjectTemplate::New();
78
    myGlobal->Set(String::New("_quit"), FunctionTemplate::New(VirtualMachine::_quit));
78
    myGlobal->Set(String::New("_quit"), FunctionTemplate::New(VirtualMachine::_quit));
79
    myGlobal->Set(String::New("_print"), FunctionTemplate::New(VirtualMachine::_print));
79
    myGlobal->Set(String::New("_print"), FunctionTemplate::New(VirtualMachine::_print));
80
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine::_log));
80
    myGlobal->Set(String::New("log"), FunctionTemplate::New(VirtualMachine::_log));
81
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine::_sendCanMessage));
81
    myGlobal->Set(String::New("sendCanMessage"), FunctionTemplate::New(VirtualMachine::_sendCanMessage));
82
    myGlobal->Set(String::New("sendCanNMTMessage"), FunctionTemplate::New(VirtualMachine::_sendCanNMTMessage));
82
    myGlobal->Set(String::New("sendCanNMTMessage"), FunctionTemplate::New(VirtualMachine::_sendCanNMTMessage));
83
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine::_loadScript));
83
    myGlobal->Set(String::New("loadScript"), FunctionTemplate::New(VirtualMachine::_loadScript));
84
    myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine::_startIntervalThread));
84
    myGlobal->Set(String::New("startIntervalThread"), FunctionTemplate::New(VirtualMachine::_startIntervalThread));
85
    myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine::_stopIntervalThread));
85
    myGlobal->Set(String::New("stopIntervalThread"), FunctionTemplate::New(VirtualMachine::_stopIntervalThread));
86
    myGlobal->Set(String::New("setIntervalThreadTimeout"), FunctionTemplate::New(VirtualMachine::_setIntervalThreadTimeout));
86
    myGlobal->Set(String::New("setIntervalThreadTimeout"), FunctionTemplate::New(VirtualMachine::_setIntervalThreadTimeout));
87
    myGlobal->Set(String::New("startSocketThread"), FunctionTemplate::New(VirtualMachine::_startSocketThread));
87
    myGlobal->Set(String::New("startSocketThread"), FunctionTemplate::New(VirtualMachine::_startSocketThread));
88
    myGlobal->Set(String::New("stopSocketThread"), FunctionTemplate::New(VirtualMachine::_stopSocketThread));
88
    myGlobal->Set(String::New("stopSocketThread"), FunctionTemplate::New(VirtualMachine::_stopSocketThread));
89
    myGlobal->Set(String::New("sendToSocketThread"), FunctionTemplate::New(VirtualMachine::_sendToSocketThread));
89
    myGlobal->Set(String::New("sendToSocketThread"), FunctionTemplate::New(VirtualMachine::_sendToSocketThread));
90
    myGlobal->Set(String::New("loadDataStore"), FunctionTemplate::New(VirtualMachine::_loadDataStore));
90
    myGlobal->Set(String::New("loadDataStore"), FunctionTemplate::New(VirtualMachine::_loadDataStore));
91
    myGlobal->Set(String::New("getFileContents"), FunctionTemplate::New(VirtualMachine::_getFileContents));
91
    myGlobal->Set(String::New("getFileContents"), FunctionTemplate::New(VirtualMachine::_getFileContents));
-
 
92
    myGlobal->Set(String::New("setFileContents"), FunctionTemplate::New(VirtualMachine::_setFileContents));
92
    myGlobal->Set(String::New("system"), FunctionTemplate::New(VirtualMachine::_system));
93
    myGlobal->Set(String::New("system"), FunctionTemplate::New(VirtualMachine::_system));
93
    myGlobal->Set(String::New("uint2hex"), FunctionTemplate::New(VirtualMachine::_uint2hex));
94
    myGlobal->Set(String::New("uint2hex"), FunctionTemplate::New(VirtualMachine::_uint2hex));
94
    myGlobal->Set(String::New("hex2bin"), FunctionTemplate::New(VirtualMachine::_hex2bin));
95
    myGlobal->Set(String::New("hex2bin"), FunctionTemplate::New(VirtualMachine::_hex2bin));
95
    myGlobal->Set(String::New("bin2hex"), FunctionTemplate::New(VirtualMachine::_bin2hex));
96
    myGlobal->Set(String::New("bin2hex"), FunctionTemplate::New(VirtualMachine::_bin2hex));
96
    myGlobal->Set(String::New("bin2float"), FunctionTemplate::New(VirtualMachine::_bin2float));
97
    myGlobal->Set(String::New("bin2float"), FunctionTemplate::New(VirtualMachine::_bin2float));
97
    myGlobal->Set(String::New("float2bin"), FunctionTemplate::New(VirtualMachine::_float2bin));
98
    myGlobal->Set(String::New("float2bin"), FunctionTemplate::New(VirtualMachine::_float2bin));
98
    myGlobal->Set(String::New("bin2uint"), FunctionTemplate::New(VirtualMachine::_bin2uint));
99
    myGlobal->Set(String::New("bin2uint"), FunctionTemplate::New(VirtualMachine::_bin2uint));
99
    myGlobal->Set(String::New("uint2bin"), FunctionTemplate::New(VirtualMachine::_uint2bin));
100
    myGlobal->Set(String::New("uint2bin"), FunctionTemplate::New(VirtualMachine::_uint2bin));
100
    myGlobal->Set(String::New("hex2uint"), FunctionTemplate::New(VirtualMachine::_hex2uint));
101
    myGlobal->Set(String::New("hex2uint"), FunctionTemplate::New(VirtualMachine::_hex2uint));
101
    myGlobal->Set(String::New("sleep"), FunctionTemplate::New(VirtualMachine::_sleep));
102
    myGlobal->Set(String::New("sleep"), FunctionTemplate::New(VirtualMachine::_sleep));
102
    myContext = Context::New(NULL, myGlobal);
103
    myContext = Context::New(NULL, myGlobal);
103
 
104
 
104
 
105
 
105
    if (loadScript("System/Base.js"))
106
    if (loadScript("System/Base.js"))
106
    {
107
    {
107
        loadScript("System/Startup.js");
108
        loadScript("System/Startup.js");
108
 
109
 
109
        loadScript("Autostart.js");
110
        loadScript("Autostart.js");
110
 
111
 
111
        Context::Scope contextScope(myContext);
112
        Context::Scope contextScope(myContext);
112
 
113
 
113
        myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
114
        myFunctionStartup = Handle<Function>::Cast(myContext->Global()->Get(String::New("startup")));
114
    }
115
    }
115
    else
116
    else
116
    {
117
    {
117
        ///FIXME: We should probably exit the application here
118
        ///FIXME: We should probably exit the application here
118
        return;
119
        return;
119
    }
120
    }
120
 
121
 
121
    const int argc = 0;
122
    const int argc = 0;
122
    Handle<Value> argv[argc] = { };
123
    Handle<Value> argv[argc] = { };
123
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv);
124
    Handle<Value> result = myFunctionStartup->Call(myFunctionStartup, argc, argv);
124
 
125
 
125
 
126
 
126
    string commandPort = Settings::get("CommandPort");
127
    string commandPort = Settings::get("CommandPort");
127
    if (commandPort != "")
128
    if (commandPort != "")
128
    {
129
    {
129
        myCommandThread.setSettings(stoi(commandPort), "Command console");
130
        myCommandThread.setSettings(stoi(commandPort), "Command console");
130
        myCommandThread.start();
131
        myCommandThread.start();
131
    }
132
    }
132
    else
133
    else
133
    {
134
    {
134
        Logger &log = Logger::getInstance();
135
        Logger &log = Logger::getInstance();
135
        log.add("CommandPort is not defined, can not start Command console socket\n");
136
        log.add("CommandPort is not defined, can not start Command console socket\n");
136
    }
137
    }
137
 
138
 
138
 
139
 
139
    mySemaphore.lock();
140
    mySemaphore.lock();
140
 
141
 
141
    while (true)
142
    while (true)
142
    {
143
    {
143
        while (myExpressions.size() > 0)
144
        while (myExpressions.size() > 0)
144
        {
145
        {
145
            runExpression(myExpressions.pop());
146
            runExpression(myExpressions.pop());
146
        }
147
        }
147
 
148
 
148
        mySemaphore.wait();
149
        mySemaphore.wait();
149
    }
150
    }
150
 
151
 
151
    mySemaphore.unlock();
152
    mySemaphore.unlock();
152
}
153
}
153
 
154
 
154
void VirtualMachine::queueExpression(Expression expression)
155
void VirtualMachine::queueExpression(Expression expression)
155
{
156
{
156
    myExpressions.push(expression);
157
    myExpressions.push(expression);
157
    mySemaphore.broadcast();
158
    mySemaphore.broadcast();
158
}
159
}
159
 
160
 
160
string VirtualMachine::formatException(TryCatch* tryCatch)
161
string VirtualMachine::formatException(TryCatch* tryCatch)
161
{
162
{
162
    string result;
163
    string result;
163
 
164
 
164
    HandleScope handleScope;
165
    HandleScope handleScope;
165
    String::Utf8Value exception(tryCatch->Exception());
166
    String::Utf8Value exception(tryCatch->Exception());
166
    Handle<v8::Message> message = tryCatch->Message();
167
    Handle<v8::Message> message = tryCatch->Message();
167
 
168
 
168
    string strException = *exception;
169
    string strException = *exception;
169
 
170
 
170
    if (message.IsEmpty())
171
    if (message.IsEmpty())
171
    {
172
    {
172
        result += strException + "\n";
173
        result += strException + "\n";
173
    }
174
    }
174
    else
175
    else
175
    {
176
    {
176
        String::Utf8Value filename(message->GetScriptResourceName());
177
        String::Utf8Value filename(message->GetScriptResourceName());
177
        string strFilename = *filename;
178
        string strFilename = *filename;
178
 
179
 
179
        result += strFilename + ":" + itos(message->GetLineNumber()) + ": " + strException + "\n";
180
        result += strFilename + ":" + itos(message->GetLineNumber()) + ": " + strException + "\n";
180
 
181
 
181
        String::Utf8Value sourceline(message->GetSourceLine());
182
        String::Utf8Value sourceline(message->GetSourceLine());
182
        string strSourceline = *sourceline;
183
        string strSourceline = *sourceline;
183
 
184
 
184
        result += strSourceline + "\n";
185
        result += strSourceline + "\n";
185
 
186
 
186
        string underline = rpad("", message->GetStartColumn(), ' ');
187
        string underline = rpad("", message->GetStartColumn(), ' ');
187
        underline = rpad(underline, message->GetEndColumn(), '^');
188
        underline = rpad(underline, message->GetEndColumn(), '^');
188
 
189
 
189
        result += underline + "\n";
190
        result += underline + "\n";
190
    }
191
    }
191
 
192
 
192
    return result;
193
    return result;
193
}
194
}
194
 
195
 
195
bool VirtualMachine::loadDataStore(string storeName)
196
bool VirtualMachine::loadDataStore(string storeName)
196
{
197
{
197
    Logger &log = Logger::getInstance();
198
    Logger &log = Logger::getInstance();
198
 
199
 
199
    string basePath = Settings::get("BasePath") + "Services/DataStores/";
200
    string basePath = Settings::get("BasePath") + "Services/DataStores/";
200
    string scriptFileName = basePath + storeName + ".js";
201
    string scriptFileName = basePath + storeName + ".js";
201
 
202
 
202
    if (!file_exists(scriptFileName))
203
    if (!file_exists(scriptFileName))
203
    {
204
    {
204
        log.add("Failed to load datastore " + scriptFileName + ", file does not exist.\n");
205
        log.add("Failed to load datastore " + scriptFileName + ", file does not exist.\n");
205
        return false;
206
        return false;
206
    }
207
    }
207
 
208
 
208
    string scriptSource = file_get_contents(scriptFileName);
209
    string scriptSource = file_get_contents(scriptFileName);
209
 
210
 
210
    scriptSource = "DataStore.addStore('" + storeName + "', " + str_replace("\n", "", scriptSource) + ");";
211
    scriptSource = "DataStore.addStore('" + storeName + "', " + str_replace("\n", "", scriptSource) + ");";
211
 
212
 
212
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
213
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
213
    Handle<String> name = String::New(scriptFileName.c_str(), scriptFileName.length());
214
    Handle<String> name = String::New(scriptFileName.c_str(), scriptFileName.length());
214
 
215
 
215
    Context::Scope contextScope(myContext);
216
    Context::Scope contextScope(myContext);
216
 
217
 
217
    TryCatch tryCatch;
218
    TryCatch tryCatch;
218
 
219
 
219
    Handle<Script> script = Script::Compile(source, name);
220
    Handle<Script> script = Script::Compile(source, name);
220
 
221
 
221
    if (script.IsEmpty())
222
    if (script.IsEmpty())
222
    {
223
    {
223
        log.add(formatException(&tryCatch));
224
        log.add(formatException(&tryCatch));
224
        return false;
225
        return false;
225
    }
226
    }
226
    else
227
    else
227
    {
228
    {
228
        Handle<Value> result = script->Run();
229
        Handle<Value> result = script->Run();
229
 
230
 
230
        if (result.IsEmpty())
231
        if (result.IsEmpty())
231
        {
232
        {
232
            log.add(formatException(&tryCatch));
233
            log.add(formatException(&tryCatch));
233
            return false;
234
            return false;
234
        }
235
        }
235
 
236
 
236
        log.add("Loaded datastore " + storeName + "\n");
237
        log.add("Loaded datastore " + storeName + "\n");
237
    }
238
    }
238
 
239
 
239
    return true;
240
    return true;
240
}
241
}
241
 
242
 
242
bool VirtualMachine::loadScript(string scriptName)
243
bool VirtualMachine::loadScript(string scriptName)
243
{
244
{
244
    Logger &log = Logger::getInstance();
245
    Logger &log = Logger::getInstance();
245
 
246
 
246
    string basePath = Settings::get("BasePath") + "Services/";
247
    string basePath = Settings::get("BasePath") + "Services/";
247
    string scriptFileName = basePath + scriptName;
248
    string scriptFileName = basePath + scriptName;
248
 
249
 
249
    if (!file_exists(scriptFileName))
250
    if (!file_exists(scriptFileName))
250
    {
251
    {
251
        log.add("Failed to load " + scriptFileName + ", file does not exist.\n");
252
        log.add("Failed to load " + scriptFileName + ", file does not exist.\n");
252
        return false;
253
        return false;
253
    }
254
    }
254
 
255
 
255
    string scriptSource = file_get_contents(scriptFileName);
256
    string scriptSource = file_get_contents(scriptFileName);
256
 
257
 
257
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
258
    Handle<String> source =  String::New(scriptSource.c_str(), scriptSource.length());
258
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
259
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
259
 
260
 
260
    Context::Scope contextScope(myContext);
261
    Context::Scope contextScope(myContext);
261
 
262
 
262
    TryCatch tryCatch;
263
    TryCatch tryCatch;
263
 
264
 
264
    Handle<Script> script = Script::Compile(source, name);
265
    Handle<Script> script = Script::Compile(source, name);
265
 
266
 
266
    if (script.IsEmpty())
267
    if (script.IsEmpty())
267
    {
268
    {
268
        log.addToSyslog(formatException(&tryCatch));
269
        log.addToSyslog(formatException(&tryCatch));
269
        return false;
270
        return false;
270
    }
271
    }
271
    else
272
    else
272
    {
273
    {
273
        Handle<Value> result = script->Run();
274
        Handle<Value> result = script->Run();
274
 
275
 
275
        if (result.IsEmpty())
276
        if (result.IsEmpty())
276
        {
277
        {
277
            log.addToSyslog(formatException(&tryCatch));
278
            log.addToSyslog(formatException(&tryCatch));
278
            return false;
279
            return false;
279
        }
280
        }
280
 
281
 
281
        log.add("Loaded " + scriptName + "\n");
282
        log.add("Loaded " + scriptName + "\n");
282
    }
283
    }
283
 
284
 
284
    return true;
285
    return true;
285
}
286
}
286
 
287
 
287
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
288
unsigned int VirtualMachine::startIntervalThread(unsigned int timeout)
288
{
289
{
289
    IntervalThread *intervalThread = new IntervalThread(timeout);
290
    IntervalThread *intervalThread = new IntervalThread(timeout);
290
 
291
 
291
    myIntervalThreads[intervalThread->getId()] = intervalThread;
292
    myIntervalThreads[intervalThread->getId()] = intervalThread;
292
    myIntervalThreads[intervalThread->getId()]->start();
293
    myIntervalThreads[intervalThread->getId()]->start();
293
 
294
 
294
    return intervalThread->getId();
295
    return intervalThread->getId();
295
}
296
}
296
 
297
 
297
bool VirtualMachine::stopIntervalThread(unsigned int id)
298
bool VirtualMachine::stopIntervalThread(unsigned int id)
298
{
299
{
299
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
300
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
300
    {
301
    {
301
        myIntervalThreads[id]->stop();
302
        myIntervalThreads[id]->stop();
302
        delete myIntervalThreads[id];
303
        delete myIntervalThreads[id];
303
        myIntervalThreads.erase(id);
304
        myIntervalThreads.erase(id);
304
 
305
 
305
        return true;
306
        return true;
306
    }
307
    }
307
 
308
 
308
    return false;
309
    return false;
309
}
310
}
310
 
311
 
311
bool VirtualMachine::setIntervalThreadTimeout(unsigned int id, unsigned int timeout)
312
bool VirtualMachine::setIntervalThreadTimeout(unsigned int id, unsigned int timeout)
312
{
313
{
313
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
314
    if (myIntervalThreads.find(id) != myIntervalThreads.end())
314
    {
315
    {
315
        myIntervalThreads[id]->setTimeout(timeout);
316
        myIntervalThreads[id]->setTimeout(timeout);
316
        return true;
317
        return true;
317
    }
318
    }
318
 
319
 
319
    return false;
320
    return false;
320
}
321
}
321
 
322
 
322
unsigned int VirtualMachine::startSocketThread(string address, int port, unsigned int reconnectTimeout)
323
unsigned int VirtualMachine::startSocketThread(string address, int port, unsigned int reconnectTimeout)
323
{
324
{
324
    SocketThread *socketThread = new SocketThread(address, port, reconnectTimeout);
325
    SocketThread *socketThread = new SocketThread(address, port, reconnectTimeout);
325
    mySocketThreads[socketThread->getId()] = socketThread;
326
    mySocketThreads[socketThread->getId()] = socketThread;
326
    mySocketThreads[socketThread->getId()]->start();
327
    mySocketThreads[socketThread->getId()]->start();
327
    mySocketThreads[socketThread->getId()]->startSocket();
328
    mySocketThreads[socketThread->getId()]->startSocket();
328
 
329
 
329
    return socketThread->getId();
330
    return socketThread->getId();
330
}
331
}
331
 
332
 
332
bool VirtualMachine::stopSocketThread(unsigned int id)
333
bool VirtualMachine::stopSocketThread(unsigned int id)
333
{
334
{
334
    if (mySocketThreads.find(id) != mySocketThreads.end())
335
    if (mySocketThreads.find(id) != mySocketThreads.end())
335
    {
336
    {
336
        delete mySocketThreads[id];
337
        delete mySocketThreads[id];
337
        mySocketThreads.erase(id);
338
        mySocketThreads.erase(id);
338
        return true;
339
        return true;
339
    }
340
    }
340
 
341
 
341
    return false;
342
    return false;
342
}
343
}
343
 
344
 
344
void VirtualMachine::sendToSocketThread(unsigned int id, string data)
345
void VirtualMachine::sendToSocketThread(unsigned int id, string data)
345
{
346
{
346
    if (mySocketThreads.find(id) != mySocketThreads.end())
347
    if (mySocketThreads.find(id) != mySocketThreads.end())
347
    {
348
    {
348
        mySocketThreads[id]->send(data);
349
        mySocketThreads[id]->send(data);
349
    }
350
    }
350
}
351
}
351
 
352
 
352
void VirtualMachine::disconnectCommandClient(unsigned int id)
353
void VirtualMachine::disconnectCommandClient(unsigned int id)
353
{
354
{
354
    myCommandThread.disconnectClient(id);
355
    myCommandThread.disconnectClient(id);
355
}
356
}
356
 
357
 
357
void VirtualMachine::sendToCommandClient(unsigned int id, string data)
358
void VirtualMachine::sendToCommandClient(unsigned int id, string data)
358
{
359
{
359
    myCommandThread.sendTo(id, data);
360
    myCommandThread.sendTo(id, data);
360
}
361
}
361
 
362
 
362
void VirtualMachine::print(unsigned int id, string data)
363
void VirtualMachine::print(unsigned int id, string data)
363
{
364
{
364
    if (id == 0)
365
    if (id == 0)
365
    {
366
    {
366
        Logger &log = Logger::getInstance();
367
        Logger &log = Logger::getInstance();
367
        log.add(data);
368
        log.add(data);
368
    }
369
    }
369
    else
370
    else
370
    {
371
    {
371
        VirtualMachine &vm = VirtualMachine::getInstance();
372
        VirtualMachine &vm = VirtualMachine::getInstance();
372
        vm.sendToCommandClient(id, data);
373
        vm.sendToCommandClient(id, data);
373
    }
374
    }
374
}
375
}
375
 
376
 
376
bool VirtualMachine::runExpression(Expression expression)
377
bool VirtualMachine::runExpression(Expression expression)
377
{
378
{
378
    string scriptName = "runExpression";
379
    string scriptName = "runExpression";
379
 
380
 
380
    string scriptData = expression.getScript();
381
    string scriptData = expression.getScript();
381
 
382
 
382
    scriptData = "setClientId(" + itos(expression.getTargetId()) + ");\n" + scriptData + "\n";
383
    scriptData = "setClientId(" + itos(expression.getTargetId()) + ");\n" + scriptData + "\n";
383
 
384
 
384
    Handle<String> source =  String::New(scriptData.c_str(), scriptData.length());
385
    Handle<String> source =  String::New(scriptData.c_str(), scriptData.length());
385
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
386
    Handle<String> name = String::New(scriptName.c_str(), scriptName.length());
386
 
387
 
387
    Context::Scope contextScope(myContext);
388
    Context::Scope contextScope(myContext);
388
 
389
 
389
    TryCatch tryCatch;
390
    TryCatch tryCatch;
390
 
391
 
391
    Handle<Script> script = Script::Compile(source, name);
392
    Handle<Script> script = Script::Compile(source, name);
392
 
393
 
393
    if (script.IsEmpty())
394
    if (script.IsEmpty())
394
    {
395
    {
395
        print(expression.getTargetId(), formatException(&tryCatch));
396
        print(expression.getTargetId(), formatException(&tryCatch));
396
        return false;
397
        return false;
397
    }
398
    }
398
    else
399
    else
399
    {
400
    {
400
        Handle<Value> result = script->Run();
401
        Handle<Value> result = script->Run();
401
 
402
 
402
        if (result.IsEmpty())
403
        if (result.IsEmpty())
403
        {
404
        {
404
            print(expression.getTargetId(), formatException(&tryCatch));
405
            print(expression.getTargetId(), formatException(&tryCatch));
405
            return false;
406
            return false;
406
        }
407
        }
407
        else if (expression.getTargetId() != 0)
408
        else if (expression.getTargetId() != 0)
408
        {
409
        {
409
             String::AsciiValue ascii(result);
410
             String::AsciiValue ascii(result);
410
             string resultString = *ascii;
411
             string resultString = *ascii;
411
 
412
 
412
             if (resultString != "undefined")
413
             if (resultString != "undefined")
413
             {
414
             {
414
                print(expression.getTargetId(), resultString + "\n");
415
                print(expression.getTargetId(), resultString + "\n");
415
             }
416
             }
416
        }
417
        }
417
    }
418
    }
418
 
419
 
419
    return true;
420
    return true;
420
}
421
}
421
 
422
 
422
 
423
 
423
Handle<Value> VirtualMachine::_quit(const Arguments& args)
424
Handle<Value> VirtualMachine::_quit(const Arguments& args)
424
{
425
{
425
    VirtualMachine &vm = VirtualMachine::getInstance();
426
    VirtualMachine &vm = VirtualMachine::getInstance();
426
 
427
 
427
    vm.disconnectCommandClient(args[0]->Uint32Value());
428
    vm.disconnectCommandClient(args[0]->Uint32Value());
428
 
429
 
429
    return Undefined();
430
    return Undefined();
430
}
431
}
431
 
432
 
432
Handle<Value> VirtualMachine::_log(const Arguments& args)
433
Handle<Value> VirtualMachine::_log(const Arguments& args)
433
{
434
{
434
    Logger &log = Logger::getInstance();
435
    Logger &log = Logger::getInstance();
435
 
436
 
436
    String::AsciiValue str(args[0]);
437
    String::AsciiValue str(args[0]);
437
 
438
 
438
    log.add(*str);
439
    log.add(*str);
439
 
440
 
440
    return Undefined();
441
    return Undefined();
441
}
442
}
442
 
443
 
443
Handle<Value> VirtualMachine::_print(const Arguments& args)
444
Handle<Value> VirtualMachine::_print(const Arguments& args)
444
{
445
{
445
    VirtualMachine &vm = VirtualMachine::getInstance();
446
    VirtualMachine &vm = VirtualMachine::getInstance();
446
 
447
 
447
    String::AsciiValue str(args[1]);
448
    String::AsciiValue str(args[1]);
448
 
449
 
449
    vm.print(args[0]->Uint32Value(), *str);
450
    vm.print(args[0]->Uint32Value(), *str);
450
 
451
 
451
    return Undefined();
452
    return Undefined();
452
}
453
}
453
 
454
 
454
Handle<Value> VirtualMachine::_sendCanMessage(const Arguments& args)
455
Handle<Value> VirtualMachine::_sendCanMessage(const Arguments& args)
455
{
456
{
456
    CanNetManager &canMan = CanNetManager::getInstance();
457
    CanNetManager &canMan = CanNetManager::getInstance();
457
 
458
 
458
    CanMessage canMessage;
459
    CanMessage canMessage;
459
 
460
 
460
    String::AsciiValue className(args[0]);
461
    String::AsciiValue className(args[0]);
461
    canMessage.setClassName(*className);
462
    canMessage.setClassName(*className);
462
    String::AsciiValue directionFlag(args[1]);
463
    String::AsciiValue directionFlag(args[1]);
463
    canMessage.setDirectionFlag(*directionFlag);
464
    canMessage.setDirectionFlag(*directionFlag);
464
    String::AsciiValue moduleName(args[2]);
465
    String::AsciiValue moduleName(args[2]);
465
    canMessage.setModuleName(*moduleName);
466
    canMessage.setModuleName(*moduleName);
466
    canMessage.setModuleId(args[3]->Uint32Value());
467
    canMessage.setModuleId(args[3]->Uint32Value());
467
    String::AsciiValue commandName(args[4]);
468
    String::AsciiValue commandName(args[4]);
468
    canMessage.setCommandName(*commandName);
469
    canMessage.setCommandName(*commandName);
469
 
470
 
470
    String::AsciiValue dataString(args[5]);
471
    String::AsciiValue dataString(args[5]);
471
 
472
 
472
    vector<string> parts = explode(",", trim(*dataString, ','));
473
    vector<string> parts = explode(",", trim(*dataString, ','));
473
    map<string, CanVariable> data;
474
    map<string, CanVariable> data;
474
 
475
 
475
    for (int n = 0; n < parts.size(); n++)
476
    for (int n = 0; n < parts.size(); n++)
476
    {
477
    {
477
        vector<string> keyAndValue = explode(":", parts[n]);
478
        vector<string> keyAndValue = explode(":", parts[n]);
478
 
479
 
479
        /* decode base64 on the data part */
480
        /* decode base64 on the data part */
480
        keyAndValue[1] = base64_decode(keyAndValue[1]);
481
        keyAndValue[1] = base64_decode(keyAndValue[1]);
481
 
482
 
482
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
483
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
483
    }
484
    }
484
 
485
 
485
    canMessage.setData(data);
486
    canMessage.setData(data);
486
   
487
   
487
    canMan.sendMessage(canMessage);
488
    canMan.sendMessage(canMessage);
488
 
489
 
489
    return Undefined();
490
    return Undefined();
490
}
491
}
491
 
492
 
492
Handle<Value> VirtualMachine::_sendCanNMTMessage(const Arguments& args)
493
Handle<Value> VirtualMachine::_sendCanNMTMessage(const Arguments& args)
493
{
494
{
494
    CanNetManager &canMan = CanNetManager::getInstance();
495
    CanNetManager &canMan = CanNetManager::getInstance();
495
 
496
 
496
    CanMessage canMessage;
497
    CanMessage canMessage;
497
 
498
 
498
    String::AsciiValue className(args[0]);
499
    String::AsciiValue className(args[0]);
499
    canMessage.setClassName(*className);
500
    canMessage.setClassName(*className);
500
    String::AsciiValue commandName(args[1]);
501
    String::AsciiValue commandName(args[1]);
501
    canMessage.setCommandName(*commandName);
502
    canMessage.setCommandName(*commandName);
502
 
503
 
503
    String::AsciiValue dataString(args[2]);
504
    String::AsciiValue dataString(args[2]);
504
 
505
 
505
    vector<string> parts = explode(",", trim(*dataString, ','));
506
    vector<string> parts = explode(",", trim(*dataString, ','));
506
    map<string, CanVariable> data;
507
    map<string, CanVariable> data;
507
 
508
 
508
    for (int n = 0; n < parts.size(); n++)
509
    for (int n = 0; n < parts.size(); n++)
509
    {
510
    {
510
        vector<string> keyAndValue = explode(":", parts[n]);
511
        vector<string> keyAndValue = explode(":", parts[n]);
511
 
512
 
512
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
513
        data[keyAndValue[0]] = CanVariable(keyAndValue[0], keyAndValue[1]);
513
    }
514
    }
514
 
515
 
515
    canMessage.setData(data);
516
    canMessage.setData(data);
516
 
517
 
517
    canMan.sendMessage(canMessage);
518
    canMan.sendMessage(canMessage);
518
 
519
 
519
    return Undefined();
520
    return Undefined();
520
}
521
}
521
 
522
 
522
Handle<Value> VirtualMachine::_loadScript(const Arguments& args)
523
Handle<Value> VirtualMachine::_loadScript(const Arguments& args)
523
{
524
{
524
    VirtualMachine &vm = VirtualMachine::getInstance();
525
    VirtualMachine &vm = VirtualMachine::getInstance();
525
 
526
 
526
    String::AsciiValue str(args[0]);
527
    String::AsciiValue str(args[0]);
527
 
528
 
528
    return Boolean::New(vm.loadScript(*str));
529
    return Boolean::New(vm.loadScript(*str));
529
}
530
}
530
 
531
 
531
Handle<Value> VirtualMachine::_loadDataStore(const Arguments& args)
532
Handle<Value> VirtualMachine::_loadDataStore(const Arguments& args)
532
{
533
{
533
    VirtualMachine &vm = VirtualMachine::getInstance();
534
    VirtualMachine &vm = VirtualMachine::getInstance();
534
 
535
 
535
    String::AsciiValue str(args[0]);
536
    String::AsciiValue str(args[0]);
536
 
537
 
537
    return Boolean::New(vm.loadDataStore(*str));
538
    return Boolean::New(vm.loadDataStore(*str));
538
}
539
}
539
 
540
 
540
Handle<Value> VirtualMachine::_startIntervalThread(const Arguments& args)
541
Handle<Value> VirtualMachine::_startIntervalThread(const Arguments& args)
541
{
542
{
542
    VirtualMachine &vm = VirtualMachine::getInstance();
543
    VirtualMachine &vm = VirtualMachine::getInstance();
543
    return Integer::New(vm.startIntervalThread(args[0]->Uint32Value()));
544
    return Integer::New(vm.startIntervalThread(args[0]->Uint32Value()));
544
}
545
}
545
 
546
 
546
Handle<Value> VirtualMachine::_stopIntervalThread(const Arguments& args)
547
Handle<Value> VirtualMachine::_stopIntervalThread(const Arguments& args)
547
{
548
{
548
    VirtualMachine &vm = VirtualMachine::getInstance();
549
    VirtualMachine &vm = VirtualMachine::getInstance();
549
    return Boolean::New(vm.stopIntervalThread(args[0]->Uint32Value()));
550
    return Boolean::New(vm.stopIntervalThread(args[0]->Uint32Value()));
550
}
551
}
551
 
552
 
552
Handle<Value> VirtualMachine::_setIntervalThreadTimeout(const Arguments& args)
553
Handle<Value> VirtualMachine::_setIntervalThreadTimeout(const Arguments& args)
553
{
554
{
554
    VirtualMachine &vm = VirtualMachine::getInstance();
555
    VirtualMachine &vm = VirtualMachine::getInstance();
555
    return Integer::New(vm.setIntervalThreadTimeout(args[0]->Uint32Value(), args[1]->Uint32Value()));
556
    return Integer::New(vm.setIntervalThreadTimeout(args[0]->Uint32Value(), args[1]->Uint32Value()));
556
}
557
}
557
 
558
 
558
Handle<Value> VirtualMachine::_startSocketThread(const Arguments& args)
559
Handle<Value> VirtualMachine::_startSocketThread(const Arguments& args)
559
{
560
{
560
    VirtualMachine &vm = VirtualMachine::getInstance();
561
    VirtualMachine &vm = VirtualMachine::getInstance();
561
 
562
 
562
    String::AsciiValue address(args[0]);
563
    String::AsciiValue address(args[0]);
563
 
564
 
564
    return Integer::New(vm.startSocketThread(*address, args[1]->Uint32Value(), args[2]->Uint32Value()));
565
    return Integer::New(vm.startSocketThread(*address, args[1]->Uint32Value(), args[2]->Uint32Value()));
565
}
566
}
566
 
567
 
567
Handle<Value> VirtualMachine::_stopSocketThread(const Arguments& args)
568
Handle<Value> VirtualMachine::_stopSocketThread(const Arguments& args)
568
{
569
{
569
    VirtualMachine &vm = VirtualMachine::getInstance();
570
    VirtualMachine &vm = VirtualMachine::getInstance();
570
 
571
 
571
    return Boolean::New(vm.stopSocketThread(args[0]->Uint32Value()));
572
    return Boolean::New(vm.stopSocketThread(args[0]->Uint32Value()));
572
}
573
}
573
 
574
 
574
Handle<Value> VirtualMachine::_sendToSocketThread(const Arguments& args)
575
Handle<Value> VirtualMachine::_sendToSocketThread(const Arguments& args)
575
{
576
{
576
    VirtualMachine &vm = VirtualMachine::getInstance();
577
    VirtualMachine &vm = VirtualMachine::getInstance();
577
 
578
 
578
    String::AsciiValue data(args[1]);
579
    String::AsciiValue data(args[1]);
579
 
580
 
580
    vm.sendToSocketThread(args[0]->Uint32Value(), *data);
581
    vm.sendToSocketThread(args[0]->Uint32Value(), *data);
581
 
582
 
582
    return Undefined();
583
    return Undefined();
583
}
584
}
584
 
585
 
585
Handle<Value> VirtualMachine::_getFileContents(const Arguments& args)
586
Handle<Value> VirtualMachine::_getFileContents(const Arguments& args)
586
{
587
{
587
    String::AsciiValue filename(args[0]);
588
    String::AsciiValue filename(args[0]);
588
 
589
 
589
    if (!file_exists(*filename))
590
    if (!file_exists(*filename))
590
    {
591
    {
591
        return Undefined();
592
        return Undefined();
592
    }
593
    }
593
 
594
 
594
    string content = file_get_contents(*filename);
595
    string content = file_get_contents(*filename);
595
 
596
 
596
    return String::New(content.c_str());
597
    return String::New(content.c_str());
-
 
598
}
-
 
599
 
-
 
600
Handle<Value> VirtualMachine::_setFileContents(const Arguments& args)
-
 
601
{
-
 
602
    String::AsciiValue filename(args[0]);
-
 
603
    String::AsciiValue content(args[1]);
-
 
604
 
-
 
605
    std::ofstream dstfile(*filename);
-
 
606
 
-
 
607
    if (!dstfile.is_open())
-
 
608
    {
-
 
609
        dstfile.close();
-
 
610
        return Undefined();
-
 
611
    }
-
 
612
 
-
 
613
    dstfile << *content;
-
 
614
    dstfile.close();
-
 
615
 
-
 
616
    return Undefined();
597
}
617
}
598
 
618
 
599
#include <string>
619
#include <string>
600
#include <iostream>
620
#include <iostream>
601
#include <stdio.h>
621
#include <stdio.h>
602
 
622
 
603
std::string exec(string cmd) {
623
std::string exec(string cmd) {
604
    FILE* pipe = popen(cmd.c_str(), "r");
624
    FILE* pipe = popen(cmd.c_str(), "r");
605
    if (!pipe) return "ERROR";
625
    if (!pipe) return "ERROR";
606
    char buffer[128];
626
    char buffer[128];
607
    std::string result = "";
627
    std::string result = "";
608
    while(!feof(pipe)) {
628
    while(!feof(pipe)) {
609
        if(fgets(buffer, 128, pipe) != NULL)
629
        if(fgets(buffer, 128, pipe) != NULL)
610
                result += buffer;
630
                result += buffer;
611
    }
631
    }
612
    pclose(pipe);
632
    pclose(pipe);
613
    return result;
633
    return result;
614
}
634
}
615
 
635
 
616
Handle<Value> VirtualMachine::_system(const Arguments& args)
636
Handle<Value> VirtualMachine::_system(const Arguments& args)
617
{
637
{
618
    String::AsciiValue command(args[0]);
638
    String::AsciiValue command(args[0]);
619
   
639
   
620
    string output = exec(*command);
640
    string output = exec(*command);
621
   
641
   
622
    return String::New(output.c_str());
642
    return String::New(output.c_str());
623
}
643
}
624
 
644
 
625
Handle<Value> VirtualMachine::_uint2hex(const Arguments& args)
645
Handle<Value> VirtualMachine::_uint2hex(const Arguments& args)
626
{
646
{
627
    string hex = uint2hex(args[0]->Uint32Value(), args[1]->Uint32Value());
647
    string hex = uint2hex(args[0]->Uint32Value(), args[1]->Uint32Value());
628
    return String::New(hex.c_str());
648
    return String::New(hex.c_str());
629
}
649
}
630
 
650
 
631
Handle<Value> VirtualMachine::_hex2bin(const Arguments& args)
651
Handle<Value> VirtualMachine::_hex2bin(const Arguments& args)
632
{
652
{
633
    String::AsciiValue hex(args[0]);
653
    String::AsciiValue hex(args[0]);
634
    string bin = hex2bin(*hex);
654
    string bin = hex2bin(*hex);
635
    return String::New(bin.c_str());
655
    return String::New(bin.c_str());
636
}
656
}
637
 
657
 
638
Handle<Value> VirtualMachine::_bin2hex(const Arguments& args)
658
Handle<Value> VirtualMachine::_bin2hex(const Arguments& args)
639
{
659
{
640
    String::AsciiValue bin(args[0]);
660
    String::AsciiValue bin(args[0]);
641
    string hex = bin2hex(*bin);
661
    string hex = bin2hex(*bin);
642
    return String::New(hex.c_str());
662
    return String::New(hex.c_str());
643
}
663
}
644
 
664
 
645
Handle<Value> VirtualMachine::_bin2float(const Arguments& args)
665
Handle<Value> VirtualMachine::_bin2float(const Arguments& args)
646
{
666
{
647
    String::AsciiValue bin(args[0]);
667
    String::AsciiValue bin(args[0]);
648
    float f = bin2float(*bin);
668
    float f = bin2float(*bin);
649
    return Number::New(f);
669
    return Number::New(f);
650
}
670
}
651
 
671
 
652
Handle<Value> VirtualMachine::_float2bin(const Arguments& args)
672
Handle<Value> VirtualMachine::_float2bin(const Arguments& args)
653
{
673
{
654
    string bin = float2bin(args[0]->NumberValue(), args[1]->Uint32Value());
674
    string bin = float2bin(args[0]->NumberValue(), args[1]->Uint32Value());
655
    return String::New(bin.c_str());
675
    return String::New(bin.c_str());
656
}
676
}
657
 
677
 
658
Handle<Value> VirtualMachine::_bin2uint(const Arguments& args)
678
Handle<Value> VirtualMachine::_bin2uint(const Arguments& args)
659
{
679
{
660
    String::AsciiValue bin(args[0]);
680
    String::AsciiValue bin(args[0]);
661
    unsigned int num = bin2uint(*bin);
681
    unsigned int num = bin2uint(*bin);
662
    return Number::New(num);
682
    return Number::New(num);
663
}
683
}
664
 
684
 
665
Handle<Value> VirtualMachine::_uint2bin(const Arguments& args)
685
Handle<Value> VirtualMachine::_uint2bin(const Arguments& args)
666
{
686
{
667
    string bin = uint2bin(args[0]->Uint32Value(), args[1]->Uint32Value());
687
    string bin = uint2bin(args[0]->Uint32Value(), args[1]->Uint32Value());
668
    return String::New(bin.c_str());
688
    return String::New(bin.c_str());
669
}
689
}
670
 
690
 
671
Handle<Value> VirtualMachine::_hex2uint(const Arguments& args)
691
Handle<Value> VirtualMachine::_hex2uint(const Arguments& args)
672
{
692
{
673
    String::AsciiValue hex(args[0]);
693
    String::AsciiValue hex(args[0]);
674
    unsigned int num = hex2uint(*hex);
694
    unsigned int num = hex2uint(*hex);
675
    return Number::New(num);
695
    return Number::New(num);
676
}
696
}
677
 
697
 
678
Handle<Value> VirtualMachine::_sleep(const Arguments& args)
698
Handle<Value> VirtualMachine::_sleep(const Arguments& args)
679
{
699
{
680
    usleep(args[0]->Uint32Value());
700
    usleep(args[0]->Uint32Value());
681
    return Undefined();
701
    return Undefined();
682
}
702
}
683
 
703