mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #133, rtsp extract tcp/udp listener.
This commit is contained in:
parent
4807f7850d
commit
40fbfd8560
17 changed files with 876 additions and 300 deletions
|
@ -231,9 +231,9 @@ int SrsRtspSdp::parse(string token)
|
|||
audio_sample_rate = audio_codec.substr(pos + 1);
|
||||
audio_codec = audio_codec.substr(0, pos);
|
||||
}
|
||||
if ((pos = audio_codec.find("/")) != string::npos) {
|
||||
audio_channel = audio_codec.substr(pos + 1);
|
||||
audio_codec = audio_codec.substr(0, pos);
|
||||
if ((pos = audio_sample_rate.find("/")) != string::npos) {
|
||||
audio_channel = audio_sample_rate.substr(pos + 1);
|
||||
audio_sample_rate = audio_sample_rate.substr(0, pos);
|
||||
}
|
||||
}
|
||||
} else if (desc_key == "fmtp") {
|
||||
|
@ -283,19 +283,20 @@ int SrsRtspSdp::parse(string token)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsRtspSdp::parse_fmtp_attribute(string& attr)
|
||||
int SrsRtspSdp::parse_fmtp_attribute(string attr)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
while (!attr.empty()) {
|
||||
std::string item = attr;
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
item = attr.substr(0, pos);
|
||||
attr = attr.substr(pos + 1);
|
||||
item = token.substr(0, pos);
|
||||
token = token.substr(pos + 1);
|
||||
} else {
|
||||
attr = "";
|
||||
token = "";
|
||||
}
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
|
@ -337,19 +338,20 @@ int SrsRtspSdp::parse_fmtp_attribute(string& attr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsRtspSdp::parse_control_attribute(string& attr)
|
||||
int SrsRtspSdp::parse_control_attribute(string attr)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
while (!attr.empty()) {
|
||||
std::string item = attr;
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
item = attr.substr(0, pos);
|
||||
attr = attr.substr(pos + 1);
|
||||
item = token.substr(0, pos);
|
||||
token = token.substr(pos + 1);
|
||||
} else {
|
||||
attr = "";
|
||||
token = "";
|
||||
}
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
|
@ -392,16 +394,81 @@ string SrsRtspSdp::base64_decode(string value)
|
|||
return plaintext;
|
||||
}
|
||||
|
||||
SrsRtspTransport::SrsRtspTransport()
|
||||
{
|
||||
client_port_min = 0;
|
||||
client_port_max = 0;
|
||||
}
|
||||
|
||||
SrsRtspTransport::~SrsRtspTransport()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsRtspTransport::parse(string attr)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
item = token.substr(0, pos);
|
||||
token = token.substr(pos + 1);
|
||||
} else {
|
||||
token = "";
|
||||
}
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
if ((pos = item.find("=")) != string::npos) {
|
||||
item_key = item.substr(0, pos);
|
||||
item_value = item.substr(pos + 1);
|
||||
}
|
||||
|
||||
if (transport.empty()) {
|
||||
transport = item_key;
|
||||
if ((pos = transport.find("/")) != string::npos) {
|
||||
profile = transport.substr(pos + 1);
|
||||
transport = transport.substr(0, pos);
|
||||
}
|
||||
if ((pos = profile.find("/")) != string::npos) {
|
||||
lower_transport = profile.substr(pos + 1);
|
||||
profile = profile.substr(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (item_key == "unicast" || item_key == "multicast") {
|
||||
cast_type = item_key;
|
||||
} else if (item_key == "mode") {
|
||||
mode = item_value;
|
||||
} else if (item_key == "client_port") {
|
||||
std::string sport = item_value;
|
||||
std::string eport = item_value;
|
||||
if ((pos = eport.find("-")) != string::npos) {
|
||||
sport = eport.substr(0, pos);
|
||||
eport = eport.substr(pos + 1);
|
||||
}
|
||||
client_port_min = ::atoi(sport.c_str());
|
||||
client_port_max = ::atoi(eport.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsRtspRequest::SrsRtspRequest()
|
||||
{
|
||||
seq = 0;
|
||||
content_length = 0;
|
||||
sdp = NULL;
|
||||
transport = NULL;
|
||||
}
|
||||
|
||||
SrsRtspRequest::~SrsRtspRequest()
|
||||
{
|
||||
srs_freep(sdp);
|
||||
srs_freep(transport);
|
||||
}
|
||||
|
||||
bool SrsRtspRequest::is_options()
|
||||
|
@ -414,6 +481,11 @@ bool SrsRtspRequest::is_announce()
|
|||
return method == __SRS_METHOD_ANNOUNCE;
|
||||
}
|
||||
|
||||
bool SrsRtspRequest::is_setup()
|
||||
{
|
||||
return method == __SRS_METHOD_SETUP;
|
||||
}
|
||||
|
||||
SrsRtspResponse::SrsRtspResponse(int cseq)
|
||||
{
|
||||
seq = cseq;
|
||||
|
@ -424,8 +496,10 @@ SrsRtspResponse::~SrsRtspResponse()
|
|||
{
|
||||
}
|
||||
|
||||
stringstream& SrsRtspResponse::encode(stringstream& ss)
|
||||
int SrsRtspResponse::encode(stringstream& ss)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// status line
|
||||
ss << __SRS_VERSION << __SRS_RTSP_SP
|
||||
<< status << __SRS_RTSP_SP
|
||||
|
@ -439,7 +513,20 @@ stringstream& SrsRtspResponse::encode(stringstream& ss)
|
|||
<< "Pragma: no-cache" << __SRS_RTSP_CRLF
|
||||
<< "Server: " << RTMP_SIG_SRS_SERVER << __SRS_RTSP_CRLF;
|
||||
|
||||
return ss;
|
||||
if ((ret = encode_header(ss)) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: encode header failed. ret=%d", ret);
|
||||
return ret;
|
||||
};
|
||||
|
||||
// header EOF.
|
||||
ss << __SRS_RTSP_CRLF;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRtspResponse::encode_header(std::stringstream& ss)
|
||||
{
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq)
|
||||
|
@ -453,10 +540,8 @@ SrsRtspOptionsResponse::~SrsRtspOptionsResponse()
|
|||
{
|
||||
}
|
||||
|
||||
stringstream& SrsRtspOptionsResponse::encode(stringstream& ss)
|
||||
int SrsRtspOptionsResponse::encode_header(stringstream& ss)
|
||||
{
|
||||
SrsRtspResponse::encode(ss);
|
||||
|
||||
SrsRtspMethod __methods[] = {
|
||||
SrsRtspMethodDescribe,
|
||||
SrsRtspMethodAnnounce,
|
||||
|
@ -489,10 +574,27 @@ stringstream& SrsRtspOptionsResponse::encode(stringstream& ss)
|
|||
}
|
||||
ss << __SRS_RTSP_CRLF;
|
||||
|
||||
// eof header.
|
||||
ss << __SRS_RTSP_CRLF;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return ss;
|
||||
SrsRtspSetupResponse::SrsRtspSetupResponse(int seq) : SrsRtspResponse(seq)
|
||||
{
|
||||
local_port_min = 0;
|
||||
local_port_max = 0;
|
||||
}
|
||||
|
||||
SrsRtspSetupResponse::~SrsRtspSetupResponse()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsRtspSetupResponse::encode_header(stringstream& ss)
|
||||
{
|
||||
ss << __SRS_TOKEN_SESSION << ":" << __SRS_RTSP_SP << session << __SRS_RTSP_CRLF;
|
||||
ss << __SRS_TOKEN_TRANSPORT << ":" << __SRS_RTSP_SP
|
||||
<< "RTP/AVP;unicast;client_port=" << client_port_min << "-" << client_port_max << ";"
|
||||
<< "server_port=" << local_port_min << "-" << local_port_max
|
||||
<< __SRS_RTSP_CRLF;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s)
|
||||
|
@ -613,6 +715,21 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
return ret;
|
||||
}
|
||||
req->content_length = ::atol(cl.c_str());
|
||||
} else if (token == __SRS_TOKEN_TRANSPORT) {
|
||||
std::string transport;
|
||||
if ((ret = recv_token_eof(transport)) != ERROR_SUCCESS) {
|
||||
if (!srs_is_client_gracefully_close(ret)) {
|
||||
srs_error("rtsp: parse %s failed. ret=%d", __SRS_TOKEN_TRANSPORT, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (!req->transport) {
|
||||
req->transport = new SrsRtspTransport();
|
||||
}
|
||||
if ((ret = req->transport->parse(transport)) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: parse transport failed, transport=%s. ret=%d", transport.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
// unknown header name, parse util EOF.
|
||||
SrsRtspTokenState state = SrsRtspTokenStateNormal;
|
||||
|
|
|
@ -60,6 +60,8 @@ class ISrsProtocolReaderWriter;
|
|||
#define __SRS_TOKEN_PUBLIC "Public"
|
||||
#define __SRS_TOKEN_CONTENT_TYPE "Content-Type"
|
||||
#define __SRS_TOKEN_CONTENT_LENGTH "Content-Length"
|
||||
#define __SRS_TOKEN_TRANSPORT "Transport"
|
||||
#define __SRS_TOKEN_SESSION "Session"
|
||||
|
||||
// RTSP methods
|
||||
#define __SRS_METHOD_OPTIONS "OPTIONS"
|
||||
|
@ -97,6 +99,53 @@ enum SrsRtspSdpState
|
|||
SrsRtspSdpStateVideo,
|
||||
};
|
||||
|
||||
/**
|
||||
* 10 Method Definitions
|
||||
* The method token indicates the method to be performed on the resource
|
||||
* identified by the Request-URI. The method is case-sensitive. New
|
||||
* methods may be defined in the future. Method names may not start with
|
||||
* a $ character (decimal 24) and must be a token. Methods are
|
||||
* summarized in Table 2.
|
||||
* Notes on Table 2: PAUSE is recommended, but not required in that a
|
||||
* fully functional server can be built that does not support this
|
||||
* method, for example, for live feeds. If a server does not support a
|
||||
* particular method, it MUST return "501 Not Implemented" and a client
|
||||
* SHOULD not try this method again for this server.
|
||||
*/
|
||||
enum SrsRtspMethod
|
||||
{
|
||||
SrsRtspMethodDescribe = 0x0001,
|
||||
SrsRtspMethodAnnounce = 0x0002,
|
||||
SrsRtspMethodGetParameter = 0x0004,
|
||||
SrsRtspMethodOptions = 0x0008,
|
||||
SrsRtspMethodPause = 0x0010,
|
||||
SrsRtspMethodPlay = 0x0020,
|
||||
SrsRtspMethodRecord = 0x0040,
|
||||
SrsRtspMethodRedirect = 0x0080,
|
||||
SrsRtspMethodSetup = 0x0100,
|
||||
SrsRtspMethodSetParameter = 0x0200,
|
||||
SrsRtspMethodTeardown = 0x0400,
|
||||
};
|
||||
|
||||
/**
|
||||
* the state of rtsp token.
|
||||
*/
|
||||
enum SrsRtspTokenState
|
||||
{
|
||||
/**
|
||||
* parse token failed, default state.
|
||||
*/
|
||||
SrsRtspTokenStateError = 100,
|
||||
/**
|
||||
* when SP follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateNormal = 101,
|
||||
/**
|
||||
* when CRLF follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateEOF = 102,
|
||||
};
|
||||
|
||||
/**
|
||||
* the sdp in announce.
|
||||
* Appendix C: Use of SDP for RTSP Session Descriptions
|
||||
|
@ -179,17 +228,64 @@ private:
|
|||
/**
|
||||
* generally, the fmtp is the sequence header for video or audio.
|
||||
*/
|
||||
virtual int parse_fmtp_attribute(std::string& attr);
|
||||
virtual int parse_fmtp_attribute(std::string attr);
|
||||
/**
|
||||
* generally, the control is the stream info for video or audio.
|
||||
*/
|
||||
virtual int parse_control_attribute(std::string& attr);
|
||||
virtual int parse_control_attribute(std::string attr);
|
||||
/**
|
||||
* decode the string by base64.
|
||||
*/
|
||||
virtual std::string base64_decode(std::string value);
|
||||
};
|
||||
|
||||
/**
|
||||
* the rtsp transport.
|
||||
* 12.39 Transport
|
||||
* This request header indicates which transport protocol is to be used
|
||||
* and configures its parameters such as destination address,
|
||||
* compression, multicast time-to-live and destination port for a single
|
||||
* stream. It sets those values not already determined by a presentation
|
||||
* description.
|
||||
*/
|
||||
class SrsRtspTransport
|
||||
{
|
||||
public:
|
||||
// The syntax for the transport specifier is
|
||||
// transport/profile/lower-transport
|
||||
std::string transport;
|
||||
std::string profile;
|
||||
std::string lower_transport;
|
||||
// unicast | multicast
|
||||
// mutually exclusive indication of whether unicast or multicast
|
||||
// delivery will be attempted. Default value is multicast.
|
||||
// Clients that are capable of handling both unicast and
|
||||
// multicast transmission MUST indicate such capability by
|
||||
// including two full transport-specs with separate parameters
|
||||
// for each.
|
||||
std::string cast_type;
|
||||
// The mode parameter indicates the methods to be supported for
|
||||
// this session. Valid values are PLAY and RECORD. If not
|
||||
// provided, the default is PLAY.
|
||||
std::string mode;
|
||||
// This parameter provides the unicast RTP/RTCP port pair on
|
||||
// which the client has chosen to receive media data and control
|
||||
// information. It is specified as a range, e.g.,
|
||||
// client_port=3456-3457.
|
||||
// where client will use port in:
|
||||
// [client_port_min, client_port_max)
|
||||
int client_port_min;
|
||||
int client_port_max;
|
||||
public:
|
||||
SrsRtspTransport();
|
||||
virtual ~SrsRtspTransport();
|
||||
public:
|
||||
/**
|
||||
* parse a line of token for transport.
|
||||
*/
|
||||
virtual int parse(std::string attr);
|
||||
};
|
||||
|
||||
/**
|
||||
* the rtsp request message.
|
||||
* 6 Request
|
||||
|
@ -245,12 +341,17 @@ public:
|
|||
* the sdp in announce, NULL for no sdp.
|
||||
*/
|
||||
SrsRtspSdp* sdp;
|
||||
/**
|
||||
* the transport in setup, NULL for no transport.
|
||||
*/
|
||||
SrsRtspTransport* transport;
|
||||
public:
|
||||
SrsRtspRequest();
|
||||
virtual ~SrsRtspRequest();
|
||||
public:
|
||||
virtual bool is_options();
|
||||
virtual bool is_announce();
|
||||
virtual bool is_setup();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -302,35 +403,12 @@ public:
|
|||
/**
|
||||
* encode message to string.
|
||||
*/
|
||||
virtual std::stringstream& encode(std::stringstream& ss);
|
||||
};
|
||||
|
||||
/**
|
||||
* 10 Method Definitions
|
||||
* The method token indicates the method to be performed on the resource
|
||||
* identified by the Request-URI. The method is case-sensitive. New
|
||||
* methods may be defined in the future. Method names may not start with
|
||||
* a $ character (decimal 24) and must be a token. Methods are
|
||||
* summarized in Table 2.
|
||||
* Notes on Table 2: PAUSE is recommended, but not required in that a
|
||||
* fully functional server can be built that does not support this
|
||||
* method, for example, for live feeds. If a server does not support a
|
||||
* particular method, it MUST return "501 Not Implemented" and a client
|
||||
* SHOULD not try this method again for this server.
|
||||
*/
|
||||
enum SrsRtspMethod
|
||||
{
|
||||
SrsRtspMethodDescribe = 0x0001,
|
||||
SrsRtspMethodAnnounce = 0x0002,
|
||||
SrsRtspMethodGetParameter = 0x0004,
|
||||
SrsRtspMethodOptions = 0x0008,
|
||||
SrsRtspMethodPause = 0x0010,
|
||||
SrsRtspMethodPlay = 0x0020,
|
||||
SrsRtspMethodRecord = 0x0040,
|
||||
SrsRtspMethodRedirect = 0x0080,
|
||||
SrsRtspMethodSetup = 0x0100,
|
||||
SrsRtspMethodSetParameter = 0x0200,
|
||||
SrsRtspMethodTeardown = 0x0400,
|
||||
virtual int encode(std::stringstream& ss);
|
||||
protected:
|
||||
/**
|
||||
* sub classes override this to encode the headers.
|
||||
*/
|
||||
virtual int encode_header(std::stringstream& ss);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -349,27 +427,38 @@ public:
|
|||
public:
|
||||
SrsRtspOptionsResponse(int cseq);
|
||||
virtual ~SrsRtspOptionsResponse();
|
||||
public:
|
||||
virtual std::stringstream& encode(std::stringstream& ss);
|
||||
protected:
|
||||
virtual int encode_header(std::stringstream& ss);
|
||||
};
|
||||
|
||||
/**
|
||||
* the state of rtsp token.
|
||||
* 10.4 SETUP
|
||||
* The SETUP request for a URI specifies the transport mechanism to be
|
||||
* used for the streamed media. A client can issue a SETUP request for a
|
||||
* stream that is already playing to change transport parameters, which
|
||||
* a server MAY allow. If it does not allow this, it MUST respond with
|
||||
* error "455 Method Not Valid In This State". For the benefit of any
|
||||
* intervening firewalls, a client must indicate the transport
|
||||
* parameters even if it has no influence over these parameters, for
|
||||
* example, where the server advertises a fixed multicast address.
|
||||
*/
|
||||
enum SrsRtspTokenState
|
||||
class SrsRtspSetupResponse : public SrsRtspResponse
|
||||
{
|
||||
/**
|
||||
* parse token failed, default state.
|
||||
*/
|
||||
SrsRtspTokenStateError = 100,
|
||||
/**
|
||||
* when SP follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateNormal = 101,
|
||||
/**
|
||||
* when CRLF follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateEOF = 102,
|
||||
public:
|
||||
// the client specified port.
|
||||
int client_port_min;
|
||||
int client_port_max;
|
||||
// client will use the port in:
|
||||
// [local_port_min, local_port_max)
|
||||
int local_port_min;
|
||||
int local_port_max;
|
||||
// session.
|
||||
std::string session;
|
||||
public:
|
||||
SrsRtspSetupResponse(int cseq);
|
||||
virtual ~SrsRtspSetupResponse();
|
||||
protected:
|
||||
virtual int encode_header(std::stringstream& ss);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue