Support for multiple public addresses, as well as proxy-overridden public addresses

This commit is contained in:
Thulinma 2020-01-23 16:51:15 +01:00
parent 131eb58c6a
commit cd19cca36b
4 changed files with 60 additions and 23 deletions

View file

@ -282,6 +282,14 @@ namespace Mist {
if ((*it)["type"].asStringRef() == "uint" || (*it)["type"].asStringRef() == "int" || (*it)["type"].asStringRef() == "debug"){ if ((*it)["type"].asStringRef() == "uint" || (*it)["type"].asStringRef() == "int" || (*it)["type"].asStringRef() == "debug"){
p[it.key()] = JSON::Value(p[it.key()].asInt()).asString(); p[it.key()] = JSON::Value(p[it.key()].asInt()).asString();
} }
if ((*it)["type"].asStringRef() == "inputlist" && p[it.key()].isArray()){
jsonForEach(p[it.key()], iVal){
(*iVal) = iVal->asString();
argarr[argnum++] = (char*)((*it)["option"].c_str());
argarr[argnum++] = (char*)((*iVal).c_str());
}
continue;
}
} }
if (p[it.key()].asStringRef().size() > 0){ if (p[it.key()].asStringRef().size() > 0){
argarr[argnum++] = (char*)((*it)["option"].c_str()); argarr[argnum++] = (char*)((*it)["option"].c_str());
@ -312,7 +320,8 @@ namespace Mist {
if (connector == "HTTP" || connector == "HTTP.exe"){ if (connector == "HTTP" || connector == "HTTP.exe"){
//restore from values in the environment, regardless of configged settings //restore from values in the environment, regardless of configged settings
if (getenv("MIST_HTTP_pubaddr")){ if (getenv("MIST_HTTP_pubaddr")){
p["pubaddr"] = getenv("MIST_HTTP_pubaddr"); std::string pubAddrs = getenv("MIST_HTTP_pubaddr");
p["pubaddr"] = JSON::fromString(pubAddrs);
} }
}else{ }else{
//find connector in config //find connector in config

View file

@ -46,7 +46,8 @@ namespace Mist {
myConn.setHost(host); myConn.setHost(host);
} }
if (config->getString("pubaddr").size()){ if (config->getString("pubaddr").size()){
setenv("MIST_HTTP_pubaddr", config->getString("pubaddr").c_str(), 1); std::string pubAddrs = config->getOption("pubaddr", true).toString();
setenv("MIST_HTTP_pubaddr", pubAddrs.c_str(), 1);
} }
if (config->getOption("wrappers",true).size() == 0 || config->getString("wrappers") == ""){ if (config->getOption("wrappers",true).size() == 0 || config->getString("wrappers") == ""){
JSON::Value & wrappers = config->getOption("wrappers",true); JSON::Value & wrappers = config->getOption("wrappers",true);
@ -149,7 +150,7 @@ namespace Mist {
capa["optional"]["pubaddr"]["name"] = "Public address"; capa["optional"]["pubaddr"]["name"] = "Public address";
capa["optional"]["pubaddr"]["help"] = "Full public address this output is available as, if being proxied"; capa["optional"]["pubaddr"]["help"] = "Full public address this output is available as, if being proxied";
capa["optional"]["pubaddr"]["default"] = ""; capa["optional"]["pubaddr"]["default"] = "";
capa["optional"]["pubaddr"]["type"] = "str"; capa["optional"]["pubaddr"]["type"] = "inputlist";
capa["optional"]["pubaddr"]["option"] = "--public-address"; capa["optional"]["pubaddr"]["option"] = "--public-address";
} }
@ -196,15 +197,12 @@ namespace Mist {
if (conncapa.isMember("player_url")){tmp["player_url"] = conncapa["player_url"].asStringRef();} if (conncapa.isMember("player_url")){tmp["player_url"] = conncapa["player_url"].asStringRef();}
tmp["simul_tracks"] = most_simul; tmp["simul_tracks"] = most_simul;
tmp["total_matches"] = total_matches; tmp["total_matches"] = total_matches;
if (url.path.size()){ tmp["url"] = url.link(rel).getUrl();
tmp["url"] = url.protocol + "://" + url.host + ":" + url.port + "/" + url.path + rel;
}else{
tmp["url"] = url.protocol + "://" + url.host + ":" + url.port + rel;
}
sources.insert(tmp); sources.insert(tmp);
} }
void addSources(std::string & streamname, std::set<JSON::Value, sourceCompare> & sources, HTTP::URL url, JSON::Value & conncapa, JSON::Value & strmMeta, const std::string & useragent){ void addSources(std::string & streamname, std::set<JSON::Value, sourceCompare> & sources, HTTP::URL url, JSON::Value & conncapa, JSON::Value & strmMeta, const std::string & useragent){
url.path += "/";
if (strmMeta.isMember("live") && conncapa.isMember("exceptions") && conncapa["exceptions"].isObject() && conncapa["exceptions"].size()){ if (strmMeta.isMember("live") && conncapa.isMember("exceptions") && conncapa["exceptions"].isObject() && conncapa["exceptions"].size()){
jsonForEach(conncapa["exceptions"], ex){ jsonForEach(conncapa["exceptions"], ex){
if (ex.key() == "live"){ if (ex.key() == "live"){
@ -264,15 +262,15 @@ namespace Mist {
std::string relurl; std::string relurl;
size_t found = rel.find('$'); size_t found = rel.find('$');
if (found != std::string::npos){ if (found != std::string::npos){
relurl = rel.substr(0, found) + Encodings::URL::encode(streamname) + rel.substr(found+1); relurl = rel.substr(1, found-1) + Encodings::URL::encode(streamname) + rel.substr(found+1);
}else{ }else{
relurl = "/"; relurl = "";
} }
jsonForEach(conncapa["methods"], it) { jsonForEach(conncapa["methods"], it) {
if (it->isMember("url_rel")){ if (it->isMember("url_rel")){
size_t foundb = (*it)["url_rel"].asStringRef().find('$'); size_t foundb = (*it)["url_rel"].asStringRef().find('$');
if (foundb != std::string::npos){ if (foundb != std::string::npos){
relurl = (*it)["url_rel"].asStringRef().substr(0, foundb) + Encodings::URL::encode(streamname) + (*it)["url_rel"].asStringRef().substr(foundb+1); relurl = (*it)["url_rel"].asStringRef().substr(1, foundb-1) + Encodings::URL::encode(streamname) + (*it)["url_rel"].asStringRef().substr(foundb+1);
} }
} }
if (!strmMeta.isMember("live") || !it->isMember("nolive")){ if (!strmMeta.isMember("live") || !it->isMember("nolive")){
@ -298,6 +296,7 @@ namespace Mist {
fullURL.port = altURL.port; fullURL.port = altURL.port;
fullURL.path = altURL.path; fullURL.path = altURL.path;
} }
if (mistPath.size()){fullURL = mistPath;}
std::string uAgent = H.GetHeader("User-Agent"); std::string uAgent = H.GetHeader("User-Agent");
std::string forceType = ""; std::string forceType = "";
@ -454,17 +453,30 @@ namespace Mist {
if (outURL.protocol.find(':') != std::string::npos){ if (outURL.protocol.find(':') != std::string::npos){
outURL.protocol.erase(outURL.protocol.find(':')); outURL.protocol.erase(outURL.protocol.find(':'));
} }
if (prots.getIndice(i).hasMember("pubaddr") && prots.getIndice(i).getMember("pubaddr").asString().size()){ JSON::Value pubAddrs;
HTTP::URL altURL(prots.getIndice(i).getMember("pubaddr").asString()); pubAddrs.append("");
outURL.protocol = altURL.protocol; if (prots.getIndice(i).hasMember("pubaddr") && prots.getIndice(i).getMember("pubaddr").getType() == DTSC_STR){
if (altURL.host.size()){outURL.host = altURL.host;} if (prots.getIndice(i).getMember("pubaddr").asString().size()){
outURL.port = altURL.port; pubAddrs[0u] = prots.getIndice(i).getMember("pubaddr").asString();
outURL.path = altURL.path; }
}
if (prots.getIndice(i).hasMember("pubaddr") && prots.getIndice(i).getMember("pubaddr").getType() == DTSC_ARR){
pubAddrs = prots.getIndice(i).getMember("pubaddr").asJSON();
}
if (mistPath.size()){
pubAddrs.null();
pubAddrs.append(mistPath);
} }
//and a URL - then list the URL //and a URL - then list the URL
JSON::Value capa_json = capa.asJSON(); JSON::Value capa_json = capa.asJSON();
if (capa.getMember("url_rel") || capa.getMember("methods")){ if (capa.getMember("url_rel") || capa.getMember("methods")){
addSources(streamName, sources, outURL, capa_json, json_resp["meta"], useragent); jsonForEach(pubAddrs, jit){
HTTP::URL altURL = outURL;
if (jit->asString().size()){altURL = jit->asString();}
if (!altURL.host.size()){altURL.host = outURL.host;}
if (!altURL.protocol.size()){altURL.protocol = outURL.protocol;}
addSources(streamName, sources, altURL, capa_json, json_resp["meta"], useragent);
}
} }
//Make note if this connector can be depended upon by other connectors //Make note if this connector can be depended upon by other connectors
if (capa.getMember("provides")){ if (capa.getMember("provides")){
@ -476,7 +488,14 @@ namespace Mist {
//if it depends on this connector and has a URL, list it //if it depends on this connector and has a URL, list it
if (conns.count(connectors.getIndiceName(j)) && connectors.getIndice(j).getMember("deps").asString() == cProv && connectors.getIndice(j).getMember("methods")){ if (conns.count(connectors.getIndiceName(j)) && connectors.getIndice(j).getMember("deps").asString() == cProv && connectors.getIndice(j).getMember("methods")){
JSON::Value subcapa_json = connectors.getIndice(j).asJSON(); JSON::Value subcapa_json = connectors.getIndice(j).asJSON();
addSources(streamName, sources, outURL, subcapa_json, json_resp["meta"], useragent);
jsonForEach(pubAddrs, jit){
HTTP::URL altURL = outURL;
if (jit->asString().size()){altURL = jit->asString();}
if (!altURL.host.size()){altURL.host = outURL.host;}
if (!altURL.protocol.size()){altURL.protocol = outURL.protocol;}
addSources(streamName, sources, altURL, subcapa_json, json_resp["meta"], useragent);
}
} }
} }
} }
@ -495,6 +514,8 @@ namespace Mist {
void OutHTTP::onHTTP(){ void OutHTTP::onHTTP(){
std::string method = H.method; std::string method = H.method;
if (H.GetHeader("X-Mst-Path").size()){mistPath = H.GetHeader("X-Mst-Path");}
//Handle certbot validations //Handle certbot validations
if (H.url.substr(0, 28) == "/.well-known/acme-challenge/"){ if (H.url.substr(0, 28) == "/.well-known/acme-challenge/"){
std::string cbToken = H.url.substr(28); std::string cbToken = H.url.substr(28);
@ -682,6 +703,7 @@ namespace Mist {
fullURL.port = altURL.port; fullURL.port = altURL.port;
fullURL.path = altURL.path; fullURL.path = altURL.path;
} }
if (mistPath.size()){fullURL = mistPath;}
std::string response; std::string response;
std::string rURL = H.url; std::string rURL = H.url;
H.Clean(); H.Clean();
@ -864,6 +886,7 @@ namespace Mist {
bool OutHTTP::websocketHandler(){ bool OutHTTP::websocketHandler(){
stayConnected = true; stayConnected = true;
std::string reqHost = HTTP::URL(H.GetHeader("Host")).host; std::string reqHost = HTTP::URL(H.GetHeader("Host")).host;
if (H.GetHeader("X-Mst-Path").size()){mistPath = H.GetHeader("X-Mst-Path");}
std::string useragent = H.GetVar("ua"); std::string useragent = H.GetVar("ua");
if (!useragent.size()){ if (!useragent.size()){
useragent = H.GetHeader("User-Agent"); useragent = H.GetHeader("User-Agent");

View file

@ -20,6 +20,8 @@ namespace Mist {
virtual bool onFinish(){ virtual bool onFinish(){
return stayConnected; return stayConnected;
} }
private:
std::string mistPath;
}; };
} }

View file

@ -45,7 +45,7 @@ namespace Mist{
capa["optional"]["pubaddr"]["name"] = "Public address"; capa["optional"]["pubaddr"]["name"] = "Public address";
capa["optional"]["pubaddr"]["help"] = "Full public address this output is available as, if being proxied"; capa["optional"]["pubaddr"]["help"] = "Full public address this output is available as, if being proxied";
capa["optional"]["pubaddr"]["default"] = ""; capa["optional"]["pubaddr"]["default"] = "";
capa["optional"]["pubaddr"]["type"] = "str"; capa["optional"]["pubaddr"]["type"] = "inputlist";
capa["optional"]["pubaddr"]["option"] = "--public-address"; capa["optional"]["pubaddr"]["option"] = "--public-address";
config = cfg; config = cfg;
} }
@ -102,9 +102,12 @@ namespace Mist{
args.push_back(Util::getMyPath() + "MistOutHTTP"); args.push_back(Util::getMyPath() + "MistOutHTTP");
args.push_back("--ip"); args.push_back("--ip");
args.push_back(myConn.getHost()); args.push_back(myConn.getHost());
if (config->getString("pubaddr").size()){ if (config->getOption("pubaddr", true).size()){
args.push_back("--public-address"); JSON::Value pubAddrs = config->getOption("pubaddr", true);
args.push_back(config->getString("pubaddr")); jsonForEach(pubAddrs, jIt){
args.push_back("--public-address");
args.push_back(jIt->asStringRef());
}
} }
args.push_back(""); args.push_back("");
Util::Procs::socketList.insert(fd[0]); Util::Procs::socketList.insert(fd[0]);