/* * Copyright (c) 2010, * Gavriloaie Eugen-Andrei (shiretu@gmail.com) * * This file is part of crtmpserver. * crtmpserver is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * crtmpserver is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with crtmpserver. If not, see . */ #ifdef HAS_PROTOCOL_RTMP #include "rtmpappprotocolhandler.h" #include "protocols/rtmp/basertmpprotocol.h" #include "protocols/rtmp/messagefactories/messagefactories.h" #include "application/baseclientapplication.h" #include "streaming/baseinnetstream.h" #include "streaming/streamstypes.h" using namespace app_flvplayback; RTMPAppProtocolHandler::RTMPAppProtocolHandler(Variant &configuration) : BaseRTMPAppProtocolHandler(configuration) { } RTMPAppProtocolHandler::~RTMPAppProtocolHandler() { } bool RTMPAppProtocolHandler::ProcessInvokeGeneric(BaseRTMPProtocol *pFrom, Variant &request) { string functionName = M_INVOKE_FUNCTION(request); if (functionName == "getAvailableFlvs") { return ProcessGetAvailableFlvs(pFrom, request); } else if (functionName == "insertMetadata") { return ProcessInsertMetadata(pFrom, request); } else { return BaseRTMPAppProtocolHandler::ProcessInvokeGeneric(pFrom, request); } } bool RTMPAppProtocolHandler::ProcessGetAvailableFlvs(BaseRTMPProtocol *pFrom, Variant &request) { Variant parameters; parameters.PushToArray(Variant()); parameters.PushToArray(Variant()); vector files; if (!ListFolder(_configuration[CONF_APPLICATION_MEDIAFOLDER], files)) { FATAL("Unable to list folder %s", STR(_configuration[CONF_APPLICATION_MEDIAFOLDER])); return false; } string file, name, extension; FOR_VECTOR_ITERATOR(string, files, i) { file = VECTOR_VAL(i); splitFileName(file, name, extension); extension = lowercase(extension); if (extension != MEDIA_TYPE_FLV && extension != MEDIA_TYPE_MP3 && extension != MEDIA_TYPE_MP4 && extension != MEDIA_TYPE_M4A && extension != MEDIA_TYPE_M4V && extension != MEDIA_TYPE_MOV && extension != MEDIA_TYPE_F4V && extension != MEDIA_TYPE_TS && extension != MEDIA_TYPE_MKV) continue; string flashName = ""; if (extension == MEDIA_TYPE_FLV) { flashName = name; } else if (extension == MEDIA_TYPE_MP3) { flashName = extension + ":" + name; } else { if (extension == MEDIA_TYPE_MP4 || extension == MEDIA_TYPE_M4A || extension == MEDIA_TYPE_M4V || extension == MEDIA_TYPE_MOV || extension == MEDIA_TYPE_F4V) { flashName = MEDIA_TYPE_MP4":" + name + "." + extension; } else { flashName = extension + ":" + name + "." + extension; } } // FINEST("Parsing `%s`", STR(flashName)); // Variant v = GetMetaData(flashName, true); // if (v != V_NULL) parameters[(uint32_t) 1].PushToArray(flashName); } map allInboundStreams = GetApplication()->GetStreamsManager()->FindByType(ST_IN_NET, true); FOR_MAP(allInboundStreams, uint32_t, BaseStream *, i) { parameters[(uint32_t) 1].PushToArray(MAP_VAL(i)->GetName()); } Variant message = GenericMessageFactory::GetInvoke(3, 0, 0, false, 0, "SetAvailableFlvs", parameters); return SendRTMPMessage(pFrom, message); } bool RTMPAppProtocolHandler::ProcessInvokeConnect(BaseRTMPProtocol *pFrom, Variant &request) { //0. Dump the request on console, just to see its structure FINEST("Initial request:\n%s", STR(request.ToString())); //1. Get the connect params from the connect invoke Variant connectParams = M_INVOKE_PARAM(request, 0); //2. This should be a key-value map if (connectParams != V_MAP) { FATAL("Incorrect invoke params:\n%s", STR(request.ToString())); return false; } //3. Let's extract few values. Make sure we extract them using non-case-sensitive keys Variant tcUrl = connectParams.GetValue(RM_INVOKE_PARAMS_CONNECT_TCURL, false); //If you are sure about case-sensitive settings, you can extract it directly like this Variant swfUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_SWFURL]; //Variant tcUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_TCURL]; Variant pageUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_PAGEURL]; //4. Do some validation on them. if (pageUrl != V_STRING) { FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_PAGEURL": %s", STR(request.ToString())); return false; } if (tcUrl != V_STRING) { FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_TCURL":\n%s", STR(request.ToString())); return false; } string rawURI; URI uri; if (!URI::FromString(pageUrl, true, uri)) { FATAL("Unable to parse the uri %s", STR(rawURI)); return false; } // as proto we are going to validate rtmp/rtmpe - media.bfy.ro=86.123.101.7 if (((string) tcUrl) != "rtmp://media.bfy.ro/ameeran") { if (((string) tcUrl) != "rtmpe://media.bfy.ro/ameeran") { FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_TCURL": %s", STR(request.ToString())); return false; } } // we use our static flowplayer which is always on the same address if (((string) swfUrl) != "http://www.a-queens.ro/flowplayer/flowplayer-3.2.5.swf") { FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_SWFURL": %s", STR(request.ToString())); return false; } // ip which resolve our calling webpage(s)/website(s) if (((string) uri.ip) != "86.122.125.158") { FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_PAGEURL": %s", STR(request.ToString())); return false; } //TODO: continue here //5. If everything looks right, continue default processing :) return BaseRTMPAppProtocolHandler::ProcessInvokeConnect(pFrom, request); } bool RTMPAppProtocolHandler::ProcessInsertMetadata(BaseRTMPProtocol *pFrom, Variant &request) { //STREAMING REFACTORING // //FINEST("request:\n%s", STR(request.ToString())); // // //1. Get the stream name // if ((VariantType) M_INVOKE_PARAM(request, 1) != V_STRING) // return true; // string streamName = M_INVOKE_PARAM(request, 1); // // //2. Get the stream // vector streams = FindOSByName(streamName); // BaseInboundStream *pInboundStream = NULL; // // FOR_VECTOR(streams, i) { // if (streams[i]->GetProtocol()->GetId() == pFrom->GetId()) { // pInboundStream = streams[i]->GetInboundStream(); // break; // } // } // if (pInboundStream == NULL) { // FINEST("This stream is not yet bound"); // return true; // } // if (pInboundStream->IsEnqueueForDelete()) { // FINEST("This stream will be deleted soon"); // return true; // } // // //3. Prepare the FlexStreamSend message // Variant params; // params.PushToArray(M_INVOKE_PARAM(request, 2)); // return pInboundStream->SendStreamMessage("onMetaData", params); NYIR; } #endif /* HAS_PROTOCOL_RTMP */