Subversion Repositories HomeAutomation

Rev

Rev 1405 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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