/* * * @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: QTSServerInterface.h Contains: This object defines an interface for getting and setting server-wide attributes, and storing global server resources. There can be only one of these objects per process, so there is a static accessor. */ #ifndef __QTSSERVERINTERFACE_H__ #define __QTSSERVERINTERFACE_H__ #include "QTSS.h" #include "QTSSDictionary.h" #include "QTSServerPrefs.h" #include "QTSSMessages.h" #include "QTSSModule.h" #include "atomic.h" #include "OSMutex.h" #include "Task.h" #include "TCPListenerSocket.h" #include "ResizeableStringFormatter.h" // OSRefTable; class UDPSocketPool; class QTSServerPrefs; class QTSSMessages; //class RTPStatsUpdaterTask; class RTPSessionInterface; // This object also functions as our assert logger class QTSSErrorLogStream : public QTSSStream, public AssertLogger { public: // This QTSSStream is used by modules to write to the error log QTSSErrorLogStream() {} virtual ~QTSSErrorLogStream() {} virtual QTSS_Error Write(void* inBuffer, UInt32 inLen, UInt32* outLenWritten, UInt32 inFlags); virtual void LogAssert(char* inMessage); }; class QTSServerInterface : public QTSSDictionary { public: //Initialize must be called right off the bat to initialize dictionary resources static void Initialize(); // // CONSTRUCTOR / DESTRUCTOR QTSServerInterface(); virtual ~QTSServerInterface() {} // // // STATISTICS MANIPULATION // These functions are how the server keeps its statistics current void AlterCurrentRTSPSessionCount(SInt32 inDifference) { OSMutexLocker locker(&fMutex); fNumRTSPSessions += inDifference; } void AlterCurrentRTSPHTTPSessionCount(SInt32 inDifference) { OSMutexLocker locker(&fMutex); fNumRTSPHTTPSessions += inDifference; } void SwapFromRTSPToHTTP() { OSMutexLocker locker(&fMutex); fNumRTSPSessions--; fNumRTSPHTTPSessions++; } //total rtp bytes sent by the server void IncrementTotalRTPBytes(UInt32 bytes) { (void)atomic_add(&fPeriodicRTPBytes, bytes); } //total rtp packets sent by the server void IncrementTotalPackets() { (void)atomic_add(&fPeriodicRTPPackets, 1); } //total rtp bytes reported as lost by the clients void IncrementTotalRTPPacketsLost(UInt32 packets) { (void)atomic_add(&fPeriodicRTPPacketsLost, packets); } // Also increments current RTP session count void IncrementTotalRTPSessions() { OSMutexLocker locker(&fMutex); fNumRTPSessions++; fTotalRTPSessions++; } void AlterCurrentRTPSessionCount(SInt32 inDifference) { OSMutexLocker locker(&fMutex); fNumRTPSessions += inDifference; } // // ACCESSORS QTSS_ServerState GetServerState() { return fServerState; } UInt32 GetNumRTPSessions() { return fNumRTPSessions; } UInt32 GetTotalRTPSessions() { return fTotalRTPSessions; } UInt32 GetCurBandwidthInBits() { return fCurrentRTPBandwidthInBits; } UInt32 GetAvgBandwidthInBits() { return fAvgRTPBandwidthInBits; } UInt32 GetRTPPacketsPerSec() { return fRTPPacketsPerSecond; } UInt64 GetTotalRTPBytes() { return fTotalRTPBytes; } UInt64 GetTotalRTPPacketsLost(){ return fTotalRTPPacketsLost; } Float32 GetCPUPercent() { return fCPUPercent; } Bool16 SigIntSet() { return fSigInt; } UInt32 GetNumMP3Sessions() { return fNumMP3Sessions; } UInt32 GetTotalMP3Sessions() { return fTotalMP3Sessions; } UInt64 GetTotalMP3Bytes() { return fTotalMP3Bytes; } // // // GLOBAL OBJECTS REPOSITORY // This object is in fact global, so there is an accessor for it as well. static QTSServerInterface* GetServer() { return sServer; } //Allows you to map RTP session IDs (strings) to actual RTP session objects OSRefTable* GetRTPSessionMap() { return fRTPMap; } //Server provides a statically created & bound UDPSocket / Demuxer pair //for each IP address setup to serve RTP. You access those pairs through //this function. This returns a pair pre-bound to the IPAddr specified. UDPSocketPool* GetSocketPool() { return fSocketPool; } QTSServerPrefs* GetPrefs() { return fSrvrPrefs; } QTSSMessages* GetMessages() { return fSrvrMessages; } // // // SERVER NAME & VERSION static StrPtrLen& GetServerName() { return sServerNameStr; } static StrPtrLen& GetServerVersion() { return sServerVersionStr; } static StrPtrLen& GetServerPlatform() { return sServerPlatformStr; } static StrPtrLen& GetServerBuildDate() { return sServerBuildDateStr; } static StrPtrLen& GetServerHeader() { return sServerHeaderPtr; } // // PUBLIC HEADER static StrPtrLen* GetPublicHeader() { return &sPublicHeaderStr; } // // KILL ALL void KillAllRTPSessions(); // // SIGINT - to interrupt the server, set this flag and the server will shut down void SetSigInt() { fSigInt = true; } // // MODULE STORAGE // All module objects are stored here, and are accessable through // these routines. // Returns the number of modules that act in a given role static UInt32 GetNumModulesInRole(QTSSModule::RoleIndex inRole) { Assert(inRole < QTSSModule::kNumRoles); return sNumModulesInRole[inRole]; } // Allows the caller to iterate over all modules that act in a given role static QTSSModule* GetModule(QTSSModule::RoleIndex inRole, UInt32 inIndex) { Assert(inRole < QTSSModule::kNumRoles); Assert(inIndex < sNumModulesInRole[inRole]); return sModuleArray[inRole][inIndex]; } // // We need to override this. This is how we implement the QTSS_StateChange_Role virtual void SetValueComplete(UInt32 inAttrIndex, QTSSDictionaryMap* inMap, UInt32 inValueIndex, const void* inNewValue, UInt32 inNewValueLen); // // ERROR LOGGING // Invokes the error logging modules with some data static void LogError(QTSS_ErrorVerbosity inVerbosity, char* inBuffer); // Returns the error log stream static QTSSErrorLogStream* GetErrorLogStream() { return &sErrorLogStream; } // // LOCKING DOWN THE SERVER OBJECT OSMutex* GetServerObjectMutex() { return &fMutex; } protected: // Setup by the derived RTSPServer object //Sockets are allocated global to the server, and arbitrated through this pool here. //RTCP data is processed completely within the following task. UDPSocketPool* fSocketPool; // All RTP sessions are put into this map OSRefTable* fRTPMap; QTSServerPrefs* fSrvrPrefs; QTSSMessages* fSrvrMessages; QTSServerPrefs* fStubSrvrPrefs; QTSSMessages* fStubSrvrMessages; QTSS_ServerState fServerState; UInt32 fDefaultIPAddr; // Array of pointers to TCPListenerSockets. TCPListenerSocket** fListeners; UInt32 fNumListeners; // Number of elements in the array // startup time SInt64 fStartupTime_UnixMilli; SInt32 fGMTOffset; static ResizeableStringFormatter sPublicHeaderFormatter; static StrPtrLen sPublicHeaderStr; // // MODULE DATA static QTSSModule** sModuleArray[QTSSModule::kNumRoles]; static UInt32 sNumModulesInRole[QTSSModule::kNumRoles]; static OSQueue sModuleQueue; static QTSSErrorLogStream sErrorLogStream; private: enum { kMaxServerHeaderLen = 100 }; static void* TimeConnected(QTSSDictionary* inConnection, UInt32* outLen); static UInt32 sServerAPIVersion; static StrPtrLen sServerNameStr; static StrPtrLen sServerVersionStr; static StrPtrLen sServerPlatformStr; static StrPtrLen sServerBuildDateStr; static char sServerHeader[kMaxServerHeaderLen]; static StrPtrLen sServerHeaderPtr; OSMutex fMutex; UInt32 fNumRTSPSessions; UInt32 fNumRTSPHTTPSessions; UInt32 fNumRTPSessions; //stores the total number of connections since startup. UInt32 fTotalRTPSessions; //stores the total number of bytes served since startup UInt64 fTotalRTPBytes; //total number of rtp packets sent since startup UInt64 fTotalRTPPackets; //stores the total number of bytes lost (as reported by clients) since startup UInt64 fTotalRTPPacketsLost; //because there is no 64 bit atomic add (for obvious reasons), we efficiently //implement total byte counting by atomic adding to this variable, then every //once in awhile updating the sTotalBytes. unsigned int fPeriodicRTPBytes; unsigned int fPeriodicRTPPacketsLost; unsigned int fPeriodicRTPPackets; //stores the current served bandwidth in BITS per second UInt32 fCurrentRTPBandwidthInBits; UInt32 fAvgRTPBandwidthInBits; UInt32 fRTPPacketsPerSecond; Float32 fCPUPercent; Float32 fCPUTimeUsedInSec; // stores # of UDP sockets in the server currently (gets updated lazily via. // param retrieval function) UInt32 fTotalUDPSockets; // are we out of descriptors? Bool16 fIsOutOfDescriptors; // Storage for current time attribute SInt64 fCurrentTime_UnixMilli; // Stats for UDP retransmits UInt32 fUDPWastageInBytes; UInt32 fNumUDPBuffers; // MP3 Client Session params UInt32 fNumMP3Sessions; UInt32 fTotalMP3Sessions; UInt32 fCurrentMP3BandwidthInBits; UInt64 fTotalMP3Bytes; UInt32 fAvgMP3BandwidthInBits; Bool16 fSigInt; // Param retrieval functions static void* CurrentUnixTimeMilli(QTSSDictionary* inServer, UInt32* outLen); static void* GetTotalUDPSockets(QTSSDictionary* inServer, UInt32* outLen); static void* IsOutOfDescriptors(QTSSDictionary* inServer, UInt32* outLen); static void* GetNumUDPBuffers(QTSSDictionary* inServer, UInt32* outLen); static void* GetNumWastedBytes(QTSSDictionary* inServer, UInt32* outLen); static QTSServerInterface* sServer; static QTSSAttrInfoDict::AttrInfo sAttributes[]; static QTSSAttrInfoDict::AttrInfo sConnectedUserAttributes[]; friend class RTPStatsUpdaterTask; friend class SessionTimeoutTask; }; class RTPStatsUpdaterTask : public Task { public: // This class runs periodically to compute current totals & averages RTPStatsUpdaterTask(); virtual ~RTPStatsUpdaterTask() {} private: virtual SInt64 Run(); RTPSessionInterface* GetNewestSession(OSRefTable* inRTPSessionMap); Float32 GetCPUTimeInSeconds(); SInt64 fLastBandwidthTime; SInt64 fLastBandwidthAvg; SInt64 fLastBytesSent; SInt64 fLastTotalMP3Bytes; }; #endif // __QTSSERVERINTERFACE_H__