/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2001 Apple Computer, Inc. All Rights Reserved. The * contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please * obtain a copy of the License at http://www.apple.com/publicsource and * read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please * see the License for the specific language governing rights and * limitations under the License. * * * @APPLE_LICENSE_HEADER_END@ * */ /* Contains: API interface for objects to use to get access to attributes, data items, whatever, specific to RTP sessions (see RTPSession.h for more details on what that object is). This object implements the RTP Session Dictionary. */ #ifndef _RTPSESSIONINTERFACE_H_ #define _RTPSESSIONINTERFACE_H_ #include "QTSSDictionary.h" #include "RTCPSRPacket.h" #include "RTSPSessionInterface.h" #include "TimeoutTask.h" #include "Task.h" #include "RTPBandwidthTracker.h" #include "RTPOverbufferWindow.h" #include "OSMutex.h" #include "atomic.h" class RTPSessionInterface : public QTSSDictionary, public Task { public: // Initializes dictionary resources static void Initialize(); // // CONSTRUCTOR / DESTRUCTOR RTPSessionInterface(); virtual ~RTPSessionInterface() { if (fRTSPSession != NULL) fRTSPSession->DecrementObjectHolderCount(); delete [] fSRBuffer.Ptr; delete [] fAuthNonce.Ptr; delete [] fAuthOpaque.Ptr; } virtual void SetValueComplete( UInt32 inAttrIndex, QTSSDictionaryMap* inMap, UInt32 inValueIndex, const void* inNewValue, UInt32 inNewValueLen); //Timeouts. This allows clients to refresh the timeout on this session void RefreshTimeout() { fTimeoutTask.RefreshTimeout(); } void RefreshRTSPTimeout() { if (fRTSPSession != NULL) fRTSPSession->RefreshTimeout(); } void RefreshTimeouts() { RefreshTimeout(); RefreshRTSPTimeout();} // // ACCESSORS Bool16 IsFirstPlay() { return fIsFirstPlay; } SInt64 GetFirstPlayTime() { return fFirstPlayTime; } //Time (msec) most recent play was issued SInt64 GetPlayTime() { return fPlayTime; } SInt64 GetNTPPlayTime() { return fNTPPlayTime; } SInt64 GetSessionCreateTime() { return fSessionCreateTime; } //Time (msec) most recent play, adjusted for start time of the movie //ex: PlayTime() == 20,000. Client said start 10 sec into the movie, //so AdjustedPlayTime() == 10,000 QTSS_PlayFlags GetPlayFlags() { return fPlayFlags; } OSMutex* GetSessionMutex() { return &fSessionMutex; } UInt32 GetPacketsSent() { return fPacketsSent; } UInt32 GetBytesSent() { return fBytesSent; } OSRef* GetRef() { return &fRTPMapElem; } RTSPSessionInterface* GetRTSPSession() { return fRTSPSession; } UInt32 GetMovieAvgBitrate(){ return fMovieAverageBitRate; } QTSS_CliSesTeardownReason GetTeardownReason() { return fTeardownReason; } QTSS_RTPSessionState GetSessionState() { return fState; } void SetUniqueID(UInt32 theID) {fUniqueID = theID;} UInt32 GetUniqueID() { return fUniqueID; } RTPBandwidthTracker* GetBandwidthTracker() { return &fTracker; } RTPOverbufferWindow* GetOverbufferWindow() { return &fOverbufferWindow; } UInt32 GetFramesSkipped() { return fFramesSkipped; } // // MEMORY FOR RTCP PACKETS // // Class for easily building a standard RTCP SR RTCPSRPacket* GetSRPacket() { return &fRTCPSRPacket; } // // Memory if you want to build your own char* GetSRBuffer(UInt32 inSRLen); // // STATISTICS UPDATING //The session tracks the total number of bytes sent during the session. //Streams can update that value by calling this function void UpdateBytesSent(UInt32 bytesSent) { fBytesSent += bytesSent; } //The session tracks the total number of packets sent during the session. //Streams can update that value by calling this function void UpdatePacketsSent(UInt32 packetsSent) { fPacketsSent += packetsSent; } void UpdateCurrentBitRate(const SInt64& curTime) { if (curTime > (fLastBitRateUpdateTime + 10000)) this->UpdateBitRateInternal(curTime); } void SetAllTracksInterleaved(Bool16 newValue) { fAllTracksInterleaved = newValue; } // // RTSP RESPONSES // This function appends a session header to the SETUP response, and // checks to see if it is a 304 Not Modified. If it is, it sends the entire // response and returns an error QTSS_Error DoSessionSetupResponse(RTSPRequestInterface* inRequest); // // RTSP SESSION // This object has a current RTSP session. This may change over the // life of the RTSPSession, so update it. It keeps an RTSP session in // case interleaved data or commands need to be sent back to the client. void UpdateRTSPSession(RTSPSessionInterface* inNewRTSPSession); // let's RTSP Session pass along it's query string void SetQueryString( StrPtrLen* queryString ); // SETTERS and ACCESSORS for auth information // Authentication information that needs to be kept around // for the duration of the session QTSS_AuthScheme GetAuthScheme() { return fAuthScheme; } StrPtrLen* GetAuthNonce() { return &fAuthNonce; } UInt32 GetAuthQop() { return fAuthQop; } UInt32 GetAuthNonceCount() { return fAuthNonceCount; } StrPtrLen* GetAuthOpaque() { return &fAuthOpaque; } void SetAuthScheme(QTSS_AuthScheme scheme) { fAuthScheme = scheme; } // Use this if the auth scheme or the qop has to be changed from the defaults // of scheme = Digest, and qop = auth void SetChallengeParams(QTSS_AuthScheme scheme, UInt32 qop, Bool16 newNonce, Bool16 createOpaque); // Use this otherwise...if newNonce == true, it will create a new nonce // and reset nonce count. If newNonce == false but nonce was never created earlier // a nonce will be created. If newNonce == false, and there is an existing nonce, // the nounce count will be incremented. void UpdateDigestAuthChallengeParams(Bool16 newNonce, Bool16 createOpaque, UInt32 qop); Float32* GetPacketLossPercent() { UInt32 outLen;return (Float32*) this->PacketLossPercent(this, &outLen);} SInt32 GetQualityLevel() { return fSessionQualityLevel; } SInt32* GetQualityLevelPtr() { return &fSessionQualityLevel; } void SetQualityLevel(SInt32 level) { fSessionQualityLevel = level; } SInt64 fLastQualityCheckTime; SInt64 fLastQualityCheckMediaTime; Bool16 fStartedThinning; #if RTP_STREAM_THINNING_TIMING_LOG SInt64 fFirstPacketSendTime; SInt64 fFirstPacketTransmitTime; UInt32 fNumPrints; static FILE* sStatsLog; static OSMutex* sStatsLogMutex; #endif protected: // These variables are setup by the derived RTPSession object when // Play and Pause get called //Some stream related information that is shared amongst all streams Bool16 fIsFirstPlay; Bool16 fAllTracksInterleaved; SInt64 fFirstPlayTime;//in milliseconds SInt64 fPlayTime; SInt64 fAdjustedPlayTime; SInt64 fNTPPlayTime; SInt64 fNextSendPacketsTime; SInt32 fSessionQualityLevel; //keeps track of whether we are playing or not QTSS_RTPSessionState fState; // If we are playing, this are the play flags that were set on play QTSS_PlayFlags fPlayFlags; //Session mutex. This mutex should be grabbed before invoking the module //responsible for managing this session. This allows the module to be //non-preemptive-safe with respect to a session OSMutex fSessionMutex; //Stores the session ID OSRef fRTPMapElem; char fRTSPSessionIDBuf[QTSS_MAX_SESSION_ID_LENGTH + 4]; UInt32 fLastBitRateBytes; SInt64 fLastBitRateUpdateTime; // In order to facilitate sending data over the RTSP channel from // an RTP session, we store a pointer to the RTSP session used in // the last RTSP request. RTSPSessionInterface* fRTSPSession; #if RTP_OVER_BUFFER_WINDOW_LOGGING static FILE* sOverbufferTimesLog; static OSMutex* sOverbufferTimesLogMutex; #endif private: // // Utility function for calculating current bit rate void UpdateBitRateInternal(const SInt64& curTime); static void* PacketLossPercent(QTSSDictionary* inSession, UInt32* outLen); static void* TimeConnected(QTSSDictionary* inSession, UInt32* outLen); // Create nonce void CreateDigestAuthenticationNonce(); // One of the RTP session attributes is an iterated list of all streams. // As an optimization, we preallocate a "large" buffer of stream pointers, // even though we don't know how many streams we need at first. enum { kStreamBufSize = 4, kUserAgentBufSize = 256, kPresentationURLSize = 256, kFullRequestURLBufferSize = 256, kRequestHostNameBufferSize = 80, kIPAddrStrBufSize = 20, kLocalDNSBufSize = 80, kAuthNonceBufSize = 32, kAuthOpaqueBufSize = 32, }; void* fStreamBuffer[kStreamBufSize]; // theses are dictionary items picked up by the RTSPSession // but we need to store copies of them for logging purposes. char fUserAgentBuffer[kUserAgentBufSize]; char fPresentationURL[kPresentationURLSize]; // eg /foo/bar.mov char fFullRequestURL[kFullRequestURLBufferSize]; // eg rtsp://yourdomain.com/foo/bar.mov char fRequestHostName[kRequestHostNameBufferSize]; // eg yourdomain.com char fRTSPSessRemoteAddrStr[kIPAddrStrBufSize]; char fRTSPSessLocalDNS[kLocalDNSBufSize]; char fRTSPSessLocalAddrStr[kIPAddrStrBufSize]; char fUserNameBuf[RTSPSessionInterface::kMaxUserNameLen]; char fUserPasswordBuf[RTSPSessionInterface::kMaxUserPasswordLen]; char fUserRealmBuf[RTSPSessionInterface::kMaxUserRealmLen]; UInt32 fLastRTSPReqRealStatusCode; //for timing out this session TimeoutTask fTimeoutTask; UInt32 fTimeout; // Time when this session got created SInt64 fSessionCreateTime; //Packet priority levels. Each stream has a current level, and //the module that owns this session sets what the number of levels is. UInt32 fNumQualityLevels; //Statistics UInt32 fBytesSent; UInt32 fPacketsSent; Float32 fPacketLossPercent; SInt64 fTimeConnected; // Movie size & movie duration. It may not be so good to associate these // statistics with the movie, for a session MAY have multiple movies... // however, the 1 movie assumption is in too many subsystems at this point Float64 fMovieDuration; UInt64 fMovieSizeInBytes; UInt32 fMovieAverageBitRate; UInt32 fMovieCurrentBitRate; QTSS_CliSesTeardownReason fTeardownReason; // So the streams can send sender reports UInt32 fUniqueID; RTCPSRPacket fRTCPSRPacket; StrPtrLen fSRBuffer; RTPBandwidthTracker fTracker; RTPOverbufferWindow fOverbufferWindow; // Built in dictionary attributes static QTSSAttrInfoDict::AttrInfo sAttributes[]; static unsigned int sRTPSessionIDCounter; // Authentication information that needs to be kept around // for the duration of the session QTSS_AuthScheme fAuthScheme; StrPtrLen fAuthNonce; UInt32 fAuthQop; UInt32 fAuthNonceCount; StrPtrLen fAuthOpaque; UInt32 fQualityUpdate; UInt32 fFramesSkipped; #if RTP_OVER_BUFFER_WINDOW_LOGGING static char* sOverbufferTimesLogFilename; #endif #if RTP_STREAM_THINNING_TIMING_LOG static char* sStatsLogFilename; #endif Bool16 fOverBufferEnabled; }; #endif //_RTPSESSIONINTERFACE_H_