mistserver/src/output/output_json.cpp

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;
}
}