diff --git a/Connector_HTTP/main.cpp b/Connector_HTTP/main.cpp index fe9d364a..1cfe5ab5 100644 --- a/Connector_HTTP/main.cpp +++ b/Connector_HTTP/main.cpp @@ -1,26 +1,109 @@ +//debugging level 0 = nothing +//debugging level 1 = critical errors +//debugging level 2 = errors +//debugging level 3 = status information +//debugging level 4 = extremely verbose status information +#define DEBUG 3 + #include -#include "../sockets/SocketW.h" -#include -#include #include #include +#include #include -#include +#include +#include +#include +#include -int main() { - SWUnixSocket mySocket; - mySocket.connect("/tmp/shared_socket"); - char buffer[500000]; - int msg; - std::string input; - // do something with mySocket... - while( std::cin >> input && input != "") {} - std::cout << "HTTP/1.1 200 OK\nConnection: close\nContent-Type: video/x-flv\n\n"; - while(std::cout.good()) { - msg = mySocket.recv(&buffer[0],10000); - std::cout.write(buffer,msg); +#define DEFAULT_PORT 80 +#include "../util/server_setup.cpp" +#include "../util/http_parser.cpp" + +int mainHandler(int CONN_fd){ + bool ready4data = false;//set to true when streaming starts + bool inited = false; + int ss; + char streamname[200]; + FLV_Pack * tag = 0; + HTTPReader HTTP_R; + + int retval; + int poller = epoll_create(1); + int sspoller = epoll_create(1); + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = CONN_fd; + epoll_ctl(poller, EPOLL_CTL_ADD, CONN_fd, &ev); + struct epoll_event events[1]; + + while (!socketError && !All_Hell_Broke_Loose){ + //only parse input if available or not yet init'ed + retval = epoll_wait(poller, events, 1, 1); + if ((retval > 0) || !ready4data){ + if (HTTP_R.ReadSocket(CONN_fd)){ + //ERIK: we hebben nu een hele HTTP request geparsed - verwerken mag hier, door aanroepen naar + //ERIK: bijvoorbeeld HTTP_R.GetHeader("headernaam") (voor headers) of HTTP_R.GetVar("varnaam") (voor GET/POST vars) + //ERIK: of HTTP_R.method of HTTP_R.url of HTTP_R.protocol.... + //ERIK: zie ook ../util/http_parser.cpp - de class definitie bovenaan zou genoeg moeten zijn voor je + HTTP_R.Clean(); //maak schoon na verwerken voor eventuele volgende requests... + } + } + if (ready4data){ + if (!inited){ + //we are ready, connect the socket! + ss = DDV_OpenUnix(streamname); + if (ss <= 0){ + #if DEBUG >= 1 + fprintf(stderr, "Could not connect to server!\n"); + #endif + socketError = 1; + break; + } + ev.events = EPOLLIN; + ev.data.fd = ss; + epoll_ctl(sspoller, EPOLL_CTL_ADD, ss, &ev); + #if DEBUG >= 3 + fprintf(stderr, "Everything connected, starting to send video data...\n"); + #endif + inited = true; + } + + retval = epoll_wait(sspoller, events, 1, 1); + switch (DDV_ready(ss)){ + case 0: + socketError = true; + #if DEBUG >= 1 + fprintf(stderr, "Source socket is disconnected.\n"); + #endif + break; + case -1: break;//not ready yet + default: + if (FLV_GetPacket(tag, ss)){//able to read a full packet? + //ERIK: "tag" bevat nu een FLV tag (video, audio, of metadata), de header hebben we al weggelezen, np. + //ERIK: Dit is het punt waarop je eventueel data mag/kan gaan sturen en/of parsen. Leef je uit. + //ERIK: je kan een HTTPReader aanmaken en gebruiken om je HTTP request op te bouwen (via SetBody, SetHeader, etc) + //ERIK: en dan met de .BuildResponse("200", "OK"); call een std::string met de hele response maken, klaar voor versturen + //ERIK: Note: hergebruik echter NIET de HTTP_R die ik al heb gemaakt hierboven, want er kunnen meerdere requests binnenkomen! + } + break; + } + } } - // disconnect - mySocket.disconnect(); + close(CONN_fd); + if (inited) close(ss); + #if DEBUG >= 1 + if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");} + fprintf(stderr, "User %i disconnected.\n", CONN_fd); + if (inited){ + fprintf(stderr, "Status was: inited\n"); + }else{ + if (ready4data){ + fprintf(stderr, "Status was: ready4data\n"); + }else{ + fprintf(stderr, "Status was: connected\n"); + } + } + #endif return 0; } + diff --git a/Connector_RTMP/parsechunks.cpp b/Connector_RTMP/parsechunks.cpp index 0640a58a..6220388a 100644 --- a/Connector_RTMP/parsechunks.cpp +++ b/Connector_RTMP/parsechunks.cpp @@ -45,7 +45,6 @@ void parseChunk(){ //6 = pingrequest, 4 bytes data //7 = pingresponse, 4 bytes data //we don't need to process this - SendCTL(3, rec_cnt);//send ack (msg 3) } break; case 5://window size of other end #if DEBUG >= 4 diff --git a/util/http_parser.cpp b/util/http_parser.cpp new file mode 100644 index 00000000..b6bf2beb --- /dev/null +++ b/util/http_parser.cpp @@ -0,0 +1,173 @@ +#include +#include + +class HTTPReader{ + public: + HTTPReader(); + bool ReadSocket(int CONN_fd); + std::string GetHeader(std::string i); + std::string GetVar(std::string i); + void SetHeader(std::string i, std::string v); + void SetHeader(std::string i, int v); + void SetVar(std::string i, std::string v); + void SetBody(std::string s); + void SetBody(char * buffer, int len); + std::string BuildRequest(); + std::string BuildResponse(std::string code, std::string message); + void Clean(); + std::string method; + std::string url; + std::string protocol; + unsigned int length; + private: + bool seenHeaders; + bool seenReq; + bool parse(); + std::string HTTPbuffer; + std::map headers; + std::map vars; + void Trim(std::string & s); +};//HTTPReader + +HTTPReader::HTTPReader(){Clean();} +void HTTPReader::Clean(){ + seenHeaders = false; + seenReq = false; + method = "GET"; + url = "/"; + protocol = "HTTP/1.0"; + length = 0; + HTTPbuffer = ""; + headers.erase(headers.begin(), headers.end()); + vars.erase(vars.begin(), vars.end()); +} + +std::string HTTPReader::BuildRequest(){ + std::map::iterator it; + std::string tmp = method+" "+url+" "+protocol+"\n"; + for (it=headers.begin(); it != headers.end(); it++){ + tmp += (*it).first + ": " + (*it).second + "\n"; + } + tmp += "\n"; + tmp += HTTPbuffer; + return tmp; +} + +std::string HTTPReader::BuildResponse(std::string code, std::string message){ + std::map::iterator it; + std::string tmp = protocol+" "+code+" "+message+"\n"; + for (it=headers.begin(); it != headers.end(); it++){ + tmp += (*it).first + ": " + (*it).second + "\n"; + } + tmp += "\n"; + tmp += HTTPbuffer; + return tmp; +} + +void HTTPReader::Trim(std::string & s){ + size_t startpos = s.find_first_not_of(" \t"); + size_t endpos = s.find_last_not_of(" \t"); + if ((std::string::npos == startpos) || (std::string::npos == endpos)){s = "";}else{s = s.substr(startpos, endpos-startpos+1);} +} + +void HTTPReader::SetBody(std::string s){ + HTTPbuffer = s; + SetHeader("Content-Length", s.length()); +} + +void HTTPReader::SetBody(char * buffer, int len){ + HTTPbuffer = ""; + HTTPbuffer.append(buffer, len); + SetHeader("Content-Length", len); +} + + +std::string HTTPReader::GetHeader(std::string i){return headers[i];} +std::string HTTPReader::GetVar(std::string i){return vars[i];} + +void HTTPReader::SetHeader(std::string i, std::string v){ + Trim(i); + Trim(v); + headers[i] = v; +} + +void HTTPReader::SetHeader(std::string i, int v){ + Trim(i); + char val[128]; + sprintf(val, "%i", v); + headers[i] = val; +} + +void HTTPReader::SetVar(std::string i, std::string v){ + Trim(i); + Trim(v); + vars[i] = v; +} + +bool HTTPReader::ReadSocket(int CONN_fd){ + //returned true als hele http packet gelezen is + int r = 0; + int b = 0; + char buffer[500]; + while (true){ + r = DDV_ready(CONN_fd); + if (r < 1){ + if (r == 0){ + socketError = true; + #if DEBUG >= 1 + fprintf(stderr, "User socket is disconnected.\n"); + #endif + } + return parse(); + } + b = DDV_iread(buffer, 500, CONN_fd); + HTTPbuffer.append(buffer, b); + } + return false; +}//HTTPReader::ReadSocket + + +bool HTTPReader::parse(){ + size_t f; + std::string tmpA, tmpB, tmpC; + while (HTTPbuffer != ""){ + if (!seenHeaders){ + f = HTTPbuffer.find('\n'); + if (f == std::string::npos) return false; + tmpA = HTTPbuffer.substr(0, f); + HTTPbuffer.erase(0, f+1); + if (!seenReq){ + seenReq = true; + f = tmpA.find(' '); + if (f != std::string::npos){method = tmpA.substr(0, f); tmpA.erase(0, f+1);} + f = tmpA.find(' '); + if (f != std::string::npos){url = tmpA.substr(0, f); tmpA.erase(0, f+1);} + f = tmpA.find(' '); + if (f != std::string::npos){protocol = tmpA.substr(0, f); tmpA.erase(0, f+1);} + //TODO: GET variable parsing + }else{ + if (tmpA[0] == '\n'){ + seenHeaders = true; + if (GetHeader("Content-Length") != ""){length = atoi(GetHeader("Content-Length").c_str());} + }else{ + f = tmpA.find(':'); + if (f == std::string::npos) continue; + tmpB = tmpA.substr(0, f); + tmpC = tmpA.substr(f+1); + SetHeader(tmpB, tmpC); + } + } + } + if (seenHeaders){ + if (length > 0){ + //TODO: POST variable parsing + return (HTTPbuffer.length() >= length); + }else{ + return true; + } + } + } + return false; //we should never get here... +}//HTTPReader::parse + + diff --git a/util/server_setup.cpp b/util/server_setup.cpp index d6be7c15..fbd93aa0 100644 --- a/util/server_setup.cpp +++ b/util/server_setup.cpp @@ -63,12 +63,12 @@ int main(int argc, char ** argv){ if (daemon_mode){ daemon(1, 0); #if DEBUG >= 3 - fprintf(stderr, "Going into background mode..."); + fprintf(stderr, "Going into background mode...\n"); #endif } }else{ #if DEBUG >= 1 - fprintf(stderr, "Error: could not make listening socket"); + fprintf(stderr, "Error: could not make listening socket\n"); #endif return 1; }