Removed debug information, fixed controller, made HTTP connector auto-discover connectors.

This commit is contained in:
Thulinma 2013-08-12 16:25:36 +02:00
parent 221cd15b07
commit a254fe7195
8 changed files with 110 additions and 85 deletions

View file

@ -19,6 +19,7 @@
#include <mist/stream.h>
#include <mist/timing.h>
#include <mist/auth.h>
#include <mist/procs.h>
#include "tinythread.h"
#include "embed.js.h"
@ -59,6 +60,7 @@ namespace Connector_HTTP {
tthread::mutex connMutex; ///< Mutex for adding/removing connector connections.
tthread::mutex timeoutMutex; ///< Mutex for timeout thread.
tthread::thread * timeouter = 0; ///< Thread that times out connections to connectors.
JSON::Value capabilities; ///< Holds a list of all HTTP connectors and their properties
///\brief Function run as a thread to timeout requests on the proxy.
///\param n A NULL-pointer
@ -232,56 +234,42 @@ namespace Connector_HTTP {
for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
conns.insert(( *it)["connector"].asStringRef());
}
//first, see if we have RTMP working and output all the RTMP.
//loop over the connectors.
for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
if (( *it)["connector"].asStringRef() == "RTMP"){
const std::string & cName = ( *it)["connector"].asStringRef();
//if the connector has a port,
if (capabilities.isMember(cName) && capabilities[cName].isMember("optional") && capabilities[cName]["optional"].isMember("port")){
//and a URL - then list the URL
if (capabilities[cName].isMember("url_type") && capabilities[cName].isMember("url_handler") && capabilities[cName].isMember("url_rel")){
if (( *it)["port"].asInt() == 0){
( *it)["port"] = 1935ll;
( *it)["port"] = capabilities[cName]["optional"]["port"]["default"];
}
JSON::Value tmp;
tmp["type"] = "rtmp";
tmp["url"] = "rtmp://" + host + ":" + ( *it)["port"].asString() + "/play/" + streamname;
tmp["type"] = capabilities[cName]["url_type"];
size_t found = capabilities[cName]["url_rel"].asStringRef().find('$');
if (found != std::string::npos){
tmp["relurl"] = capabilities[cName]["url_rel"].asStringRef().substr(0, found) + streamname + capabilities[cName]["url_rel"].asStringRef().substr(found+1);
}else{
tmp["relurl"] = "/";
}
tmp["url"] = capabilities[cName]["url_handler"].asStringRef() + "://" + host + ":" + ( *it)["port"].asString() + tmp["relurl"].asStringRef();
json_resp["source"].append(tmp);
}
}
/// \todo Add raw MPEG2 TS support here?
//then, see if we have HTTP working and output all the HTTP.
for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
if (( *it)["connector"].asStringRef() == "HTTP"){
if (( *it)["port"].asInt() == 0){
( *it)["port"] = 8080ll;
}
// check for dynamic
if (conns.count("HTTPDynamic")){
//check each enabled protocol separately to see if it depends on this connector
for (JSON::ObjIter oit = capabilities.ObjBegin(); oit != capabilities.ObjEnd(); oit++){
//if it depends on this connector and has a URL, list it
if (conns.count(oit->first) && oit->second["deps"].asStringRef() == cName && oit->second.isMember("url_type") && oit->second.isMember("url_handler") && oit->second.isMember("url_rel")){
JSON::Value tmp;
tmp["type"] = "f4v";
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/dynamic/" + streamname + "/manifest.f4m";
tmp["relurl"] = "/dynamic/" + streamname + "/manifest.f4m";
tmp["type"] = oit->second["url_type"];
size_t found = oit->second["url_rel"].asStringRef().find('$');
if (found != std::string::npos){
tmp["relurl"] = oit->second["url_rel"].asStringRef().substr(0, found) + streamname + oit->second["url_rel"].asStringRef().substr(found+1);
}else{
tmp["relurl"] = "/";
}
tmp["url"] = oit->second["url_handler"].asStringRef() + "://" + host + ":" + ( *it)["port"].asString() + tmp["relurl"].asStringRef();
json_resp["source"].append(tmp);
}
// check for smooth
if (conns.count("HTTPSmooth")){
JSON::Value tmp;
tmp["type"] = "ism";
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/smooth/" + streamname + ".ism/Manifest";
tmp["relurl"] = "/smooth/" + streamname + ".ism/Manifest";
json_resp["source"].append(tmp);
}
// check for HLS
if (conns.count("HTTPLive")){
JSON::Value tmp;
tmp["type"] = "hls";
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/hls/" + streamname + "/index.m3u8";
tmp["relurl"] = "/hls/" + streamname + "/index.m3u8";
json_resp["source"].append(tmp);
}
// check for progressive
if (conns.count("HTTPProgressive")){
JSON::Value tmp;
tmp["type"] = "flv";
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/" + streamname + ".flv";
tmp["relurl"] = "/" + streamname + ".flv";
json_resp["source"].append(tmp);
}
}
}
@ -325,7 +313,7 @@ namespace Connector_HTTP {
delete connectorConnections[uid];
connectorConnections.erase(uid);
}
connectorConnections[uid] = new ConnConn(new Socket::Connection("/tmp/mist/http_" + connector));
connectorConnections[uid] = new ConnConn(new Socket::Connection("/tmp/mist/" + connector));
connectorConnections[uid]->conn->setBlocking(false); //do not block on spool() with no data
#if DEBUG >= 4
std::cout << "Created new connection " << uid << std::endl;
@ -481,38 +469,46 @@ namespace Connector_HTTP {
///Possible values are:
/// - "none" The request is not supported.
/// - "internal" The request should be handled by the proxy itself.
/// - "dynamic" The request should be dispatched to the HTTP Dynamic Connector
/// - "progressive" The request should be dispatched to the HTTP Progressive Connector
/// - "smooth" The request should be dispatched to the HTTP Smooth Connector
/// - "live" The request should be dispatched to the HTTP Live Connector
/// - anything else: The request should be dispatched to a connector on the named socket.
std::string proxyGetHandleType(HTTP::Parser & H){
std::string url = H.getUrl();
if (url.find("/dynamic/") != std::string::npos){
std::string streamname = url.substr(9, url.find("/", 9) - 9);
//loop over the connectors
for (JSON::ObjIter oit = capabilities.ObjBegin(); oit != capabilities.ObjEnd(); oit++){
//if it depends on HTTP and has a match or prefix...
if (oit->second["deps"].asStringRef() == "HTTP" && oit->second.isMember("socket") && (oit->second.isMember("url_match") || oit->second.isMember("url_prefix"))){
//if there is a matcher, try to match
if (oit->second.isMember("url_match")){
size_t found = oit->second["url_match"].asStringRef().find('$');
if (found != std::string::npos){
if (oit->second["url_match"].asStringRef().substr(0, found) == url.substr(0, found) && oit->second["url_match"].asStringRef().substr(found+1) == url.substr(url.size() - (oit->second["url_match"].asStringRef().size() - found) + 1)){
//it matched - handle it now
std::string streamname = url.substr(found, url.size() - oit->second["url_match"].asStringRef().size() + 1);
Util::Stream::sanitizeName(streamname);
H.SetVar("stream", streamname);
return "dynamic";
return oit->second["socket"];
}
if (url.find("/smooth/") != std::string::npos && url.find(".ism") != std::string::npos){
std::string streamname = url.substr(8, url.find("/", 8) - 12);
}
}
//if there is a prefix, try to match
if (oit->second.isMember("url_prefix")){
size_t found = oit->second["url_prefix"].asStringRef().find('$');
if (found != std::string::npos){
size_t found_suf = url.find(oit->second["url_prefix"].asStringRef().substr(found+1), found);
if (oit->second["url_prefix"].asStringRef().substr(0, found) == url.substr(0, found) && found_suf != std::string::npos){
//it matched - handle it now
std::string streamname = url.substr(found, found_suf - found);
Util::Stream::sanitizeName(streamname);
H.SetVar("stream", streamname);
return "smooth";
return oit->second["socket"];
}
if (url.find("/hls/") != std::string::npos && (url.find(".m3u") != std::string::npos || url.find(".ts") != std::string::npos)){
std::string streamname = url.substr(5, url.find("/", 5) - 5);
Util::Stream::sanitizeName(streamname);
H.SetVar("stream", streamname);
return "live";
}
}
}
}
if (url.length() > 4){
std::string ext = url.substr(url.length() - 4, 4);
if (ext == ".flv" || ext == ".mp3"){
std::string streamname = url.substr(1, url.length() - 5);
Util::Stream::sanitizeName(streamname);
H.SetVar("stream", streamname);
return "progressive";
}
if (ext == ".ico"){
return "internal";
}
@ -607,6 +603,22 @@ int main(int argc, char ** argv){
return -1;
}
//list available protocols and report about them
std::deque<std::string> execs;
Util::getMyExec(execs);
std::string arg_one;
char const * conn_args[] = {0, "-j", 0};
for (std::deque<std::string>::iterator it = execs.begin(); it != execs.end(); it++){
if ((*it).substr(0, 8) == "MistConn"){
arg_one = Util::getMyPath() + (*it);
conn_args[0] = arg_one.c_str();
Connector_HTTP::capabilities[(*it).substr(8)] = JSON::fromString(Util::Procs::getOutputOf((char**)conn_args));
if (Connector_HTTP::capabilities[(*it).substr(8)].size() < 1){
Connector_HTTP::capabilities.removeMember((*it).substr(8));
}
}
}
Socket::Server server_socket = Socket::Server(conf.getInteger("listen_port"), conf.getString("listen_interface"));
if ( !server_socket.connected()){
return 1;

View file

@ -341,6 +341,11 @@ int main(int argc, char ** argv){
JSON::Value capa;
capa["desc"] = "Enables HTTP protocol Adobe-specific dynamic streaming (also known as HDS).";
capa["deps"] = "HTTP";
capa["url_rel"] = "/dynamic/$/manifest.f4m";
capa["url_prefix"] = "/dynamic/$/";
capa["url_handler"] = "http";
capa["url_type"] = "flash";
capa["socket"] = "http_dynamic";
conf.addBasicConnectorOptions(capa);
conf.parseArgs(argc, argv);

View file

@ -360,6 +360,11 @@ int main(int argc, char ** argv){
JSON::Value capa;
capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
capa["deps"] = "HTTP";
capa["url_rel"] = "/hls/$/index.m3u8";
capa["url_prefix"] = "/hls/$/";
capa["url_handler"] = "http";
capa["url_type"] = "hls";
capa["socket"] = "http_live";
conf.addBasicConnectorOptions(capa);
conf.parseArgs(argc, argv);

View file

@ -219,6 +219,11 @@ int main(int argc, char ** argv){
JSON::Value capa;
capa["desc"] = "Enables HTTP protocol progressive streaming.";
capa["deps"] = "HTTP";
capa["url_rel"] = "/$.flv";
capa["url_match"] = "/$.flv";
capa["url_handler"] = "http";
capa["url_type"] = "flash";
capa["socket"] = "http_progressive";
conf.addBasicConnectorOptions(capa);
conf.parseArgs(argc, argv);

View file

@ -476,6 +476,11 @@ int main(int argc, char ** argv){
JSON::Value capa;
capa["desc"] = "Enables HTTP protocol Microsoft-specific smooth streaming through silverlight (also known as HSS).";
capa["deps"] = "HTTP";
capa["url_rel"] = "/smooth/$.ism/Manifest";
capa["url_prefix"] = "/smooth/$.ism/";
capa["url_handler"] = "http";
capa["url_type"] = "ism";
capa["socket"] = "http_smooth";
conf.addBasicConnectorOptions(capa);
conf.parseArgs(argc, argv);

View file

@ -664,6 +664,9 @@ int main(int argc, char ** argv){
JSON::Value capa;
capa["desc"] = "Enables the RTMP protocol which is used by Adobe Flash Player.";
capa["deps"] = "";
capa["url_rel"] = "/play/$";
capa["url_handler"] = "rtmp";
capa["url_type"] = "flash";
conf.addConnectorOptions(1935, capa);
conf.parseArgs(argc, argv);
if (conf.getBool("json")){

View file

@ -249,7 +249,6 @@ int main(int argc, char ** argv){
char const * conn_args[] = {0, "-j", 0};
for (std::deque<std::string>::iterator it = execs.begin(); it != execs.end(); it++){
if ((*it).substr(0, 8) == "MistConn"){
std::cout << "Exec: '" << (*it) << "'" << std::endl;
arg_one = Util::getMyPath() + (*it);
conn_args[0] = arg_one.c_str();
capabilities["connectors"][(*it).substr(8)] = JSON::fromString(Util::Procs::getOutputOf((char**)conn_args));
@ -258,9 +257,6 @@ int main(int argc, char ** argv){
}
}
}
std::cout << capabilities.toPrettyString() << std::endl;
createAccount(conf.getString("account"));

View file

@ -18,7 +18,7 @@ namespace Controller {
static inline std::string toConn(long long i){
return std::string("Conn") + JSON::Value(i).asStringRef();
return std::string("Conn") + JSON::Value(i).asString();
}
///\brief Checks if the binary mentioned in the protocol argument is currently active, if so, restarts it.
@ -71,12 +71,6 @@ namespace Controller {
JSON::Value & pipedCapa = capabilities["connectors"][p["connector"].asStringRef()];
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
for (int i = 0; i < argnum; ++i){
if (argarr[i] > 0){
std::cerr << argarr[i] << " ";
}
}
std::cerr << std::endl;
}
///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary.