Subversion Repositories HomeAutomation

Rev

Rev 1644 | Rev 1648 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1644 Rev 1647
Line 24... Line 24...
24
#include <boost/algorithm/string/trim.hpp>
24
#include <boost/algorithm/string/trim.hpp>
25
#include <boost/algorithm/string/split.hpp>
25
#include <boost/algorithm/string/split.hpp>
26
 
26
 
27
#include "net/Manager.h"
27
#include "net/Manager.h"
28
#include "vm/Manager.h"
28
#include "vm/Manager.h"
-
 
29
#include "common/common.h"
29
 
30
 
30
namespace atom {
31
namespace atom {
31
namespace vm {
32
namespace vm {
32
namespace plugin {
33
namespace plugin {
33
   
34
   
34
logging::Logger Console::LOG("vm::plugin::Console");
35
logging::Logger Console::LOG("vm::plugin::Console");
35
common::StringList Console::commands_;
36
net::ClientId Console::current_client_id_;
36
   
37
   
37
Console::Console(boost::asio::io_service& io_service, unsigned int port) : Plugin(io_service)
38
Console::Console(boost::asio::io_service& io_service, unsigned int port) : Plugin(io_service)
38
{
39
{
39
    this->name_ = "console";
40
    this->name_ = "console";
-
 
41
    Console::current_client_id_ = 0;
40
   
42
   
41
    net::Manager::Instance()->ConnectSlots(net::Manager::SignalOnNewState::slot_type(&Console::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
43
    net::Manager::Instance()->ConnectSlots(net::Manager::SignalOnNewState::slot_type(&Console::SlotOnNewState, this, _1, _2, _3).track(this->tracker_),
42
                                           net::Manager::SignalOnNewData::slot_type(&Console::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
44
                                           net::Manager::SignalOnNewData::slot_type(&Console::SlotOnNewData, this, _1, _2, _3).track(this->tracker_));
43
   
45
   
44
    this->ExportFunction("ConsoleExport_RegisterCommand", Console::Export_RegisterCommand);
46
    this->ExportFunction("ConsoleExport_PromptRequest", Console::Export_PromptRequest);
-
 
47
    this->ExportFunction("ConsoleExport_AutoCompleteResponse", Console::Export_AutoCompleteResponse);
45
   
48
   
46
    try
49
    try
47
    {
50
    {
48
        this->server_id_ = net::Manager::Instance()->StartServer(net::PROTOCOL_TCP, port);
51
        this->server_id_ = net::Manager::Instance()->StartServer(net::PROTOCOL_TCP, port);
49
        LOG.Info("Started TCP server on port " + boost::lexical_cast<std::string>(port) + ".");
52
        LOG.Info("Started TCP server on port " + boost::lexical_cast<std::string>(port) + ".");
Line 63... Line 66...
63
 
66
 
64
void Console::InitializeDone()
67
void Console::InitializeDone()
65
{
68
{
66
    Plugin::InitializeDone();
69
    Plugin::InitializeDone();
67
   
70
   
68
    this->ImportFunction("Console_DoAutocomplete");
71
    this->ImportFunction("Console_AutocompleteRequest");
69
    this->ImportFunction("Console_PromptResponse");
72
    this->ImportFunction("Console_PromptResponse");
-
 
73
    this->ImportFunction("Console_NewConnection");
70
}
74
}
71
 
75
 
-
 
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
 
72
void Console::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
85
void Console::SlotOnNewData(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
73
{
86
{
74
    if (server_id != this->server_id_)
87
    if (server_id != this->server_id_)
75
    {
88
    {
76
        return;
89
        return;
77
    }
90
    }
78
   
91
   
79
    this->io_service_.post(boost::bind(&Console::SlotOnNewDataHandler, this, client_id, server_id, data));
92
    this->io_service_.post(boost::bind(&Console::SlotOnNewDataHandler, this, client_id, server_id, data));
80
}
93
}
81
 
94
 
82
void Console::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
95
void Console::SlotOnNewState(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
83
{
96
{
84
    if (server_id != this->server_id_)
97
    if (server_id != this->server_id_)
85
    {
98
    {
86
        return;
99
        return;
87
    }
100
    }
88
   
101
   
89
    this->io_service_.post(boost::bind(&Console::SlotOnNewStateHandler, this, client_id, server_id, client_state));
102
    this->io_service_.post(boost::bind(&Console::SlotOnNewStateHandler, this, client_id, server_id, client_state));
90
}
103
}
91
 
104
 
92
void Console::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
105
void Console::SlotOnNewDataHandler(net::ClientId client_id, net::ServerId server_id, common::Byteset data)
93
{
106
{
94
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
107
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
95
 
108
 
96
    LOG.Debug(std::string(__FUNCTION__) + " called!");
109
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
97
 
110
 
98
    std::string str(data.ToCharString());
111
    std::string s(data.ToCharString());
99
   
112
   
100
    boost::algorithm::trim_right_if(str, boost::is_any_of("\r\n"));
113
    std::string command = s.substr(0, 4);
101
   
-
 
102
    common::StringList parts;
114
    unsigned int payload_length = boost::lexical_cast<unsigned int>(s.substr(4, 4));
103
   
115
 
104
    boost::algorithm::split(parts, str, boost::is_any_of(";"), boost::algorithm::token_compress_off);
116
    Console::current_client_id_ = client_id;
105
   
117
   
106
    if (parts[0] == "A") // Autocomplete
118
    if (command == "COMP")
107
    {
119
    {
108
        unsigned int arg_index = boost::lexical_cast<unsigned int>(parts[1]);
120
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
109
       
-
 
110
        std::string result;
-
 
111
        common::StringList arguments;
-
 
112
       
121
       
113
        boost::algorithm::split(arguments, parts[2], boost::is_any_of(" "), boost::algorithm::token_compress_on);
122
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
114
       
-
 
115
        if (arg_index == 0)
-
 
116
        {
-
 
117
            for (unsigned int n = 0; n < this->commands_.size(); n++)
123
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(s.substr(8, 4))));
118
            {
-
 
119
                //LOG.Debug(this->commands_[n]);
-
 
120
                result += this->commands_[n] + "\n";
-
 
121
            }
-
 
122
           
-
 
123
            net::Manager::Instance()->SendTo(client_id, result);
124
        call_arguments->push_back(v8::String::New(s.substr(12).data()));
124
        }
-
 
125
        else
-
 
126
        {
125
       
127
            ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
126
        if (!this->Call(client_id, "Console_AutocompleteRequest", call_arguments))
128
            common::StringList arguments;
-
 
129
           
-
 
130
            boost::algorithm::split(arguments, parts[2], boost::is_any_of(" "), boost::algorithm::token_compress_on);
-
 
131
           
-
 
132
            for (unsigned int n = 0; n < arguments.size() && n <= arg_index; n++)
-
 
133
            {
127
        {
134
                call_arguments->push_back(v8::String::New(arguments[n].data()));
-
 
135
            }
-
 
136
           
-
 
137
            this->Call(client_id, "Console_DoAutocomplete", call_arguments);
128
            LOG.Error("Console_AutocompleteRequest failed, we are now in an undefined state!");
138
        }
129
        }
139
    }
130
    }
140
    else if (parts[0] == "E")
131
    else if (command == "RESP")
141
    {
132
    {
142
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
133
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
143
        common::StringList arguments;
-
 
144
       
134
       
145
        boost::algorithm::split(arguments, parts[1], boost::is_any_of(" "), boost::algorithm::token_compress_on);
135
        call_arguments->push_back(v8::Integer::New(boost::lexical_cast<unsigned int>(client_id)));
146
       
-
 
147
        std::string command = arguments[0];
136
        call_arguments->push_back(v8::String::New(s.substr(8).data()));
148
       
137
       
149
        for (unsigned int n = 1; n < arguments.size(); n++)
138
        if (!this->Call(client_id, "Console_PromptResponse", call_arguments))
150
        {
139
        {
151
            call_arguments->push_back(v8::String::New(arguments[n].data()));
140
            LOG.Error("Console_PromptResponse failed, we are now in an undefined state!");
152
        }
141
        }
153
       
142
    }
154
        this->Call(client_id, command, call_arguments);
-
 
155
    }
143
    else
156
    else if (parts[0] == "R")
-
 
157
    {
144
    {
158
        ArgumentListPointer call_arguments = ArgumentListPointer(new ArgumentList);
145
        LOG.Error("Unknown packat received, we are now in an undefined state!");
159
       
146
    }
160
        call_arguments->push_back(v8::String::New(parts[1].data()));
-
 
161
        call_arguments->push_back(v8::String::New(parts[2].data()));
-
 
162
       
147
   
163
        this->Call(client_id, "Console_PromptResponse", call_arguments);
148
    Console::current_client_id_ = 0;
164
    }
-
 
165
}
149
}
166
 
150
 
167
void Console::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
151
void Console::SlotOnNewStateHandler(net::ClientId client_id, net::ServerId server_id, net::ClientState client_state)
168
{
152
{
169
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
153
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
170
 
154
 
171
    LOG.Debug(std::string(__FUNCTION__) + " called!");
155
    //LOG.Debug(std::string(__FUNCTION__) + " called!");
172
   
156
   
173
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
157
    if (client_state == net::CLIENT_STATE_DISCONNECTED)
174
    {
158
    {
175
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has disconnected.");
159
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has disconnected.");
176
    }
160
    }
177
    else if (client_state == net::CLIENT_STATE_CONNECTED)
161
    else if (client_state == net::CLIENT_STATE_CONNECTED)
178
    {
162
    {
179
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has connected.");
163
        LOG.Info("Client " + boost::lexical_cast<std::string>(client_id) + " has connected.");
-
 
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;
180
    }
177
    }
181
    else
178
    else
182
    {
179
    {
183
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
180
        LOG.Debug("Got state: " + boost::lexical_cast<std::string>((int)client_state));
184
    }
181
    }
185
}
182
}
-
 
183
 
-
 
184
Value Console::Export_PromptRequest(const v8::Arguments& args)
-
 
185
{
-
 
186
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
-
 
187
   
-
 
188
    LOG.Debug(std::string(__FUNCTION__) + " called!");
186
 
189
   
187
void Console::ExecutionResult(std::string response, unsigned int request_id)
190
    if (args.Length() < 2)
188
{
191
    {
189
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
192
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
-
 
193
        return v8::Boolean::New(false);
-
 
194
    }
190
   
195
   
-
 
196
    v8::String::AsciiValue prompt(args[1]);
-
 
197
   
-
 
198
    std::string packet = "PROM";
191
    LOG.Debug("ExecutionResult: response=" + response + ", request_id=" + boost::lexical_cast<std::string>(request_id));
199
    packet += common::PadNumber(prompt.length() + 1, 4);
-
 
200
    packet += *prompt;
192
   
201
   
193
    net::Manager::Instance()->SendTo(request_id, response);
202
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
-
 
203
    return v8::Boolean::New(true);
-
 
204
       
-
 
205
    return v8::Boolean::New(false);
194
}
206
}
195
 
207
 
196
Value Console::Export_RegisterCommand(const v8::Arguments& args)
208
Value Console::Export_AutoCompleteResponse(const v8::Arguments& args)
197
{
209
{
198
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
210
    v8::Context::Scope context_scope(vm::Manager::Instance()->GetContext());
199
   
211
   
200
    LOG.Debug(std::string(__FUNCTION__) + " called!");
212
    LOG.Debug(std::string(__FUNCTION__) + " called!");
201
   
213
   
202
    if (args.Length() < 1)
214
    if (args.Length() < 2)
203
    {
-
 
204
        LOG.Error("To few arguments.");
-
 
205
    }
-
 
206
   
-
 
207
    v8::String::AsciiValue command(args[0]);
-
 
208
   
-
 
209
    if (Console::ImportFunction(std::string(*command)))
-
 
210
    {
215
    {
211
        LOG.Debug(std::string(*command) + " registered successfully.");
216
        LOG.Error(std::string(__FUNCTION__) + ": To few arguments.");
212
        Console::commands_.push_back(std::string(*command));
-
 
213
        return v8::Boolean::New(true);
217
        return v8::Boolean::New(false);
214
    }
218
    }
215
   
219
   
216
    LOG.Debug("Failed to register command!");
220
    v8::String::AsciiValue result(args[1]);
-
 
221
   
-
 
222
    std::string packet = "COMP";
-
 
223
    packet += common::PadNumber(result.length() + 1, 4);
-
 
224
    packet += *result;
-
 
225
   
-
 
226
    net::Manager::Instance()->SendTo(args[0]->Uint32Value(), packet);
-
 
227
    return v8::Boolean::New(true);
217
   
228
   
218
    return v8::Boolean::New(false);
229
    return v8::Boolean::New(false);
219
}
230
}
220
 
231
 
221
}; // namespace plugin
232
}; // namespace plugin