Ejemplo n.º 1
0
// This sends the HTTP response to the server that contains the RTSPtext Ref movie
QTSS_Error SendTheResponse(QTSS_RTSPSessionObject theSession, QTSS_StreamRef stream, StrPtrLen& movie)
{
    QTSS_Error err = QTSS_NoErr;
    char theMovieFile[512];
    theMovieFile[sizeof(theMovieFile) -1] = 0;
    
    char tmp[600];	
    tmp[sizeof(tmp) -1] = 0;
    
    char tmp2[80];
    tmp2[sizeof(tmp2) -1] = 0;
    
    UInt8 x1, x2, x3, x4;

    // send the HTTP reply header to the client
    err= QTSS_Write(stream, sResponseHeader, ::strlen(sResponseHeader), NULL, qtssWriteFlagsBufferData);
    if (err != QTSS_NoErr)
        return QTSS_NoErr;
   
    UInt32 ip4address = 0;
    UInt32 len = sizeof(ip4address);
    err = QTSS_GetValue(theSession, qtssRTSPSesLocalAddr, 0, &ip4address, &len);
        
	// Format the server IP address for building the RTSP address in the reply.
    x1 = (UInt8)((ip4address >> 24) & 0xff);
    x2 = (UInt8)((ip4address >> 16) & 0xff);
    x3 = (UInt8)((ip4address >> 8) & 0xff);
    x4 = (UInt8)((ip4address) & 0xff);
    
    if (movie.Len > sizeof(theMovieFile)  -1 )
        movie.Len = sizeof(theMovieFile) -1;
        
    ::memcpy(theMovieFile, movie.Ptr, movie.Len);
	theMovieFile[movie.Len] = '\0';
	
    UInt16 port = sRTSPReplyPort;
    if (0 == port)
    {
        len = sizeof(port);
        err = QTSS_GetValue(theSession, qtssRTSPSesLocalPort, 0, &port, &len);
    }
            
	// construct the RTSP address reply string for the client.
	qtss_snprintf(tmp,sizeof(tmp) -1, "rtsptext\r\nrtsp://%d.%d.%d.%d:%d%s\r\n", x1,x2,x3,x4, port, theMovieFile);
    
    // send the 'Content-Length:' part of the HTTP reply
    qtss_snprintf(tmp2, sizeof(tmp2) -1, "Content-Length: %d\r\n\r\n", (int) ::strlen(tmp));
    err = QTSS_Write(stream, tmp2, ::strlen(tmp2), NULL, qtssWriteFlagsBufferData);
    if (err != QTSS_NoErr)
        return QTSS_NoErr;
        
    // send the formatted RTSP reference part of the reply
    err = QTSS_Write(stream, tmp, ::strlen(tmp), NULL, qtssWriteFlagsBufferData);
    if (err != QTSS_NoErr)
        return QTSS_NoErr;
        
    // flush the pending write to the client.
    err = QTSS_Flush(stream);
    return err;
}
Ejemplo n.º 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;
}
Ejemplo n.º 3
0
void    QTSSModuleUtils::SendDescribeResponse(QTSS_RTSPRequestObject inRequest,
                                                    QTSS_ClientSessionObject inSession,
                                                    iovec* describeData,
                                                    UInt32 inNumVectors,
                                                    UInt32 inTotalLength)
{
    //write content size header
    char buf[32];
    qtss_sprintf(buf, "%"_S32BITARG_"", inTotalLength);
    (void)QTSS_AppendRTSPHeader(inRequest, qtssContentLengthHeader, &buf[0], ::strlen(&buf[0]));

    (void)QTSS_SendStandardRTSPResponse(inRequest, inSession, 0);

        // On solaris, the maximum # of vectors is very low (= 16) so to ensure that we are still able to
        // send the SDP if we have a number greater than the maximum allowed, we coalesce the vectors into
        // a single big buffer
#ifdef __solaris__
    if (inNumVectors > IOV_MAX )
    {
            char* describeDataBuffer = QTSSModuleUtils::CoalesceVectors(describeData, inNumVectors, inTotalLength);
            (void)QTSS_Write(inRequest, (void *)describeDataBuffer, inTotalLength, NULL, qtssWriteFlagsNoFlags);
            // deleting memory allocated by the CoalesceVectors call
            delete [] describeDataBuffer;
    }
    else
        (void)QTSS_WriteV(inRequest, describeData, inNumVectors, inTotalLength, NULL);
#else
    (void)QTSS_WriteV(inRequest, describeData, inNumVectors, inTotalLength, NULL);
#endif

}
Ejemplo n.º 4
0
SInt64 ProxyTask::Run()
{
    const UInt32 kMaxRTCPPacketSize = 2048;
    char thePacketBuffer[kMaxRTCPPacketSize];
    QTSS_PacketStruct thePacketStruct;
    thePacketStruct.packetTransmitTime = QTSS_Milliseconds();
    thePacketStruct.packetData = thePacketBuffer;

    (void)this->GetEvents();    

    OSMutexLocker locker(sSocketPool->GetMutex());
    for (OSQueueIter iter(sSocketPool->GetSocketQueue()); !iter.IsDone(); iter.Next())
    {
        UInt32 theRemoteAddr = 0;
        UInt16 theRemotePort = 0;

        UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject();
        Assert(thePair != NULL);
        
        for (UInt32 x = 0; x < 2; x++)
        {
            QTSS_WriteFlags theFlags = qtssWriteFlagsNoFlags;
            
            UDPSocket* theSocket = NULL;
            if (x == 0)
            {
                theFlags = qtssWriteFlagsIsRTP;
                theSocket = thePair->GetSocketA();
            }
            else
            {
                theFlags = qtssWriteFlagsIsRTCP;
                theSocket = thePair->GetSocketB();
            }
            
            Assert(theSocket->GetDemuxer() != NULL);
            OSMutexLocker locker(theSocket->GetDemuxer()->GetMutex());
            
            //get all the outstanding packets for this socket
            while (true)
            {
                UInt32 thePacketLen = 0;
                theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacketStruct.packetData, 
                                kMaxRTCPPacketSize, &thePacketLen);
                if (thePacketLen == 0)
                    break;//no more packets on this socket!
                    
                ProxyDemuxerTask* theDemuxerTask = (ProxyDemuxerTask*)theSocket->GetDemuxer()->GetTask(theRemoteAddr, 0);
                if (theDemuxerTask != NULL)
                {
                    QTSS_RTPStreamObject theStream = theDemuxerTask->GetStream();
                    (void)QTSS_Write(theStream, &thePacketStruct, thePacketLen, NULL, theFlags);
                }
            }
        }
    }
    return kProxyTaskPollIntervalMsec;
}
Ejemplo n.º 5
0
inline void SendHeader(QTSS_StreamRef inStream)
{
    (void)QTSS_Write(inStream, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);
    (void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);              
    (void)QTSS_Write(inStream, sVersionHeader, ::strlen(sVersionHeader), NULL, 0);      
    (void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);              
    (void)QTSS_Write(inStream, sConnectionHeader, ::strlen(sConnectionHeader), NULL, 0);        
    (void)QTSS_Write(inStream, sEOL, ::strlen(sEOL), NULL, 0);      
    (void)QTSS_Write(inStream, sContentType, ::strlen(sContentType), NULL, 0);      
    (void)QTSS_Write(inStream, sEOM, ::strlen(sEOM), NULL, 0);      
}
Ejemplo n.º 6
0
void QTSSModuleUtils::LogPrefErrorStr( QTSS_ErrorVerbosity inVerbosity, char*  preference, char* inMessage)
{  	
	if (inMessage == NULL || preference == NULL) 
	{  Assert(0);
	   return;  
	}
	char buffer[1024];
	
	qtss_snprintf(buffer,sizeof(buffer), "Server preference %s %s",  preference, inMessage);
   
	(void)QTSS_Write(sErrorLog, buffer, ::strlen(buffer), NULL, inVerbosity);
}
Ejemplo n.º 7
0
void    QTSSModuleUtils::LogError(  QTSS_ErrorVerbosity inVerbosity,
                                    QTSS_AttributeID inTextMessage,
                                    UInt32 /*inErrNumber*/,
                                    char* inArgument,
                                    char* inArg2)
{
    static char* sEmptyArg = "";
    
    if (sMessages == NULL)
        return;
        
    // Retrieve the specified text message from the text messages dictionary.
    
    StrPtrLen theMessage;
    (void)QTSS_GetValuePtr(sMessages, inTextMessage, 0, (void**)(void*)&theMessage.Ptr, &theMessage.Len);
    if ((theMessage.Ptr == NULL) || (theMessage.Len == 0))
        (void)QTSS_GetValuePtr(sMessages, qtssMsgNoMessage, 0, (void**)(void*)&theMessage.Ptr, &theMessage.Len);

    if ((theMessage.Ptr == NULL) || (theMessage.Len == 0))
        return;
    
    // qtss_sprintf and ::strlen will crash if inArgument is NULL
    if (inArgument == NULL)
        inArgument = sEmptyArg;
    if (inArg2 == NULL)
        inArg2 = sEmptyArg;
    
    // Create a new string, and put the argument into the new string.
    
    UInt32 theMessageLen = theMessage.Len + ::strlen(inArgument) + ::strlen(inArg2);

    OSCharArrayDeleter theLogString(NEW char[theMessageLen + 1]);
    qtss_sprintf(theLogString.GetObject(), theMessage.Ptr, inArgument, inArg2);
    Assert(theMessageLen >= ::strlen(theLogString.GetObject()));
    
    (void)QTSS_Write(sErrorLog, theLogString.GetObject(), ::strlen(theLogString.GetObject()),
                        NULL, inVerbosity);
}
Ejemplo n.º 8
0
void ReportErr(QTSS_Filter_Params* inParams, UInt32 err)
{   
    StrPtrLen* urlPtr = sQueryPtr->GetURL();
    StrPtrLen* evalMessagePtr = sQueryPtr->GetEvalMsg();
    char temp[32];
    
    if (urlPtr && evalMessagePtr)   
    {   qtss_sprintf(temp,"(%"_U32BITARG_")",err);
        (void)QTSS_Write(inParams->inRTSPRequest, "error:", strlen("error:"), NULL, 0);
        (void)QTSS_Write(inParams->inRTSPRequest, temp, strlen(temp), NULL, 0);
        if (sQueryPtr->VerboseParam())
        {   (void)QTSS_Write(inParams->inRTSPRequest, ";URL=", strlen(";URL="), NULL, 0);
            if (urlPtr) (void)QTSS_Write(inParams->inRTSPRequest, urlPtr->Ptr, urlPtr->Len, NULL, 0);
        }
        if (sQueryPtr->DebugParam())
        {
            (void)QTSS_Write(inParams->inRTSPRequest, ";", strlen(";"), NULL, 0);
            (void)QTSS_Write(inParams->inRTSPRequest, evalMessagePtr->Ptr, evalMessagePtr->Len, NULL, 0);               
        }
        (void)QTSS_Write(inParams->inRTSPRequest, "\r\n\r\n", 4, NULL, 0);
    }
}
Ejemplo n.º 9
0
QTSS_Error SendPackets(QTSS_RTPSendPackets_Params* inParams)
{
    FileSession** theFile = NULL;
    UInt32 theLen = 0;
    QTSS_Error theErr = QTSS_GetValuePtr(inParams->inClientSession, sFileSessionAttr, 0, (void**)&theFile, &theLen);
    if ((theErr != QTSS_NoErr) || (theLen != sizeof(FileSession*)))
    {
        Assert( 0 );
        return QTSS_RequestFailed;
    }
    
    while (true)
    {   
        if ((*theFile)->fPacketStruct.packetData == NULL)
        {
            void* theCookie = NULL;
            Float64 theTransmitTime = (*theFile)->fFile.GetNextPacket((UInt8**)&(*theFile)->fPacketStruct.packetData, &(*theFile)->fNextPacketLen, &theCookie);
            
            //
            // Check to see if we should stop playing based on a client specified stop time
            if (((*theFile)->fStopTime != -1) && (theTransmitTime > (*theFile)->fStopTime))
            {
                // We should indeed stop playing
                (void)QTSS_Pause(inParams->inClientSession);
                inParams->outNextPacketTime = qtssDontCallSendPacketsAgain;
                return QTSS_NoErr;
            }

            //
            // Adjust transmit time based on speed
            Float64 theOffsetFromStartTime = theTransmitTime - (*theFile)->fStartTime;
            theTransmitTime = (*theFile)->fStartTime + (theOffsetFromStartTime / (*theFile)->fSpeed);
            
            (*theFile)->fStream = (QTSS_RTPStreamObject)theCookie;
            (*theFile)->fPacketStruct.packetTransmitTime = (*theFile)->fAdjustedPlayTime + ((SInt64)(theTransmitTime * 1000));
#if RTP_FILE_MODULE_DEBUGGING >= 8
            UInt16* theSeqNumPtr = (UInt16*)(*theFile)->fNextPacket;
            UInt32* theTimestampP = (UInt32*)(*theFile)->fNextPacket;
            UInt32* theTrackID = NULL;
            (void)QTSS_GetValuePtr((*theFile)->fStream, qtssRTPStrTrackID, 0, (void**)&theTrackID, &theLen);
            qtss_printf("Got packet. Seq num: %d. Timestamp: %d. TrackID: %d. Transmittime: %f\n",theSeqNumPtr[1], theTimestampP[1], *theTrackID, theTransmitTime);
#endif
        }
        
        //We are done playing all streams!
        if ((*theFile)->fPacketStruct.packetData == NULL)
        {
#if RTP_FILE_MODULE_DEBUGGING >= 8
            qtss_printf("done w all packets\n");
#endif
            inParams->outNextPacketTime = qtssDontCallSendPacketsAgain;
            return QTSS_NoErr;
        }
        //we have a packet that needs to be sent now
        Assert((*theFile)->fStream != NULL);

        // Send the packet!
        theErr =  QTSS_Write((*theFile)->fStream, &(*theFile)->fPacketStruct, (*theFile)->fNextPacketLen, NULL, qtssWriteFlagsIsRTP);

        if ( theErr == QTSS_WouldBlock )
        {   
            if ((*theFile)->fPacketStruct.packetTransmitTime == -1)
                inParams->outNextPacketTime = sFlowControlProbeInterval;    // for buffering, try me again in # MSec
            else
            {
                Assert((*theFile)->fPacketStruct.packetTransmitTime > inParams->inCurrentTime);
                inParams->outNextPacketTime = (*theFile)->fPacketStruct.packetTransmitTime - inParams->inCurrentTime;
            }
                
            return QTSS_NoErr;
        }

        (*theFile)->fPacketStruct.packetData = NULL;
    }
    Assert(0);
    return QTSS_NoErr;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
{
    if (NULL == inParams || NULL == inParams->inRTSPSession || NULL == inParams->inRTSPRequest)
    {   Assert(0);
        return QTSS_NoErr;
    }

    OSMutexLocker locker(sAdminMutex);
    //check to see if we should handle this request. Invokation is triggered
    //by a "GET /" request
    
    QTSS_Error err = QTSS_NoErr;
    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;

    UInt32 paramLen = sizeof(sSessID);
    err = QTSS_GetValue(inParams->inRTSPSession, qtssRTSPSesID, 0, (void*)&sSessID, &paramLen);     
    if (err != QTSS_NoErr) 
        return QTSS_NoErr;

    StrPtrLen theFullRequest;
    err = QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
    if (err != QTSS_NoErr) 
        return QTSS_NoErr;
        
    
    StringParser fullRequest(&theFullRequest);
        
    if ( !IsAdminRequest(&fullRequest) ) 
        return QTSS_NoErr;
        
    if ( !AcceptSession(inParams->inRTSPSession) )
    {   (void)QTSS_Write(inParams->inRTSPRequest, sPermissionDeniedHeader, ::strlen(sPermissionDeniedHeader), NULL, 0);     
        (void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
        KeepSession(theRequest,false);
        return QTSS_NoErr;
    }
    
    if(!GetRequestAuthenticatedState(inParams)) // must authenticate before handling
    {
        if(QTSS_IsGlobalLocked()) // must NOT be global locked
            return QTSS_RequestFailed;
            
        if (!IsAuthentic(inParams,&fullRequest)) 
        {  
            (void)QTSS_Write(inParams->inRTSPRequest, sUnauthorizedResponseHeader, ::strlen(sUnauthorizedResponseHeader), NULL, 0);     
            (void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
            KeepSession(theRequest,false);
            return QTSS_NoErr;
        }
        
    }
    
    if (GetRequestFlushState(inParams)) 
    {   StillFlushing(inParams,true);
        return QTSS_NoErr;
    }
        
    if (!QTSS_IsGlobalLocked())
    {       
        if (InWaitInterval(inParams)) 
            return QTSS_NoErr; 

        //qtss_printf("New Request Wait for GlobalLock session=%"_U32BITARG_"\n",sSessID);
        (void)QTSS_RequestGlobalLock();
        KeepSession(theRequest,true);
        return QTSS_NoErr; 
    }
    
    //qtss_printf("Handle request session=%"_U32BITARG_"\n",sSessID);
    APITests_DEBUG();
    
    if (sQueryPtr != NULL) 
    {   delete sQueryPtr;
        sQueryPtr = NULL;   
    }
    sQueryPtr = NEW QueryURI(&theFullRequest);
    if (sQueryPtr == NULL) return QTSS_NoErr;
    
    ShowQuery_DEBUG();
    
    if (sAdminPtr != NULL) 
    {   delete sAdminPtr;
        sAdminPtr = NULL;
    }
    UInt32 result = sQueryPtr->EvalQuery(NULL, NULL);
    if (result == 0) do
    {
        if( ElementNode_CountPtrs() > 0)
        {   ElementNode_ShowPtrs();
            Assert(0);
        }
            
        GetQueryData(theRequest);
        
        SendResult(theRequest); 
        delete sAdminPtr;
        sAdminPtr = NULL;
        
        if (sQueryPtr && !sQueryPtr->QueryHasReponse())
        {   UInt32 err = 404;
            (void) sQueryPtr->EvalQuery(&err,NULL);
            ReportErr(inParams, err);
            break;
        }

        if (sQueryPtr && sQueryPtr->QueryHasReponse())
        {   ReportErr(inParams, sQueryPtr->GetEvaluResult());
        }
        
        if (sQueryPtr->fIsPref && sQueryPtr->GetEvaluResult() == 0)
        {   QTSS_ServiceID id;
            (void) QTSS_IDForService(QTSS_REREAD_PREFS_SERVICE, &id);           
            (void) QTSS_DoService(id, NULL);
        }
    } while(false);
    else
    {
        SendHeader(theRequest);         
        ReportErr(inParams, sQueryPtr->GetEvaluResult());
    }
    
    if (sQueryPtr != NULL) 
    {   delete sQueryPtr;
        sQueryPtr = NULL;
    }
    
    (void) StillFlushing(inParams,true);
    return QTSS_NoErr;

}
Ejemplo n.º 12
0
QTSS_Error	QTSSModuleUtils::SendHTTPErrorResponse( QTSS_RTSPRequestObject inRequest,
													QTSS_SessionStatusCode inStatusCode,
                                                    Bool16 inKillSession,
                                                    char *errorMessage)
{
    static Bool16 sFalse = false;
    
    //set status code for access log
    (void)QTSS_SetValue(inRequest, qtssRTSPReqStatusCode, 0, &inStatusCode, sizeof(inStatusCode));

    if (inKillSession) // tell the server to end the session
        (void)QTSS_SetValue(inRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
    
    ResizeableStringFormatter theErrorMessage(NULL, 0); //allocates and deletes memory
    ResizeableStringFormatter bodyMessage(NULL,0); //allocates and deletes memory

    char messageLineBuffer[64]; // used for each line
    static const int maxMessageBufferChars = sizeof(messageLineBuffer) -1;
    messageLineBuffer[maxMessageBufferChars] = 0; // guarantee termination

    // ToDo: put in a more meaningful http error message for each error. Not required by spec.
    // ToDo: maybe use the HTTP protcol class static error strings.
    char* errorMsg = "error"; 

    DateBuffer theDate;
    DateTranslator::UpdateDateBuffer(&theDate, 0); // get the current GMT date and time

    UInt32 realCode = 0;
    UInt32 len = sizeof(realCode);
    (void) QTSS_GetValue(inRequest, qtssRTSPReqRealStatusCode, 0,  (void*)&realCode,&len);

    char serverHeaderBuffer[64]; // the qtss Server: header field
    len = sizeof(serverHeaderBuffer) -1; // leave room for terminator
    (void) QTSS_GetValue(sServer, qtssSvrRTSPServerHeader, 0,  (void*)serverHeaderBuffer,&len);
    serverHeaderBuffer[len] = 0; // terminate.
 
    qtss_snprintf(messageLineBuffer,maxMessageBufferChars, "HTTP/1.1 %"_U32BITARG_" %s",realCode, errorMsg);
    theErrorMessage.Put(messageLineBuffer,::strlen(messageLineBuffer));
    theErrorMessage.PutEOL();

    theErrorMessage.Put(serverHeaderBuffer,::strlen(serverHeaderBuffer));
    theErrorMessage.PutEOL();
 
    qtss_snprintf(messageLineBuffer,maxMessageBufferChars, "Date: %s",theDate.GetDateBuffer());
    theErrorMessage.Put(messageLineBuffer,::strlen(messageLineBuffer));
    theErrorMessage.PutEOL();
 
    Bool16 addBody =  (errorMessage != NULL && ::strlen(errorMessage) != 0); // body error message so add body headers
    if (addBody) // body error message so add body headers
    {
        // first create the html body
        static const StrPtrLen htmlBodyStart("<html><body>\n");
        bodyMessage.Put(htmlBodyStart.Ptr,htmlBodyStart.Len);
 
        //<h1>errorMessage</h1>\n
        static const StrPtrLen hStart("<h1>");
        bodyMessage.Put(hStart.Ptr,hStart.Len);

        bodyMessage.Put(errorMessage,::strlen(errorMessage));

        static const StrPtrLen hTerm("</h1>\n");
        bodyMessage.Put(hTerm.Ptr,hTerm.Len);
 
        static const StrPtrLen htmlBodyTerm("</body></html>\n");
        bodyMessage.Put(htmlBodyTerm.Ptr,htmlBodyTerm.Len);

        // write body headers
        static const StrPtrLen bodyHeaderType("Content-Type: text/html");
        theErrorMessage.Put(bodyHeaderType.Ptr,bodyHeaderType.Len);
        theErrorMessage.PutEOL();

        qtss_snprintf(messageLineBuffer,maxMessageBufferChars, "Content-Length: %"_U32BITARG_"", bodyMessage.GetBytesWritten());
        theErrorMessage.Put(messageLineBuffer,::strlen(messageLineBuffer));        
        theErrorMessage.PutEOL();
    }

    static const StrPtrLen headerClose("Connection: close");
    theErrorMessage.Put(headerClose.Ptr,headerClose.Len);
    theErrorMessage.PutEOL();

    theErrorMessage.PutEOL();  // terminate headers with empty line

    if (addBody) // add html body
    {
        theErrorMessage.Put(bodyMessage.GetBufPtr(),bodyMessage.GetBytesWritten());
    }

    //
    // 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.GetBufPtr(), theErrorMessage.GetBytesWritten(), NULL, 0);
    (void)QTSS_SetValue(inRequest, qtssRTSPReqRespMsg, 0, theErrorMessage.GetBufPtr(), theErrorMessage.GetBytesWritten());
    
    return QTSS_RequestFailed;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
QTSS_Error  QTSSModuleUtils::SendErrorResponse( QTSS_RTSPRequestObject inRequest,
                                                        QTSS_RTSPStatusCode inStatusCode,
                                                        QTSS_AttributeID inTextMessage,
                                                        StrPtrLen* inStringArg)
{
    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));
    StringFormatter theErrorMsgFormatter(NULL, 0);
    char *messageBuffPtr = NULL;
    
    if (sEnableRTSPErrorMsg)
    {
        // Retrieve the specified message out of the text messages dictionary.
        StrPtrLen theMessage;
        (void)QTSS_GetValuePtr(sMessages, inTextMessage, 0, (void**)(void*)&theMessage.Ptr, &theMessage.Len);

        if ((theMessage.Ptr == NULL) || (theMessage.Len == 0))
        {
            // If we couldn't find the specified message, get the default
            // "No Message" message, and return that to the client instead.
            
            (void)QTSS_GetValuePtr(sMessages, qtssMsgNoMessage, 0, (void**)(void*)&theMessage.Ptr, &theMessage.Len);
        }
        Assert(theMessage.Ptr != NULL);
        Assert(theMessage.Len > 0);
        
        // Allocate a temporary buffer for the error message, and format the error message
        // into that buffer
        UInt32 theMsgLen = 256;
        if (inStringArg != NULL)
            theMsgLen += inStringArg->Len;
        
        messageBuffPtr = NEW char[theMsgLen];
        messageBuffPtr[0] = 0;
        theErrorMsgFormatter.Set(messageBuffPtr, theMsgLen);
        //
        // Look for a %s in the string, and if one exists, replace it with the
        // argument passed into this function.
        
        //we can safely assume that message is in fact NULL terminated
        char* stringLocation = ::strstr(theMessage.Ptr, "%s");
        if (stringLocation != NULL)
        {
            //write first chunk
            theErrorMsgFormatter.Put(theMessage.Ptr, stringLocation - theMessage.Ptr);
            
            if (inStringArg != NULL && inStringArg->Len > 0)
            {
                //write string arg if it exists
                theErrorMsgFormatter.Put(inStringArg->Ptr, inStringArg->Len);
                stringLocation += 2;
            }
            //write last chunk
            theErrorMsgFormatter.Put(stringLocation, (theMessage.Ptr + theMessage.Len) - stringLocation);
        }
        else
            theErrorMsgFormatter.Put(theMessage);
        
        
        char buff[32];
        qtss_sprintf(buff,"%"_U32BITARG_"",theErrorMsgFormatter.GetBytesWritten());
        (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, theErrorMsgFormatter.GetBufPtr(), theErrorMsgFormatter.GetBytesWritten(), NULL, 0);
    (void)QTSS_SetValue(inRequest, qtssRTSPReqRespMsg, 0, theErrorMsgFormatter.GetBufPtr(), theErrorMsgFormatter.GetBytesWritten());
    
    delete [] messageBuffPtr;
    return QTSS_RequestFailed;
}
Ejemplo n.º 15
0
void QTSSModuleUtils::LogErrorStr( QTSS_ErrorVerbosity inVerbosity, char* inMessage) 
{  	
	if (inMessage == NULL) return;  
	(void)QTSS_Write(sErrorLog, inMessage, ::strlen(inMessage), NULL, inVerbosity);
}
Ejemplo n.º 16
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);        
}
Ejemplo n.º 17
0
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
{
#if HTTP_FILE_DEBUGGING
    qtss_printf("FilterRequest\n");
#endif

    static Bool16 sFalse = false;

    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
    
    // Initial state.   
    StrPtrLen theFullRequest;
    StrPtrLen reqMethod;
    StrPtrLen reqStr;
    StrPtrLen httpVersion;
    
    (void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
    StringParser fullRequest(&theFullRequest);

    // Parsing the HTTP request
    fullRequest.ConsumeWord(&reqMethod);
    if ( !(reqMethod.Equal(StrPtrLen("GET")) || reqMethod.Equal(StrPtrLen("HEAD"))) )
        // It's not a "Get" or a "Head" request 
        return QTSS_NoErr;
     
    fullRequest.ConsumeWhitespace();
    if ( !fullRequest.Expect('/') )
        // Improperly formed request
        return QTSS_NoErr;
            
    fullRequest.ConsumeUntil(&reqStr, StringParser::sEOLWhitespaceMask);
    if( reqStr.Len == 0 )
        //if a file or directory name is not given, return
        return QTSS_NoErr;
        
    if ( !reqStr.Equal(StrPtrLen("Popular.smil")) )
        return QTSS_NoErr;
    
    // If it's a "Head" request send the Head response header back and just return
    if ( reqMethod.Equal(StrPtrLen("HEAD")) )
    {
        QTSS_Write(theRequest, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);    
        return QTSS_NoErr;
    }

    // Create a buffer to store data.
    char theFileBuffer[8192];
    char contentLength[256];
        
    // 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
    (void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
    
#if HTTP_FILE_DEBUGGING
    qtss_printf("Creating a smil file\n");   
#endif
    // Create a ref movie buffer for the single file. It is of the form:
    //  rtsptext\r
    //  rtsp://servername/filepath
    char smilFileBuf[8192] = {0};

    GenerateHotHitSMIL(smilFileBuf);
                
    qtss_sprintf(contentLength, "%lu", strlen(smilFileBuf));
    // Allocate memory for theFileBuffer
    // Write the HTTP header prefix into the buffer
    ::strcpy(theFileBuffer, sRespHeaderPrefix.Ptr);
    ::strcat(theFileBuffer, sContentLengthHeaderTag.Ptr);
    // Write the remaining part of the HTTP header into the file buffer
    ::strcat(theFileBuffer, contentLength);
    ::strcat(theFileBuffer, sContentTypeHeaderTag.Ptr);
    ::strcat(theFileBuffer, sSmilMimeType.Ptr);
    ::strcat(theFileBuffer, "\r\n\r\n");
    
    // Write the smil file created above to the file buffer
    ::strcat(theFileBuffer, smilFileBuf);
    
    // Write the contents of the file buffer to the request stream and return
    QTSS_Write(theRequest, theFileBuffer, strlen(theFileBuffer), NULL, 0);
    
#if HTTP_FILE_DEBUGGING
    qtss_printf("Wrote the smil file to the request stream. Successful!\n"); 
#endif

    return QTSS_NoErr;
}