Subversion Repositories HomeAutomation

Rev

Rev 1648 | Rev 1664 | 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);
1608 runge 49
 
50
    try
51
    {
52
        this->server_id_ = net::Manager::Instance()->StartServer(net::PROTOCOL_TCP, port);
53
        LOG.Info("Started TCP server on port " + boost::lexical_cast<std::string>(port) + ".");
54
        LOG.Debug("Server id is " + boost::lexical_cast<std::string>(this->server_id_) + ".");
55
    }
56
    catch (std::runtime_error& e)
57
    {
58
        LOG.Error(e.what());
59
    }
60
}
61
 
62
Console::~Console()
63
{
64
    net::Manager::Instance()->StopServer(this->server_id_);
65
    this->server_id_ = 0;
66
}
67
 
68
void Console::InitializeDone()
69
{
70
    Plugin::InitializeDone();
1609 runge 71
 
1647 runge 72
    this->ImportFunction("Console_AutocompleteRequest");
1620 runge 73
    this->ImportFunction("Console_PromptResponse");
1647 runge 74
    this->ImportFunction("Console_NewConnection");
1608 runge 75
}
76
 
1647 runge 77
void Console::CallOutput(unsigned int request_id, std::string output)
78
{
79
    std::string packet = "TEXT";
80
    packet += common::PadNumber(output.length() + 1, 4);
81
    packet += output;
82
 
83
    net::Manager::Instance()->SendTo(request_id, packet);
84
}
85
 
1642 runge 86
void Console::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
1608 runge 87
{
88
    if (server_id != this->server_id_)
89
    {
90
        return;
91
    }
92
 
1625 runge 93
    this->io_service_.post(boost::bind(&Console::SlotOnNewDataHandler, this, client_id, server_id, data));
94
}
95
 
96
void Console::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
97
{
98
    if (server_id != this->server_id_)
99
    {
100
        return;
101
    }
102
 
103
    this->io_service_.post(boost::bind(&Console::SlotOnNewStateHandler, this, client_id, server_id, client_state));
104
}
105
 
1642 runge 106
void Console::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
1625 runge 107
{
108
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
109
 
1647 runge 110
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 111
 
1647 runge 112
    std::string s(data.ToCharString());
1608 runge 113
 
1647 runge 114
    std::string command = s.substr(0, 4);
115
    unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
116
 
117
    Console::current_client_id_ = client_id;
1608 runge 118
 
1647 runge 119
    if (command == "COMP")
1608 runge 120
    {
1647 runge 121
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
1608 runge 122
 
1647 runge 123
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
124
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(s.substr(8, 4))));
125
        call_arguments->push_back(v8::String::New(s.substr(12).data()));
1608 runge 126
 
1647 runge 127
        if (!this->Call(client_id, "Console_AutocompleteRequest", call_arguments))
1608 runge 128
        {
1647 runge 129
            LOG.Error("Console_AutocompleteRequest failed, we are now in an undefined state!");
1608 runge 130
        }
131
    }
1647 runge 132
    else if (command == "RESP")
1608 runge 133
    {
134
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
135
 
1647 runge 136
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
137
        call_arguments->push_back(v8::String::New(s.substr(8).data()));
1608 runge 138
 
1647 runge 139
        if (!this->Call(client_id, "Console_PromptResponse", call_arguments))
1608 runge 140
        {
1647 runge 141
            LOG.Error("Console_PromptResponse failed, we are now in an undefined state!");
1608 runge 142
        }
143
    }
1647 runge 144
    else
1620 runge 145
    {
1647 runge 146
        LOG.Error("Unknown packat received, we are now in an undefined state!");
1620 runge 147
    }
1647 runge 148
 
149
    Console::current_client_id_ = 0;
1608 runge 150
}
151
 
1625 runge 152
void Console::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
1608 runge 153
{
1625 runge 154
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
155
 
1647 runge 156
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1608 runge 157
 
158
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
159
    {
160
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has disconnected.");
161
    }
162
    else if (client_state == net::CLIENT_STATE_CONNECTED)
163
    {
164
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has connected.");
1647 runge 165
 
166
        Console::current_client_id_ = client_id;
167
 
168
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
169
 
170
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
171
 
172
        if (!this->Call(client_id, "Console_NewConnection", call_arguments))
173
        {
174
            LOG.Error("Console_NewConnection failed, we are now in an undefined state!");
175
        }
176
 
177
        Console::current_client_id_ = 0;
1608 runge 178
    }
179
    else
180
    {
181
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
182
    }
183
}
184
 
1647 runge 185
Value Console::Export_PromptRequest(const v8::Arguments& args)
1608 runge 186
{
1625 runge 187
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
188
 
1648 runge 189
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 190
 
1647 runge 191
    if (args.Length() < 2)
192
    {
193
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
194
        return v8::Boolean::New(false);
195
    }
196
 
197
    v8::String::AsciiValue prompt(args[1]);
198
 
199
    std::string packet = "PROM";
200
    packet += common::PadNumber(prompt.length() + 1, 4);
201
    packet += *prompt;
202
 
203
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 204
    return v8::Boolean::New(true);
1608 runge 205
}
206
 
1647 runge 207
Value Console::Export_AutoCompleteResponse(const v8::Arguments& args)
1608 runge 208
{
1625 runge 209
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
210
 
1648 runge 211
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
1625 runge 212
 
1647 runge 213
    if (args.Length() < 2)
1608 runge 214
    {
1647 runge 215
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
216
        return v8::Boolean::New(false);
1608 runge 217
    }
218
 
1647 runge 219
    v8::String::AsciiValue result(args[1]);
1608 runge 220
 
1647 runge 221
    std::string packet = "COMP";
222
    packet += common::PadNumber(result.length() + 1, 4);
223
    packet += *result;
1608 runge 224
 
1647 runge 225
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
1657 runge 226
    return v8::Boolean::New(true);
227
}
228
 
229
Value Console::Export_LogToClient(const v8::Arguments& args)
230
{
231
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
1608 runge 232
 
1657 runge 233
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
234
 
235
    if (args.Length() < 2)
236
    {
237
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
238
        return v8::Boolean::New(false);
239
    }
240
 
241
    v8::String::AsciiValue text(args[1]);
242
 
243
    std::string line = *text;
244
 
245
    std::string packet = "TEXT";
246
    packet += common::PadNumber(line.length() + 1, 4);
247
    packet += line;
248
 
249
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
250
    return v8::Boolean::New(true);
1608 runge 251
}
252
 
253
}; // namespace plugin
254
}; // namespace vm
255
}; // namespace atom