mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	for #133, support the rtsp options request and response.
This commit is contained in:
		
							parent
							
								
									c0e50265bd
								
							
						
					
					
						commit
						604f4cc57b
					
				
					 8 changed files with 849 additions and 33 deletions
				
			
		| 
						 | 
					@ -62,7 +62,7 @@ int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// get the status text of code.
 | 
					// get the status text of code.
 | 
				
			||||||
string srs_generate_status_text(int status)
 | 
					string srs_generate_http_status_text(int status)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static std::map<int, std::string> _status_map;
 | 
					    static std::map<int, std::string> _status_map;
 | 
				
			||||||
    if (_status_map.empty()) {
 | 
					    if (_status_map.empty()) {
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,7 @@ void SrsGoHttpHeader::write(stringstream& ss)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::map<std::string, std::string>::iterator it;
 | 
					    std::map<std::string, std::string>::iterator it;
 | 
				
			||||||
    for (it = headers.begin(); it != headers.end(); ++it) {
 | 
					    for (it = headers.begin(); it != headers.end(); ++it) {
 | 
				
			||||||
        ss << it->first << ": " << it->second << __SRS_CRLF;
 | 
					        ss << it->first << ": " << it->second << __SRS_HTTP_CRLF;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -711,7 +711,7 @@ int SrsGoHttpResponseWriter::final_request()
 | 
				
			||||||
    // complete the chunked encoding.
 | 
					    // complete the chunked encoding.
 | 
				
			||||||
    if (content_length == -1) {
 | 
					    if (content_length == -1) {
 | 
				
			||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
        ss << 0 << __SRS_CRLF << __SRS_CRLF;
 | 
					        ss << 0 << __SRS_HTTP_CRLF << __SRS_HTTP_CRLF;
 | 
				
			||||||
        std::string ch = ss.str();
 | 
					        std::string ch = ss.str();
 | 
				
			||||||
        return skt->write((void*)ch.data(), (int)ch.length(), NULL);
 | 
					        return skt->write((void*)ch.data(), (int)ch.length(), NULL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -752,7 +752,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // send in chunked encoding.
 | 
					    // send in chunked encoding.
 | 
				
			||||||
    std::stringstream ss;
 | 
					    std::stringstream ss;
 | 
				
			||||||
    ss << hex << size << __SRS_CRLF;
 | 
					    ss << hex << size << __SRS_HTTP_CRLF;
 | 
				
			||||||
    std::string ch = ss.str();
 | 
					    std::string ch = ss.str();
 | 
				
			||||||
    if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) {
 | 
					    if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
| 
						 | 
					@ -760,7 +760,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size)
 | 
				
			||||||
    if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) {
 | 
					    if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if ((ret = skt->write((void*)__SRS_CRLF, 2, NULL)) != ERROR_SUCCESS) {
 | 
					    if ((ret = skt->write((void*)__SRS_HTTP_CRLF, 2, NULL)) != ERROR_SUCCESS) {
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -794,7 +794,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // status_line
 | 
					    // status_line
 | 
				
			||||||
    ss << "HTTP/1.1 " << status << " " 
 | 
					    ss << "HTTP/1.1 " << status << " " 
 | 
				
			||||||
        << srs_generate_status_text(status) << __SRS_CRLF;
 | 
					        << srs_generate_http_status_text(status) << __SRS_HTTP_CRLF;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
    // detect content type
 | 
					    // detect content type
 | 
				
			||||||
    if (srs_go_http_body_allowd(status)) {
 | 
					    if (srs_go_http_body_allowd(status)) {
 | 
				
			||||||
| 
						 | 
					@ -820,7 +820,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size)
 | 
				
			||||||
    hdr->write(ss);
 | 
					    hdr->write(ss);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // header_eof
 | 
					    // header_eof
 | 
				
			||||||
    ss << __SRS_CRLF;
 | 
					    ss << __SRS_HTTP_CRLF;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    std::string buf = ss.str();
 | 
					    std::string buf = ss.str();
 | 
				
			||||||
    return skt->write((void*)buf.c_str(), buf.length(), NULL);
 | 
					    return skt->write((void*)buf.c_str(), buf.length(), NULL);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
#include <http_parser.h>
 | 
					#include <http_parser.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <srs_app_st.hpp>
 | 
					#include <srs_app_st.hpp>
 | 
				
			||||||
 | 
					#include <srs_kernel_consts.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SrsRequest;
 | 
					class SrsRequest;
 | 
				
			||||||
class SrsStSocket;
 | 
					class SrsStSocket;
 | 
				
			||||||
| 
						 | 
					@ -51,19 +52,19 @@ class ISrsGoHttpResponseWriter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// http specification
 | 
					// http specification
 | 
				
			||||||
// CR             = <US-ASCII CR, carriage return (13)>
 | 
					// CR             = <US-ASCII CR, carriage return (13)>
 | 
				
			||||||
#define __SRS_CR SRS_CONSTS_CR // 0x0D
 | 
					#define __SRS_HTTP_CR SRS_CONSTS_CR // 0x0D
 | 
				
			||||||
// LF             = <US-ASCII LF, linefeed (10)>
 | 
					// LF             = <US-ASCII LF, linefeed (10)>
 | 
				
			||||||
#define __SRS_LF SRS_CONSTS_LF // 0x0A
 | 
					#define __SRS_HTTP_LF SRS_CONSTS_LF // 0x0A
 | 
				
			||||||
// SP             = <US-ASCII SP, space (32)>
 | 
					// SP             = <US-ASCII SP, space (32)>
 | 
				
			||||||
#define __SRS_SP ' ' // 0x20
 | 
					#define __SRS_HTTP_SP ' ' // 0x20
 | 
				
			||||||
// HT             = <US-ASCII HT, horizontal-tab (9)>
 | 
					// HT             = <US-ASCII HT, horizontal-tab (9)>
 | 
				
			||||||
#define __SRS_HT '\x09' // 0x09
 | 
					#define __SRS_HTTP_HT '\x09' // 0x09
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
 | 
					// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
 | 
				
			||||||
// protocol elements except the entity-body (see appendix 19.3 for
 | 
					// protocol elements except the entity-body (see appendix 19.3 for
 | 
				
			||||||
// tolerant applications). 
 | 
					// tolerant applications). 
 | 
				
			||||||
#define __SRS_CRLF "\r\n" // 0x0D0A
 | 
					#define __SRS_HTTP_CRLF "\r\n" // 0x0D0A
 | 
				
			||||||
#define __SRS_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
 | 
					#define __SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// @see SrsHttpMessage._http_ts_send_buffer
 | 
					// @see SrsHttpMessage._http_ts_send_buffer
 | 
				
			||||||
#define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
 | 
					#define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,13 +76,13 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r
 | 
				
			||||||
    // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
 | 
					    // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
 | 
				
			||||||
    std::stringstream ss;
 | 
					    std::stringstream ss;
 | 
				
			||||||
    ss << "POST " << uri->get_path() << " "
 | 
					    ss << "POST " << uri->get_path() << " "
 | 
				
			||||||
        << "HTTP/1.1" << __SRS_CRLF
 | 
					        << "HTTP/1.1" << __SRS_HTTP_CRLF
 | 
				
			||||||
        << "Host: " << uri->get_host() << __SRS_CRLF
 | 
					        << "Host: " << uri->get_host() << __SRS_HTTP_CRLF
 | 
				
			||||||
        << "Connection: Keep-Alive" << __SRS_CRLF
 | 
					        << "Connection: Keep-Alive" << __SRS_HTTP_CRLF
 | 
				
			||||||
        << "Content-Length: " << std::dec << req.length() << __SRS_CRLF
 | 
					        << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF
 | 
				
			||||||
        << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_CRLF
 | 
					        << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF
 | 
				
			||||||
        << "Content-Type: application/json" << __SRS_CRLF
 | 
					        << "Content-Type: application/json" << __SRS_HTTP_CRLF
 | 
				
			||||||
        << __SRS_CRLF
 | 
					        << __SRS_HTTP_CRLF
 | 
				
			||||||
        << req;
 | 
					        << req;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    SrsStSocket skt(stfd);
 | 
					    SrsStSocket skt(stfd);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ using namespace std;
 | 
				
			||||||
#include <srs_app_st_socket.hpp>
 | 
					#include <srs_app_st_socket.hpp>
 | 
				
			||||||
#include <srs_kernel_log.hpp>
 | 
					#include <srs_kernel_log.hpp>
 | 
				
			||||||
#include <srs_app_utility.hpp>
 | 
					#include <srs_app_utility.hpp>
 | 
				
			||||||
 | 
					#include <srs_core_autofree.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SRS_AUTO_STREAM_CASTER
 | 
					#ifdef SRS_AUTO_STREAM_CASTER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +77,28 @@ int SrsRtspConn::do_cycle()
 | 
				
			||||||
    std::string ip = srs_get_peer_ip(st_netfd_fileno(stfd));
 | 
					    std::string ip = srs_get_peer_ip(st_netfd_fileno(stfd));
 | 
				
			||||||
    srs_trace("rtsp: serve %s", ip.c_str());
 | 
					    srs_trace("rtsp: serve %s", ip.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // consume all rtsp messages.
 | 
				
			||||||
 | 
					    for (;;) {
 | 
				
			||||||
 | 
					        SrsRtspRequest* req = NULL;
 | 
				
			||||||
 | 
					        if ((ret = rtsp->recv_message(&req)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                srs_error("rtsp: recv request failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        SrsAutoFree(SrsRtspRequest, req);
 | 
				
			||||||
 | 
					        srs_info("rtsp: got rtsp request");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (req->is_options()) {
 | 
				
			||||||
 | 
					            if ((ret = rtsp->send_message(new SrsRtspOptionsResponse(req->seq))) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					                if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                    srs_error("rtsp: send response failed. ret=%d", ret);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return ret;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -265,43 +265,137 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Continue_str                           "Continue"
 | 
					#define SRS_CONSTS_HTTP_Continue_str                           "Continue"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_SwitchingProtocols_str                 "Switching Protocols"
 | 
					#define SRS_CONSTS_HTTP_SwitchingProtocols_str                 "Switching Protocols"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_OK_str                                 "OK"
 | 
					#define SRS_CONSTS_HTTP_OK_str                                 "OK"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Created_str                            "Created "
 | 
					#define SRS_CONSTS_HTTP_Created_str                            "Created"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Accepted_str                           "Accepted"
 | 
					#define SRS_CONSTS_HTTP_Accepted_str                           "Accepted"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NonAuthoritativeInformation_str        "Non Authoritative Information "
 | 
					#define SRS_CONSTS_HTTP_NonAuthoritativeInformation_str        "Non Authoritative Information"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NoContent_str                          "No Content "
 | 
					#define SRS_CONSTS_HTTP_NoContent_str                          "No Content"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_ResetContent_str                       "Reset Content"
 | 
					#define SRS_CONSTS_HTTP_ResetContent_str                       "Reset Content"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_PartialContent_str                     "Partial Content"
 | 
					#define SRS_CONSTS_HTTP_PartialContent_str                     "Partial Content"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_MultipleChoices_str                    "Multiple Choices "
 | 
					#define SRS_CONSTS_HTTP_MultipleChoices_str                    "Multiple Choices"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_MovedPermanently_str                   "Moved Permanently"
 | 
					#define SRS_CONSTS_HTTP_MovedPermanently_str                   "Moved Permanently"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Found_str                              "Found"
 | 
					#define SRS_CONSTS_HTTP_Found_str                              "Found"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_SeeOther_str                           "See Other"
 | 
					#define SRS_CONSTS_HTTP_SeeOther_str                           "See Other"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NotModified_str                        "Not Modified "
 | 
					#define SRS_CONSTS_HTTP_NotModified_str                        "Not Modified"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_UseProxy_str                           "Use Proxy"
 | 
					#define SRS_CONSTS_HTTP_UseProxy_str                           "Use Proxy"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_TemporaryRedirect_str                  "Temporary Redirect "
 | 
					#define SRS_CONSTS_HTTP_TemporaryRedirect_str                  "Temporary Redirect"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_BadRequest_str                         "Bad Request"
 | 
					#define SRS_CONSTS_HTTP_BadRequest_str                         "Bad Request"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Unauthorized_str                       "Unauthorized"
 | 
					#define SRS_CONSTS_HTTP_Unauthorized_str                       "Unauthorized"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_PaymentRequired_str                    "Payment Required "
 | 
					#define SRS_CONSTS_HTTP_PaymentRequired_str                    "Payment Required"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Forbidden_str                          "Forbidden "
 | 
					#define SRS_CONSTS_HTTP_Forbidden_str                          "Forbidden"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NotFound_str                           "Not Found"
 | 
					#define SRS_CONSTS_HTTP_NotFound_str                           "Not Found"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_MethodNotAllowed_str                   "Method Not Allowed"
 | 
					#define SRS_CONSTS_HTTP_MethodNotAllowed_str                   "Method Not Allowed"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NotAcceptable_str                      "Not Acceptable "
 | 
					#define SRS_CONSTS_HTTP_NotAcceptable_str                      "Not Acceptable"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str        "Proxy Authentication Required "
 | 
					#define SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str        "Proxy Authentication Required"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_RequestTimeout_str                     "Request Timeout"
 | 
					#define SRS_CONSTS_HTTP_RequestTimeout_str                     "Request Timeout"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Conflict_str                           "Conflict"
 | 
					#define SRS_CONSTS_HTTP_Conflict_str                           "Conflict"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_Gone_str                               "Gone"
 | 
					#define SRS_CONSTS_HTTP_Gone_str                               "Gone"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_LengthRequired_str                     "Length Required"
 | 
					#define SRS_CONSTS_HTTP_LengthRequired_str                     "Length Required"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_PreconditionFailed_str                 "Precondition Failed"
 | 
					#define SRS_CONSTS_HTTP_PreconditionFailed_str                 "Precondition Failed"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_RequestEntityTooLarge_str              "Request Entity Too Large "
 | 
					#define SRS_CONSTS_HTTP_RequestEntityTooLarge_str              "Request Entity Too Large"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_RequestURITooLarge_str                 "Request URI Too Large"
 | 
					#define SRS_CONSTS_HTTP_RequestURITooLarge_str                 "Request URI Too Large"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_UnsupportedMediaType_str               "Unsupported Media Type"
 | 
					#define SRS_CONSTS_HTTP_UnsupportedMediaType_str               "Unsupported Media Type"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str       "Requested Range Not Satisfiable"
 | 
					#define SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str       "Requested Range Not Satisfiable"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_ExpectationFailed_str                  "Expectation Failed "
 | 
					#define SRS_CONSTS_HTTP_ExpectationFailed_str                  "Expectation Failed"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_InternalServerError_str                "Internal Server Error "
 | 
					#define SRS_CONSTS_HTTP_InternalServerError_str                "Internal Server Error"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_NotImplemented_str                     "Not Implemented"
 | 
					#define SRS_CONSTS_HTTP_NotImplemented_str                     "Not Implemented"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_BadGateway_str                         "Bad Gateway"
 | 
					#define SRS_CONSTS_HTTP_BadGateway_str                         "Bad Gateway"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_ServiceUnavailable_str                 "Service Unavailable"
 | 
					#define SRS_CONSTS_HTTP_ServiceUnavailable_str                 "Service Unavailable"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_GatewayTimeout_str                     "Gateway Timeout"
 | 
					#define SRS_CONSTS_HTTP_GatewayTimeout_str                     "Gateway Timeout"
 | 
				
			||||||
#define SRS_CONSTS_HTTP_HTTPVersionNotSupported_str            "HTTP Version Not Supported"
 | 
					#define SRS_CONSTS_HTTP_HTTPVersionNotSupported_str            "HTTP Version Not Supported"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// RTSP consts values
 | 
				
			||||||
 | 
					///////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					// 7.1.1 Status Code and Reason Phrase
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Continue                       100
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OK                             200
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Created                        201
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_LowOnStorageSpace              250
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MultipleChoices                300
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MovedPermanently               301
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MovedTemporarily               302
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_SeeOther                       303
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotModified                    304
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UseProxy                       305
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_BadRequest                     400
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Unauthorized                   401
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_PaymentRequired                402
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Forbidden                      403
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotFound                       404
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MethodNotAllowed               405
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotAcceptable                  406
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ProxyAuthenticationRequired    407
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestTimeout                 408
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Gone                           410
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_LengthRequired                 411
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_PreconditionFailed             412
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestEntityTooLarge          413
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestURITooLarge             414
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UnsupportedMediaType           415
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ParameterNotUnderstood         451
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ConferenceNotFound             452
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotEnoughBandwidth             453
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_SessionNotFound                454
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MethodNotValidInThisState      455
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_HeaderFieldNotValidForResource 456
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_InvalidRange                   457
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ParameterIsReadOnly            458
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_AggregateOperationNotAllowed   459
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed  460
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UnsupportedTransport           461
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_DestinationUnreachable         462
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_InternalServerError            500
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotImplemented                 501
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_BadGateway                     502
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ServiceUnavailable             503
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_GatewayTimeout                 504
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RTSPVersionNotSupported        505
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OptionNotSupported             551
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Continue_str                            "Continue"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OK_str                                  "OK"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Created_str                             "Created"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_LowOnStorageSpace_str                   "Low on Storage Space"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MultipleChoices_str                     "Multiple Choices"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MovedPermanently_str                    "Moved Permanently"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MovedTemporarily_str                    "Moved Temporarily"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_SeeOther_str                            "See Other"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotModified_str                         "Not Modified"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UseProxy_str                            "Use Proxy"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_BadRequest_str                          "Bad Request"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Unauthorized_str                        "Unauthorized"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_PaymentRequired_str                     "Payment Required"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Forbidden_str                           "Forbidden"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotFound_str                            "Not Found"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MethodNotAllowed_str                    "Method Not Allowed"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotAcceptable_str                       "Not Acceptable"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ProxyAuthenticationRequired_str         "Proxy Authentication Required"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestTimeout_str                      "Request Timeout"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_Gone_str                                "Gone"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_LengthRequired_str                      "Length Required"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_PreconditionFailed_str                  "Precondition Failed"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestEntityTooLarge_str               "Request Entity Too Large"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RequestURITooLarge_str                  "Request URI Too Large"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UnsupportedMediaType_str                "Unsupported Media Type"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ParameterNotUnderstood_str              "Invalid parameter"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ConferenceNotFound_str                  "Illegal Conference Identifier"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotEnoughBandwidth_str                  "Not Enough Bandwidth"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_SessionNotFound_str                     "Session Not Found"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_MethodNotValidInThisState_str           "Method Not Valid In This State"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_HeaderFieldNotValidForResource_str      "Header Field Not Valid"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_InvalidRange_str                        "Invalid Range"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ParameterIsReadOnly_str                 "Parameter Is Read-Only"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_AggregateOperationNotAllowed_str        "Aggregate Operation Not Allowed"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed_str       "Only Aggregate Operation Allowed"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_UnsupportedTransport_str                "Unsupported Transport"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_DestinationUnreachable_str              "Destination Unreachable"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_InternalServerError_str                 "Internal Server Error"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_NotImplemented_str                      "Not Implemented"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_BadGateway_str                          "Bad Gateway"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_ServiceUnavailable_str                  "Service Unavailable"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_GatewayTimeout_str                      "Gateway Timeout"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_RTSPVersionNotSupported_str             "RTSP Version Not Supported"
 | 
				
			||||||
 | 
					#define SRS_CONSTS_RTSP_OptionNotSupported_str                  "Option not support"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,6 +142,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
#define ERROR_OpenSslComputeSharedKey       2039
 | 
					#define ERROR_OpenSslComputeSharedKey       2039
 | 
				
			||||||
#define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED    2040
 | 
					#define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED    2040
 | 
				
			||||||
#define ERROR_RTMP_MIC_CACHE_OVERFLOW       2041
 | 
					#define ERROR_RTMP_MIC_CACHE_OVERFLOW       2041
 | 
				
			||||||
 | 
					#define ERROR_RTSP_TOKEN_NOT_NORMAL         2042
 | 
				
			||||||
 | 
					#define ERROR_RTSP_REQUEST_HEADER_EOF       2043
 | 
				
			||||||
//                                           
 | 
					//                                           
 | 
				
			||||||
// system control message, 
 | 
					// system control message, 
 | 
				
			||||||
// not an error, but special control logic.
 | 
					// not an error, but special control logic.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,17 +23,465 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <srs_rtsp_stack.hpp>
 | 
					#include <srs_rtsp_stack.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <srs_rtmp_io.hpp>
 | 
					#include <srs_rtmp_io.hpp>
 | 
				
			||||||
 | 
					#include <srs_kernel_buffer.hpp>
 | 
				
			||||||
 | 
					#include <srs_kernel_error.hpp>
 | 
				
			||||||
 | 
					#include <srs_kernel_log.hpp>
 | 
				
			||||||
 | 
					#include <srs_kernel_consts.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SRS_AUTO_STREAM_CASTER
 | 
					#ifdef SRS_AUTO_STREAM_CASTER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define __SRS_RTSP_BUFFER 4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// get the status text of code.
 | 
				
			||||||
 | 
					string srs_generate_rtsp_status_text(int status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static std::map<int, std::string> _status_map;
 | 
				
			||||||
 | 
					    if (_status_map.empty()) {
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_Continue                       ] = SRS_CONSTS_RTSP_Continue_str                        ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_OK                             ] = SRS_CONSTS_RTSP_OK_str                              ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_Created                        ] = SRS_CONSTS_RTSP_Created_str                         ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_LowOnStorageSpace              ] = SRS_CONSTS_RTSP_LowOnStorageSpace_str               ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_MultipleChoices                ] = SRS_CONSTS_RTSP_MultipleChoices_str                 ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_MovedPermanently               ] = SRS_CONSTS_RTSP_MovedPermanently_str                ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_MovedTemporarily               ] = SRS_CONSTS_RTSP_MovedTemporarily_str                ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_SeeOther                       ] = SRS_CONSTS_RTSP_SeeOther_str                        ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_NotModified                    ] = SRS_CONSTS_RTSP_NotModified_str                     ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_UseProxy                       ] = SRS_CONSTS_RTSP_UseProxy_str                        ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_BadRequest                     ] = SRS_CONSTS_RTSP_BadRequest_str                      ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_Unauthorized                   ] = SRS_CONSTS_RTSP_Unauthorized_str                    ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_PaymentRequired                ] = SRS_CONSTS_RTSP_PaymentRequired_str                 ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_Forbidden                      ] = SRS_CONSTS_RTSP_Forbidden_str                       ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_NotFound                       ] = SRS_CONSTS_RTSP_NotFound_str                        ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_MethodNotAllowed               ] = SRS_CONSTS_RTSP_MethodNotAllowed_str                ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_NotAcceptable                  ] = SRS_CONSTS_RTSP_NotAcceptable_str                   ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_ProxyAuthenticationRequired    ] = SRS_CONSTS_RTSP_ProxyAuthenticationRequired_str     ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_RequestTimeout                 ] = SRS_CONSTS_RTSP_RequestTimeout_str                  ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_Gone                           ] = SRS_CONSTS_RTSP_Gone_str                            ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_LengthRequired                 ] = SRS_CONSTS_RTSP_LengthRequired_str                  ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_PreconditionFailed             ] = SRS_CONSTS_RTSP_PreconditionFailed_str              ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_RequestEntityTooLarge          ] = SRS_CONSTS_RTSP_RequestEntityTooLarge_str           ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_RequestURITooLarge             ] = SRS_CONSTS_RTSP_RequestURITooLarge_str              ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_UnsupportedMediaType           ] = SRS_CONSTS_RTSP_UnsupportedMediaType_str            ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_ParameterNotUnderstood         ] = SRS_CONSTS_RTSP_ParameterNotUnderstood_str          ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_ConferenceNotFound             ] = SRS_CONSTS_RTSP_ConferenceNotFound_str              ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_NotEnoughBandwidth             ] = SRS_CONSTS_RTSP_NotEnoughBandwidth_str              ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_SessionNotFound                ] = SRS_CONSTS_RTSP_SessionNotFound_str                 ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_MethodNotValidInThisState      ] = SRS_CONSTS_RTSP_MethodNotValidInThisState_str       ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_HeaderFieldNotValidForResource ] = SRS_CONSTS_RTSP_HeaderFieldNotValidForResource_str  ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_InvalidRange                   ] = SRS_CONSTS_RTSP_InvalidRange_str                    ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_ParameterIsReadOnly            ] = SRS_CONSTS_RTSP_ParameterIsReadOnly_str             ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_AggregateOperationNotAllowed   ] = SRS_CONSTS_RTSP_AggregateOperationNotAllowed_str    ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed  ] = SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed_str   ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_UnsupportedTransport           ] = SRS_CONSTS_RTSP_UnsupportedTransport_str            ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_DestinationUnreachable         ] = SRS_CONSTS_RTSP_DestinationUnreachable_str          ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_InternalServerError            ] = SRS_CONSTS_RTSP_InternalServerError_str             ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_NotImplemented                 ] = SRS_CONSTS_RTSP_NotImplemented_str                  ;      
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_BadGateway                     ] = SRS_CONSTS_RTSP_BadGateway_str                      ;     
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_ServiceUnavailable             ] = SRS_CONSTS_RTSP_ServiceUnavailable_str              ;     
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_GatewayTimeout                 ] = SRS_CONSTS_RTSP_GatewayTimeout_str                  ;     
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_RTSPVersionNotSupported        ] = SRS_CONSTS_RTSP_RTSPVersionNotSupported_str         ;     
 | 
				
			||||||
 | 
					        _status_map[SRS_CONSTS_RTSP_OptionNotSupported             ] = SRS_CONSTS_RTSP_OptionNotSupported_str              ;        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    std::string status_text;
 | 
				
			||||||
 | 
					    if (_status_map.find(status) == _status_map.end()) {
 | 
				
			||||||
 | 
					        status_text = "Status Unknown";
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        status_text = _status_map[status];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return status_text;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string srs_generate_rtsp_method_str(SrsRtspMethod method) 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch (method) {
 | 
				
			||||||
 | 
					        case SrsRtspMethodDescribe: return __SRS_METHOD_DESCRIBE;
 | 
				
			||||||
 | 
					        case SrsRtspMethodAnnounce: return __SRS_METHOD_ANNOUNCE;
 | 
				
			||||||
 | 
					        case SrsRtspMethodGetParameter: return __SRS_METHOD_GET_PARAMETER;
 | 
				
			||||||
 | 
					        case SrsRtspMethodOptions: return __SRS_METHOD_OPTIONS;
 | 
				
			||||||
 | 
					        case SrsRtspMethodPause: return __SRS_METHOD_PAUSE;
 | 
				
			||||||
 | 
					        case SrsRtspMethodPlay: return __SRS_METHOD_PLAY;
 | 
				
			||||||
 | 
					        case SrsRtspMethodRecord: return __SRS_METHOD_RECORD;
 | 
				
			||||||
 | 
					        case SrsRtspMethodRedirect: return __SRS_METHOD_REDIRECT;
 | 
				
			||||||
 | 
					        case SrsRtspMethodSetup: return __SRS_METHOD_SETUP;
 | 
				
			||||||
 | 
					        case SrsRtspMethodSetParameter: return __SRS_METHOD_SET_PARAMETER;
 | 
				
			||||||
 | 
					        case SrsRtspMethodTeardown: return __SRS_METHOD_TEARDOWN;
 | 
				
			||||||
 | 
					        default: return "Unknown";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspRequest::SrsRtspRequest()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    seq = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspRequest::~SrsRtspRequest()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SrsRtspRequest::is_options()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return method == __SRS_METHOD_OPTIONS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspResponse::SrsRtspResponse(int cseq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    seq = cseq;
 | 
				
			||||||
 | 
					    status = SRS_CONSTS_RTSP_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspResponse::~SrsRtspResponse()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stringstream& SrsRtspResponse::encode(stringstream& ss)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // status line
 | 
				
			||||||
 | 
					    ss << __SRS_VERSION << __SRS_RTSP_SP 
 | 
				
			||||||
 | 
					        << status << __SRS_RTSP_SP 
 | 
				
			||||||
 | 
					        << srs_generate_rtsp_status_text(status) << __SRS_RTSP_CRLF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cseq
 | 
				
			||||||
 | 
					    ss << __SRS_TOKEN_CSEQ << ":" << __SRS_RTSP_SP << seq << __SRS_RTSP_CRLF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // others.
 | 
				
			||||||
 | 
					    ss << "Cache-Control: no-store" << __SRS_RTSP_CRLF
 | 
				
			||||||
 | 
					        << "Pragma: no-cache" << __SRS_RTSP_CRLF
 | 
				
			||||||
 | 
					        << "Server: " << RTMP_SIG_SRS_SERVER << __SRS_RTSP_CRLF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ss;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    methods = (SrsRtspMethod)(SrsRtspMethodDescribe | SrsRtspMethodOptions 
 | 
				
			||||||
 | 
					        | SrsRtspMethodPause | SrsRtspMethodPlay | SrsRtspMethodSetup | SrsRtspMethodTeardown
 | 
				
			||||||
 | 
					        | SrsRtspMethodAnnounce | SrsRtspMethodRecord);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SrsRtspOptionsResponse::~SrsRtspOptionsResponse()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stringstream& SrsRtspOptionsResponse::encode(stringstream& ss)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SrsRtspResponse::encode(ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SrsRtspMethod __methods[] = {
 | 
				
			||||||
 | 
					        SrsRtspMethodDescribe,
 | 
				
			||||||
 | 
					        SrsRtspMethodAnnounce,
 | 
				
			||||||
 | 
					        SrsRtspMethodGetParameter,
 | 
				
			||||||
 | 
					        SrsRtspMethodOptions,
 | 
				
			||||||
 | 
					        SrsRtspMethodPause,
 | 
				
			||||||
 | 
					        SrsRtspMethodPlay,
 | 
				
			||||||
 | 
					        SrsRtspMethodRecord,
 | 
				
			||||||
 | 
					        SrsRtspMethodRedirect,
 | 
				
			||||||
 | 
					        SrsRtspMethodSetup,
 | 
				
			||||||
 | 
					        SrsRtspMethodSetParameter,
 | 
				
			||||||
 | 
					        SrsRtspMethodTeardown,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ss << __SRS_TOKEN_PUBLIC << ":" << __SRS_RTSP_SP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool appended = false;
 | 
				
			||||||
 | 
					    int nb_methods = (int)(sizeof(__methods) / sizeof(SrsRtspMethod));
 | 
				
			||||||
 | 
					    for (int i = 0; i < nb_methods; i++) {
 | 
				
			||||||
 | 
					        SrsRtspMethod method = __methods[i];
 | 
				
			||||||
 | 
					        if (((int)methods & (int)method) != (int)method) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (appended) {
 | 
				
			||||||
 | 
					            ss << ", ";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        ss << srs_generate_rtsp_method_str(method);
 | 
				
			||||||
 | 
					        appended = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ss << __SRS_RTSP_CRLF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // eof header.
 | 
				
			||||||
 | 
					    ss << __SRS_RTSP_CRLF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ss;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s)
 | 
					SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    buf = new SrsSimpleBuffer();
 | 
				
			||||||
    skt = s;
 | 
					    skt = s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SrsRtspStack::~SrsRtspStack()
 | 
					SrsRtspStack::~SrsRtspStack()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    srs_freep(buf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::recv_message(SrsRtspRequest** preq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SrsRtspRequest* req = new SrsRtspRequest();
 | 
				
			||||||
 | 
					    if ((ret = do_recv_message(req)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        srs_freep(req);
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *preq = req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::send_message(SrsRtspResponse* res)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::stringstream ss;
 | 
				
			||||||
 | 
					    // encode the message to string.
 | 
				
			||||||
 | 
					    res->encode(ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string str = ss.str();
 | 
				
			||||||
 | 
					    srs_assert(!str.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = skt->write((char*)str.c_str(), (int)str.length(), NULL)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: send response failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    srs_info("rtsp: send response ok");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // parse request line.
 | 
				
			||||||
 | 
					    if ((ret = recv_token_normal(req->method)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse method failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = recv_token_normal(req->uri)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse uri failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = recv_token_eof(req->version)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse version failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // parse headers.
 | 
				
			||||||
 | 
					    for (;;) {
 | 
				
			||||||
 | 
					        // parse the header name
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        if ((ret = recv_token_normal(token)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					            if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
 | 
				
			||||||
 | 
					                ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					                srs_info("rtsp: message header parsed");
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                srs_error("rtsp: parse token failed. ret=%d", ret);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // parse the header value according by header name
 | 
				
			||||||
 | 
					        if (token == __SRS_TOKEN_CSEQ) {
 | 
				
			||||||
 | 
					            std::string seq;
 | 
				
			||||||
 | 
					            if ((ret = recv_token_eof(seq)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					                if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                    srs_error("rtsp: parse seq failed. ret=%d", ret);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return ret;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            req->seq = ::atoi(seq.c_str());
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // unknown header name, parse util EOF.
 | 
				
			||||||
 | 
					            SrsRtspTokenState state = SrsRtspTokenStateNormal;
 | 
				
			||||||
 | 
					            while (state == SrsRtspTokenStateNormal) {
 | 
				
			||||||
 | 
					                std::string value;
 | 
				
			||||||
 | 
					                if ((ret = recv_token(value, state)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					                    if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                        srs_error("rtsp: parse token failed. ret=%d", ret);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    return ret;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                srs_trace("rtsp: ignore header %s=%s", token.c_str(), value.c_str());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // parse body.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::recv_token_normal(std::string& token)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SrsRtspTokenState state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = recv_token(token, state)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse token failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state != SrsRtspTokenStateNormal) {
 | 
				
			||||||
 | 
					        ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
 | 
				
			||||||
 | 
					        srs_error("rtsp: parse normal token failed, state=%d. ret=%d", state, ret);
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::recv_token_eof(std::string& token)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SrsRtspTokenState state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = recv_token(token, state)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse token failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state != SrsRtspTokenStateEOF) {
 | 
				
			||||||
 | 
					        ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
 | 
				
			||||||
 | 
					        srs_error("rtsp: parse eof token failed, state=%d. ret=%d", state, ret);
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::recv_token_util_eof(std::string& token)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SrsRtspTokenState state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // use 0x00 as ignore the normal token flag.
 | 
				
			||||||
 | 
					    if ((ret = recv_token(token, state, 0x00)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					        if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					            srs_error("rtsp: parse token failed. ret=%d", ret);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state != SrsRtspTokenStateEOF) {
 | 
				
			||||||
 | 
					        ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
 | 
				
			||||||
 | 
					        srs_error("rtsp: parse eof token failed, state=%d. ret=%d", state, ret);
 | 
				
			||||||
 | 
					        return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret = ERROR_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // whatever, default to error state.
 | 
				
			||||||
 | 
					    state = SrsRtspTokenStateError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // when buffer is empty, append bytes first.
 | 
				
			||||||
 | 
					    bool append_bytes = buf->length() == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // parse util token.
 | 
				
			||||||
 | 
					    for (;;) {
 | 
				
			||||||
 | 
					        // append bytes if required.
 | 
				
			||||||
 | 
					        if (append_bytes) {
 | 
				
			||||||
 | 
					            append_bytes = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char buffer[__SRS_RTSP_BUFFER];
 | 
				
			||||||
 | 
					            ssize_t nb_read = 0;
 | 
				
			||||||
 | 
					            if ((ret = skt->read(buffer, __SRS_RTSP_BUFFER, &nb_read)) != ERROR_SUCCESS) {
 | 
				
			||||||
 | 
					                if (!srs_is_client_gracefully_close(ret)) {
 | 
				
			||||||
 | 
					                    srs_error("rtsp: io read failed. ret=%d", ret);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return ret;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            srs_info("rtsp: io read %d bytes", nb_read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            buf->append(buffer, nb_read);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // parse one by one.
 | 
				
			||||||
 | 
					        char* start = buf->bytes();
 | 
				
			||||||
 | 
					        char* end = start + buf->length();
 | 
				
			||||||
 | 
					        char* p = start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // find util SP/CR/LF, max 2 EOF, to finger out the EOF of message.
 | 
				
			||||||
 | 
					        for (; p < end && p[0] != normal_ch && p[0] != __SRS_RTSP_CR && p[0] != __SRS_RTSP_LF; p++) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // matched.
 | 
				
			||||||
 | 
					        if (p < end) {
 | 
				
			||||||
 | 
					            // finger out the state.
 | 
				
			||||||
 | 
					            if (p[0] == normal_ch) {
 | 
				
			||||||
 | 
					                state = SrsRtspTokenStateNormal;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                state = SrsRtspTokenStateEOF;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // got the token.
 | 
				
			||||||
 | 
					            int nb_token = p - start;
 | 
				
			||||||
 | 
					            // trim last ':' character.
 | 
				
			||||||
 | 
					            if (nb_token && p[-1] == ':') {
 | 
				
			||||||
 | 
					                nb_token--;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (nb_token) {
 | 
				
			||||||
 | 
					                token.append(start, nb_token);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ret = ERROR_RTSP_REQUEST_HEADER_EOF;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // ignore SP/CR/LF
 | 
				
			||||||
 | 
					            for (int i = 0; i < 2 && p < end && (p[0] == normal_ch || p[0] == __SRS_RTSP_CR || p[0] == __SRS_RTSP_LF); p++, i++) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // consume the token bytes.
 | 
				
			||||||
 | 
					            srs_assert(p - start);
 | 
				
			||||||
 | 
					            buf->erase(p - start);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // append more and parse again.
 | 
				
			||||||
 | 
					        append_bytes = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,16 +30,223 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <srs_core.hpp>
 | 
					#include <srs_core.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <srs_kernel_consts.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef SRS_AUTO_STREAM_CASTER
 | 
					#ifdef SRS_AUTO_STREAM_CASTER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SrsSimpleBuffer;
 | 
				
			||||||
class ISrsProtocolReaderWriter;
 | 
					class ISrsProtocolReaderWriter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// rtsp specification
 | 
				
			||||||
 | 
					// CR             = <US-ASCII CR, carriage return (13)>
 | 
				
			||||||
 | 
					#define __SRS_RTSP_CR SRS_CONSTS_CR // 0x0D
 | 
				
			||||||
 | 
					// LF             = <US-ASCII LF, linefeed (10)>
 | 
				
			||||||
 | 
					#define __SRS_RTSP_LF SRS_CONSTS_LF // 0x0A
 | 
				
			||||||
 | 
					// SP             = <US-ASCII SP, space (32)>
 | 
				
			||||||
 | 
					#define __SRS_RTSP_SP ' ' // 0x20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 4 RTSP Message
 | 
				
			||||||
 | 
					// Lines are terminated by CRLF, but
 | 
				
			||||||
 | 
					// receivers should be prepared to also interpret CR and LF by
 | 
				
			||||||
 | 
					// themselves as line terminators.
 | 
				
			||||||
 | 
					#define __SRS_RTSP_CRLF "\r\n" // 0x0D0A
 | 
				
			||||||
 | 
					#define __SRS_RTSP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RTSP token
 | 
				
			||||||
 | 
					#define __SRS_TOKEN_CSEQ "CSeq"
 | 
				
			||||||
 | 
					#define __SRS_TOKEN_PUBLIC "Public"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RTSP methods
 | 
				
			||||||
 | 
					#define __SRS_METHOD_OPTIONS            "OPTIONS"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_DESCRIBE           "DESCRIBE"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_ANNOUNCE           "ANNOUNCE"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_SETUP              "SETUP"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_PLAY               "PLAY"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_PAUSE              "PAUSE"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_TEARDOWN           "TEARDOWN"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_GET_PARAMETER      "GET_PARAMETER"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_SET_PARAMETER      "SET_PARAMETER"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_REDIRECT           "REDIRECT"
 | 
				
			||||||
 | 
					#define __SRS_METHOD_RECORD             "RECORD"
 | 
				
			||||||
 | 
					// Embedded (Interleaved) Binary Data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RTSP-Version
 | 
				
			||||||
 | 
					#define __SRS_VERSION "RTSP/1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* the rtsp request message.
 | 
				
			||||||
 | 
					* 6 Request
 | 
				
			||||||
 | 
					* A request message from a client to a server or vice versa includes,
 | 
				
			||||||
 | 
					* within the first line of that message, the method to be applied to
 | 
				
			||||||
 | 
					* the resource, the identifier of the resource, and the protocol
 | 
				
			||||||
 | 
					* version in use.
 | 
				
			||||||
 | 
					* Request = Request-Line ; Section 6.1
 | 
				
			||||||
 | 
					*           *( general-header ; Section 5
 | 
				
			||||||
 | 
					*           | request-header ; Section 6.2
 | 
				
			||||||
 | 
					*           | entity-header ) ; Section 8.1
 | 
				
			||||||
 | 
					*           CRLF
 | 
				
			||||||
 | 
					*           [ message-body ] ; Section 4.3
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					class SrsRtspRequest
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 6.1 Request Line
 | 
				
			||||||
 | 
					    * Request-Line = Method SP Request-URI SP RTSP-Version CRLF
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    std::string method;
 | 
				
			||||||
 | 
					    std::string uri;
 | 
				
			||||||
 | 
					    std::string version;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 12.17 CSeq
 | 
				
			||||||
 | 
					    * The CSeq field specifies the sequence number for an RTSP requestresponse
 | 
				
			||||||
 | 
					    * pair. This field MUST be present in all requests and
 | 
				
			||||||
 | 
					    * responses. For every RTSP request containing the given sequence
 | 
				
			||||||
 | 
					    * number, there will be a corresponding response having the same
 | 
				
			||||||
 | 
					    * number. Any retransmitted request must contain the same sequence
 | 
				
			||||||
 | 
					    * number as the original (i.e. the sequence number is not incremented
 | 
				
			||||||
 | 
					    * for retransmissions of the same request).
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    int seq;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    SrsRtspRequest();
 | 
				
			||||||
 | 
					    virtual ~SrsRtspRequest();
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    virtual bool is_options();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* the rtsp response message.
 | 
				
			||||||
 | 
					* 7 Response
 | 
				
			||||||
 | 
					* [H6] applies except that HTTP-Version is replaced by RTSP-Version.
 | 
				
			||||||
 | 
					* Also, RTSP defines additional status codes and does not define some
 | 
				
			||||||
 | 
					* HTTP codes. The valid response codes and the methods they can be used
 | 
				
			||||||
 | 
					* with are defined in Table 1.
 | 
				
			||||||
 | 
					* After receiving and interpreting a request message, the recipient
 | 
				
			||||||
 | 
					* responds with an RTSP response message.
 | 
				
			||||||
 | 
					*       Response = Status-Line ; Section 7.1
 | 
				
			||||||
 | 
					*                   *( general-header ; Section 5
 | 
				
			||||||
 | 
					*                   | response-header ; Section 7.1.2
 | 
				
			||||||
 | 
					*                   | entity-header ) ; Section 8.1
 | 
				
			||||||
 | 
					*                   CRLF
 | 
				
			||||||
 | 
					*                   [ message-body ] ; Section 4.3
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					class SrsRtspResponse
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 7.1 Status-Line
 | 
				
			||||||
 | 
					    * The first line of a Response message is the Status-Line, consisting
 | 
				
			||||||
 | 
					    * of the protocol version followed by a numeric status code, and the
 | 
				
			||||||
 | 
					    * textual phrase associated with the status code, with each element
 | 
				
			||||||
 | 
					    * separated by SP characters. No CR or LF is allowed except in the
 | 
				
			||||||
 | 
					    * final CRLF sequence.
 | 
				
			||||||
 | 
					    *       Status-Line = RTSP-Version SP Status-Code SP Reason-Phrase CRLF
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    // @see about the version of rtsp, see __SRS_VERSION
 | 
				
			||||||
 | 
					    // @see about the status of rtsp, see SRS_CONSTS_RTSP_OK
 | 
				
			||||||
 | 
					    int status;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * 12.17 CSeq
 | 
				
			||||||
 | 
					    * The CSeq field specifies the sequence number for an RTSP requestresponse
 | 
				
			||||||
 | 
					    * pair. This field MUST be present in all requests and
 | 
				
			||||||
 | 
					    * responses. For every RTSP request containing the given sequence
 | 
				
			||||||
 | 
					    * number, there will be a corresponding response having the same
 | 
				
			||||||
 | 
					    * number. Any retransmitted request must contain the same sequence
 | 
				
			||||||
 | 
					    * number as the original (i.e. the sequence number is not incremented
 | 
				
			||||||
 | 
					    * for retransmissions of the same request).
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    int seq;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    SrsRtspResponse(int cseq);
 | 
				
			||||||
 | 
					    virtual ~SrsRtspResponse();
 | 
				
			||||||
 | 
					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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* 10.1 OPTIONS
 | 
				
			||||||
 | 
					* The behavior is equivalent to that described in [H9.2]. An OPTIONS
 | 
				
			||||||
 | 
					* request may be issued at any time, e.g., if the client is about to
 | 
				
			||||||
 | 
					* try a nonstandard request. It does not influence server state.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					class SrsRtspOptionsResponse : public SrsRtspResponse
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * join of SrsRtspMethod
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    SrsRtspMethod methods;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    SrsRtspOptionsResponse(int cseq);
 | 
				
			||||||
 | 
					    virtual ~SrsRtspOptionsResponse();
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    virtual std::stringstream& encode(std::stringstream& ss);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* 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 rtsp protocol stack to parse the rtsp packets.
 | 
					* the rtsp protocol stack to parse the rtsp packets.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
class SrsRtspStack
 | 
					class SrsRtspStack
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * cached bytes buffer.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    SrsSimpleBuffer* buf;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    * underlayer socket object, send/recv bytes.
 | 
					    * underlayer socket object, send/recv bytes.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
| 
						 | 
					@ -47,6 +254,47 @@ private:
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    SrsRtspStack(ISrsProtocolReaderWriter* s);
 | 
					    SrsRtspStack(ISrsProtocolReaderWriter* s);
 | 
				
			||||||
    virtual ~SrsRtspStack();
 | 
					    virtual ~SrsRtspStack();
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * recv rtsp message from underlayer io.
 | 
				
			||||||
 | 
					    * @param preq the output rtsp request message, which user must free it.
 | 
				
			||||||
 | 
					    * @return an int error code. 
 | 
				
			||||||
 | 
					    *       ERROR_RTSP_REQUEST_HEADER_EOF indicates request header EOF.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int recv_message(SrsRtspRequest** preq);
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * send rtsp message over underlayer io.
 | 
				
			||||||
 | 
					    * @param res the rtsp response message, which user should never free it.
 | 
				
			||||||
 | 
					    * @return an int error code.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int send_message(SrsRtspResponse* res);
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * recv the rtsp message.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int do_recv_message(SrsRtspRequest* req);
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * read a normal token from io, error when token state is not normal.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int recv_token_normal(std::string& token);
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * read a normal token from io, error when token state is not eof.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int recv_token_eof(std::string& token);
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * read the token util got eof, for example, to read the response status Reason-Phrase
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int recv_token_util_eof(std::string& token);
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * read a token from io, split by SP, endswith CRLF:
 | 
				
			||||||
 | 
					    *       token1 SP token2 SP ... tokenN CRLF
 | 
				
			||||||
 | 
					    * @param normal_ch, the char to indicates the normal token. 
 | 
				
			||||||
 | 
					    *       the SP use to indicates the normal token, @see __SRS_RTSP_SP
 | 
				
			||||||
 | 
					    *       the 0x00 use to ignore normal token flag. @see recv_token_util_eof
 | 
				
			||||||
 | 
					    * @param token, output the read token.
 | 
				
			||||||
 | 
					    * @param state, output the token parse state.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    virtual int recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch = __SRS_RTSP_SP);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue