1049 lines
38 KiB
C++
1049 lines
38 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: QTSSAdminModule.cpp
|
|
|
|
Contains: Implements Admin module
|
|
|
|
*/
|
|
|
|
|
|
#ifndef __Win32__
|
|
#include <unistd.h> /* for getopt() et al */
|
|
#endif
|
|
|
|
#include <time.h>
|
|
#include <stdio.h> /* for qtss_printf */
|
|
#include <stdlib.h> /* for getloadavg & other useful stuff */
|
|
#include "QTSSAdminModule.h"
|
|
#include "OSArrayObjectDeleter.h"
|
|
#include "StringParser.h"
|
|
#include "StrPtrLen.h"
|
|
#include "QTSSModuleUtils.h"
|
|
#include "OSHashTable.h"
|
|
#include "OSMutex.h"
|
|
#include "StrPtrLen.h"
|
|
#include "OSRef.h"
|
|
#include "AdminElementNode.h"
|
|
#include "base64.h"
|
|
#include "OSMemory.h"
|
|
#include "md5.h"
|
|
#include "md5digest.h"
|
|
|
|
#if __MacOSX__
|
|
#include <Security/Authorization.h>
|
|
#include <Security/AuthorizationTags.h>
|
|
#endif
|
|
|
|
#if __solaris__ || __linux__ || __sgi__ || __hpux__
|
|
#include <crypt.h>
|
|
#endif
|
|
|
|
#define DEBUG_ADMIN_MODULE 0
|
|
|
|
|
|
//**************************************************
|
|
#define kAuthNameAndPasswordBuffSize 512
|
|
#define kPasswordBuffSize kAuthNameAndPasswordBuffSize/2
|
|
|
|
// STATIC DATA
|
|
//**************************************************
|
|
#if DEBUG_ADMIN_MODULE
|
|
static UInt32 sRequestCount= 0;
|
|
#endif
|
|
|
|
static QTSS_Initialize_Params sQTSSparams;
|
|
|
|
//static char* sResponseHeader = "HTTP/1.0 200 OK\r\nServer: QTSS\r\nConnection: Close\r\nContent-Type: text/plain\r\n\r\n";
|
|
static char* sResponseHeader = "HTTP/1.0 200 OK";
|
|
static char* sUnauthorizedResponseHeader = "HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"QTSS/modules/admin\"\r\nServer: QTSS\r\nConnection: Close\r\nContent-Type: text/plain\r\n\r\n";
|
|
static char* sPermissionDeniedHeader = "HTTP/1.1 403 Forbidden\r\nConnection: Close\r\nContent-Type: text/html\r\n\r\n";
|
|
static char* sHTMLBody = "<HTML><BODY>\n<P><b>Your request was denied by the server.</b></P>\n</BODY></HTML>\r\n\r\n";
|
|
|
|
|
|
static char* sVersionHeader = NULL;
|
|
static char* sConnectionHeader = "Connection: Close";
|
|
static char* kDefaultHeader = "Server: QTSS";
|
|
static char* sContentType = "Content-Type: text/plain";
|
|
static char* sEOL = "\r\n";
|
|
static char* sEOM = "\r\n\r\n";
|
|
static char* sAuthRealm = "QTSS/modules/admin";
|
|
static char* sAuthResourceLocalPath = "/modules/admin/";
|
|
|
|
static QTSS_ServerObject sServer = NULL;
|
|
static QTSS_ModuleObject sModule = NULL;
|
|
static QTSS_ModulePrefsObject sModulePrefs = NULL;
|
|
static QTSS_PrefsObject sServerPrefs = NULL;
|
|
static AdminClass *sAdminPtr = NULL;
|
|
static QueryURI *sQueryPtr = NULL;
|
|
static OSMutex* sAdminMutex = NULL;//admin module isn't reentrant
|
|
static UInt32 sVersion=20030306;
|
|
static char *sDesc="Implements HTTP based Admin Protocol for accessing server attributes";
|
|
static char decodedLine[kAuthNameAndPasswordBuffSize] = { 0 };
|
|
static char codedLine[kAuthNameAndPasswordBuffSize] = { 0 };
|
|
static QTSS_TimeVal sLastRequestTime = 0;
|
|
static UInt32 sSessID = 0;
|
|
|
|
static StrPtrLen sAuthRef("AuthRef");
|
|
#if __MacOSX__
|
|
|
|
static char* sSecurityServerAuthKey = "com.apple.server.admin.streaming";
|
|
static AuthorizationItem sRight = { sSecurityServerAuthKey, 0, NULL, 0 };
|
|
static AuthorizationRights sRightSet = { 1, &sRight };
|
|
#endif
|
|
|
|
|
|
// ATTRIBUTES
|
|
//**************************************************
|
|
enum { kMaxRequestTimeIntervalMilli = 1000, kDefaultRequestTimeIntervalMilli = 50 };
|
|
static UInt32 sDefaultRequestTimeIntervalMilli = kDefaultRequestTimeIntervalMilli;
|
|
static UInt32 sRequestTimeIntervalMilli = kDefaultRequestTimeIntervalMilli;
|
|
|
|
static Bool16 sAuthenticationEnabled = true;
|
|
static Bool16 sDefaultAuthenticationEnabled = true;
|
|
|
|
static Bool16 sLocalLoopBackOnlyEnabled = true;
|
|
static Bool16 sDefaultLocalLoopBackOnlyEnabled = true;
|
|
|
|
static Bool16 sEnableRemoteAdmin = true;
|
|
static Bool16 sDefaultEnableRemoteAdmin = true;
|
|
|
|
|
|
static QTSS_AttributeID sIPAccessListID = qtssIllegalAttrID;
|
|
static char* sIPAccessList = NULL;
|
|
static char* sLocalLoopBackAddress = "127.0.0.*";
|
|
|
|
static char* sAdministratorGroup = NULL;
|
|
static char* sDefaultAdministratorGroup = "admin";
|
|
|
|
static Bool16 sFlushing = false;
|
|
static QTSS_AttributeID sFlushingID = qtssIllegalAttrID;
|
|
static char* sFlushingName = "QTSSAdminModuleFlushingState";
|
|
static UInt32 sFlushingLen = sizeof(sFlushing);
|
|
|
|
static QTSS_AttributeID sAuthenticatedID = qtssIllegalAttrID;
|
|
static char* sAuthenticatedName = "QTSSAdminModuleAuthenticatedState";
|
|
|
|
//**************************************************
|
|
|
|
static QTSS_Error QTSSAdminModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams);
|
|
static QTSS_Error Register(QTSS_Register_Params* inParams);
|
|
static QTSS_Error Initialize(QTSS_Initialize_Params* inParams);
|
|
static QTSS_Error FilterRequest(QTSS_Filter_Params* inParams);
|
|
static QTSS_Error RereadPrefs();
|
|
static QTSS_Error AuthorizeAdminRequest(QTSS_RTSPRequestObject request);
|
|
static Bool16 AcceptSession(QTSS_RTSPSessionObject inRTSPSession);
|
|
|
|
|
|
#if !DEBUG_ADMIN_MODULE
|
|
#define APITests_DEBUG()
|
|
#define ShowQuery_DEBUG()
|
|
#else
|
|
void ShowQuery_DEBUG()
|
|
{
|
|
qtss_printf("======REQUEST #%"_U32BITARG_"======\n",++sRequestCount);
|
|
StrPtrLen* aStr;
|
|
aStr = sQueryPtr->GetURL();
|
|
qtss_printf("URL="); PRINT_STR(aStr);
|
|
|
|
aStr = sQueryPtr->GetQuery();
|
|
qtss_printf("Query="); PRINT_STR(aStr);
|
|
|
|
aStr = sQueryPtr->GetParameters();
|
|
qtss_printf("Parameters="); PRINT_STR(aStr);
|
|
|
|
aStr = sQueryPtr->GetCommand();
|
|
qtss_printf("Command="); PRINT_STR(aStr);
|
|
qtss_printf("CommandID=%"_S32BITARG_" \n",sQueryPtr->GetCommandID());
|
|
aStr = sQueryPtr->GetValue();
|
|
qtss_printf("Value="); PRINT_STR(aStr);
|
|
aStr = sQueryPtr->GetType();
|
|
qtss_printf("Type="); PRINT_STR(aStr);
|
|
aStr = sQueryPtr->GetAccess();
|
|
qtss_printf("Access="); PRINT_STR(aStr);
|
|
}
|
|
|
|
void APITests_DEBUG()
|
|
{
|
|
if (0)
|
|
{ qtss_printf("QTSSAdminModule start tests \n");
|
|
|
|
if (0)
|
|
{
|
|
qtss_printf("admin called locked \n");
|
|
const int ksleeptime = 15;
|
|
qtss_printf("sleeping for %d seconds \n",ksleeptime);
|
|
sleep(ksleeptime);
|
|
qtss_printf("done sleeping \n");
|
|
qtss_printf("QTSS_GlobalUnLock \n");
|
|
(void) QTSS_GlobalUnLock();
|
|
qtss_printf("again sleeping for %d seconds \n",ksleeptime);
|
|
sleep(ksleeptime);
|
|
}
|
|
|
|
if (0)
|
|
{
|
|
qtss_printf(" GET VALUE PTR TEST \n");
|
|
|
|
QTSS_Object *sessionsPtr = NULL;
|
|
UInt32 paramLen = sizeof(sessionsPtr);
|
|
UInt32 numValues = 0;
|
|
QTSS_Error err = 0;
|
|
|
|
err = QTSS_GetNumValues (sServer, qtssSvrClientSessions, &numValues);
|
|
err = QTSS_GetValuePtr(sServer, qtssSvrClientSessions, 0, (void**)&sessionsPtr, ¶mLen);
|
|
qtss_printf("Admin Module Num Sessions = %"_U32BITARG_" sessions[0] = %"_S32BITARG_" err = %"_S32BITARG_" paramLen =%"_U32BITARG_"\n", numValues, (SInt32) *sessionsPtr,err,paramLen);
|
|
|
|
UInt32 numAttr = 0;
|
|
if (sessionsPtr)
|
|
{ err = QTSS_GetNumAttributes (*sessionsPtr, &numAttr);
|
|
qtss_printf("Admin Module Num attributes = %"_U32BITARG_" sessions[0] = %"_S32BITARG_" err = %"_S32BITARG_"\n", numAttr, (SInt32) *sessionsPtr,err);
|
|
|
|
QTSS_Object theAttributeInfo;
|
|
char nameBuff[128];
|
|
UInt32 len = 127;
|
|
for (UInt32 i = 0; i < numAttr; i++)
|
|
{ err = QTSS_GetAttrInfoByIndex(*sessionsPtr, i, &theAttributeInfo);
|
|
nameBuff[0] = 0;len = 127;
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrName,0, nameBuff,&len);
|
|
nameBuff[len] = 0;
|
|
qtss_printf("found %s \n",nameBuff);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0)
|
|
{
|
|
qtss_printf(" GET VALUE TEST \n");
|
|
|
|
QTSS_Object sessions = NULL;
|
|
UInt32 paramLen = sizeof(sessions);
|
|
UInt32 numValues = 0;
|
|
QTSS_Error err = 0;
|
|
|
|
err = QTSS_GetNumValues (sServer, qtssSvrClientSessions, &numValues);
|
|
err = QTSS_GetValue(sServer, qtssSvrClientSessions, 0, (void*)&sessions, ¶mLen);
|
|
qtss_printf("Admin Module Num Sessions = %"_U32BITARG_" sessions[0] = %"_S32BITARG_" err = %"_S32BITARG_" paramLen = %"_U32BITARG_"\n", numValues, (SInt32) sessions,err, paramLen);
|
|
|
|
if (sessions)
|
|
{
|
|
UInt32 numAttr = 0;
|
|
err = QTSS_GetNumAttributes (sessions, &numAttr);
|
|
qtss_printf("Admin Module Num attributes = %"_U32BITARG_" sessions[0] = %"_S32BITARG_" err = %"_S32BITARG_"\n", numAttr,(SInt32) sessions,err);
|
|
|
|
QTSS_Object theAttributeInfo;
|
|
char nameBuff[128];
|
|
UInt32 len = 127;
|
|
for (UInt32 i = 0; i < numAttr; i++)
|
|
{ err = QTSS_GetAttrInfoByIndex(sessions, i, &theAttributeInfo);
|
|
nameBuff[0] = 0;len = 127;
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrName,0, nameBuff,&len);
|
|
nameBuff[len] = 0;
|
|
qtss_printf("found %s \n",nameBuff);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (0)
|
|
{
|
|
qtss_printf("----------------- Start test ----------------- \n");
|
|
qtss_printf(" GET indexed pref TEST \n");
|
|
|
|
QTSS_Error err = 0;
|
|
|
|
UInt32 numAttr = 1;
|
|
err = QTSS_GetNumAttributes (sModulePrefs, &numAttr);
|
|
qtss_printf("Admin Module Num preference attributes = %"_U32BITARG_" err = %"_S32BITARG_"\n", numAttr, err);
|
|
|
|
QTSS_Object theAttributeInfo;
|
|
char valueBuff[512];
|
|
char nameBuff[128];
|
|
QTSS_AttributeID theID;
|
|
UInt32 len = 127;
|
|
UInt32 i = 0;
|
|
qtss_printf("first pass over preferences\n");
|
|
for ( i = 0; i < numAttr; i++)
|
|
{ err = QTSS_GetAttrInfoByIndex(sModulePrefs, i, &theAttributeInfo);
|
|
nameBuff[0] = 0;len = 127;
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrName,0, nameBuff,&len);
|
|
nameBuff[len]=0;
|
|
|
|
theID = qtssIllegalAttrID; len = sizeof(theID);
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrID,0, &theID,&len);
|
|
qtss_printf("found preference=%s \n",nameBuff);
|
|
}
|
|
valueBuff[0] = 0;len = 512;
|
|
err = QTSS_GetValue (sModulePrefs, theID,0, valueBuff,&len);valueBuff[len] = 0;
|
|
qtss_printf("Admin Module QTSS_GetValue name = %s id = %"_S32BITARG_" value=%s err = %"_S32BITARG_"\n", nameBuff,theID, valueBuff, err);
|
|
err = QTSS_SetValue (sModulePrefs,theID,0, valueBuff,len);
|
|
qtss_printf("Admin Module QTSS_SetValue name = %s id = %"_S32BITARG_" value=%s err = %"_S32BITARG_"\n", nameBuff,theID, valueBuff, err);
|
|
|
|
{ QTSS_ServiceID id;
|
|
(void) QTSS_IDForService(QTSS_REREAD_PREFS_SERVICE, &id);
|
|
(void) QTSS_DoService(id, NULL);
|
|
}
|
|
|
|
valueBuff[0] = 0;len = 512;
|
|
err = QTSS_GetValue (sModulePrefs, theID,0, valueBuff,&len);valueBuff[len] = 0;
|
|
qtss_printf("Admin Module QTSS_GetValue name = %s id = %"_S32BITARG_" value=%s err = %"_S32BITARG_"\n", nameBuff,theID, valueBuff, err);
|
|
err = QTSS_SetValue (sModulePrefs,theID,0, valueBuff,len);
|
|
qtss_printf("Admin Module QTSS_SetValue name = %s id = %"_S32BITARG_" value=%s err = %"_S32BITARG_"\n", nameBuff,theID, valueBuff, err);
|
|
|
|
qtss_printf("second pass over preferences\n");
|
|
for ( i = 0; i < numAttr; i++)
|
|
{ err = QTSS_GetAttrInfoByIndex(sModulePrefs, i, &theAttributeInfo);
|
|
nameBuff[0] = 0;len = 127;
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrName,0, nameBuff,&len);
|
|
nameBuff[len]=0;
|
|
|
|
theID = qtssIllegalAttrID; len = sizeof(theID);
|
|
err = QTSS_GetValue (theAttributeInfo, qtssAttrID,0, &theID,&len);
|
|
qtss_printf("found preference=%s \n",nameBuff);
|
|
}
|
|
qtss_printf("----------------- Done test ----------------- \n");
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
inline void KeepSession(QTSS_RTSPRequestObject theRequest,Bool16 keep)
|
|
{
|
|
(void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &keep, sizeof(keep));
|
|
}
|
|
|
|
// FUNCTION IMPLEMENTATIONS
|
|
|
|
QTSS_Error QTSSAdminModule_Main(void* inPrivateArgs)
|
|
{
|
|
return _stublibrary_main(inPrivateArgs, QTSSAdminModuleDispatch);
|
|
}
|
|
|
|
|
|
QTSS_Error QTSSAdminModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams)
|
|
{
|
|
switch (inRole)
|
|
{
|
|
case QTSS_Register_Role:
|
|
return Register(&inParams->regParams);
|
|
case QTSS_Initialize_Role:
|
|
return Initialize(&inParams->initParams);
|
|
case QTSS_RTSPFilter_Role:
|
|
{ if (!sEnableRemoteAdmin)
|
|
break;
|
|
return FilterRequest(&inParams->rtspFilterParams);
|
|
}
|
|
case QTSS_RTSPAuthorize_Role:
|
|
return AuthorizeAdminRequest(inParams->rtspRequestParams.inRTSPRequest);
|
|
case QTSS_RereadPrefs_Role:
|
|
return RereadPrefs();
|
|
}
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
|
|
QTSS_Error Register(QTSS_Register_Params* inParams)
|
|
{
|
|
// Do role & attribute setup
|
|
(void)QTSS_AddRole(QTSS_Initialize_Role);
|
|
(void)QTSS_AddRole(QTSS_RTSPFilter_Role);
|
|
(void)QTSS_AddRole(QTSS_RereadPrefs_Role);
|
|
(void)QTSS_AddRole(QTSS_RTSPAuthorize_Role);
|
|
|
|
(void)QTSS_AddStaticAttribute(qtssRTSPRequestObjectType, sFlushingName, NULL, qtssAttrDataTypeBool16);
|
|
(void)QTSS_IDForAttr(qtssRTSPRequestObjectType, sFlushingName, &sFlushingID);
|
|
|
|
(void)QTSS_AddStaticAttribute(qtssRTSPRequestObjectType, sAuthenticatedName, NULL, qtssAttrDataTypeBool16);
|
|
(void)QTSS_IDForAttr(qtssRTSPRequestObjectType, sAuthenticatedName, &sAuthenticatedID);
|
|
|
|
// Tell the server our name!
|
|
static char* sModuleName = "QTSSAdminModule";
|
|
::strcpy(inParams->outModuleName, sModuleName);
|
|
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
QTSS_Error RereadPrefs()
|
|
{
|
|
|
|
delete [] sVersionHeader;
|
|
sVersionHeader = QTSSModuleUtils::GetStringAttribute(sServer, "qtssSvrRTSPServerHeader", kDefaultHeader);
|
|
|
|
delete [] sIPAccessList;
|
|
sIPAccessList = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "IPAccessList", sLocalLoopBackAddress);
|
|
sIPAccessListID = QTSSModuleUtils::GetAttrID(sModulePrefs, "IPAccessList");
|
|
|
|
QTSSModuleUtils::GetAttribute(sModulePrefs, "Authenticate", qtssAttrDataTypeBool16, &sAuthenticationEnabled, &sDefaultAuthenticationEnabled, sizeof(sAuthenticationEnabled));
|
|
QTSSModuleUtils::GetAttribute(sModulePrefs, "LocalAccessOnly", qtssAttrDataTypeBool16, &sLocalLoopBackOnlyEnabled, &sDefaultLocalLoopBackOnlyEnabled, sizeof(sLocalLoopBackOnlyEnabled));
|
|
QTSSModuleUtils::GetAttribute(sModulePrefs, "RequestTimeIntervalMilli", qtssAttrDataTypeUInt32, &sRequestTimeIntervalMilli, &sDefaultRequestTimeIntervalMilli, sizeof(sRequestTimeIntervalMilli));
|
|
QTSSModuleUtils::GetAttribute(sModulePrefs, "enable_remote_admin", qtssAttrDataTypeBool16, &sEnableRemoteAdmin, &sDefaultEnableRemoteAdmin, sizeof(sDefaultEnableRemoteAdmin));
|
|
|
|
delete [] sAdministratorGroup;
|
|
sAdministratorGroup = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "AdministratorGroup", sDefaultAdministratorGroup);
|
|
|
|
if (sRequestTimeIntervalMilli > kMaxRequestTimeIntervalMilli)
|
|
{ sRequestTimeIntervalMilli = kMaxRequestTimeIntervalMilli;
|
|
}
|
|
|
|
(void)QTSS_SetValue(sModule, qtssModDesc, 0, sDesc, strlen(sDesc)+1);
|
|
(void)QTSS_SetValue(sModule, qtssModVersion, 0, &sVersion, sizeof(sVersion));
|
|
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
QTSS_Error Initialize(QTSS_Initialize_Params* inParams)
|
|
{
|
|
sAdminMutex = NEW OSMutex();
|
|
ElementNode_InitPtrArray();
|
|
// Setup module utils
|
|
QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream);
|
|
|
|
sQTSSparams = *inParams;
|
|
sServer = inParams->inServer;
|
|
sModule = inParams->inModule;
|
|
sModulePrefs = QTSSModuleUtils::GetModulePrefsObject(sModule);
|
|
sServerPrefs = inParams->inPrefs;
|
|
|
|
RereadPrefs();
|
|
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
|
|
void ReportErr(QTSS_Filter_Params* inParams, UInt32 err)
|
|
{
|
|
StrPtrLen* urlPtr = sQueryPtr->GetURL();
|
|
StrPtrLen* evalMessagePtr = sQueryPtr->GetEvalMsg();
|
|
char temp[32];
|
|
|
|
if (urlPtr && evalMessagePtr)
|
|
{ qtss_sprintf(temp,"(%"_U32BITARG_")",err);
|
|
(void)QTSS_Write(inParams->inRTSPRequest, "error:", strlen("error:"), NULL, 0);
|
|
(void)QTSS_Write(inParams->inRTSPRequest, temp, strlen(temp), NULL, 0);
|
|
if (sQueryPtr->VerboseParam())
|
|
{ (void)QTSS_Write(inParams->inRTSPRequest, ";URL=", strlen(";URL="), NULL, 0);
|
|
if (urlPtr) (void)QTSS_Write(inParams->inRTSPRequest, urlPtr->Ptr, urlPtr->Len, NULL, 0);
|
|
}
|
|
if (sQueryPtr->DebugParam())
|
|
{
|
|
(void)QTSS_Write(inParams->inRTSPRequest, ";", strlen(";"), NULL, 0);
|
|
(void)QTSS_Write(inParams->inRTSPRequest, evalMessagePtr->Ptr, evalMessagePtr->Len, NULL, 0);
|
|
}
|
|
(void)QTSS_Write(inParams->inRTSPRequest, "\r\n\r\n", 4, NULL, 0);
|
|
}
|
|
}
|
|
|
|
|
|
inline Bool16 AcceptAddress(StrPtrLen *theAddressPtr)
|
|
{
|
|
IPComponentStr ipComponentStr(theAddressPtr);
|
|
|
|
Bool16 isLocalRequest = ipComponentStr.IsLocal();
|
|
if (sLocalLoopBackOnlyEnabled && isLocalRequest)
|
|
return true;
|
|
|
|
if (sLocalLoopBackOnlyEnabled && !isLocalRequest)
|
|
return false;
|
|
|
|
if (QTSSModuleUtils::AddressInList(sModulePrefs, sIPAccessListID, theAddressPtr))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
inline Bool16 IsAdminRequest(StringParser *theFullRequestPtr)
|
|
{
|
|
Bool16 handleRequest = false;
|
|
if (theFullRequestPtr != NULL) do
|
|
{
|
|
StrPtrLen strPtr;
|
|
theFullRequestPtr->ConsumeWord(&strPtr);
|
|
if ( !strPtr.Equal(StrPtrLen("GET")) ) break; //it's a "Get" request
|
|
|
|
theFullRequestPtr->ConsumeWhitespace();
|
|
if ( !theFullRequestPtr->Expect('/') ) break;
|
|
|
|
theFullRequestPtr->ConsumeWord(&strPtr);
|
|
if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("modules") ) ) break;
|
|
if (!theFullRequestPtr->Expect('/') ) break;
|
|
|
|
theFullRequestPtr->ConsumeWord(&strPtr);
|
|
if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("admin") ) ) break;
|
|
handleRequest = true;
|
|
|
|
} while (false);
|
|
|
|
return handleRequest;
|
|
}
|
|
|
|
inline void ParseAuthNameAndPassword(StrPtrLen *codedStrPtr, StrPtrLen* namePtr, StrPtrLen* passwordPtr)
|
|
{
|
|
|
|
if (!codedStrPtr || (codedStrPtr->Len >= kAuthNameAndPasswordBuffSize) )
|
|
{ return;
|
|
}
|
|
|
|
StrPtrLen codedLineStr;
|
|
StrPtrLen nameAndPassword;
|
|
memset(decodedLine,0,kAuthNameAndPasswordBuffSize);
|
|
memset(codedLine,0,kAuthNameAndPasswordBuffSize);
|
|
|
|
memcpy (codedLine,codedStrPtr->Ptr,codedStrPtr->Len);
|
|
codedLineStr.Set((char*) codedLine, codedStrPtr->Len);
|
|
(void) Base64decode(decodedLine, codedLineStr.Ptr);
|
|
|
|
nameAndPassword.Set((char*) decodedLine, strlen(decodedLine));
|
|
StringParser parsedNameAndPassword(&nameAndPassword);
|
|
|
|
parsedNameAndPassword.ConsumeUntil(namePtr,':');
|
|
parsedNameAndPassword.ConsumeLength(NULL, 1);
|
|
|
|
// password can have whitespace, so read until the end of the line, not just until whitespace
|
|
parsedNameAndPassword.ConsumeUntil(passwordPtr, StringParser::sEOLMask);
|
|
|
|
namePtr->Ptr[namePtr->Len]= 0;
|
|
passwordPtr->Ptr[passwordPtr->Len]= 0;
|
|
|
|
//qtss_printf("decoded nameAndPassword="); PRINT_STR(&nameAndPassword);
|
|
//qtss_printf("decoded name="); PRINT_STR(namePtr);
|
|
//qtss_printf("decoded password="); PRINT_STR(passwordPtr);
|
|
|
|
return;
|
|
};
|
|
|
|
|
|
inline Bool16 OSXAuthenticate(StrPtrLen *keyStrPtr)
|
|
{
|
|
#if __MacOSX__
|
|
// Authorization: AuthRef QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
|
Bool16 result = false;
|
|
|
|
if (keyStrPtr == NULL || keyStrPtr->Len == 0)
|
|
return result;
|
|
|
|
char *encodedKey = keyStrPtr->GetAsCString();
|
|
OSCharArrayDeleter encodedKeyDeleter(encodedKey);
|
|
|
|
char *decodedKey = NEW char[Base64decode_len(encodedKey) + 1];
|
|
OSCharArrayDeleter decodedKeyDeleter(decodedKey);
|
|
|
|
(void) Base64decode(decodedKey, encodedKey);
|
|
|
|
AuthorizationExternalForm *receivedExtFormPtr = (AuthorizationExternalForm *) decodedKey;
|
|
AuthorizationRef receivedAuthorization;
|
|
OSStatus status = AuthorizationCreateFromExternalForm(receivedExtFormPtr, &receivedAuthorization);
|
|
|
|
if (status != errAuthorizationSuccess)
|
|
return result;
|
|
|
|
status = AuthorizationCopyRights(receivedAuthorization, &sRightSet, kAuthorizationEmptyEnvironment, kAuthorizationFlagExtendRights , NULL);
|
|
if (status == errAuthorizationSuccess)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
AuthorizationFree(receivedAuthorization, kAuthorizationFlagDestroyRights);
|
|
|
|
return result;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
inline Bool16 HasAuthentication(StringParser *theFullRequestPtr, StrPtrLen* namePtr, StrPtrLen* passwordPtr, StrPtrLen* outAuthTypePtr)
|
|
{
|
|
// Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
|
Bool16 hasAuthentication = false;
|
|
StrPtrLen strPtr;
|
|
StrPtrLen authType;
|
|
StrPtrLen authString;
|
|
while (theFullRequestPtr->GetDataRemaining() > 0)
|
|
{
|
|
theFullRequestPtr->ConsumeWhitespace();
|
|
theFullRequestPtr->ConsumeUntilWhitespace(&strPtr);
|
|
if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("Authorization:")) )
|
|
continue;
|
|
|
|
theFullRequestPtr->ConsumeWhitespace();
|
|
theFullRequestPtr->ConsumeUntilWhitespace(&authType);
|
|
if ( authType.Len == 0 )
|
|
continue;
|
|
|
|
theFullRequestPtr->ConsumeWhitespace();
|
|
theFullRequestPtr->ConsumeUntil(&authString, StringParser::sEOLMask);
|
|
if ( authString.Len == 0 )
|
|
continue;
|
|
|
|
if (outAuthTypePtr != NULL)
|
|
outAuthTypePtr->Set(authType.Ptr, authType.Len);
|
|
|
|
if (authType.Equal(StrPtrLen("Basic") ) )
|
|
{
|
|
(void) ParseAuthNameAndPassword(&authString,namePtr, passwordPtr);
|
|
if (namePtr->Len == 0)
|
|
continue;
|
|
|
|
hasAuthentication = true;
|
|
break;
|
|
}
|
|
else if (authType.Equal(sAuthRef) )
|
|
{
|
|
namePtr->Set(NULL,0);
|
|
passwordPtr->Set(authString.Ptr, authString.Len);
|
|
hasAuthentication = true;
|
|
break;
|
|
}
|
|
|
|
|
|
};
|
|
|
|
return hasAuthentication;
|
|
}
|
|
|
|
Bool16 Authenticate(QTSS_RTSPRequestObject request, StrPtrLen* namePtr, StrPtrLen* passwordPtr)
|
|
{
|
|
Bool16 authenticated = true;
|
|
|
|
char* authName = namePtr->GetAsCString();
|
|
OSCharArrayDeleter authNameDeleter(authName);
|
|
|
|
QTSS_ActionFlags authAction = qtssActionFlagsAdmin;
|
|
|
|
// authenticate callback to retrieve the password
|
|
QTSS_Error err = QTSS_Authenticate(authName, sAuthResourceLocalPath, sAuthResourceLocalPath, authAction, qtssAuthBasic, request);
|
|
if (err != QTSS_NoErr) {
|
|
return false; // Couldn't even call QTSS_Authenticate...abandon!
|
|
}
|
|
|
|
// Get the user profile object from the request object that was created in the authenticate callback
|
|
QTSS_UserProfileObject theUserProfile = NULL;
|
|
UInt32 len = sizeof(QTSS_UserProfileObject);
|
|
err = QTSS_GetValue(request, qtssRTSPReqUserProfile, 0, (void*)&theUserProfile, &len);
|
|
Assert(len == sizeof(QTSS_UserProfileObject));
|
|
if (err != QTSS_NoErr)
|
|
authenticated = false;
|
|
|
|
if(err == QTSS_NoErr) {
|
|
char* reqPassword = passwordPtr->GetAsCString();
|
|
OSCharArrayDeleter reqPasswordDeleter(reqPassword);
|
|
char* userPassword = NULL;
|
|
(void) QTSS_GetValueAsString(theUserProfile, qtssUserPassword, 0, &userPassword);
|
|
OSCharArrayDeleter userPasswordDeleter(userPassword);
|
|
|
|
if(userPassword == NULL) {
|
|
authenticated = false;
|
|
}
|
|
else {
|
|
#ifdef __Win32__
|
|
// The password is md5 encoded for win32
|
|
char md5EncodeResult[120];
|
|
MD5Encode(reqPassword, userPassword, md5EncodeResult, sizeof(md5EncodeResult));
|
|
if(::strcmp(userPassword, md5EncodeResult) != 0)
|
|
authenticated = false;
|
|
#else
|
|
if(::strcmp(userPassword, (char*)crypt(reqPassword, userPassword)) != 0)
|
|
authenticated = false;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
char* realm = NULL;
|
|
Bool16 allowed = true;
|
|
//authorize callback to check authorization
|
|
// allocates memory for realm
|
|
err = QTSS_Authorize(request, &realm, &allowed);
|
|
// QTSS_Authorize allocates memory for the realm string
|
|
// we don't use the realm returned by the callback, but instead
|
|
// use our own.
|
|
// delete the memory allocated for realm because we don't need it!
|
|
OSCharArrayDeleter realmDeleter(realm);
|
|
|
|
if(err != QTSS_NoErr) {
|
|
qtss_printf("QTSSAdminModule::Authenticate: QTSS_Authorize failed\n");
|
|
return false; // Couldn't even call QTSS_Authorize...abandon!
|
|
}
|
|
|
|
if(authenticated && allowed)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
QTSS_Error AuthorizeAdminRequest(QTSS_RTSPRequestObject request)
|
|
{
|
|
Bool16 allowed = false;
|
|
|
|
// get the resource path
|
|
// if the path does not match the admin path, don't handle the request
|
|
char* resourcePath = QTSSModuleUtils::GetLocalPath_Copy(request);
|
|
OSCharArrayDeleter resourcePathDeleter(resourcePath);
|
|
|
|
if(strcmp(sAuthResourceLocalPath, resourcePath) != 0)
|
|
return QTSS_NoErr;
|
|
|
|
// get the type of request
|
|
QTSS_ActionFlags action = QTSSModuleUtils::GetRequestActions(request);
|
|
if(!(action & qtssActionFlagsAdmin))
|
|
return QTSS_RequestFailed;
|
|
|
|
QTSS_UserProfileObject theUserProfile = QTSSModuleUtils::GetUserProfileObject(request);
|
|
if (NULL == theUserProfile)
|
|
return QTSS_RequestFailed;
|
|
|
|
(void) QTSS_SetValue(request,qtssRTSPReqURLRealm, 0, sAuthRealm, ::strlen(sAuthRealm));
|
|
|
|
// Authorize the user if the user belongs to the AdministratorGroup (this is an admin module pref)
|
|
UInt32 numGroups = 0;
|
|
char** groupsArray = QTSSModuleUtils::GetGroupsArray_Copy(theUserProfile, &numGroups);
|
|
|
|
if ((groupsArray != NULL) && (numGroups != 0))
|
|
{
|
|
UInt32 index = 0;
|
|
for (index = 0; index < numGroups; index++)
|
|
{
|
|
if(strcmp(sAdministratorGroup, groupsArray[index]) == 0)
|
|
{
|
|
allowed = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// delete the memory allocated in QTSSModuleUtils::GetGroupsArray_Copy call
|
|
delete [] groupsArray;
|
|
}
|
|
|
|
if(!allowed)
|
|
{
|
|
if (QTSS_NoErr != QTSS_SetValue(request,qtssRTSPReqUserAllowed, 0, &allowed, sizeof(allowed)))
|
|
return QTSS_RequestFailed; // Bail on the request. The Server will handle the error
|
|
}
|
|
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
|
|
Bool16 AcceptSession(QTSS_RTSPSessionObject inRTSPSession)
|
|
{
|
|
char remoteAddress[20] = {0};
|
|
StrPtrLen theClientIPAddressStr(remoteAddress,sizeof(remoteAddress));
|
|
QTSS_Error err = QTSS_GetValue(inRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void*)theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len);
|
|
if (err != QTSS_NoErr) return false;
|
|
|
|
return AcceptAddress(&theClientIPAddressStr);
|
|
}
|
|
|
|
Bool16 StillFlushing(QTSS_Filter_Params* inParams,Bool16 flushing)
|
|
{
|
|
|
|
QTSS_Error err = QTSS_NoErr;
|
|
if (flushing)
|
|
{
|
|
err = QTSS_Flush(inParams->inRTSPRequest);
|
|
//qtss_printf("Flushing session=%"_U32BITARG_" QTSS_Flush err =%"_S32BITARG_"\n",sSessID,err);
|
|
}
|
|
if (err == QTSS_WouldBlock) // more to flush later
|
|
{
|
|
sFlushing = true;
|
|
(void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen);
|
|
err = QTSS_RequestEvent(inParams->inRTSPRequest, QTSS_WriteableEvent);
|
|
KeepSession(inParams->inRTSPRequest,true);
|
|
//qtss_printf("Flushing session=%"_U32BITARG_" QTSS_RequestEvent err =%"_S32BITARG_"\n",sSessID,err);
|
|
}
|
|
else
|
|
{
|
|
sFlushing = false;
|
|
(void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen);
|
|
KeepSession(inParams->inRTSPRequest,false);
|
|
|
|
if (flushing) // we were flushing so reset the LastRequestTime
|
|
{
|
|
sLastRequestTime = QTSS_Milliseconds();
|
|
//qtss_printf("Done Flushing session=%"_U32BITARG_"\n",sSessID);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return sFlushing;
|
|
}
|
|
|
|
Bool16 IsAuthentic(QTSS_Filter_Params* inParams,StringParser *fullRequestPtr)
|
|
{
|
|
Bool16 isAuthentic = false;
|
|
|
|
if (!sAuthenticationEnabled) // no authentication
|
|
{
|
|
isAuthentic = true;
|
|
}
|
|
else // must authenticate
|
|
{
|
|
StrPtrLen theClientIPAddressStr;
|
|
(void) QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void**)&theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len);
|
|
Bool16 isLocal = IPComponentStr(&theClientIPAddressStr).IsLocal();
|
|
|
|
StrPtrLen authenticateName;
|
|
StrPtrLen authenticatePassword;
|
|
StrPtrLen authType;
|
|
Bool16 hasAuthentication = HasAuthentication(fullRequestPtr,&authenticateName,&authenticatePassword, &authType);
|
|
if (hasAuthentication)
|
|
{
|
|
if (authType.Equal(sAuthRef))
|
|
{
|
|
if (isLocal)
|
|
isAuthentic = OSXAuthenticate(&authenticatePassword);
|
|
}
|
|
else
|
|
isAuthentic = Authenticate(inParams->inRTSPRequest, &authenticateName,&authenticatePassword);
|
|
}
|
|
}
|
|
// if (isAuthentic)
|
|
// isAuthentic = AuthorizeAdminRequest(inParams->inRTSPRequest);
|
|
(void) QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&isAuthentic, sizeof(isAuthentic));
|
|
|
|
return isAuthentic;
|
|
}
|
|
|
|
inline Bool16 InWaitInterval(QTSS_Filter_Params* inParams)
|
|
{
|
|
QTSS_TimeVal nextExecuteTime = sLastRequestTime + sRequestTimeIntervalMilli;
|
|
QTSS_TimeVal currentTime = QTSS_Milliseconds();
|
|
SInt32 waitTime = 0;
|
|
if (currentTime < nextExecuteTime)
|
|
{
|
|
waitTime = (SInt32) (nextExecuteTime - currentTime) + 1;
|
|
//qtss_printf("(currentTime < nextExecuteTime) sSessID = %"_U32BITARG_" waitTime =%"_S32BITARG_" currentTime = %qd nextExecute = %qd interval=%"_U32BITARG_"\n",sSessID, waitTime, currentTime, nextExecuteTime,sRequestTimeIntervalMilli);
|
|
(void)QTSS_SetIdleTimer(waitTime);
|
|
KeepSession(inParams->inRTSPRequest,true);
|
|
|
|
//qtss_printf("-- call me again after %"_S32BITARG_" millisecs session=%"_U32BITARG_" \n",waitTime,sSessID);
|
|
return true;
|
|
}
|
|
sLastRequestTime = QTSS_Milliseconds();
|
|
//qtss_printf("handle sessID=%"_U32BITARG_" time=%qd \n",sSessID,currentTime);
|
|
return false;
|
|
}
|
|
|
|
inline void GetQueryData(QTSS_RTSPRequestObject theRequest)
|
|
{
|
|
sAdminPtr = NEW AdminClass();
|
|
Assert(sAdminPtr != NULL);
|
|
if (sAdminPtr == NULL)
|
|
{ //qtss_printf ("NEW AdminClass() failed!! \n");
|
|
return;
|
|
}
|
|
if (sAdminPtr != NULL)
|
|
{
|
|
sAdminPtr->Initialize(&sQTSSparams,sQueryPtr); // Get theData
|
|
}
|
|
}
|
|
|
|
inline void SendHeader(QTSS_StreamRef inStream)
|
|
{
|
|
(void)QTSS_Write(inStream, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);
|
|
(void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);
|
|
(void)QTSS_Write(inStream, sVersionHeader, ::strlen(sVersionHeader), NULL, 0);
|
|
(void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);
|
|
(void)QTSS_Write(inStream, sConnectionHeader, ::strlen(sConnectionHeader), NULL, 0);
|
|
(void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);
|
|
(void)QTSS_Write(inStream, sContentType, ::strlen(sContentType), NULL, 0);
|
|
(void)QTSS_Write(inStream, sEOM, ::strlen(sEOM), NULL, 0);
|
|
}
|
|
|
|
inline void SendResult(QTSS_StreamRef inStream)
|
|
{
|
|
SendHeader(inStream);
|
|
if (sAdminPtr != NULL)
|
|
sAdminPtr->RespondToQuery(inStream,sQueryPtr,sQueryPtr->GetRootID());
|
|
|
|
}
|
|
|
|
inline Bool16 GetRequestAuthenticatedState(QTSS_Filter_Params* inParams)
|
|
{
|
|
Bool16 result = false;
|
|
UInt32 paramLen = sizeof(result);
|
|
QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, ¶mLen);
|
|
if(err != QTSS_NoErr)
|
|
{
|
|
paramLen = sizeof(result);
|
|
result = false;
|
|
err =QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, paramLen);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
inline Bool16 GetRequestFlushState(QTSS_Filter_Params* inParams)
|
|
{ Bool16 result = false;
|
|
UInt32 paramLen = sizeof(result);
|
|
QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, ¶mLen);
|
|
if (err != QTSS_NoErr)
|
|
{ paramLen = sizeof(result);
|
|
result = false;
|
|
//qtss_printf("no flush val so set to false session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err);
|
|
err =QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, paramLen);
|
|
//qtss_printf("QTSS_SetValue flush session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
|
|
{
|
|
if (NULL == inParams || NULL == inParams->inRTSPSession || NULL == inParams->inRTSPRequest)
|
|
{ Assert(0);
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
OSMutexLocker locker(sAdminMutex);
|
|
//check to see if we should handle this request. Invokation is triggered
|
|
//by a "GET /" request
|
|
|
|
QTSS_Error err = QTSS_NoErr;
|
|
QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
|
|
|
|
UInt32 paramLen = sizeof(sSessID);
|
|
err = QTSS_GetValue(inParams->inRTSPSession, qtssRTSPSesID, 0, (void*)&sSessID, ¶mLen);
|
|
if (err != QTSS_NoErr)
|
|
return QTSS_NoErr;
|
|
|
|
StrPtrLen theFullRequest;
|
|
err = QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
|
|
if (err != QTSS_NoErr)
|
|
return QTSS_NoErr;
|
|
|
|
|
|
StringParser fullRequest(&theFullRequest);
|
|
|
|
if ( !IsAdminRequest(&fullRequest) )
|
|
return QTSS_NoErr;
|
|
|
|
if ( !AcceptSession(inParams->inRTSPSession) )
|
|
{ (void)QTSS_Write(inParams->inRTSPRequest, sPermissionDeniedHeader, ::strlen(sPermissionDeniedHeader), NULL, 0);
|
|
(void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
|
|
KeepSession(theRequest,false);
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
if(!GetRequestAuthenticatedState(inParams)) // must authenticate before handling
|
|
{
|
|
if(QTSS_IsGlobalLocked()) // must NOT be global locked
|
|
return QTSS_RequestFailed;
|
|
|
|
if (!IsAuthentic(inParams,&fullRequest))
|
|
{
|
|
(void)QTSS_Write(inParams->inRTSPRequest, sUnauthorizedResponseHeader, ::strlen(sUnauthorizedResponseHeader), NULL, 0);
|
|
(void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
|
|
KeepSession(theRequest,false);
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
}
|
|
|
|
if (GetRequestFlushState(inParams))
|
|
{ StillFlushing(inParams,true);
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
if (!QTSS_IsGlobalLocked())
|
|
{
|
|
if (InWaitInterval(inParams))
|
|
return QTSS_NoErr;
|
|
|
|
//qtss_printf("New Request Wait for GlobalLock session=%"_U32BITARG_"\n",sSessID);
|
|
(void)QTSS_RequestGlobalLock();
|
|
KeepSession(theRequest,true);
|
|
return QTSS_NoErr;
|
|
}
|
|
|
|
//qtss_printf("Handle request session=%"_U32BITARG_"\n",sSessID);
|
|
APITests_DEBUG();
|
|
|
|
if (sQueryPtr != NULL)
|
|
{ delete sQueryPtr;
|
|
sQueryPtr = NULL;
|
|
}
|
|
sQueryPtr = NEW QueryURI(&theFullRequest);
|
|
if (sQueryPtr == NULL) return QTSS_NoErr;
|
|
|
|
ShowQuery_DEBUG();
|
|
|
|
if (sAdminPtr != NULL)
|
|
{ delete sAdminPtr;
|
|
sAdminPtr = NULL;
|
|
}
|
|
UInt32 result = sQueryPtr->EvalQuery(NULL, NULL);
|
|
if (result == 0) do
|
|
{
|
|
if( ElementNode_CountPtrs() > 0)
|
|
{ ElementNode_ShowPtrs();
|
|
Assert(0);
|
|
}
|
|
|
|
GetQueryData(theRequest);
|
|
|
|
SendResult(theRequest);
|
|
delete sAdminPtr;
|
|
sAdminPtr = NULL;
|
|
|
|
if (sQueryPtr && !sQueryPtr->QueryHasReponse())
|
|
{ UInt32 err = 404;
|
|
(void) sQueryPtr->EvalQuery(&err,NULL);
|
|
ReportErr(inParams, err);
|
|
break;
|
|
}
|
|
|
|
if (sQueryPtr && sQueryPtr->QueryHasReponse())
|
|
{ ReportErr(inParams, sQueryPtr->GetEvaluResult());
|
|
}
|
|
|
|
if (sQueryPtr->fIsPref && sQueryPtr->GetEvaluResult() == 0)
|
|
{ QTSS_ServiceID id;
|
|
(void) QTSS_IDForService(QTSS_REREAD_PREFS_SERVICE, &id);
|
|
(void) QTSS_DoService(id, NULL);
|
|
}
|
|
} while(false);
|
|
else
|
|
{
|
|
SendHeader(theRequest);
|
|
ReportErr(inParams, sQueryPtr->GetEvaluResult());
|
|
}
|
|
|
|
if (sQueryPtr != NULL)
|
|
{ delete sQueryPtr;
|
|
sQueryPtr = NULL;
|
|
}
|
|
|
|
(void) StillFlushing(inParams,true);
|
|
return QTSS_NoErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|