Subversion Repositories HomeAutomation

Rev

Rev 1657 | Rev 1740 | 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
{
109
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
110
 
1647 runge 111
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 112
 
1647 runge 113
    std::string s(data.ToCharString());
1608 runge 114
 
1647 runge 115
    std::string command = s.substr(0, 4);
116
    unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
117
 
118
    Console::current_client_id_ = client_id;
1608 runge 119
 
1647 runge 120
    if (command == "COMP")
1608 runge 121
    {
1647 runge 122
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
1608 runge 123
 
1647 runge 124
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
125
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(s.substr(8, 4))));
126
        call_arguments->push_back(v8::String::New(s.substr(12).data()));
1608 runge 127
 
1647 runge 128
        if (!this->Call(client_id, "Console_AutocompleteRequest", call_arguments))
1608 runge 129
        {
1647 runge 130
            LOG.Error("Console_AutocompleteRequest failed, we are now in an undefined state!");
1608 runge 131
        }
132
    }
1647 runge 133
    else if (command == "RESP")
1608 runge 134
    {
135
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
136
 
1647 runge 137
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
138
        call_arguments->push_back(v8::String::New(s.substr(8).data()));
1608 runge 139
 
1647 runge 140
        if (!this->Call(client_id, "Console_PromptResponse", call_arguments))
1608 runge 141
        {
1647 runge 142
            LOG.Error("Console_PromptResponse failed, we are now in an undefined state!");
1608 runge 143
        }
144
    }
1647 runge 145
    else
1620 runge 146
    {
1647 runge 147
        LOG.Error("Unknown packat received, we are now in an undefined state!");
1620 runge 148
    }
1647 runge 149
 
150
    Console::current_client_id_ = 0;
1608 runge 151
}
152
 
1625 runge 153
void Console::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
1608 runge 154
{
1625 runge 155
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
156
 
1647 runge 157
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1608 runge 158
 
159
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
160
    {
161
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has disconnected.");
162
    }
163
    else if (client_state == net::CLIENT_STATE_CONNECTED)
164
    {
165
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has connected.");
1647 runge 166
 
167
        Console::current_client_id_ = client_id;
168
 
169
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
170
 
171
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
172
 
173
        if (!this->Call(client_id, "Console_NewConnection", call_arguments))
174
        {
175
            LOG.Error("Console_NewConnection failed, we are now in an undefined state!");
176
        }
177
 
178
        Console::current_client_id_ = 0;
1608 runge 179
    }
180
    else
181
    {
182
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
183
    }
184
}
185
 
1647 runge 186
Value Console::Export_PromptRequest(const v8::Arguments& args)
1608 runge 187
{
1625 runge 188
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
189
 
1648 runge 190
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 191
 
1647 runge 192
    if (args.Length() < 2)
193
    {
194
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
195
        return v8::Boolean::New(false);
196
    }
197
 
198
    v8::String::AsciiValue prompt(args[1]);
199
 
200
    std::string packet = "PROM";
201
    packet += common::PadNumber(prompt.length() + 1, 4);
202
    packet += *prompt;
203
 
204
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 205
    return v8::Boolean::New(true);
1608 runge 206
}
207
 
1647 runge 208
Value Console::Export_AutoCompleteResponse(const v8::Arguments& args)
1608 runge 209
{
1625 runge 210
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
211
 
1648 runge 212
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 213
 
1647 runge 214
    if (args.Length() < 2)
1608 runge 215
    {
1647 runge 216
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
217
        return v8::Boolean::New(false);
1608 runge 218
    }
219
 
1647 runge 220
    v8::String::AsciiValue result(args[1]);
1608 runge 221
 
1647 runge 222
    std::string packet = "COMP";
223
    packet += common::PadNumber(result.length() + 1, 4);
224
    packet += *result;
1608 runge 225
 
1647 runge 226
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 227
    return v8::Boolean::New(true);
228
}
229
 
230
Value Console::Export_LogToClient(const v8::Arguments& args)
231
{
232
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
1608 runge 233
 
1657 runge 234
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
235
 
236
    if (args.Length() < 2)
237
    {
238
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
239
        return v8::Boolean::New(false);
240
    }
241
 
242
    v8::String::AsciiValue text(args[1]);
243
 
244
    std::string line = *text;
245
 
246
    std::string packet = "TEXT";
247
    packet += common::PadNumber(line.length() + 1, 4);
248
    packet += line;
249
 
250
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
251
    return v8::Boolean::New(true);
1608 runge 252
}
253
 
1664 runge 254
Value Console::Export_DisconnectClient(const v8::Arguments& args)
255
{
256
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
257
 
258
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
259
 
260
    if (args.Length() < 1)
261
    {
262
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
263
        return v8::Boolean::New(false);
264
    }
265
    net::Manager::Instance()->Disconnect(args[0]->Uint32Value());
266
    return v8::Boolean::New(true);
267
}
268
 
1608 runge 269
}; // namespace plugin
270
}; // namespace vm
271
}; // namespace atom