Implemented triggers.

Merged from code by Wouter Spruit, with additions by yours truly.
This commit is contained in:
Thulinma 2015-10-07 13:23:27 +02:00
parent eb6b98b219
commit 279add438a
18 changed files with 597 additions and 6 deletions

View file

@ -14,6 +14,7 @@
#include "output.h"
/*LTS-START*/
#include <mist/triggers.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
@ -102,6 +103,14 @@ namespace Mist {
myConn.close();
}
/// \triggers
/// The `"CONN_PLAY"` trigger is stream-specific, and is ran when an active connection first opens a stream. Its payload is:
/// ~~~~~~~~~~~~~~~
/// streamname
/// connected client host
/// output handler name
/// request URL (if any)
/// ~~~~~~~~~~~~~~~
void Output::initialize(){
if (isInitialized){
return;
@ -121,6 +130,14 @@ namespace Mist {
}
selectDefaultTracks();
sought = false;
/*LTS-START*/
if(Triggers::shouldTrigger("CONN_PLAY", streamName)){
std::string payload = streamName+"\n" + myConn.getHost() +"\n"+capa["name"].asStringRef()+"\n"+reqUrl;
if (!Triggers::doTrigger("CONN_PLAY", payload, streamName)){
myConn.close();
}
}
/*LTS-END*/
}
/// Connects or reconnects to the stream.
@ -701,7 +718,30 @@ namespace Mist {
}
}
/// \triggers
/// The `"CONN_OPEN"` trigger is stream-specific, and is ran when a connection is made or passed to a new handler. Its payload is:
/// ~~~~~~~~~~~~~~~
/// streamname
/// connected client host
/// output handler name
/// request URL (if any)
/// ~~~~~~~~~~~~~~~
/// The `"CONN_CLOSE"` trigger is stream-specific, and is ran when a connection closes. Its payload is:
/// ~~~~~~~~~~~~~~~
/// streamname
/// connected client host
/// output handler name
/// request URL (if any)
/// ~~~~~~~~~~~~~~~
int Output::run() {
/*LTS-START*/
if(Triggers::shouldTrigger("CONN_OPEN", streamName)){
std::string payload = streamName+"\n" + myConn.getHost() +"\n"+capa["name"].asStringRef()+"\n"+reqUrl;
if (!Triggers::doTrigger("CONN_OPEN", payload, streamName)){
return 1;
}
}
/*LTS-END*/
DEBUG_MSG(DLVL_MEDIUM, "MistOut client handler started");
while (config->is_active && myConn.connected() && (wantRequest || parseData)){
stats();
@ -727,6 +767,14 @@ namespace Mist {
}
}
DEBUG_MSG(DLVL_MEDIUM, "MistOut client handler shutting down: %s, %s, %s", myConn.connected() ? "conn_active" : "conn_closed", wantRequest ? "want_request" : "no_want_request", parseData ? "parsing_data" : "not_parsing_data");
/*LTS-START*/
if(Triggers::shouldTrigger("CONN_CLOSE", streamName)){
std::string payload = streamName+"\n"+myConn.getHost()+"\n"+capa["name"].asStringRef()+"\n"+reqUrl; ///\todo generate payload
Triggers::doTrigger("CONN_CLOSE", payload, streamName); //no stream specified
}
/*LTS-END*/
stats();
userClient.finish();
statsPage.finish();
@ -777,6 +825,12 @@ namespace Mist {
thisPacket.null();
DEBUG_MSG(DLVL_DEVEL, "Buffer completely played out");
onFinish();
/*LTS-START*/
if(Triggers::shouldTrigger("CONN_STOP", streamName)){
std::string payload = streamName+"\n" + myConn.getHost() +"\n"+capa["name"].asStringRef()+"\n";
Triggers::doTrigger("CONN_STOP", payload, streamName);
}
/*LTS-END*/
return;
}
sortedPageInfo nxt = *(buffer.begin());

View file

@ -51,6 +51,7 @@ namespace Mist {
static GeoIP * geoIP4;
static GeoIP * geoIP6;
#endif
std::string reqUrl;
/*LTS-END*/
//non-virtual generic functions
int run();

View file

@ -159,6 +159,7 @@ namespace Mist {
if (!myConn.Received().size()){
if (myConn.peek() && H.Read(myConn)){
std::string handler = getHandler();
reqUrl = H.getUrl();//LTS
DEBUG_MSG(DLVL_MEDIUM, "Received request: %s => %s (%s)", H.getUrl().c_str(), handler.c_str(), H.GetVar("stream").c_str());
if (!handler.size()){
H.Clean();

View file

@ -2,6 +2,7 @@
#include <mist/http_parser.h>
#include <mist/defines.h>
#include <mist/stream.h>
#include <mist/triggers.h>
#include <sys/stat.h>
#include <cstring>
#include <cstdlib>
@ -325,6 +326,14 @@ namespace Mist {
///\param amfData The received request.
///\param messageType The type of message.
///\param streamId The ID of the AMF stream.
/// \triggers
/// The `"STREAM_PUSH"` trigger is stream-specific, and is ran right before an incoming push is accepted. If cancelled, the push is denied. Its payload is:
/// ~~~~~~~~~~~~~~~
/// streamname
/// connected client host
/// output handler name
/// request URL (if any)
/// ~~~~~~~~~~~~~~~
void OutRTMP::parseAMFCommand(AMF::Object & amfData, int messageType, int streamId) {
#if DEBUG >= 5
fprintf(stderr, "Received command: %s\n", amfData.Print().c_str());
@ -359,6 +368,7 @@ namespace Mist {
}
#endif
app_name = amfData.getContentP(2)->getContentP("tcUrl")->StrValue();
reqUrl = app_name;//LTS
app_name = app_name.substr(app_name.find('/', 7) + 1);
RTMPStream::chunk_snd_max = 4096;
myConn.SendNow(RTMPStream::SendCTL(1, RTMPStream::chunk_snd_max)); //send chunk size max (msg 1)
@ -467,6 +477,7 @@ namespace Mist {
if ((amfData.getContentP(0)->StrValue() == "publish")) {
if (amfData.getContentP(3)) {
streamName = amfData.getContentP(3)->StrValue();
reqUrl += "/"+streamName;//LTS
if (streamName.find('/')){
streamName = streamName.substr(0, streamName.find('/'));
@ -513,6 +524,16 @@ namespace Mist {
}
}
}
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)){
@ -567,6 +588,7 @@ namespace Mist {
int playMessageType = messageType;
int playStreamId = streamId;
streamName = amfData.getContentP(3)->StrValue();
reqUrl += "/"+streamName;//LTS
//handle variables
if (streamName.find('?') != std::string::npos){