1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**********/
// "liveMedia"
// Copyright (c) 1996-2005 Live Networks, Inc. All rights reserved.
// A generic RTSP client
// C++ header
#ifndef _RTSP_CLIENT_HH
#define _RTSP_CLIENT_HH
#ifndef _MEDIA_SESSION_HH
#include "MediaSession.hh"
#endif
#ifndef _NET_ADDRESS_HH
#include "NetAddress.hh"
#endif
#ifndef _DIGEST_AUTHENTICATION_HH
#include "DigestAuthentication.hh"
#endif
class RTSPClient: public Medium {
public:
static RTSPClient* createNew(UsageEnvironment& env,
int verbosityLevel = 0,
char const* applicationName = NULL,
portNumBits tunnelOverHTTPPortNum = 0);
// If "tunnelOverHTTPPortNum" is non-zero, we tunnel RTSP (and RTP)
// over a HTTP connection with the given port number, using the technique
// described in Apple's document <http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html>
int socketNum() const { return fInputSocketNum; }
static Boolean lookupByName(UsageEnvironment& env,
char const* sourceName,
RTSPClient*& resultClient);
char* describeURL(char const* url, Authenticator* authenticator = NULL,
Boolean allowKasennaProtocol = False);
// Issues a RTSP "DESCRIBE" command
// Returns the SDP description of a session, or NULL if none
// (This is dynamically allocated, and must later be freed
// by the caller - using "delete[]")
char* describeWithPassword(char const* url,
char const* username, char const* password);
// Uses "describeURL()" to do a "DESCRIBE" - first
// without using "password", then (if we get an Unauthorized
// response) with an authentication response computed from "password"
Boolean announceSDPDescription(char const* url,
char const* sdpDescription,
Authenticator* authenticator = NULL);
// Issues a RTSP "ANNOUNCE" command
// Returns True iff this command succeeds
Boolean announceWithPassword(char const* url, char const* sdpDescription,
char const* username, char const* password);
// Uses "announceSDPDescription()" to do an "ANNOUNCE" - first
// without using "password", then (if we get an Unauthorized
// response) with an authentication response computed from "password"
char* sendOptionsCmd(char const* url,
char* username = NULL, char* password = NULL,
Authenticator* authenticator = NULL);
// Issues a RTSP "OPTIONS" command
// Returns a string containing the list of options, or NULL
Boolean setupMediaSubsession(MediaSubsession& subsession,
Boolean streamOutgoing = False,
Boolean streamUsingTCP = False,
Boolean forceMulticastOnUnspecified = False);
// Issues a RTSP "SETUP" command on "subsession".
// Returns True iff this command succeeds
// If "forceMulticastOnUnspecified" is True (and "streamUsingTCP" is False),
// then the client will request a multicast stream if the media address
// in the original SDP response was unspecified (i.e., 0.0.0.0).
// Note, however, that not all servers will support this.
Boolean playMediaSession(MediaSession& session,
float start = 0.0f, float end = -1.0f,
float scale = 1.0f);
// Issues an aggregate RTSP "PLAY" command on "session".
// Returns True iff this command succeeds
// (Note: start=-1 means 'resume'; end=-1 means 'play to end')
Boolean playMediaSubsession(MediaSubsession& subsession,
float start = 0.0f, float end = -1.0f,
float scale = 1.0f,
Boolean hackForDSS = False);
// Issues a RTSP "PLAY" command on "subsession".
// Returns True iff this command succeeds
// (Note: start=-1 means 'resume'; end=-1 means 'play to end')
Boolean pauseMediaSession(MediaSession& session);
// Issues an aggregate RTSP "PAUSE" command on "session".
// Returns True iff this command succeeds
Boolean pauseMediaSubsession(MediaSubsession& subsession);
// Issues a RTSP "PAUSE" command on "subsession".
// Returns True iff this command succeeds
Boolean recordMediaSubsession(MediaSubsession& subsession);
// Issues a RTSP "RECORD" command on "subsession".
// Returns True iff this command succeeds
Boolean setMediaSessionParameter(MediaSession& session,
char const* parameterName,
char const* parameterValue);
// Issues a RTSP "SET_PARAMETER" command on "subsession".
// Returns True iff this command succeeds
Boolean getMediaSessionParameter(MediaSession& session,
char const* parameterName,
char*& parameterValue);
// Issues a RTSP "GET_PARAMETER" command on "subsession".
// Returns True iff this command succeeds
Boolean teardownMediaSession(MediaSession& session);
// Issues an aggregate RTSP "TEARDOWN" command on "session".
// Returns True iff this command succeeds
Boolean teardownMediaSubsession(MediaSubsession& subsession);
// Issues a RTSP "TEARDOWN" command on "subsession".
// Returns True iff this command succeeds
static Boolean parseRTSPURL(UsageEnvironment& env, char const* url,
NetAddress& address, portNumBits& portNum,
char const** urlSuffix = NULL);
// (ignores any "<username>[:<password>]@" in "url")
static Boolean parseRTSPURLUsernamePassword(char const* url,
char*& username,
char*& password);
unsigned describeStatus() const { return fDescribeStatusCode; }
void setUserAgentString(char const* userAgentStr);
// sets an alternative string to be used in RTSP "User-Agent:" headers
unsigned sessionTimeoutParameter() const { return fSessionTimeoutParameter; }
#ifdef SUPPORT_REAL_RTSP
Boolean usingRealNetworksChallengeResponse() const { return fRealChallengeStr != NULL; }
#endif
protected:
virtual ~RTSPClient();
private: // redefined virtual functions
virtual Boolean isRTSPClient() const;
private:
RTSPClient(UsageEnvironment& env, int verbosityLevel,
char const* applicationName, portNumBits tunnelOverHTTPPortNum);
// called only by createNew();
void reset();
void resetTCPSockets();
Boolean openConnectionFromURL(char const* url, Authenticator* authenticator);
char* createAuthenticatorString(Authenticator const* authenticator,
char const* cmd, char const* url);
static void checkForAuthenticationFailure(unsigned responseCode,
char*& nextLineStart,
Authenticator* authenticator);
Boolean sendRequest(char const* requestString, char const* tag,
Boolean base64EncodeIfOverHTTP = True);
Boolean getResponse(char const* tag,
unsigned& bytesRead, unsigned& responseCode,
char*& firstLine, char*& nextLineStart,
Boolean checkFor200Response = True);
unsigned getResponse1(char*& responseBuffer, unsigned responseBufferSize);
Boolean parseResponseCode(char const* line, unsigned& responseCode);
Boolean parseTransportResponse(char const* line,
char*& serverAddressStr,
portNumBits& serverPortNum,
unsigned char& rtpChannelId,
unsigned char& rtcpChannelId);
Boolean parseRTPInfoHeader(char const* line, unsigned& trackId,
u_int16_t& seqNum, u_int32_t& timestamp);
Boolean parseScaleHeader(char const* line, float& scale);
Boolean parseGetParameterHeader(char const* line,
const char* param,
char*& value);
void constructSubsessionURL(MediaSubsession const& subsession,
char const*& prefix,
char const*& separator,
char const*& suffix);
Boolean setupHTTPTunneling(char const* urlSuffix, Authenticator* authenticator);
// Support for handling requests sent back by a server:
static void incomingRequestHandler(void*, int /*mask*/);
void incomingRequestHandler1();
void handleCmd_notSupported(char const* cseq);
private:
int fVerbosityLevel;
portNumBits fTunnelOverHTTPPortNum;
char* fUserAgentHeaderStr;
unsigned fUserAgentHeaderStrSize;
int fInputSocketNum, fOutputSocketNum;
unsigned fServerAddress;
static unsigned fCSeq; // sequence number, used in consecutive requests
// Note: it's static, to ensure that it differs if more than one
// connection is made to the same server, using the same URL.
// Some servers (e.g., DSS) may have problems with this otherwise.
char* fBaseURL;
Authenticator fCurrentAuthenticator;
unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
char* fLastSessionId;
unsigned fSessionTimeoutParameter; // optionally set in response "Session:" headers
#ifdef SUPPORT_REAL_RTSP
char* fRealChallengeStr;
char* fRealETagStr;
#endif
unsigned fDescribeStatusCode;
// 0: OK; 1: connection failed; 2: stream unavailable
char* fResponseBuffer;
unsigned fResponseBufferSize;
// The following fields are used to implement the non-standard Kasenna protocol:
Boolean fServerIsKasenna;
char* fKasennaContentType;
// The following is used to deal with Microsoft servers' non-standard use of RTSP:
Boolean fServerIsMicrosoft;
};
#endif
|