Added skipDynamic optional argument to most binary representations of metadata/tracks, which skips sending dynamic parts of the metadata if true.
This commit is contained in:
parent
10af060ab4
commit
668560ff05
11 changed files with 344 additions and 111 deletions
|
@ -23,7 +23,9 @@ namespace Analysers {
|
|||
std::cerr << "Not a valid DTSC file" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
F.getMeta().toPrettyString(std::cout,0, 0x03);
|
||||
if (F.getMeta().vod || F.getMeta().live){
|
||||
F.getMeta().toPrettyString(std::cout,0, 0x03);
|
||||
}
|
||||
|
||||
int bPos = 0;
|
||||
F.seek_bpos(0);
|
||||
|
@ -42,6 +44,10 @@ namespace Analysers {
|
|||
std::cout << "DTSC header: " << F.getPacket().getScan().toPrettyString() << std::endl;
|
||||
break;
|
||||
}
|
||||
case DTSC::DTCM: {
|
||||
std::cout << "DTCM command: " << F.getPacket().getScan().toPrettyString() << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG_MSG(DLVL_WARN,"Invalid dtsc packet @ bpos %d", bPos);
|
||||
break;
|
||||
|
|
|
@ -240,6 +240,58 @@ namespace Mist {
|
|||
//end player functionality
|
||||
}
|
||||
|
||||
/// Main loop for stream-style inputs.
|
||||
/// This loop will start the buffer without resume support, and then repeatedly call ..... followed by ....
|
||||
void Input::stream(){
|
||||
char userPageName[NAME_BUFFER_SIZE];
|
||||
snprintf(userPageName, NAME_BUFFER_SIZE, SHM_USERS, streamName.c_str());
|
||||
/*LTS-START*/
|
||||
if(Triggers::shouldTrigger("STREAM_READY", config->getString("streamname"))){
|
||||
std::string payload = config->getString("streamname")+"\n" +capa["name"].asStringRef()+"\n";
|
||||
if (!Triggers::doTrigger("STREAM_READY", payload, config->getString("streamname"))){
|
||||
config->is_active = false;
|
||||
}
|
||||
}
|
||||
/*LTS-END*/
|
||||
userPage.init(userPageName, PLAY_EX_SIZE, true);
|
||||
if (!isBuffer) {
|
||||
for (std::map<unsigned int, DTSC::Track>::iterator it = myMeta.tracks.begin(); it != myMeta.tracks.end(); it++) {
|
||||
bufferFrame(it->first, 1);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MSG(DLVL_DEVEL, "Input for stream %s started", streamName.c_str());
|
||||
|
||||
long long int activityCounter = Util::bootSecs();
|
||||
while ((Util::bootSecs() - activityCounter) < 10 && config->is_active) { //10 second timeout
|
||||
userPage.parseEach(callbackWrapper);
|
||||
removeUnused();
|
||||
if (userPage.amount) {
|
||||
activityCounter = Util::bootSecs();
|
||||
DEBUG_MSG(DLVL_INSANE, "Connected users: %d", userPage.amount);
|
||||
} else {
|
||||
DEBUG_MSG(DLVL_INSANE, "Timer running");
|
||||
}
|
||||
/*LTS-START*/
|
||||
if ((Util::bootSecs() - activityCounter) >= 10 || !config->is_active){//10 second timeout
|
||||
if(Triggers::shouldTrigger("STREAM_UNLOAD", config->getString("streamname"))){
|
||||
std::string payload = config->getString("streamname")+"\n" +capa["name"].asStringRef()+"\n";
|
||||
if (!Triggers::doTrigger("STREAM_UNLOAD", payload, config->getString("streamname"))){
|
||||
activityCounter = Util::bootSecs();
|
||||
config->is_active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*LTS-END*/
|
||||
if (config->is_active){
|
||||
Util::sleep(1000);
|
||||
}
|
||||
}
|
||||
finish();
|
||||
DEBUG_MSG(DLVL_DEVEL, "Input for stream %s closing clean", streamName.c_str());
|
||||
//end player functionality
|
||||
}
|
||||
|
||||
void Input::finish() {
|
||||
for (std::map<unsigned int, std::map<unsigned int, unsigned int> >::iterator it = pageCounter.begin(); it != pageCounter.end(); it++) {
|
||||
for (std::map<unsigned int, unsigned int>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) {
|
||||
|
|
|
@ -338,10 +338,12 @@ namespace Mist {
|
|||
}
|
||||
if (!found){
|
||||
for (std::map<unsigned int,DTSC::Track>::iterator trit = myMeta.tracks.begin(); trit != myMeta.tracks.end(); trit++){
|
||||
if (trit->second.codec == (*itc).asStringRef()){
|
||||
if (trit->second.codec == (*itc).asStringRef() || (*itc).asStringRef() == "*"){
|
||||
genCounter++;
|
||||
found = true;
|
||||
break;
|
||||
if ((*itc).asStringRef() != "*"){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,6 +370,7 @@ namespace Mist {
|
|||
if ((*itb).size() && myMeta.tracks.size()){
|
||||
bool found = false;
|
||||
jsonForEach((*itb), itc) {
|
||||
INFO_MSG("Filling codec: '%s'", (*itc).asStringRef().c_str());
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
|
@ -379,10 +382,12 @@ namespace Mist {
|
|||
}
|
||||
if (!found){
|
||||
for (std::map<unsigned int,DTSC::Track>::iterator trit = myMeta.tracks.begin(); trit != myMeta.tracks.end(); trit++){
|
||||
if (trit->second.codec == (*itc).asStringRef()){
|
||||
if (trit->second.codec == (*itc).asStringRef() || (*itc).asStringRef() == "*"){
|
||||
selectedTracks.insert(trit->first);
|
||||
found = true;
|
||||
break;
|
||||
if ((*itc).asStringRef() != "*"){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
147
src/output/output_dtsc.cpp
Normal file
147
src/output/output_dtsc.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
#include "output_dtsc.h"
|
||||
#include <mist/defines.h>
|
||||
#include <mist/stream.h>
|
||||
#include <mist/triggers.h>
|
||||
#include <mist/auth.h>
|
||||
#include <mist/bitfields.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Mist {
|
||||
OutDTSC::OutDTSC(Socket::Connection & conn) : Output(conn) {
|
||||
setBlocking(true);
|
||||
JSON::Value prep;
|
||||
prep["cmd"] = "hi";
|
||||
prep["version"] = "MistServer " PACKAGE_VERSION;
|
||||
#ifdef BIGMETA
|
||||
prep["pack_method"] = 2ll;
|
||||
#else
|
||||
prep["pack_method"] = 1ll;
|
||||
#endif
|
||||
salt = Secure::md5("mehstuff"+JSON::Value((long long)time(0)).asString());
|
||||
prep["salt"] = salt;
|
||||
/// \todo Make this securererer.
|
||||
unsigned long sendSize = prep.packedSize();
|
||||
myConn.SendNow("DTCM");
|
||||
char sSize[4] = {0, 0, 0, 0};
|
||||
Bit::htobl(sSize, prep.packedSize());
|
||||
myConn.SendNow(sSize, 4);
|
||||
prep.sendTo(myConn);
|
||||
pushing = false;
|
||||
}
|
||||
|
||||
OutDTSC::~OutDTSC() {}
|
||||
|
||||
void OutDTSC::init(Util::Config * cfg){
|
||||
Output::init(cfg);
|
||||
capa["name"] = "DTSC";
|
||||
capa["desc"] = "Enables the DTSC protocol for efficient inter-server stream exchange.";
|
||||
capa["deps"] = "";
|
||||
capa["codecs"][0u][0u].append("*");
|
||||
cfg->addConnectorOptions(4200, capa);
|
||||
config = cfg;
|
||||
}
|
||||
|
||||
void OutDTSC::sendNext(){
|
||||
myConn.SendNow(thisPacket.getData(), thisPacket.getDataLen());
|
||||
}
|
||||
|
||||
void OutDTSC::sendHeader(){
|
||||
sentHeader = true;
|
||||
myMeta.send(myConn, true);
|
||||
}
|
||||
|
||||
void OutDTSC::onRequest(){
|
||||
while (myConn.Received().available(8)){
|
||||
if (myConn.Received().copy(4) == "DTCM"){
|
||||
// Command message
|
||||
std::string toRec = myConn.Received().copy(8);
|
||||
unsigned long rSize = Bit::btohl(toRec.c_str()+4);
|
||||
if (!myConn.Received().available(8+rSize)){return;}//abort - not enough data yet
|
||||
myConn.Received().remove(8);
|
||||
std::string dataPacket = myConn.Received().remove(rSize);
|
||||
DTSC::Scan dScan((char*)dataPacket.data(), rSize);
|
||||
if (dScan.getMember("cmd").asString() == "push"){handlePush(dScan); continue;}
|
||||
if (dScan.getMember("cmd").asString() == "play"){handlePlay(dScan); continue;}
|
||||
WARN_MSG("Unhandled DTCM command: '%s'", dScan.getMember("cmd").asString().c_str());
|
||||
}else{
|
||||
// Non-command message
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OutDTSC::handlePlay(DTSC::Scan & dScan){
|
||||
streamName = dScan.getMember("stream").asString();
|
||||
Util::sanitizeName(streamName);
|
||||
parseData = true;
|
||||
}
|
||||
|
||||
void OutDTSC::handlePush(DTSC::Scan & dScan){
|
||||
streamName = dScan.getMember("stream").asString();
|
||||
std::string passString = dScan.getMember("password").asString();
|
||||
|
||||
Util::sanitizeName(streamName);
|
||||
//pull the server configuration
|
||||
std::string smp = streamName.substr(0,(streamName.find_first_of("+ ")));
|
||||
IPC::sharedPage serverCfg("!mistConfig", DEFAULT_CONF_PAGE_SIZE); ///< Contains server configuration and capabilities
|
||||
IPC::semaphore configLock("!mistConfLock", O_CREAT | O_RDWR, ACCESSPERMS, 1);
|
||||
configLock.wait();
|
||||
|
||||
DTSC::Scan streamCfg = DTSC::Scan(serverCfg.mapped, serverCfg.len).getMember("streams").getMember(smp);
|
||||
if (streamCfg){
|
||||
if (streamCfg.getMember("source").asString().substr(0, 7) != "push://"){
|
||||
DEBUG_MSG(DLVL_FAIL, "Push rejected - stream %s not a push-able stream. (%s != push://*)", streamName.c_str(), streamCfg.getMember("source").asString().c_str());
|
||||
myConn.close();
|
||||
}else{
|
||||
std::string source = streamCfg.getMember("source").asString().substr(7);
|
||||
std::string IP = source.substr(0, source.find('@'));
|
||||
/*LTS-START*/
|
||||
std::string password;
|
||||
if (source.find('@') != std::string::npos){
|
||||
password = source.substr(source.find('@')+1);
|
||||
if (password != ""){
|
||||
if (passString == Secure::md5(salt + password)){
|
||||
DEBUG_MSG(DLVL_DEVEL, "Password accepted - ignoring IP settings.");
|
||||
IP = "";
|
||||
}else{
|
||||
DEBUG_MSG(DLVL_DEVEL, "Password rejected - checking IP.");
|
||||
if (IP == ""){
|
||||
IP = "deny-all.invalid";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Triggers::shouldTrigger("STREAM_PUSH", smp)){
|
||||
std::string payload = streamName+"\n" + myConn.getHost() +"\n"+capa["name"].asStringRef()+"\n"+reqUrl;
|
||||
if (!Triggers::doTrigger("STREAM_PUSH", payload, smp)){
|
||||
DEBUG_MSG(DLVL_FAIL, "Push from %s to %s rejected - STREAM_PUSH trigger denied the push", myConn.getHost().c_str(), streamName.c_str());
|
||||
myConn.close();
|
||||
configLock.post();
|
||||
configLock.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*LTS-END*/
|
||||
if (IP != ""){
|
||||
if (!myConn.isAddress(IP)){
|
||||
DEBUG_MSG(DLVL_FAIL, "Push from %s to %s rejected - source host not whitelisted", myConn.getHost().c_str(), streamName.c_str());
|
||||
myConn.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
DEBUG_MSG(DLVL_FAIL, "Push from %s rejected - stream '%s' not configured.", myConn.getHost().c_str(), streamName.c_str());
|
||||
myConn.close();
|
||||
}
|
||||
configLock.post();
|
||||
configLock.close();
|
||||
if (!myConn){return;}//do not initialize if rejected
|
||||
initialize();
|
||||
pushing = true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
22
src/output/output_dtsc.h
Normal file
22
src/output/output_dtsc.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "output.h"
|
||||
|
||||
namespace Mist {
|
||||
|
||||
class OutDTSC : public Output {
|
||||
public:
|
||||
OutDTSC(Socket::Connection & conn);
|
||||
~OutDTSC();
|
||||
static void init(Util::Config * cfg);
|
||||
void onRequest();
|
||||
void sendNext();
|
||||
void sendHeader();
|
||||
private:
|
||||
std::string salt;
|
||||
bool pushing;
|
||||
void handlePush(DTSC::Scan & dScan);
|
||||
void handlePlay(DTSC::Scan & dScan);
|
||||
};
|
||||
}
|
||||
|
||||
typedef Mist::OutDTSC mistOut;
|
||||
|
|
@ -4,11 +4,11 @@ namespace Mist {
|
|||
OutRaw::OutRaw(Socket::Connection & conn) : Output(conn) {
|
||||
streamName = config->getString("streamname");
|
||||
initialize();
|
||||
selectedTracks.clear();
|
||||
std::string tracks = config->getString("tracks");
|
||||
unsigned int currTrack = 0;
|
||||
//loop over tracks, add any found track IDs to selectedTracks
|
||||
if (tracks != ""){
|
||||
if (tracks.size()){
|
||||
selectedTracks.clear();
|
||||
unsigned int currTrack = 0;
|
||||
//loop over tracks, add any found track IDs to selectedTracks
|
||||
for (unsigned int i = 0; i < tracks.size(); ++i){
|
||||
if (tracks[i] >= '0' && tracks[i] <= '9'){
|
||||
currTrack = currTrack*10 + (tracks[i] - '0');
|
||||
|
@ -46,8 +46,7 @@ namespace Mist {
|
|||
capa["optional"]["seek"]["help"] = "The time in milliseconds to seek to, 0 by default.";
|
||||
capa["optional"]["seek"]["type"] = "int";
|
||||
capa["optional"]["seek"]["option"] = "--seek";
|
||||
capa["codecs"][0u][0u].append("H264");
|
||||
capa["codecs"][0u][1u].append("AAC");
|
||||
capa["codecs"][0u][0u].append("*");
|
||||
cfg->addOption("streamname",
|
||||
JSON::fromString("{\"arg\":\"string\",\"short\":\"s\",\"long\":\"stream\",\"help\":\"The name of the stream that this connector will transmit.\"}"));
|
||||
cfg->addOption("tracks",
|
||||
|
@ -68,3 +67,4 @@ namespace Mist {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue