Darwin-Streaming-Server/Server.tproj/QTSSModule.cpp
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

364 lines
15 KiB
C++

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: QTSSModule.cpp
Contains: Implements object defined in QTSSModule.h
*/
#include <errno.h>
#include "QTSSModule.h"
#include "OSArrayObjectDeleter.h"
#include "OSMemory.h"
#include "StringParser.h"
#include "Socket.h"
#include "QTSServerInterface.h"
Bool16 QTSSModule::sHasRTSPRequestModule = false;
Bool16 QTSSModule::sHasOpenFileModule = false;
Bool16 QTSSModule::sHasRTSPAuthenticateModule = false;
QTSSAttrInfoDict::AttrInfo QTSSModule::sAttributes[] =
{ /*fields: fAttrName, fFuncPtr, fAttrDataType, fAttrPermission */
/* 0 */ { "qtssModName", NULL, qtssAttrDataTypeCharArray, qtssAttrModeRead | qtssAttrModePreempSafe },
/* 1 */ { "qtssModDesc", NULL, qtssAttrDataTypeCharArray, qtssAttrModeRead | qtssAttrModeWrite },
/* 2 */ { "qtssModVersion", NULL, qtssAttrDataTypeUInt32, qtssAttrModeRead | qtssAttrModeWrite },
/* 3 */ { "qtssModRoles", NULL, qtssAttrDataTypeUInt32, qtssAttrModeRead | qtssAttrModePreempSafe },
/* 4 */ { "qtssModPrefs", NULL, qtssAttrDataTypeQTSS_Object,qtssAttrModeRead | qtssAttrModePreempSafe | qtssAttrModeInstanceAttrAllowed },
/* 5 */ { "qtssModAttributes", NULL, qtssAttrDataTypeQTSS_Object, qtssAttrModeRead | qtssAttrModePreempSafe | qtssAttrModeInstanceAttrAllowed }
};
char* QTSSModule::sRoleNames[] =
{
"InitializeRole" ,
"ShutdownRole" ,
"RTSPFilterRole" ,
"RTSPRouteRole" ,
"RTSPAthnRole" ,
"RTSPAuthRole" ,
"RTSPPreProcessorRole" ,
"RTSPRequestRole" ,
"RTSPPostProcessorRole" ,
"RTSPSessionClosingRole" ,
"RTPSendPacketsRole" ,
"ClientSessionClosingRole" ,
"RTCPProcessRole" ,
"ErrorLogRole" ,
"RereadPrefsRole" ,
"OpenFileRole" ,
"OpenFilePreProcessRole" ,
"AdviseFileRole" ,
"ReadFileRole" ,
"CloseFileRole" ,
"RequestEventFileRole" ,
"RTSPIncomingDataRole" ,
"StateChangeRole" ,
"TimedIntervalRole" ,
""
};
void QTSSModule::Initialize()
{
//Setup all the dictionary stuff
for (UInt32 x = 0; x < qtssModNumParams; x++)
QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kModuleDictIndex)->
SetAttribute(x, sAttributes[x].fAttrName, sAttributes[x].fFuncPtr,
sAttributes[x].fAttrDataType, sAttributes[x].fAttrPermission);
}
QTSSModule::QTSSModule(char* inName, char* inPath)
: QTSSDictionary(QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kModuleDictIndex)),
fQueueElem(NULL),
fPath(NULL),
fFragment(NULL),
fDispatchFunc(NULL),
fPrefs(NULL),
fAttributes(NULL)
{
fQueueElem.SetEnclosingObject(this);
this->SetTaskName("QTSSModule");
if ((inPath != NULL) && (inPath[0] != '\0'))
{
// Create a code fragment if this module is being loaded from disk
fFragment = NEW OSCodeFragment(inPath);
fPath = NEW char[::strlen(inPath) + 2];
::strcpy(fPath, inPath);
}
fAttributes = NEW QTSSDictionary( NULL, &fAttributesMutex );
this->SetVal(qtssModPrefs, &fPrefs, sizeof(fPrefs));
this->SetVal(qtssModAttributes, &fAttributes, sizeof(fAttributes));
// If there is a name, copy it into the module object's internal buffer
if (inName != NULL)
this->SetValue(qtssModName, 0, inName, ::strlen(inName), QTSSDictionary::kDontObeyReadOnly);
::memset(fRoleArray, 0, sizeof(fRoleArray));
::memset(&fModuleState, 0, sizeof(fModuleState));
}
QTSS_Error QTSSModule::SetupModule(QTSS_CallbacksPtr inCallbacks, QTSS_MainEntryPointPtr inEntrypoint)
{
QTSS_Error theErr = QTSS_NoErr;
// Load fragment from disk if necessary
if ((fFragment != NULL) && (inEntrypoint == NULL))
theErr = this->LoadFromDisk(&inEntrypoint);
if (theErr != QTSS_NoErr)
return theErr;
// At this point, we must have an entrypoint
if (inEntrypoint == NULL)
return QTSS_NotAModule;
// Invoke the private initialization routine
QTSS_PrivateArgs thePrivateArgs;
thePrivateArgs.inServerAPIVersion = QTSS_API_VERSION;
thePrivateArgs.inCallbacks = inCallbacks;
thePrivateArgs.outStubLibraryVersion = 0;
thePrivateArgs.outDispatchFunction = NULL;
theErr = (inEntrypoint)(&thePrivateArgs);
if (theErr != QTSS_NoErr)
return theErr;
if (thePrivateArgs.outStubLibraryVersion > thePrivateArgs.inServerAPIVersion)
return QTSS_WrongVersion;
// Set the dispatch function so we'll be able to invoke this module later on
fDispatchFunc = thePrivateArgs.outDispatchFunction;
//Log
char msgStr[2048];
char* moduleName = NULL;
(void)this->GetValueAsString (qtssModName, 0, &moduleName);
qtss_snprintf(msgStr, sizeof(msgStr), "Module Loaded...%s [%s]", moduleName, (fFragment==NULL)?"static":"dynamic");
delete moduleName;
QTSServerInterface::LogError(qtssMessageVerbosity, msgStr);
return QTSS_NoErr;
}
QTSS_Error QTSSModule::LoadFromDisk(QTSS_MainEntryPointPtr* outEntrypoint)
{
static StrPtrLen sMainEntrypointName("_Main");
Assert(outEntrypoint != NULL);
// Modules only need to be initialized if they reside on disk.
if (fFragment == NULL)
return QTSS_NoErr;
if (!fFragment->IsValid())
return QTSS_NotAModule;
// fPath is actually a path. Extract the file name.
StrPtrLen theFileName(fPath);
StringParser thePathParser(&theFileName);
while (thePathParser.GetThru(&theFileName, kPathDelimiterChar))
;
Assert(theFileName.Len > 0);
Assert(theFileName.Ptr != NULL);
#ifdef __Win32__
StringParser theDLLTruncator(&theFileName);
theDLLTruncator.ConsumeUntil(&theFileName, '.'); // strip off the ".DLL"
#endif
/** 08/16/01 quellish **/
#if __MacOSX__
StringParser theBundleTruncator(&theFileName);
theBundleTruncator.ConsumeUntil(&theFileName, '.'); // strip off the ".bundle"
#endif
// At this point, theFileName points to the file name. Make this the module name.
this->SetValue(qtssModName, 0, theFileName.Ptr, theFileName.Len, QTSSDictionary::kDontObeyReadOnly);
//
// The main entrypoint symbol name is the file name plus that _Main__ string up there.
OSCharArrayDeleter theSymbolName(NEW char[theFileName.Len + sMainEntrypointName.Len + 2]);
::memcpy(theSymbolName, theFileName.Ptr, theFileName.Len);
theSymbolName[theFileName.Len] = '\0';
::strcat(theSymbolName, sMainEntrypointName.Ptr);
*outEntrypoint = (QTSS_MainEntryPointPtr)fFragment->GetSymbol(theSymbolName.GetObject());
return QTSS_NoErr;
}
SInt32 QTSSModule::GetPrivateRoleIndex(QTSS_Role apiRole)
{
switch (apiRole)
{
// Map actual QTSS Role names to our private enum values. Turn on the proper one
// in the role array
case QTSS_Initialize_Role: return kInitializeRole ;
case QTSS_Shutdown_Role: return kShutdownRole ;
case QTSS_RTSPFilter_Role: return kRTSPFilterRole ;
case QTSS_RTSPRoute_Role: return kRTSPRouteRole ;
case QTSS_RTSPAuthenticate_Role: return kRTSPAthnRole ;
case QTSS_RTSPAuthorize_Role: return kRTSPAuthRole ;
case QTSS_RTSPPreProcessor_Role: return kRTSPPreProcessorRole ;
case QTSS_RTSPRequest_Role: return kRTSPRequestRole ;
case QTSS_RTSPPostProcessor_Role: return kRTSPPostProcessorRole ;
case QTSS_RTSPSessionClosing_Role: return kRTSPSessionClosingRole ;
case QTSS_RTPSendPackets_Role: return kRTPSendPacketsRole ;
case QTSS_ClientSessionClosing_Role:return kClientSessionClosingRole;
case QTSS_RTCPProcess_Role: return kRTCPProcessRole ;
case QTSS_ErrorLog_Role: return kErrorLogRole ;
case QTSS_RereadPrefs_Role: return kRereadPrefsRole ;
case QTSS_OpenFile_Role: return kOpenFileRole ;
case QTSS_OpenFilePreProcess_Role: return kOpenFilePreProcessRole ;
case QTSS_AdviseFile_Role: return kAdviseFileRole ;
case QTSS_ReadFile_Role: return kReadFileRole ;
case QTSS_CloseFile_Role: return kCloseFileRole ;
case QTSS_RequestEventFile_Role: return kRequestEventFileRole ;
case QTSS_RTSPIncomingData_Role: return kRTSPIncomingDataRole ;
case QTSS_StateChange_Role: return kStateChangeRole ;
case QTSS_Interval_Role: return kTimedIntervalRole ;
default:
return -1;
}
}
QTSS_Error QTSSModule::AddRole(QTSS_Role inRole)
{
// There can only be one QTSS_RTSPRequest processing module
if ((inRole == QTSS_RTSPRequest_Role) && (sHasRTSPRequestModule))
return QTSS_RequestFailed;
if ((inRole == QTSS_OpenFilePreProcess_Role) && (sHasOpenFileModule))
return QTSS_RequestFailed;
#if 0// Allow multiple modules in QTSS v6.0. Enabling forces the first auth module There can be only one module registered for QTSS_RTSPAuthenticate_Role
if ((inRole == QTSS_RTSPAuthenticate_Role) && (sHasRTSPAuthenticateModule))
return QTSS_RequestFailed;
#endif
SInt32 arrayID = GetPrivateRoleIndex(inRole);
if (arrayID < 0)
return QTSS_BadArgument;
fRoleArray[arrayID] = true;
/*
switch (inRole)
{
// Map actual QTSS Role names to our private enum values. Turn on the proper one
// in the role array
case QTSS_Initialize_Role: fRoleArray[kInitializeRole] = true; break;
case QTSS_Shutdown_Role: fRoleArray[kShutdownRole] = true; break;
case QTSS_RTSPFilter_Role: fRoleArray[kRTSPFilterRole] = true; break;
case QTSS_RTSPRoute_Role: fRoleArray[kRTSPRouteRole] = true; break;
case QTSS_RTSPAuthenticate_Role: fRoleArray[kRTSPAthnRole] = true; break;
case QTSS_RTSPAuthorize_Role: fRoleArray[kRTSPAuthRole] = true; break;
case QTSS_RTSPPreProcessor_Role: fRoleArray[kRTSPPreProcessorRole] = true; break;
case QTSS_RTSPRequest_Role: fRoleArray[kRTSPRequestRole] = true; break;
case QTSS_RTSPPostProcessor_Role: fRoleArray[kRTSPPostProcessorRole] = true; break;
case QTSS_RTSPSessionClosing_Role: fRoleArray[kRTSPSessionClosingRole] = true; break;
case QTSS_RTPSendPackets_Role: fRoleArray[kRTPSendPacketsRole] = true; break;
case QTSS_ClientSessionClosing_Role:fRoleArray[kClientSessionClosingRole] = true;break;
case QTSS_RTCPProcess_Role: fRoleArray[kRTCPProcessRole] = true; break;
case QTSS_ErrorLog_Role: fRoleArray[kErrorLogRole] = true; break;
case QTSS_RereadPrefs_Role: fRoleArray[kRereadPrefsRole] = true; break;
case QTSS_OpenFile_Role: fRoleArray[kOpenFileRole] = true; break;
case QTSS_OpenFilePreProcess_Role: fRoleArray[kOpenFilePreProcessRole] = true; break;
case QTSS_AdviseFile_Role: fRoleArray[kAdviseFileRole] = true; break;
case QTSS_ReadFile_Role: fRoleArray[kReadFileRole] = true; break;
case QTSS_CloseFile_Role: fRoleArray[kCloseFileRole] = true; break;
case QTSS_RequestEventFile_Role: fRoleArray[kRequestEventFileRole] = true; break;
case QTSS_RTSPIncomingData_Role: fRoleArray[kRTSPIncomingDataRole] = true; break;
case QTSS_StateChange_Role: fRoleArray[kStateChangeRole] = true; break;
case QTSS_Interval_Role: fRoleArray[kTimedIntervalRole] = true; break;
default:
return QTSS_BadArgument;
}
*/
if (inRole == QTSS_RTSPRequest_Role)
sHasRTSPRequestModule = true;
if (inRole == QTSS_OpenFile_Role)
sHasOpenFileModule = true;
if (inRole == QTSS_RTSPAuthenticate_Role)
sHasRTSPAuthenticateModule = true;
//
// Add this role to the array of roles attribute
QTSS_Error theErr = this->SetValue(qtssModRoles, this->GetNumValues(qtssModRoles), &inRole, sizeof(inRole), QTSSDictionary::kDontObeyReadOnly);
Assert(theErr == QTSS_NoErr);
return QTSS_NoErr;
}
SInt64 QTSSModule::Run()
{
EventFlags events = this->GetEvents();
OSThreadDataSetter theSetter(&fModuleState, NULL);
if (events & Task::kUpdateEvent)
{ // force us to update to a new idle time
return fModuleState.idleTime;// If the module has requested idle time...
}
if (fRoleArray[kTimedIntervalRole])
{
if (events & Task::kIdleEvent || fModuleState.globalLockRequested)
{
fModuleState.curModule = this; // this structure is setup in each thread
fModuleState.curRole = QTSS_Interval_Role; // before invoking a module in a role. Sometimes
fModuleState.eventRequested = false;
fModuleState.curTask = this;
if (fModuleState.globalLockRequested )
{ fModuleState.globalLockRequested = false;
fModuleState.isGlobalLocked = true;
}
(void)this->CallDispatch(QTSS_Interval_Role, NULL);
fModuleState.isGlobalLocked = false;
if (fModuleState.globalLockRequested) // call this request back locked
return this->CallLocked();
return fModuleState.idleTime; // If the module has requested idle time...
}
}
return 0;
}