/* * * @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@ * */ /* File: ClientSession.h */ #ifndef __CLIENT_SESSION__ #define __CLIENT_SESSION__ #include "Task.h" #include "TimeoutTask.h" #include "RTSPClient.h" #include "ClientSocket.h" #include "SDPSourceInfo.h" #include "UDPSocket.h" class ClientSession : public Task { public: enum { kRTSPUDPClientType = 0, kRTSPTCPClientType = 1, kRTSPHTTPClientType = 2, kRTSPHTTPDropPostClientType = 3, kRTSPReliableUDPClientType = 4 }; typedef UInt32 ClientType; ClientSession( UInt32 inAddr, UInt16 inPort, char* inURL, ClientType inClientType, UInt32 inDurationInSec, UInt32 inStartPlayTimeInSec, UInt32 inRTCPIntervalInSec, UInt32 inOptionsIntervalInSec, UInt32 inHTTPCookie, Bool16 inAppendJunkData, UInt32 inReadInterval, UInt32 inSockRcvBufSize, Float32 inLateTolerance, char* inMetaInfoFields, Float32 inSpeed, Bool16 inVerbosePrinting, char* inPacketRangePlayHeader, UInt32 inOverbufferWindowSizeInK ); virtual ~ClientSession(); // // Signals. // // Send a kKillEvent to delete this object. // Send a kTeardownEvent to tell the object to send a TEARDOWN and abort enum { kTeardownEvent = 0x00000100 }; virtual SInt64 Run(); // // States. Find out what the object is currently doing enum { kSendingDescribe = 0, kSendingSetup = 1, kSendingPlay = 2, kPlaying = 3, kSendingTeardown = 4, kDone = 5 }; // // Why did this session die? enum { kDiedNormally = 0, // Session went fine kTeardownFailed = 1, // Teardown failed, but session stats are all valid kRequestFailed = 2, // Session couldn't be setup because the server returned an error kBadSDP = 3, // Server sent back some bad SDP kSessionTimedout = 4, // Server not responding kConnectionFailed = 5, // Couldn't connect at all. kDiedWhilePlaying = 6 // Connection was forceably closed while playing the movie }; // // Once this client session is completely done with the TEARDOWN and ready to be // destructed, this will return true. Until it returns true, this object should not // be deleted. When it does return true, this object should be deleted. Bool16 IsDone() { return fState == kDone; } // // ACCESSORS RTSPClient* GetClient() { return fClient; } ClientSocket* GetSocket() { return fSocket; } SDPSourceInfo* GetSDPInfo() { return &fSDPParser; } UInt32 GetState() { return fState; } // When this object is in the kDone state, this will tell you why the session died. UInt32 GetReasonForDying() { return fDeathReason; } UInt32 GetRequestStatus() { return fClient->GetStatus(); } // Tells you the total time we were receiving packets. You can use this // for computing bit rate SInt64 GetTotalPlayTimeInMsec() { return fTotalPlayTime; } QTSS_RTPPayloadType GetTrackType(UInt32 inTrackIndex) { return fSDPParser.GetStreamInfo(inTrackIndex)->fPayloadType; } UInt32 GetNumPacketsReceived(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumPacketsReceived; } UInt32 GetNumBytesReceived(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumBytesReceived; } UInt32 GetNumPacketsLost(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumLostPackets; } UInt32 GetNumPacketsOutOfOrder(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumOutOfOrderPackets; } UInt32 GetNumDuplicates(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumDuplicates; } UInt32 GetNumAcks(UInt32 inTrackIndex) { return fStats[inTrackIndex].fNumAcks; } // // Global stats static UInt32 GetActiveConnections() { return sActiveConnections; } static UInt32 GetPlayingConnections() { return sPlayingConnections; } static UInt32 GetConnectionAttempts() { return sTotalConnectionAttempts; } private: enum { kRawRTSPControlType = 0, kRTSPHTTPControlType = 1, kRTSPHTTPDropPostControlType= 2 }; typedef UInt32 ControlType; enum { kUDPTransportType = 0, kReliableUDPTransportType = 1, kTCPTransportType = 2 }; typedef UInt32 TransportType; ClientSocket* fSocket; // Connection object RTSPClient* fClient; // Manages the client connection SDPSourceInfo fSDPParser; // Parses the SDP in the DESCRIBE response TimeoutTask fTimeoutTask; // Kills this connection in the event the server isn't responding ControlType fControlType; TransportType fTransportType; UInt32 fDurationInSec; UInt32 fStartPlayTimeInSec; UInt32 fRTCPIntervalInSec; UInt32 fOptionsIntervalInSec; UInt32 fState; // For managing the state machine UInt32 fDeathReason; UInt32 fNumSetups; UDPSocket** fUDPSocketArray; SInt64 fPlayTime; SInt64 fTotalPlayTime; SInt64 fLastRTCPTime; Bool16 fTeardownImmediately; Bool16 fAppendJunk; UInt32 fReadInterval; UInt32 fSockRcvBufSize; Float32 fSpeed; char* fPacketRangePlayHeader; // // Client stats struct TrackStats { enum { kSeqNumMapSize = 100, kHalfSeqNumMap = 50 }; UInt16 fDestRTCPPort; UInt32 fNumPacketsReceived; UInt32 fNumBytesReceived; UInt32 fNumLostPackets; UInt32 fNumOutOfOrderPackets; UInt32 fNumThrownAwayPackets; UInt8 fSequenceNumberMap[kSeqNumMapSize]; UInt16 fWrapSeqNum; UInt16 fLastSeqNum; UInt32 fSSRC; Bool16 fIsSSRCValid; UInt16 fHighestSeqNum; UInt16 fLastAckedSeqNum; Bool16 fHighestSeqNumValid; UInt32 fNumAcks; UInt32 fNumDuplicates; }; TrackStats* fStats; UInt32 fOverbufferWindowSizeInK; UInt32 fCurRTCPTrack; // // Global stats static UInt32 sActiveConnections; static UInt32 sPlayingConnections; static UInt32 sTotalConnectionAttempts; // // Helper functions for Run() void SetupUDPSockets(); void ProcessMediaPacket(char* inPacket, UInt32 inLength, UInt32 inTrackID, Bool16 isRTCP); OS_Error ReadMediaData(); OS_Error SendReceiverReport(UInt32 inTrackID); void AckPackets(UInt32 inTrackIndex, UInt16 inCurSeqNum, Bool16 inCurSeqNumValid); }; #endif //__CLIENT_SESSION__