Several stability improvements and optimizations for HTTP handling and parsing (also, should fix HTTP Progressive under Windows - again).
This commit is contained in:
		
							parent
							
								
									682ecd2a0e
								
							
						
					
					
						commit
						a08f8e3033
					
				
					 4 changed files with 203 additions and 250 deletions
				
			
		| 
						 | 
					@ -20,13 +20,6 @@ void HTTP::Parser::Clean(){
 | 
				
			||||||
  vars.clear();
 | 
					  vars.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Re-initializes the HTTP::Parser, leaving the internal data buffer alone, then tries to parse a new request or response.
 | 
					 | 
				
			||||||
/// Does the same as HTTP::Parser::Clean(), then returns HTTP::Parser::parse().
 | 
					 | 
				
			||||||
bool HTTP::Parser::CleanForNext(){
 | 
					 | 
				
			||||||
  Clean();
 | 
					 | 
				
			||||||
  return parse();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Returns a string containing a valid HTTP 1.0 or 1.1 request, ready for sending.
 | 
					/// Returns a string containing a valid HTTP 1.0 or 1.1 request, ready for sending.
 | 
				
			||||||
/// The request is build from internal variables set before this call is made.
 | 
					/// The request is build from internal variables set before this call is made.
 | 
				
			||||||
/// To be precise, method, url, protocol, headers and body are used.
 | 
					/// To be precise, method, url, protocol, headers and body are used.
 | 
				
			||||||
| 
						 | 
					@ -115,34 +108,20 @@ void HTTP::Parser::SetVar(std::string i, std::string v){
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Attempt to read a whole HTTP request or response from Socket::Connection.
 | 
					/// Attempt to read a whole HTTP request or response from a std::string buffer.
 | 
				
			||||||
/// \param sock The socket to use.
 | 
					/// If a whole request could be read, it is removed from the front of the given buffer.
 | 
				
			||||||
/// \param nonblock When true, will not block even if the socket is blocking.
 | 
					/// \param strbuf The buffer to read from.
 | 
				
			||||||
/// \return True of a whole request or response was read, false otherwise.
 | 
					/// \return True if a whole request or response was read, false otherwise.
 | 
				
			||||||
bool HTTP::Parser::Read(Socket::Connection & sock, bool nonblock){
 | 
					bool HTTP::Parser::Read(std::string & strbuf){
 | 
				
			||||||
  if (nonblock && (sock.ready() < 1)){return parse();}
 | 
					  return parse(strbuf);
 | 
				
			||||||
  sock.read(HTTPbuffer);
 | 
					}//HTTPReader::Read
 | 
				
			||||||
  return parse();
 | 
					 | 
				
			||||||
}//HTTPReader::ReadSocket
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Reads a full set of HTTP responses/requests from file F.
 | 
					/// Attempt to read a whole HTTP response or request from a data buffer.
 | 
				
			||||||
/// \return Always false. Use HTTP::Parser::CleanForNext() to parse the contents of the file.
 | 
					 | 
				
			||||||
bool HTTP::Parser::Read(FILE * F){
 | 
					 | 
				
			||||||
  //returned true als hele http packet gelezen is
 | 
					 | 
				
			||||||
  int b = 1;
 | 
					 | 
				
			||||||
  char buffer[500];
 | 
					 | 
				
			||||||
  while (b > 0){
 | 
					 | 
				
			||||||
    b = fread(buffer, 1, 500, F);
 | 
					 | 
				
			||||||
    HTTPbuffer.append(buffer, b);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}//HTTPReader::ReadSocket
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Attempt to read a whole HTTP response or request from the internal data buffer.
 | 
					 | 
				
			||||||
/// If succesful, fills its own fields with the proper data and removes the response/request
 | 
					/// If succesful, fills its own fields with the proper data and removes the response/request
 | 
				
			||||||
/// from the internal data buffer.
 | 
					/// from the data buffer.
 | 
				
			||||||
 | 
					/// \param HTTPbuffer The data buffer to read from.
 | 
				
			||||||
/// \return True on success, false otherwise.
 | 
					/// \return True on success, false otherwise.
 | 
				
			||||||
bool HTTP::Parser::parse(){
 | 
					bool HTTP::Parser::parse(std::string & HTTPbuffer){
 | 
				
			||||||
  size_t f;
 | 
					  size_t f;
 | 
				
			||||||
  std::string tmpA, tmpB, tmpC;
 | 
					  std::string tmpA, tmpB, tmpC;
 | 
				
			||||||
  while (HTTPbuffer != ""){
 | 
					  while (HTTPbuffer != ""){
 | 
				
			||||||
| 
						 | 
					@ -194,16 +173,6 @@ bool HTTP::Parser::parse(){
 | 
				
			||||||
  return false; //we should never get here...
 | 
					  return false; //we should never get here...
 | 
				
			||||||
}//HTTPReader::parse
 | 
					}//HTTPReader::parse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Sends data as response to conn.
 | 
					 | 
				
			||||||
/// The response is automatically first build using HTTP::Parser::BuildResponse().
 | 
					 | 
				
			||||||
/// \param conn The Socket::Connection to send the response over.
 | 
					 | 
				
			||||||
/// \param code The HTTP response code. Usually you want 200.
 | 
					 | 
				
			||||||
/// \param message The HTTP response message. Usually you want "OK".
 | 
					 | 
				
			||||||
void HTTP::Parser::SendResponse(Socket::Connection & conn, std::string code, std::string message){
 | 
					 | 
				
			||||||
  std::string tmp = BuildResponse(code, message);
 | 
					 | 
				
			||||||
  conn.write(tmp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
/// Parses GET or POST-style variable data.
 | 
					/// Parses GET or POST-style variable data.
 | 
				
			||||||
/// Saves to internal variable structure using HTTP::Parser::SetVar.
 | 
					/// Saves to internal variable structure using HTTP::Parser::SetVar.
 | 
				
			||||||
| 
						 | 
					@ -237,31 +206,16 @@ void HTTP::Parser::parseVars(std::string data){
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Sends data as HTTP/1.1 bodypart to conn.
 | 
					/// Converts a string to chunked format if protocol is HTTP/1.1 - does nothing otherwise.
 | 
				
			||||||
/// HTTP/1.1 chunked encoding is automatically applied if needed.
 | 
					/// \param bodypart The data to convert - will be converted in-place.
 | 
				
			||||||
/// \param conn The Socket::Connection to send the part over.
 | 
					void HTTP::Parser::Chunkify(std::string & bodypart){
 | 
				
			||||||
/// \param buffer The buffer to send.
 | 
					 | 
				
			||||||
/// \param len The length of the buffer.
 | 
					 | 
				
			||||||
void HTTP::Parser::SendBodyPart(Socket::Connection & conn, char * buffer, int len){
 | 
					 | 
				
			||||||
  std::string tmp;
 | 
					 | 
				
			||||||
  tmp.append(buffer, len);
 | 
					 | 
				
			||||||
  SendBodyPart(conn, tmp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Sends data as HTTP/1.1 bodypart to conn.
 | 
					 | 
				
			||||||
/// HTTP/1.1 chunked encoding is automatically applied if needed.
 | 
					 | 
				
			||||||
/// \param conn The Socket::Connection to send the part over.
 | 
					 | 
				
			||||||
/// \param bodypart The data to send.
 | 
					 | 
				
			||||||
void HTTP::Parser::SendBodyPart(Socket::Connection & conn, std::string bodypart){
 | 
					 | 
				
			||||||
  if (protocol == "HTTP/1.1"){
 | 
					  if (protocol == "HTTP/1.1"){
 | 
				
			||||||
    static char len[10];
 | 
					    static char len[10];
 | 
				
			||||||
    int sizelen;
 | 
					    int sizelen = snprintf(len, 10, "%x\r\n", (unsigned int)bodypart.size());
 | 
				
			||||||
    sizelen = snprintf(len, 10, "%x\r\n", (unsigned int)bodypart.size());
 | 
					    //prepend the chunk size and \r\n
 | 
				
			||||||
    conn.write(len, sizelen);
 | 
					    bodypart.insert(0, len, sizelen);
 | 
				
			||||||
    conn.write(bodypart);
 | 
					    //append \r\n
 | 
				
			||||||
    conn.write(len+sizelen-2, 2);
 | 
					    bodypart.append("\r\n", 2);
 | 
				
			||||||
  }else{
 | 
					 | 
				
			||||||
    conn.write(bodypart);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,6 @@
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include "socket.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Holds all HTTP processing related code.
 | 
					/// Holds all HTTP processing related code.
 | 
				
			||||||
namespace HTTP{
 | 
					namespace HTTP{
 | 
				
			||||||
| 
						 | 
					@ -14,8 +13,7 @@ namespace HTTP{
 | 
				
			||||||
  class Parser{
 | 
					  class Parser{
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
      Parser();
 | 
					      Parser();
 | 
				
			||||||
      bool Read(Socket::Connection & sock, bool nonblock = true);
 | 
					      bool Read(std::string & strbuf);
 | 
				
			||||||
      bool Read(FILE * F);
 | 
					 | 
				
			||||||
      std::string GetHeader(std::string i);
 | 
					      std::string GetHeader(std::string i);
 | 
				
			||||||
      std::string GetVar(std::string i);
 | 
					      std::string GetVar(std::string i);
 | 
				
			||||||
      void SetHeader(std::string i, std::string v);
 | 
					      void SetHeader(std::string i, std::string v);
 | 
				
			||||||
| 
						 | 
					@ -25,11 +23,8 @@ namespace HTTP{
 | 
				
			||||||
      void SetBody(char * buffer, int len);
 | 
					      void SetBody(char * buffer, int len);
 | 
				
			||||||
      std::string BuildRequest();
 | 
					      std::string BuildRequest();
 | 
				
			||||||
      std::string BuildResponse(std::string code, std::string message);
 | 
					      std::string BuildResponse(std::string code, std::string message);
 | 
				
			||||||
      void SendResponse(Socket::Connection & conn, std::string code, std::string message);
 | 
					      void Chunkify(std::string & bodypart);
 | 
				
			||||||
      void SendBodyPart(Socket::Connection & conn, char * buffer, int len);
 | 
					 | 
				
			||||||
      void SendBodyPart(Socket::Connection & conn, std::string bodypart);
 | 
					 | 
				
			||||||
      void Clean();
 | 
					      void Clean();
 | 
				
			||||||
      bool CleanForNext();
 | 
					 | 
				
			||||||
      static std::string urlunescape(const std::string & in);
 | 
					      static std::string urlunescape(const std::string & in);
 | 
				
			||||||
      static std::string urlencode(const std::string & in);
 | 
					      static std::string urlencode(const std::string & in);
 | 
				
			||||||
      std::string body;
 | 
					      std::string body;
 | 
				
			||||||
| 
						 | 
					@ -40,9 +35,9 @@ namespace HTTP{
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
      bool seenHeaders;
 | 
					      bool seenHeaders;
 | 
				
			||||||
      bool seenReq;
 | 
					      bool seenReq;
 | 
				
			||||||
      bool parse();
 | 
					      bool parse(std::string & HTTPbuffer);
 | 
				
			||||||
      void parseVars(std::string data);
 | 
					      void parseVars(std::string data);
 | 
				
			||||||
      std::string HTTPbuffer;
 | 
					      std::string read_buffer;
 | 
				
			||||||
      std::map<std::string, std::string> headers;
 | 
					      std::map<std::string, std::string> headers;
 | 
				
			||||||
      std::map<std::string, std::string> vars;
 | 
					      std::map<std::string, std::string> vars;
 | 
				
			||||||
      void Trim(std::string & s);
 | 
					      void Trim(std::string & s);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ namespace Connector_HTTP{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Returns AMF-format metadata for Adobe HTTP Dynamic Streaming.
 | 
					  /// Returns AMF-format metadata for Adobe HTTP Dynamic Streaming.
 | 
				
			||||||
  std::string GetMetaData( ) {
 | 
					  std::string GetMetaData( ) {
 | 
				
			||||||
 | 
					    /// \todo Make this actually do what it should - even though it seems to be ignored completely by all media players.
 | 
				
			||||||
    AMF::Object amfreply("container", AMF::AMF0_DDV_CONTAINER);
 | 
					    AMF::Object amfreply("container", AMF::AMF0_DDV_CONTAINER);
 | 
				
			||||||
    amfreply.addContent(AMF::Object("onMetaData",AMF::AMF0_STRING));
 | 
					    amfreply.addContent(AMF::Object("onMetaData",AMF::AMF0_STRING));
 | 
				
			||||||
    amfreply.addContent(AMF::Object("",AMF::AMF0_ECMA_ARRAY));
 | 
					    amfreply.addContent(AMF::Object("",AMF::AMF0_ECMA_ARRAY));
 | 
				
			||||||
| 
						 | 
					@ -95,31 +96,32 @@ namespace Connector_HTTP{
 | 
				
			||||||
  void Progressive(FLV::Tag & tag, HTTP::Parser HTTP_S, Socket::Connection & conn, DTSC::Stream & Strm){
 | 
					  void Progressive(FLV::Tag & tag, HTTP::Parser HTTP_S, Socket::Connection & conn, DTSC::Stream & Strm){
 | 
				
			||||||
    static bool progressive_has_sent_header = false;
 | 
					    static bool progressive_has_sent_header = false;
 | 
				
			||||||
    if (!progressive_has_sent_header){
 | 
					    if (!progressive_has_sent_header){
 | 
				
			||||||
      HTTP_S.Clean();//troep opruimen die misschien aanwezig is...
 | 
					      HTTP_S.Clean();//make sure no parts of old requests are left in any buffers
 | 
				
			||||||
      HTTP_S.SetHeader("Content-Type", "video/x-flv");//FLV files hebben altijd dit content-type.
 | 
					      HTTP_S.SetHeader("Content-Type", "video/x-flv");//Send the correct content-type for FLV files
 | 
				
			||||||
      //HTTP_S.SetHeader("Transfer-Encoding", "chunked");
 | 
					      //HTTP_S.SetHeader("Transfer-Encoding", "chunked");
 | 
				
			||||||
      HTTP_S.protocol = "HTTP/1.0";
 | 
					      HTTP_S.protocol = "HTTP/1.0";
 | 
				
			||||||
      HTTP_S.SendResponse(conn, "200", "OK");//geen SetBody = unknown length! Dat willen we hier.
 | 
					      conn.Send(HTTP_S.BuildResponse("200", "OK"));//no SetBody = unknown length - this is intentional, we will stream the entire file
 | 
				
			||||||
      //HTTP_S.SendBodyPart(CONN_fd, FLVHeader, 13);//schrijf de FLV header
 | 
					      conn.Send(std::string(FLV::Header, 13));//write FLV header
 | 
				
			||||||
      conn.write(FLV::Header, 13);
 | 
					 | 
				
			||||||
      static FLV::Tag tmp;
 | 
					      static FLV::Tag tmp;
 | 
				
			||||||
 | 
					      //write metadata
 | 
				
			||||||
      tmp.DTSCMetaInit(Strm);
 | 
					      tmp.DTSCMetaInit(Strm);
 | 
				
			||||||
      conn.write(tmp.data, tmp.len);
 | 
					      conn.Send(std::string(tmp.data, tmp.len));
 | 
				
			||||||
 | 
					      //write video init data, if needed
 | 
				
			||||||
      if (Strm.metadata.getContentP("video") && Strm.metadata.getContentP("video")->getContentP("init")){
 | 
					      if (Strm.metadata.getContentP("video") && Strm.metadata.getContentP("video")->getContentP("init")){
 | 
				
			||||||
        tmp.DTSCVideoInit(Strm);
 | 
					        tmp.DTSCVideoInit(Strm);
 | 
				
			||||||
        conn.write(tmp.data, tmp.len);
 | 
					        conn.Send(std::string(tmp.data, tmp.len));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      //write audio init data, if needed
 | 
				
			||||||
      if (Strm.metadata.getContentP("audio") && Strm.metadata.getContentP("audio")->getContentP("init")){
 | 
					      if (Strm.metadata.getContentP("audio") && Strm.metadata.getContentP("audio")->getContentP("init")){
 | 
				
			||||||
        tmp.DTSCAudioInit(Strm);
 | 
					        tmp.DTSCAudioInit(Strm);
 | 
				
			||||||
        conn.write(tmp.data, tmp.len);
 | 
					        conn.Send(std::string(tmp.data, tmp.len));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      progressive_has_sent_header = true;
 | 
					      progressive_has_sent_header = true;
 | 
				
			||||||
      #if DEBUG >= 1
 | 
					      #if DEBUG >= 1
 | 
				
			||||||
      fprintf(stderr, "Sent progressive FLV header\n");
 | 
					      fprintf(stderr, "Sent progressive FLV header\n");
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    //HTTP_S.SendBodyPart(CONN_fd, tag->data, tag->len);//schrijf deze FLV tag onbewerkt weg
 | 
					    conn.Send(std::string(tag.data, tag.len));//write the tag contents
 | 
				
			||||||
    conn.write(tag.data, tag.len);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Handles Flash Dynamic HTTP streaming requests
 | 
					  /// Handles Flash Dynamic HTTP streaming requests
 | 
				
			||||||
| 
						 | 
					@ -129,6 +131,9 @@ namespace Connector_HTTP{
 | 
				
			||||||
    if (Strm.getPacket(0).getContentP("keyframe")){
 | 
					    if (Strm.getPacket(0).getContentP("keyframe")){
 | 
				
			||||||
      if (FlashBuf != ""){
 | 
					      if (FlashBuf != ""){
 | 
				
			||||||
        Flash_FragBuffer.push(FlashBuf);
 | 
					        Flash_FragBuffer.push(FlashBuf);
 | 
				
			||||||
 | 
					        while (Flash_FragBuffer.size() > 2){
 | 
				
			||||||
 | 
					          Flash_FragBuffer.pop();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        #if DEBUG >= 4
 | 
					        #if DEBUG >= 4
 | 
				
			||||||
        fprintf(stderr, "Received a fragment. Now %i in buffer.\n", (int)Flash_FragBuffer.size());
 | 
					        fprintf(stderr, "Received a fragment. Now %i in buffer.\n", (int)Flash_FragBuffer.size());
 | 
				
			||||||
        #endif
 | 
					        #endif
 | 
				
			||||||
| 
						 | 
					@ -165,96 +170,102 @@ namespace Connector_HTTP{
 | 
				
			||||||
    int temp;
 | 
					    int temp;
 | 
				
			||||||
    int Flash_RequestPending = 0;
 | 
					    int Flash_RequestPending = 0;
 | 
				
			||||||
    unsigned int lastStats = 0;
 | 
					    unsigned int lastStats = 0;
 | 
				
			||||||
    //int CurrentFragment = -1; later herbruiken?
 | 
					    conn.setBlocking(false);//do not block on conn.spool() when no data is available
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (conn.connected()){
 | 
					    while (conn.connected()){
 | 
				
			||||||
      //only parse input if available or not yet init'ed
 | 
					      //only parse input if available or not yet init'ed
 | 
				
			||||||
      if (HTTP_R.Read(conn, ready4data)){
 | 
					      if (conn.spool()){
 | 
				
			||||||
        handler = HANDLER_PROGRESSIVE;
 | 
					        if (HTTP_R.Read(conn.Received())){
 | 
				
			||||||
        #if DEBUG >= 4
 | 
					          handler = HANDLER_PROGRESSIVE;
 | 
				
			||||||
        std::cout << "Received request: " << HTTP_R.url << std::endl;
 | 
					          #if DEBUG >= 4
 | 
				
			||||||
        #endif
 | 
					          std::cout << "Received request: " << HTTP_R.url << std::endl;
 | 
				
			||||||
        if ((HTTP_R.url.find("Seg") != std::string::npos) && (HTTP_R.url.find("Frag") != std::string::npos)){handler = HANDLER_FLASH;}
 | 
					 | 
				
			||||||
        if (HTTP_R.url.find("f4m") != std::string::npos){handler = HANDLER_FLASH;}
 | 
					 | 
				
			||||||
        if (HTTP_R.url == "/crossdomain.xml"){
 | 
					 | 
				
			||||||
          handler = HANDLER_NONE;
 | 
					 | 
				
			||||||
          HTTP_S.Clean();
 | 
					 | 
				
			||||||
          HTTP_S.SetHeader("Content-Type", "text/xml");
 | 
					 | 
				
			||||||
          HTTP_S.SetBody("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" /><site-control permitted-cross-domain-policies=\"all\"/></cross-domain-policy>");
 | 
					 | 
				
			||||||
          HTTP_S.SendResponse(conn, "200", "OK");
 | 
					 | 
				
			||||||
          #if DEBUG >= 3
 | 
					 | 
				
			||||||
          printf("Sending crossdomain.xml file\n");
 | 
					 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
        }
 | 
					          if ((HTTP_R.url.find("Seg") != std::string::npos) && (HTTP_R.url.find("Frag") != std::string::npos)){handler = HANDLER_FLASH;}
 | 
				
			||||||
        if (HTTP_R.url.length() > 10 && HTTP_R.url.substr(0, 7) == "/embed_" && HTTP_R.url.substr(HTTP_R.url.length() - 3, 3) == ".js"){
 | 
					          if (HTTP_R.url.find("f4m") != std::string::npos){handler = HANDLER_FLASH;}
 | 
				
			||||||
          streamname = HTTP_R.url.substr(7, HTTP_R.url.length() - 10);
 | 
					          if (HTTP_R.url == "/crossdomain.xml"){
 | 
				
			||||||
          JSON::Value ServConf = JSON::fromFile("/tmp/mist/streamlist");
 | 
					            handler = HANDLER_NONE;
 | 
				
			||||||
          std::string response;
 | 
					 | 
				
			||||||
          handler = HANDLER_NONE;
 | 
					 | 
				
			||||||
          HTTP_S.Clean();
 | 
					 | 
				
			||||||
          HTTP_S.SetHeader("Content-Type", "application/javascript");
 | 
					 | 
				
			||||||
          response = "// Generating embed code for stream " + streamname + "\n\n";
 | 
					 | 
				
			||||||
          if (ServConf["streams"].isMember(streamname)){
 | 
					 | 
				
			||||||
            std::string streamurl = "http://" + HTTP_S.GetHeader("Host") + "/" + streamname + ".flv";
 | 
					 | 
				
			||||||
            response += "// Stream URL: " + streamurl + "\n\n";
 | 
					 | 
				
			||||||
            response += "document.write('<object width=\"600\" height=\"409\"><param name=\"movie\" value=\"http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf\"></param><param name=\"flashvars\" value=\"src="+HTTP::Parser::urlencode(streamurl)+"&controlBarMode=floating\"></param><param name=\"allowFullScreen\" value=\"true\"></param><param name=\"allowscriptaccess\" value=\"always\"></param><embed src=\"http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" width=\"600\" height=\"409\" flashvars=\"src="+HTTP::Parser::urlencode(streamurl)+"&controlBarMode=floating\"></embed></object>');\n";
 | 
					 | 
				
			||||||
          }else{
 | 
					 | 
				
			||||||
            response += "// Stream not available at this server.\nalert(\"This stream is currently not available at this server.\\\\nPlease try again later!\");";
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          response += "";
 | 
					 | 
				
			||||||
          HTTP_S.SetBody(response);
 | 
					 | 
				
			||||||
          HTTP_S.SendResponse(conn, "200", "OK");
 | 
					 | 
				
			||||||
          #if DEBUG >= 3
 | 
					 | 
				
			||||||
          printf("Sending embed code for %s\n", streamname.c_str());
 | 
					 | 
				
			||||||
          #endif
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (handler == HANDLER_FLASH){
 | 
					 | 
				
			||||||
          if (HTTP_R.url.find("f4m") == std::string::npos){
 | 
					 | 
				
			||||||
            Movie = HTTP_R.url.substr(1);
 | 
					 | 
				
			||||||
            Movie = Movie.substr(0,Movie.find("/"));
 | 
					 | 
				
			||||||
            Quality = HTTP_R.url.substr( HTTP_R.url.find("/",1)+1 );
 | 
					 | 
				
			||||||
            Quality = Quality.substr(0, Quality.find("Seg"));
 | 
					 | 
				
			||||||
            temp = HTTP_R.url.find("Seg") + 3;
 | 
					 | 
				
			||||||
            Segment = atoi( HTTP_R.url.substr(temp,HTTP_R.url.find("-",temp)-temp).c_str());
 | 
					 | 
				
			||||||
            temp = HTTP_R.url.find("Frag") + 4;
 | 
					 | 
				
			||||||
            ReqFragment = atoi( HTTP_R.url.substr(temp).c_str() );
 | 
					 | 
				
			||||||
            #if DEBUG >= 4
 | 
					 | 
				
			||||||
            printf( "Quality: %s, Seg %d Frag %d\n", Quality.c_str(), Segment, ReqFragment);
 | 
					 | 
				
			||||||
            #endif
 | 
					 | 
				
			||||||
            Flash_RequestPending++;
 | 
					 | 
				
			||||||
          }else{
 | 
					 | 
				
			||||||
            Movie = HTTP_R.url.substr(1);
 | 
					 | 
				
			||||||
            Movie = Movie.substr(0,Movie.find("/"));
 | 
					 | 
				
			||||||
            HTTP_S.Clean();
 | 
					            HTTP_S.Clean();
 | 
				
			||||||
            HTTP_S.SetHeader("Content-Type","text/xml");
 | 
					            HTTP_S.SetHeader("Content-Type", "text/xml");
 | 
				
			||||||
            HTTP_S.SetHeader("Cache-Control","no-cache");
 | 
					            HTTP_S.SetBody("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" /><site-control permitted-cross-domain-policies=\"all\"/></cross-domain-policy>");
 | 
				
			||||||
            std::string manifest = BuildManifest(Movie);
 | 
					            conn.Send(HTTP_S.BuildResponse("200", "OK"));
 | 
				
			||||||
            #if DEBUG >= 4
 | 
					 | 
				
			||||||
            printf("Manifest: %s\n", manifest.c_str());
 | 
					 | 
				
			||||||
            #endif
 | 
					 | 
				
			||||||
            HTTP_S.SetBody(manifest);
 | 
					 | 
				
			||||||
            HTTP_S.SendResponse(conn, "200", "OK");
 | 
					 | 
				
			||||||
            #if DEBUG >= 3
 | 
					            #if DEBUG >= 3
 | 
				
			||||||
            printf("Sent manifest\n");
 | 
					            printf("Sending crossdomain.xml file\n");
 | 
				
			||||||
            #endif
 | 
					            #endif
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          #if DEBUG >= 4
 | 
					          if (HTTP_R.url.length() > 10 && HTTP_R.url.substr(0, 7) == "/embed_" && HTTP_R.url.substr(HTTP_R.url.length() - 3, 3) == ".js"){
 | 
				
			||||||
          printf( "Movie: %s\n", Movie.c_str());
 | 
					            streamname = HTTP_R.url.substr(7, HTTP_R.url.length() - 10);
 | 
				
			||||||
 | 
					            JSON::Value ServConf = JSON::fromFile("/tmp/mist/streamlist");
 | 
				
			||||||
 | 
					            std::string response;
 | 
				
			||||||
 | 
					            handler = HANDLER_NONE;
 | 
				
			||||||
 | 
					            HTTP_S.Clean();
 | 
				
			||||||
 | 
					            HTTP_S.SetHeader("Content-Type", "application/javascript");
 | 
				
			||||||
 | 
					            response = "// Generating embed code for stream " + streamname + "\n\n";
 | 
				
			||||||
 | 
					            if (ServConf["streams"].isMember(streamname)){
 | 
				
			||||||
 | 
					              std::string streamurl = "http://" + HTTP_S.GetHeader("Host") + "/" + streamname + ".flv";
 | 
				
			||||||
 | 
					              response += "// Stream URL: " + streamurl + "\n\n";
 | 
				
			||||||
 | 
					              response += "document.write('<object width=\"600\" height=\"409\"><param name=\"movie\" value=\"http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf\"></param><param name=\"flashvars\" value=\"src="+HTTP::Parser::urlencode(streamurl)+"&controlBarMode=floating\"></param><param name=\"allowFullScreen\" value=\"true\"></param><param name=\"allowscriptaccess\" value=\"always\"></param><embed src=\"http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" width=\"600\" height=\"409\" flashvars=\"src="+HTTP::Parser::urlencode(streamurl)+"&controlBarMode=floating\"></embed></object>');\n";
 | 
				
			||||||
 | 
					            }else{
 | 
				
			||||||
 | 
					              response += "// Stream not available at this server.\nalert(\"This stream is currently not available at this server.\\\\nPlease try again later!\");";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            response += "";
 | 
				
			||||||
 | 
					            HTTP_S.SetBody(response);
 | 
				
			||||||
 | 
					            conn.Send(HTTP_S.BuildResponse("200", "OK"));
 | 
				
			||||||
 | 
					            #if DEBUG >= 3
 | 
				
			||||||
 | 
					            printf("Sending embed code for %s\n", streamname.c_str());
 | 
				
			||||||
 | 
					            #endif
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (handler == HANDLER_FLASH){
 | 
				
			||||||
 | 
					            if (HTTP_R.url.find("f4m") == std::string::npos){
 | 
				
			||||||
 | 
					              Movie = HTTP_R.url.substr(1);
 | 
				
			||||||
 | 
					              Movie = Movie.substr(0,Movie.find("/"));
 | 
				
			||||||
 | 
					              Quality = HTTP_R.url.substr( HTTP_R.url.find("/",1)+1 );
 | 
				
			||||||
 | 
					              Quality = Quality.substr(0, Quality.find("Seg"));
 | 
				
			||||||
 | 
					              temp = HTTP_R.url.find("Seg") + 3;
 | 
				
			||||||
 | 
					              Segment = atoi( HTTP_R.url.substr(temp,HTTP_R.url.find("-",temp)-temp).c_str());
 | 
				
			||||||
 | 
					              temp = HTTP_R.url.find("Frag") + 4;
 | 
				
			||||||
 | 
					              ReqFragment = atoi( HTTP_R.url.substr(temp).c_str() );
 | 
				
			||||||
 | 
					              #if DEBUG >= 4
 | 
				
			||||||
 | 
					              printf( "Quality: %s, Seg %d Frag %d\n", Quality.c_str(), Segment, ReqFragment);
 | 
				
			||||||
 | 
					              #endif
 | 
				
			||||||
 | 
					              Flash_RequestPending++;
 | 
				
			||||||
 | 
					            }else{
 | 
				
			||||||
 | 
					              Movie = HTTP_R.url.substr(1);
 | 
				
			||||||
 | 
					              Movie = Movie.substr(0,Movie.find("/"));
 | 
				
			||||||
 | 
					              HTTP_S.Clean();
 | 
				
			||||||
 | 
					              HTTP_S.SetHeader("Content-Type","text/xml");
 | 
				
			||||||
 | 
					              HTTP_S.SetHeader("Cache-Control","no-cache");
 | 
				
			||||||
 | 
					              std::string manifest = BuildManifest(Movie);
 | 
				
			||||||
 | 
					              #if DEBUG >= 4
 | 
				
			||||||
 | 
					              printf("Manifest: %s\n", manifest.c_str());
 | 
				
			||||||
 | 
					              #endif
 | 
				
			||||||
 | 
					              HTTP_S.SetBody(manifest);
 | 
				
			||||||
 | 
					              conn.Send(HTTP_S.BuildResponse("200", "OK"));
 | 
				
			||||||
 | 
					              #if DEBUG >= 3
 | 
				
			||||||
 | 
					              printf("Sent manifest\n");
 | 
				
			||||||
 | 
					              #endif
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            #if DEBUG >= 4
 | 
				
			||||||
 | 
					            printf( "Movie: %s\n", Movie.c_str());
 | 
				
			||||||
 | 
					            #endif
 | 
				
			||||||
 | 
					            streamname = Movie;
 | 
				
			||||||
 | 
					            ready4data = true;
 | 
				
			||||||
 | 
					          }//FLASH handler
 | 
				
			||||||
 | 
					          if (handler == HANDLER_PROGRESSIVE){
 | 
				
			||||||
 | 
					            //we assume the URL is the stream name with a 3 letter extension
 | 
				
			||||||
 | 
					            std::string extension = HTTP_R.url.substr(HTTP_R.url.size()-4);
 | 
				
			||||||
 | 
					            streamname = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip the extension
 | 
				
			||||||
 | 
					            /// \todo VoD streams will need support for position reading from the URL parameters
 | 
				
			||||||
 | 
					            ready4data = true;
 | 
				
			||||||
 | 
					            #if DEBUG >= 4
 | 
				
			||||||
 | 
					            printf( "Opening progressive stream: %s\n", streamname.c_str());
 | 
				
			||||||
 | 
					            #endif
 | 
				
			||||||
 | 
					          }//PROGRESSIVE handler
 | 
				
			||||||
 | 
					          HTTP_R.Clean(); //clean for any possinble next requests
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					          #if DEBUG >= 3
 | 
				
			||||||
 | 
					          fprintf(stderr, "Could not parse the following:\n%s\n", conn.Received().c_str());
 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
          streamname = Movie;
 | 
					        }
 | 
				
			||||||
          ready4data = true;
 | 
					 | 
				
			||||||
        }//FLASH handler
 | 
					 | 
				
			||||||
        if (handler == HANDLER_PROGRESSIVE){
 | 
					 | 
				
			||||||
          //we assume the URL is the stream name with a 3 letter extension
 | 
					 | 
				
			||||||
          std::string extension = HTTP_R.url.substr(HTTP_R.url.size()-4);
 | 
					 | 
				
			||||||
          streamname = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip the extension
 | 
					 | 
				
			||||||
          /// \todo VoD streams will need support for position reading from the URL parameters
 | 
					 | 
				
			||||||
          ready4data = true;
 | 
					 | 
				
			||||||
          #if DEBUG >= 4
 | 
					 | 
				
			||||||
          printf( "Opening progressive stream: %s\n", streamname.c_str());
 | 
					 | 
				
			||||||
          #endif
 | 
					 | 
				
			||||||
        }//PROGRESSIVE handler
 | 
					 | 
				
			||||||
        HTTP_R.CleanForNext(); //clean for any possinble next requests
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (ready4data){
 | 
					      if (ready4data){
 | 
				
			||||||
        if (!inited){
 | 
					        if (!inited){
 | 
				
			||||||
| 
						 | 
					@ -277,22 +288,18 @@ namespace Connector_HTTP{
 | 
				
			||||||
          HTTP_S.SetHeader("Content-Type","video/mp4");
 | 
					          HTTP_S.SetHeader("Content-Type","video/mp4");
 | 
				
			||||||
          HTTP_S.SetBody(MP4::mdatFold(Flash_FragBuffer.front()));
 | 
					          HTTP_S.SetBody(MP4::mdatFold(Flash_FragBuffer.front()));
 | 
				
			||||||
          Flash_FragBuffer.pop();
 | 
					          Flash_FragBuffer.pop();
 | 
				
			||||||
          HTTP_S.SendResponse(conn, "200", "OK");//schrijf de HTTP response header
 | 
					          conn.Send(HTTP_S.BuildResponse("200", "OK"));
 | 
				
			||||||
          Flash_RequestPending--;
 | 
					          Flash_RequestPending--;
 | 
				
			||||||
          #if DEBUG >= 3
 | 
					          #if DEBUG >= 3
 | 
				
			||||||
          fprintf(stderr, "Sending a video fragment. %i left in buffer, %i requested\n", (int)Flash_FragBuffer.size(), Flash_RequestPending);
 | 
					          fprintf(stderr, "Sending a video fragment. %i left in buffer, %i requested\n", (int)Flash_FragBuffer.size(), Flash_RequestPending);
 | 
				
			||||||
          #endif
 | 
					          #endif
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (inited){
 | 
					        unsigned int now = time(0);
 | 
				
			||||||
          unsigned int now = time(0);
 | 
					        if (now != lastStats){
 | 
				
			||||||
          if (now != lastStats){
 | 
					          lastStats = now;
 | 
				
			||||||
            lastStats = now;
 | 
					          ss.Send("S "+conn.getStats("HTTP"));
 | 
				
			||||||
            std::string stat = "S "+conn.getStats("HTTP");
 | 
					 | 
				
			||||||
            ss.write(stat);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (ss.canRead()){
 | 
					        if (ss.spool() || ss.Received() != ""){
 | 
				
			||||||
          ss.spool();
 | 
					 | 
				
			||||||
          if (Strm.parsePacket(ss.Received())){
 | 
					          if (Strm.parsePacket(ss.Received())){
 | 
				
			||||||
            tag.DTSCLoader(Strm);
 | 
					            tag.DTSCLoader(Strm);
 | 
				
			||||||
            if (handler == HANDLER_FLASH){
 | 
					            if (handler == HANDLER_FLASH){
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,6 @@ void WriteFile( std::string Filename, std::string contents ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConnectedUser{
 | 
					class ConnectedUser{
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
    std::string writebuffer;
 | 
					 | 
				
			||||||
    Socket::Connection C;
 | 
					    Socket::Connection C;
 | 
				
			||||||
    HTTP::Parser H;
 | 
					    HTTP::Parser H;
 | 
				
			||||||
    bool Authorized;
 | 
					    bool Authorized;
 | 
				
			||||||
| 
						 | 
					@ -439,7 +438,7 @@ int main(int argc, char ** argv){
 | 
				
			||||||
        uplink->H.Clean();
 | 
					        uplink->H.Clean();
 | 
				
			||||||
        uplink->H.SetBody("command="+HTTP::Parser::urlencode(Response.toString()));
 | 
					        uplink->H.SetBody("command="+HTTP::Parser::urlencode(Response.toString()));
 | 
				
			||||||
        uplink->H.BuildRequest();
 | 
					        uplink->H.BuildRequest();
 | 
				
			||||||
        uplink->writebuffer += uplink->H.BuildResponse("200", "OK");
 | 
					        uplink->C.Send(uplink->H.BuildResponse("200", "OK"));
 | 
				
			||||||
        uplink->H.Clean();
 | 
					        uplink->H.Clean();
 | 
				
			||||||
        //Log("UPLK", "Sending server data to uplink.");
 | 
					        //Log("UPLK", "Sending server data to uplink.");
 | 
				
			||||||
      }else{
 | 
					      }else{
 | 
				
			||||||
| 
						 | 
					@ -459,8 +458,7 @@ int main(int argc, char ** argv){
 | 
				
			||||||
          buffers.erase(it);
 | 
					          buffers.erase(it);
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        it->spool();
 | 
					        if (it->spool()){
 | 
				
			||||||
        if (it->Received() != ""){
 | 
					 | 
				
			||||||
          size_t newlines = it->Received().find("\n\n");
 | 
					          size_t newlines = it->Received().find("\n\n");
 | 
				
			||||||
          while (newlines != std::string::npos){
 | 
					          while (newlines != std::string::npos){
 | 
				
			||||||
            Request = it->Received().substr(0, newlines);
 | 
					            Request = it->Received().substr(0, newlines);
 | 
				
			||||||
| 
						 | 
					@ -489,85 +487,84 @@ int main(int argc, char ** argv){
 | 
				
			||||||
          users.erase(it);
 | 
					          users.erase(it);
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (it->writebuffer != ""){
 | 
					        if (it->C.spool()){
 | 
				
			||||||
          it->C.iwrite(it->writebuffer);
 | 
					          if (it->H.Read(it->C.Received())){
 | 
				
			||||||
        }
 | 
					            Response.null(); //make sure no data leaks from previous requests
 | 
				
			||||||
        if (it->H.Read(it->C)){
 | 
					            if (it->clientMode){
 | 
				
			||||||
          Response.null(); //make sure no data leaks from previous requests
 | 
					              // In clientMode, requests are reversed. These are connections we initiated to GearBox.
 | 
				
			||||||
          if (it->clientMode){
 | 
					              // They are assumed to be authorized, but authorization to gearbox is still done.
 | 
				
			||||||
            // In clientMode, requests are reversed. These are connections we initiated to GearBox.
 | 
					              // This authorization uses the compiled-in username and password (account).
 | 
				
			||||||
            // They are assumed to be authorized, but authorization to gearbox is still done.
 | 
					              Request = JSON::fromString(it->H.body);
 | 
				
			||||||
            // This authorization uses the compiled-in username and password (account).
 | 
					              if (Request["authorize"]["status"] != "OK"){
 | 
				
			||||||
            Request = JSON::fromString(it->H.body);
 | 
					                if (Request["authorize"].isMember("challenge")){
 | 
				
			||||||
            if (Request["authorize"]["status"] != "OK"){
 | 
					                  it->logins++;
 | 
				
			||||||
              if (Request["authorize"].isMember("challenge")){
 | 
					                  if (it->logins > 2){
 | 
				
			||||||
                it->logins++;
 | 
					                    Log("UPLK", "Max login attempts passed - dropping connection to uplink.");
 | 
				
			||||||
                if (it->logins > 2){
 | 
					                    it->C.close();
 | 
				
			||||||
                  Log("UPLK", "Max login attempts passed - dropping connection to uplink.");
 | 
					                  }else{
 | 
				
			||||||
                  it->C.close();
 | 
					                    Response["config"] = Storage["config"];
 | 
				
			||||||
                }else{
 | 
					                    Response["streams"] = Storage["streams"];
 | 
				
			||||||
                  Response["config"] = Storage["config"];
 | 
					                    Response["log"] = Storage["log"];
 | 
				
			||||||
                  Response["streams"] = Storage["streams"];
 | 
					                    Response["statistics"] = Storage["statistics"];
 | 
				
			||||||
                  Response["log"] = Storage["log"];
 | 
					                    Response["authorize"]["username"] = TOSTRING(COMPILED_USERNAME);
 | 
				
			||||||
                  Response["statistics"] = Storage["statistics"];
 | 
					                    Log("UPLK", "Responding to login challenge: " + (std::string)Request["authorize"]["challenge"]);
 | 
				
			||||||
                  Response["authorize"]["username"] = TOSTRING(COMPILED_USERNAME);
 | 
					                    Response["authorize"]["password"] = md5(TOSTRING(COMPILED_PASSWORD) + (std::string)Request["authorize"]["challenge"]);
 | 
				
			||||||
                  Log("UPLK", "Responding to login challenge: " + (std::string)Request["authorize"]["challenge"]);
 | 
					                    it->H.Clean();
 | 
				
			||||||
                  Response["authorize"]["password"] = md5(TOSTRING(COMPILED_PASSWORD) + (std::string)Request["authorize"]["challenge"]);
 | 
					                    it->H.SetBody("command="+HTTP::Parser::urlencode(Response.toString()));
 | 
				
			||||||
                  it->H.Clean();
 | 
					                    it->H.BuildRequest();
 | 
				
			||||||
                  it->H.SetBody("command="+HTTP::Parser::urlencode(Response.toString()));
 | 
					                    it->C.Send(it->H.BuildResponse("200", "OK"));
 | 
				
			||||||
                  it->H.BuildRequest();
 | 
					                    it->H.Clean();
 | 
				
			||||||
                  it->writebuffer += it->H.BuildResponse("200", "OK");
 | 
					                    Log("UPLK", "Attempting login to uplink.");
 | 
				
			||||||
                  it->H.Clean();
 | 
					                  }
 | 
				
			||||||
                  Log("UPLK", "Attempting login to uplink.");
 | 
					                }
 | 
				
			||||||
 | 
					              }else{
 | 
				
			||||||
 | 
					                if (Request.isMember("config")){CheckConfig(Request["config"], Storage["config"]);}
 | 
				
			||||||
 | 
					                if (Request.isMember("streams")){CheckStreams(Request["streams"], Storage["streams"]);}
 | 
				
			||||||
 | 
					                if (Request.isMember("clearstatlogs")){
 | 
				
			||||||
 | 
					                  Storage["log"].null();
 | 
				
			||||||
 | 
					                  Storage["statistics"].null();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }else{
 | 
					            }else{
 | 
				
			||||||
              if (Request.isMember("config")){CheckConfig(Request["config"], Storage["config"]);}
 | 
					              Request = JSON::fromString(it->H.GetVar("command"));
 | 
				
			||||||
              if (Request.isMember("streams")){CheckStreams(Request["streams"], Storage["streams"]);}
 | 
					              std::cout << "Request: " << Request.toString() << std::endl;
 | 
				
			||||||
              if (Request.isMember("clearstatlogs")){
 | 
					              Authorize(Request, Response, (*it));
 | 
				
			||||||
 | 
					              if (it->Authorized){
 | 
				
			||||||
 | 
					                //Parse config and streams from the request.
 | 
				
			||||||
 | 
					                if (Request.isMember("config")){CheckConfig(Request["config"], Storage["config"]);}
 | 
				
			||||||
 | 
					                if (Request.isMember("streams")){CheckStreams(Request["streams"], Storage["streams"]);}
 | 
				
			||||||
 | 
					                if (Request.isMember("save")){
 | 
				
			||||||
 | 
					                  WriteFile("config.json", Storage.toString());
 | 
				
			||||||
 | 
					                  Log("CONF", "Config written to file on request through API");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                //sent current configuration, no matter if it was changed or not
 | 
				
			||||||
 | 
					                //Response["streams"] = Storage["streams"];
 | 
				
			||||||
 | 
					                Response["config"] = Storage["config"];
 | 
				
			||||||
 | 
					                Response["streams"] = Storage["streams"];
 | 
				
			||||||
 | 
					                //add required data to the current unix time to the config, for syncing reasons
 | 
				
			||||||
 | 
					                Response["config"]["time"] = (long long int)time(0);
 | 
				
			||||||
 | 
					                if (!Response["config"].isMember("serverid")){Response["config"]["serverid"] = "";}
 | 
				
			||||||
 | 
					                //sent any available logs and statistics
 | 
				
			||||||
 | 
					                Response["log"] = Storage["log"];
 | 
				
			||||||
 | 
					                Response["statistics"] = Storage["statistics"];
 | 
				
			||||||
 | 
					                //clear log and statistics to prevent useless data transfer
 | 
				
			||||||
                Storage["log"].null();
 | 
					                Storage["log"].null();
 | 
				
			||||||
                Storage["statistics"].null();
 | 
					                Storage["statistics"].null();
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					              jsonp = "";
 | 
				
			||||||
          }else{
 | 
					              if (it->H.GetVar("callback") != ""){jsonp = it->H.GetVar("callback");}
 | 
				
			||||||
            Request = JSON::fromString(it->H.GetVar("command"));
 | 
					              if (it->H.GetVar("jsonp") != ""){jsonp = it->H.GetVar("jsonp");}
 | 
				
			||||||
            std::cout << "Request: " << Request.toString() << std::endl;
 | 
					              it->H.Clean();
 | 
				
			||||||
            Authorize(Request, Response, (*it));
 | 
					              it->H.protocol = "HTTP/1.0";
 | 
				
			||||||
            if (it->Authorized){
 | 
					              it->H.SetHeader("Content-Type", "text/javascript");
 | 
				
			||||||
              //Parse config and streams from the request.
 | 
					              if (jsonp == ""){
 | 
				
			||||||
              if (Request.isMember("config")){CheckConfig(Request["config"], Storage["config"]);}
 | 
					                it->H.SetBody(Response.toString()+"\n\n");
 | 
				
			||||||
              if (Request.isMember("streams")){CheckStreams(Request["streams"], Storage["streams"]);}
 | 
					              }else{
 | 
				
			||||||
              if (Request.isMember("save")){
 | 
					                it->H.SetBody(jsonp+"("+Response.toString()+");\n\n");
 | 
				
			||||||
                WriteFile("config.json", Storage.toString());
 | 
					 | 
				
			||||||
                Log("CONF", "Config written to file on request through API");
 | 
					 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              //sent current configuration, no matter if it was changed or not
 | 
					              it->C.Send(it->H.BuildResponse("200", "OK"));
 | 
				
			||||||
              //Response["streams"] = Storage["streams"];
 | 
					                it->H.Clean();
 | 
				
			||||||
              Response["config"] = Storage["config"];
 | 
					 | 
				
			||||||
              Response["streams"] = Storage["streams"];
 | 
					 | 
				
			||||||
              //add required data to the current unix time to the config, for syncing reasons
 | 
					 | 
				
			||||||
              Response["config"]["time"] = (long long int)time(0);
 | 
					 | 
				
			||||||
              if (!Response["config"].isMember("serverid")){Response["config"]["serverid"] = "";}
 | 
					 | 
				
			||||||
              //sent any available logs and statistics
 | 
					 | 
				
			||||||
              Response["log"] = Storage["log"];
 | 
					 | 
				
			||||||
              Response["statistics"] = Storage["statistics"];
 | 
					 | 
				
			||||||
              //clear log and statistics to prevent useless data transfer
 | 
					 | 
				
			||||||
              Storage["log"].null();
 | 
					 | 
				
			||||||
              Storage["statistics"].null();
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            jsonp = "";
 | 
					 | 
				
			||||||
            if (it->H.GetVar("callback") != ""){jsonp = it->H.GetVar("callback");}
 | 
					 | 
				
			||||||
            if (it->H.GetVar("jsonp") != ""){jsonp = it->H.GetVar("jsonp");}
 | 
					 | 
				
			||||||
            it->H.Clean();
 | 
					 | 
				
			||||||
            it->H.protocol = "HTTP/1.0";
 | 
					 | 
				
			||||||
            it->H.SetHeader("Content-Type", "text/javascript");
 | 
					 | 
				
			||||||
            if (jsonp == ""){
 | 
					 | 
				
			||||||
              it->H.SetBody(Response.toString()+"\n\n");
 | 
					 | 
				
			||||||
            }else{
 | 
					 | 
				
			||||||
              it->H.SetBody(jsonp+"("+Response.toString()+");\n\n");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            it->writebuffer += it->H.BuildResponse("200", "OK");
 | 
					 | 
				
			||||||
            it->H.Clean();
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue