Merge branch 'development' into LTS_development

This commit is contained in:
Thulinma 2020-03-12 16:26:48 +01:00
commit dd5d8815be
6 changed files with 72 additions and 17 deletions

View file

@ -612,6 +612,24 @@ JSON::Value &JSON::Value::assignFrom(const Value &rhs, const std::set<std::strin
return *this; return *this;
} }
/// Extends this JSON::Value object with the given JSON::Value object, skipping given member(s) recursively.
JSON::Value &JSON::Value::extend(const Value &rhs, const std::set<std::string> &skip){
//Null values turn into objects automatically for sanity reasons
if (myType == EMPTY){myType = OBJECT;}
//Abort if either value is not an object
if (myType != rhs.myType || myType != OBJECT){return *this;}
jsonForEachConst(rhs, i){
if (!skip.count(i.key())){
if (!objVal.count(i.key()) || !i->isObject()){
(*this)[i.key()] = *i;
}else{
(*this)[i.key()].extend(*i, skip);
}
}
}
return *this;
}
/// Sets this JSON::Value to be equal to the given JSON::Value. /// Sets this JSON::Value to be equal to the given JSON::Value.
JSON::Value &JSON::Value::operator=(const JSON::Value &rhs){ JSON::Value &JSON::Value::operator=(const JSON::Value &rhs){
null(); null();

View file

@ -10,6 +10,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
static const std::set<std::string> emptyset;
/// JSON-related classes and functions /// JSON-related classes and functions
namespace JSON{ namespace JSON{
@ -50,10 +52,11 @@ namespace JSON{
// comparison operators // comparison operators
bool operator==(const Value &rhs) const; bool operator==(const Value &rhs) const;
bool operator!=(const Value &rhs) const; bool operator!=(const Value &rhs) const;
bool compareExcept(const Value &rhs, const std::set<std::string> &skip) const; bool compareExcept(const Value &rhs, const std::set<std::string> &skip = emptyset) const;
bool compareOnly(const Value &rhs, const std::set<std::string> &check) const; bool compareOnly(const Value &rhs, const std::set<std::string> &check = emptyset) const;
// assignment operators // assignment operators
Value &assignFrom(const Value &rhs, const std::set<std::string> &skip); Value &extend(const Value &rhs, const std::set<std::string> &skip = emptyset);
Value &assignFrom(const Value &rhs, const std::set<std::string> &skip = emptyset);
Value &operator=(const Value &rhs); Value &operator=(const Value &rhs);
Value &operator=(const std::string &rhs); Value &operator=(const std::string &rhs);
Value &operator=(const char *rhs); Value &operator=(const char *rhs);

View file

@ -33,6 +33,15 @@ static const char *addrFam(int f){
} }
} }
/// Calls gai_strerror with the given argument, calling regular strerror on the global errno as needed
static const char * gai_strmagic(int errcode){
if (errcode == EAI_SYSTEM){
return strerror(errno);
}else{
return gai_strerror(errcode);
}
}
static std::string getIPv6BinAddr(const struct sockaddr_in6 &remoteaddr){ static std::string getIPv6BinAddr(const struct sockaddr_in6 &remoteaddr){
char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000"; char tmpBuffer[17] = "\000\000\000\000\000\000\000\000\000\000\377\377\000\000\000\000";
switch (remoteaddr.sin6_family){ switch (remoteaddr.sin6_family){
@ -238,7 +247,7 @@ std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host,
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
int s = getaddrinfo(host.c_str(), 0, &hints, &result); int s = getaddrinfo(host.c_str(), 0, &hints, &result);
if (s != 0){ if (s != 0){
FAIL_MSG("Could not resolve %s! Error: %s", host.c_str(), gai_strerror(s)); FAIL_MSG("Could not resolve %s! Error: %s", host.c_str(), gai_strmagic(s));
return ""; return "";
} }
@ -436,13 +445,21 @@ void Socket::Buffer::clear(){
} }
void Socket::Connection::setBoundAddr(){ void Socket::Connection::setBoundAddr(){
//If a bound address was set through environment (e.g. HTTPS output), restore it from there.
char * envbound = getenv("MIST_BOUND_ADDR");
if (envbound){
boundaddr = envbound;
return;
}
//If we can't read the address, don't try
if (!isTrueSocket){ if (!isTrueSocket){
boundaddr = ""; boundaddr = "";
return; return;
} }
//Otherwise, read from socket pointer. Works for both SSL and non-SSL sockets, and real sockets passed as fd's, but not for non-sockets (duh)
struct sockaddr_in6 tmpaddr; struct sockaddr_in6 tmpaddr;
socklen_t len = sizeof(tmpaddr); socklen_t len = sizeof(tmpaddr);
if (!getsockname(sSend, (sockaddr *)&tmpaddr, &len)){ if (!getsockname(getSocket(), (sockaddr *)&tmpaddr, &len)){
static char addrconv[INET6_ADDRSTRLEN]; static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){ if (tmpaddr.sin6_family == AF_INET6){
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN); boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
@ -649,12 +666,18 @@ void Socket::Connection::drop(){
/// Returns internal socket number. /// Returns internal socket number.
int Socket::Connection::getSocket(){ int Socket::Connection::getSocket(){
#ifdef SSL
if (sslConnected){return server_fd->fd;}
#endif
if (sSend != -1){return sSend;} if (sSend != -1){return sSend;}
return sRecv; return sRecv;
} }
/// Returns non-piped internal socket number. /// Returns non-piped internal socket number.
int Socket::Connection::getPureSocket(){ int Socket::Connection::getPureSocket(){
#ifdef SSL
if (sslConnected){return server_fd->fd;}
#endif
if (!isTrueSocket){return -1;} if (!isTrueSocket){return -1;}
return sSend; return sSend;
} }
@ -790,6 +813,8 @@ void Socket::Connection::open(std::string host, int port, bool nonblock, bool wi
} }
} }
sslConnected = true; sslConnected = true;
isTrueSocket = true;
setBoundAddr();
Blocking = true; Blocking = true;
if (nonblock){setBlocking(false);} if (nonblock){setBlocking(false);}
DONTEVEN_MSG("SSL connect success"); DONTEVEN_MSG("SSL connect success");
@ -809,7 +834,7 @@ void Socket::Connection::open(std::string host, int port, bool nonblock, bool wi
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
int s = getaddrinfo(host.c_str(), ss.str().c_str(), &hints, &result); int s = getaddrinfo(host.c_str(), ss.str().c_str(), &hints, &result);
if (s != 0){ if (s != 0){
lastErr = gai_strerror(s); lastErr = gai_strmagic(s);
FAIL_MSG("Could not connect to %s:%i! Error: %s", host.c_str(), port, lastErr.c_str()); FAIL_MSG("Could not connect to %s:%i! Error: %s", host.c_str(), port, lastErr.c_str());
close(); close();
return; return;
@ -1605,7 +1630,7 @@ void Socket::UDPConnection::SetDestination(std::string destIp, uint32_t port){
hints.ai_next = NULL; hints.ai_next = NULL;
int s = getaddrinfo(destIp.c_str(), ss.str().c_str(), &hints, &result); int s = getaddrinfo(destIp.c_str(), ss.str().c_str(), &hints, &result);
if (s != 0){ if (s != 0){
FAIL_MSG("Could not connect UDP socket to %s:%i! Error: %s", destIp.c_str(), port, gai_strerror(s)); FAIL_MSG("Could not connect UDP socket to %s:%i! Error: %s", destIp.c_str(), port, gai_strmagic(s));
return; return;
} }
@ -1762,12 +1787,12 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
if (iface == "0.0.0.0" || iface.length() == 0){ if (iface == "0.0.0.0" || iface.length() == 0){
if ((addr_ret = getaddrinfo(0, ss.str().c_str(), &hints, &addr_result)) != 0){ if ((addr_ret = getaddrinfo(0, ss.str().c_str(), &hints, &addr_result)) != 0){
FAIL_MSG("Could not resolve %s for UDP: %s", iface.c_str(), gai_strerror(addr_ret)); FAIL_MSG("Could not resolve %s for UDP: %s", iface.c_str(), gai_strmagic(addr_ret));
return 0; return 0;
} }
}else{ }else{
if ((addr_ret = getaddrinfo(iface.c_str(), ss.str().c_str(), &hints, &addr_result)) != 0){ if ((addr_ret = getaddrinfo(iface.c_str(), ss.str().c_str(), &hints, &addr_result)) != 0){
FAIL_MSG("Could not resolve %s for UDP: %s", iface.c_str(), gai_strerror(addr_ret)); FAIL_MSG("Could not resolve %s for UDP: %s", iface.c_str(), gai_strmagic(addr_ret));
return 0; return 0;
} }
} }
@ -1844,7 +1869,7 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
memset(&mreq6, 0, sizeof(mreq6)); memset(&mreq6, 0, sizeof(mreq6));
struct addrinfo *reslocal, *resmulti; struct addrinfo *reslocal, *resmulti;
if ((addr_ret = getaddrinfo(iface.c_str(), 0, &hints, &resmulti)) != 0){ if ((addr_ret = getaddrinfo(iface.c_str(), 0, &hints, &resmulti)) != 0){
WARN_MSG("Unable to parse multicast address: %s", gai_strerror(addr_ret)); WARN_MSG("Unable to parse multicast address: %s", gai_strmagic(addr_ret));
close(); close();
return 0; return 0;
} }
@ -1883,7 +1908,7 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
if (family == AF_INET6){ if (family == AF_INET6){
INFO_MSG("Registering for IPv6 multicast on interface %s", curIface.c_str()); INFO_MSG("Registering for IPv6 multicast on interface %s", curIface.c_str());
if ((addr_ret = getaddrinfo(curIface.c_str(), 0, &hints, &reslocal)) != 0){ if ((addr_ret = getaddrinfo(curIface.c_str(), 0, &hints, &reslocal)) != 0){
WARN_MSG("Unable to resolve IPv6 interface address %s: %s", curIface.c_str(), gai_strerror(addr_ret)); WARN_MSG("Unable to resolve IPv6 interface address %s: %s", curIface.c_str(), gai_strmagic(addr_ret));
continue; continue;
} }
memcpy(&mreq6.ipv6mr_multiaddr, &((sockaddr_in6 *)resmulti->ai_addr)->sin6_addr, memcpy(&mreq6.ipv6mr_multiaddr, &((sockaddr_in6 *)resmulti->ai_addr)->sin6_addr,
@ -1898,7 +1923,7 @@ uint16_t Socket::UDPConnection::bind(int port, std::string iface, const std::str
}else{ }else{
INFO_MSG("Registering for IPv4 multicast on interface %s", curIface.c_str()); INFO_MSG("Registering for IPv4 multicast on interface %s", curIface.c_str());
if ((addr_ret = getaddrinfo(curIface.c_str(), 0, &hints, &reslocal)) != 0){ if ((addr_ret = getaddrinfo(curIface.c_str(), 0, &hints, &reslocal)) != 0){
WARN_MSG("Unable to resolve IPv4 interface address %s: %s", curIface.c_str(), gai_strerror(addr_ret)); WARN_MSG("Unable to resolve IPv4 interface address %s: %s", curIface.c_str(), gai_strmagic(addr_ret));
continue; continue;
} }
mreq4.imr_multiaddr = ((sockaddr_in *)resmulti->ai_addr)->sin_addr; mreq4.imr_multiaddr = ((sockaddr_in *)resmulti->ai_addr)->sin_addr;

View file

@ -87,6 +87,12 @@ uint64_t Util::bootMS() {
return ((uint64_t)t.tv_sec) * 1000 + t.tv_nsec / 1000000; return ((uint64_t)t.tv_sec) * 1000 + t.tv_nsec / 1000000;
} }
uint64_t Util::unixMS(){
struct timeval t;
gettimeofday(&t, 0);
return ((uint64_t)t.tv_sec) * 1000 + t.tv_usec / 1000;
}
/// Gets the current time in microseconds. /// Gets the current time in microseconds.
uint64_t Util::getMicros() { uint64_t Util::getMicros() {
struct timespec t; struct timespec t;

View file

@ -11,9 +11,10 @@ namespace Util {
void sleep(int64_t ms); ///< Sleeps for roughly the indicated amount of milliseconds. void sleep(int64_t ms); ///< Sleeps for roughly the indicated amount of milliseconds.
uint64_t getMS(); ///< Gets the current time in milliseconds. uint64_t getMS(); ///< Gets the current time in milliseconds.
uint64_t bootSecs(); ///< Gets the current system uptime in seconds. uint64_t bootSecs(); ///< Gets the current system uptime in seconds.
uint64_t unixMS(); ///< Gets the current Unix time in milliseconds.
uint64_t bootMS(); ///< Gets the current system uptime in milliseconds. uint64_t bootMS(); ///< Gets the current system uptime in milliseconds.
uint64_t getMicros();///<Gets the current time in microseconds uint64_t getMicros(); ///< Gets the current time in microseconds
uint64_t getMicros(uint64_t previous);///<Gets the time difference in microseconds. uint64_t getMicros(uint64_t previous); ///< Gets the time difference in microseconds.
uint64_t getNTP(); uint64_t getNTP();
uint64_t epoch(); ///< Gets the amount of seconds since 01/01/1970. uint64_t epoch(); ///< Gets the amount of seconds since 01/01/1970.
std::string getUTCString(uint64_t epoch = 0); std::string getUTCString(uint64_t epoch = 0);

View file

@ -121,7 +121,9 @@ namespace Mist{
} }
args.push_back(""); args.push_back("");
Util::Procs::socketList.insert(fd[0]); Util::Procs::socketList.insert(fd[0]);
setenv("MIST_BOUND_ADDR", myConn.getBoundAddress().c_str(), 1);
pid_t http_proc = Util::Procs::StartPiped(args, &(fd[1]), &(fd[1]), &fderr); pid_t http_proc = Util::Procs::StartPiped(args, &(fd[1]), &(fd[1]), &fderr);
unsetenv("MIST_BOUND_ADDR");
close(fd[1]); close(fd[1]);
if (http_proc < 2){ if (http_proc < 2){
FAIL_MSG("Could not spawn MistOutHTTP process for SSL connection!"); FAIL_MSG("Could not spawn MistOutHTTP process for SSL connection!");