Пример #1
0
Bool16 StillFlushing(QTSS_Filter_Params* inParams,Bool16 flushing)
{   

    QTSS_Error err = QTSS_NoErr;
    if (flushing) 
    {   
        err = QTSS_Flush(inParams->inRTSPRequest);
        //qtss_printf("Flushing session=%"_U32BITARG_" QTSS_Flush err =%"_S32BITARG_"\n",sSessID,err); 
    }
    if (err == QTSS_WouldBlock) // more to flush later
    {   
        sFlushing = true;
        (void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen);
        err = QTSS_RequestEvent(inParams->inRTSPRequest, QTSS_WriteableEvent);
        KeepSession(inParams->inRTSPRequest,true);
        //qtss_printf("Flushing session=%"_U32BITARG_" QTSS_RequestEvent err =%"_S32BITARG_"\n",sSessID,err);
    }
    else 
    {
        sFlushing = false;
        (void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen);
        KeepSession(inParams->inRTSPRequest,false);
    
        if (flushing) // we were flushing so reset the LastRequestTime
        {   
            sLastRequestTime = QTSS_Milliseconds();
            //qtss_printf("Done Flushing session=%"_U32BITARG_"\n",sSessID);
            return true;
        }
    }
    
    return sFlushing;
}
Пример #2
0
QTSS_Error	QTSSModuleUtils::SendErrorResponseWithMessage( QTSS_RTSPRequestObject inRequest,
														QTSS_RTSPStatusCode inStatusCode,
														StrPtrLen* inErrorMessagePtr)
{
    static Bool16 sFalse = false;
    
    //set RTSP headers necessary for this error response message
    (void)QTSS_SetValue(inRequest, qtssRTSPReqStatusCode, 0, &inStatusCode, sizeof(inStatusCode));
    (void)QTSS_SetValue(inRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
    StrPtrLen theErrorMessage(NULL, 0);
    
    if (sEnableRTSPErrorMsg)
    {
		Assert(inErrorMessagePtr != NULL);
		//Assert(inErrorMessagePtr->Ptr != NULL);
		//Assert(inErrorMessagePtr->Len != 0);
		theErrorMessage.Set(inErrorMessagePtr->Ptr, inErrorMessagePtr->Len);
		
        char buff[32];
        qtss_sprintf(buff,"%"_U32BITARG_"",inErrorMessagePtr->Len);
        (void)QTSS_AppendRTSPHeader(inRequest, qtssContentLengthHeader, buff, ::strlen(buff));
    }
    
    //send the response header. In all situations where errors could happen, we
    //don't really care, cause there's nothing we can do anyway!
    (void)QTSS_SendRTSPHeaders(inRequest);

    //
    // Now that we've formatted the message into the temporary buffer,
    // write it out to the request stream and the Client Session object
    (void)QTSS_Write(inRequest, theErrorMessage.Ptr, theErrorMessage.Len, NULL, 0);
    (void)QTSS_SetValue(inRequest, qtssRTSPReqRespMsg, 0, theErrorMessage.Ptr, theErrorMessage.Len);
    
    return QTSS_RequestFailed;
}
Пример #3
0
QTSS_Error RereadPrefs()
{   

    delete [] sVersionHeader;
    sVersionHeader = QTSSModuleUtils::GetStringAttribute(sServer, "qtssSvrRTSPServerHeader", kDefaultHeader);

    delete [] sIPAccessList;
    sIPAccessList = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "IPAccessList", sLocalLoopBackAddress);
    sIPAccessListID = QTSSModuleUtils::GetAttrID(sModulePrefs, "IPAccessList");

    QTSSModuleUtils::GetAttribute(sModulePrefs, "Authenticate",     qtssAttrDataTypeBool16, &sAuthenticationEnabled, &sDefaultAuthenticationEnabled, sizeof(sAuthenticationEnabled));
    QTSSModuleUtils::GetAttribute(sModulePrefs, "LocalAccessOnly",  qtssAttrDataTypeBool16, &sLocalLoopBackOnlyEnabled, &sDefaultLocalLoopBackOnlyEnabled, sizeof(sLocalLoopBackOnlyEnabled));
    QTSSModuleUtils::GetAttribute(sModulePrefs, "RequestTimeIntervalMilli",     qtssAttrDataTypeUInt32, &sRequestTimeIntervalMilli, &sDefaultRequestTimeIntervalMilli, sizeof(sRequestTimeIntervalMilli));
    QTSSModuleUtils::GetAttribute(sModulePrefs, "enable_remote_admin",  qtssAttrDataTypeBool16, &sEnableRemoteAdmin, &sDefaultEnableRemoteAdmin, sizeof(sDefaultEnableRemoteAdmin));

	QTSSModuleUtils::GetAttribute(sModulePrefs, "http_port",     qtssAttrDataTypeUInt16, &sHttpPort, &sDefaultHttpPort, sizeof(sHttpPort));

	delete [] sDocumentRoot;
    sDocumentRoot = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "document_root", sDefaultDocumentRoot);
    
    delete [] sAdministratorGroup;
    sAdministratorGroup = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "AdministratorGroup", sDefaultAdministratorGroup);
    
    if (sRequestTimeIntervalMilli > kMaxRequestTimeIntervalMilli) 
    {   
		sRequestTimeIntervalMilli = kMaxRequestTimeIntervalMilli;
    }

    (void)QTSS_SetValue(sModule, qtssModDesc, 0, sDesc, strlen(sDesc)+1);   
    (void)QTSS_SetValue(sModule, qtssModVersion, 0, &sVersion, sizeof(sVersion));   

    return QTSS_NoErr;
}
QTSS_Error  OpenFile(QTSS_OpenFile_Params* inParams)
{
    OSFileSource* theFileSource = NEW OSFileSource(inParams->inPath);

    UInt64 theLength = theFileSource->GetLength();
    
    //
    // OSFileSource returns mod date as a time_t.
    // This is the same as a QTSS_TimeVal, except the latter is in msec
    QTSS_TimeVal theModDate = (QTSS_TimeVal)theFileSource->GetModDate();
    theModDate *= 1000;
    
    //
    // Check to see if the file actually exists
    if (theLength == 0)
    {
        delete theFileSource;
        return QTSS_FileNotFound;
    }
    
    //
    // Add this new file source object to the file object
    QTSS_Error theErr = QTSS_SetValue(inParams->inFileObject, sOSFileSourceAttr, 0, &theFileSource, sizeof(theFileSource));
    if (theErr != QTSS_NoErr)
    {
        delete theFileSource;
        return QTSS_RequestFailed;
    }

    //
    // If caller wants async I/O, at this point we should set up the EventContext
    if (inParams->inFlags & qtssOpenFileAsync)
    {
        EventContext* theEventContext = NEW EventContext(EventContext::kInvalidFileDesc, Socket::GetEventThread());
        theEventContext->InitNonBlocking(theFileSource->GetFD());
        
        theErr = QTSS_SetValue(inParams->inFileObject, sEventContextAttr, 0, &theEventContext, sizeof(theEventContext));
        if (theErr != QTSS_NoErr)
        {
            delete theFileSource;
            delete theEventContext;
            return QTSS_RequestFailed;
        }
    }
    
    //
    // Set up the other attribute values in the file object
    (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjLength, 0, &theLength, sizeof(theLength));
    (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjModDate, 0, &theModDate, sizeof(theModDate));

    return QTSS_NoErr;
}
Пример #5
0
QTSS_Error AuthorizeAdminRequest(QTSS_RTSPRequestObject request)
{
    Bool16 allowed = false;
    
    // get the resource path
    // if the path does not match the admin path, don't handle the request
    char* resourcePath = QTSSModuleUtils::GetLocalPath_Copy(request);
    OSCharArrayDeleter resourcePathDeleter(resourcePath);
    
    if(strcmp(sAuthResourceLocalPath, resourcePath) != 0)
        return QTSS_NoErr;
    
    // get the type of request
    QTSS_ActionFlags action = QTSSModuleUtils::GetRequestActions(request);
    if(!(action & qtssActionFlagsAdmin))
        return QTSS_RequestFailed;
       
    QTSS_UserProfileObject theUserProfile = QTSSModuleUtils::GetUserProfileObject(request);
    if (NULL == theUserProfile)
        return QTSS_RequestFailed;
           
    (void) QTSS_SetValue(request,qtssRTSPReqURLRealm, 0, sAuthRealm, ::strlen(sAuthRealm));
    
    // Authorize the user if the user belongs to the AdministratorGroup (this is an admin module pref)
    UInt32 numGroups = 0;
    char** groupsArray = QTSSModuleUtils::GetGroupsArray_Copy(theUserProfile, &numGroups);
    
    if ((groupsArray != NULL) && (numGroups != 0))
    {
        UInt32 index = 0;
        for (index = 0; index < numGroups; index++)
        {
            if(strcmp(sAdministratorGroup, groupsArray[index]) == 0)
            {
                allowed = true;
                break;
            }
        }
    
        // delete the memory allocated in QTSSModuleUtils::GetGroupsArray_Copy call 
        delete [] groupsArray;
    }
    
    if(!allowed)
    {
        if (QTSS_NoErr != QTSS_SetValue(request,qtssRTSPReqUserAllowed, 0, &allowed, sizeof(allowed)))
            return QTSS_RequestFailed; // Bail on the request. The Server will handle the error
    }
    
    return QTSS_NoErr;
}
Пример #6
0
/*
	Content报文读取与解析
	同步进行报文处理,构造回复报文
*/
QTSS_Error CServiceSession::SetupRequest()
{
    //解析请求报文
    QTSS_Error theErr = fRequest->Parse();
    if (theErr != QTSS_NoErr)
        return QTSS_BadArgument;

    QTSS_RTSPStatusCode statusCode = qtssSuccessOK;
    char *body = NULL;
    UInt32 bodySizeBytes = 0;

	//获取具体Content json数据部分

	//1、获取json部分长度
	StrPtrLen* lengthPtr = fRequest->GetHeaderValue(httpContentLengthHeader);

	StringParser theContentLenParser(lengthPtr);
    theContentLenParser.ConsumeWhitespace();
    UInt32 content_length = theContentLenParser.ConsumeInteger(NULL);
       
	qtss_printf("ServiceSession read content-length:%d \n", content_length);

    if (content_length <= 0) return QTSS_BadArgument;

	   //
    // Check for the existence of 2 attributes in the request: a pointer to our buffer for
    // the request body, and the current offset in that buffer. If these attributes exist,
    // then we've already been here for this request. If they don't exist, add them.
    UInt32 theBufferOffset = 0;
    char* theRequestBody = NULL;
	 UInt32 theLen = 0;
    theLen = sizeof(theRequestBody);
    theErr = QTSS_GetValue(this, qtssEasySesContentBody, 0, &theRequestBody, &theLen);

    if (theErr != QTSS_NoErr)
    {
        // First time we've been here for this request. Create a buffer for the content body and
        // shove it in the request.
        theRequestBody = NEW char[content_length + 1];
        memset(theRequestBody,0,content_length + 1);
        theLen = sizeof(theRequestBody);
        theErr = QTSS_SetValue(this, qtssEasySesContentBody, 0, &theRequestBody, theLen);// SetValue creates an internal copy.
        Assert(theErr == QTSS_NoErr);
        
        // Also store the offset in the buffer
        theLen = sizeof(theBufferOffset);
        theErr = QTSS_SetValue(this, qtssEasySesContentBodyOffset, 0, &theBufferOffset, theLen);
        Assert(theErr == QTSS_NoErr);
    }
Пример #7
0
void    InitializeDictionaryItems(QTSS_RTPStreamObject inStream)
{
    UInt32* theValue = NULL;
    UInt32 theValueLen = 0;
    
    QTSS_Error theErr = QTSS_GetValuePtr(inStream, sNumLossesAboveTolAttr, 0, (void**)&theValue, &theValueLen);

    if (theErr != QTSS_NoErr)
    {
        // The dictionary parameters haven't been initialized yet. Just set them all to 0.
        (void)QTSS_SetValue(inStream, sNumLossesAboveTolAttr, 0, &theValueLen, sizeof(theValueLen));
        (void)QTSS_SetValue(inStream, sNumLossesBelowTolAttr, 0, &theValueLen, sizeof(theValueLen));
        (void)QTSS_SetValue(inStream, sNumWorsesAttr, 0, &theValueLen, sizeof(theValueLen));
    }
}
QTSS_Error DoPlay(QTSS_StandardRTSP_Params* inParams, ReflectorSession* inSession)
{
    QTSS_Error theErr = QTSS_NoErr;
    UInt32 flags = 0;
    UInt32 theLen = 0;
    
    if (inSession == NULL) // it is a broadcast session so store the broadcast session.
		return QTSS_RequestFailed;
    else
    {   
        UInt32 bitsPerSecond =  inSession->GetBitRate();
        (void)QTSS_SetValue(inParams->inClientSession, qtssCliSesMovieAverageBitRate, 0, &bitsPerSecond, sizeof(bitsPerSecond));
   
        QTSS_Error theErr = QTSS_Play(inParams->inClientSession, inParams->inRTSPRequest, qtssPlayFlagsAppendServerInfo);
        if (theErr != QTSS_NoErr)
            return theErr;
    }
    
	OSRef* theRelaySessionRef = sClientSessionMap->Resolve(inSession->GetRef()->GetString());
	if(theRelaySessionRef != NULL)
	{
		RTSPRelaySession* relaySes = (RTSPRelaySession*)theRelaySessionRef->GetObject();
		QTSS_Error err = relaySes->Start();
		sClientSessionMap->Release(theRelaySessionRef);
	}
	else
	{
		return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerInternal, 0);
	}

    (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, flags);
    return QTSS_NoErr;
}
Пример #9
0
Bool16 IsAuthentic(QTSS_Filter_Params* inParams,StringParser *fullRequestPtr)
{
    Bool16 isAuthentic = false;

    if (!sAuthenticationEnabled) // no authentication
    {
        isAuthentic = true;
    }
    else // must authenticate
    {
        StrPtrLen theClientIPAddressStr;
        (void) QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void**)&theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len);
        Bool16 isLocal =  IPComponentStr(&theClientIPAddressStr).IsLocal(); 
        
        StrPtrLen authenticateName;
        StrPtrLen authenticatePassword;
        StrPtrLen authType;
        Bool16 hasAuthentication = HasAuthentication(fullRequestPtr,&authenticateName,&authenticatePassword, &authType);               
        if (hasAuthentication) 
        {
            if (authType.Equal(sAuthRef))
            {    
                if (isLocal)
                    isAuthentic = OSXAuthenticate(&authenticatePassword);
            }
            else
                isAuthentic = Authenticate(inParams->inRTSPRequest, &authenticateName,&authenticatePassword);
       }
    }
//    if (isAuthentic)
//        isAuthentic = AuthorizeAdminRequest(inParams->inRTSPRequest);
    (void) QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&isAuthentic, sizeof(isAuthentic));

    return isAuthentic;
}
/**
 * For the given RTSP session, will return true if the client is already flagged
 * as authenticated, false if they arent. if the value is not initialized, this
 * method will intitialize it. This is used to ensure a session is only authenticated
 * once.
 */
static Bool16 IsRTSPSessionAuthenticated(QTSS_RTSPSessionObject* theRTSPSession) {
    printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated method start\n");
    Bool16* alreadyAuthenticated = false;
    UInt32 theLen = 0;
    QTSS_Error getAlreadyAuthError = QTSS_GetValuePtr(*theRTSPSession, attrRtspSessionAuthenticated, 0, (void**)&alreadyAuthenticated, &theLen);
    //printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated read value of already aythenticated: &i\n", alreadyAuthenticated);
    if (getAlreadyAuthError == QTSS_ValueNotFound) {
        // the value hasn't been set yet. initialize it to false, and return false.
        // TODO - check how to set a default variable (if possible), so we don't have to rely on this.
        
        Bool16 authenticated = false;
      
        (void)QTSS_SetValue(*theRTSPSession, attrRtspSessionAuthenticated, 0,  &authenticated, sizeof(authenticated));
        
        // we had to initialize, so def. not logged in
        return false;
    }
    else if (*alreadyAuthenticated) {
        // we are already logged in
        printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated session already authenticated\n");
        return true;
    }
    else if (!*alreadyAuthenticated && getAlreadyAuthError == QTSS_NoErr) {
        // we are not authed and there was no error, to return
        return false;
    }
    else {
        //printf("QTSSIcecastAuthModule::RTSPFilter ERROR while looking up not logged in\n");
        PrintQTSSError("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated", "while looking up not logged in", getAlreadyAuthError);
        return false;
    }
}
kern_return_t StopServer(int inMinutes)
{
    //if time is -1, we're supposed to wait until all clients have disconnected
    if (inMinutes == -1)
    {
        QTSS_ServerState theState = qtssRefusingConnectionsState;
        (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theState, sizeof(theState));
        sGracefulShutdownInProgress = true;
    }
    else
    {
        //just set the server state to shutting down
        QTSS_ServerState theShutDownState = qtssShuttingDownState;
        (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theShutDownState, sizeof(theShutDownState));
    }
    return SCNoError;
}
Пример #12
0
void    QTSSModuleUtils::SetupSupportedMethods(QTSS_Object inServer, QTSS_RTSPMethod* inMethodArray, UInt32 inNumMethods)
{
    // Report to the server that this module handles DESCRIBE, SETUP, PLAY, PAUSE, and TEARDOWN
    UInt32 theNumMethods = 0;
    (void)QTSS_GetNumValues(inServer, qtssSvrHandledMethods, &theNumMethods);
    
    for (UInt32 x = 0; x < inNumMethods; x++)
        (void)QTSS_SetValue(inServer, qtssSvrHandledMethods, theNumMethods++, (void*)&inMethodArray[x], sizeof(inMethodArray[x]));
}
Пример #13
0
QTSS_Error Initialize(QTSS_Initialize_Params* inParams)
{

    // Setup module utils
    QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream);

    // Get the server object
    sServer = inParams->inServer;
    
    // Get our prefs object
    sModule = inParams->inModule;
    sModulePrefs = QTSSModuleUtils::GetModulePrefsObject(sModule);

    // Set our version and description
    (void)QTSS_SetValue(sModule, qtssModDesc, 0, sDescription, ::strlen(sDescription));   
    (void)QTSS_SetValue(sModule, qtssModVersion, 0, &sVersion, sizeof(sVersion)); 

    RereadPrefs();
    return QTSS_NoErr;
}
QTSS_Error Authorize(QTSS_StandardRTSP_Params* inParams)
{
    static Bool16 sTrue = true;
    
    Bool16* isFirstRequest = NULL;
    UInt32* theIPAddr = NULL;
    UInt32 theLen = 0;
    
    // Only do anything if this is the first request
    (void)QTSS_GetValuePtr(inParams->inRTSPSession, sIsFirstRequestAttr, 0, (void**)&isFirstRequest, &theLen);
    if (isFirstRequest != NULL)
        return QTSS_NoErr;
        
    // Get the IP address of this client.
    (void)QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddr, 0, (void**)&theIPAddr, &theLen);
    if ((theIPAddr == NULL) || (theLen != sizeof(UInt32)))
    {
        Assert(0);
        return QTSS_NoErr;
    }

    IPAddrTableKey theKey(*theIPAddr);
    
    // This must be atomic
    OSMutexLocker locker(sMutex);

    // Check to see if this client currently has a connection open.
    IPAddrTableElem* theElem = sHashTable->Map(&theKey);
    if (theElem == NULL)
    {
        // Client doesn't have a connetion open currently. Create a map element,
        // and add it into the map.
        theElem = NEW IPAddrTableElem(*theIPAddr);
        sHashTable->Add(theElem);
    }
    
    // Check to see if this client has too many connections open. If it does,
    // return an error, otherwise, allow the connection and increment the
    // refcount.
    if (theElem->GetRefCount() >= sNumConnsPerIP)
        return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientForbidden,
                                                    sTooManyConnectionsErr);
    else
        theElem->IncrementRefCount();
        
    // Mark the request so we'll know subsequent ones aren't the first.
    // Note that we only do this if we've successfully added this client to our map.
    // That way, we only remove it in SessionClosing if we've added it.
    (void)QTSS_SetValue(inParams->inRTSPSession, sIsFirstRequestAttr, 0, &sTrue, sizeof(sTrue));
    
    return QTSS_NoErr;
}
Пример #15
0
void RTPSessionOutput::InitializeStreams()
{ 
        
    UInt32                  theLen = 0;
    QTSS_RTPStreamObject*   theStreamPtr = NULL;
    UInt32                  packetCountInitValue = 0;
    
    for (SInt16 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&theStreamPtr, &theLen) == QTSS_NoErr; z++)
    {
        (void) QTSS_SetValue(*theStreamPtr, sStreamPacketCountAttr, 0, &packetCountInitValue, sizeof(UInt32));
    }

}
Пример #16
0
QTSS_Error PostProcess(QTSS_StandardRTSP_Params* inParams)
{
	static UInt32 sZero = 0;

	UInt32* theStatus = NULL;
	UInt32 theLen = 0;
	QTSS_Error theErr = QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqRealStatusCode, 0, (void**)&theStatus, &theLen);
	if (theErr != QTSS_NoErr)
		return theErr;

	QTSS_CliSesClosingReason theReason = qtssCliSesCloseClientTeardown;

	if ((*theStatus == 401) || (*theStatus == 403))
	{
		LogRequest(inParams->inClientSession, NULL, &theReason);
		(void)QTSS_SetValue(inParams->inClientSession, sLoggedAuthorizationAttrID, 0, theStatus, sizeof(*theStatus));
	}
	else
		(void)QTSS_SetValue(inParams->inClientSession, sLoggedAuthorizationAttrID, 0, &sZero, sizeof(sZero));

	return theErr;
}
Пример #17
0
inline Bool16 GetRequestAuthenticatedState(QTSS_Filter_Params* inParams) 
{
    Bool16 result = false;
    UInt32 paramLen = sizeof(result);
    QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, &paramLen);
    if(err != QTSS_NoErr)
    {
           paramLen = sizeof(result);
           result = false;
           err =QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, paramLen);
    }     
    return result;
}
Пример #18
0
inline Bool16 GetRequestFlushState(QTSS_Filter_Params* inParams)
{   Bool16 result = false;
    UInt32 paramLen = sizeof(result);
    QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, &paramLen);
    if (err != QTSS_NoErr)
    {   paramLen = sizeof(result);
        result = false;
        //qtss_printf("no flush val so set to false session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err);
        err =QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, paramLen);
        //qtss_printf("QTSS_SetValue flush session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err);
    }
    return result;
}
Пример #19
0
QTSS_Error HTTPSessionInterface::RegDevSession(const char* serial, UInt32 serailLen)
{
	if((::strlen(serial) == 0) || (serailLen == 0))
		return QTSS_ValueNotFound;
	fSessionType = qtssDeviceSession;
	QTSS_SetValue(this, qtssEasySesSerial, 0, serial, serailLen);

	fDevSerialPtr.Set( fSerial, serailLen);
	fDevRef.Set( fDevSerialPtr, this);
	OS_Error theErr = QTSServerInterface::GetServer()->GetRecordSessionMap()->Register(GetRef());
	//printf("[line:%d]HTTPSessionInterface::RegDevSession theErr = %d\n",__LINE__, theErr);
	if(theErr == OS_NoErr)
		fAuthenticated = true;
	return theErr;
}
Пример #20
0
void RunServer()
{   
    Bool16 restartServer = false;
    UInt32 loopCount = 0;
    UInt32 debugLevel = 0;
    Bool16 printHeader = false;
    Bool16 printStatus = false;


    //just wait until someone stops the server or a fatal error occurs.
    QTSS_ServerState theServerState = sServer->GetServerState();
    while ((theServerState != qtssShuttingDownState) &&
            (theServerState != qtssFatalErrorState))
    {
#ifdef __sgi__
        OSThread::Sleep(999);
#else
        OSThread::Sleep(1000);
#endif
        
        if ((sServer->SigIntSet()) || (sServer->SigTermSet()))
        {
            //
            // start the shutdown process
            theServerState = qtssShuttingDownState;
            (void)QTSS_SetValue(QTSServerInterface::GetServer(), qtssSvrState, 0, &theServerState, sizeof(theServerState));

            if (sServer->SigIntSet())
                restartServer = true;
        }
    }
        
    //Now, make sure that the server can't do any work
    TaskThreadPool::RemoveThreads();
    
    //now that the server is definitely stopped, it is safe to initate
    //the shutdown process
    delete sServer;
    
    CleanPid(false);
    //ok, we're ready to exit. If we're quitting because of some fatal error
    //while running the server, make sure to let the parent process know by
    //exiting with a nonzero status. Otherwise, exit with a 0 status
    if (theServerState == qtssFatalErrorState || restartServer)
        ::exit (-2);//-2 signals parent process to restart server
}
kern_return_t SetRefuseConnections(QTSRefuseConnectionsRec* inRefuseConnections)
{
    //make sure not to allow people to stop the server from refusing connections when it
    //is in the process of a graceful shutdown. The only way to stop this is to call
    //CancelStopServer
    if (sGracefulShutdownInProgress)
        return SCServerShuttingDown;

    QTSS_ServerState theState = qtssRunningState;
    UInt32 theSize = sizeof(theState);

    if (inRefuseConnections->refuseConnections != 0)
        theState = qtssRefusingConnectionsState;

    (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theState, theSize);
    return SCNoError;
}
Пример #22
0
QTSS_Error DestroySession(QTSS_ClientSessionClosing_Params* inParams)
{
    ProxyClientInfo* theClient = NULL;
    UInt32 theLen = sizeof(theClient);
    QTSS_Error theErr = QTSS_GetValue(inParams->inClientSession, sProxyClientInfoAttr, 0,
                                                                &theClient, &theLen);

    if (theErr != QTSS_NoErr)
        return theErr;
        
    delete theClient;
    
    //
    // NULL out the attribute so in case there is a race condition no one will
    // get this dangling pointer
    (void)QTSS_SetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, NULL, 0);
    return QTSS_NoErr;
}
Пример #23
0
QTSS_Error RelaySession::SetupRelaySession(SourceInfo* inInfo)
{
    QTSS_Error theErr = QTSS_NoErr;
    theErr = this->SetupReflectorSession(inInfo, NULL);
    
    if (theErr != QTSS_NoErr)
        return theErr;
        
    // create the reflector session object for this session
    UInt32 outIndex = 0;
    fRelaySessionObject = NULL;
        
        theErr = QTSS_LockObject(relayModuleAttributesObject);
        Assert(theErr == QTSS_NoErr);
        
    theErr = QTSS_CreateObjectValue (relayModuleAttributesObject , sRelaySessionObjectID, qtssRelaySessionObjectType, &outIndex, &fRelaySessionObject);
    Assert(theErr == QTSS_NoErr);
   
    if (fRelaySessionObject == NULL)
        return theErr;
        
        // set the values for all the static attributes in this session
    
    char* relayName = inInfo->Name();       // name of the relay
        if (relayName != NULL)
            theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)relayName, ::strlen(relayName));
        else
            theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)sEmptyStr.Ptr, sEmptyStr.Len);
        Assert(theErr == QTSS_NoErr);


    StrPtrLen sourceStr;            // type of source

    if (inInfo->IsRTSPSourceInfo())
    {       
        if (((RTSPSourceInfo*)inInfo)->IsAnnounce())
            sourceStr.Set(sAnnouncedSourceStr.Ptr, sAnnouncedSourceStr.Len);
        else
            sourceStr.Set(sRTSPSourceStr.Ptr, sRTSPSourceStr.Len);
    }
    else
        sourceStr.Set(sUDPSourceStr.Ptr, sUDPSourceStr.Len);
    
    theErr = QTSS_SetValue (fRelaySessionObject, sSourceType, 0, (void*)sourceStr.Ptr, sourceStr.Len);
    Assert(theErr == QTSS_NoErr);
    
    char theIPAddrBuf[20];          
    StrPtrLen theIPAddr(theIPAddrBuf, 20);
    
    struct in_addr theSrcAddr;      // source ip address
    theSrcAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fSrcIPAddr);
    SocketUtils::ConvertAddrToString(theSrcAddr, &theIPAddr);   
    
    theErr = QTSS_SetValue (fRelaySessionObject, sSourceIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
    Assert(theErr == QTSS_NoErr);
    
    struct in_addr theDestAddr;     // dest (of source) ip address
    theDestAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fDestIPAddr);
    SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr);
    
    theErr = QTSS_SetValue (fRelaySessionObject, sSourceInIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
    Assert(theErr == QTSS_NoErr);
    
    
    for (UInt32 index = 0; index < (inInfo->GetNumStreams()); index++)  // source udp ports
    {
        UInt16 udpPort = inInfo->GetStreamInfo(index)->fPort;
        theErr = QTSS_SetValue (fRelaySessionObject, sSourceUDPPorts, index, &udpPort, sizeof(udpPort));
                Assert(theErr == QTSS_NoErr);
    }
    
    if (inInfo->IsRTSPSourceInfo())     
    {
        RTSPSourceInfo* rtspInfo = (RTSPSourceInfo*)inInfo;
        if (!rtspInfo->IsAnnounce())
        {
            UInt16 rtspPort = (UInt16) rtspInfo->GetHostPort();
            char* username = rtspInfo->GetUsername();
            char* password = rtspInfo->GetPassword();
            theErr = QTSS_SetValue (fRelaySessionObject, sSourceRTSPPort, 0, &rtspPort, sizeof(rtspPort));  // source rtsp port
                        Assert(theErr == QTSS_NoErr);
                        
            theErr = QTSS_SetValue (fRelaySessionObject, sSourceUsername, 0, username, sizeof(username));   // source username
                        Assert(theErr == QTSS_NoErr);
                        
            theErr = QTSS_SetValue (fRelaySessionObject, sSourcePassword, 0, password, sizeof(password));   // source password  
                        Assert(theErr == QTSS_NoErr);
        }
        
        char* url = rtspInfo->GetSourceURL();
        theErr = QTSS_SetValue (fRelaySessionObject, sSourceURL, 0, url, ::strlen(url));
                Assert(theErr == QTSS_NoErr);                   // source url
    }

        UInt16 ttl = inInfo->GetStreamInfo(0)->fTimeToLive;
        theErr = QTSS_SetValue (fRelaySessionObject, sSourceTTL, 0, &ttl, sizeof(ttl)); // source ttl
        Assert(theErr == QTSS_NoErr);
        
        theErr = QTSS_UnlockObject(relayModuleAttributesObject);
        Assert(theErr == QTSS_NoErr);
        
        return QTSS_NoErr;
}
Пример #24
0
void RTPSessionOutput::TearDown()
{
    QTSS_CliSesTeardownReason reason = qtssCliSesTearDownBroadcastEnded;
    (void)QTSS_SetValue(fClientSession, qtssCliTeardownReason, 0, &reason, sizeof(reason));     
    (void)QTSS_Teardown(fClientSession);
}
Пример #25
0
// this routine is not used
Bool16 RTPSessionOutput::PacketShouldBeThinned(QTSS_RTPStreamObject inStream, StrPtrLen* inPacket)
{
    return false; // function is disabled.
    
    static UInt16 sZero = 0;
    //This function determines whether the packet should be dropped.
    //It also adjusts the sequence number if necessary

    if (inPacket->Len < 4)
        return false;
    
    UInt16 curSeqNum = this->GetPacketSeqNumber(inPacket);
    UInt32* curQualityLevel = NULL;
    UInt16* nextSeqNum = NULL;
    UInt16* theSeqNumOffset = NULL;
    SInt64* lastChangeTime = NULL;
    
    UInt32 theLen = 0;
    (void)QTSS_GetValuePtr(inStream, qtssRTPStrQualityLevel, 0, (void**)&curQualityLevel, &theLen);
    if ((curQualityLevel == NULL) || (theLen != sizeof(UInt32)))
        return false;
    (void)QTSS_GetValuePtr(inStream, sNextSeqNumAttr, 0, (void**)&nextSeqNum, &theLen);
    if ((nextSeqNum == NULL) || (theLen != sizeof(UInt16)))
    {
        nextSeqNum = &sZero;
        (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, nextSeqNum, sizeof(UInt16));
    }
    (void)QTSS_GetValuePtr(inStream, sSeqNumOffsetAttr, 0, (void**)&theSeqNumOffset, &theLen);
    if ((theSeqNumOffset == NULL) || (theLen != sizeof(UInt16)))
    {
        theSeqNumOffset = &sZero;
        (void)QTSS_SetValue(inStream, sSeqNumOffsetAttr, 0, theSeqNumOffset, sizeof(UInt16));
    }
    UInt16 newSeqNumOffset = *theSeqNumOffset;
    
    (void)QTSS_GetValuePtr(inStream, sLastQualityChangeAttr, 0, (void**)&lastChangeTime, &theLen);
    if ((lastChangeTime == NULL) || (theLen != sizeof(SInt64)))
    {   static SInt64 startTime = 0;
        lastChangeTime = &startTime;
        (void)QTSS_SetValue(inStream, sLastQualityChangeAttr, 0, lastChangeTime, sizeof(SInt64));
    }
    
    SInt64 timeNow = OS::Milliseconds();
    if (*lastChangeTime == 0 || *curQualityLevel == 0) 
        *lastChangeTime =timeNow;
    
    if (*curQualityLevel > 0 && ((*lastChangeTime + 30000) < timeNow) ) // 30 seconds between reductions
    {   *curQualityLevel -= 1; // reduce quality value.  If we quality doesn't change then we may have hit some steady state which we can't get out of without thinning or increasing the quality
        *lastChangeTime =timeNow; 
        //qtss_printf("RTPSessionOutput set quality to %"_U32BITARG_"\n",*curQualityLevel);
    }

    //Check to see if we need to drop to audio only
    if ((*curQualityLevel >= ReflectorSession::kAudioOnlyQuality) &&
        (*nextSeqNum == 0))
    {
#if REFLECTOR_THINNING_DEBUGGING || RTP_SESSION_DEBUGGING
        qtss_printf(" *** Reflector Dropping to audio only *** \n");
#endif
        //All we need to do in this case is mark the sequence number of the first dropped packet
        (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, &curSeqNum, sizeof(UInt16));  
         *lastChangeTime =timeNow;  
    }
    
    
    //Check to see if we can reinstate video
    if ((*curQualityLevel == ReflectorSession::kNormalQuality) && (*nextSeqNum != 0))
    {
        //Compute the offset amount for each subsequent sequence number. This offset will
        //alter the sequence numbers so that they increment normally (providing the illusion to the
        //client that there are no missing packets)
        newSeqNumOffset = (*theSeqNumOffset) + (curSeqNum - (*nextSeqNum));
        (void)QTSS_SetValue(inStream, sSeqNumOffsetAttr, 0, &newSeqNumOffset, sizeof(UInt16));
        (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, &sZero, sizeof(UInt16));
    }
    
    //tell the caller whether to drop this packet or not.
    if (*curQualityLevel >= ReflectorSession::kAudioOnlyQuality)
        return true;
    else
    {
        //Adjust the sequence number of the current packet based on the offset, if any
        curSeqNum -= newSeqNumOffset;
        this->SetPacketSeqNumber(inPacket, curSeqNum);
        return false;
    }
}
Пример #26
0
QTSS_Error  RTPSessionOutput::WritePacket(StrPtrLen* inPacket, void* inStreamCookie, UInt32 inFlags, SInt64 packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr, Bool16 firstPacket)
{
    QTSS_RTPSessionState*   theState = NULL;
    UInt32                  theLen = 0;
    QTSS_Error              writeErr = QTSS_NoErr;
    SInt64                  currentTime = OS::Milliseconds();
    
 	if (inPacket == NULL || inPacket->Len == 0)
		return QTSS_NoErr;

 
	(void)QTSS_GetValuePtr(fClientSession, qtssCliSesState, 0, (void**)&theState, &theLen);
    if (theLen == 0 || theState == NULL || *theState != qtssPlayingState)
    {   //qtss_printf("QTSS_WouldBlock *theState=%d qtssPlayingState=%d\n", *theState , qtssPlayingState);
        return QTSS_WouldBlock;
    }
    
    //make sure all RTP streams with this ID see this packet
    QTSS_RTPStreamObject *theStreamPtr = NULL;
                                  
    for (UInt32 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&theStreamPtr, &theLen) == QTSS_NoErr; z++)
    {
        if (this->PacketMatchesStream(inStreamCookie, theStreamPtr))
        { 
            if (  (inFlags & qtssWriteFlagsIsRTP) && this->FilterPacket(theStreamPtr, inPacket) )
                return  QTSS_NoErr; // keep looking at packets
                
            if (this->PacketAlreadySent(theStreamPtr,inFlags, packetIDPtr)) 
                return QTSS_NoErr; // keep looking at packets
                
            if (!this->PacketReadyToSend(theStreamPtr,&currentTime, inFlags, packetIDPtr, timeToSendThisPacketAgain)) 
            {   //qtss_printf("QTSS_WouldBlock\n");
                return QTSS_WouldBlock; // stop not ready to send packets now
            }
                                          
    
       // TrackPackets below is for re-writing the rtcps we don't use it right now-- shouldn't need to    
       // (void) this->TrackPackets(theStreamPtr, inPacket, &currentTime,inFlags,  &packetLatenessInMSec, timeToSendThisPacketAgain, packetIDPtr,arrivalTimeMSecPtr);

            QTSS_PacketStruct thePacket;
            thePacket.packetData = inPacket->Ptr;
            SInt64 delayMSecs = fBufferDelayMSecs - (currentTime - *arrivalTimeMSecPtr);
            thePacket.packetTransmitTime = (currentTime - packetLatenessInMSec);
            if (fBufferDelayMSecs > 0 ) 
                thePacket.packetTransmitTime += delayMSecs; // add buffer time where oldest buffered packet as now == 0 and newest is entire buffer time in the future.
 
            writeErr = QTSS_Write(*theStreamPtr, &thePacket, inPacket->Len, NULL, inFlags | qtssWriteFlagsWriteBurstBegin); 
            if (writeErr == QTSS_WouldBlock)
            {  
                 //qtss_printf("QTSS_Write == QTSS_WouldBlock\n");
                //
                // We are flow controlled. See if we know when flow control will be lifted and report that
                *timeToSendThisPacketAgain = thePacket.suggestedWakeupTime;
                 
                if (firstPacket)
                {   fBufferDelayMSecs = (currentTime - *arrivalTimeMSecPtr);
                    //qtss_printf("firstPacket fBufferDelayMSecs =%lu \n", fBufferDelayMSecs);
                } 
            }
            else
            {   
                fLastIntervalMilliSec = currentTime - fLastPacketTransmitTime;
                if (fLastIntervalMilliSec > 100) //reset interval maybe first packet or it has been blocked for awhile
                    fLastIntervalMilliSec = 5;
                fLastPacketTransmitTime = currentTime;

                if (inFlags & qtssWriteFlagsIsRTP)
                {
                    (void) QTSS_SetValue (*theStreamPtr, sLastRTPPacketIDAttr, 0, packetIDPtr, sizeof(UInt64));
                }
                else if (inFlags & qtssWriteFlagsIsRTCP)
                {
                    (void) QTSS_SetValue (*theStreamPtr, sLastRTCPPacketIDAttr, 0, packetIDPtr, sizeof(UInt64));                            
                    (void) QTSS_SetValue (*theStreamPtr, sLastRTCPTransmitAttr, 0, &currentTime, sizeof(UInt64));
                }
                       
                       
                       
               { // increment packet counts
                    UInt32* packetCountPtr = NULL;
                    UInt32 theLen = 0;
                    
                    (void) QTSS_GetValuePtr(*theStreamPtr, sStreamPacketCountAttr, 0,(void**) &packetCountPtr,&theLen);
                    if (theLen > 0)
                    {   *packetCountPtr += 1;
                        //printf("SET sStreamPacketCountAttr =%lu\n", *packetCountPtr);
                    }
               }
           }
        }

        if ( writeErr != QTSS_NoErr )
            break;
    }
        
    return writeErr;
}
Пример #27
0
QTSS_Error  RTPSessionOutput::TrackRTPPackets(QTSS_RTPStreamObject *theStreamPtr, StrPtrLen* inPacketStrPtr, SInt64 *currentTimePtr, UInt32 inFlags, SInt64* packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr)
{
    QTSS_Error writeErr = QTSS_NoErr;

    Assert(inFlags & qtssWriteFlagsIsRTP);

    if (!(inFlags & qtssWriteFlagsIsRTP))
        return QTSS_NoErr;
    
    ReflectorPacket packetContainer;
    packetContainer.SetPacketData(inPacketStrPtr->Ptr, inPacketStrPtr->Len);
    packetContainer.fIsRTCP = false;
    SInt64 *theTimePtr = NULL;
    UInt32 theLen = 0;
    
    if (QTSS_NoErr != QTSS_GetValuePtr(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, (void**)&theTimePtr, &theLen))
    {                   
        UInt32 theSSRC = packetContainer.GetSSRC(packetContainer.fIsRTCP);
        (void) QTSS_SetValue(*theStreamPtr, sStreamSSRCAttr, 0, &theSSRC, sizeof(theSSRC));
        
        UInt32 rtpTime = packetContainer.GetPacketRTPTime();
        writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPTimeStampAttr, 0, &rtpTime, sizeof(rtpTime));
        Assert(writeErr == QTSS_NoErr);
        
        writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, arrivalTimeMSecPtr, sizeof(SInt64));
        Assert(writeErr == QTSS_NoErr);
        
        writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPCurrentTimeAttr, 0, currentTimePtr, sizeof(SInt64));
        Assert(writeErr == QTSS_NoErr);

        UInt32 initValue = 0;
        writeErr = QTSS_SetValue(*theStreamPtr, sStreamByteCountAttr, 0, &initValue, sizeof(UInt32));
        Assert(writeErr == QTSS_NoErr);
        
        //printf("first rtp on stream stream=%"_U32BITARG_" ssrc=%"_U32BITARG_" rtpTime=%"_U32BITARG_" arrivalTimeMSecPtr=%qd currentTime=%qd\n",(UInt32) theStreamPtr, theSSRC, rtpTime, *arrivalTimeMSecPtr, *currentTimePtr);
        
    }
    else
    {
        UInt32* packetCountPtr = NULL;
        UInt32* byteCountPtr = NULL;
        UInt32 theLen = 0;
                
        writeErr = QTSS_GetValuePtr(*theStreamPtr, sStreamByteCountAttr, 0, (void**) &byteCountPtr,&theLen);
        if (writeErr == QTSS_NoErr && theLen > 0)
            *byteCountPtr += inPacketStrPtr->Len - 12;// 12 header bytes
            
            
       UInt32* theSSRCPtr = 0;
        (void) QTSS_GetValuePtr(*theStreamPtr, sStreamSSRCAttr, 0, (void**)&theSSRCPtr, &theLen);
        if (*theSSRCPtr != packetContainer.GetSSRC(packetContainer.fIsRTCP))
        {    

           
           (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPArrivalTimeAttr,0);
           (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPTimeStampAttr,0);
           (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPCurrentTimeAttr,0);
           (void) QTSS_RemoveValue(*theStreamPtr,sStreamPacketCountAttr,0);
           (void) QTSS_RemoveValue(*theStreamPtr,sStreamByteCountAttr,0);
           fMustSynch = true;
           
           //printf("found different ssrc =%"_U32BITARG_" packetssrc=%"_U32BITARG_"\n",*theSSRCPtr, packetContainer.GetSSRC(packetContainer.fIsRTCP));
           
        }
        
              
            
    } 
    
    return writeErr; 

}
Пример #28
0
QTSS_Error  RTPSessionOutput::TrackRTCPBaseTime(QTSS_RTPStreamObject *theStreamPtr, StrPtrLen* inPacketStrPtr, SInt64 *currentTimePtr, UInt32 inFlags, SInt64* packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr)
{
    Bool16 haveBaseTime = false;
    Bool16 haveAllFirstRTPs = true;
    
    UInt32 streamTimeScale = 0;
    UInt32  theLen =  sizeof(streamTimeScale);
    QTSS_Error writeErr = QTSS_GetValue(*theStreamPtr, qtssRTPStrTimescale, 0, (void *) &streamTimeScale, &theLen);
    Assert(writeErr == QTSS_NoErr);
         
    UInt32 baseTimeStamp = 0;
    theLen = sizeof(baseTimeStamp);
    if (!fMustSynch || QTSS_NoErr ==  QTSS_GetValue(*theStreamPtr, sBaseRTPTimeStampAttr, 0, (void*)&baseTimeStamp, &theLen) ) // we need a starting stream time that is synched 
    {
        haveBaseTime = true;
    }
    else
    {
        UInt64 earliestArrivalTime = ~(UInt64) 0; //max value
        UInt32 firstStreamTime = 0;
        SInt64 firstStreamArrivalTime = 0;
        QTSS_RTPStreamObject *findStream = NULL;
        
        if (fMustSynch || QTSS_NoErr != QTSS_GetValuePtr(*theStreamPtr, sBaseArrivalTimeStampAttr, 0, (void**)&fBaseArrivalTime, &theLen)  )
        {   // we don't have a base arrival time for the session see if we can set one now.
        
            for (SInt32 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&findStream, &theLen) == QTSS_NoErr; z++)
            {
                SInt64* firstArrivalTimePtr = NULL;
                if (QTSS_NoErr != QTSS_GetValuePtr(*findStream, sFirstRTPArrivalTimeAttr, 0, (void**)&firstArrivalTimePtr, &theLen))
                {// no packet on this stream yet 
                    haveAllFirstRTPs = false; // not enough info to calc a base time
                    break;
                }
                else
                { // we have an arrival time see if it is the first for all streams
                   if ( (UInt64) *firstArrivalTimePtr < earliestArrivalTime )
                    {
                        earliestArrivalTime = *firstArrivalTimePtr;
                    }
                }

            }
        
            if (haveAllFirstRTPs) // we can now create a base arrival time and base stream time from that
            {
                
                writeErr = QTSS_SetValue(*theStreamPtr, sBaseArrivalTimeStampAttr, 0, &earliestArrivalTime, sizeof(SInt64));
                Assert(writeErr == QTSS_NoErr);
                fBaseArrivalTime = (SInt64) earliestArrivalTime;
            }
        }
        
        if (haveAllFirstRTPs)//sBaseRTPTimeStamp
        {   // we don't have a base stream time but we have a base session time so calculate the base stream time.
            theLen = sizeof(firstStreamTime);
            if (QTSS_NoErr != QTSS_GetValue(*theStreamPtr, sFirstRTPTimeStampAttr, 0, (void*)&firstStreamTime, &theLen))
                return QTSS_NoErr;
              
            theLen = sizeof(firstStreamArrivalTime);  
            if (QTSS_NoErr != QTSS_GetValue(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, (void*)&firstStreamArrivalTime, &theLen))
                return QTSS_NoErr;

            SInt64 arrivalTimeDiffMSecs = (firstStreamArrivalTime - fBaseArrivalTime);// + fBufferDelayMSecs;//add the buffer delay !! not sure about faster than real time arrival times....
            UInt32 timeDiffStreamTime = (UInt32)( ( (Float64) arrivalTimeDiffMSecs/(Float64) 1000.0) * (Float64) streamTimeScale );
            baseTimeStamp = firstStreamTime - timeDiffStreamTime;
            if (QTSS_NoErr == QTSS_SetValue(*theStreamPtr, sBaseRTPTimeStampAttr, 0, (void*)&baseTimeStamp, sizeof(baseTimeStamp)))
                haveBaseTime = true;               
             
            (void) QTSS_SetValue(*theStreamPtr, qtssRTPStrFirstTimestamp, 0, &baseTimeStamp, sizeof(baseTimeStamp));   
            
            fMustSynch = false;
            //printf("fBaseArrivalTime =%qd baseTimeStamp %"_U32BITARG_" streamStartTime=%qd diff =%qd\n", fBaseArrivalTime, baseTimeStamp, firstStreamArrivalTime, arrivalTimeDiffMSecs);
        }
    }

    return writeErr;

}
Пример #29
0
QTSS_Error ProcessRTSPRequest(QTSS_StandardRTSP_Params* inParams)
{
    ProxyClientInfo* theClient = NULL;
    UInt32 theLen = sizeof(theClient);
    QTSS_Error theErr = QTSS_GetValue(inParams->inClientSession, sProxyClientInfoAttr, 0,
                                                                &theClient, &theLen);

    //
    // If there is no client yet, this is the first request made on this session.
    // Create an RTSPClient
    if (theErr != QTSS_NoErr)
    {
        theClient = NEW ProxyClientInfo();
        
        //
        // Parse out the DNS name of the origin server and the port
        StrPtrLen theDNSNameAndPort;
        theErr = QTSS_GetValuePtr(inParams->inRTSPHeaders, qtssHostHeader, 0, (void**)&theDNSNameAndPort.Ptr, &theDNSNameAndPort.Len);
        Assert(theErr == QTSS_NoErr);
        
        StringParser extractPortNumber(&theDNSNameAndPort);
        
        StrPtrLen theDNSNamePtr;
        extractPortNumber.GetThru(&theDNSNamePtr, ':');
        UInt32 thePort = extractPortNumber.ConsumeInteger(NULL);
        
        //
        // For now, if there was no port specified, use 554
        if (thePort == 0)
            thePort = 554;
            
        //
        // Make sure the port is in the range of a 2-byte integer
        if (thePort > 65536)
            return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest,
                                                        sPortNumberTooBigErr);
        
        //
        // gethostbyname takes a NULL terminated C-string
        OSCharArrayDeleter theDNSName(theDNSNamePtr.GetAsCString());

        //
        // Do a DNS lookup on the host to find its IP address
        struct hostent* theHostent = ::gethostbyname(theDNSName);
        
        UInt32 theIPAddr = 0;
        if (theHostent != NULL)
            theIPAddr = ntohl(*(UInt32*)(theHostent->h_addr_list[0]));
        else
            theIPAddr = SocketUtils::ConvertStringToAddr(theDNSName);
            
        //
        // Give this information to the ClientSocket object
        theClient->GetRTSPClient()->GetSocket()->Set(theIPAddr, (UInt16)thePort);
        
        theErr = QTSS_SetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, &theClient, sizeof(theClient));
        Assert(theErr == QTSS_NoErr);

        //
        // Start the process of connecting to the origin server, first
        // just by telling the ClientSocket to send an empty message
        theErr = theClient->GetRTSPClient()->GetSocket()->Send(NULL, 0);
        if (theErr != QTSS_NoErr)
            //
            // we are connecting. This function will be called when connection is set up
            return HandleRTSPClientErr(inParams->inRTSPRequest, theClient, theErr);
    }
    
    //
    // If we aren't in the middle of sending a request, we have to set it up
    if (!theClient->GetRTSPClient()->IsTransactionInProgress())
        theErr = DoRequestPreProcessing(theClient, inParams->inRTSPRequest, inParams->inClientSession);
    else
        //
        // Continue our attempt to send this request
        theErr = theClient->GetRTSPClient()->DoTransaction();
    
    if (theErr != QTSS_NoErr)
        HandleRTSPClientErr(inParams->inRTSPRequest, theClient, theErr);
    else
        //
        // The response has come back from the origin server. Do whatever
        // processing we need on it, and send the response to the proxy client.
        theErr = DoRequestPostProcessing(theClient, inParams->inRTSPRequest, inParams->inClientSession);

    return theErr;
}
Пример #30
0
void RelayOutput::SetupRelayOutputObject(RTSPOutputInfo* inRTSPInfo)
{
	fRelaySessionObject = fRelaySession->GetRelaySessionObject();
	UInt32 outIndex = 0;

	QTSS_Error theErr = QTSS_LockObject(fRelaySessionObject);
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_CreateObjectValue(fRelaySessionObject, RelaySession::sRelayOutputObject, qtssRelayOutputObjectType, &outIndex, &fRelayOutputObject);
	Assert(theErr == QTSS_NoErr);

	if ((inRTSPInfo == NULL) || !inRTSPInfo->fIsAnnounced)          // output type
	{
		theErr = QTSS_SetValue(fRelayOutputObject, sOutputType, 0, (void*)sUDPDestStr.Ptr, sUDPDestStr.Len);
		Assert(theErr == QTSS_NoErr);
	}
	else
	{
		theErr = QTSS_SetValue(fRelayOutputObject, sOutputType, 0, (void*)sAnnouncedDestStr.Ptr, sAnnouncedDestStr.Len); // output type
		Assert(theErr == QTSS_NoErr);

		theErr = QTSS_SetValue(fRelayOutputObject, sOutputRTSPPort, 0, &inRTSPInfo->fAnnouncePort, sizeof(inRTSPInfo->fAnnouncePort)); // rtsp port
		Assert(theErr == QTSS_NoErr);

		theErr = QTSS_SetValue(fRelayOutputObject, sOutputURL, 0, (fClient->GetURL())->Ptr, (fClient->GetURL())->Len); // output url
		Assert(theErr == QTSS_NoErr);
	}

	char theIPAddrBuf[20];
	StrPtrLen theIPAddr(theIPAddrBuf, 20);

	struct in_addr theDestAddr;     // output destination address
	theDestAddr.s_addr = htonl(fOutputInfo.fDestAddr);
	SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr);

	theErr = QTSS_SetValue(fRelayOutputObject, sOutputDestAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
	Assert(theErr == QTSS_NoErr);

	struct in_addr theLocalAddr;        // output local address
	theLocalAddr.s_addr = htonl(fOutputInfo.fLocalAddr);
	SocketUtils::ConvertAddrToString(theLocalAddr, &theIPAddr);

	theErr = QTSS_SetValue(fRelayOutputObject, sOutputLocalAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len);
	Assert(theErr == QTSS_NoErr);


	for (UInt32 index = 0; index < fNumStreams; index++)    // output udp ports
	{
		UInt16 udpPort = fOutputInfo.fPortArray[index];
		theErr = QTSS_SetValue(fRelayOutputObject, sOutputUDPPorts, index, &udpPort, sizeof(udpPort));
		Assert(theErr == QTSS_NoErr);
	}

	theErr = QTSS_SetValue(fRelayOutputObject, sOutputTTL, 0, &(fOutputInfo.fTimeToLive), sizeof(fOutputInfo.fTimeToLive));
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputCurPacketsPerSec, &fPacketsPerSecond, sizeof(fPacketsPerSecond));
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputCurBitsPerSec, &fBitsPerSecond, sizeof(fBitsPerSecond));
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputTotalPacketsSent, &fTotalPacketsSent, sizeof(fTotalPacketsSent));
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputTotalBytesSent, &fTotalBytesSent, sizeof(fTotalBytesSent));
	Assert(theErr == QTSS_NoErr);

	theErr = QTSS_UnlockObject(fRelaySessionObject);
	Assert(theErr == QTSS_NoErr);

}