Subversion Repositories HomeAutomation

Rev

Rev 1664 | Rev 1741 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1608 runge 1
/*
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License along
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 */
20
 
21
#include "Console.h"
22
 
23
#include <boost/lexical_cast.hpp>
24
#include <boost/algorithm/string/trim.hpp>
25
#include <boost/algorithm/string/split.hpp>
26
 
27
#include "net/Manager.h"
1625 runge 28
#include "vm/Manager.h"
1647 runge 29
#include "common/common.h"
1608 runge 30
 
31
namespace atom {
32
namespace vm {
33
namespace plugin {
34
 
35
logging::Logger Console::LOG("vm::plugin::Console");
1647 runge 36
net::ClientId Console::current_client_id_;
1608 runge 37
 
1625 runge 38
Console::Console(boost::asio::io_service& io_service, unsigned int port) : Plugin(io_service)
1608 runge 39
{
40
    this->name_ = "console";
1647 runge 41
    Console::current_client_id_ = 0;
1608 runge 42
 
43
    net::Manager::Instance()->ConnectSlots(net::Manager::SignalOnNewState::slot_type(&Console::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
44
                                           net::Manager::SignalOnNewData::slot_type(&Console::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
45
 
1657 runge 46
    this->ExportFunction("ConsoleExport_PromptRequest",        Console::Export_PromptRequest);
1647 runge 47
    this->ExportFunction("ConsoleExport_AutoCompleteResponse", Console::Export_AutoCompleteResponse);
1657 runge 48
    this->ExportFunction("ConsoleExport_LogToClient",          Console::Export_LogToClient);
1664 runge 49
    this->ExportFunction("ConsoleExport_DisconnectClient",     Console::Export_DisconnectClient);
1608 runge 50
 
51
    try
52
    {
53
        this->server_id_ = net::Manager::Instance()->StartServer(net::PROTOCOL_TCP, port);
54
        LOG.Info("Started TCP server on port " + boost::lexical_cast<std::string>(port) + ".");
55
        LOG.Debug("Server id is " + boost::lexical_cast<std::string>(this->server_id_) + ".");
56
    }
57
    catch (std::runtime_error& e)
58
    {
59
        LOG.Error(e.what());
60
    }
61
}
62
 
63
Console::~Console()
64
{
65
    net::Manager::Instance()->StopServer(this->server_id_);
66
    this->server_id_ = 0;
67
}
68
 
69
void Console::InitializeDone()
70
{
71
    Plugin::InitializeDone();
1609 runge 72
 
1647 runge 73
    this->ImportFunction("Console_AutocompleteRequest");
1620 runge 74
    this->ImportFunction("Console_PromptResponse");
1647 runge 75
    this->ImportFunction("Console_NewConnection");
1608 runge 76
}
77
 
1647 runge 78
void Console::CallOutput(unsigned int request_id, std::string output)
79
{
80
    std::string packet = "TEXT";
81
    packet += common::PadNumber(output.length() + 1, 4);
82
    packet += output;
83
 
84
    net::Manager::Instance()->SendTo(request_id, packet);
85
}
86
 
1642 runge 87
void Console::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
1608 runge 88
{
89
    if (server_id != this->server_id_)
90
    {
91
        return;
92
    }
93
 
1625 runge 94
    this->io_service_.post(boost::bind(&Console::SlotOnNewDataHandler, this, client_id, server_id, data));
95
}
96
 
97
void Console::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
98
{
99
    if (server_id != this->server_id_)
100
    {
101
        return;
102
    }
103
 
104
    this->io_service_.post(boost::bind(&Console::SlotOnNewStateHandler, this, client_id, server_id, client_state));
105
}
106
 
1642 runge 107
void Console::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
1625 runge 108
{
1740 runge 109
    v8::Locker lock;
1625 runge 110
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
111
 
1647 runge 112
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 113
 
1647 runge 114
    std::string s(data.ToCharString());
1608 runge 115
 
1647 runge 116
    std::string command = s.substr(0, 4);
117
    unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
118
 
119
    Console::current_client_id_ = client_id;
1608 runge 120
 
1647 runge 121
    if (command == "COMP")
1608 runge 122
    {
1647 runge 123
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
1608 runge 124
 
1647 runge 125
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
126
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(s.substr(8, 4))));
127
        call_arguments->push_back(v8::String::New(s.substr(12).data()));
1608 runge 128
 
1647 runge 129
        if (!this->Call(client_id, "Console_AutocompleteRequest", call_arguments))
1608 runge 130
        {
1647 runge 131
            LOG.Error("Console_AutocompleteRequest failed, we are now in an undefined state!");
1608 runge 132
        }
133
    }
1647 runge 134
    else if (command == "RESP")
1608 runge 135
    {
136
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
137
 
1647 runge 138
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
139
        call_arguments->push_back(v8::String::New(s.substr(8).data()));
1608 runge 140
 
1647 runge 141
        if (!this->Call(client_id, "Console_PromptResponse", call_arguments))
1608 runge 142
        {
1647 runge 143
            LOG.Error("Console_PromptResponse failed, we are now in an undefined state!");
1608 runge 144
        }
145
    }
1647 runge 146
    else
1620 runge 147
    {
1647 runge 148
        LOG.Error("Unknown packat received, we are now in an undefined state!");
1620 runge 149
    }
1647 runge 150
 
151
    Console::current_client_id_ = 0;
1608 runge 152
}
153
 
1625 runge 154
void Console::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
1608 runge 155
{
1740 runge 156
    v8::Locker lock;
1625 runge 157
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
158
 
1647 runge 159
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1608 runge 160
 
161
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
162
    {
163
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has disconnected.");
164
    }
165
    else if (client_state == net::CLIENT_STATE_CONNECTED)
166
    {
167
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has connected.");
1647 runge 168
 
169
        Console::current_client_id_ = client_id;
170
 
171
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
172
 
173
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
174
 
175
        if (!this->Call(client_id, "Console_NewConnection", call_arguments))
176
        {
177
            LOG.Error("Console_NewConnection failed, we are now in an undefined state!");
178
        }
179
 
180
        Console::current_client_id_ = 0;
1608 runge 181
    }
182
    else
183
    {
184
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
185
    }
186
}
187
 
1647 runge 188
Value Console::Export_PromptRequest(const v8::Arguments& args)
1608 runge 189
{
1740 runge 190
    v8::Locker lock;
1625 runge 191
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
192
 
1648 runge 193
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 194
 
1647 runge 195
    if (args.Length() < 2)
196
    {
197
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
198
        return v8::Boolean::New(false);
199
    }
200
 
201
    v8::String::AsciiValue prompt(args[1]);
202
 
203
    std::string packet = "PROM";
204
    packet += common::PadNumber(prompt.length() + 1, 4);
205
    packet += *prompt;
206
 
207
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 208
    return v8::Boolean::New(true);
1608 runge 209
}
210
 
1647 runge 211
Value Console::Export_AutoCompleteResponse(const v8::Arguments& args)
1608 runge 212
{
1740 runge 213
    v8::Locker lock;
1625 runge 214
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
215
 
1648 runge 216
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 217
 
1647 runge 218
    if (args.Length() < 2)
1608 runge 219
    {
1647 runge 220
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
221
        return v8::Boolean::New(false);
1608 runge 222
    }
223
 
1647 runge 224
    v8::String::AsciiValue result(args[1]);
1608 runge 225
 
1647 runge 226
    std::string packet = "COMP";
227
    packet += common::PadNumber(result.length() + 1, 4);
228
    packet += *result;
1608 runge 229
 
1647 runge 230
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 231
    return v8::Boolean::New(true);
232
}
233
 
234
Value Console::Export_LogToClient(const v8::Arguments& args)
235
{
1740 runge 236
    v8::Locker lock;
1657 runge 237
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
1608 runge 238
 
1657 runge 239
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
240
 
241
    if (args.Length() < 2)
242
    {
243
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
244
        return v8::Boolean::New(false);
245
    }
246
 
247
    v8::String::AsciiValue text(args[1]);
248
 
249
    std::string line = *text;
250
 
251
    std::string packet = "TEXT";
252
    packet += common::PadNumber(line.length() + 1, 4);
253
    packet += line;
254
 
255
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
256
    return v8::Boolean::New(true);
1608 runge 257
}
258
 
1664 runge 259
Value Console::Export_DisconnectClient(const v8::Arguments& args)
260
{
1740 runge 261
    v8::Locker lock;
1664 runge 262
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
263
 
264
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
265
 
266
    if (args.Length() < 1)
267
    {
268
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
269
        return v8::Boolean::New(false);
270
    }
271
    net::Manager::Instance()->Disconnect(args[0]->Uint32Value());
272
    return v8::Boolean::New(true);
273
}
274
 
1608 runge 275
}; // namespace plugin
276
}; // namespace vm
277
}; // namespace atom