Added api_endpoint API call to give local API endpoint address, added responses to local-only UDP API, added Socket::getSocketName(), added ability to discover current listening interface address and port for serveSocket-style functions

This commit is contained in:
Thulinma 2020-07-15 19:29:16 +02:00
parent b45fd85b95
commit b057698018
5 changed files with 52 additions and 28 deletions

View file

@ -40,6 +40,9 @@ static Socket::Server *serv_sock_pointer = 0;
uint32_t Util::Config::printDebugLevel = DEBUG; //
std::string Util::Config::streamName;
std::string Util::listenInterface;
uint32_t Util::listenPort = 0;
Util::Config::Config(){
// global options here
vals["debug"]["long"] = "debug";
@ -341,6 +344,7 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
DEVEL_MSG("Failure to open socket");
return 1;
}
Socket::getSocketName(server_socket.getSocket(), Util::listenInterface, Util::listenPort);
serv_sock_pointer = &server_socket;
activate();
if (server_socket.getSocket()){
@ -368,6 +372,7 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
DEVEL_MSG("Failure to open socket");
return 1;
}
Socket::getSocketName(server_socket.getSocket(), Util::listenInterface, Util::listenPort);
serv_sock_pointer = &server_socket;
activate();
if (server_socket.getSocket()){

View file

@ -49,6 +49,11 @@ namespace Util{
void addConnectorOptions(int port, JSON::Value &capabilities);
};
/// The interface address the current serveSocket function is listening on
extern std::string listenInterface;
/// The port the current serveSocket function is listening on
extern uint32_t listenPort;
/// Gets directory the current executable is stored in.
std::string getMyPath();

View file

@ -270,6 +270,31 @@ std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host,
return newaddr;
}
/// Gets bound host and port for a socket and returns them by reference.
/// Returns true on success and false on failure.
bool Socket::getSocketName(int fd, std::string & host, uint32_t & port){
struct sockaddr_in6 tmpaddr;
socklen_t len = sizeof(tmpaddr);
if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){
return false;
}
static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){
host = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
if (host.substr(0, 7) == "::ffff:"){host = host.substr(7);}
port = ntohs(tmpaddr.sin6_port);
HIGH_MSG("Local IPv6 addr [%s:%" PRIu32 "]", host.c_str(), port);
return true;
}
if (tmpaddr.sin6_family == AF_INET){
host = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
port = ntohs(((sockaddr_in *)&tmpaddr)->sin_port);
HIGH_MSG("Local IPv4 addr [%s:%" PRIu32 "]", host.c_str(), port);
return true;
}
return false;
}
std::string uint2string(unsigned int i){
std::stringstream st;
st << i;
@ -457,20 +482,8 @@ void Socket::Connection::setBoundAddr(){
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;
socklen_t len = sizeof(tmpaddr);
if (!getsockname(getSocket(), (sockaddr *)&tmpaddr, &len)){
static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
if (boundaddr.substr(0, 7) == "::ffff:"){boundaddr = boundaddr.substr(7);}
HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str());
}
if (tmpaddr.sin6_family == AF_INET){
boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str());
}
}
uint32_t boundport = 0;
getSocketName(getSocket(), boundaddr, boundport);
}
// Cleans up the socket by dropping the connection.
@ -1741,21 +1754,9 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len){
}
std::string Socket::UDPConnection::getBoundAddress(){
struct sockaddr_in6 tmpaddr;
socklen_t len = sizeof(tmpaddr);
std::string boundaddr;
if (!getsockname(sock, (sockaddr *)&tmpaddr, &len)){
static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
if (boundaddr.substr(0, 7) == "::ffff:"){boundaddr = boundaddr.substr(7);}
HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str());
}
if (tmpaddr.sin6_family == AF_INET){
boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str());
}
}
uint32_t boundport;
Socket::getSocketName(sock, boundaddr, boundport);
return boundaddr;
}

View file

@ -44,6 +44,7 @@ namespace Socket{
bool checkTrueSocket(int sock);
std::string resolveHostToBestExternalAddrGuess(const std::string &host, int family = AF_UNSPEC,
const std::string &hint = "");
bool getSocketName(int fd, std::string & host, uint32_t & port);
/// A buffer made out of std::string objects that can be efficiently read from and written to.
class Buffer{

View file

@ -1,6 +1,7 @@
#include <dirent.h> //for browse API call
#include <sys/stat.h> //for browse API call
#include <mist/http_parser.h>
#include <mist/url.h>
#include <mist/auth.h>
#include <mist/config.h>
#include <mist/defines.h>
@ -368,6 +369,7 @@ void Controller::handleUDPAPI(void * np){
return;
}
Util::Procs::socketList.insert(uSock.getSock());
uSock.SetDestination(UDP_API_HOST, UDP_API_PORT);
while (Controller::conf.is_active){
if (uSock.Receive()){
MEDIUM_MSG("UDP API: %s", uSock.data);
@ -377,6 +379,7 @@ void Controller::handleUDPAPI(void * np){
if (Request.isObject()){
tthread::lock_guard<tthread::mutex> guard(configMutex);
handleAPICommands(Request, Response);
uSock.SendNow(Response.toString());
}else{
WARN_MSG("Invalid API command received over UDP: %s", uSock.data);
}
@ -639,6 +642,15 @@ void Controller::handleAPICommands(JSON::Value & Request, JSON::Value & Response
if (Request.isMember("stats_streams")){
Controller::fillActive(Request["stats_streams"], Response["stats_streams"]);
}
if (Request.isMember("api_endpoint")){
HTTP::URL url("http://localhost:4242");
url.host = Util::listenInterface;
if (url.host == "::"){url.host = "::1";}
if (url.host == "0.0.0.0"){url.host = "127.0.0.1";}
url.port = JSON::Value(Util::listenPort).asString();
Response["api_endpoint"] = url.getUrl();
}
Controller::configChanged = true;
}