160 lines
3.8 KiB
C++
160 lines
3.8 KiB
C++
#include "output_json.h"
|
|
#include <mist/stream.h>
|
|
#include <iomanip>
|
|
|
|
namespace Mist {
|
|
OutJSON::OutJSON(Socket::Connection & conn) : HTTPOutput(conn){
|
|
ws = 0;
|
|
realTime = 0;
|
|
keepReselecting = false;
|
|
dupcheck = false;
|
|
}
|
|
OutJSON::~OutJSON() {
|
|
if (ws){
|
|
delete ws;
|
|
ws = 0;
|
|
}
|
|
}
|
|
|
|
void OutJSON::init(Util::Config * cfg){
|
|
HTTPOutput::init(cfg);
|
|
capa["name"] = "JSON";
|
|
capa["desc"] = "Enables HTTP protocol JSON streaming.";
|
|
capa["url_match"] = "/$.json";
|
|
capa["codecs"][0u][0u].append("@+meta");
|
|
capa["methods"][0u]["handler"] = "http";
|
|
capa["methods"][0u]["type"] = "html5/text/javascript";
|
|
capa["methods"][0u]["priority"] = 0ll;
|
|
capa["methods"][0u]["url_rel"] = "/$.json";
|
|
capa["methods"][1u]["handler"] = "ws";
|
|
capa["methods"][1u]["type"] = "html5/text/javascript";
|
|
capa["methods"][1u]["priority"] = 0ll;
|
|
capa["methods"][1u]["url_rel"] = "/$.json";
|
|
}
|
|
|
|
void OutJSON::sendNext(){
|
|
JSON::Value jPack = thisPacket.toJSON();
|
|
if (dupcheck){
|
|
if (jPack.compareExcept(lastVal, nodup)){
|
|
return;//skip duplicates
|
|
}
|
|
lastVal = jPack;
|
|
}
|
|
if (ws){
|
|
ws->sendFrame(jPack.toString());
|
|
return;
|
|
}
|
|
if (!jsonp.size()){
|
|
if(!first) {
|
|
myConn.SendNow(", ", 2);
|
|
}else{
|
|
myConn.SendNow("[", 1);
|
|
first = false;
|
|
}
|
|
}else{
|
|
myConn.SendNow(jsonp + "(");
|
|
}
|
|
myConn.SendNow(jPack.toString());
|
|
if (jsonp.size()){
|
|
myConn.SendNow(");\n", 3);
|
|
}
|
|
}
|
|
|
|
void OutJSON::sendHeader(){
|
|
std::string method = H.method;
|
|
H.Clean();
|
|
H.SetHeader("Content-Type", "text/javascript");
|
|
H.protocol = "HTTP/1.0";
|
|
H.setCORSHeaders();
|
|
H.SendResponse("200", "OK", myConn);
|
|
sentHeader = true;
|
|
}
|
|
|
|
void OutJSON::onFail(){
|
|
//Only run failure handle if we're not being persistent
|
|
if (!keepReselecting){
|
|
HTTPOutput::onFail();
|
|
}else{
|
|
onFinish();
|
|
}
|
|
}
|
|
|
|
bool OutJSON::onFinish(){
|
|
static bool recursive = false;
|
|
if (recursive){return true;}
|
|
recursive = true;
|
|
if (keepReselecting){
|
|
uint64_t maxTimer = 7200;
|
|
while (--maxTimer && nProxy.userClient.isAlive() && keepGoing()){
|
|
Util::wait(500);
|
|
stats();
|
|
if (Util::getStreamStatus(streamName) != STRMSTAT_READY){
|
|
disconnect();
|
|
}else{
|
|
updateMeta();
|
|
if (isReadyForPlay()){
|
|
recursive = false;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
recursive = false;
|
|
return false;
|
|
}
|
|
if (!jsonp.size() && !first){
|
|
myConn.SendNow("]);\n\n", 5);
|
|
}
|
|
myConn.close();
|
|
return false;
|
|
}
|
|
|
|
void OutJSON::onHTTP(){
|
|
std::string method = H.method;
|
|
jsonp = "";
|
|
if (H.GetVar("persist") != ""){keepReselecting = true;}
|
|
if (H.GetVar("dedupe") != ""){
|
|
dupcheck = true;
|
|
size_t index;
|
|
std::string dupes = H.GetVar("dedupe");
|
|
while (dupes != "") {
|
|
index = dupes.find(',');
|
|
nodup.insert(dupes.substr(0, index));
|
|
if (index != std::string::npos) {
|
|
dupes.erase(0, index + 1);
|
|
} else {
|
|
dupes = "";
|
|
}
|
|
}
|
|
}
|
|
if (H.GetVar("callback") != ""){jsonp = H.GetVar("callback");}
|
|
if (H.GetVar("jsonp") != ""){jsonp = H.GetVar("jsonp");}
|
|
|
|
if (H.GetHeader("Upgrade") == "websocket"){
|
|
ws = new HTTP::Websocket(myConn, H);
|
|
if (!(*ws)){
|
|
delete ws;
|
|
ws = 0;
|
|
return;
|
|
}
|
|
sentHeader = true;
|
|
parseData = true;
|
|
wantRequest = false;
|
|
return;
|
|
}
|
|
|
|
H.Clean();
|
|
H.setCORSHeaders();
|
|
if(method == "OPTIONS" || method == "HEAD"){
|
|
H.SetHeader("Content-Type", "text/javascript");
|
|
H.protocol = "HTTP/1.0";
|
|
H.SendResponse("200", "OK", myConn);
|
|
H.Clean();
|
|
return;
|
|
}
|
|
first = true;
|
|
parseData = true;
|
|
wantRequest = false;
|
|
}
|
|
|
|
}
|
|
|