CLI communication now working.

This commit is contained in:
Adam Ierymenko 2013-08-05 17:44:39 -04:00
parent 70f368fdc3
commit c9c63074bb
5 changed files with 41 additions and 33 deletions

12
cli.cpp
View file

@ -37,6 +37,7 @@
#include "node/Constants.hpp" #include "node/Constants.hpp"
#include "node/Utils.hpp" #include "node/Utils.hpp"
#include "node/Thread.hpp" #include "node/Thread.hpp"
#include "node/Condition.hpp"
using namespace ZeroTier; using namespace ZeroTier;
@ -51,14 +52,15 @@ static void printHelp(FILE *out,const char *exename)
fprintf(out,"Use the 'help' command to get help from ZeroTier One itself."ZT_EOL_S); fprintf(out,"Use the 'help' command to get help from ZeroTier One itself."ZT_EOL_S);
} }
static volatile uint64_t lastResultTime = 0ULL;
static volatile unsigned int numResults = 0; static volatile unsigned int numResults = 0;
static Condition doneCondition;
static void resultHandler(void *arg,unsigned long id,const char *line) static void resultHandler(void *arg,unsigned long id,const char *line)
{ {
lastResultTime = Utils::now();
++numResults; ++numResults;
fprintf(stdout,"%s"ZT_EOL_S,line); if (strlen(line))
fprintf(stdout,"%s"ZT_EOL_S,line);
else doneCondition.signal();
} }
int main(int argc,char **argv) int main(int argc,char **argv)
@ -118,9 +120,7 @@ int main(int argc,char **argv)
Node::LocalClient client(authToken.c_str(),&resultHandler,(void *)0); Node::LocalClient client(authToken.c_str(),&resultHandler,(void *)0);
client.send(command.c_str()); client.send(command.c_str());
lastResultTime = Utils::now(); doneCondition.wait(1000);
while ((Utils::now() - lastResultTime) < 300)
Thread<void>::sleep(50);
if (!numResults) { if (!numResults) {
fprintf(stdout,"ERROR: no results received. Is ZeroTier One running?"ZT_EOL_S); fprintf(stdout,"ERROR: no results received. Is ZeroTier One running?"ZT_EOL_S);

View file

@ -97,11 +97,11 @@ public:
{ {
InetAddress v4(p->ipv4ActivePath(_now)); InetAddress v4(p->ipv4ActivePath(_now));
InetAddress v6(p->ipv6ActivePath(_now)); InetAddress v6(p->ipv6ActivePath(_now));
_P("200 listpeers %s %s %s %u", _P("200 listpeers %s %s %s %d",
p->address().toString().c_str(), p->address().toString().c_str(),
((v4) ? v4.toString().c_str() : "(none)"), ((v4) ? v4.toString().c_str() : "(none)"),
((v6) ? v6.toString().c_str() : "(none)"), ((v6) ? v6.toString().c_str() : "(none)"),
(((v4)||(v6)) ? p->latency() : 0)); (((v4)||(v6)) ? (int)p->latency() : -1));
} }
private: private:
@ -129,11 +129,20 @@ std::vector<std::string> NodeConfig::execute(const char *command)
_r->topology->eachPeer(_DumpPeerStatistics(r)); _r->topology->eachPeer(_DumpPeerStatistics(r));
} else if (cmd[0] == "listnetworks") { } else if (cmd[0] == "listnetworks") {
Mutex::Lock _l(_networks_m); Mutex::Lock _l(_networks_m);
_P("200 listnetworks <nwid> <type> <dev> <ips>");
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator nw(_networks.begin());nw!=_networks.end();++nw) { for(std::map< uint64_t,SharedPtr<Network> >::const_iterator nw(_networks.begin());nw!=_networks.end();++nw) {
_P("200 listnetworks %llu %s %s", std::string tmp;
nw->first, std::set<InetAddress> ips(nw->second->tap().ips());
for(std::set<InetAddress>::iterator i(ips.begin());i!=ips.end();++i) {
if (tmp.length())
tmp.push_back(',');
tmp.append(i->toString());
}
_P("200 listnetworks %.16llx %s %s %s",
(unsigned long long)nw->first,
(nw->second->isOpen() ? "public" : "private"),
nw->second->tap().deviceName().c_str(), nw->second->tap().deviceName().c_str(),
(nw->second->isOpen() ? "public" : "private")); tmp.c_str());
} }
} else if (cmd[0] == "join") { } else if (cmd[0] == "join") {
_P("404 join Not implemented yet."); _P("404 join Not implemented yet.");
@ -143,6 +152,8 @@ std::vector<std::string> NodeConfig::execute(const char *command)
_P("404 %s No such command. Use 'help' for help.",cmd[0].c_str()); _P("404 %s No such command. Use 'help' for help.",cmd[0].c_str());
} }
r.push_back(std::string()); // terminate with empty line
return r; return r;
} }
@ -154,8 +165,9 @@ std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > NodeConfig::encodeControlMe
std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets; std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets;
Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> packet; Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> packet;
packet.setSize(16); // HMAC and IV packet.setSize(16); // room for HMAC and IV
packet.append((uint32_t)(conversationId & 0xffffffff)); packet.append((uint32_t)(conversationId & 0xffffffff));
for(unsigned int i=0;i<payload.size();++i) { for(unsigned int i=0;i<payload.size();++i) {
packet.append(payload[i]); // will throw if too big packet.append(payload[i]); // will throw if too big
packet.append((unsigned char)0); packet.append((unsigned char)0);
@ -174,7 +186,7 @@ std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > NodeConfig::encodeControlMe
packets.push_back(packet); packets.push_back(packet);
packet.setSize(16); // HMAC and IV packet.setSize(16); // room for HMAC and IV
packet.append((uint32_t)(conversationId & 0xffffffff)); packet.append((uint32_t)(conversationId & 0xffffffff));
} }
} }
@ -211,7 +223,7 @@ bool NodeConfig::decodeControlMessagePacket(const void *key,const void *data,uns
unsigned int eos = i; unsigned int eos = i;
while ((eos < pll)&&(pl[eos])) while ((eos < pll)&&(pl[eos]))
++eos; ++eos;
if (eos > i) { if (eos >= i) {
payload.push_back(std::string(pl + i,eos - i)); payload.push_back(std::string(pl + i,eos - i));
i = eos + 1; i = eos + 1;
} else break; } else break;

View file

@ -52,19 +52,6 @@ class RuntimeEnvironment;
/** /**
* Node configuration endpoint * Node configuration endpoint
*
* Packet format for local UDP configuration packets:
* [16] first 16 bytes of HMAC-SHA-256 of payload
* [ -- begin HMAC'ed envelope -- ]
* [8] random initialization vector
* [ -- begin cryptographic envelope -- ]
* [4] arbitrary tag, echoed in response
* [...] payload
*
* For requests, the payload consists of a single ASCII command. For
* responses, the payload consists of one or more response lines delimited
* by NULL (0) characters. The tag field is replicated in the result
* packet.
*/ */
class NodeConfig class NodeConfig
{ {

View file

@ -125,7 +125,13 @@ UdpSocket::UdpSocket(
UdpSocket::~UdpSocket() UdpSocket::~UdpSocket()
{ {
close(_sock); int s = _sock;
_sock = 0;
if (s > 0) {
::shutdown(s,SHUT_RDWR);
::close(s);
}
Thread<UdpSocket>::join(_thread);
} }
bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int hopLimit) bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int hopLimit)
@ -148,19 +154,22 @@ bool UdpSocket::send(const InetAddress &to,const void *data,unsigned int len,int
void UdpSocket::threadMain() void UdpSocket::threadMain()
throw() throw()
{ {
char buf[32768]; char buf[65536];
InetAddress from; InetAddress from;
socklen_t salen; socklen_t salen;
int n; int n;
for(;;) { while (_sock > 0) {
salen = from.saddrSpaceLen(); salen = from.saddrSpaceLen();
n = (int)recvfrom(_sock,buf,sizeof(buf),0,from.saddr(),&salen); n = (int)recvfrom(_sock,buf,sizeof(buf),0,from.saddr(),&salen);
if (n < 0) { if (n < 0) {
if ((errno != EINTR)&&(errno != ETIMEDOUT)) if ((errno != EINTR)&&(errno != ETIMEDOUT))
break; break;
} else if (n > 0) } else if (n > 0) {
_packetHandler(this,_arg,from,buf,(unsigned int)n); try {
_packetHandler(this,_arg,from,buf,(unsigned int)n);
} catch ( ... ) {} // should never be thrown from here anyway...
}
} }
} }

View file

@ -98,7 +98,7 @@ private:
void (*_packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int); void (*_packetHandler)(UdpSocket *,void *,const InetAddress &,const void *,unsigned int);
void *_arg; void *_arg;
int _localPort; int _localPort;
int _sock; volatile int _sock;
bool _v6; bool _v6;
Mutex _sendLock; Mutex _sendLock;
}; };