Darwin-Streaming-Server/RTSPClientLib/RTSPClient.h
Darren VanBuren 849723c9cf Add even more of the source
This should be about everything needed to build so far?
2017-03-07 17:14:16 -08:00

474 lines
17 KiB
C++

/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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: RTSPClient.h
Works only for QTSS.
Assumes that different streams within a session is distinguished by trackID=
For example, streams within sample.mov would be refered to as sample.mov/trackID=4
Does not work if the URL contains digits!!!
*/
#ifndef __RTSP_CLIENT_H__
#define __RTSP_CLIENT_H__
#include "OSHeaders.h"
#include "StrPtrLen.h"
#include "TCPSocket.h"
#include "ClientSocket.h"
#include "RTPMetaInfoPacket.h"
#include "StringFormatter.h"
#include "SVector.h"
// for authentication
#include "StringParser.h"
class Authenticator
{
public:
enum { kAuthBufferLen = 1024 };
enum
{
kNoType = 0,
kBasicType = 1,
kDigestType = 2 // higher number is stronger type
};
Authenticator();
virtual ~Authenticator() {};
virtual SInt16 GetType() { return 0;};
virtual Bool16 ParseParams(StrPtrLen *authParamsPtr) {return 0;};
virtual void AttachAuthParams(StrPtrLen *theRequestPtr) {};
virtual void ResetAuthParams() {};
StrPtrLen fAuthBuffer;
StrPtrLen fNameSPL;// client
StrPtrLen fPasswordSPL;// client
StrPtrLen fRealmSPL; // server
StrPtrLen fURISPL; // client
StrPtrLen fMethodSPL; // client -- must be all caps
time_t fAuthTime;
//the outHeaderStr argument is not actually implemented
//char *GetRequestHeader( StrPtrLen *inSourceStr, StrPtrLen *searchHeaderStr,StrPtrLen *outHeaderStr = NULL);
char *GetRequestHeader( StrPtrLen *inSourceStr, StrPtrLen *searchHeaderStr);
//Does nothing if the Authorization header is not found
void RemoveAuthLine(StrPtrLen *theRequestPtr);
static Bool16 CopyParam(StrPtrLen *inPtr, StrPtrLen *outPtr);
void SetName(StrPtrLen *inNamePtr);
void SetPassword(StrPtrLen *inPasswordPtr);
void SetMethod(StrPtrLen *inMethodStr);
void SetRealm(StrPtrLen *inRealmPtr);
void SetURI(StrPtrLen *inURIPtr);
void ResetRequestLen(StrPtrLen *theRequestPtr, StrPtrLen *theParamsPtr);
void ParseTag(StringParser *parserPtr,StrPtrLen *outTagPtr);
Bool16 GetParamValue(StringParser *valueSourcePtr, StrPtrLen *outParamValuePtr);
Bool16 GetParamValueAsNewCopy(StringParser *valueSourcePtr, StrPtrLen *outParamValueCopyPtr);
Bool16 GetMatchListParamValueAsNewCopy(StringParser *valueSourcePtr, StrPtrLen *inMatchListParamValuePtr, SInt16 numToMatch, StrPtrLen *outParamValueCopyPtr);
Bool16 ParseRealm(StringParser *realmParserPtr);
static StrPtrLen sAuthorizationStr;
static StrPtrLen sRealmStr;
static StrPtrLen sAuthBasicStr;
static StrPtrLen sAuthDigestStr;
static StrPtrLen sUsernameStr;
static StrPtrLen sWildCardMatch;
static StrPtrLen sTrue;
static StrPtrLen sFalse;
void Clean();
private:
StrPtrLen fCurrentAuthLine;
};
class BasicAuth : public Authenticator
{
public:
BasicAuth() {};
~BasicAuth() {Clean();}
SInt16 GetType() { return kBasicType; };
Bool16 ParseParams(StrPtrLen *authParamsPtr);
void AttachAuthParams(StrPtrLen *theRequestPtr);
UInt32 ParamsLen(StrPtrLen *requestParams);
void ResetAuthParams() {};
protected:
enum { kEncodedBufferLen = 256 };
char fEncodedBuffer[kEncodedBufferLen];
};
class DigestAuth : public Authenticator
{
public:
SInt16 GetType() { return kDigestType; };
Bool16 ParseParams(StrPtrLen *authParamsPtr);
void AttachAuthParams(StrPtrLen *theRequestPtr);
void ResetAuthParams();
StrPtrLen fcnonce;
StrPtrLen fNonceCountStr;
SInt16 fNonceCount;
StrPtrLen fnonce;
StrPtrLen fopaque;
StrPtrLen fqop;
StrPtrLen fAlgorithmStr;
StrPtrLen fStaleStr;
StrPtrLen fURIStr;
StrPtrLen fRequestDigestStr;
SInt16 fAlgorithm;
Bool16 fStale;
void GenerateAuthorizationRequestLine(StrPtrLen *requestPtr);
DigestAuth();
~DigestAuth();
enum {kMaxReqParams = 10};
private:
struct ReqFields
{
StrPtrLen *fReqParamTags[kMaxReqParams];
StrPtrLen *fReqParamValues[kMaxReqParams];
Bool16 fQuoted[kMaxReqParams];
SInt16 fNumFields;
};
ReqFields fReqFields;
void ReqFieldsClean() { memset( (void *) fReqFields.fReqParamTags,0,sizeof(StrPtrLen *) * kMaxReqParams);
memset( (void *) fReqFields.fReqParamValues,0,sizeof(StrPtrLen *) * kMaxReqParams);
memset( (void *) fReqFields.fQuoted,0,sizeof(Bool16) * kMaxReqParams);
fReqFields.fNumFields = 0;
}
void AddAuthParam(StrPtrLen *theTagPtr, StrPtrLen *theValuePtr, Bool16 quoted);
UInt32 ParamsLen(StrPtrLen *requestParams);
void SetNonceCountStr();
void MakeRequestDigest();
void MakeCNonce();
// request tags
static StrPtrLen sCnonceStr;
static StrPtrLen sUriStr;
static StrPtrLen sResponseStr;
static StrPtrLen sNonceCountStr;
// response tags
static StrPtrLen sStaleStr;
// request and response tags
static StrPtrLen sNonceStr;
static StrPtrLen sQopStr;
static StrPtrLen sOpaqueStr;
static StrPtrLen sDomainStr;
static StrPtrLen sAlgorithmStr;
// response values
static StrPtrLen sQopAuthStr;
static StrPtrLen sQopAuthIntStr;
static StrPtrLen sMD5Str;
static StrPtrLen sMD5SessStr;
};
class AuthParser
{
public:
AuthParser() {};
~AuthParser() {}
Authenticator *ParseChallenge(StrPtrLen *challenge);
};
class RTSPClient
{
public:
//
// Before using this class, you must set the User Agent this way.
static void SetUserAgentStr(char* inUserAgent) { sUserAgent = inUserAgent; }
// verbosePrinting = print out all requests and responses
RTSPClient(ClientSocket* inSocket, Bool16 verbosePrinting = false, char* inUserAgent = NULL);
~RTSPClient();
// This must be called before any other function. Sets up very important info; sets the URL
void Set(const StrPtrLen& inURL);
//
// This function allows you to add some special-purpose headers to your
// SETUP request if you want. These are mainly used for the caching proxy protocol,
// though there may be other uses.
//
// inLateTolerance: default = 0 (don't care)
// inMetaInfoFields: default = NULL (don't want RTP-Meta-Info packets
// inSpeed: default = 1 (normal speed)
void SetSetupParams(Float32 inLateTolerance, char* inMetaInfoFields);
// Send specified RTSP request to server, wait for complete response.
// These return EAGAIN if transaction is in progress, OS_NoErr if transaction
// was successful, EINPROGRESS if connection is in progress, or some other
// error if transaction failed entirely.
OS_Error SendDescribe(Bool16 inAppendJunkData = false);
OS_Error SendReliableUDPSetup(UInt32 inTrackID, UInt16 inClientPort);
OS_Error SendUDPSetup(UInt32 inTrackID, UInt16 inClientPort);
OS_Error SendTCPSetup(UInt32 inTrackID, UInt16 inClientRTPid, UInt16 inClientRTCPid);
OS_Error SendPlay(UInt32 inStartPlayTimeInSec, Float32 inSpeed = 1, UInt32 inTrackID = kUInt32_Max); //use a inTrackID of kUInt32_Max to turn off per stream headers
OS_Error SendPacketRangePlay(char* inPacketRangeHeader, Float32 inSpeed = 1);
OS_Error SendReceive(UInt32 inStartPlayTimeInSec);
OS_Error SendAnnounce(char *sdp);
OS_Error SendTeardown();
OS_Error SendInterleavedWrite(UInt8 channel, UInt16 len, char*data,Bool16 *getNext);
OS_Error SendSetParameter();
OS_Error SendOptions();
OS_Error SendOptionsWithRandomDataRequest(SInt32 dataSize);
//
// If you just want to send a generic request, do it this way
OS_Error SendRTSPRequest(iovec* inRequest, UInt32 inNumVecs);
//
// Once you call all of the above functions, assuming they return an error, you
// should call DoTransaction until it returns OS_NoErr, then you can move onto your
// next request
OS_Error DoTransaction();
//
// If any of the tracks are being interleaved, this fetches a media packet from
// the control connection. This function assumes that SendPlay has already completed
// successfully and media packets are being sent.
OS_Error GetMediaPacket( UInt32* outTrackID, Bool16* outIsRTCP,
char** outBuffer, UInt32* outLen);
//
// If any of the tracks are being interleaved, this puts a media packet to the control
// connection. This function assumes that SendPlay has already completed
// successfully and media packets are being sent.
OS_Error PutMediaPacket( UInt32 inTrackID, Bool16 isRTCP, char* inBuffer, UInt16 inLen);
// set name and password for authentication in case we are challenged
void SetName(char *name);
void SetPassword(char *password);
// set control id string default is "trackID"
void SetControlID(char* controlID);
// level 0, 1, 2, or 3
void SetVerboseLevel(UInt32 level) { fVerboseLevel = level; }
//Sets the 3GPP-Link-Char header values; set to all 0 to not send this header
void Set3GPPLinkChars(UInt32 GBW = 0, UInt32 MBW = 0, UInt32 MTD = 0)
{
fGuarenteedBitRate = GBW;
fMaxBitRate = MBW;
fMaxTransferDelay = MTD;
}
//Use 0 for undefined
void SetBandwidth(UInt32 bps = 0) { fBandwidth = bps; }
void Set3GPPRateAdaptation(UInt32 bufferSpace = 0, UInt32 delayTime = 0)
{
fBufferSpace = bufferSpace;
fDelayTime = delayTime;
}
// ACCESSORS
StrPtrLen* GetURL() { return &fURL; }
UInt32 GetStatus() { return fStatus; }
StrPtrLen* GetSessionID() { return &fSessionID; }
UInt16 GetServerPort() { return fServerPort; }
UInt32 GetContentLength() { return fContentLength; }
char* GetContentBody() { return fRecvContentBuffer; }
ClientSocket* GetSocket() { return fSocket; }
UInt32 GetTransportMode() { return fTransportMode; }
void SetTransportMode(UInt32 theMode) { fTransportMode = theMode; };
char* GetResponse() { return fRecvHeaderBuffer; }
UInt32 GetResponseLen() { return fHeaderLen; }
Bool16 IsTransactionInProgress() { return fState != kInitial; }
Bool16 IsVerbose() { return fVerboseLevel >= 1; }
// If available, returns the SSRC associated with the track in the PLAY response.
// Returns 0 if SSRC is not available.
UInt32 GetSSRCByTrack(UInt32 inTrackID);
enum { kPlayMode=0,kPushMode=1,kRecordMode=2};
//
// If available, returns the RTP-Meta-Info field ID array for
// a given track. For more details, see RTPMetaInfoPacket.h
RTPMetaInfoPacket::FieldID* GetFieldIDArrayByTrack(UInt32 inTrackID);
enum
{
kMinNumChannelElements = 5,
kReqBufSize = 4095,
kMethodBuffLen = 24 //buffer for "SETUP" or "PLAY" etc.
};
OSMutex* GetMutex() { return &fMutex; }
private:
static char* sUserAgent;
// Helper methods
void ParseInterleaveSubHeader(StrPtrLen* inSubHeader);
void ParseRTPInfoHeader(StrPtrLen* inHeader);
void ParseRTPMetaInfoHeader(StrPtrLen* inHeader);
//Use a inTrackID of kUInt32_Max to turn the Rate-Adaptation header off
void Attach3GPPHeaders(StringFormatter &fmt, UInt32 inTrackID = kUInt32_Max);
// Call this to receive an RTSP response from the server.
// Returns EAGAIN until a complete response has been received.
OS_Error ReceiveResponse();
OSMutex fMutex;//this data structure is shared!
AuthParser fAuthenticationParser;
Authenticator *fAuthenticator; // only one will be supported
ClientSocket* fSocket;
UInt32 fVerboseLevel;
// Information we need to send the request
StrPtrLen fURL;
UInt32 fCSeq;
// authenticate info
StrPtrLen fName;
StrPtrLen fPassword;
// Response data we get back
UInt32 fStatus;
StrPtrLen fSessionID;
UInt16 fServerPort;
UInt32 fContentLength;
//StrPtrLen fRTPInfoHeader;
// Special purpose SETUP params
char* fSetupHeaders;
// If we are interleaving, this maps channel numbers to track IDs
struct ChannelMapElem
{
UInt32 fTrackID;
Bool16 fIsRTCP;
};
ChannelMapElem* fChannelTrackMap;
UInt8 fNumChannelElements;
//Maps between trackID and SSRC number
struct SSRCMapElem
{
UInt32 fTrackID;
UInt32 fSSRC;
SSRCMapElem(UInt32 trackID = kUInt32_Max, UInt32 inSSRC = 0)
: fTrackID(trackID), fSSRC(inSSRC)
{}
};
SVector<SSRCMapElem> fSSRCMap;
// For storing FieldID arrays
struct FieldIDArrayElem
{
UInt32 fTrackID;
RTPMetaInfoPacket::FieldID fFieldIDs[RTPMetaInfoPacket::kNumFields];
};
FieldIDArrayElem* fFieldIDMap;
UInt32 fNumFieldIDElements;
UInt32 fFieldIDMapSize;
// If we are interleaving, we need this stuff to support the GetMediaPacket function
char* fPacketBuffer;
UInt32 fPacketBufferOffset;
Bool16 fPacketOutstanding;
// Data buffers
char fMethod[kMethodBuffLen]; // holds the current method
char fSendBuffer[kReqBufSize + 1]; // for sending requests
char fRecvHeaderBuffer[kReqBufSize + 1];// for receiving response headers
char* fRecvContentBuffer; // for receiving response body
// Tracking the state of our receives
UInt32 fContentRecvLen;
UInt32 fHeaderRecvLen;
UInt32 fHeaderLen;
UInt32 fSetupTrackID; //is valid during a Setup Transaction
enum { kInitial, kRequestSending, kResponseReceiving, kHeaderReceived };
UInt32 fState;
//UInt32 fEventMask;
Bool16 fAuthAttempted;
UInt32 fTransportMode;
//
// For tracking media data that got read into the header buffer
UInt32 fPacketDataInHeaderBufferLen;
char* fPacketDataInHeaderBuffer;
char* fUserAgent;
static char* sControlID;
char* fControlID;
//These values are for the wireless links only -- not end-to-end
//For the following values; use 0 for undefined.
UInt32 fGuarenteedBitRate; //kbps
UInt32 fMaxBitRate; //kbps
UInt32 fMaxTransferDelay; //milliseconds
UInt32 fBandwidth; //bps
UInt32 fBufferSpace; //bytes
UInt32 fDelayTime; //milliseconds
struct InterleavedParams
{
char *extraBytes;
int extraLen;
UInt8 extraChannel;
int extraByteOffset;
};
static InterleavedParams sInterleavedParams;
};
#endif //__CLIENT_SESSION_H__