bool HTTP4CLIProtocol::SignalInputData(IOBuffer &buffer) { //1. Get the HTTP protocol. We are sure is a PT_INBOUND_HTTP //because we return true inside AllowFarProtocol only when type == PT_INBOUND_HTTP InboundHTTPProtocol *pHTTP = (InboundHTTPProtocol *) GetFarProtocol(); //2. Get the request headers Variant headers = pHTTP->GetHeaders(); //3. Populate the input buffer for the next protocol in the stack (PT_INBOUND_JSONCLI) //with the data we just found out inside the headers URI uri; string dummy = "http://localhost" + (string) headers[HTTP_FIRST_LINE][HTTP_URL]; FINEST("dummy: %s",STR(dummy)); if (!URI::FromString(dummy, false, uri)) { FATAL("Invalid request"); return false; } string fullCommand=uri.document; fullCommand+=" "; if(uri.parameters.size()!=0){ fullCommand+=unb64(MAP_VAL(uri.parameters.begin())); } fullCommand+="\n"; _localInputBuffer.ReadFromString(fullCommand); //4. Call the next protocol with the new buffer return GetNearProtocol()->SignalInputData(_localInputBuffer); }
bool InboundHTTP4RTMP::SignalInputData(IOBuffer &buffer) { //1. Get the HTTP far protool and test to see if it has ContentLength InboundHTTPProtocol *pHTTP = (InboundHTTPProtocol *) _pFarProtocol; if (pHTTP == NULL || pHTTP->GetContentLength() == 0) { FATAL("Invalid HTTP request"); return false; } //2. Test it and see if all the data was transfered if (!pHTTP->TransferCompleted()) { return true; } //3. Get the HTTP request Variant request = pHTTP->GetHeaders(); //4. Is this a keep-alive? pHTTP->SetDisconnectAfterTransfer( request[HTTP_HEADERS][HTTP_HEADERS_CONNECTION] != HTTP_HEADERS_CONNECTION_KEEP_ALIVE); DeleteNearProtocol(false); //4. Get the URL string url = request[HTTP_FIRST_LINE][HTTP_URL]; //5. split it in meaningful parts vector<string> parts; split(url, "/", parts); if (parts.size() < 2) { FATAL("Invalid request:\n%s", STR(request.ToString())); return false; } //7. Do the dammage bool result; if (parts[1] == "fcs") { result = ProcessFcs(parts); buffer.Ignore(pHTTP->GetContentLength()); } else if (parts[1] == "open") { result = ProcessOpen(parts); buffer.Ignore(pHTTP->GetContentLength()); } else if (parts[1] == "idle") { result = ProcessIdle(parts); buffer.Ignore(pHTTP->GetContentLength()); } else if (parts[1] == "send") { if (GETAVAILABLEBYTESCOUNT(buffer) < 1) return false; _inputBuffer.ReadFromBuffer(GETIBPOINTER(buffer), pHTTP->GetContentLength()); buffer.Ignore(pHTTP->GetContentLength()); result = ProcessSend(parts); } else { FATAL("Invalid command: %s", STR(parts[1])); result = false; } //8. Cleanup if (!result) { DeleteNearProtocol(true); EnqueueForDelete(); } //9. Done return result; }
bool EchoProtocol::SignalInputData(IOBuffer &buffer) { //PREAMBLE //First, check the transport type. If it is a //http transport, wait for it to finish the request //before doing stuff with it. This is not mandatory. //We can start consume the buffer right away, but since //we do a echo protocol, let's keep the things simple //If the transport is direct TCP, we will echo back only after //getting a new line character. //I will try to keep the things extremely simple in this function //sacrificing "user input sanitize" for simplicity. Anyway, I think //we all know how an echo protocol should behave... //1. Check and see if the protocol is HTTP or not if (GetFarProtocol()->GetType() == PT_INBOUND_HTTP) { //2. This has HTTP protocol as carrier. Get it and //wait for it to complete InboundHTTPProtocol *pHTTP = (InboundHTTPProtocol *) GetFarProtocol(); if (!pHTTP->TransferCompleted()) { FINEST("HTTP transfer not completed yet"); return true; } //3. Ok, it is complete. Get the data and put it inside the output buffer //Actually, we are going to add the string "ECHO " first, and after that //the actual data. Just for fun... _outputBuffer.ReadFromString("ECHO "); _outputBuffer.ReadFromBuffer( GETIBPOINTER(buffer), GETAVAILABLEBYTESCOUNT(buffer)); //3.1. Let's also dump the complete HTTP request. You might want to pick //up a thing or 2 from it. Just for fun... FINEST("HTTP request:\n%s", STR(pHTTP->GetHeaders().ToString())); //4. Ignore the input buffer now. buffer.IgnoreAll(); //5. Add some fancy mime type and some custom HTTP headers... Just for fun... pHTTP->SetOutboundHeader(HTTP_HEADERS_CONTENT_TYPE, "text/plain"); pHTTP->SetOutboundHeader("My-fancy-http-header", "aloha from C++ RTMP Server"); //6. We are done. Enqueue the stack for outbound I/O return EnqueueForOutbound(); } else { //7. Get the data inside a string string data = string((const char *) GETIBPOINTER(buffer), GETAVAILABLEBYTESCOUNT(buffer)); //8. extremely minimal and dangerous test to see if we have a new-line, //but for the sake of simplicity, I'm just going to keep it like that if (data.length() == 0 || data[data.length() - 1] != '\n') { FINEST("Not enough data. So far I have %s. Wait for more...", STR(data)); return true; } //9. Ok, it is complete. Get the data and put it inside the output buffer //Actually, we are going to add the string "ECHO " first, and after that //the actual data. Just for fun... _outputBuffer.ReadFromString("ECHO "); _outputBuffer.ReadFromBuffer( GETIBPOINTER(buffer), GETAVAILABLEBYTESCOUNT(buffer)); //10. Ignore the input buffer now. buffer.IgnoreAll(); //11. for demonstration purposes, whenever I get the string "testHttpRequest" //I'm just going to do a request to "http://www.rtmpd.com" and print out //the page on console. This should illustrate how to use the outbound HTTP protocol HTTPDownloadProtocol::DoSimpleGETRequestWithSomePayload("http://www.rtmpd.com/resources","Some data.... Hello World!"); //11. We are done. Enqueue the stack for outbound I/O return EnqueueForOutbound(); } }