Skip to content

Commit b057698

Browse files
committed
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
1 parent b45fd85 commit b057698

File tree

5 files changed

+52
-28
lines changed

5 files changed

+52
-28
lines changed

lib/config.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ static Socket::Server *serv_sock_pointer = 0;
4040
uint32_t Util::Config::printDebugLevel = DEBUG; //
4141
std::string Util::Config::streamName;
4242

43+
std::string Util::listenInterface;
44+
uint32_t Util::listenPort = 0;
45+
4346
Util::Config::Config(){
4447
// global options here
4548
vals["debug"]["long"] = "debug";
@@ -341,6 +344,7 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
341344
DEVEL_MSG("Failure to open socket");
342345
return 1;
343346
}
347+
Socket::getSocketName(server_socket.getSocket(), Util::listenInterface, Util::listenPort);
344348
serv_sock_pointer = &server_socket;
345349
activate();
346350
if (server_socket.getSocket()){
@@ -368,6 +372,7 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
368372
DEVEL_MSG("Failure to open socket");
369373
return 1;
370374
}
375+
Socket::getSocketName(server_socket.getSocket(), Util::listenInterface, Util::listenPort);
371376
serv_sock_pointer = &server_socket;
372377
activate();
373378
if (server_socket.getSocket()){

lib/config.h

+5
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ namespace Util{
4949
void addConnectorOptions(int port, JSON::Value &capabilities);
5050
};
5151

52+
/// The interface address the current serveSocket function is listening on
53+
extern std::string listenInterface;
54+
/// The port the current serveSocket function is listening on
55+
extern uint32_t listenPort;
56+
5257
/// Gets directory the current executable is stored in.
5358
std::string getMyPath();
5459

lib/socket.cpp

+29-28
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,31 @@ std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host,
270270
return newaddr;
271271
}
272272

273+
/// Gets bound host and port for a socket and returns them by reference.
274+
/// Returns true on success and false on failure.
275+
bool Socket::getSocketName(int fd, std::string & host, uint32_t & port){
276+
struct sockaddr_in6 tmpaddr;
277+
socklen_t len = sizeof(tmpaddr);
278+
if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){
279+
return false;
280+
}
281+
static char addrconv[INET6_ADDRSTRLEN];
282+
if (tmpaddr.sin6_family == AF_INET6){
283+
host = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
284+
if (host.substr(0, 7) == "::ffff:"){host = host.substr(7);}
285+
port = ntohs(tmpaddr.sin6_port);
286+
HIGH_MSG("Local IPv6 addr [%s:%" PRIu32 "]", host.c_str(), port);
287+
return true;
288+
}
289+
if (tmpaddr.sin6_family == AF_INET){
290+
host = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
291+
port = ntohs(((sockaddr_in *)&tmpaddr)->sin_port);
292+
HIGH_MSG("Local IPv4 addr [%s:%" PRIu32 "]", host.c_str(), port);
293+
return true;
294+
}
295+
return false;
296+
}
297+
273298
std::string uint2string(unsigned int i){
274299
std::stringstream st;
275300
st << i;
@@ -457,20 +482,8 @@ void Socket::Connection::setBoundAddr(){
457482
return;
458483
}
459484
//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)
460-
struct sockaddr_in6 tmpaddr;
461-
socklen_t len = sizeof(tmpaddr);
462-
if (!getsockname(getSocket(), (sockaddr *)&tmpaddr, &len)){
463-
static char addrconv[INET6_ADDRSTRLEN];
464-
if (tmpaddr.sin6_family == AF_INET6){
465-
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
466-
if (boundaddr.substr(0, 7) == "::ffff:"){boundaddr = boundaddr.substr(7);}
467-
HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str());
468-
}
469-
if (tmpaddr.sin6_family == AF_INET){
470-
boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
471-
HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str());
472-
}
473-
}
485+
uint32_t boundport = 0;
486+
getSocketName(getSocket(), boundaddr, boundport);
474487
}
475488

476489
// Cleans up the socket by dropping the connection.
@@ -1741,21 +1754,9 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len){
17411754
}
17421755

17431756
std::string Socket::UDPConnection::getBoundAddress(){
1744-
struct sockaddr_in6 tmpaddr;
1745-
socklen_t len = sizeof(tmpaddr);
17461757
std::string boundaddr;
1747-
if (!getsockname(sock, (sockaddr *)&tmpaddr, &len)){
1748-
static char addrconv[INET6_ADDRSTRLEN];
1749-
if (tmpaddr.sin6_family == AF_INET6){
1750-
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
1751-
if (boundaddr.substr(0, 7) == "::ffff:"){boundaddr = boundaddr.substr(7);}
1752-
HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str());
1753-
}
1754-
if (tmpaddr.sin6_family == AF_INET){
1755-
boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
1756-
HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str());
1757-
}
1758-
}
1758+
uint32_t boundport;
1759+
Socket::getSocketName(sock, boundaddr, boundport);
17591760
return boundaddr;
17601761
}
17611762

lib/socket.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace Socket{
4444
bool checkTrueSocket(int sock);
4545
std::string resolveHostToBestExternalAddrGuess(const std::string &host, int family = AF_UNSPEC,
4646
const std::string &hint = "");
47+
bool getSocketName(int fd, std::string & host, uint32_t & port);
4748

4849
/// A buffer made out of std::string objects that can be efficiently read from and written to.
4950
class Buffer{

src/controller/controller_api.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <dirent.h> //for browse API call
22
#include <sys/stat.h> //for browse API call
33
#include <mist/http_parser.h>
4+
#include <mist/url.h>
45
#include <mist/auth.h>
56
#include <mist/config.h>
67
#include <mist/defines.h>
@@ -368,6 +369,7 @@ void Controller::handleUDPAPI(void * np){
368369
return;
369370
}
370371
Util::Procs::socketList.insert(uSock.getSock());
372+
uSock.SetDestination(UDP_API_HOST, UDP_API_PORT);
371373
while (Controller::conf.is_active){
372374
if (uSock.Receive()){
373375
MEDIUM_MSG("UDP API: %s", uSock.data);
@@ -377,6 +379,7 @@ void Controller::handleUDPAPI(void * np){
377379
if (Request.isObject()){
378380
tthread::lock_guard<tthread::mutex> guard(configMutex);
379381
handleAPICommands(Request, Response);
382+
uSock.SendNow(Response.toString());
380383
}else{
381384
WARN_MSG("Invalid API command received over UDP: %s", uSock.data);
382385
}
@@ -639,6 +642,15 @@ void Controller::handleAPICommands(JSON::Value & Request, JSON::Value & Response
639642
if (Request.isMember("stats_streams")){
640643
Controller::fillActive(Request["stats_streams"], Response["stats_streams"]);
641644
}
645+
646+
if (Request.isMember("api_endpoint")){
647+
HTTP::URL url("http://localhost:4242");
648+
url.host = Util::listenInterface;
649+
if (url.host == "::"){url.host = "::1";}
650+
if (url.host == "0.0.0.0"){url.host = "127.0.0.1";}
651+
url.port = JSON::Value(Util::listenPort).asString();
652+
Response["api_endpoint"] = url.getUrl();
653+
}
642654

643655
Controller::configChanged = true;
644656
}

0 commit comments

Comments
 (0)