Removed debug information, fixed controller, made HTTP connector auto-discover connectors.
This commit is contained in:
parent
221cd15b07
commit
a254fe7195
8 changed files with 110 additions and 85 deletions
|
@ -19,6 +19,7 @@
|
||||||
#include <mist/stream.h>
|
#include <mist/stream.h>
|
||||||
#include <mist/timing.h>
|
#include <mist/timing.h>
|
||||||
#include <mist/auth.h>
|
#include <mist/auth.h>
|
||||||
|
#include <mist/procs.h>
|
||||||
|
|
||||||
#include "tinythread.h"
|
#include "tinythread.h"
|
||||||
#include "embed.js.h"
|
#include "embed.js.h"
|
||||||
|
@ -59,6 +60,7 @@ namespace Connector_HTTP {
|
||||||
tthread::mutex connMutex; ///< Mutex for adding/removing connector connections.
|
tthread::mutex connMutex; ///< Mutex for adding/removing connector connections.
|
||||||
tthread::mutex timeoutMutex; ///< Mutex for timeout thread.
|
tthread::mutex timeoutMutex; ///< Mutex for timeout thread.
|
||||||
tthread::thread * timeouter = 0; ///< Thread that times out connections to connectors.
|
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.
|
///\brief Function run as a thread to timeout requests on the proxy.
|
||||||
///\param n A NULL-pointer
|
///\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++){
|
for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
|
||||||
conns.insert(( *it)["connector"].asStringRef());
|
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++){
|
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 (( *it)["port"].asInt() == 0){
|
//if the connector has a port,
|
||||||
( *it)["port"] = 1935ll;
|
if (capabilities.isMember(cName) && capabilities[cName].isMember("optional") && capabilities[cName]["optional"].isMember("port")){
|
||||||
}
|
//and a URL - then list the URL
|
||||||
JSON::Value tmp;
|
if (capabilities[cName].isMember("url_type") && capabilities[cName].isMember("url_handler") && capabilities[cName].isMember("url_rel")){
|
||||||
tmp["type"] = "rtmp";
|
if (( *it)["port"].asInt() == 0){
|
||||||
tmp["url"] = "rtmp://" + host + ":" + ( *it)["port"].asString() + "/play/" + streamname;
|
( *it)["port"] = capabilities[cName]["optional"]["port"]["default"];
|
||||||
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")){
|
|
||||||
JSON::Value tmp;
|
JSON::Value tmp;
|
||||||
tmp["type"] = "f4v";
|
tmp["type"] = capabilities[cName]["url_type"];
|
||||||
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/dynamic/" + streamname + "/manifest.f4m";
|
size_t found = capabilities[cName]["url_rel"].asStringRef().find('$');
|
||||||
tmp["relurl"] = "/dynamic/" + streamname + "/manifest.f4m";
|
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);
|
json_resp["source"].append(tmp);
|
||||||
}
|
}
|
||||||
// check for smooth
|
//check each enabled protocol separately to see if it depends on this connector
|
||||||
if (conns.count("HTTPSmooth")){
|
for (JSON::ObjIter oit = capabilities.ObjBegin(); oit != capabilities.ObjEnd(); oit++){
|
||||||
JSON::Value tmp;
|
//if it depends on this connector and has a URL, list it
|
||||||
tmp["type"] = "ism";
|
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")){
|
||||||
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/smooth/" + streamname + ".ism/Manifest";
|
JSON::Value tmp;
|
||||||
tmp["relurl"] = "/smooth/" + streamname + ".ism/Manifest";
|
tmp["type"] = oit->second["url_type"];
|
||||||
json_resp["source"].append(tmp);
|
size_t found = oit->second["url_rel"].asStringRef().find('$');
|
||||||
}
|
if (found != std::string::npos){
|
||||||
// check for HLS
|
tmp["relurl"] = oit->second["url_rel"].asStringRef().substr(0, found) + streamname + oit->second["url_rel"].asStringRef().substr(found+1);
|
||||||
if (conns.count("HTTPLive")){
|
}else{
|
||||||
JSON::Value tmp;
|
tmp["relurl"] = "/";
|
||||||
tmp["type"] = "hls";
|
}
|
||||||
tmp["url"] = "http://" + host + ":" + ( *it)["port"].asString() + "/hls/" + streamname + "/index.m3u8";
|
tmp["url"] = oit->second["url_handler"].asStringRef() + "://" + host + ":" + ( *it)["port"].asString() + tmp["relurl"].asStringRef();
|
||||||
tmp["relurl"] = "/hls/" + streamname + "/index.m3u8";
|
json_resp["source"].append(tmp);
|
||||||
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];
|
delete connectorConnections[uid];
|
||||||
connectorConnections.erase(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
|
connectorConnections[uid]->conn->setBlocking(false); //do not block on spool() with no data
|
||||||
#if DEBUG >= 4
|
#if DEBUG >= 4
|
||||||
std::cout << "Created new connection " << uid << std::endl;
|
std::cout << "Created new connection " << uid << std::endl;
|
||||||
|
@ -481,38 +469,46 @@ namespace Connector_HTTP {
|
||||||
///Possible values are:
|
///Possible values are:
|
||||||
/// - "none" The request is not supported.
|
/// - "none" The request is not supported.
|
||||||
/// - "internal" The request should be handled by the proxy itself.
|
/// - "internal" The request should be handled by the proxy itself.
|
||||||
/// - "dynamic" The request should be dispatched to the HTTP Dynamic Connector
|
/// - anything else: The request should be dispatched to a connector on the named socket.
|
||||||
/// - "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
|
|
||||||
std::string proxyGetHandleType(HTTP::Parser & H){
|
std::string proxyGetHandleType(HTTP::Parser & H){
|
||||||
std::string url = H.getUrl();
|
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
|
||||||
Util::Stream::sanitizeName(streamname);
|
for (JSON::ObjIter oit = capabilities.ObjBegin(); oit != capabilities.ObjEnd(); oit++){
|
||||||
H.SetVar("stream", streamname);
|
//if it depends on HTTP and has a match or prefix...
|
||||||
return "dynamic";
|
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 (url.find("/smooth/") != std::string::npos && url.find(".ism") != std::string::npos){
|
if (oit->second.isMember("url_match")){
|
||||||
std::string streamname = url.substr(8, url.find("/", 8) - 12);
|
size_t found = oit->second["url_match"].asStringRef().find('$');
|
||||||
Util::Stream::sanitizeName(streamname);
|
if (found != std::string::npos){
|
||||||
H.SetVar("stream", streamname);
|
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)){
|
||||||
return "smooth";
|
//it matched - handle it now
|
||||||
}
|
std::string streamname = url.substr(found, url.size() - oit->second["url_match"].asStringRef().size() + 1);
|
||||||
if (url.find("/hls/") != std::string::npos && (url.find(".m3u") != std::string::npos || url.find(".ts") != std::string::npos)){
|
Util::Stream::sanitizeName(streamname);
|
||||||
std::string streamname = url.substr(5, url.find("/", 5) - 5);
|
H.SetVar("stream", streamname);
|
||||||
Util::Stream::sanitizeName(streamname);
|
return oit->second["socket"];
|
||||||
H.SetVar("stream", streamname);
|
}
|
||||||
return "live";
|
}
|
||||||
|
}
|
||||||
|
//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 oit->second["socket"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.length() > 4){
|
if (url.length() > 4){
|
||||||
std::string ext = url.substr(url.length() - 4, 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"){
|
if (ext == ".ico"){
|
||||||
return "internal";
|
return "internal";
|
||||||
}
|
}
|
||||||
|
@ -607,6 +603,22 @@ int main(int argc, char ** argv){
|
||||||
return -1;
|
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"));
|
Socket::Server server_socket = Socket::Server(conf.getInteger("listen_port"), conf.getString("listen_interface"));
|
||||||
if ( !server_socket.connected()){
|
if ( !server_socket.connected()){
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -341,6 +341,11 @@ int main(int argc, char ** argv){
|
||||||
JSON::Value capa;
|
JSON::Value capa;
|
||||||
capa["desc"] = "Enables HTTP protocol Adobe-specific dynamic streaming (also known as HDS).";
|
capa["desc"] = "Enables HTTP protocol Adobe-specific dynamic streaming (also known as HDS).";
|
||||||
capa["deps"] = "HTTP";
|
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.addBasicConnectorOptions(capa);
|
||||||
conf.parseArgs(argc, argv);
|
conf.parseArgs(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -360,6 +360,11 @@ int main(int argc, char ** argv){
|
||||||
JSON::Value capa;
|
JSON::Value capa;
|
||||||
capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
|
capa["desc"] = "Enables HTTP protocol Apple-specific streaming (also known as HLS).";
|
||||||
capa["deps"] = "HTTP";
|
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.addBasicConnectorOptions(capa);
|
||||||
conf.parseArgs(argc, argv);
|
conf.parseArgs(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,11 @@ int main(int argc, char ** argv){
|
||||||
JSON::Value capa;
|
JSON::Value capa;
|
||||||
capa["desc"] = "Enables HTTP protocol progressive streaming.";
|
capa["desc"] = "Enables HTTP protocol progressive streaming.";
|
||||||
capa["deps"] = "HTTP";
|
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.addBasicConnectorOptions(capa);
|
||||||
conf.parseArgs(argc, argv);
|
conf.parseArgs(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -476,6 +476,11 @@ int main(int argc, char ** argv){
|
||||||
JSON::Value capa;
|
JSON::Value capa;
|
||||||
capa["desc"] = "Enables HTTP protocol Microsoft-specific smooth streaming through silverlight (also known as HSS).";
|
capa["desc"] = "Enables HTTP protocol Microsoft-specific smooth streaming through silverlight (also known as HSS).";
|
||||||
capa["deps"] = "HTTP";
|
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.addBasicConnectorOptions(capa);
|
||||||
conf.parseArgs(argc, argv);
|
conf.parseArgs(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -664,6 +664,9 @@ int main(int argc, char ** argv){
|
||||||
JSON::Value capa;
|
JSON::Value capa;
|
||||||
capa["desc"] = "Enables the RTMP protocol which is used by Adobe Flash Player.";
|
capa["desc"] = "Enables the RTMP protocol which is used by Adobe Flash Player.";
|
||||||
capa["deps"] = "";
|
capa["deps"] = "";
|
||||||
|
capa["url_rel"] = "/play/$";
|
||||||
|
capa["url_handler"] = "rtmp";
|
||||||
|
capa["url_type"] = "flash";
|
||||||
conf.addConnectorOptions(1935, capa);
|
conf.addConnectorOptions(1935, capa);
|
||||||
conf.parseArgs(argc, argv);
|
conf.parseArgs(argc, argv);
|
||||||
if (conf.getBool("json")){
|
if (conf.getBool("json")){
|
||||||
|
|
|
@ -249,7 +249,6 @@ int main(int argc, char ** argv){
|
||||||
char const * conn_args[] = {0, "-j", 0};
|
char const * conn_args[] = {0, "-j", 0};
|
||||||
for (std::deque<std::string>::iterator it = execs.begin(); it != execs.end(); it++){
|
for (std::deque<std::string>::iterator it = execs.begin(); it != execs.end(); it++){
|
||||||
if ((*it).substr(0, 8) == "MistConn"){
|
if ((*it).substr(0, 8) == "MistConn"){
|
||||||
std::cout << "Exec: '" << (*it) << "'" << std::endl;
|
|
||||||
arg_one = Util::getMyPath() + (*it);
|
arg_one = Util::getMyPath() + (*it);
|
||||||
conn_args[0] = arg_one.c_str();
|
conn_args[0] = arg_one.c_str();
|
||||||
capabilities["connectors"][(*it).substr(8)] = JSON::fromString(Util::Procs::getOutputOf((char**)conn_args));
|
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"));
|
createAccount(conf.getString("account"));
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Controller {
|
||||||
|
|
||||||
|
|
||||||
static inline std::string toConn(long long i){
|
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.
|
///\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()];
|
JSON::Value & pipedCapa = capabilities["connectors"][p["connector"].asStringRef()];
|
||||||
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
|
if (pipedCapa.isMember("required")){builPipedPart(p, argarr, argnum, pipedCapa["required"]);}
|
||||||
if (pipedCapa.isMember("optional")){builPipedPart(p, argarr, argnum, pipedCapa["optional"]);}
|
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.
|
///\brief Checks current protocol coguration, updates state of enabled connectors if neccesary.
|
||||||
|
|
Loading…
Add table
Reference in a new issue