HOW TO Developing an Authorization plug-in
#if defined (_win32)
#pragma warning(disable : 4996)
bool winapi dllmain(
hinstance hinstdll, // handle dll module
dword fdwreason, // reason calling function
lpvoid lpreserved ) // reserved
{
return true;
}
#endif
how create here
/*----------------------------------------------------------------------------+
| ___ _ _ |
| / | | | | | |
| / /| | __| | ___ | |__ ___ |
| / /_| |/ _ |/ _ \| _ \ / _ \ |
| / ___ | (_| | (_) | |_) | __/ |
| /_/ |_|\__,_|\___/|____/ \___| |
| |
| |
| adobe confidential |
| __________________ |
| |
| copyright (c) 2003 - 2010, adobe systems incorporated. |
| rights reserved. |
| |
| notice: information contained herein is, , remains property |
| of adobe systems incorporated , suppliers, if any. intellectual |
| , technical concepts contained herein proprietary adobe systems |
| incorporated , suppliers , may covered u.s. , foreign |
| patents, patents in process, , protected trade secret or |
| copyright law. dissemination of information or reproduction of this |
| material strictly forbidden unless prior written permission is |
| obtained adobe systems incorporated. |
| |
| adobe systems incorporated 415.832.2000 |
| 601 townsend street 415.832.2020 fax |
| san francisco, ca 94103 |
| |
+----------------------------------------------------------------------------*/
#include "stdafx.h"
#include "fmsauthadaptor.h"
#include "fmsauthactions.h"
#include "fmsmedia.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include "hash.h"
#include <sstream>
#if defined (_win32)
#pragma warning(disable : 4996)
bool winapi dllmain(
hinstance hinstdll, // handle dll module
dword fdwreason, // reason calling function
lpvoid lpreserved ) // reserved
{
return true;
}
#endif
// flag process swf verification in auth sample. real swf file
// must targeted in swfverification code below example work.
static const bool kauthorizeswfverification = false;
class fmsauthadaptor : public ifmsauthadaptor
{
public:
fmsauthadaptor(ifmsauthservercontext2* pfmsauthservercontext)
: m_pfmsauthservercontext(pfmsauthservercontext) {}
virtual ~fmsauthadaptor() {}
void authorize(ifmsauthevent* paev);
void notify(ifmsauthevent* paev);
void getevents(i32 aevbitauth[], i32 aevbitnotf[], unsigned int count);
private:
bool getstats(i64 clientstatshandle, fmsclientstats& basestats);
void processstats(ifmsauthevent* paev);
ifmsauthservercontext2* m_pfmsauthservercontext;
};
//
// utils
//
// note: not delete return value. return value buffer
// allocated in fms memory space, , fms manage memory.
static char* getstringfield(const ifmsauthevent* pev, ifmsauthevent::field prop)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.kstring)
{
return reinterpret_cast<char*>(field.str);
}
return 0;
}
// note: not delete return value. return value buffer
// allocated in fms memory space, , fms manage memory.
static u8* getbufferfield(const ifmsauthevent* pev, ifmsauthevent::field prop)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.kbuffer)
{
return field.buf;
}
return 0;
}
static bool geti8field(const ifmsauthevent* pev, ifmsauthevent::field prop, i8& ivalue)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.ki8)
{
ivalue = field.i8;
return true;
}
return false;
}
static bool geti32field(const ifmsauthevent* pev, ifmsauthevent::field prop, i32& ivalue)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.ki32)
{
ivalue = field.i32;
return true;
}
return false;
}
static bool geti64field(const ifmsauthevent* pev, ifmsauthevent::field prop, i64& ivalue)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.ki64)
{
ivalue = field.i64;
return true;
}
return false;
}
static bool getfloatfield(const ifmsauthevent* pev, ifmsauthevent::field prop, float& fvalue)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.kfloat)
{
fvalue = field.f;
return true;
}
return false;
}
static bool getu16field(const ifmsauthevent* pev, ifmsauthevent::field prop, u16& ivalue)
{
fmsvariant field;
if (pev->getfield(prop, field) == ifmsauthevent::s_success && field.type == field.ku16)
{
ivalue = field.u16;
return true;
}
return false;
}
static bool setstringfield(ifmsauthevent* pev, ifmsauthevent::field prop, char* pvalue)
{
fmsvariant field;
field.setstring(reinterpret_cast<i8*>(pvalue));
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool seti8field(ifmsauthevent* pev, ifmsauthevent::field prop, i8 ivalue)
{
fmsvariant field;
field.seti8(ivalue);
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool setu8field(ifmsauthevent* pev, ifmsauthevent::field prop, u8 ivalue)
{
fmsvariant field;
field.setu8(ivalue);
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool seti32field(ifmsauthevent* pev, ifmsauthevent::field prop, i32 ivalue)
{
fmsvariant field;
field.seti32(ivalue);
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool seti64field(ifmsauthevent* pev, ifmsauthevent::field prop, i64 ivalue)
{
fmsvariant field;
field.seti64(ivalue);
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool setfloatfield(ifmsauthevent* pev, ifmsauthevent::field prop, float fvalue)
{
fmsvariant field;
field.setfloat(fvalue);
return pev->setfield(prop, field) == ifmsauthevent::s_success;
}
static bool isadpcmsupported(int iaudiocodecs)
{
return (iaudiocodecs & support_snd_adpcm) != 0;
}
static bool isvp6supported(int ivideocodecs)
{
int iallvp6 = ( support_vid_vp6alpha | support_vid_vp6 );
return (ivideocodecs & iallvp6) != 0;
}
static bool isservice(int itype)
{
return (itype & type_service) != 0;
}
static bool isamf3(unsigned char uencod)
{
return (uencod == encode_amf3);
}
//
// class process authorization events
//
class myfmsauthorizeevent
{
public:
myfmsauthorizeevent(ifmsauthevent* paev, ifmsauthservercontext2* pfmsauthservercontext)
: m_paev(paev), m_pfmsauthservercontext(pfmsauthservercontext) {}
virtual ~myfmsauthorizeevent() {}
void authorize();
private:
ifmsauthevent* m_paev;
ifmsauthservercontext2* m_pfmsauthservercontext;
};
void myfmsauthorizeevent::authorize()
{
bool bauthorized = true; // default authorization state
switch(m_paev->gettype())
{
case ifmsauthevent::e_connect:
{
// e_connect allows changes following fields:
// f_client_audio_sample_access
// f_client_audio_sample_access_lock
// f_client_read_access
// f_client_read_access_lock
// f_client_video_sample_access
// f_client_video_sample_access_lock
// f_client_write_access_lock
// f_client_write_access
i8 ivalue;
if (geti8field(m_paev, ifmsauthevent::f_client_write_access, ivalue))
{
seti8field(m_paev, ifmsauthevent::f_client_write_access, ivalue);
}
// redirect connection example
char* puri = getstringfield(m_paev, ifmsauthevent::f_client_uri);
if (puri && !strcmp(puri, "rtmp://localhost/streamtest"))
{
setstringfield(m_paev, ifmsauthevent::f_client_redirect_uri,
"rtmp://localhost:1935/streamtest");
bauthorized = false;
}
// set diffserv fields based on client ip
// char* pip = getstringfield(m_paev, ifmsauthevent::f_client_ip);
// if (pip && !strcmp(pip, "192.168.1.1"))
{
// set dscp bits , mask
u8 m_diffservbits = 170;
u8 m_diffservmask = 252;
setu8field(m_paev, ifmsauthevent::f_client_diffserv_bits, m_diffservbits);
setu8field(m_paev, ifmsauthevent::f_client_diffserv_mask, m_diffservmask);
bauthorized = true;
}
}
break;
case ifmsauthevent::e_play:
{
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
if (pstreamname)
{
setstringfield(m_paev, ifmsauthevent::f_stream_name, pstreamname);
}
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
if (pstreamtype)
{
setstringfield(m_paev, ifmsauthevent::f_stream_type, pstreamtype);
}
char* pstreamquery = getstringfield(m_paev, ifmsauthevent::f_stream_query);
if (pstreamquery)
{
setstringfield(m_paev, ifmsauthevent::f_stream_query, pstreamquery);
}
i8 ivalue;
if (geti8field(m_paev, ifmsauthevent::f_stream_reset, ivalue))
{
// if ivalue 1 (true) playlist reset ,
// stream stream in playlist; otherwise
// 0 (false) means stream added existing
// playlist.
seti8field(m_paev, ifmsauthevent::f_stream_reset, ivalue);
}
if (geti8field(m_paev, ifmsauthevent::f_stream_ignore, ivalue))
{
// if ivalue 1 (true) stream timestamps ignored;
// otherwise 0 (false) means timestamps handled.
seti8field(m_paev, ifmsauthevent::f_stream_ignore, ivalue);
}
char* pstreamtransition = getstringfield(m_paev, ifmsauthevent::f_stream_transition);
if (pstreamtransition && strlen(pstreamtransition))
{
// mbr transition example
if (!strcmp(pstreamtransition, "switch") ||
!strcmp(pstreamtransition, "swap"))
{
// old stream's properties
char* poldstreamname = getstringfield(m_paev, ifmsauthevent::f_old_stream_name);
char* poldstreamtype = getstringfield(m_paev, ifmsauthevent::f_old_stream_type);
char* poldstreamquery = getstringfield(m_paev, ifmsauthevent::f_old_stream_query);
// if poldstream empty (optional switch) current stream in play
// want stream transition?
{
// no not allow transition
// bauthorized = false;
// transition turned off , old stream continue playing
// break;
}
// doing nothing execute transition mode is
// or modify transition changing transition properties
// set 1 indicate hooking stream,
// not exist
seti32field(m_paev, ifmsauthevent::f_stream_live_publish_pending, 1);
}
// offset value if transition set offset mode reconnect
if (!strcmp(pstreamtransition, "resume"))
{
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_offset, fvalue))
{
float offset = fvalue; //offset value in seconds
}
}
}
else
{
// regular play waiting approval, may converted
// play2 command changing transition properties
}
}
break;
case ifmsauthevent::e_publish:
{
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
if (pstreamname)
{
setstringfield(m_paev, ifmsauthevent::f_stream_name, pstreamname);
}
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
if (pstreamtype)
{
setstringfield(m_paev, ifmsauthevent::f_stream_type, pstreamtype);
}
i32 ivalue;
if (geti32field(m_paev, ifmsauthevent::f_stream_publish_type, ivalue))
{
// publish types:
// 0 : record
// 1 : append
// 2 : appendwithgap
// -1 : live
seti32field(m_paev, ifmsauthevent::f_stream_publish_type, ivalue);
}
}
break;
case ifmsauthevent::e_filename_transform:
{
i64 ivalue;
if (geti64field(m_paev, ifmsauthevent::f_client_id, ivalue))
{
// fields not eligible modified. return
// value false when trying modify f_client_id.
bool bset = seti64field(m_paev, ifmsauthevent::f_client_id, ivalue);
}
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
if (pstreamname)
{
// fields not eligible modified. return
// value false when trying modify f_stream_name.
bool bset = setstringfield(m_paev, ifmsauthevent::f_stream_name, pstreamname);
}
char* pstreampath = getstringfield(m_paev, ifmsauthevent::f_stream_path);
if (pstreampath)
{
setstringfield(m_paev, ifmsauthevent::f_stream_path, pstreampath);
}
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
if (pstreamtype)
{
setstringfield(m_paev, ifmsauthevent::f_stream_type, pstreamtype);
}
}
break;
case ifmsauthevent::e_pause:
{
bauthorized = false; // block e_pause events.
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_pause_time, fvalue))
{
float fpausetime = fvalue; // in seconds
}
i8 ivalue;
if (geti8field(m_paev, ifmsauthevent::f_stream_pause, ivalue))
{
// 1 (true) means pause
// 0 (false) means unpause
bool boolpause = ivalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_stream_pause_toggle, ivalue))
{
// 1 (true) means pause_toggle
// 0 (false) means no pause_toggle set
bool boolpausetoggle = ivalue != 0;
}
fmsvariant field;
// notify action example: ifmsnofifyaction created notify
// server side action script (ssas) of e_pause event calling
// function name "method" in script. in example two
// variables passed "method" calling addparam(field)
// on action.
if (m_paev->getfield(ifmsauthevent::f_client_id, field) == ifmsauthevent::s_success)
{
i64 clientid = field.i64;
ifmsnotifyaction* paction = m_paev->addnotifyaction("notified adaptor");
paction->setclientid(field);
const char mtd[] = "method";
field.setstring(reinterpret_cast<i8*>(const_cast<char*>(mtd)));
paction->setmethodname(field);
// create , insert u16 "12345" first parameter
field.setu16(12345);
paction->addparam(field);
// create , insert clientid double second parameter
field.setdouble((double)clientid);
paction->addparam(field);
// note: ssas not work i64 or buffer variants
// field.seti64(clientid);
// paction->addparam(field); // incorrect
}
}
break;
case ifmsauthevent::e_seek:
{
bauthorized = false; // block e_seek events
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_seek_position, fvalue))
{
// modification of seek position example:
// fvalue + 3; add 3 seconds initial seek posistion
float fseektime = fvalue; // value in seconds
setfloatfield(m_paev, ifmsauthevent::f_stream_seek_position, fseektime);
}
}
break;
case ifmsauthevent::e_loadsegment:
{
// bauthorized = false; // block e_loadsegment events
// e_loadsegment read event substitutes e_play on
// fms origin servers recorded streams.
i64 ivalue;
if (geti64field(m_paev, ifmsauthevent::f_segment_start, ivalue))
{
i64 istart = ivalue; // in bytes
}
if (geti64field(m_paev, ifmsauthevent::f_segment_end, ivalue))
{
i64 iend = ivalue; // in bytes
}
}
break;
case ifmsauthevent::e_record:
{
// bauthorized = false; // block e_record events
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_record_maxsize, fvalue))
{
float recmaxsize = fvalue; // in kilobytes
setfloatfield(m_paev, ifmsauthevent::f_stream_record_maxsize, recmaxsize);
}
if (getfloatfield(m_paev, ifmsauthevent::f_stream_record_maxduration, fvalue))
{
float recmaxduration = fvalue; // in seconds
setfloatfield(m_paev, ifmsauthevent::f_stream_record_maxduration, recmaxduration);
}
}
break;
case ifmsauthevent::e_swf_verify:
{
// swf verification example:
// kauthorizeswfverification assigned false default. the
// target swf file must updated work.
if(kauthorizeswfverification)
{
i8 swfvversion = 0;
if(geti8field(m_paev, ifmsauthevent::f_client_swfv_version, swfvversion))
{
std::stringstream stream;
stream << "swf verification version " << static_cast<int>(swfvversion);
m_pfmsauthservercontext->log(stream.str().c_str(), ifmsservercontext::kinformation, false);
}
i64 swfvdepth;
if(geti64field(m_paev, ifmsauthevent::f_client_swfv_depth, swfvdepth))
{
i32 swfvttl;
if(geti32field(m_paev, ifmsauthevent::f_client_swfv_ttl, swfvttl))
{
swfvttl /= 2;
seti32field(m_paev, ifmsauthevent::f_client_swfv_ttl, swfvttl);
}
u8 digest[ksha256digestlen];
// target real swf file instead of sample.swf
hashswffileatdepth("c:\\sample.swf", swfvdepth, digest);
fmsvariant field;
field.setbuffer(digest, ksha256digestlen);
m_paev->setfield(ifmsauthevent::f_client_swfv_digest, field);
}
}
}
break;
case ifmsauthevent::e_appstart:
case ifmsauthevent::e_appstop:
case ifmsauthevent::e_disconnect:
case ifmsauthevent::e_stop:
case ifmsauthevent::e_unpublish:
case ifmsauthevent::e_action:
case ifmsauthevent::e_codec_change:
case ifmsauthevent::e_record_stop:
case ifmsauthevent::e_client_pause:
case ifmsauthevent::e_swf_verify_complete:
case ifmsauthevent::e_client_seek:
case ifmsauthevent::e_start_transmit:
case ifmsauthevent::e_stop_transmit:
case ifmsauthevent::e_maxevent:
break;
}
ifmsauthservercontext2::authfailuredesc* desc = null;
if(!bauthorized)
{
desc = new ifmsauthservercontext2::authfailuredesc("blocked auth adaptor",
ifmsauthservercontext2::kdefaultstatus, -1);
}
char buf[1024];
const char* const action = bauthorized ? "approved" : "rejected";
sprintf(buf, "received authorization type=%d id=%p %s\n", m_paev->gettype(),
m_paev, action);
// log configured fms log directory. if third parameter true,
// send log system event log.
m_pfmsauthservercontext->log(buf, ifmsservercontext::kinformation, false);
m_pfmsauthservercontext->onauthorize(m_paev, bauthorized, desc);
delete desc;
}
class myfmsnotifyevent
{
public:
myfmsnotifyevent(ifmsauthevent* paev, ifmsauthservercontext2* pfmsauthservercontext)
: m_paev(paev), m_pfmsauthservercontext(pfmsauthservercontext) {}
virtual ~myfmsnotifyevent() {}
void notify() const;
private:
ifmsauthevent* m_paev;
ifmsauthservercontext2* m_pfmsauthservercontext;
};
void myfmsnotifyevent::notify() const
{
switch(m_paev->gettype())
{
case ifmsauthevent::e_play:
{
char* pappname = getstringfield(m_paev, ifmsauthevent::f_app_name);
char* pappinst = getstringfield(m_paev, ifmsauthevent::f_app_inst);
char* pappuri = getstringfield(m_paev, ifmsauthevent::f_app_uri);
char* pclip = getstringfield(m_paev, ifmsauthevent::f_client_ip);
char* pcluri = getstringfield(m_paev, ifmsauthevent::f_client_uri);
char* pclnewuri = getstringfield(m_paev, ifmsauthevent::f_client_redirect_uri);
char* pclvhost = getstringfield(m_paev, ifmsauthevent::f_client_vhost);
char* pclref = getstringfield(m_paev, ifmsauthevent::f_client_referrer);
char* pclpurl = getstringfield(m_paev, ifmsauthevent::f_client_page_url);
char* pclagent = getstringfield(m_paev, ifmsauthevent::f_client_user_agent);
char* pclraccess = getstringfield(m_paev, ifmsauthevent::f_client_read_access);
char* pclwaccess = getstringfield(m_paev, ifmsauthevent::f_client_write_access);
char* pclaudioaccess = getstringfield(m_paev, ifmsauthevent::f_client_audio_sample_access);
char* pclvideoaccess = getstringfield(m_paev, ifmsauthevent::f_client_video_sample_access);
char* pclproto = getstringfield(m_paev, ifmsauthevent::f_client_proto);
char* pclustem = getstringfield(m_paev, ifmsauthevent::f_client_uri_stem);
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
char* pstreamquery = getstringfield(m_paev, ifmsauthevent::f_stream_query);
char* pstreampath = getstringfield(m_paev, ifmsauthevent::f_stream_path);
i32 ivalue;
if (geti32field(m_paev, ifmsauthevent::f_client_audio_codecs, ivalue))
{
bool badpcm = isadpcmsupported(ivalue);
}
if (geti32field(m_paev, ifmsauthevent::f_client_video_codecs, ivalue))
{
bool bvp6 = isvp6supported(ivalue);
}
if (geti32field(m_paev, ifmsauthevent::f_client_type, ivalue))
{
bool bservice = isservice(ivalue);
}
if (geti32field(m_paev, ifmsauthevent::f_stream_id, ivalue))
{
i32 istreamid = ivalue;
}
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_length, fvalue))
{
float flength = fvalue; // in seconds
}
if (getfloatfield(m_paev, ifmsauthevent::f_stream_position, fvalue))
{
float iposition = fvalue; // in seconds
}
i64 lvalue;
if (geti64field(m_paev, ifmsauthevent::f_client_id, lvalue))
{
i64 iclientid = lvalue;
}
i8 svalue;
if (geti8field(m_paev, ifmsauthevent::f_client_secure, svalue))
{
bool bsecure = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_client_amf_encoding, svalue))
{
bool bamf3 = isamf3(svalue);
}
if (geti8field(m_paev, ifmsauthevent::f_client_read_access_lock, svalue))
{
bool bread = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_client_write_access_lock, svalue))
{
bool bwrite = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_client_audio_sample_access_lock, svalue))
{
bool baudioread = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_client_video_sample_access_lock, svalue))
{
bool bvideoread = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_stream_reset, svalue))
{
bool breset = svalue != 0;
}
if (geti8field(m_paev, ifmsauthevent::f_stream_ignore, svalue))
{
bool bignore = svalue != 0;
}
}
break;
case ifmsauthevent::e_seek:
{
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_seek_position, fvalue))
{
float fseektime = fvalue;
}
// disconnect action example: disconnect client
// specified e_seek notify event
fmsvariant field;
if (m_paev->getfield(ifmsauthevent::f_client_id, field) == ifmsauthevent::s_success)
{
ifmsdisconnectaction* paction =
const_cast<ifmsauthevent*>(m_paev)->
adddisconnectaction("seek not allowed. blocked adaptor");
paction->setclientid(field);
}
}
break;
case ifmsauthevent::e_codec_change:
{
char* pappname = getstringfield(m_paev, ifmsauthevent::f_app_name);
char* pappinst = getstringfield(m_paev, ifmsauthevent::f_app_inst);
char* pappuri = getstringfield(m_paev, ifmsauthevent::f_app_uri);
char* pclip = getstringfield(m_paev, ifmsauthevent::f_client_ip);
char* pcluri = getstringfield(m_paev, ifmsauthevent::f_client_uri);
char* pclnewuri = getstringfield(m_paev, ifmsauthevent::f_client_redirect_uri);
char* pclvhost = getstringfield(m_paev, ifmsauthevent::f_client_vhost);
char* pclref = getstringfield(m_paev, ifmsauthevent::f_client_referrer);
char* pclpurl = getstringfield(m_paev, ifmsauthevent::f_client_page_url);
char* pclagent = getstringfield(m_paev, ifmsauthevent::f_client_user_agent);
char* pclraccess = getstringfield(m_paev, ifmsauthevent::f_client_read_access);
char* pclwaccess = getstringfield(m_paev, ifmsauthevent::f_client_write_access);
char* pclaudioaccess = getstringfield(m_paev, ifmsauthevent::f_client_audio_sample_access);
char* pclvideoaccess = getstringfield(m_paev, ifmsauthevent::f_client_video_sample_access);
char* pclproto = getstringfield(m_paev, ifmsauthevent::f_client_proto);
char* pclustem = getstringfield(m_paev, ifmsauthevent::f_client_uri_stem);
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
char* pstreamquery = getstringfield(m_paev, ifmsauthevent::f_stream_query);
char* pstreampath = getstringfield(m_paev, ifmsauthevent::f_stream_path);
u16 ftype;
if (getu16field(m_paev, ifmsauthevent::f_stream_codec_type, ftype))
{
u16 streamcodectype = ftype;
if (streamcodectype == kvideo_codec)
{
u16 fvalue;
if (getu16field(m_paev, ifmsauthevent::f_stream_codec, fvalue))
{
u16 streamcodecvalue = fvalue;
if (streamcodecvalue == video_codec_sorenson)
{
// disconnect action example: disallow clients trying
// publish content sorenson video codec.
fmsvariant field;
if (m_paev->getfield(ifmsauthevent::f_client_id, field) == ifmsauthevent::s_success)
{
ifmsdisconnectaction* paction =
const_cast<ifmsauthevent*>(m_paev)->
adddisconnectaction("sorenson not allowed. blocked adaptor");
paction->setclientid(field);
}
}
}
}
}
}
break;
case ifmsauthevent::e_record_stop:
{
char* pappname = getstringfield(m_paev, ifmsauthevent::f_app_name);
char* pappinst = getstringfield(m_paev, ifmsauthevent::f_app_inst);
char* pappuri = getstringfield(m_paev, ifmsauthevent::f_app_uri);
char* pclip = getstringfield(m_paev, ifmsauthevent::f_client_ip);
char* pcluri = getstringfield(m_paev, ifmsauthevent::f_client_uri);
char* pclnewuri = getstringfield(m_paev, ifmsauthevent::f_client_redirect_uri);
char* pclvhost = getstringfield(m_paev, ifmsauthevent::f_client_vhost);
char* pclref = getstringfield(m_paev, ifmsauthevent::f_client_referrer);
char* pclpurl = getstringfield(m_paev, ifmsauthevent::f_client_page_url);
char* pclagent = getstringfield(m_paev, ifmsauthevent::f_client_user_agent);
char* pclraccess = getstringfield(m_paev, ifmsauthevent::f_client_read_access);
char* pclwaccess = getstringfield(m_paev, ifmsauthevent::f_client_write_access);
char* pclaudioaccess = getstringfield(m_paev, ifmsauthevent::f_client_audio_sample_access);
char* pclvideoaccess = getstringfield(m_paev, ifmsauthevent::f_client_video_sample_access);
char* pclproto = getstringfield(m_paev, ifmsauthevent::f_client_proto);
char* pclustem = getstringfield(m_paev, ifmsauthevent::f_client_uri_stem);
char* pstreamname = getstringfield(m_paev, ifmsauthevent::f_stream_name);
char* pstreamtype = getstringfield(m_paev, ifmsauthevent::f_stream_type);
char* pstreamquery = getstringfield(m_paev, ifmsauthevent::f_stream_query);
char* pstreampath = getstringfield(m_paev, ifmsauthevent::f_stream_path);
float fvalue;
if (getfloatfield(m_paev, ifmsauthevent::f_stream_record_maxsize, fvalue))
{
float recmaxsize = fvalue; // in kilobytes
}
if (getfloatfield(m_paev, ifmsauthevent::f_stream_record_maxduration, fvalue))
{
float recmaxduration = fvalue; // in seconds
}
}
break;
case ifmsauthevent::e_swf_verify_complete:
{
char* pclip = getstringfield(m_paev, ifmsauthevent::f_client_ip);
i8 version; // version of swf verification
geti8field(m_paev, ifmsauthevent::f_client_swfv_version, version);
i64 depth; // depth in swf file hashed
geti64field(m_paev, ifmsauthevent::f_client_swfv_depth, depth);
i32 ttl; // time live of swf hash provided
geti32field(m_paev, ifmsauthevent::f_client_swfv_ttl, ttl);
// digest provided match against
u8* buffer = getbufferfield(m_paev, ifmsauthevent::f_client_swfv_digest);
// result of attempted match-- see fmsauthevents.h enum
// eswfmatch meaning of field
i32 match;
geti32field(m_paev, ifmsauthevent::f_client_swfv_result, match);
std::stringstream stream;
stream << "swf verification client: "
<< std::string(pclip)
<< " complete, result is: " << match;
m_pfmsauthservercontext->log(stream.str().c_str(), ifmsservercontext::kinformation, false);
}
break;
case ifmsauthevent::e_appstart:
case ifmsauthevent::e_appstop:
case ifmsauthevent::e_connect:
case ifmsauthevent::e_disconnect:
case ifmsauthevent::e_filename_transform:
case ifmsauthevent::e_stop:
case ifmsauthevent::e_pause:
case ifmsauthevent::e_publish:
case ifmsauthevent::e_unpublish:
case ifmsauthevent::e_loadsegment:
case ifmsauthevent::e_action:
case ifmsauthevent::e_record:
case ifmsauthevent::e_client_pause:
case ifmsauthevent::e_swf_verify:
case ifmsauthevent::e_client_seek:
case ifmsauthevent::e_start_transmit:
case ifmsauthevent::e_stop_transmit:
case ifmsauthevent::e_maxevent:
break;
}
char buf[1024];
sprintf(buf, "received notification type=%d id=%p\n", m_paev->gettype(), m_paev);
// log configured fms log directory. if third parameter true,
// send log system event log.
m_pfmsauthservercontext->log(buf, ifmsservercontext::kinformation, false);
m_pfmsauthservercontext->onnotify(m_paev);
}
/* authorization events flow through wrapper function.
*
* note: sample auth adaptor has myfmsappauthevent allocated on
* stack, time intensive implementations may warrant authorization to
* allocated on heap work may passed thread pool. this
* prevents starvation of calling fms threads in custom code may
* have processing delays (ie database calls, network filesystem access, etc..).
*/
void fmsauthadaptor::authorize(ifmsauthevent* paev)
{
myfmsauthorizeevent(paev, m_pfmsauthservercontext).authorize();
}
/* notification events flow through wrapper function.
*
* note: sample auth adaptor has myfmsnotifyevent allocated on
* stack, time intensive implementations may warrant notifications to
* allocated on heap work may passed thread pool. this
* prevents starvation of calling fms threads in custom code may
* have processing delays (ie database calls, network filesystem access, etc..).
*/
void fmsauthadaptor::notify(ifmsauthevent* paev)
{
processstats(paev);
myfmsnotifyevent(paev, m_pfmsauthservercontext).notify();
}
/*
* client statistics.
*/
bool fmsauthadaptor::getstats(i64 clientstatshandle, fmsclientstats& basestats)
{
bool bvalue= m_pfmsauthservercontext->getclientstats(clientstatshandle, basestats);
return bvalue;
}
/*
* example obtainting client stats e_connect or e_stop event
*/
void fmsauthadaptor::processstats(ifmsauthevent* paev)
{
i64 statshandle;
fmsclientstats basestats;
if (!geti64field(paev, ifmsauthevent::f_client_stats_handle, statshandle))
return;
char* pappname = getstringfield(paev, ifmsauthevent::f_app_name);
if (paev->gettype() == ifmsauthevent::e_connect)
{
getstats(statshandle, basestats);
// log data
char buf[1024];
char hashkey[9];
memset(hashkey, 0, 9);
memcpy(hashkey, &statshandle, sizeof(statshandle));
sprintf(buf, "client stats handle= %s, bytes_in= %f, bytes_out= %f\n", hashkey,
static_cast<double>(basestats.bytes_in), static_cast<double>(basestats.bytes_out));
m_pfmsauthservercontext->log(buf, ifmsservercontext::kinformation, false);
}
else if (paev->gettype() == ifmsauthevent::e_stop)
{
getstats(statshandle, basestats);
}
}
/* default, authorization , notifications events sent.
* call excludeevents bit set 1, stop recieving events.
* note: events:
* e_appstart, e_appstop, e_disconnect, e_stop, e_unpublish, e_codec_change
* excluded default , not authorizable.
*/
void fmsauthadaptor::getevents(i32 aevbitauth[], i32 aevbitnotf[], unsigned int count)
{
// exclude auth events
ifmsauthevent::eventtype authexcludeevent[] = { ifmsauthevent::e_seek };
// set e_seek non authorizable event
m_pfmsauthservercontext->excludeevents(aevbitauth, count, authexcludeevent, 1);
// warning: if e_codec_change event not excluded, messages be
// scanned detect codec change. subscribe event needed.
// example excludes notify events. (e_pause, e_codec_change)
ifmsauthevent::eventtype notifyexcludeevent[] =
{ ifmsauthevent::e_pause, ifmsauthevent::e_codec_change };
m_pfmsauthservercontext->excludeevents(aevbitnotf, count, notifyexcludeevent, 2);
}
extern "c" void fcexport fmscreateauthadaptor3(ifmsauthservercontext2* pauthserverctx,
ifmsauthadaptor*& pfmsauthadaptor, u32& iversion)
{
pfmsauthadaptor = new fmsauthadaptor(pauthserverctx);
u32 version = pauthserverctx->getversion();
u16 w2 = lword(version);
u16 w1 = hword(version);
iversion = mklong(interface_minor_version, interface_major_version);
char buf[1024];
char *ptr = buf;
int valuelen = pauthserverctx->getconfig("userkey1", &ptr, sizeof(buf));
if (!valuelen)
{
valuelen = pauthserverctx->getconfig("userkey2", &ptr, sizeof(buf));
if (!valuelen)
{
return;
}
if (valuelen < 0)
{
// failed find key
return;
}
}
if (valuelen < 0)
{
// failed find key
return;
}
// value length bigger buffer size, , real adaptor should
// allocate valuelen + 1 bytes , call again
}
extern "c" void fcexport fmsdestroyauthadaptor3(ifmsauthadaptor* pauthadaptor )
{
delete pauthadaptor;
}
More discussions in Adobe Media Server
adobe
Comments
Post a Comment