This commit is contained in:
j3d1 2016-02-23 21:47:45 +01:00
parent 299490ca5f
commit 0f01d375db
13 changed files with 347 additions and 262 deletions

View file

@ -15,8 +15,7 @@ $(BUILDDIR):
$(TARGET): $(OBJECTS) $(TARGET): $(OBJECTS)
$(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lpthread $(CC) $^ -o $(BUILDDIR)/$@ -lboost_filesystem -lboost_system -lreadline -lboost_program_options
$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp $(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View file

@ -3,8 +3,10 @@ Command-Line Tool which might in the future be able to configure TP-Link Easy Sm
The usage is loosely based on the swconfig utility. The usage is loosely based on the swconfig utility.
### dependencys ### dependencys
libboost-filesystem-dev libboost-filesystem
libboost-system-dev libboost-system
libboost-program-options
libreadline
### compatible devices ### compatible devices
+ TL-SG105E + TL-SG105E

View file

@ -7,27 +7,40 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include <algorithm>
#include<boost/program_options/parsers.hpp>
#include<readline/readline.h>
#include<readline/history.h>
#include "Program.h"
#include "Interactive.h" #include "Interactive.h"
using namespace std; using namespace std;
Interactive::Interactive() { int Interactive::loop() {
// TODO Auto-generated constructor stub
}
Interactive::~Interactive() {
// TODO Auto-generated destructor stub
}
int Interactive::run() {
string cmd; string cmd;
while(cmd.compare("quit")){ vector<string> v;
cout<< "smrtlink>" << flush; Program p = Program();
cin >> cmd; p.init();
cout << cmd <<endl;; while (1) {
cmd = readline("smrtlink> ");
if (!cmd.compare("quit") || !cmd.compare("q"))
return 0;
if (!cmd.empty()) {
add_history(cmd.c_str());
v = boost::program_options::split_unix(cmd);
p.run(v);
}
} }
return 0; return 0;
} }
int Interactive::single(vector<string> v) {
Program p = Program();
p.init();
p.run(v);
return 0;
}

View file

@ -10,9 +10,12 @@
class Interactive { class Interactive {
public: public:
Interactive(); Interactive() {
virtual ~Interactive(); }
int run(); virtual ~Interactive() {
}
int loop();
int single(std::vector<std::string> v);
}; };
#endif /* INTERACTIVE_H_ */ #endif /* INTERACTIVE_H_ */

View file

@ -158,8 +158,8 @@ std::string Packet::opCodeToString() {
return "SET"; return "SET";
case CONFIRM: case CONFIRM:
return "CONFIRM"; return "CONFIRM";
case RETURN: case REPLY:
return "RETURN"; return "REPLY";
default: default:
return "NONE"; return "NONE";
} }

View file

@ -13,12 +13,13 @@
#include "Types.h" #include "Types.h"
static short sequenceId=0; static short sequenceId = 0;
class Packet class Packet {
{
public: public:
enum OpCode {DISCOVERY, GET, RETURN, SET, CONFIRM, NONE}; enum OpCode {
DISCOVERY, GET, REPLY, SET, CONFIRM, NONE
};
Packet(OpCode); Packet(OpCode);
static void encode(bytes&); static void encode(bytes&);
bytes getBytes(); bytes getBytes();
@ -37,7 +38,7 @@ public:
void setHostMac(macAddr); void setHostMac(macAddr);
void setSwitchMac(macAddr); void setSwitchMac(macAddr);
void setCheckSum(int); void setCheckSum(int);
void setSequenceId(short ); void setSequenceId(short);
void setPayload(datasets payload); void setPayload(datasets payload);
short getTokenId() const; short getTokenId() const;
void setTokenId(short tokenId = 0); void setTokenId(short tokenId = 0);
@ -50,9 +51,9 @@ private:
datasets payload; datasets payload;
byte version = 1; byte version = 1;
byte opCode; byte opCode;
macAddr switchMac { {0, 0, 0, 0, 0, 0}}; macAddr switchMac { { 0, 0, 0, 0, 0, 0 } };
macAddr hostMac { {0, 0, 0, 0, 0, 0}}; macAddr hostMac { { 0, 0, 0, 0, 0, 0 } };
macAddr broadcastMac { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; macAddr broadcastMac { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
short tokenId = 0; short tokenId = 0;
short fragmentOffset = 0; short fragmentOffset = 0;
int errorCode = 0; int errorCode = 0;
@ -60,7 +61,7 @@ private:
short flag = 0; short flag = 0;
void buildHead(); void buildHead();
void buildBody(); void buildBody();
void push(bytes&, int&, short ); void push(bytes&, int&, short);
void push(bytes&, int&, int); void push(bytes&, int&, int);
void push(bytes&, int&, byte); void push(bytes&, int&, byte);
void push(bytes&, int&, bytes); void push(bytes&, int&, bytes);
@ -70,7 +71,7 @@ private:
void pull(bytes&, int&, short &); void pull(bytes&, int&, short &);
void pull(bytes&, int&, int&); void pull(bytes&, int&, int&);
void pull(bytes&, int&, byte&); void pull(bytes&, int&, byte&);
void pull(bytes&, int&, bytes&, unsigned ); void pull(bytes&, int&, bytes&, unsigned);
void pull(bytes&, int&, ipAddr&); void pull(bytes&, int&, ipAddr&);
void pull(bytes&, int&, macAddr&); void pull(bytes&, int&, macAddr&);
void pull(bytes&, int&, dataset&); void pull(bytes&, int&, dataset&);

View file

@ -6,6 +6,9 @@
*/ */
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <regex>
#include <string>
#include <cstring>
#include "Constant.h" #include "Constant.h"
#include "Program.h" #include "Program.h"
@ -14,11 +17,110 @@
#include "Socket.h" #include "Socket.h"
#include "Switch.h" #include "Switch.h"
#include "Packet.h" #include "Packet.h"
#include "Filter.h"
#include "Types.h"
#include "lookup.h" #include "lookup.h"
#include "table.h" #include "table.h"
using namespace smrtlink;
using namespace std; using namespace std;
int Program::run(vector<string> arg) {
int optind = 0;
std::vector<std::string> vect;
std::map<std::string, std::string> ll;
std::cmatch sm;
std::string cmd = arg[optind++];
io_service->reset();
sock->clear();
switch (caseArg(cmd.c_str())) {
case caseArg("reboot"):
if (reboot())
return 1;
break;
case caseArg("reset"):
if (!reset())
return 0;
break;
case caseArg("save"):
if (save())
return 1;
break;
case caseArg("restore"):
if (restore())
return 1;
break;
case caseArg("flash"):
if (flash())
return 1;
break;
case caseArg("list"):
if (list())
return 1;
break;
case caseArg("sniff"):
if (sniff())
return 1;
break;
case caseArg("encode"):
if (optind < arg.size()) {
std::string s(arg[optind]);
optind++;
if (!encode(s))
return 1;
} else {
fprintf(stderr, "Argument expected after encode\n");
return 1;
}
break;
case caseArg("set"):
while (optind < arg.size()) {
if (regex_match(arg[optind].c_str(), sm,
std::regex("^([a-z]+)=(.*)$"))) {
if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) {
cerr << "Unknown argument " << arg[optind] << endl;
return 1;
}
ll.insert(std::pair<std::string, std::string>(sm[1], sm[2]));
} else {
cerr << "Invalid Syntax " << arg[optind] << endl;
return 1;
}
optind++;
}
if (setProperty(ll))
return 1;
break;
case caseArg("get"):
while (optind < arg.size()) {
if (regex_match(arg[optind].c_str(), sm,
std::regex("^([a-z]+)$"))) {
if (!snd_lookup.exists(sm[1]) && !rcv_lookup.exists(sm[1])) {
cerr << "Unknown argument " << arg[optind] << endl;
return 1;
}
vect.push_back(sm[1]);
} else {
cerr << "Invalid argument " << arg[optind] << endl;
return 1;
}
optind++;
}
if (getProperty(vect))
return 1;
break;
default:
printf("Unknown command: %s\n", cmd.c_str());
return 1;
}
io_service->run();
return 0;
}
int printHeader(Packet p) { int printHeader(Packet p) {
if (options.flags.HEADER) { if (options.flags.HEADER) {
if (options.flags.HEX) { if (options.flags.HEX) {
@ -93,15 +195,18 @@ int Program::list() {
cout <<"Received Payload:\n"<<a.getBody()<<"\n"; cout <<"Received Payload:\n"<<a.getBody()<<"\n";
} else { } else {
datasets d =a.getPayload(); datasets d =a.getPayload();
Switch sw = Switch();
sw.parse(d); int b = a.getSwitchMac().hash();
if (devices.empty()||devices.find(b) == devices.end())
devices.insert(pair<int,Switch>(b,Switch()));
devices[a.getSwitchMac().hash()].parse(d);
devices[a.getSwitchMac().hash()].print();
File f; File f;
f.write(sw.toString()); f.write(devices[a.getSwitchMac().hash()].toString());
sw.print();
} }
return 0; return 0;
}); });
io_service->run();
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
@ -111,22 +216,15 @@ int Program::list() {
int Program::sniff() { int Program::sniff() {
printf("Listening:\n"); printf("Listening:\n");
try { try {
boost::asio::io_service io_service; sock->listen([](Packet p) {
Socket s(io_service);
s.setHostIp(host.getIp());
s.init(DST_PORT, SRC_PORT);
s.callback = [](Packet p) {
cout << p.opCodeToString() << "\n"; cout << p.opCodeToString() << "\n";
printHeader(p); printHeader(p);
printPacket(p); printPacket(p);
return 0; return 0;
}; });
s.listen();
io_service.run();
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
return 0; return 0;
} }
@ -179,8 +277,6 @@ int Program::setProperty(map<string, string> prop) {
}); });
return 0; return 0;
}); });
io_service->run();
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
@ -210,7 +306,6 @@ int Program::getProperty(vector<string> prop) {
return 0; return 0;
}); });
io_service->run();
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
@ -240,27 +335,27 @@ int Program::flash() {
int Program::reboot() { int Program::reboot() {
try { try {
discover([this](Packet a) { discover(
datasets d =a.getPayload(); [this](Packet a) {
Switch sw = Switch(); datasets d =a.getPayload();
sw.parse(d); int b = a.getSwitchMac().hash();
cout <<sw.settings.hostname<<"\t"; if (devices.empty()||devices.find(b) == devices.end())
datasets t = { {SND_PING, 0, {}}}; devices.insert(pair<int,Switch>(b,Switch()));
get(a, t, [this](Packet a) { devices[a.getSwitchMac().hash()].parse(d);
datasets d =a.getPayload(); datasets t = { {SND_PING, 0, {}}};
Switch sw = Switch(); get(a, t, [this](Packet a) {
sw.parse(d); datasets d =a.getPayload();
datasets t = { {REBOOT, 1, {options.flags.PERMANENT?(byte)1:(byte)0}}}; cout <<devices[a.getSwitchMac().hash()].settings.hostname<<"\t";
set(a,t,[this](Packet a) { devices[a.getSwitchMac().hash()].parse(d);
if( a.getOpCode()==Packet::CONFIRM) datasets t = { {REBOOT, 1, {options.flags.PERMANENT?(byte)1:(byte)0}}};
cout<< "rebooting now.\n"; set(a,t,[this](Packet a) {
return 0; cout<< "rebooting now.\n";
}); return 0;
return 0; });
}); return 0;
return 0; });
}); return 0;
io_service->run(); });
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
@ -289,33 +384,32 @@ int Program::reset() {
}); });
return 0; return 0;
}); });
io_service->run();
} catch (exception& e) { } catch (exception& e) {
cerr << "Exception: " << e.what() << "\n"; cerr << "Exception: " << e.what() << "\n";
} }
return 0; return 0;
} }
int Program::discover(function<int(Packet)> c) { int Program::discover(Listener c) {
Packet p = Packet(Packet::DISCOVERY); Packet p = Packet(Packet::DISCOVERY);
p.setHostMac(host.getMac()); p.setHostMac(host.getMac());
p.setPayload( { }); p.setPayload( { });
sock->callback = c; sock->listen(c, Filter(Packet::REPLY));
sock->send(p); sock->send(p);
return 0; return 0;
} }
int Program::get(Packet l, datasets t, function<int(Packet)> c) { int Program::get(Packet l, datasets t, Listener c) {
Packet p = Packet(Packet::GET); Packet p = Packet(Packet::GET);
p.setSwitchMac(l.getSwitchMac()); p.setSwitchMac(l.getSwitchMac());
p.setHostMac(host.getMac()); p.setHostMac(host.getMac());
p.setPayload(t); p.setPayload(t);
sock->callback = c; sock->listen(c, Filter(Packet::REPLY).mac(l.getSwitchMac()));
sock->send(p); sock->send(p);
return 0; return 0;
} }
int Program::set(Packet l, datasets t, function<int(Packet)> c) { int Program::set(Packet l, datasets t, Listener c) {
Packet p = Packet(Packet::SET); Packet p = Packet(Packet::SET);
p.setSwitchMac(l.getSwitchMac()); p.setSwitchMac(l.getSwitchMac());
p.setTokenId(l.getTokenId()); p.setTokenId(l.getTokenId());
@ -325,12 +419,14 @@ int Program::set(Packet l, datasets t, function<int(Packet)> c) {
datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD, datasets ld = { { LOGIN_USER, (short) (n.size()), n }, { LOGIN_PASSWORD,
(short) (w.size()), w } }; (short) (w.size()), w } };
p.setPayload(ld + t); p.setPayload(ld + t);
sock->callback = c; sock->listen(c, Filter(Packet::CONFIRM).mac(l.getSwitchMac()));
sock->send(p); sock->send(p);
return 0; return 0;
} }
void Program::init() { void Program::init() {
io_service = std::make_shared<boost::asio::io_service>();
sock = std::make_shared < Socket > (*io_service);
if (options.interface.compare("") == 0) if (options.interface.compare("") == 0)
options.interface = host.getIface(); options.interface = host.getIface();

View file

@ -9,36 +9,42 @@
#define PROGRAM_H_ #define PROGRAM_H_
#include <memory> #include <memory>
#include <vector>
#include "Types.h" #include "Types.h"
#include "Host.h" #include "Host.h"
#include "Switch.h"
#include "Socket.h" #include "Socket.h"
class Program { class Program {
private: private:
std::shared_ptr<boost::asio::io_service> io_service; std::shared_ptr<boost::asio::io_service> io_service;
std::shared_ptr<Socket> sock; std::shared_ptr<Socket> sock;
Host host = Host(); Host host = Host();
int get(Packet,datasets,std::function<int(Packet)>); std::map<int, Switch> devices;
int set(Packet,datasets,std::function<int(Packet)>); int get(Packet, datasets, std::function<int(Packet)>);
int set(Packet, datasets, std::function<int(Packet)>);
int discover(std::function<int(Packet)>); int discover(std::function<int(Packet)>);
public: public:
Program() { Program() {
io_service = std::make_shared<boost::asio::io_service>(); }
sock = std::make_shared<Socket>(*io_service); void init();
} int run(std::vector<std::string>);
void init(); std::function<int()> callback = []() {
int list(); return 0;
int sniff(); };
int encode(std::string);
int getProperty(std::vector<std::string>); int list();
int setProperty(std::map<std::string,std::string>); int sniff();
int save(); int encode(std::string);
int restore(); int getProperty(std::vector<std::string>);
int flash(); int setProperty(std::map<std::string, std::string>);
int reboot(); int save();
int reset(); int restore();
std::string input; int flash();
int reboot();
int reset();
std::string input;
}; };
#endif /* PROGRAM_H_ */ #endif /* PROGRAM_H_ */

View file

@ -5,29 +5,33 @@
* Author: jdi * Author: jdi
*/ */
#include <cstdlib> #include <cstdlib>
#include <array> #include <map>
#include <unistd.h> #include <unistd.h>
#include "Socket.h" #include "Socket.h"
#include "Packet.h" #include "Packet.h"
#include "Constant.h" #include "Constant.h"
#include "Filter.h"
#include "Host.h" #include "Host.h"
#include "Types.h" #include "Types.h"
using namespace std;
Socket::Socket(boost::asio::io_service& io_service) : Socket::Socket(boost::asio::io_service& io_service) :
send_socket_(io_service), receive_socket_(io_service), timer(io_service) { send_socket_(io_service), receive_socket_(io_service), timer(io_service) {
} }
//, resolver( io_service) //, resolver( io_service)
void Socket::init(short dst_port, short src_port) {
if (initialized)
return;
Socket::~Socket() {
}
void Socket::init(short dst_port, short src_port) {
if (options.flags.REVERSE) { if (options.flags.REVERSE) {
short p = dst_port; short p = dst_port;
dst_port = src_port; dst_port = src_port;
src_port = p; src_port = p;
} }
if (options.debug_level>=1) if (options.debug_level >= 1)
std::cout << "Local IP:\t" << local_ip << "\n"; std::cout << "Local IP:\t" << local_ip << "\n";
wildcard_endpoint_ = boost::asio::ip::udp::endpoint( wildcard_endpoint_ = boost::asio::ip::udp::endpoint(
@ -47,26 +51,25 @@ void Socket::init(short dst_port, short src_port) {
receive_socket_.set_option(boost::asio::socket_base::broadcast(true)); receive_socket_.set_option(boost::asio::socket_base::broadcast(true));
receive_socket_.set_option(boost::asio::socket_base::reuse_address(true)); receive_socket_.set_option(boost::asio::socket_base::reuse_address(true));
receive_socket_.bind(wildcard_endpoint_); receive_socket_.bind(wildcard_endpoint_);
if (options.timeout != 0) {
timer.expires_from_now(
boost::posix_time::milliseconds(options.timeout));
timer.async_wait([this](const boost::system::error_code& error)
{
if (!error)
{
receive_socket_.close();
}
});
}
initialized = 1;
} }
void Socket::setHostIp(ipAddr ip) { void Socket::setHostIp(ipAddr ip) {
local_ip = ip; local_ip = ip;
} }
void Socket::clear(){
callback.clear();
}
void Socket::listen(Listener l, Filter f) {
if (callback.find(f) == callback.end()) {
callback.insert(ListenerPair(f, l));
} else {
callback[f] = l;
}
receive();
}
void Socket::send(Packet p) { void Socket::send(Packet p) {
bytes data = p.getBytes(); bytes data = p.getBytes();
p.encode(data); p.encode(data);
@ -75,11 +78,12 @@ void Socket::send(Packet p) {
broadcast_endpoint_, broadcast_endpoint_,
[this](boost::system::error_code ec, std::size_t bytes_sent) [this](boost::system::error_code ec, std::size_t bytes_sent)
{ {
listen(); receive();
settimeout();
}); });
} }
void Socket::listen() { void Socket::receive() {
data.resize(MAX_LENGTH); data.resize(MAX_LENGTH);
receive_socket_.async_receive_from(boost::asio::buffer(data, MAX_LENGTH), receive_socket_.async_receive_from(boost::asio::buffer(data, MAX_LENGTH),
remote_endpoint_, remote_endpoint_,
@ -92,13 +96,37 @@ void Socket::listen() {
data.resize(bytes_recvd); data.resize(bytes_recvd);
Packet p = Packet(Packet::NONE); Packet p = Packet(Packet::NONE);
p.encode(data); p.encode(data);
// std::cout << "err" << p.getErrorCode() <<std::endl;
p.parse(data); p.parse(data);
//std::cout << "err" << p.getErrorCode() <<std::endl; for(auto r : callback) {
if(!callback(p)) { if(r.first.pass(p)) {
//TODO do something r.second(p);
// std::cout<<"pass"<<std::endl;
break;
} else {
// std::cout<<"no pass"<<std::endl;
}
} }
listen(); receive();
settimeout();
} }
}); });
} }
void Socket::settimeout() {
if (options.timeout != 0) {
timer.expires_from_now(
boost::posix_time::milliseconds(options.timeout));
timer.async_wait(
[this](const boost::system::error_code& error)
{
if (!error)
{
receive_socket_.close();
receive_socket_.open(boost::asio::ip::udp::v4());
receive_socket_.set_option(boost::asio::socket_base::broadcast(true));
receive_socket_.set_option(boost::asio::socket_base::reuse_address(true));
receive_socket_.bind(wildcard_endpoint_);
}
});
}
}

View file

@ -8,8 +8,10 @@
#ifndef SOCKET_H_ #ifndef SOCKET_H_
#define SOCKET_H_ #define SOCKET_H_
#include <map>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Packet.h" #include "Packet.h"
#include "Filter.h"
#include "Types.h" #include "Types.h"
#define SRC_PORT 29809 #define SRC_PORT 29809
@ -17,30 +19,32 @@
#define MAX_LENGTH 1024 #define MAX_LENGTH 1024
typedef std::function<int(Packet)> Listener;
typedef std::pair<Filter, Listener> ListenerPair;
class Socket { class Socket {
public: public:
Socket(boost::asio::io_service&); Socket(boost::asio::io_service&);
virtual ~Socket() { virtual ~Socket();
} void init(short, short);
void init(short, short); void clear();
void send(Packet); void send(Packet);
void listen(); void setHostIp(ipAddr);
void setHostIp(ipAddr); void listen(Listener l, Filter f = Filter());
std::function<int(Packet)> callback = [](Packet a) {
return 0;
};
private: private:
boost::asio::ip::udp::socket send_socket_; void receive();
boost::asio::ip::udp::socket receive_socket_; void settimeout();
boost::asio::ip::udp::endpoint broadcast_endpoint_; boost::asio::ip::udp::socket send_socket_;
boost::asio::ip::udp::endpoint remote_endpoint_; boost::asio::ip::udp::socket receive_socket_;
boost::asio::ip::udp::endpoint wildcard_endpoint_; boost::asio::ip::udp::endpoint broadcast_endpoint_;
boost::asio::ip::udp::endpoint local_endpoint_; boost::asio::ip::udp::endpoint remote_endpoint_;
boost::asio::deadline_timer timer; boost::asio::ip::udp::endpoint wildcard_endpoint_;
bytes data = bytes(MAX_LENGTH); boost::asio::ip::udp::endpoint local_endpoint_;
ipAddr local_ip; boost::asio::deadline_timer timer;
int initialized = 0; bytes data = bytes(MAX_LENGTH);
ipAddr local_ip;
std::map<Filter, Listener> callback = { };
}; };

View file

@ -65,9 +65,13 @@ public:
int parse(datasets); int parse(datasets);
int parse(dataset); int parse(dataset);
int parse(std::string); int parse(std::string);
int print(); int set(std::pair<std::string,std::string>);
std::string get(std::string);
std::string toString(); std::string toString();
int print();
struct { struct {
std::string type; std::string type;
std::string hardware_version; std::string hardware_version;

View file

@ -50,6 +50,28 @@ public:
else break; else break;
} }
} }
int hash() {
int ret=0;
for (unsigned i = 0; i < 6; i++) {
ret = (ret*33) ^ (*this)[i];
}
return ret;
}
bool operator==(const macAddr &A) {
for (unsigned i = 0; i < 6; i++) {
if(A[i]!=(*this)[i])return false;
}
return true;
}
bool operator!=(const macAddr &A) {
for (unsigned i = 0; i < 6; i++) {
if(A[i]!=(*this)[i])return true;
}
return false;
}
}; };
/* /*
@ -95,6 +117,14 @@ public:
} }
}; };
namespace smrtlink {
constexpr unsigned int caseArg(const char* str, int h = 0) {
return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h];
}
}
template<typename T> template<typename T>
std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B) { std::vector<T> operator+(const std::vector<T> &A, const std::vector<T> &B) {
std::vector<T> AB; std::vector<T> AB;
@ -117,6 +147,7 @@ struct Options {
bool JSON; bool JSON;
bool PLAIN; bool PLAIN;
bool REVERSE; bool REVERSE;
bool HEADER; bool HEADER;
bool PERMANENT; bool PERMANENT;
bool WAIT; bool WAIT;
@ -128,7 +159,7 @@ struct Options {
std::string file; std::string file;
int debug_level = 0; int debug_level = 0;
int verbosity = 0; int verbosity = 0;
long timeout = 180U; long timeout = 250U;
}; };
#endif /* TYPES_H_ */ #endif /* TYPES_H_ */

View file

@ -1,14 +1,13 @@
//============================================================================ //============================================================================
// Name : smrtlink.cpp // Name : smrtlink.cpp
// Author : jdi // Author : jdi
// Version : // Version : 1.2
// Copyright : GPL v2 // Copyright : GPL v2
// Description : SmrtLink in C++, Ansi-style // Description : SmrtLink in C++, Ansi-style
//============================================================================ //============================================================================
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <regex>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
@ -21,6 +20,7 @@
#include "Interactive.h" #include "Interactive.h"
#include "Host.h" #include "Host.h"
#include "Program.h" #include "Program.h"
#include "Types.h"
#include "Switch.h" #include "Switch.h"
#include "lookup.h" #include "lookup.h"
@ -32,12 +32,8 @@ using namespace std;
Options options; Options options;
constexpr unsigned int caseArg(const char* str, int h = 0) {
return !str[h] ? 5381 : (caseArg(str, h + 1) * 33) ^ str[h];
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int index,opt; int index, opt;
options.user = DEFAULT_USER; options.user = DEFAULT_USER;
options.password = DEFAULT_PASS; options.password = DEFAULT_PASS;
@ -56,7 +52,7 @@ int main(int argc, char *argv[]) {
while ((opt = getopt_long(argc, argv, "bhrVsxP:U:i:t::", longopts, while ((opt = getopt_long(argc, argv, "bhrVXsxP:U:i:t::", longopts,
&index)) != -1) { &index)) != -1) {
switch (opt) { switch (opt) {
@ -149,118 +145,20 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
Interactive p = Interactive();
if (options.flags.INTERACTIVE) { if (options.flags.INTERACTIVE) {
if (optind < argc) { if (optind < argc) {
cerr << "Command is ignored in interactive mode\n"; cerr << "Command is ignored in interactive mode\n";
} }
Interactive p = Interactive(); if (!p.loop())
if (!p.run())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n"); fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} } else if (optind < argc) {
else if (optind < argc) { vector<string> v;
Program p = Program(); while (optind < argc)
p.init(); v.push_back(argv[optind++]);
std::vector<std::string> vect; p.single(v);
std::map<std::string, std::string> list;
std::cmatch sm;
std::string cmd = std::string(argv[optind++]);
switch (caseArg(cmd.c_str())) {
case caseArg("reboot"):
if (!p.reboot())
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("reset"):
if (!p.reset())
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("save"):
if (!p.save())
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("restore"):
if (!p.restore())
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("flash"):
if (!p.flash())
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("list"):
if (!p.list())
exit(EXIT_SUCCESS);
break;
case caseArg("sniff"):
if (!p.sniff())
exit(EXIT_SUCCESS);
break;
case caseArg("encode"):
if (optind < argc) {
std::string s(argv[optind]);
optind++;
if (p.encode(s))
exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "Argument expected after encode\n");
exit(EXIT_FAILURE);
}
break;
case caseArg("set"):
while (optind < argc) {
if (regex_match(argv[optind], sm,
std::regex("^([a-z]+)=(.*)$"))) {
if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) {
cerr << "Unknown argument " << argv[optind] << endl;
exit(EXIT_FAILURE);
}
list.insert(
std::pair<std::string, std::string>(sm[1], sm[2]));
} else {
cerr << "Invalid Syntax " << argv[optind] << endl;
exit(EXIT_FAILURE);
}
optind++;
}
if (!p.setProperty(list))
exit(EXIT_SUCCESS);
fprintf(stderr, "Not yet implemented.\n");
exit(EXIT_FAILURE);
break;
case caseArg("get"):
while (optind < argc) {
if (regex_match(argv[optind], sm, std::regex("^([a-z]+)$"))) {
if (!snd_lookup.exists(sm[1])&&!rcv_lookup.exists(sm[1])) {
cerr << "Unknown argument " << argv[optind] << endl;
exit(EXIT_FAILURE);
}
vect.push_back(sm[1]);
} else {
cerr << "Invalid argument " << argv[optind] << endl;
exit(EXIT_FAILURE);
}
optind++;
}
if (!p.getProperty(vect))
exit(EXIT_SUCCESS);
break;
default:
printf("Unknown command: %s\n", cmd.c_str());
exit(EXIT_FAILURE);
}
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }