Converting to split-up controller for readability.

This commit is contained in:
Thulinma 2012-12-04 13:01:22 +01:00
parent 4c9e0c7083
commit 0db5f60b95
8 changed files with 134 additions and 128 deletions

View file

@ -298,6 +298,9 @@
// protocol select
$pname = $('<select>').attr('id', 'new-protocol-name');
$pname.append( $('<option>').attr('value', 'HTTP').text('HTTP') );
$pname.append( $('<option>').attr('value', 'HTTPDynamic').text('HTTPDynamic') );
$pname.append( $('<option>').attr('value', 'HTTPProgressive').text('HTTPProgressive') );
$pname.append( $('<option>').attr('value', 'HTTPSmooth').text('HTTPSmooth') );
$pname.append( $('<option>').attr('value', 'RTMP').text('RTMP') );
$nprot.append( $('<td>').append($pname) );

View file

@ -11,7 +11,7 @@ SUBDIRS=converters analysers
bin_PROGRAMS=MistBuffer MistController MistConnRAW MistConnRTMP MistConnHTTP MistConnHTTPProgressive MistConnHTTPDynamic MistConnHTTPSmooth MistPlayer
MistBuffer_SOURCES=buffer.cpp buffer_user.h buffer_user.cpp buffer_stream.h buffer_stream.cpp tinythread.cpp tinythread.h ../VERSION
MistBuffer_LDADD=$(MIST_LIBS) -lpthread
MistController_SOURCES=controller.cpp ../VERSION ./server.html.h
MistController_SOURCES=controller.cpp controller_connectors.h controller_connectors.cpp controller_storage.h controller_storage.cpp ../VERSION ./server.html.h
MistConnRAW_SOURCES=conn_raw.cpp ../VERSION
MistConnRTMP_SOURCES=conn_rtmp.cpp ../VERSION
MistConnHTTP_SOURCES=conn_http.cpp tinythread.cpp tinythread.h ../VERSION ./embed.js.h

View file

@ -11,13 +11,13 @@
#include <sys/wait.h>
#include <getopt.h>
#include <set>
#include <openssl/md5.h>
#include <mist/socket.h>
#include <mist/http_parser.h>
#include <mist/config.h>
#include <mist/procs.h>
#include <mist/stream.h>
#include <mist/timing.h>
#include <mist/auth.h>
#include "tinythread.h"
#include "embed.js.h"
@ -188,22 +188,10 @@ namespace Connector_HTTP{
Handle_None(H, conn);//anything else doesn't get handled
}
/// Wrapper function for openssl MD5 implementation
std::string md5(std::string input){
char tmp[3];
std::string ret;
const unsigned char * res = MD5((const unsigned char*)input.c_str(), input.length(), 0);
for (int i = 0; i < 16; ++i){
snprintf(tmp, 3, "%02x", res[i]);
ret += tmp;
}
return ret;
}
/// Handles requests without associated handler, displaying a nice friendly error message.
void Handle_Through_Connector(HTTP::Parser & H, Socket::Connection * conn, std::string & connector){
//create a unique ID based on a hash of the user agent and host, followed by the stream name and connector
std::string uid = md5(H.GetHeader("User-Agent")+conn->getHost())+"_"+H.GetVar("stream")+"_"+connector;
std::string uid = Secure::md5(H.GetHeader("User-Agent")+conn->getHost())+"_"+H.GetVar("stream")+"_"+connector;
H.SetHeader("X-UID", uid);//add the UID to the headers before copying
H.SetHeader("X-Origin", conn->getHost());//add the UID to the headers before copying
std::string request = H.BuildRequest();//copy the request for later forwarding to the connector
@ -417,11 +405,6 @@ int main(int argc, char ** argv){
if (!server_socket.connected()){return 1;}
conf.activate();
//start progressive and dynamic handlers from the same folder as this application
Util::Procs::Start("progressive", Util::getMyPath() + "MistConnHTTPProgressive -n");
Util::Procs::Start("dynamic", Util::getMyPath() + "MistConnHTTPDynamic -n");
Util::Procs::Start("smooth", Util::getMyPath() + "MistConnHTTPSmooth -n");
while (server_socket.connected() && conf.is_active){
Socket::Connection S = server_socket.accept();
if (S.connected()){//check if the new connection is valid

View file

@ -22,13 +22,14 @@
#include <sys/types.h>
#include <signal.h>
#include <sstream>
#include <openssl/md5.h>
#include <mist/config.h>
#include <mist/socket.h>
#include <mist/http_parser.h>
#include <mist/procs.h>
#include <mist/auth.h>
#include <mist/timing.h>
#include "controller_storage.h"
#include "controller_connectors.h"
#include "server.html.h"
#define UPLINK_INTERVAL 30
@ -38,22 +39,8 @@
namespace Controller{
std::map<std::string, int> lastBuffer; ///< Last moment of contact with all buffers.
Auth keychecker; ///< Checks key authorization.
Secure::Auth keychecker; ///< Checks key authorization.
/// Wrapper function for openssl MD5 implementation
std::string md5(std::string input){
char tmp[3];
std::string ret;
const unsigned char * res = MD5((const unsigned char*)input.c_str(), input.length(), 0);
for (int i = 0; i < 16; ++i){
snprintf(tmp, 3, "%02x", res[i]);
ret += tmp;
}
return ret;
}
JSON::Value Storage; ///< Global storage of data.
void WriteFile( std::string Filename, std::string contents ) {
std::ofstream File;
@ -79,32 +66,17 @@ class ConnectedUser{
}
};
void Log(std::string kind, std::string message){
//if last log message equals this one, do not log.
if (Storage["log"].size() > 0){
JSON::ArrIter it = Storage["log"].ArrEnd() - 1;
if ((*it)[2] == message){return;}
}
JSON::Value m;
m.append(Util::epoch());
m.append(kind);
m.append(message);
Storage["log"].append(m);
Storage["log"].shrink(100);//limit to 100 log messages
std::cout << "[" << kind << "] " << message << std::endl;
}
void Authorize( JSON::Value & Request, JSON::Value & Response, ConnectedUser & conn ) {
time_t Time = time(0);
tm * TimeInfo = localtime(&Time);
std::stringstream Date;
std::string retval;
Date << TimeInfo->tm_mday << "-" << TimeInfo->tm_mon << "-" << TimeInfo->tm_year + 1900;
std::string Challenge = md5( Date.str().c_str() + conn.C.getHost() );
std::string Challenge = Secure::md5( Date.str().c_str() + conn.C.getHost() );
if( Request.isMember( "authorize" ) ) {
std::string UserID = Request["authorize"]["username"];
if (Storage["account"].isMember(UserID)){
if (md5(Storage["account"][UserID]["password"].asString() + Challenge) == Request["authorize"]["password"].asString()){
if (Secure::md5(Storage["account"][UserID]["password"].asString() + Challenge) == Request["authorize"]["password"].asString()){
Response["authorize"]["status"] = "OK";
conn.Username = UserID;
conn.Authorized = true;
@ -112,7 +84,7 @@ void Authorize( JSON::Value & Request, JSON::Value & Response, ConnectedUser & c
}
}
if (UserID != ""){
if (Request["authorize"]["password"].asString() != "" && md5(Storage["account"][UserID]["password"].asString()) != Request["authorize"]["password"].asString()){
if (Request["authorize"]["password"].asString() != "" && Secure::md5(Storage["account"][UserID]["password"].asString()) != Request["authorize"]["password"].asString()){
Log("AUTH", "Failed login attempt "+UserID+" @ "+conn.C.getHost());
}
}
@ -125,78 +97,6 @@ void Authorize( JSON::Value & Request, JSON::Value & Response, ConnectedUser & c
return;
}
void CheckProtocols(JSON::Value & p){
static std::map<std::string, std::string> current_connectors;
std::map<std::string, std::string> new_connectors;
std::map<std::string, std::string>::iterator iter;
std::string tmp;
JSON::Value counter = (long long int)0;
//collect object type
for (JSON::ObjIter jit = p.ObjBegin(); jit != p.ObjEnd(); jit++){
if (!jit->second.isMember("connector") || jit->second["connector"].asString() == ""){continue;}
if (!jit->second.isMember("port") || jit->second["port"].asInt() == 0){continue;}
tmp = "MistConn";
tmp += jit->second["connector"].asString();
tmp += " -n -p ";
tmp += jit->second["port"].asString();
if (jit->second.isMember("interface") && jit->second["interface"].asString() != "" && jit->second["interface"].asString() != "0.0.0.0"){
tmp += " -i ";
tmp += jit->second["interface"].asString();
}
if (jit->second.isMember("username") && jit->second["username"].asString() != "" && jit->second["username"].asString() != "root"){
tmp += " -u ";
tmp += jit->second["username"].asString();
}
counter = counter.asInt() + 1;
new_connectors[std::string("Conn")+counter.asString()] = tmp;
}
//collect array type
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
if (!(*ait).isMember("connector") || (*ait)["connector"].asString() == ""){continue;}
if (!(*ait).isMember("port") || (*ait)["port"].asInt() == 0){continue;}
tmp = "MistConn";
tmp += (*ait)["connector"].asString();
tmp += " -n -p ";
tmp += (*ait)["port"].asString();
if ((*ait).isMember("interface") && (*ait)["interface"].asString() != "" && (*ait)["interface"].asString() != "0.0.0.0"){
tmp += " -i ";
tmp += (*ait)["interface"].asString();
}
if ((*ait).isMember("username") && (*ait)["username"].asString() != "" && (*ait)["username"].asString() != "root"){
tmp += " -u ";
tmp += (*ait)["username"].asString();
}
counter = counter.asInt() + 1;
new_connectors[std::string("Conn")+counter.asString()] = tmp;
if (Util::Procs::isActive(std::string("Conn")+counter.asString())){
(*ait)["online"] = 1;
}else{
(*ait)["online"] = 0;
}
}
//shut down deleted/changed connectors
for (iter = current_connectors.begin(); iter != current_connectors.end(); iter++){
if (new_connectors.count(iter->first) != 1 || new_connectors[iter->first] != iter->second){
Log("CONF", "Stopping connector: " + iter->second);
Util::Procs::Stop(iter->first);
}
}
//start up new/changed connectors
for (iter = new_connectors.begin(); iter != new_connectors.end(); iter++){
if (current_connectors.count(iter->first) != 1 || current_connectors[iter->first] != iter->second || !Util::Procs::isActive(iter->first)){
Log("CONF", "Starting connector: " + iter->second);
Util::Procs::Start(iter->first, Util::getMyPath() + iter->second);
}
}
//store new state
current_connectors = new_connectors;
}
void CheckConfig(JSON::Value & in, JSON::Value & out){
for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){
if (out.isMember(jit->first)){
@ -477,7 +377,7 @@ int main(int argc, char ** argv){
std::string uname = account.substr(0, colon);
std::string pword = account.substr(colon + 1, std::string::npos);
Controller::Log("CONF", "Created account "+uname+" through commandline option");
Controller::Storage["account"][uname]["password"] = Controller::md5(pword);
Controller::Storage["account"][uname]["password"] = Secure::md5(pword);
}
}
time_t lastuplink = 0;
@ -645,7 +545,7 @@ int main(int argc, char ** argv){
Response["authorize"]["username"] = COMPILED_USERNAME;
Controller::checkCapable(Response["capabilities"]);
Controller::Log("UPLK", "Responding to login challenge: " + Request["authorize"]["challenge"].asString());
Response["authorize"]["password"] = Controller::md5(COMPILED_PASSWORD + Request["authorize"]["challenge"].asString());
Response["authorize"]["password"] = Secure::md5(COMPILED_PASSWORD + Request["authorize"]["challenge"].asString());
it->H.Clean();
it->H.SetBody("command="+HTTP::Parser::urlencode(Response.toString()));
it->H.BuildRequest();

View file

@ -0,0 +1,79 @@
#include <mist/json.h>
#include <mist/config.h>
#include <mist/procs.h>
#include "controller_storage.h"
namespace Controller{
void CheckProtocols(JSON::Value & p){
static std::map<std::string, std::string> current_connectors;
std::map<std::string, std::string> new_connectors;
std::map<std::string, std::string>::iterator iter;
bool haveHTTPgeneric = false;
bool haveHTTPspecific = false;
std::string tmp;
JSON::Value counter = (long long int)0;
for (JSON::ArrIter ait = p.ArrBegin(); ait != p.ArrEnd(); ait++){
if (!(*ait).isMember("connector") || (*ait)["connector"].asString() == ""){continue;}
tmp = std::string("MistConn") + (*ait)["connector"].asString() + std::string(" -n");
if ((*ait)["connector"].asString() == "HTTP"){haveHTTPgeneric = true;}
if ((*ait)["connector"].asString() != "HTTP" && (*ait)["connector"].asString().substr(0, 4) == "HTTP"){haveHTTPspecific = true;}
if ((*ait).isMember("port") && (*ait)["port"].asInt() != 0){
tmp += std::string(" -p ") + (*ait)["port"].asString();
}
if ((*ait).isMember("interface") && (*ait)["interface"].asString() != "" && (*ait)["interface"].asString() != "0.0.0.0"){
tmp += std::string(" -i ") + (*ait)["interface"].asString();
}
if ((*ait).isMember("username") && (*ait)["username"].asString() != "" && (*ait)["username"].asString() != "root"){
tmp += std::string(" -u ") + (*ait)["username"].asString();
}
if ((*ait).isMember("args") && (*ait)["args"].asString() != ""){
tmp += std::string(" ") + (*ait)["args"].asString();
}
counter = counter.asInt() + 1;
new_connectors[std::string("Conn")+counter.asString()] = tmp;
if (Util::Procs::isActive(std::string("Conn")+counter.asString())){
(*ait)["online"] = 1;
}else{
(*ait)["online"] = 0;
}
}
//shut down deleted/changed connectors
for (iter = current_connectors.begin(); iter != current_connectors.end(); iter++){
if (new_connectors.count(iter->first) != 1 || new_connectors[iter->first] != iter->second){
Log("CONF", "Stopping connector: " + iter->second);
Util::Procs::Stop(iter->first);
}
}
//start up new/changed connectors
for (iter = new_connectors.begin(); iter != new_connectors.end(); iter++){
if (current_connectors.count(iter->first) != 1 || current_connectors[iter->first] != iter->second || !Util::Procs::isActive(iter->first)){
Log("CONF", "Starting connector: " + iter->second);
Util::Procs::Start(iter->first, Util::getMyPath() + iter->second);
}
}
if (haveHTTPgeneric && !haveHTTPspecific){
Log("WARN", "HTTP Connector is enabled but no HTTP-based protocols are active!");
}
if (!haveHTTPgeneric && haveHTTPspecific){
Log("WARN", "HTTP-based protocols will not work without the generic HTTP connector!");
}
//store new state
current_connectors = new_connectors;
}
}

View file

@ -0,0 +1,5 @@
namespace Controller{
void CheckProtocols(JSON::Value & p);
}

View file

@ -0,0 +1,25 @@
#include <iostream>
#include <mist/timing.h>
#include "controller_storage.h"
namespace Controller{
JSON::Value Storage; ///< Global storage of data.
/// Store and print a log message.
void Log(std::string kind, std::string message){
//if last log message equals this one, do not log.
if (Storage["log"].size() > 0){
JSON::ArrIter it = Storage["log"].ArrEnd() - 1;
if ((*it)[2] == message){return;}
}
JSON::Value m;
m.append(Util::epoch());
m.append(kind);
m.append(message);
Storage["log"].append(m);
Storage["log"].shrink(100);//limit to 100 log messages
std::cout << "[" << kind << "] " << message << std::endl;
}
}

11
src/controller_storage.h Normal file
View file

@ -0,0 +1,11 @@
#include <string>
#include <mist/json.h>
namespace Controller{
extern JSON::Value Storage; ///< Global storage of data.
/// Store and print a log message.
void Log(std::string kind, std::string message);
}