Example #1
0
void PrintStatus(Bool16 printHeader)
{
    char* thePrefStr = NULL;
    UInt32 theLen = 0;
    
    if ( printHeader )
    {                       
        qtss_printf("     RTP-Conns RTSP-Conns HTTP-Conns  kBits/Sec   Pkts/Sec    TotConn     TotBytes   TotPktsLost          Time\n");   
    }

    (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    UInt32 curBandwidth = 0;
    theLen = sizeof(curBandwidth);
    (void)QTSS_GetValue(sServer, qtssRTPSvrCurBandwidth, 0, &curBandwidth, &theLen);
    qtss_printf("%11"_U32BITARG_, curBandwidth/1024);
    
    (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurPackets, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalConn, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    UInt64 totalBytes = sServer->GetTotalRTPBytes();
    char  displayBuff[32] = "";
    FormattedTotalBytesBuffer(displayBuff, sizeof(displayBuff),totalBytes);
    qtss_printf( "%17s", displayBuff);
    
    qtss_printf( "%11"_64BITARG_"u", sServer->GetTotalRTPPacketsLost());
                    
    char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
    (void) QTSSRollingLog::FormatDate(theDateBuffer, false);
    qtss_printf( "%25s",theDateBuffer);
    
    qtss_printf( "\n");
    
}
char* EasyAdmin_GetMoviesFolder()
{
    char* movieFolderString = NULL;
    (void) QTSS_GetValueAsString (sServerPrefs, qtssPrefsMovieFolder, 0, &movieFolderString);
    
	return movieFolderString;
}
char* EasyAdmin_GetErrorLogFolder()
{
    char* logFolderString = NULL;
    (void) QTSS_GetValueAsString (sServerPrefs, qtssPrefsErrorLogDir, 0, &logFolderString);
    
	return logFolderString;
}
Example #4
0
void DebugLevel_1(FILE*   statusFile, FILE*   stdOut,  Bool16 printHeader )
{
    char*  thePrefStr = NULL;
    static char numStr[12] ="";
    static char dateStr[25] ="";
    UInt32 theLen = 0;

    if ( printHeader )
    {                   
        printf("****************************************");
	}
       
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssCurrentSessionCount, 0, &thePrefStr);
    print_status(statusFile, stdOut,"%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;

    qtss_snprintf(numStr,sizeof(numStr) -1, "%"  _U32BITARG_  "", (SInt32) sServer->GetNumThinned() );
    print_status(statusFile, stdOut,"%11s", numStr);
 
    char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
    (void) QTSSRollingLog::FormatDate(theDateBuffer, false);
    
    qtss_snprintf(dateStr,sizeof(dateStr) -1, "%s", theDateBuffer );
    print_status(statusFile, stdOut,"%24s\n", dateStr);
}
/**
 * This is called when a clients session ends - use this to update services
 */
static QTSS_Error ClientSessionClosing(QTSS_ClientSessionClosing_Params* inParams) {
    QTSS_ClientSessionObject theClientSession = inParams->inClientSession;
    
    printf("QTSSIcecastAuthModule::ClientSessionClosing called"); 
    
//    QTSS_TimeVal clientSessCreateTime = NULL;
//    UInt32 createTimeLen = sizeof(clientSessCreateTime);
//    QTSS_GetValue(theClientSession, qtssCliSesCreateTimeInMsec, 0, (void*)&clientSessCreateTime, &createTimeLen); 
//    printf("QTSSIcecastAuthModule::ClientSessionClosing: Client session start time (millis): %ld\n", (long)clientSessCreateTime);

    char* iceSessID = NULL;
    QTSS_Error getSessErr = QTSS_GetValueAsString(theClientSession, attrClientSessionFullSessionID, 0, &iceSessID);
    if (getSessErr == QTSS_ValueNotFound) {
        // this client session doesn't have a session ID, therefore probably came in via
        // the IP exclusion list. Ignore
        printf("QTSSIcecastAuthModule::ClientSessionClosing: session ID not found. probably in exclusion list.\n");
    }
    else {
        // handle the session closing.
        printf("QTSSIcecastAuthModule::ClientSessionClosing: the full session ID: %s\n", iceSessID);
        CallEndSession(&theClientSession);
    }
    

    return QTSS_NoErr;
}
void DoDescribeAddRequiredSDPLines2(QTSS_StandardRTSP_Params* inParams, ReflectorSession* theSession, QTSS_TimeVal modDate,  ResizeableStringFormatter *editedSDP, StrPtrLen* theSDPPtr)
{
    SDPContainer checkedSDPContainer;
    checkedSDPContainer.SetSDPBuffer( theSDPPtr );  
    if (!checkedSDPContainer.HasReqLines())
    {
        if (!checkedSDPContainer.HasLineType('v'))
        { // add v line
            editedSDP->Put("v=0\r\n");
        }
        
        if (!checkedSDPContainer.HasLineType('s'))
        { // add s line
           char* theSDPName = NULL;            
            (void)QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFilePath, 0, &theSDPName);
            QTSSCharArrayDeleter thePathStrDeleter(theSDPName);
            editedSDP->Put("s=");
            editedSDP->Put(theSDPName);
            editedSDP->PutEOL();
        }
        
       if (!checkedSDPContainer.HasLineType('t'))
       { // add t line
            editedSDP->Put("t=0 0\r\n");
       }

       if (!checkedSDPContainer.HasLineType('o'))
       { // add o line
            editedSDP->Put("o=broadcast_sdp ");
            char tempBuff[256]= "";               
            tempBuff[255] = 0;
            qtss_snprintf(tempBuff,sizeof(tempBuff) - 1, "%lu", (UInt64) theSession);
            editedSDP->Put(tempBuff);

            editedSDP->Put(" ");
            // modified date is in milliseconds.  Convert to NTP seconds as recommended by rfc 2327
            qtss_snprintf(tempBuff, sizeof(tempBuff) - 1, "%"_64BITARG_"d", (SInt64) (modDate/1000) + 2208988800LU);
            editedSDP->Put(tempBuff);

            editedSDP->Put(" IN IP4 ");
            UInt32 buffLen = sizeof(tempBuff) -1;
            (void)QTSS_GetValue(inParams->inClientSession, qtssCliSesHostName, 0, &tempBuff, &buffLen);
            editedSDP->Put(tempBuff, buffLen);

            editedSDP->PutEOL();
        }
    } 
    editedSDP->Put(*theSDPPtr);
}
Example #7
0
void PrintStatus(Bool16 printHeader)
{
    char* thePrefStr = NULL;
    UInt32 theLen = 0;

    (void)QTSS_GetValueAsString(sServer, qtssCurrentSessionCount, 0, &thePrefStr);
    qtss_printf( "%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;

	//获取当前时间
    char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
    (void) QTSSRollingLog::FormatDate(theDateBuffer, false);
    qtss_printf( "%25s",theDateBuffer);

    qtss_printf( "\n");
}
QTSS_Error DoDescribe(QTSS_StandardRTSP_Params* inParams)
{
	char* theUriStr = NULL;
    QTSS_Error err = QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFileName, 0, &theUriStr);
    Assert(err == QTSS_NoErr);
    if(err != QTSS_NoErr)
		return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest, 0);
    QTSSCharArrayDeleter theUriStrDeleter(theUriStr);

	//从接口获取信息结构体

	//信息存在rtsp://59.46.115.84:8554/h264/ch1/sub/av_stream
	RTSPRelaySession* clientSes = NULL;
	//首先查找Map里面是否已经有了对应的流
	StrPtrLen streamName(theUriStr);
	OSRef* clientSesRef = sRelaySessionMap->Resolve(&streamName);
	if(clientSesRef != NULL)
	{
		clientSes = (RTSPRelaySession*)clientSesRef->GetObject();
	}
	else
	{
		clientSes = NEW RTSPRelaySession("rtsp://*****:*****@192.168.66.189/", RTSPRelaySession::kRTSPTCPClientType, theUriStr);


		QTSS_Error theErr = clientSes->SendDescribe();

		if(theErr == QTSS_NoErr)
		{
			OS_Error theErr = sRelaySessionMap->Register(clientSes->GetRef());
			Assert(theErr == QTSS_NoErr);
		}
		else
		{
			clientSes->Signal(Task::kKillEvent);
			return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); 
		}

		//增加一次对RelaySession的无效引用,后面会统一释放
		OSRef* debug = sRelaySessionMap->Resolve(&streamName);
		Assert(debug == clientSes->GetRef());
	}

    return QTSS_NoErr;
}
QTSS_Error RereadPrefs()
{
	delete[] sDefaultLogDir;
	(void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogDir, 0, &sDefaultLogDir);

	QTSSModuleUtils::GetAttribute(sPrefs, "request_logging", qtssAttrDataTypeBool16,
		&sLogEnabled, &sDefaultLogEnabled, sizeof(sLogEnabled));
	QTSSModuleUtils::GetAttribute(sPrefs, "request_logfile_size", qtssAttrDataTypeUInt32,
		&sMaxLogBytes, &sDefaultMaxLogBytes, sizeof(sMaxLogBytes));
	QTSSModuleUtils::GetAttribute(sPrefs, "request_logfile_interval", qtssAttrDataTypeUInt32,
		&sRollInterval, &sDefaultRollInterval, sizeof(sRollInterval));
	QTSSModuleUtils::GetAttribute(sPrefs, "request_logtime_in_gmt", qtssAttrDataTypeBool16,
		&sLogTimeInGMT, &sDefaultLogTimeInGMT, sizeof(sLogTimeInGMT));

	CheckAccessLogState(false);

	return QTSS_NoErr;
}
Example #10
0
char*   QTSSModuleUtils::GetStringAttribute(QTSS_Object inObject, char* inAttributeName, char* inDefaultValue)
{
    UInt32 theDefaultValLen = 0;
    if (inDefaultValue != NULL)
        theDefaultValLen = ::strlen(inDefaultValue);
    
    //
    // Check to make sure this attribute is the right type. If it's not, this will coerce
    // it to be the right type
    QTSS_AttributeID theID = QTSSModuleUtils::CheckAttributeDataType(inObject, inAttributeName, qtssAttrDataTypeCharArray, inDefaultValue, theDefaultValLen);

    char* theString = NULL;
    (void)QTSS_GetValueAsString(inObject, theID, 0, &theString);
    if (theString != NULL)
        return theString;
    
    //
    // If we get here the attribute must be missing, so create it and log
    // an error.
    
    QTSSModuleUtils::CreateAttribute(inObject, inAttributeName, qtssAttrDataTypeCharArray, inDefaultValue, theDefaultValLen);
    
    //
    // Return the default if it was provided. Only log an error if the default value was provided
    if (theDefaultValLen > 0)
    {
        QTSSModuleUtils::LogError(  sMissingPrefVerbosity,
                                    qtssServerPrefMissing,
                                    0,
                                    inAttributeName,
                                    inDefaultValue);
    }
    
    if (inDefaultValue != NULL)
    {
        //
        // Whether to return the default value or not from this function is dependent
        // solely on whether the caller passed in a non-NULL pointer or not.
        // This ensures that if the caller wants an empty-string returned as a default
        // value, it can do that.
        theString = NEW char[theDefaultValLen + 1];
        ::strcpy(theString, inDefaultValue);
        return theString;
    }
static void CallEndSession(QTSS_ClientSessionObject* theClientSession) {
    // action=listener_remove&server=myserver.com&port=8000&client=1&mount=/live&user=&pass=&duration=3600
    
    // the duration
    SInt64* connectedTime = NULL;
    UInt32 connectedTimeLen = sizeof(connectedTime);
    (void)QTSS_GetValuePtr(*theClientSession, qtssCliSesTimeConnectedInMsec, 0, (void**)&connectedTime, &connectedTimeLen);
    qtss_printf("QTSSIcecastAuthModule::CallEndSession connected time in seconds %li\n", (*connectedTime / 1000));
    long duration = (long)*connectedTime / 1000;
    
    // the mount point
    char mountPoint[128] = {0};
    StrPtrLen mountPointStr(mountPoint,sizeof(mountPoint));
    (void)QTSS_GetValue(*theClientSession, attrClientSessionMountPoint, 0, (void*)mountPointStr.Ptr, &mountPointStr.Len);
    printf("QTSSIcecastAuthModule::CallEndSession: mount point: %s\n", mountPoint);
    
    
    // TODO - we don't use this data on the remote end (yet), but implement - will probably need to copy 
    // credentials into the client session from the RTSP session (annoying, but both aren't visible at all times)
//    // username and password
//    char* username = NULL;
//    (void)QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedUsername, 0,  &username);
//    printf("QTSSIcecastAuthModule::CallEndSession: Provided username extracted from client session: %s\n", username);
//    
//    char* password = NULL;
//    (void)QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedPassword, 0,  &password);
//    printf("QTSSIcecastAuthModule::CallEndSession: Provided password extracted from client session: %s\n", password);
    
    // ice session id
    char* iceSessID = NULL;
    QTSS_Error getSessErr = QTSS_GetValueAsString(*theClientSession, attrClientSessionFullSessionID, 0, &iceSessID);
    
    char postdata[512];
    
    qtss_sprintf(postdata, "action=listener_remove&server=%s&port=554&client=%s&mount=%s&user=%s&pass=%s&duration=%li",
            hostname, iceSessID, mountPoint, "", "", duration);
    
    
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: generated postdata: %s\n", postdata);
    
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: i would post this to: %s\n", sEndSessionEndpoint);
    
}
Example #12
0
char*   GetPrefAsString(QTSS_ModulePrefsObject inPrefsObject, char* inPrefName)
{
    static StrPtrLen                sEmpty("");

    //
    // Get the attribute ID of this pref.
    QTSS_AttributeID theID = qtssIllegalAttrID;
    
    if(inPrefsObject != NULL) 
        theID = QTSSModuleUtils::GetAttrID(inPrefsObject, inPrefName);  

    char* theString = NULL;
    
    if(inPrefsObject != NULL)
        (void)QTSS_GetValueAsString(inPrefsObject, theID, 0, &theString);
    
    if (theString == NULL)
        theString = sEmpty.GetAsCString();
        
    return theString;
}
Example #13
0
QTSS_Error RereadPrefs()
{
	delete [] sRedis_IP;
    sRedis_IP = QTSSModuleUtils::GetStringAttribute(modulePrefs, "redis_ip", sDefaultRedis_IP_Addr);

	QTSSModuleUtils::GetAttribute(modulePrefs, "redis_port", qtssAttrDataTypeUInt16, &sRedisPort, &sDefaultRedisPort, sizeof(sRedisPort));

	delete [] sRedisUser;
    sRedisUser = QTSSModuleUtils::GetStringAttribute(modulePrefs, "redis_user", sDefaultRedisUser);
	
	delete [] sRedisPassword;
    sRedisPassword = QTSSModuleUtils::GetStringAttribute(modulePrefs, "redis_password", sDefaultRedisPassword);

	//get EasyDarwin ip and port
	delete [] sEasyDarwinIP;
	(void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsEasyDarWinIP, 0, &sEasyDarwinIP);

	UInt32 len = sizeof(SInt32);
	(void) QTSS_GetValue(sServerPrefs, qtssPrefsEasyDarWinPort, 0, (void*)&sEasyDarwinPort, &len);

	return QTSS_NoErr;

}
static Bool16 CallAuthorizeSession(QTSS_ClientSessionObject* theClientSession, QTSS_RTSPSessionObject* theRTSPSession,
        QTSS_RTSPRequestObject* theRTSPRequest, char* username, char* password) {
    qtss_printf("QTSSIcecastAuthModule::CallAuthorizeSession called\n");
    //{ :action => "listener_add", :server => "server", :port => "8000", :client => "sessionidone",
    //  :mount => "somemount.sdp", :user => "lstoll", :pass => @working_hash, :ip => "127.0.0.1", :agent => "RSPEC"}

    // generate the client session id (and save in client) format <start time millis>-<rtsp session id>
    char ice_sessid[128];

    QTSS_TimeVal clientSessCreateTime = NULL;
    UInt32 createTimeLen = sizeof (clientSessCreateTime);
    QTSS_GetValue(*theClientSession, qtssCliSesCreateTimeInMsec, 0, (void*) & clientSessCreateTime, &createTimeLen);

    char* qtssRTSPSesIDString = NULL;
    (void) QTSS_GetValueAsString(*theRTSPSession, qtssRTSPSesID, 0, &qtssRTSPSesIDString);

    sprintf(ice_sessid, "%lld-%s", clientSessCreateTime, qtssRTSPSesIDString);

    printf("QTSSIcecastAuthModule::CallAuthorizeSession generated session id: %s\n", ice_sessid);

    (void) QTSS_SetValue(*theClientSession, attrClientSessionFullSessionID, 0, &ice_sessid, sizeof (ice_sessid));

    // get the user agent
    char* userAgentString = NULL;
    (void) QTSS_GetValueAsString(*theClientSession, qtssCliSesFirstUserAgent, 0, &userAgentString);
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: request user agent: %s\n", userAgentString);
    
    // get the client IP address
    char remoteAddress[20] = {0};
    StrPtrLen theClientIPAddressStr(remoteAddress,sizeof(remoteAddress));
    (void)QTSS_GetValue(*theRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void*)theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len);
    
    // get the mount point
    char mountPoint[128] = {0};
    StrPtrLen mountPointStr(mountPoint,sizeof(mountPoint));
    (void)QTSS_GetValue(*theRTSPRequest, qtssRTSPReqURI, 0, (void*)mountPointStr.Ptr, &mountPointStr.Len);
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: mount point: %s\n", mountPoint);
    // and set it in the client for use on session end
    (void) QTSS_SetValue(*theClientSession, attrClientSessionMountPoint, 0, mountPointStr.Ptr, mountPointStr.Len);
    
    char postdata[512];
    
    qtss_sprintf(postdata, "action=listener_add&server=%s&port=554&client=%s&mount=%s&user=%s&pass=%s&ip=%s&agent%s",
            hostname, ice_sessid, mountPoint, username, password, remoteAddress, userAgentString);
    
    
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: generated postdata: %s\n", postdata);
    
    printf("QTSSIcecastAuthModule::CallAuthorizeSession: i would post this to: %s\n", sStartSessionEndpoint);
    
    return true;
    
//    
//    CURL *easyhandle = NULL; 
//    easyhandle = curl_easy_init();
//    CURLcode curl_code;
//
//    
//    curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, postdata);
//    curl_easy_setopt(easyhandle, CURLOPT_URL, "http://posthere.com/");
//    curl_easy_perform(easyhandle); /* post away! */
//
//    long http_code = 0;
//    curl_easy_getinfo(easyhandle, CURLINFO_HTTP_CODE, &http_code);
//    if (http_code == 200 && curl_code != CURLE_ABORTED_BY_CALLBACK) {
//        // the call to the remote server was OK. pass.
//        return true;
//    } else {
//        return false;
//    }
//    return false;
}
Example #15
0
QTSS_Error AuthenticateRTSPRequest(QTSS_RTSPAuth_Params* inParams)
{
    OSMutexLocker locker(sAuthMutex);

    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
    QTSS_AuthScheme authScheme = qtssAuthNone;
    
    debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest start\n");

    if  ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) )
    {
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest inParams NULL\n");
        return QTSS_RequestFailed;
    }
    
    
    // Get the user profile object from the request object
    QTSS_UserProfileObject theUserProfile = NULL;
    UInt32 len = sizeof(QTSS_UserProfileObject);
    QTSS_Error theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqUserProfile, 0, (void*)&theUserProfile, &len);
    Assert(len == sizeof(QTSS_UserProfileObject));
    if (theErr != QTSS_NoErr)
    {
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username error is %"_S32BITARG_"\n", theErr);
        return theErr;
    }    
    char*   nameBuff = NULL;
    theErr = QTSS_GetValueAsString(theUserProfile, qtssUserName, 0, &nameBuff);
    debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s\n", nameBuff);
    OSCharArrayDeleter usernameBufDeleter(nameBuff);
    if (theErr != QTSS_NoErr)
    {
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - theUserProfile nameBuff error is %"_S32BITARG_"\n", theErr);
    }    


    len = sizeof(authScheme);
    theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqAuthScheme, 0, (void*)&authScheme, &len);
  
    if (theErr != QTSS_NoErr)
        return theErr;
        
	DSAccessChecker accessChecker;
	Bool16 allowed = true;
	Bool16 foundUser = true;
	Bool16 authHandled = true;

    if ( authScheme == qtssAuthDigest)
    {
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - authScheme = qtssAuthDigest\n");

        char*   challengeBuff = NULL;
        (void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqDigestChallenge, 0, &challengeBuff);
        OSCharArrayDeleter challengeDeleter(challengeBuff);
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - Server Challenge =%s\n",challengeBuff);
    
        char*   responseBuff = NULL;
        (void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqDigestResponse, 0, &responseBuff);
        OSCharArrayDeleter responseDeleter(responseBuff);
        
        char*   methodBuff = NULL;
        (void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqMethodStr, 0, &methodBuff);
        OSCharArrayDeleter methodDeleter(methodBuff);
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - Server Method =%s\n",methodBuff);

        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s challenge=%s response=%s method=%s\n", nameBuff, challengeBuff, responseBuff, methodBuff);
        if ( false == accessChecker.CheckDigest(nameBuff, challengeBuff, responseBuff, methodBuff) )
        {    debug_printf("QTSSDSAuthModule CheckDigest returned false\n");
        }
        else
        {   debug_printf("QTSSDSAuthModule CheckDigest returned true\n");
            (void) QTSSModuleUtils::AuthorizeRequest(theRTSPRequest,&allowed,&foundUser,&authHandled);
        }
    
    }
    if ( authScheme == qtssAuthBasic)
    {
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - authScheme = qtssAuthBasic\n");

        
        char passwordBuff[kBuffLen];
        StrPtrLen passwordStr(passwordBuff, kBuffLen -1);
        
        char nameBuff[kBuffLen];
        StrPtrLen nameStr(nameBuff, kBuffLen -1);
    
        theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserName,0, (void *) nameStr.Ptr, &nameStr.Len);
        if ( (QTSS_NoErr != theErr) || (nameStr.Len >= kBuffLen) ) 
        {
            debug_printf("QTSSDSAuthModule:AuthenticateRequest() Username Error - %"_S32BITARG_"\n", theErr);
            return false;    
        }           
        theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserPassword,0, (void *) passwordStr.Ptr, &passwordStr.Len);
        if ( (QTSS_NoErr != theErr) || (passwordStr.Len >= kBuffLen) )
        {
            debug_printf("QTSSDSAuthModule:AuthenticateRequest() Password Error - %"_S32BITARG_"\n", theErr);
        }
        nameBuff[nameStr.Len] = '\0';
        passwordBuff[passwordStr.Len] = '\0';
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s\n", nameBuff);
        debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - password is %s\n", passwordBuff);
        if ( !accessChecker.CheckPassword(nameBuff, passwordBuff) )
        {   debug_printf("QTSSDSAuthModule CheckPassword returned false\n");
        }
        else
        {
            debug_printf("QTSSDSAuthModule CheckPassword returned true\n");
            (void) QTSSModuleUtils::AuthorizeRequest(theRTSPRequest,&allowed,&foundUser,&authHandled);
        }
   
    }
        
    return QTSS_NoErr;
}
/*
 * This method is used to capture the full session ID details, and to reject the session. 
 * The username and password from the query string can't be grabbed here, we need to
 * do that in the Filter. This is called AFTER Filter
 */
QTSS_Error RTSPPreProcess(QTSS_StandardRTSP_Params* inParams) {
    QTSS_Error              theErr = QTSS_NoErr;
    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
    QTSS_RTSPSessionObject  theRTSPSession = inParams->inRTSPSession;
    QTSS_RTSPHeaderObject   theRTSPHeader = inParams->inRTSPHeaders;
    QTSS_ClientSessionObject theClientSession = inParams->inClientSession;

    Bool16 sessionValid = false;
    
    // see if the method is bypassable. if it is, skip processing
    qtss_printf("QTSSIcecastAuthModule::RTSPPreProcess: about to check if the method is bypassable\n");
    if (IsRequestMethodBypassable(&theRTSPRequest)) return QTSS_NoErr;
            
    //  see if the client is in the bypass list. if they are, skip all processing
    if (IsClientInBypassList(&theRTSPSession)) return QTSS_NoErr; 
    
    // check to see if the session is already auth'd. If it is, skip processing
    if (IsRTSPSessionAuthenticated(&theRTSPSession)) {
        printf("QTSSIcecastAuthModule::RTSPPreProcess RTSP session is authenticated, do nothing.\n");
        return QTSS_NoErr; // we are authenticated, don't do anything
    }
        
    
    char* providedUsername = NULL;
    (void)QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedUsername, 0,  &providedUsername);
    printf("QTSSIcecastAuthModule::RTSPPreProcess: Provided username extracted from session: %s\n", providedUsername);
    
    char* providedPassword = NULL;
    (void)QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedPassword, 0,  &providedPassword);
    printf("QTSSIcecastAuthModule::RTSPPreProcess: Provided password extracted from session: %s\n", providedPassword);
    
    // check to see if the username and password have been provided. If they are, process. if not
    // do nothing, we will default to an invalid session
    if (providedUsername != NULL && providedPassword != NULL) {
        
        printf("QTSSIcecastAuthModule::RTSPPreProcess: about to call authorize session\n");
        // if we get to this point we have credentials that need to be validated, so validate them.
        sessionValid = CallAuthorizeSession(&theClientSession, &theRTSPSession, &theRTSPRequest, providedUsername, providedPassword);
        
        
        
        


        // request, qtssRTSPReqFilePath - the mount point (?)
        // request, qtssRTSPReqURI - the request URI (query params parsed from here?)
        // request, qtssRTSPReqAbsoluteURL - the request url with RTSP.
        // request, qtssRTSPReqFullRequest - the full request
        // session, qtssRTSPSesID - the session id

        // note - QTSS_GetValueAsString is the least efficent method - should move to one of the more efficent methods. 
//
//    char* qtssRTSPReqFilePathString = NULL;
//    (void)QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqFilePath, 0,  &qtssRTSPReqFilePathString);
//    printf("QTSSIcecastAuthModule::RTSPPreProcess: request qtssRTSPReqFilePath: %s\n", qtssRTSPReqFilePathString);
//
//        char* qtssRTSPReqURIString = NULL;
//        (void)QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqURI, 0,  &qtssRTSPReqURIString);
//        printf("QTSSIcecastAuthModule::RTSPPreProcess: request qtssRTSPReqURI: %s\n", qtssRTSPReqURIString);
//
//    char* qtssRTSPReqAbsoluteURLString = NULL;
//    (void)QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqAbsoluteURL, 0,  &qtssRTSPReqAbsoluteURLString);
//    printf("QTSSIcecastAuthModule::RTSPPreProcess: request qtssRTSPReqAbsoluteURL: %s\n", qtssRTSPReqAbsoluteURLString);

        





//        //QTSS_Delete(qtssRTSPReqFilePathString);
//        QTSS_Delete(qtssRTSPReqURIString);
//        //QTSS_Delete(qtssRTSPReqAbsoluteURLString);
//        QTSS_Delete(qtssRTSPSesIDString);
    }
    else {
        
        printf("QTSSIcecastAuthModule::RTSPPreProcess: username and/or password are NULL\n");
    }
    
    // set the auth status on the RTSP session
    (void)QTSS_SetValue(theRTSPSession, attrRtspSessionAuthenticated, 0,  &sessionValid, sizeof(sessionValid));
    
    if (sessionValid) {
        // valid session, return
        
        return QTSS_NoErr;
    }
    else {
        // not a valid session, error
        char* accessDeniedMessage = "Access DENIED";
        StrPtrLen accessDeniedMessageStr(accessDeniedMessage,sizeof(accessDeniedMessage));
        (void)QTSSModuleUtils::SendErrorResponseWithMessage(theRTSPRequest, qtssClientForbidden, &accessDeniedMessageStr);
        
        return QTSS_NoErr;
    }
}
/*
 * This method is called because it is the only one that gets the full URL params, to capture
 * the username and password. We don't have access to the client session here, so save
 * the user and pass in the session for later. This is called BEFORE PostProcess
 */
QTSS_Error RTSPFilter(QTSS_StandardRTSP_Params* inParams) {
    QTSS_Error              theErr = QTSS_NoErr;
    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
    QTSS_RTSPSessionObject  theRTSPSession = inParams->inRTSPSession;
    
    // FAIL - can't do this here. need to finally move the auth to preprocess, and use this
    // just for param capture.
    // On the flip site, it seems that everything is really early here - if query params
    // don't work, can embed them in the URL path, extract here, and rewrite the URL in the request
    // and it should work fine. this could be handy if proxy's become an issue, because each request
    // would have a unique path.
    
//    // see if the method is bypassable. if it is, skip processing
//    qtss_printf("QTSSIcecastAuthModule::RTSPFilter: about to check if the method is bypassable\n");
//    if (IsRequestMethodBypassable(&theRTSPRequest)) return QTSS_NoErr;
    
    // see if the client is in the bypass list. if they are, skip all processing
    if (IsClientInBypassList(&theRTSPSession)) return QTSS_NoErr;
    
    // check to see if the session is already auth'd. If it is, skip processing
    if (IsRTSPSessionAuthenticated(&theRTSPSession)) {
        printf("QTSSIcecastAuthModule::RTSPFilter RTSP session is authenticated, do nothing.\n");
        return QTSS_NoErr; // we are authenticated, don't do anything
    }
    
    char* qtssRTSPSesIDString = NULL;
    (void) QTSS_GetValueAsString(theRTSPSession, qtssRTSPSesID, 0, &qtssRTSPSesIDString);
    printf("QTSSIcecastAuthModule::RTSPFilter session qtssRTSPSesID: %s\n", qtssRTSPSesIDString);
    
    char* qtssRTSPReqFullRequestString = NULL;
    (void)QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqFullRequest, 0,  &qtssRTSPReqFullRequestString);
    qtss_printf("QTSSIcecastAuthModule::RTSPFilter: request qtssRTSPReqFullRequest: %s\n", qtssRTSPReqFullRequestString);
    
    /* will want to modify this for proper tokenization, but it works for now */ 
    char username[255];
    bool usernameset = false;
    char password[255];
    bool passwordset = false;
    
    Bool16 requiredAuthParametersProvided = false;
    
    if(index(qtssRTSPReqFullRequestString, '?')){ 
        char buf[512]; 
        snprintf(buf, 512, qtssRTSPReqFullRequestString);
        
        char* queryString;
        
        char* progress1;
        
        // split off everything after the first line, we don't need it.
        queryString = ::strtok_r(buf, "\n", &progress1); 
        // split around the ?, ignore the first part
        ::strtok_r(buf, "?", &progress1); 
        // get the second part of the previous split
        queryString = ::strtok_r(NULL, "?", &progress1); 
        // split working around the space
        queryString = ::strtok_r(queryString, " ", &progress1);
        //printf("queryString: %s\n", queryString);
        // we should now have our url
        
        char* tmp = strtok(queryString, "=&");
        
        int iters;
    
        for (iters=0; (tmp != NULL); iters++)
        {    
            char name[255]; // I'm asking for a buffer overflow, aren't I? TODO - check this.
            if ((iters % 2) != 1) {
                // even - its a name. this will always be 'first'
                strcpy(name, tmp);
                //printf("name: %s\n", tmp);
            }
            else {
                // non-even, its a value. this will always come second
                //printf("value: %s\n", tmp);
                
                if (strcmp(name, "u") == 0) {
                    // this value is the username
                    //printf("name is currently: %s. username being set to %s\n", name, tmp);
                    strcpy(username, tmp);
                    usernameset = true;
                }
                else if (strcmp(name, "p") == 0) {
                    // this value is the username
                    //printf("name is currently: %s. password being set to %s\n", name, tmp);
                    strcpy(password, tmp);
                    passwordset = true;
                }
                
            }
            tmp = strtok(NULL, "=&");
        }
        
        //printf("username: %s, password: %s\n\n", username, password);
        
        if (usernameset && passwordset) {
            printf("QTSSIcecastAuthModule::RTSPFilter username and password have been provided.\n");
            requiredAuthParametersProvided = true;
        }
        
    }
    
    if (requiredAuthParametersProvided) {
        // we have a username and password. set them on the RTSP session, so they can be validated later.
        
        QTSS_Error setErr = QTSS_SetValue(theRTSPSession, attrRtspSessionProvidedUsername, 0,  &username, sizeof(username));
        QTSS_SetValue(theRTSPSession, attrRtspSessionProvidedPassword, 0,  &password, sizeof(password));
        
        PrintQTSSError("QTSSIcecastAuthModule::RTSPFilter", "after username set", setErr);
        
        char* providedUsername = NULL;
        (void)QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedUsername, 0,  &providedUsername);
        printf("QTSSIcecastAuthModule::RTSPFilter: Provided username extracted from session right after set: %s\n", providedUsername);

        char* providedPassword = NULL;
        (void) QTSS_GetValueAsString(theRTSPSession, attrRtspSessionProvidedPassword, 0, &providedPassword);
        printf("QTSSIcecastAuthModule::RTSPFilter: Provided password extracted from session right after set: %s\n", providedPassword);          
    }
    else {
        // WRONG. username and password weren't provided, do nothing - we will handle later.
    }
    
    // TODO - we should be cleaning up more things here, I think.
    QTSS_Delete(qtssRTSPReqFullRequestString);
    
    return QTSS_NoErr;
}
Example #18
0
QTSS_Error Authorize(QTSS_StandardRTSP_Params* inParams)
{

    OSMutexLocker locker(sAuthMutex);


    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
 
    if  ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) )
    {
        debug_printf("QTSSDSAuthModule - Authorize inParams: Error");
        return QTSS_RequestFailed;
    }
        
    //get the local file path
    char*   pathBuffStr = NULL;
    QTSS_Error theErr = QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqLocalPath, 0, &pathBuffStr);
    QTSSCharArrayDeleter pathBuffDeleter(pathBuffStr);
    if (theErr != QTSS_NoErr)
    {
        debug_printf("QTSSDSAuthModule - Authorize [QTSS_GetValueAsString]: Error %"_S32BITARG_"", theErr);
        return QTSS_RequestFailed;  
    }
    //get the root movie directory
    char*   movieRootDirStr = NULL;
    theErr = QTSS_GetValueAsString(theRTSPRequest,qtssRTSPReqRootDir, 0, &movieRootDirStr);
    OSCharArrayDeleter movieRootDeleter(movieRootDirStr);
    if (theErr != QTSS_NoErr)
    {
        debug_printf("QTSSDSAuthModule - Authorize[QTSS_GetValueAsString]: Error %"_S32BITARG_"", theErr);
        return false;
    }
    //check if this user is allowed to see this movie
    
    DSAccessFile accessFile;
    Bool16 allowNoAccessFiles = sAllowGuestDefaultEnabled; //no access files allowed means allowing guest access (unknown users)
    Bool16 allowAnyUser = false;
    QTSS_ActionFlags noAction = ~qtssActionFlagsRead; //only handle read
    QTSS_ActionFlags authorizeAction =  QTSSModuleUtils::GetRequestActions(theRTSPRequest);
    Bool16 authorized =false;
    Bool16 saclUser = false;
 
    char *name = NULL;
    (void) QTSS_GetValueAsString (theRTSPRequest,qtssRTSPReqUserName,0, &name);
    OSCharArrayDeleter nameDeleter(name);
    if (sAllowGuestDefaultEnabled) // if guest access is on, sacls are ignored.
    {
        authorized =  true;
    }
    else
    {   int result = check_sacl(name);
        
        switch (result)
        {
            case kSACLAuthorized: authorized = true;	
            break;
            
            case kSACLUnknownUser: authorized = false;	//set this to true to allow file based and other non-directory service users access, when SACLs are enabled in the system for QTSS.
            break;
            
            case kSACLNotAuthorized: authorized = false;	
            break;
            
            case kSACLAnyUser: authorized = true;
            break;
        
            default: authorized = false;	
       }

          
         debug_printf("QTSSDSAuthModule:Authorize sacl_check result=%d for %s authorized = %d\n",result,  name, authorized);
         if (false == authorized)
            saclUser = true;
    }

    Bool16 foundUser = false;
    Bool16 passwordOK = false; //::AuthenticateRequest(inParams, pathBuffStr, movieRootDirStr, &sRealmNameStr, &foundUser);
    if (authorized) //have to be authorized by sacls or guest first before qtaccess file checks can allow or disallow.
    {
       theErr = accessFile.AuthorizeRequest(inParams,allowNoAccessFiles, noAction, authorizeAction,&authorized,  &allowAnyUser);
       debug_printf("QTSSDSAuthModule:Authorize AuthorizeRequest() returned authorized=%d allowAnyUser=%d\n", authorized, allowAnyUser);

    }
    
    debug_printf("QTSSDSAuthModule:Authorize AuthenticateRequest() returned passwordOK=%d foundUser=%d authorized=%d allowAnyUser=%d\n", passwordOK ,foundUser, authorized,allowAnyUser);

    Bool16 allowRequest = authorized;
    Bool16 authHandled = true;

    if(!(authorizeAction & qtssActionFlagsRead)) //not for us
    {
        debug_printf("QTSSDSAuthModule:Authorize(qtssActionFlagsRead) not handled do nothing.\n");
    }
    else if (allowRequest)
    {
        debug_printf("QTSSDSAuthModule:Authorize() succeeded.\n");
        theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &foundUser, &authHandled);
        debug_printf("QTSSDSAuthModule:Authorize allowRequest=%d founduser=%d authHandled=%d\n", allowRequest, foundUser, authHandled);
    }
    else //request denied
    {
         debug_printf("QTSSDSAuthModule:Authorize() failed.\n");
         foundUser = saclUser;
         authHandled = true;
         theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &foundUser, &authHandled);
         debug_printf("QTSSDSAuthModule:Authorize allowRequest=%d founduser=%d authHandled=%d saclUser=%d\n", allowRequest, foundUser, authHandled,saclUser);
    }


  return theErr;
}
QTSS_Error Authenticate(QTSS_StandardRTSP_Params* inParams)
{

    if  ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) ) {
        return QTSS_RequestFailed;
    }
    
    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
    QTSS_Error theErr = QTSS_NoErr;
        
    char *movieUrlTrunc = NULL;
    theErr = QTSS_GetValueAsString(theRTSPRequest,qtssRTSPReqTruncAbsoluteURL, 0, &movieUrlTrunc);
    QTSSCharArrayDeleter movieUrlTruncDeleter(movieUrlTrunc);
    if (theErr != QTSS_NoErr)
        return QTSS_RequestFailed;

    char *movieUrlFilename = NULL;
    theErr = QTSS_GetValueAsString(theRTSPRequest,qtssRTSPReqFileName, 0, &movieUrlFilename);
    QTSSCharArrayDeleter movieUrlFilenameDeleter(movieUrlFilename);
    if (theErr != QTSS_NoErr)
        return QTSS_RequestFailed;
    
    // Return unless the requested filename matches the redirect URL
    if (::strncmp(movieUrlFilename, sRedirectUrl,  (::strlen(movieUrlFilename) <= ::strlen(sRedirectUrl)) 
            ? ::strlen(sRedirectUrl) : ::strlen(movieUrlFilename)))
        return QTSS_NoErr;
    
    // Get the client's bandwidth header
    UInt32 bandwidthBits = 0;
    UInt32 len = sizeof(bandwidthBits);
	(void)QTSS_GetValue(theRTSPRequest, qtssRTSPReqBandwidthBits, 0, (void *)&bandwidthBits, &len);

    // Prepare a filename extension to use for redirection.
    // These numbers match the "Streaming Speed" options in the QuickTime Player 7 settings.
    // The extension will be appended to the requested URL.
    char theNewFilename[kBuffSize];
    ::memset(theNewFilename, 0, kBuffSize);
    
    if (bandwidthBits <= 0) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_50kbit.3gp", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 28000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_50kbit.3gp", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 56000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_50kbit.3gp", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 112000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_100kbit.mov", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 256000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_100kbit.mov", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 384000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_300kbit.mov", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 512000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_300kbit.mov", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 768000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_300kbit.mov", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 1000000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_h264_1mbit.mp4", movieUrlTrunc, movieUrlFilename);
    } else if (bandwidthBits <= 1500000) {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_h264_1mbit.mp4", movieUrlTrunc, movieUrlFilename);
    } else {
        qtss_snprintf(theNewFilename, sizeof(theNewFilename), "%s/%s_h264_1mbit.mp4", movieUrlTrunc, movieUrlFilename);
    }
    
    // In order to send the redirect, we need to get a QTSS_StreamRef
    // so we can send data to the client. Get the QTSS_StreamRef out of the request.
    QTSS_StreamRef* theStreamRef = NULL;
    UInt32 strRefLen = 0;
        
    theErr = QTSS_GetValuePtr(theRTSPRequest, qtssRTSPReqStreamRef, 0,
        (void**)&theStreamRef, &strRefLen);
    if (( QTSS_NoErr != theErr ) || ( sizeof(QTSS_StreamRef) != strRefLen) ) {
        return QTSS_RequestFailed;
    }

    // Send the redirect
    UInt32 theLenWritten = 0;
    
    (void)QTSS_Write(*theStreamRef, sRedirect.Ptr, sRedirect.Len, &theLenWritten, 0);
    (void)QTSS_Write(*theStreamRef, sLocation.Ptr, sLocation.Len, &theLenWritten, 0);
    (void)QTSS_Write(*theStreamRef, theNewFilename, ::strlen(theNewFilename), &theLenWritten, 0);
    (void)QTSS_Write(*theStreamRef, sRedirectEnd.Ptr, sRedirectEnd.Len, &theLenWritten, 0);
    (void)QTSS_Flush(*theStreamRef);
     
    return QTSS_NoErr;
}
Example #20
0
void LogStatus(QTSS_ServerState theServerState)
{
    static QTSS_ServerState lastServerState = 0;
    static char *sPLISTHeader[] =
    {     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
#if __MacOSX__
        "<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">",
#else
        "<!ENTITY % plistObject \"(array | data | date | dict | real | integer | string | true | false )\">",
        "<!ELEMENT plist %plistObject;>",
        "<!ATTLIST plist version CDATA \"0.9\">",
        "",
        "<!-- Collections -->",
        "<!ELEMENT array (%plistObject;)*>",
        "<!ELEMENT dict (key, %plistObject;)*>",
        "<!ELEMENT key (#PCDATA)>",
        "",
        "<!--- Primitive types -->",
        "<!ELEMENT string (#PCDATA)>",
        "<!ELEMENT data (#PCDATA)> <!-- Contents interpreted as Base-64 encoded -->",
        "<!ELEMENT date (#PCDATA)> <!-- Contents should conform to a subset of ISO 8601 (in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'.  Smaller units may be omitted with a loss of precision) -->",
        "",
        "<!-- Numerical primitives -->",
        "<!ELEMENT true EMPTY>  <!-- Boolean constant true -->",
        "<!ELEMENT false EMPTY> <!-- Boolean constant false -->",
        "<!ELEMENT real (#PCDATA)> <!-- Contents should represent a floating point number matching (\"+\" | \"-\")? d+ (\".\"d*)? (\"E\" (\"+\" | \"-\") d+)? where d is a digit 0-9.  -->",
        "<!ELEMENT integer (#PCDATA)> <!-- Contents should represent a (possibly signed) integer number in base 10 -->",
        "]>",
#endif
    };

    static int numHeaderLines = sizeof(sPLISTHeader) / sizeof(char*);

    static char*    sPlistStart = "<plist version=\"0.9\">";
    static char*    sPlistEnd = "</plist>";
    static char*    sDictStart = "<dict>";
    static char*    sDictEnd = "</dict>";
    
    static char*    sKey    = "     <key>%s</key>\n";
    static char*    sValue  = "     <string>%s</string>\n";
    
    static char *sAttributes[] =
    {
        "qtssSvrServerName",
        "qtssSvrServerVersion",
        "qtssSvrServerBuild",
        "qtssSvrServerPlatform",
        "qtssSvrRTSPServerComment",
        "qtssSvrServerBuildDate",
        "qtssSvrStartupTime",
        "qtssSvrCurrentTimeMilliseconds",
        "qtssSvrCPULoadPercent",
         "qtssSvrState",
        "qtssRTPSvrCurConn",
        "qtssRTSPCurrentSessionCount",
        "qtssRTSPHTTPCurrentSessionCount",
        "qtssRTPSvrCurBandwidth",
        "qtssRTPSvrCurPackets",
        "qtssRTPSvrTotalConn",
        "qtssRTPSvrTotalBytes",
        "qtssMP3SvrCurConn",
        "qtssMP3SvrTotalConn",
        "qtssMP3SvrCurBandwidth",
        "qtssMP3SvrTotalBytes"
    };
    static int numAttributes = sizeof(sAttributes) / sizeof(char*);
        
    static StrPtrLen statsFileNameStr("server_status");    
    
    if (false == sServer->GetPrefs()->ServerStatFileEnabled())
        return;
        
    UInt32 interval = sServer->GetPrefs()->GetStatFileIntervalSec();
    if (interval == 0 || (OS::UnixTime_Secs() % interval) > 0 ) 
        return;
    
    // If the total number of RTSP sessions is 0  then we 
    // might not need to update the "server_status" file.
    char* thePrefStr = NULL;
    // We start lastRTSPSessionCount off with an impossible value so that
    // we force the "server_status" file to be written at least once.
    static int lastRTSPSessionCount = -1; 
    // Get the RTSP session count from the server.
    (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr);
    int currentRTSPSessionCount = ::atoi(thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    if (currentRTSPSessionCount == 0 && currentRTSPSessionCount == lastRTSPSessionCount)
    {
        // we don't need to update the "server_status" file except the
        // first time we are in the idle state.
        if (theServerState == qtssIdleState && lastServerState == qtssIdleState)
        {
            lastRTSPSessionCount = currentRTSPSessionCount;
            lastServerState = theServerState;
            return;
        }
    }
    else
    {
        // save the RTSP session count for the next time we execute.
        lastRTSPSessionCount = currentRTSPSessionCount;
    }

    StrPtrLenDel pathStr(sServer->GetPrefs()->GetErrorLogDir());
    StrPtrLenDel fileNameStr(sServer->GetPrefs()->GetStatsMonitorFileName());
    ResizeableStringFormatter pathBuffer(NULL,0);
    pathBuffer.PutFilePath(&pathStr,&fileNameStr);
    pathBuffer.PutTerminator();
    
    char*   filePath = pathBuffer.GetBufPtr();    
    FILE*   statusFile = ::fopen(filePath, "w");
    char*   theAttributeValue = NULL;
    int     i;
    
    if (statusFile != NULL)
    {
        ::chmod(filePath, 0640);
        for ( i = 0; i < numHeaderLines; i++)
        {    
            qtss_fprintf(statusFile, "%s\n",sPLISTHeader[i]);    
        }

        qtss_fprintf(statusFile, "%s\n", sPlistStart);
        qtss_fprintf(statusFile, "%s\n", sDictStart);    

          // show each element value
         for ( i = 0; i < numAttributes; i++)
        {
            (void)QTSS_GetValueAsString(sServer, QTSSModuleUtils::GetAttrID(sServer,sAttributes[i]), 0, &theAttributeValue);
            if (theAttributeValue != NULL)
             {
                qtss_fprintf(statusFile, sKey, sAttributes[i]);    
               qtss_fprintf(statusFile, sValue, theAttributeValue);    
                delete [] theAttributeValue;
                theAttributeValue = NULL;
             }
         }
                  
        qtss_fprintf(statusFile, "%s\n", sDictEnd);
        qtss_fprintf(statusFile, "%s\n\n", sPlistEnd);    
         
          ::fclose(statusFile);
    }
    lastServerState = theServerState;
}
Example #21
0
QTSS_Error Preprocess(QTSS_StandardRTSP_Params* inParams)
{
    static UInt32 sFileBufSize = 32768;
    static UInt32 sInitialState = kReadingBufferState;
    static UInt32 sZero = 0;
    
    UInt32 theLen = 0;
    UInt32* theStateP = NULL;
    QTSS_Error theErr = QTSS_NoErr;

    QTSS_Object theFile = NULL;
    
    (void)QTSS_GetValuePtr(inParams->inRTSPSession, sStateAttr, 0, (void**)&theStateP, &theLen);
    if ((theStateP == NULL) || (theLen != sizeof(UInt32)))
    {
        // Initial state. We haven't started sending the file yet, so
        // check to see if this is our request, and if it is, set everything up.
        
        // Only operate if this is a DESCRIBE
        QTSS_RTSPMethod* theMethod = NULL;
        UInt32 theLen = 0;
        if ((QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqMethod, 0,
                (void**)&theMethod, &theLen) != QTSS_NoErr) || (theLen != sizeof(QTSS_RTSPMethod)))
        {
            Assert(0);
            return QTSS_RequestFailed;
        }

        if (*theMethod != qtssDescribeMethod)
            return QTSS_RequestFailed;

        // Check to see if this is a raw file request
        char* theFilePath = NULL;          
        (void)QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqLocalPath, 0, &theFilePath);
		QTSSCharArrayDeleter theFilePathDeleter(theFilePath);
        theLen = ::strlen(theFilePath);
		
        // Copy the full path, and append a ".raw"
        OSCharArrayDeleter rawPath(NEW char[theLen + sRawSuffix.Len + 4]);
        ::memcpy(rawPath.GetObject(), theFilePath, theLen);
        ::strcpy(rawPath.GetObject() + theLen, sRawSuffix.Ptr);
        
#if RAWFILE_FILE_ASYNC
        theErr = QTSS_OpenFileObject(rawPath.GetObject(), qtssOpenFileAsync, &theFile);
#else
        theErr = QTSS_OpenFileObject(rawPath.GetObject(), qtssOpenFileAsync, &theFile);
#endif
        
        // If the file doesn't exist, and if this is a path with a '.raw' at the end,
        // check to see if the path without the extra .raw exists
        if (theErr != QTSS_NoErr)
        {
            theFile = NULL;
            rawPath.GetObject()[theLen] = '\0';
            
            if (theLen > sRawSuffix.Len)
            {
                StrPtrLen comparer((theFilePath + theLen) - sRawSuffix.Len, sRawSuffix.Len);
                if (comparer.Equal(sRawSuffix))
                {
#if RAWFILE_FILE_ASYNC
                    theErr = QTSS_OpenFileObject(rawPath.GetObject(), qtssOpenFileAsync, &theFile);
#else
                    theErr = QTSS_OpenFileObject(rawPath.GetObject(), kOpenFileNoFlags, &theFile);
#endif
                }
            }
        }

        // If the file doesn't exist, we should probably return a 404 not found.
        if (theErr != QTSS_NoErr)
            return QTSS_RequestFailed;

        // Before sending any response, set keep alive to off for this connection
        // Regardless of what the client sends, the server always closes the connection after sending the file
        static Bool16 sFalse = false;
        (void)QTSS_SetValue(inParams->inRTSPRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));

        // We have a real file. Setup all the dictionary values we need
        (void)QTSS_SetValue(inParams->inRTSPSession, sFileAttr, 0, &theFile, sizeof(theFile));

        // Create a buffer to store data.
        char* theFileBuffer = NEW char[sFileBufSize];
        (void)QTSS_SetValue(inParams->inRTSPSession, sFileBufferAttr, 0, &theFileBuffer, sizeof(theFileBuffer));

        // Store our initial state
        (void)QTSS_SetValue(inParams->inRTSPSession, sStateAttr, 0, &sInitialState, sizeof(sInitialState));
        theStateP = &sInitialState; // so we can proceed normally

        (void)QTSS_SetValue(inParams->inRTSPSession, sReadOffsetAttr, 0, &sZero, sizeof(sZero));
        (void)QTSS_SetValue(inParams->inRTSPSession, sWriteOffsetAttr, 0, &sZero, sizeof(sZero));
    }
Example #22
0
void SendStats(QTSS_StreamRef inStream, UInt32  refreshInterval, Bool16 displayHelp, StrPtrLen* fieldList)
{
    struct FieldIndex {
        char*   fieldName;
        int fieldIndex;
    };
    
    const FieldIndex kFieldIndexes[] = {
                                    {"title", 1},
                                    {"dnsname", 2},
                                    {"curtime", 3},
                                    {"", 4},
                                    {"serververs", 5},
                                    {"serverbornon", 6},
                                    {"serverstatus", 7},
                                    {"", 8},
                                    {"", 9},
                                    {"", 10},
                                    {"", 11},
                                    {"", 12},
                                    {"", 13},
                                    {"currtp", 14},
                                    {"currtsp", 15},
                                    {"currtsphttp", 16},
                                    {"curthru", 17},
                                    {"curpkts", 18},
                                    {"totbytes", 19},
                                    {"totconns", 20},
                                    {"", 21},
                                    {"connlimit", 22},
                                    {"thrulimit", 23},
                                    {"moviedir", 24},
                                    {"rtspip", 25},
                                    {"rtspport", 26},
                                    {"rtsptimeout", 27},
                                    {"rtptimeout", 28},
                                    {"secstobuffer", 29},
                                    {"", 30},
                                    {"accesslog", 31},
                                    {"accesslogdir",32},
                                    {"accesslogname", 33},
                                    {"accessrollsize", 34},
                                    {"accessrollinterval", 35},
                                    {"", 36},
                                    {"errorlog", 37},
                                    {"errorlogdir", 38},
                                    {"errorlogname", 39},
                                    {"errorrollsize", 40},
                                    {"errorrollinterval", 41},
                                    {"errorloglevel", 42},
                                    {"", 43},
                                    {"assertbreak", 44},
                                    {"autostart", 45},
                                    {"totbytesupdateinterval", 46},
                                    {"reflectordelay", 47},
                                    {"reflectorbucketsize", 48},
                                    {"historyinterval", 49},
                                    {"outoffiledesc", 50},
                                    {"numudpsockets", 51},
                                    {"apiversion", 52},
                                    {"numreliableudpbuffers", 53},
                                    {"reliableudpwastedbytes", 54},
                                    {"numtaskthreads", 55}
    };
    const int kMaxFieldNum = 55;
    static char* kEmptyStr = "?";
    char* thePrefStr = kEmptyStr;

    char buffer[1024];

    (void)QTSS_Write(inStream, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);

    if (refreshInterval > 0)
    {
        qtss_sprintf(buffer, "<META HTTP-EQUIV=Refresh CONTENT=%"_U32BITARG_">\n", refreshInterval);
        (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
    }
        
    //qtss_sprintf(buffer, "<body text=\"#000000\" bgcolor=\"#C0C0C0\" link=\"#0000FF\" vlink=\"#551A8B\" alink=\"#0000FF\">\n");
    //(void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
    
    char *theHTML =  "<HTML><BODY>\n";
    
    (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0);
    
    if (displayHelp)
    {
    
    #ifndef __MacOSX__
        static StrPtrLen sHelpLine1("<P><b>Streaming Server Statistics Help</b></P>\n");
    #else
        static StrPtrLen sHelpLine1("<P><b>QuickTime Streaming Server Statistics Help</b></P>\n");
    #endif

        static StrPtrLen sHelpLine2("<P>Example:</P>\n");
        static StrPtrLen sHelpLine3("<BLOCKQUOTE><P>http://server/statsURL?help&amp;refresh=15&amp;fields=curtime,cpuload </P>\n");

        static StrPtrLen sHelpLine4("\"?\" means that there are options being attached to the stats request.<BR>\n");
        static StrPtrLen sHelpLine5("\"&amp;\" separates multiple stats options<BR>\n<BR>\n");

        static StrPtrLen sHelpLine6("<P>The three possible parameters to stats are:</P>\n");
        static StrPtrLen sHelpLine7("<P>\"help\"  -- shows the help information you're reading right now.</P>\n");
        static StrPtrLen sHelpLine8("<P>\"refresh=&#91;n&#93;\"  -- tells the browser to automatically update the page every &#91;n&#93; seconds.</P>\n");
        static StrPtrLen sHelpLine9("<P>\"fields=&#91;fieldList&#93;\"  -- show only the fields specified in comma delimited &#91;fieldList&#93;</P>\n");
        static StrPtrLen sHelpLine10("<BLOCKQUOTE>The following fields are available for use with the \"fields\" option:</P><BLOCKQUOTE><DL>\n");
        
        (void)QTSS_Write(inStream, sHelpLine1.Ptr, sHelpLine1.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine2.Ptr, sHelpLine2.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine3.Ptr, sHelpLine3.Len, NULL, 0);

        (void)QTSS_Write(inStream, sHelpLine4.Ptr, sHelpLine4.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine5.Ptr, sHelpLine5.Len, NULL, 0);

        (void)QTSS_Write(inStream, sHelpLine6.Ptr, sHelpLine6.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine7.Ptr, sHelpLine7.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine8.Ptr, sHelpLine8.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine9.Ptr, sHelpLine9.Len, NULL, 0);
        (void)QTSS_Write(inStream, sHelpLine10.Ptr, sHelpLine10.Len, NULL, 0);      
    
        for (short i = 0; i < kMaxFieldNum; i++)
        {
                qtss_sprintf(buffer, "<DT><I>%s</I></DT>\n", kFieldIndexes[i].fieldName);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
        }
        
        static StrPtrLen sHelpLine11("</DL></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE><BR><P><HR>");
        (void)QTSS_Write(inStream, sHelpLine11.Ptr, sHelpLine11.Len, NULL, 0);      
    }

    StringParser fieldNamesParser(fieldList);
    StrPtrLen fieldName;
    int fieldNum = 0;
    do
    {
    
            
        if (fieldList != NULL)
        {
            fieldNum = 0;
            
            fieldNamesParser.ConsumeWord(&fieldName);
            
            for (short i = 0; i < kMaxFieldNum; i++)
            {
                if ( fieldName.Equal(StrPtrLen(kFieldIndexes[i].fieldName, ::strlen(kFieldIndexes[i].fieldName))) )
                {
                    fieldNum = kFieldIndexes[i].fieldIndex;
                    break;
                }
            }
        }
        else
        {
            fieldNum++;
            if ( fieldNum > kMaxFieldNum )
                fieldNum = 0;
        }

        UInt32 theLen = 0;
        
        switch (fieldNum)
        {
            case 1:
            {
#if __MacOSX__
                    static StrPtrLen sStatsLine1("<TITLE>QuickTime Streaming Server Stats</TITLE><BR>\n");
                    (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0);      
#else
                    static StrPtrLen sStatsLine1("<TITLE>Streaming Server Stats</TITLE><BR>\n");
                    (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0);      
#endif
                    
#if __MacOSX__
                    static StrPtrLen sStatsLine2("<center><h1>QuickTime Streaming Server Statistics</h1></center>\n");
                    (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0);      
#else
                    static StrPtrLen sStatsLine2("<center><h1>Streaming Server Statistics</h1></center>\n");
                    (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0);      
#endif
            }
            break;
        
            case 2:
            {
                StrPtrLen theDNS;
                (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultDNSName, 0, (void**)&theDNS.Ptr, &theDNS.Len);
                
                if ( theDNS.Ptr == NULL )
                {   // no DNS, try for the IP address only.
                    (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultIPAddr, 0, (void**)&theDNS.Ptr, &theDNS.Len);
                    
                }
                
                if ( theDNS.Ptr != NULL )
                {
                    qtss_sprintf(buffer, "<b>DNS Name (default): </b> %s<BR>\n", theDNS.Ptr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
            
            case 3:
            {
                char uptimebuffer[1024];
                time_t curTime = ::time(NULL); 
                qtss_sprintf(uptimebuffer, "<b>Current Time: </b> %s<BR>\n", qtss_ctime(&curTime, buffer, sizeof(buffer)));
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
                
                time_t upTime = curTime - sStartupTime;
                #define kDaySeconds  (24 * 60 * 60)
                #define kHourSeconds  (60 * 60)
                #define kMinuteSeconds 60

                UInt32 upTimeDays = upTime / kDaySeconds;
                UInt32 upTimeHours = (upTime % kDaySeconds) / kHourSeconds;
                UInt32 upTimeMinutes = (upTime % kHourSeconds) / kMinuteSeconds;
                UInt32 upTimeSeconds = (upTime % kMinuteSeconds);
                qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "<b>Up Time Total Seconds: </b> %"_U32BITARG_"<BR>\n", upTime);
                uptimebuffer[sizeof(uptimebuffer) -1] = 0;
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
                       
                qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "<b>Up Time: </b> %"_U32BITARG_" days %"_U32BITARG_" hours %"_U32BITARG_" minutes %"_U32BITARG_" seconds <BR>\n", upTimeDays, upTimeHours,upTimeMinutes, upTimeSeconds);
                uptimebuffer[sizeof(uptimebuffer) -1] = 0;
                (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0);    
            }
            break;
            
            case 4:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 5:
            {
                StrPtrLen theVersion;
                (void)QTSS_GetValuePtr(sServer, qtssSvrRTSPServerHeader, 0, (void**)&theVersion.Ptr, &theVersion.Len);
                Assert(theVersion.Ptr != NULL);
                if (theVersion.Len > 7) //Skip the "Server:" text
                   theVersion.Ptr += 7;
                qtss_sprintf(buffer, "<b>Server Version: </b>%s<BR>\n", theVersion.Ptr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 6:
            {
                StrPtrLen theBuildDate;
                (void)QTSS_GetValuePtr(sServer, qtssSvrServerBuildDate, 0, (void**)&theBuildDate.Ptr, &theBuildDate.Len);
                Assert(theBuildDate.Ptr != NULL);
                qtss_sprintf(buffer, "<b>Server Build Date: </b> %s<BR>\n", theBuildDate.Ptr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 7:
            {
                char statusBuffer[1024];
                const char* states[]    = { "Starting Up",
                                            "Running",
                                            "Refusing Connections",
                                            "Fatal Error",
                                            "Shutting Down"
                                          };
                QTSS_ServerState theState = qtssRunningState;
                theLen = sizeof(theState);
                (void)QTSS_GetValue(sServer, qtssSvrState, 0, &theState, &theLen);

                if (theState == qtssRunningState)
                {	qtss_snprintf(statusBuffer, sizeof(statusBuffer), "<b>Status: </b> %s since %s<BR>", states[theState], qtss_ctime(&sStartupTime,buffer,sizeof(buffer)));
                }
                else
                    qtss_snprintf(statusBuffer,sizeof(statusBuffer), "<b>Status: </b> %s<BR>", states[theState]);
                (void)QTSS_Write(inStream, statusBuffer, ::strlen(statusBuffer), NULL, 0);      
            }
            break;
            
            case 8:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 9:
            {
                
                //NOOP
            }
            break;
            
            case 10:
            {
                
                //NOOP
            }
            break;
    
            case 11:
            {
                
                //NOOP
            }
            break;
    
            case 12:
            {       
            /*  
                struct vm_statistics vmStats = {};
                if (vm_statistics (current_task (), &vmStats) != KERN_SUCCESS)
                    memset (&stats, '\0', sizeof (vmStats)) ;
            */
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
            
            case 13:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
                
            //**********************************



    
            case 14:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 15:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTSP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 16:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current RTSP over HTTP Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 17:
            {
                UInt32 curBandwidth = 0;
                theLen = sizeof(curBandwidth);
                (void)QTSS_GetValue(sServer, qtssRTPSvrCurBandwidth, 0, &curBandwidth, &theLen);

                qtss_sprintf(buffer, "<b>Current Throughput: </b> %"_U32BITARG_" kbits<BR>\n", curBandwidth/1024);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 18:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurPackets, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Current Packets Per Second: </b> %s <BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 19:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalBytes, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Bytes Served: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 20:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalConn, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Connections: </b> %s<BR>", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
            
            case 21:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            //**************************************
            case 22:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumConnections, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Maximum Connections: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 23:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumBandwidth, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Maximum Throughput: </b> %s Kbits<BR>\n",thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 24:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMovieFolder, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Movie Folder Path: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 25:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPIPAddr, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTSP IP Address: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);
            }
            break;
    
            case 26:
            {
                static StrPtrLen sRTSPPortsStart("<b>RTSP Ports: </b> ");
                (void)QTSS_Write(inStream, sRTSPPortsStart.Ptr, sRTSPPortsStart.Len, NULL, 0);      

                StrPtrLen thePort;
                for (UInt32 theIndex = 0; true; theIndex++)
                {
                    QTSS_Error theErr = QTSS_GetValuePtr(sServer, qtssSvrRTSPPorts, theIndex, (void**)&thePort.Ptr, &thePort.Len);
                    if (theErr != QTSS_NoErr)
                        break;

                    Assert(thePort.Ptr != NULL);
                    char temp[20];
                    qtss_sprintf(temp, "%u ", *(UInt16*)thePort.Ptr);
                    (void)QTSS_Write(inStream, temp, ::strlen(temp), NULL, 0);      
                }
                
                static StrPtrLen sRTSPPortsEnd("<BR>\n");
                (void)QTSS_Write(inStream, sRTSPPortsEnd.Ptr, sRTSPPortsEnd.Len, NULL, 0);      
            }
            break;
    
            case 27:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPTimeout, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 28:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTPTimeout, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 29:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 30:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 31:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logging");
                    qtss_sprintf(buffer, "<b>Access Logging: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 32:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_dir");
                    qtss_sprintf(buffer, "<b>Access Log Directory: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 33:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_name");
                    qtss_sprintf(buffer, "<b>Access Log Name: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 34:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_size");
                    qtss_sprintf(buffer, "<b>Access Log Roll Size: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 35:
            {
                if ( sAccessLogPrefs  != NULL )
                {
                    thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_interval");
                    qtss_sprintf(buffer, "<b>Access Log Roll Interval (days): </b> %s<BR>", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
            
            case 36:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 37:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogEnabled, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Logging: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 38:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogDir, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Directory: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 39:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogName, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Name: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 40:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaxErrorLogSize, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Roll Size: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 41:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorRollInterval, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Roll Interval (days): </b> %s<BR>\n",thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 42:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogVerbosity, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Error Log Verbosity: </b> %s<BR>", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
            
            case 43:
            {
                (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0);        
            }
            break;
    
            case 44:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsBreakOnAssert, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Break On Assert: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 45:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsAutoRestart, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>AutoStart: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 46:
            {
                (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsTotalBytesUpdate, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Total Bytes Update Interval: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 47:
            {
                if (sReflectorPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_delay");
                    qtss_sprintf(buffer, "<b>Reflector Delay Time: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 48:
            {
                if (sReflectorPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_bucket_size");
                    qtss_sprintf(buffer, "<b>Reflector Bucket Size: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }
            }
            break;
    
            case 49:
            {
                if ( sSvrControlPrefs != NULL)
                {
                    thePrefStr = GetPrefAsString(sSvrControlPrefs, "history_update_interval");
                    qtss_sprintf(buffer, "<b>History Update Interval: </b> %s<BR>\n", thePrefStr);
                    (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
                }       
            }
            break;
    
            case 50:
            {
                Bool16 isOutOfDescriptors = false;
                theLen = sizeof(isOutOfDescriptors);
                (void)QTSS_GetValue(sServer, qtssSvrIsOutOfDescriptors, 0, &isOutOfDescriptors, &theLen);

                qtss_sprintf(buffer, "<b>Out of file descriptors: </b> %d<BR>\n", isOutOfDescriptors);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 51:
            {
                (void)QTSS_GetValueAsString(sServer, qtssRTPSvrNumUDPSockets, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Number of UDP sockets: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
    
            case 52:
            {
                UInt32 apiVersion = 0;
                UInt32 size = sizeof(UInt32);
                (void)QTSS_GetValue(sServer, qtssServerAPIVersion, 0, &apiVersion, &size);
                qtss_sprintf(buffer, "<b>API version: </b> %d.%d<BR>\n", (int)( (UInt32) (apiVersion & (UInt32) 0xFFFF0000L) >> 16), (int)(apiVersion &(UInt32) 0x0000FFFFL));
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;

            case 53:
            {
                UInt32 reliableUDPBuffers = 0;
                UInt32 blahSize = sizeof(reliableUDPBuffers);
                (void)QTSS_GetValue(sServer, qtssSvrNumReliableUDPBuffers, 0, &reliableUDPBuffers, &blahSize);
                qtss_sprintf(buffer, "<b>Num Reliable UDP Retransmit Buffers: </b> %"_U32BITARG_"<BR>\n", reliableUDPBuffers);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;

            case 54:
            {
                UInt32 wastedBufSpace = 0;
                UInt32 blahSize2 = sizeof(wastedBufSpace);
                (void)QTSS_GetValue(sServer, qtssSvrReliableUDPWastageInBytes, 0, &wastedBufSpace, &blahSize2);
                qtss_sprintf(buffer, "<b>Amount of buffer space being wasted in UDP Retrans buffers: </b> %"_U32BITARG_"<BR>\n", wastedBufSpace);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
            
            case 55:
            {
                (void)QTSS_GetValueAsString(sServer, qtssSvrNumThreads, 0, &thePrefStr);
                qtss_sprintf(buffer, "<b>Number of Task Threads: </b> %s<BR>\n", thePrefStr);
                (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0);      
            }
            break;
             
            
    
            default:        
                break;
    
                
        } //switch fieldNum
            
            
        if (fieldList != NULL && !fieldNamesParser.Expect(','))
            fieldNum = 0;
            
        if (thePrefStr != kEmptyStr)
            delete [] thePrefStr; 
            
        thePrefStr = kEmptyStr;
            
    } while (fieldNum != 0);
    
    theHTML = "</BODY></HTML>\n";
    (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0);        
}
Example #23
0
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;
}
Example #24
0
QTSS_Error DoDescribe(QTSS_StandardRTSP_Params* inParams)
{
	//解析命令
    char* theFullPathStr = NULL;
    QTSS_Error theErr = QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFileName, 0, &theFullPathStr);
    Assert(theErr == QTSS_NoErr);
    QTSSCharArrayDeleter theFullPathStrDeleter(theFullPathStr);
        
    if (theErr != QTSS_NoErr)
        return NULL;

    StrPtrLen theFullPath(theFullPathStr);

    if (theFullPath.Len != sRelaySuffix.Len )
	return NULL;

	StrPtrLen endOfPath2(&theFullPath.Ptr[theFullPath.Len -  sRelaySuffix.Len], sRelaySuffix.Len);
    if (!endOfPath2.Equal(sRelaySuffix))
    {   
        return NULL;
    }

	//解析查询字符串
    char* theQueryStr = NULL;
    theErr = QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqQueryString, 0, &theQueryStr);
    Assert(theErr == QTSS_NoErr);
    QTSSCharArrayDeleter theQueryStringDeleter(theQueryStr);
        
    if (theErr != QTSS_NoErr)
        return NULL;

    StrPtrLen theQueryString(theQueryStr);

	QueryParamList parList(theQueryStr);

	const char* sName = parList.DoFindCGIValueForParam(QUERY_STREAM_NAME);
	const char* sChannel = parList.DoFindCGIValueForParam(QUERY_STREAM_CHANNEL);
	if(sName == NULL && sChannel == NULL)
	{
		return NULL;
	}
	char szChannelURL[256] = {0,};
	char szUsername[32] = {0,};
	char szPassword[32] = {0,};

	const char* sURL = NULL;
	char sPushServerAddr[256] = {0,};

	if (NULL != sChannel)
	{
		//find channel info
		
		GetChannelInfoById( (char*)sChannel, szChannelURL, sizeof(szChannelURL), szUsername, sizeof(szUsername), szPassword, sizeof(szPassword), sPushServerAddr, sizeof(sPushServerAddr));

		if ( (int)strlen(szChannelURL) < 1 )	return NULL;	//not found the channel

		//sURL = "rtsp://192.168.1.186:8557";
		sURL = szChannelURL;
	}
	else
	{
		sURL = parList.DoFindCGIValueForParam(QUERY_STREAM_URL);
	}
	//if(sURL == NULL) return NULL;

	const char* sCMD = parList.DoFindCGIValueForParam(QUERY_STREAM_CMD);

	bool bStop = false;
	if(sCMD)
	{
		if(::strcmp(sCMD,QUERY_STREAM_CMD_STOP) == 0)
			bStop = true;
	}

	StrPtrLen streamName(NULL!=sName?(char*)sName:(char*)sChannel);
	//从接口获取信息结构体
	EasyRelaySession* session = NULL;
	//首先查找Map里面是否已经有了对应的流
	OSRef* sessionRef = sRelaySessionMap->Resolve(&streamName);
	if(sessionRef != NULL)
	{
		session = (EasyRelaySession*)sessionRef->GetObject();
	}
	else
	{
		if(bStop) return NULL;

		if(sURL == NULL) return NULL;

		session = NEW EasyRelaySession((char*)sURL, EasyRelaySession::kRTSPTCPClientType, NULL!=sName?(char*)sName:(char*)sChannel, sPushServerAddr);

		QTSS_Error theErr = session->RelaySessionStart();

		if(theErr == QTSS_NoErr)
		{
			OS_Error theErr = sRelaySessionMap->Register(session->GetRef());
			Assert(theErr == QTSS_NoErr);
		}
		else
		{
			session->Signal(Task::kKillEvent);
			return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); 
		}

		//增加一次对RelaySession的无效引用,后面会统一释放
		OSRef* debug = sRelaySessionMap->Resolve(&streamName);
		Assert(debug == session->GetRef());
	}

	sRelaySessionMap->Release(session->GetRef());

	if(bStop)
	{
		sRelaySessionMap->UnRegister(session->GetRef());
		session->Signal(Task::kKillEvent);
		return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssSuccessOK, 0); 
	}

	QTSS_RTSPStatusCode statusCode = qtssRedirectPermMoved;
	QTSS_SetValue(inParams->inRTSPRequest, qtssRTSPReqStatusCode, 0, &statusCode, sizeof(statusCode));

	// Get the ip addr out of the prefs dictionary
	UInt16 thePort = 554;
	UInt32 theLen = sizeof(UInt16);
	theErr = QTSServerInterface::GetServer()->GetPrefs()->GetValue(qtssPrefsRTSPPorts, 0, &thePort, &theLen);
	Assert(theErr == QTSS_NoErr);   

	//构造本地URL
	char url[QTSS_MAX_URL_LENGTH] = { 0 };

	qtss_sprintf(url,"rtsp://%s:%d/%s.sdp", sLocal_IP_Addr, thePort, NULL!=sName?(char*)sName:(char*)sChannel);
	StrPtrLen locationRedirect(url);

	Bool16 sFalse = false;
	(void)QTSS_SetValue(inParams->inRTSPRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
	QTSS_AppendRTSPHeader(inParams->inRTSPRequest, qtssLocationHeader, locationRedirect.Ptr, locationRedirect.Len);	
	return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssRedirectPermMoved, 0);
}
Example #25
0
QTSS_Error QTAccessFile::AuthorizeRequest(QTSS_StandardRTSP_Params* inParams, Bool16 allowNoAccessFiles, QTSS_ActionFlags noAction, QTSS_ActionFlags authorizeAction, Bool16 *outAuthorizedPtr, Bool16 *outAllowAnyUserPtr)
{
    if  ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) || (NULL == outAllowAnyUserPtr) || (NULL == outAuthorizedPtr)  )
        return QTSS_RequestFailed;

    *outAllowAnyUserPtr = false;
    *outAuthorizedPtr = false;
    
    QTSS_RTSPRequestObject  theRTSPRequest = inParams->inRTSPRequest;
    
    // get the type of request
    // Don't touch write requests
    QTSS_ActionFlags action = QTSSModuleUtils::GetRequestActions(theRTSPRequest);
    if(action == qtssActionFlagsNoFlags)
        return QTSS_RequestFailed;
    
    if( (action & noAction) != 0)
        return QTSS_NoErr; // we don't handle
    
    //get the local file path
    char*   pathBuffStr = QTSSModuleUtils::GetLocalPath_Copy(theRTSPRequest);
    OSCharArrayDeleter pathBuffDeleter(pathBuffStr);
    if (NULL == pathBuffStr)
        return QTSS_RequestFailed;

    //get the root movie directory
    char*   movieRootDirStr = QTSSModuleUtils::GetMoviesRootDir_Copy(theRTSPRequest);
    OSCharArrayDeleter movieRootDeleter(movieRootDirStr);
    if (NULL == movieRootDirStr)
        return QTSS_RequestFailed;
    
    QTSS_UserProfileObject theUserProfile = QTSSModuleUtils::GetUserProfileObject(theRTSPRequest);
    if (NULL == theUserProfile)
        return QTSS_RequestFailed;

    char* accessFilePath = QTAccessFile::GetAccessFile_Copy(movieRootDirStr, pathBuffStr);
    OSCharArrayDeleter accessFilePathDeleter(accessFilePath);
        
    char* username = QTSSModuleUtils::GetUserName_Copy(theUserProfile);
    OSCharArrayDeleter usernameDeleter(username);

    UInt32 numGroups = 0;
    char** groupCharPtrArray =  QTSSModuleUtils::GetGroupsArray_Copy(theUserProfile, &numGroups);
    OSCharPointerArrayDeleter groupCharPtrArrayDeleter(groupCharPtrArray);
    
    StrPtrLen accessFileBuf;
    (void)QTSSModuleUtils::ReadEntireFile(accessFilePath, &accessFileBuf);
    OSCharArrayDeleter accessFileBufDeleter(accessFileBuf.Ptr);
        
    if (accessFileBuf.Len == 0 && !allowNoAccessFiles)
    {   accessFileBuf.Set(sAccessValidUser);
        if (DEBUG_QTACCESS) 
            qtss_printf("QTAccessFile::AuthorizeRequest SET Accessfile valid user for no accessfile %s\n", sAccessValidUser);
    }
      
    if (accessFileBuf.Len == 0 && allowNoAccessFiles)
    {   accessFileBuf.Set(sAccessAnyUser);
        if (DEBUG_QTACCESS) 
            qtss_printf("QTAccessFile::AuthorizeRequest SET Accessfile any user for no access file %s\n", sAccessAnyUser);
    }
      
    char realmName[kBuffLen] = { 0 };
    StrPtrLen   realmNameStr(realmName,kBuffLen -1);
    
    //check if this user is allowed to see this movie
    Bool16 allowRequest = this->AccessAllowed(username, groupCharPtrArray, numGroups,  &accessFileBuf, authorizeAction,&realmNameStr, outAllowAnyUserPtr );
    debug_printf("accessFile.AccessAllowed for user=%s returned %d\n", username, allowRequest);
    
    // Get the auth scheme
    QTSS_AuthScheme theAuthScheme = qtssAuthNone;
    UInt32 len = sizeof(theAuthScheme);
    QTSS_Error theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqAuthScheme, 0, (void*)&theAuthScheme, &len);
    Assert(len == sizeof(theAuthScheme));
    if(theErr != QTSS_NoErr)
        return theErr;
    
    // If auth scheme is basic and the realm is present in the access file, use it
    if((theAuthScheme == qtssAuthBasic) && (realmNameStr.Ptr[0] != '\0'))   //set the realm if we have one
        (void) QTSS_SetValue(theRTSPRequest,qtssRTSPReqURLRealm, 0, realmNameStr.Ptr, ::strlen(realmNameStr.Ptr));
    else // if auth scheme is basic and no realm is present, or if the auth scheme is digest, use the realm from the users file
    {  
        char*   userRealm = NULL;   
        (void) QTSS_GetValueAsString(theUserProfile, qtssUserRealm, 0, &userRealm);
        if(userRealm != NULL)
        {
            OSCharArrayDeleter userRealmDeleter(userRealm);
            (void) QTSS_SetValue(theRTSPRequest,qtssRTSPReqURLRealm, 0, userRealm, ::strlen(userRealm));
        }
    }
    
    *outAuthorizedPtr = allowRequest;
    
    Bool16 founduser = this->HaveUser(username, NULL);
    Bool16 authContinue = true;
    char nameBuff[256];
    StrPtrLen reqNameStr(nameBuff, kBuffLen);
    StrPtrLen profileNameStr(username);
    theErr = QTSS_GetValue (theRTSPRequest,qtssRTSPReqUserName,0, (void *) reqNameStr.Ptr, &reqNameStr.Len);
 
    
if (DEBUG_QTACCESS)
{   qtss_printf("QTAccessFile::AuthorizeRequest qtaccess profile user =%s ", username);
    reqNameStr.PrintStr("request user="******"\n");
    qtss_printf("QTAccessFile::AuthorizeRequest allowRequest=%d founduser=%d authContinue=%d\n", allowRequest, founduser, authContinue);
}   
    if (allowRequest && founduser)
        theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &founduser,&authContinue);
    if (!allowRequest && !founduser)
        theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &founduser,&authContinue);

if (DEBUG_QTACCESS)
{   qtss_printf("QTAccessFile::AuthorizeRequest QTSSModuleUtils::AuthorizeRequest qtaccess profile user =%s ", username);
    reqNameStr.PrintStr("request user="******"\n");
    qtss_printf("QTAccessFile::AuthorizeRequest allowRequest=%d founduser=%d authContinue=%d\n", allowRequest, founduser, authContinue);
}   
 
    return theErr;
}
QTSS_Error DoDescribe(QTSS_StandardRTSP_Params* inParams)
{
	char* theUriStr = NULL;
    QTSS_Error err = QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFileName, 0, &theUriStr);
    Assert(err == QTSS_NoErr);
    if(err != QTSS_NoErr)
		return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest, 0);
    QTSSCharArrayDeleter theUriStrDeleter(theUriStr);

	//从接口获取信息结构体
	//TODO:
	DeviceInfo* pDeviceInfo = parseDevice->GetDeviceInfoByIdName(theUriStr);

	if(pDeviceInfo == NULL)
	{
		qtss_printf("ID:%s Not Found\n",theUriStr);
		return QTSS_RequestFailed;
	}

	//信息存在rtsp://59.46.115.84:8554/h264/ch1/sub/av_stream
	RTSPRelaySession* clientSes = NULL;
	//首先查找Map里面是否已经有了对应的流
	StrPtrLen streamName(theUriStr);
	OSRef* clientSesRef = sClientSessionMap->Resolve(&streamName);
	if(clientSesRef != NULL)
	{
		clientSes = (RTSPRelaySession*)clientSesRef->GetObject();
	}
	else
	{
		clientSes = NEW RTSPRelaySession(
									SocketUtils::ConvertStringToAddr(pDeviceInfo->m_szIP),
									pDeviceInfo->m_nPort,
									pDeviceInfo->m_szSourceUrl,
									1,
									rtcpInterval,
									0,
									theReadInterval,
									sockRcvBuf,
									speed,
									packetPlayHeader,
									overbufferwindowInK,
									sendOptions,
									pDeviceInfo->m_szUser,
									pDeviceInfo->m_szPassword,
									theUriStr);

			OS_Error theErr = clientSes->SendDescribe();

			if(theErr == QTSS_NoErr)
			{
				OS_Error theErr = sClientSessionMap->Register(clientSes->GetRef());
				Assert(theErr == QTSS_NoErr);
			}
			else
			{
				clientSes->Signal(Task::kKillEvent);
				return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientNotFound, 0); 
			}

			//增加一次对RelaySession的无效引用,后面会统一释放
			OSRef* debug = sClientSessionMap->Resolve(&streamName);
			Assert(debug == clientSes->GetRef());
		}

	ReflectorSession* theSession = SetupProxySession(inParams, clientSes);
    
    if (theSession == NULL)
	{
		sClientSessionMap->Release(clientSes->GetRef());
        return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerNotImplemented, 0);
	}

	QTSS_Error Err = QTSS_SetValue(inParams->inRTSPSession, sRTSPBroadcastSessionAttr, 0, &theSession, sizeof(theSession));
	Assert(Err == QTSS_NoErr);

	clientSes->SetReflectorSession(theSession);
	theSession->SetRTSPRelaySession((void*)clientSes);
	sClientSessionMap->Release(clientSes->GetRef());

    iovec theDescribeVec[3] = { {0 }};
    Assert(theSession->GetLocalSDP()->Ptr != NULL);

    StrPtrLen theFileData;
	QTSS_TimeVal outModDate = 0;
	QTSS_TimeVal inModDate = -1;

	theFileData.Ptr = theSession->GetLocalSDP()->Ptr;
	theFileData.Len = theSession->GetLocalSDP()->Len;

// -------------- process SDP to remove connection info and add track IDs, port info, and default c= line
    StrPtrLen theSDPData;
    SDPSourceInfo tempSDPSourceInfo(theFileData.Ptr, theFileData.Len); // will make a copy and delete in destructor
    theSDPData.Ptr = tempSDPSourceInfo.GetLocalSDP(&theSDPData.Len); // returns a new buffer with processed sdp
    OSCharArrayDeleter sdpDeleter(theSDPData.Ptr); // delete the temp sdp source info buffer returned by GetLocalSDP
    
    if (theSDPData.Len <= 0) // can't find it on disk or it failed to parse just use the one in the session.
    {
        theSDPData.Ptr = theSession->GetLocalSDP()->Ptr; // this sdp isn't ours it must not be deleted
        theSDPData.Len = theSession->GetLocalSDP()->Len;
    }

// ------------  Clean up missing required SDP lines
    ResizeableStringFormatter editedSDP(NULL,0);
    DoDescribeAddRequiredSDPLines2(inParams, theSession, outModDate, &editedSDP, &theSDPData);
    StrPtrLen editedSDPSPL(editedSDP.GetBufPtr(),editedSDP.GetBytesWritten());

// ------------ Check the headers
    SDPContainer checkedSDPContainer;
    checkedSDPContainer.SetSDPBuffer( &editedSDPSPL );  
    if (!checkedSDPContainer.IsSDPBufferValid())
    {  
        return QTSSModuleUtils::SendErrorResponseWithMessage(inParams->inRTSPRequest, qtssUnsupportedMediaType, &sSDPNotValidMessage);
    }

// ------------ Put SDP header lines in correct order
    Float32 adjustMediaBandwidthPercent = 1.0;
    Bool16 adjustMediaBandwidth = false;

    SDPLineSorter sortedSDP(&checkedSDPContainer,adjustMediaBandwidthPercent);

// ------------ Write the SDP 
    UInt32 sessLen = sortedSDP.GetSessionHeaders()->Len;
    UInt32 mediaLen = sortedSDP.GetMediaHeaders()->Len;
    theDescribeVec[1].iov_base = sortedSDP.GetSessionHeaders()->Ptr;
    theDescribeVec[1].iov_len = sortedSDP.GetSessionHeaders()->Len;

    theDescribeVec[2].iov_base = sortedSDP.GetMediaHeaders()->Ptr;
    theDescribeVec[2].iov_len = sortedSDP.GetMediaHeaders()->Len;

    (void)QTSS_AppendRTSPHeader(inParams->inRTSPRequest, qtssCacheControlHeader,
                                kCacheControlHeader.Ptr, kCacheControlHeader.Len);
    QTSSModuleUtils::SendDescribeResponse(inParams->inRTSPRequest, inParams->inClientSession,
                                            &theDescribeVec[0], 3, sessLen + mediaLen ); 
    return QTSS_NoErr;
}
Example #27
0
void DebugLevel_1(FILE*   statusFile, FILE*   stdOut,  Bool16 printHeader )
{
    char*  thePrefStr = NULL;
    static char numStr[12] ="";
    static char dateStr[25] ="";
    UInt32 theLen = 0;

    if ( printHeader )
    {                   
   
        print_status(statusFile,stdOut,"%s", "     RTP-Conns RTSP-Conns HTTP-Conns  kBits/Sec   Pkts/Sec   RTP-Playing   AvgDelay CurMaxDelay  MaxDelay  AvgQuality  NumThinned      Time\n");

    }
    
    (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr);
    print_status(statusFile, stdOut,"%11s", thePrefStr);
    
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr);
    print_status(statusFile, stdOut,"%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr);
    print_status(statusFile, stdOut,"%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;
    
    UInt32 curBandwidth = 0;
    theLen = sizeof(curBandwidth);
    (void)QTSS_GetValue(sServer, qtssRTPSvrCurBandwidth, 0, &curBandwidth, &theLen);
    qtss_snprintf(numStr, 11, "%"_U32BITARG_"", curBandwidth/1024);
    print_status(statusFile, stdOut,"%11s", numStr);

    (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurPackets, 0, &thePrefStr);
    print_status(statusFile, stdOut,"%11s", thePrefStr);
    delete [] thePrefStr; thePrefStr = NULL;


    UInt32 currentPlaying = sServer->GetNumRTPPlayingSessions();
    qtss_snprintf( numStr, sizeof(numStr) -1, "%"_U32BITARG_"", currentPlaying);
    print_status(statusFile, stdOut,"%14s", numStr);

   
    //is the server keeping up with the streams?
    //what quality are the streams?
    SInt64 totalRTPPaackets = sServer->GetTotalRTPPackets();
    SInt64 deltaPackets = totalRTPPaackets - sLastDebugPackets;
    sLastDebugPackets = totalRTPPaackets;

    SInt64 totalQuality = sServer->GetTotalQuality();
    SInt64 deltaQuality = totalQuality - sLastDebugTotalQuality;
    sLastDebugTotalQuality = totalQuality;

    SInt64 currentMaxLate =  sServer->GetCurrentMaxLate();
    SInt64 totalLate =  sServer->GetTotalLate();

    sServer->ClearTotalLate();
    sServer->ClearCurrentMaxLate();
    sServer->ClearTotalQuality();
    
    ::qtss_snprintf(numStr, sizeof(numStr) -1, "%s", "0");
    if (deltaPackets > 0)
        qtss_snprintf(numStr, sizeof(numStr) -1, "%"_S32BITARG_"", (SInt32) ((SInt64)totalLate /  (SInt64) deltaPackets ));
    print_status(statusFile, stdOut,"%11s", numStr);

    qtss_snprintf(numStr,sizeof(numStr) -1, "%"_S32BITARG_"", (SInt32) currentMaxLate);
    print_status(statusFile, stdOut,"%11s", numStr);
    
    qtss_snprintf(numStr,sizeof(numStr) -1, "%"_S32BITARG_"", (SInt32)  sServer->GetMaxLate() );
    print_status(statusFile, stdOut,"%11s", numStr);

    ::qtss_snprintf(numStr, sizeof(numStr) -1, "%s", "0");
    if (deltaPackets > 0)
        qtss_snprintf(numStr, sizeof(numStr) -1, "%"_S32BITARG_"", (SInt32) ((SInt64) deltaQuality /  (SInt64) deltaPackets));
    print_status(statusFile, stdOut,"%11s", numStr);

    qtss_snprintf(numStr,sizeof(numStr) -1, "%"_S32BITARG_"", (SInt32) sServer->GetNumThinned() );
    print_status(statusFile, stdOut,"%11s", numStr);

    
    
    char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes];
    (void) QTSSRollingLog::FormatDate(theDateBuffer, false);
    
    qtss_snprintf(dateStr,sizeof(dateStr) -1, "%s", theDateBuffer );
    print_status(statusFile, stdOut,"%24s\n", dateStr);
}
QTSS_Error DoSetup(QTSS_StandardRTSP_Params* inParams)
{
    ReflectorSession* theSession = NULL;
	UInt32 len = sizeof(theSession);
	QTSS_GetValue(inParams->inRTSPSession, sRTSPBroadcastSessionAttr, 0, &theSession, &len);

	if(theSession == NULL)
		return QTSS_RequestFailed;

    Bool16 foundSession = false;
    UInt32 theLen = 0;
    RTPSessionOutput** theOutput = NULL;
    QTSS_Error theErr = QTSS_GetValuePtr(inParams->inClientSession, sOutputAttr, 0, (void**)&theOutput, &theLen);
    if (theLen != sizeof(RTPSessionOutput*))
	{
        if (theErr != QTSS_NoErr)
        {            
            RTPSessionOutput* theNewOutput = NEW RTPSessionOutput(inParams->inClientSession, theSession, sServerPrefs, sStreamCookieAttr );
            theSession->AddOutput(theNewOutput,true);
            (void)QTSS_SetValue(inParams->inClientSession, sOutputAttr, 0, &theNewOutput, sizeof(theNewOutput));
        }
    }

    //unless there is a digit at the end of this path (representing trackID), don't
    //even bother with the request
    char* theDigitStr = NULL;
    (void)QTSS_GetValueAsString(inParams->inRTSPRequest, qtssRTSPReqFileDigit, 0, &theDigitStr);
    QTSSCharArrayDeleter theDigitStrDeleter(theDigitStr);
    if (theDigitStr == NULL)
    {
        return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest,sExpectedDigitFilenameErr);
    }
    
    UInt32 theTrackID = ::strtol(theDigitStr, NULL, 10);
   
    // Get info about this trackID
    SourceInfo::StreamInfo* theStreamInfo = theSession->GetSourceInfo()->GetStreamInfoByTrackID(theTrackID);
    // If theStreamInfo is NULL, we don't have a legit track, so return an error
    if (theStreamInfo == NULL)
        return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest,
                                                    sReflectorBadTrackIDErr);
                                                    
    StrPtrLen* thePayloadName = &theStreamInfo->fPayloadName;
    QTSS_RTPPayloadType thePayloadType = theStreamInfo->fPayloadType;

    StringParser parser(thePayloadName);
    
    parser.GetThru(NULL, '/');
    theStreamInfo->fTimeScale = parser.ConsumeInteger(NULL);
    if (theStreamInfo->fTimeScale == 0)
        theStreamInfo->fTimeScale = 90000;
    
    QTSS_RTPStreamObject newStream = NULL;
    {
        // Ok, this is completely crazy but I can't think of a better way to do this that's
        // safe so we'll do it this way for now. Because the ReflectorStreams use this session's
        // stream queue, we need to make sure that each ReflectorStream is not reflecting to this
        // session while we call QTSS_AddRTPStream. One brutal way to do this is to grab each
        // ReflectorStream's mutex, which will stop every reflector stream from running.
        
        for (UInt32 x = 0; x < theSession->GetNumStreams(); x++)
            theSession->GetStreamByIndex(x)->GetMutex()->Lock();
            
        theErr = QTSS_AddRTPStream(inParams->inClientSession, inParams->inRTSPRequest, &newStream, 0);

        for (UInt32 y = 0; y < theSession->GetNumStreams(); y++)
            theSession->GetStreamByIndex(y)->GetMutex()->Unlock();
            
        if (theErr != QTSS_NoErr)
            return theErr;
    }
    
    // Set up dictionary items for this stream
    theErr = QTSS_SetValue(newStream, qtssRTPStrPayloadName, 0, thePayloadName->Ptr, thePayloadName->Len);
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrPayloadType, 0, &thePayloadType, sizeof(thePayloadType));
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrTrackID, 0, &theTrackID, sizeof(theTrackID));
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrTimescale, 0, &theStreamInfo->fTimeScale, sizeof(theStreamInfo->fTimeScale));
    Assert(theErr == QTSS_NoErr);

    // We only want to allow over buffering to dynamic rate clients   
    SInt32  canDynamicRate = -1;
    theLen = sizeof(canDynamicRate);
    (void) QTSS_GetValue(inParams->inRTSPRequest, qtssRTSPReqDynamicRateState, 0, (void*) &canDynamicRate, &theLen);
    if (canDynamicRate < 1) // -1 no rate field, 0 off
        (void)QTSS_SetValue(inParams->inClientSession, qtssCliSesOverBufferEnabled, 0, &sFalse, sizeof(sFalse));

    // Place the stream cookie in this stream for future reference
    void* theStreamCookie = theSession->GetStreamCookie(theTrackID);
    Assert(theStreamCookie != NULL);
    theErr = QTSS_SetValue(newStream, sStreamCookieAttr, 0, &theStreamCookie, sizeof(theStreamCookie));
    Assert(theErr == QTSS_NoErr);

    // Set the number of quality levels.
    static UInt32 sNumQualityLevels = ReflectorSession::kNumQualityLevels;
    theErr = QTSS_SetValue(newStream, qtssRTPStrNumQualityLevels, 0, &sNumQualityLevels, sizeof(sNumQualityLevels));
    Assert(theErr == QTSS_NoErr);
    
    //send the setup response
    (void)QTSS_AppendRTSPHeader(inParams->inRTSPRequest, qtssCacheControlHeader,
                                kCacheControlHeader.Ptr, kCacheControlHeader.Len);
    (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, newStream, qtssSetupRespDontWriteSSRC);
    return QTSS_NoErr;
}
Example #29
0
// Handle the QTSS_RTSPFilter_Role role call back.
QTSS_Error Filter(QTSS_Filter_Params* inParams)
{
    QTSS_Error err = QTSS_NoErr;
    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
    QTSS_RTSPSessionObject theSession = inParams->inRTSPSession;
    char theURL[512];
    
    // If this module is disabled do nothing but return.
    if (!sRefMovieXferEnabled)
        return QTSS_NoErr;
            
   // Get the full RTSP request from the server's attribute.
    StrPtrLen theFullRequest;
    err = QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
    
    if (err != QTSS_NoErr) 
    {
        return QTSS_NoErr;
    }
    
    // if this is not an HTTP GET then ignore it.
    if (!IsHTTPGet(theFullRequest))
        return QTSS_NoErr;
    
    // If this is a tunneled RTSP request we ignore it.
    if (IsTunneledRTSP(theFullRequest))
    {
        return QTSS_NoErr;
    }
        
    // if we can't parse out the URL then we just ignore this request.
    if (!ParseURL(theFullRequest, theURL, 512))
    {
        return QTSS_NoErr;
    }
    
    // Make sure that this is not an admin request before
    // we go any further.
    StrPtrLen movie(theURL);
    if (IsAdminURL(movie))
    {
        // The file path in the URL is actually an admin request.
        // Just ignore it and let the admin module handle it.
        return QTSS_NoErr;
    }
    
    Bool16 isHomeDir = IsHomeDirURL(movie);
    
    // Get the server's movie folder location.
    char* movieFolderString = NULL;
    err = QTSS_GetValueAsString (sServerPrefs, qtssPrefsMovieFolder, 0, &movieFolderString);
    if (err != QTSS_NoErr)
        return QTSS_NoErr;
        
    OSCharArrayDeleter movieFolder(movieFolderString);
    StrPtrLen theMovieFolder(movieFolderString);
    
    if (!isHomeDir && !FileExists(theMovieFolder, movie))
    {
        // we couldn't find a file at the specified location
        // so we will ignore this HTTP request and let some other module
        // deal with the issue.
        return QTSS_NoErr;
    }
    else
    {
        // Eureka!!! We found a file at the specified location.
        // We assume that it is a valid movie file and we send
        // the client an RTSP text reference movie in the HTTP reply.
        err = SendTheResponse(theSession,theRequest, movie);
    }
        
    return QTSS_NoErr;
}
Example #30
0
QTSS_Error DoSetup(QTSS_StandardRTSP_Params* inParamBlock)
{
    //setup this track in the file object 
    FileSession* theFile = NULL;
    UInt32 theLen = sizeof(FileSession*);
    QTSS_Error theErr = QTSS_GetValue(inParamBlock->inClientSession, sFileSessionAttr, 0, (void*)&theFile, &theLen);
    if ((theErr != QTSS_NoErr) || (theLen != sizeof(FileSession*)))
    {
        // This is possible, as clients are not required to send a DESCRIBE. If we haven't set
        // anything up yet, set everything up
		char* theFullPathStr = NULL;
        theErr = QTSS_GetValueAsString(inParamBlock->inRTSPRequest, qtssRTSPReqLocalPath, 0, &theFullPathStr);
        Assert(theErr == QTSS_NoErr);
		QTSSCharArrayDeleter theFullPathDeleter(theFullPathStr);
		StrPtrLen theFullPath(theFullPathStr);
        	
        if ((theFullPath.Len <= sRTPSuffix.Len) ||
            (!sRTPSuffix.NumEqualIgnoreCase(&theFullPath.Ptr[theFullPath.Len - sRTPSuffix.Len], sRTPSuffix.Len)))
            return QTSS_RequestFailed;

        theErr = CreateRTPFileSession(inParamBlock, theFullPath, &theFile);
        if (theErr != QTSS_NoErr)
            return theErr;

        // Store this newly created file object in the RTP session.
        theErr = QTSS_SetValue(inParamBlock->inClientSession, sFileSessionAttr, 0, &theFile, sizeof(theFile));
    }

    //unless there is a digit at the end of this path (representing trackID), don't
    //even bother with the request
    char* theDigitStr = NULL;
    (void)QTSS_GetValueAsString(inParamBlock->inRTSPRequest, qtssRTSPReqFileDigit, 0, &theDigitStr);
    QTSSCharArrayDeleter theDigitStrDeleter(theDigitStr);
	if (theDigitStr == NULL)
        return QTSSModuleUtils::SendErrorResponse(inParamBlock->inRTSPRequest,
                                                    qtssClientBadRequest, sExpectedDigitFilenameErr);
    
    UInt32 theTrackID = ::strtol(theDigitStr, NULL, 10);
	
    RTPFileSession::ErrorCode qtfileErr = theFile->fFile.AddTrack(theTrackID);
    
    //if we get an error back, forward that error to the client
    if (qtfileErr == RTPFileSession::errTrackDoesntExist)
        return QTSSModuleUtils::SendErrorResponse(inParamBlock->inRTSPRequest,
                                                    qtssClientNotFound, sTrackDoesntExistErr);
    else if (qtfileErr != RTPFileSession::errNoError)
        return QTSSModuleUtils::SendErrorResponse(inParamBlock->inRTSPRequest,
                                                    qtssUnsupportedMediaType, sBadQTFileErr);

    //find the payload for this track ID (if applicable)
    StrPtrLen* thePayload = NULL;
    UInt32 thePayloadType = qtssUnknownPayloadType;
    Float32 bufferDelay = (Float32) 3.0; // FIXME need a constant defined for 3.0 value. It is used multiple places
    
    for (UInt32 x = 0; x < theFile->fFile.GetSourceInfo()->GetNumStreams(); x++)
    {
        SourceInfo::StreamInfo* theStreamInfo = theFile->fFile.GetSourceInfo()->GetStreamInfo(x);
        if (theStreamInfo->fTrackID == theTrackID)
        {
            thePayload = &theStreamInfo->fPayloadName;
            thePayloadType = theStreamInfo->fPayloadType;
            bufferDelay = theStreamInfo->fBufferDelay;
            break;
        }   
    }

    //Create a new RTP stream           
    QTSS_RTPStreamObject newStream = NULL;
    theErr = QTSS_AddRTPStream(inParamBlock->inClientSession, inParamBlock->inRTSPRequest, &newStream, 0);
    if (theErr != QTSS_NoErr)
        return theErr;
    
    // Set the payload type, payload name & timescale of this track
    SInt32 theTimescale = theFile->fFile.GetTrackTimeScale(theTrackID);
    
    theErr = QTSS_SetValue(newStream, qtssRTPStrBufferDelayInSecs, 0, &bufferDelay, sizeof(bufferDelay));
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrPayloadName, 0, thePayload->Ptr, thePayload->Len);
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrPayloadType, 0, &thePayloadType, sizeof(thePayloadType));
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrTimescale, 0, &theTimescale, sizeof(theTimescale));
    Assert(theErr == QTSS_NoErr);
    theErr = QTSS_SetValue(newStream, qtssRTPStrTrackID, 0, &theTrackID, sizeof(theTrackID));
    Assert(theErr == QTSS_NoErr);
    
    // Set the number of quality levels. Allow up to 6
    static UInt32 sNumQualityLevels = 0;
    
    theErr = QTSS_SetValue(newStream, qtssRTPStrNumQualityLevels, 0, &sNumQualityLevels, sizeof(sNumQualityLevels));
    Assert(theErr == QTSS_NoErr);
    
    // Get the SSRC of this track
    UInt32* theTrackSSRC = NULL;
    UInt32 theTrackSSRCSize = 0;
    (void)QTSS_GetValuePtr(newStream, qtssRTPStrSSRC, 0, (void**)&theTrackSSRC, &theTrackSSRCSize);

    // The RTP stream should ALWAYS have an SSRC assuming QTSS_AddStream succeeded.
    Assert((theTrackSSRC != NULL) && (theTrackSSRCSize == sizeof(UInt32)));
    
    //give the file some info it needs.
    theFile->fFile.SetTrackSSRC(theTrackID, *theTrackSSRC);
    theFile->fFile.SetTrackCookie(theTrackID, newStream);
    
    //
    // Our array has now been updated to reflect the fields requested by the client.
    //send the setup response
    //(void)QTSS_AppendRTSPHeader(inParamBlock->inRTSPRequest, qtssLastModifiedHeader,
    //                          theFile->fFile.GetQTFile()->GetModDateStr(), DateBuffer::kDateBufferLen);
    (void)QTSS_AppendRTSPHeader(inParamBlock->inRTSPRequest, qtssCacheControlHeader,
                                kCacheControlHeader.Ptr, kCacheControlHeader.Len);

    //send the setup response
    (void)QTSS_SendStandardRTSPResponse(inParamBlock->inRTSPRequest, newStream, 0);
    return QTSS_NoErr;
}