Subversion Repositories HomeAutomation

Rev

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