/*
* 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 */