madhawa

rtmpappprotocolhandler.cpp

Apr 25th, 2011
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.47 KB | None | 0 0
  1. /*
  2.  *  Copyright (c) 2010,
  3.  *  Gavriloaie Eugen-Andrei ([email protected])
  4.  *
  5.  *  This file is part of crtmpserver.
  6.  *  crtmpserver is free software: you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation, either version 3 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  crtmpserver is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with crtmpserver.  If not, see <http://www.gnu.org/licenses/>.
  18.  */
  19.  
  20.  
  21. #ifdef HAS_PROTOCOL_RTMP
  22. #include "rtmpappprotocolhandler.h"
  23. #include "protocols/rtmp/basertmpprotocol.h"
  24. #include "protocols/rtmp/messagefactories/messagefactories.h"
  25. #include "application/baseclientapplication.h"
  26. #include "streaming/baseinnetstream.h"
  27. #include "streaming/streamstypes.h"
  28. using namespace app_flvplayback;
  29.  
  30. RTMPAppProtocolHandler::RTMPAppProtocolHandler(Variant &configuration)
  31. : BaseRTMPAppProtocolHandler(configuration) {
  32.  
  33. }
  34.  
  35. RTMPAppProtocolHandler::~RTMPAppProtocolHandler() {
  36. }
  37.  
  38. bool RTMPAppProtocolHandler::ProcessInvokeGeneric(BaseRTMPProtocol *pFrom,
  39.                 Variant &request) {
  40.  
  41.         string functionName = M_INVOKE_FUNCTION(request);
  42.         if (functionName == "getAvailableFlvs") {
  43.                 return ProcessGetAvailableFlvs(pFrom, request);
  44.         } else if (functionName == "insertMetadata") {
  45.                 return ProcessInsertMetadata(pFrom, request);
  46.         } else {
  47.                 return BaseRTMPAppProtocolHandler::ProcessInvokeGeneric(pFrom, request);
  48.         }
  49. }
  50.  
  51. // adding functions for filter validations
  52. bool RTMPAppProtocolHandler::ProcessInvokeConnect(BaseRTMPProtocol *pFrom, Variant &request) {
  53.         //1. Get the request params
  54.         if (M_INVOKE_PARAMS(request).MapSize() < 1) {
  55.                 FATAL("Invalid request");
  56.                 return false;
  57.         }
  58.         Variant connectParameters = M_INVOKE_PARAM(request, 0);
  59.  
  60.         if (_authMethod != "") {
  61.                 //we have adobe auth enabled
  62.                 string flashVer = connectParameters[RM_INVOKE_PARAMS_CONNECT_FLASHVER];
  63.                 if (!_configuration[CONF_APPLICATION_AUTH][CONF_APPLICATION_AUTH_ENCODER_AGENTS].HasKey(flashVer)) {
  64.                         //this connection will not be authenticated, so we will try to validate the URI's
  65.                         //if (!ValidateRequest(request)) {
  66.             //For URI Token-Key Auth added by Madhawa Jayanath
  67.             if (!ValidateRequest(pFrom, request)) {
  68.                                 FATAL("Invalid connect request");
  69.                                 return false;
  70.                         }
  71.                 }
  72.         } else {
  73.                 //we don't have adobe auth enabled at all. We will try to validate the URI's
  74.                 //if (!ValidateRequest(request)) {
  75.         //For URI Token-Key Auth added by Madhawa Jayanath
  76.         if (!ValidateRequest(pFrom, request)) {
  77.                         FATAL("Invalid connect request");
  78.                         return false;
  79.                 }
  80.         }
  81.  
  82.  
  83.         return BaseRTMPAppProtocolHandler::ProcessInvokeConnect(pFrom, request);
  84. }
  85.  
  86. //bool RTMPAppProtocolHandler::ValidateRequest(Variant &request) {
  87. //For URI Token-Key Auth added by Madhawa Jayanath
  88. bool RTMPAppProtocolHandler::ValidateRequest(BaseRTMPProtocol *pFrom, Variant &request) {
  89.         //TODO: Validate the various URI's inside the request here
  90.         //0. Dump the request on console, just to see its structure
  91.        FINEST("Initial request:\n%s", STR(request.ToString()));
  92.  
  93.        //1. Get the connect params from the connect invoke
  94.        Variant connectParams = M_INVOKE_PARAM(request, 0);
  95.  
  96.         //For URI Token-Key Auth added by Madhawa Jayanath
  97.         Variant mySecondparam=M_INVOKE_PARAM(request,1);
  98.         if (_configuration["sharedKey"] != "") {
  99.             string sharedkey = _configuration["sharedKey"];
  100.             IOHandler *pHandler=pFrom->GetIOHandler();
  101.             if(pHandler==NULL)
  102.                 return false;
  103.             if(pHandler->GetType()!= IOHT_TCP_CARRIER)
  104.                 return false;
  105.             string peerAddress=((TCPCarrier *)pHandler)->GetFarEndpointAddressIp();
  106.             uint16_t peerPort=((TCPCarrier *)pHandler)->GetFarEndpointPort();
  107.        
  108.             string md5Code = md5(peerAddress+sharedkey, true);
  109.             if(mySecondparam !=V_STRING) {
  110.                 FATAL("Invalid connect request");
  111.                 return false;
  112.             }
  113.             string myTokenKey=(string)mySecondparam;
  114.             if(myTokenKey !=md5Code) {
  115.                 FATAL("Invalid Token-Key");
  116.                 return false;
  117.             }
  118.             INFO("Requested URL Token-Key is \'%s\'", STR((string) myTokenKey));
  119.             INFO("IP + Shared Key is \'%s\'", STR((string) peerAddress+sharedkey));
  120.             INFO("Calculated URL Token-Key is \'%s\'", STR((string) md5Code));
  121.             INFO("Peer IP is \'%s\'", STR((string) peerAddress));
  122.             INFO("Peer Port is \'%i\'", peerPort);
  123.         }
  124.        
  125.        //2. This should be a key-value map
  126.        if (connectParams != V_MAP) {
  127.                FATAL("Incorrect invoke params:\n%s", STR(request.ToString()));
  128.                return false;
  129.        }
  130.  
  131.         //3. Let's extract few values. Make sure we extract them using non-case-sensitive keys
  132.         Variant tcUrl = connectParams.GetValue(RM_INVOKE_PARAMS_CONNECT_TCURL, false);
  133.  
  134.         //If you are sure about case-sensitive settings, you can extract it directly like this
  135.         Variant swfUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_SWFURL];
  136.         //Variant tcUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_TCURL];
  137.         Variant pageUrl = connectParams[RM_INVOKE_PARAMS_CONNECT_PAGEURL];
  138.  
  139.  
  140.         //4. Do some validation on them.
  141.  
  142.         if (pageUrl != V_STRING) {
  143.                FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_PAGEURL": %s", STR(request.ToString()));
  144.                 return false;
  145.         }
  146.  
  147.         if (tcUrl != V_STRING) {
  148.                 FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_TCURL":\n%s", STR(request.ToString()));
  149.                 return false;
  150.         }
  151.  
  152.         string rawURI;
  153.         URI uri;
  154.         if (!URI::FromString(pageUrl, true, uri)) {
  155.                 FATAL("Unable to parse the uri %s", STR(rawURI));
  156.                 return false;
  157.         }
  158.  
  159.         // as proto we are going to validate rtmp/rtmpe
  160.         // added if/elseif/else and INFO like Andriy suggested
  161.          if (((string) tcUrl) != "rtmp://media.bfy.ro/livestream") {
  162.              INFO("Connect schema is \'%s\'", STR((string) tcUrl));
  163.          } else if (((string) tcUrl) != "rtmpe://media.bfy.ro/livestream") {
  164.             INFO("Connect schema is \'%s\'", STR((string) tcUrl));
  165.          }
  166.          else {
  167.                 FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_TCURL": %s", STR(request.ToString()));
  168.                 return false;
  169.          }
  170.         // we use our static flowplayer which is always on the same address
  171.         // added if/elseif/else and INFO like Andriy suggested
  172.          if (((string) swfUrl) != "http://www.a-queens.ro/flowplayer/flowplayer-3.2.5.swf") {
  173.              INFO("Flash player address is \'%s\'", STR((string) swfUrl));
  174.          } else if (((string) swfUrl) != "http://www.a-queens.ro/player.swf") {
  175.              INFO("Flash player address is \'%s\'", STR((string) swfUrl));
  176.          }
  177.          else {
  178.               FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_SWFURL": %s", STR(request.ToString()));
  179.               return false;
  180.          }
  181.  
  182.         // ip which resolve our calling webpage(s)/website(s)
  183.         // added if/elseif/else and INFO like Andriy suggested
  184.         if (((string) uri.ip) == "86.122.125.158") {
  185.                  INFO("Stream calling webpage is \'%s\'", STR((string) pageUrl));
  186.                  INFO("stream Calling webpage IP is \'%s\'", STR((string) uri.ip));
  187.         }
  188.         else {
  189.              FATAL("Incorrect "RM_INVOKE_PARAMS_CONNECT_PAGEURL": %s", STR(request.ToString()));
  190.              return false;
  191.         }
  192.  
  193.         return true;
  194.         //NYIR;
  195. }
  196.  
  197. bool RTMPAppProtocolHandler::ProcessGetAvailableFlvs(BaseRTMPProtocol *pFrom, Variant &request) {
  198.         Variant parameters;
  199.         parameters.PushToArray(Variant());
  200.         parameters.PushToArray(Variant());
  201.  
  202.         vector<string> files;
  203.         if (!ListFolder(_configuration[CONF_APPLICATION_MEDIAFOLDER], files)) {
  204.                 FATAL("Unable to list folder %s",
  205.                                 STR(_configuration[CONF_APPLICATION_MEDIAFOLDER]));
  206.                 return false;
  207.         }
  208.  
  209.         string file, name, extension;
  210.  
  211.         FOR_VECTOR_ITERATOR(string, files, i) {
  212.                 file = VECTOR_VAL(i);
  213.  
  214.                 splitFileName(file, name, extension);
  215.                 extension = lowercase(extension);
  216.  
  217.                 if (extension != MEDIA_TYPE_FLV
  218.                                 && extension != MEDIA_TYPE_MP3
  219.                                 && extension != MEDIA_TYPE_MP4
  220.                                 && extension != MEDIA_TYPE_M4A
  221.                                 && extension != MEDIA_TYPE_M4V
  222.                                 && extension != MEDIA_TYPE_MOV
  223.                                 && extension != MEDIA_TYPE_F4V
  224.                                 && extension != MEDIA_TYPE_TS
  225.                                 && extension != MEDIA_TYPE_MKV)
  226.                         continue;
  227.                 string flashName = "";
  228.                 if (extension == MEDIA_TYPE_FLV) {
  229.                         flashName = name;
  230.                 } else if (extension == MEDIA_TYPE_MP3) {
  231.                         flashName = extension + ":" + name;
  232.                 } else {
  233.                         if (extension == MEDIA_TYPE_MP4
  234.                                         || extension == MEDIA_TYPE_M4A
  235.                                         || extension == MEDIA_TYPE_M4V
  236.                                         || extension == MEDIA_TYPE_MOV
  237.                                         || extension == MEDIA_TYPE_F4V) {
  238.                                 flashName = MEDIA_TYPE_MP4":" + name + "." + extension;
  239.                         } else {
  240.                                 flashName = extension + ":" + name + "." + extension;
  241.                         }
  242.                 }
  243.  
  244.  
  245.                 //        FINEST("Parsing `%s`", STR(flashName));
  246.                 //        Variant v = GetMetaData(flashName, true);
  247.                 //        if (v != V_NULL)
  248.                 parameters[(uint32_t) 1].PushToArray(flashName);
  249.         }
  250.  
  251.         map<uint32_t, BaseStream *> allInboundStreams =
  252.                         GetApplication()->GetStreamsManager()->FindByType(ST_IN_NET, true);
  253.  
  254.         FOR_MAP(allInboundStreams, uint32_t, BaseStream *, i) {
  255.                 parameters[(uint32_t) 1].PushToArray(MAP_VAL(i)->GetName());
  256.         }
  257.  
  258.         Variant message = GenericMessageFactory::GetInvoke(3, 0, 0, false, 0,
  259.                         "SetAvailableFlvs", parameters);
  260.  
  261.         return SendRTMPMessage(pFrom, message);
  262. }
  263.  
  264. bool RTMPAppProtocolHandler::ProcessInsertMetadata(BaseRTMPProtocol *pFrom, Variant &request) {
  265.         //STREAMING REFACTORING
  266.         //    //FINEST("request:\n%s", STR(request.ToString()));
  267.         //
  268.         //    //1. Get the stream name
  269.         //    if ((VariantType) M_INVOKE_PARAM(request, 1) != V_STRING)
  270.         //        return true;
  271.         //    string streamName = M_INVOKE_PARAM(request, 1);
  272.         //
  273.         //    //2. Get the stream
  274.         //    vector<BaseOutboundStream *> streams = FindOSByName(streamName);
  275.         //    BaseInboundStream *pInboundStream = NULL;
  276.         //
  277.         //    FOR_VECTOR(streams, i) {
  278.         //        if (streams[i]->GetProtocol()->GetId() == pFrom->GetId()) {
  279.         //            pInboundStream = streams[i]->GetInboundStream();
  280.         //            break;
  281.         //        }
  282.         //    }
  283.         //    if (pInboundStream == NULL) {
  284.         //        FINEST("This stream is not yet bound");
  285.         //        return true;
  286.         //    }
  287.         //    if (pInboundStream->IsEnqueueForDelete()) {
  288.         //        FINEST("This stream will be deleted soon");
  289.         //        return true;
  290.         //    }
  291.         //
  292.         //    //3. Prepare the FlexStreamSend message
  293.         //    Variant params;
  294.         //    params.PushToArray(M_INVOKE_PARAM(request, 2));
  295.         //    return pInboundStream->SendStreamMessage("onMetaData", params);
  296.         NYIR;
  297. }
  298. #endif /* HAS_PROTOCOL_RTMP */
Advertisement
Add Comment
Please, Sign In to add comment