winlin

for #133, support the rtsp options request and response.

@@ -62,7 +62,7 @@ int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data) @@ -62,7 +62,7 @@ int srs_go_http_response_json(ISrsGoHttpResponseWriter* w, string data)
62 } 62 }
63 63
64 // get the status text of code. 64 // get the status text of code.
65 -string srs_generate_status_text(int status) 65 +string srs_generate_http_status_text(int status)
66 { 66 {
67 static std::map<int, std::string> _status_map; 67 static std::map<int, std::string> _status_map;
68 if (_status_map.empty()) { 68 if (_status_map.empty()) {
@@ -212,7 +212,7 @@ void SrsGoHttpHeader::write(stringstream& ss) @@ -212,7 +212,7 @@ void SrsGoHttpHeader::write(stringstream& ss)
212 { 212 {
213 std::map<std::string, std::string>::iterator it; 213 std::map<std::string, std::string>::iterator it;
214 for (it = headers.begin(); it != headers.end(); ++it) { 214 for (it = headers.begin(); it != headers.end(); ++it) {
215 - ss << it->first << ": " << it->second << __SRS_CRLF; 215 + ss << it->first << ": " << it->second << __SRS_HTTP_CRLF;
216 } 216 }
217 } 217 }
218 218
@@ -711,7 +711,7 @@ int SrsGoHttpResponseWriter::final_request() @@ -711,7 +711,7 @@ int SrsGoHttpResponseWriter::final_request()
711 // complete the chunked encoding. 711 // complete the chunked encoding.
712 if (content_length == -1) { 712 if (content_length == -1) {
713 std::stringstream ss; 713 std::stringstream ss;
714 - ss << 0 << __SRS_CRLF << __SRS_CRLF; 714 + ss << 0 << __SRS_HTTP_CRLF << __SRS_HTTP_CRLF;
715 std::string ch = ss.str(); 715 std::string ch = ss.str();
716 return skt->write((void*)ch.data(), (int)ch.length(), NULL); 716 return skt->write((void*)ch.data(), (int)ch.length(), NULL);
717 } 717 }
@@ -752,7 +752,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size) @@ -752,7 +752,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size)
752 752
753 // send in chunked encoding. 753 // send in chunked encoding.
754 std::stringstream ss; 754 std::stringstream ss;
755 - ss << hex << size << __SRS_CRLF; 755 + ss << hex << size << __SRS_HTTP_CRLF;
756 std::string ch = ss.str(); 756 std::string ch = ss.str();
757 if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) { 757 if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) {
758 return ret; 758 return ret;
@@ -760,7 +760,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size) @@ -760,7 +760,7 @@ int SrsGoHttpResponseWriter::write(char* data, int size)
760 if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) { 760 if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) {
761 return ret; 761 return ret;
762 } 762 }
763 - if ((ret = skt->write((void*)__SRS_CRLF, 2, NULL)) != ERROR_SUCCESS) { 763 + if ((ret = skt->write((void*)__SRS_HTTP_CRLF, 2, NULL)) != ERROR_SUCCESS) {
764 return ret; 764 return ret;
765 } 765 }
766 766
@@ -794,7 +794,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size) @@ -794,7 +794,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size)
794 794
795 // status_line 795 // status_line
796 ss << "HTTP/1.1 " << status << " " 796 ss << "HTTP/1.1 " << status << " "
797 - << srs_generate_status_text(status) << __SRS_CRLF; 797 + << srs_generate_http_status_text(status) << __SRS_HTTP_CRLF;
798 798
799 // detect content type 799 // detect content type
800 if (srs_go_http_body_allowd(status)) { 800 if (srs_go_http_body_allowd(status)) {
@@ -820,7 +820,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size) @@ -820,7 +820,7 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size)
820 hdr->write(ss); 820 hdr->write(ss);
821 821
822 // header_eof 822 // header_eof
823 - ss << __SRS_CRLF; 823 + ss << __SRS_HTTP_CRLF;
824 824
825 std::string buf = ss.str(); 825 std::string buf = ss.str();
826 return skt->write((void*)buf.c_str(), buf.length(), NULL); 826 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. @@ -39,6 +39,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 #include <http_parser.h> 39 #include <http_parser.h>
40 40
41 #include <srs_app_st.hpp> 41 #include <srs_app_st.hpp>
  42 +#include <srs_kernel_consts.hpp>
42 43
43 class SrsRequest; 44 class SrsRequest;
44 class SrsStSocket; 45 class SrsStSocket;
@@ -51,19 +52,19 @@ class ISrsGoHttpResponseWriter; @@ -51,19 +52,19 @@ class ISrsGoHttpResponseWriter;
51 52
52 // http specification 53 // http specification
53 // CR = <US-ASCII CR, carriage return (13)> 54 // CR = <US-ASCII CR, carriage return (13)>
54 -#define __SRS_CR SRS_CONSTS_CR // 0x0D 55 +#define __SRS_HTTP_CR SRS_CONSTS_CR // 0x0D
55 // LF = <US-ASCII LF, linefeed (10)> 56 // LF = <US-ASCII LF, linefeed (10)>
56 -#define __SRS_LF SRS_CONSTS_LF // 0x0A 57 +#define __SRS_HTTP_LF SRS_CONSTS_LF // 0x0A
57 // SP = <US-ASCII SP, space (32)> 58 // SP = <US-ASCII SP, space (32)>
58 -#define __SRS_SP ' ' // 0x20 59 +#define __SRS_HTTP_SP ' ' // 0x20
59 // HT = <US-ASCII HT, horizontal-tab (9)> 60 // HT = <US-ASCII HT, horizontal-tab (9)>
60 -#define __SRS_HT '\x09' // 0x09 61 +#define __SRS_HTTP_HT '\x09' // 0x09
61 62
62 // HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all 63 // HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
63 // protocol elements except the entity-body (see appendix 19.3 for 64 // protocol elements except the entity-body (see appendix 19.3 for
64 // tolerant applications). 65 // tolerant applications).
65 -#define __SRS_CRLF "\r\n" // 0x0D0A  
66 -#define __SRS_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A 66 +#define __SRS_HTTP_CRLF "\r\n" // 0x0D0A
  67 +#define __SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
67 68
68 // @see SrsHttpMessage._http_ts_send_buffer 69 // @see SrsHttpMessage._http_ts_send_buffer
69 #define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096 70 #define __SRS_HTTP_TS_SEND_BUFFER_SIZE 4096
@@ -76,13 +76,13 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r @@ -76,13 +76,13 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r
76 // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s 76 // POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
77 std::stringstream ss; 77 std::stringstream ss;
78 ss << "POST " << uri->get_path() << " " 78 ss << "POST " << uri->get_path() << " "
79 - << "HTTP/1.1" << __SRS_CRLF  
80 - << "Host: " << uri->get_host() << __SRS_CRLF  
81 - << "Connection: Keep-Alive" << __SRS_CRLF  
82 - << "Content-Length: " << std::dec << req.length() << __SRS_CRLF  
83 - << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_CRLF  
84 - << "Content-Type: application/json" << __SRS_CRLF  
85 - << __SRS_CRLF 79 + << "HTTP/1.1" << __SRS_HTTP_CRLF
  80 + << "Host: " << uri->get_host() << __SRS_HTTP_CRLF
  81 + << "Connection: Keep-Alive" << __SRS_HTTP_CRLF
  82 + << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF
  83 + << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF
  84 + << "Content-Type: application/json" << __SRS_HTTP_CRLF
  85 + << __SRS_HTTP_CRLF
86 << req; 86 << req;
87 87
88 SrsStSocket skt(stfd); 88 SrsStSocket skt(stfd);
@@ -32,6 +32,7 @@ using namespace std; @@ -32,6 +32,7 @@ using namespace std;
32 #include <srs_app_st_socket.hpp> 32 #include <srs_app_st_socket.hpp>
33 #include <srs_kernel_log.hpp> 33 #include <srs_kernel_log.hpp>
34 #include <srs_app_utility.hpp> 34 #include <srs_app_utility.hpp>
  35 +#include <srs_core_autofree.hpp>
35 36
36 #ifdef SRS_AUTO_STREAM_CASTER 37 #ifdef SRS_AUTO_STREAM_CASTER
37 38
@@ -76,6 +77,28 @@ int SrsRtspConn::do_cycle() @@ -76,6 +77,28 @@ int SrsRtspConn::do_cycle()
76 std::string ip = srs_get_peer_ip(st_netfd_fileno(stfd)); 77 std::string ip = srs_get_peer_ip(st_netfd_fileno(stfd));
77 srs_trace("rtsp: serve %s", ip.c_str()); 78 srs_trace("rtsp: serve %s", ip.c_str());
78 79
  80 + // consume all rtsp messages.
  81 + for (;;) {
  82 + SrsRtspRequest* req = NULL;
  83 + if ((ret = rtsp->recv_message(&req)) != ERROR_SUCCESS) {
  84 + if (!srs_is_client_gracefully_close(ret)) {
  85 + srs_error("rtsp: recv request failed. ret=%d", ret);
  86 + }
  87 + return ret;
  88 + }
  89 + SrsAutoFree(SrsRtspRequest, req);
  90 + srs_info("rtsp: got rtsp request");
  91 +
  92 + if (req->is_options()) {
  93 + if ((ret = rtsp->send_message(new SrsRtspOptionsResponse(req->seq))) != ERROR_SUCCESS) {
  94 + if (!srs_is_client_gracefully_close(ret)) {
  95 + srs_error("rtsp: send response failed. ret=%d", ret);
  96 + }
  97 + return ret;
  98 + }
  99 + }
  100 + }
  101 +
79 return ret; 102 return ret;
80 } 103 }
81 104
@@ -265,43 +265,137 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -265,43 +265,137 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
265 #define SRS_CONSTS_HTTP_Continue_str "Continue" 265 #define SRS_CONSTS_HTTP_Continue_str "Continue"
266 #define SRS_CONSTS_HTTP_SwitchingProtocols_str "Switching Protocols" 266 #define SRS_CONSTS_HTTP_SwitchingProtocols_str "Switching Protocols"
267 #define SRS_CONSTS_HTTP_OK_str "OK" 267 #define SRS_CONSTS_HTTP_OK_str "OK"
268 -#define SRS_CONSTS_HTTP_Created_str "Created " 268 +#define SRS_CONSTS_HTTP_Created_str "Created"
269 #define SRS_CONSTS_HTTP_Accepted_str "Accepted" 269 #define SRS_CONSTS_HTTP_Accepted_str "Accepted"
270 -#define SRS_CONSTS_HTTP_NonAuthoritativeInformation_str "Non Authoritative Information "  
271 -#define SRS_CONSTS_HTTP_NoContent_str "No Content " 270 +#define SRS_CONSTS_HTTP_NonAuthoritativeInformation_str "Non Authoritative Information"
  271 +#define SRS_CONSTS_HTTP_NoContent_str "No Content"
272 #define SRS_CONSTS_HTTP_ResetContent_str "Reset Content" 272 #define SRS_CONSTS_HTTP_ResetContent_str "Reset Content"
273 #define SRS_CONSTS_HTTP_PartialContent_str "Partial Content" 273 #define SRS_CONSTS_HTTP_PartialContent_str "Partial Content"
274 -#define SRS_CONSTS_HTTP_MultipleChoices_str "Multiple Choices " 274 +#define SRS_CONSTS_HTTP_MultipleChoices_str "Multiple Choices"
275 #define SRS_CONSTS_HTTP_MovedPermanently_str "Moved Permanently" 275 #define SRS_CONSTS_HTTP_MovedPermanently_str "Moved Permanently"
276 #define SRS_CONSTS_HTTP_Found_str "Found" 276 #define SRS_CONSTS_HTTP_Found_str "Found"
277 #define SRS_CONSTS_HTTP_SeeOther_str "See Other" 277 #define SRS_CONSTS_HTTP_SeeOther_str "See Other"
278 -#define SRS_CONSTS_HTTP_NotModified_str "Not Modified " 278 +#define SRS_CONSTS_HTTP_NotModified_str "Not Modified"
279 #define SRS_CONSTS_HTTP_UseProxy_str "Use Proxy" 279 #define SRS_CONSTS_HTTP_UseProxy_str "Use Proxy"
280 -#define SRS_CONSTS_HTTP_TemporaryRedirect_str "Temporary Redirect " 280 +#define SRS_CONSTS_HTTP_TemporaryRedirect_str "Temporary Redirect"
281 #define SRS_CONSTS_HTTP_BadRequest_str "Bad Request" 281 #define SRS_CONSTS_HTTP_BadRequest_str "Bad Request"
282 #define SRS_CONSTS_HTTP_Unauthorized_str "Unauthorized" 282 #define SRS_CONSTS_HTTP_Unauthorized_str "Unauthorized"
283 -#define SRS_CONSTS_HTTP_PaymentRequired_str "Payment Required "  
284 -#define SRS_CONSTS_HTTP_Forbidden_str "Forbidden " 283 +#define SRS_CONSTS_HTTP_PaymentRequired_str "Payment Required"
  284 +#define SRS_CONSTS_HTTP_Forbidden_str "Forbidden"
285 #define SRS_CONSTS_HTTP_NotFound_str "Not Found" 285 #define SRS_CONSTS_HTTP_NotFound_str "Not Found"
286 #define SRS_CONSTS_HTTP_MethodNotAllowed_str "Method Not Allowed" 286 #define SRS_CONSTS_HTTP_MethodNotAllowed_str "Method Not Allowed"
287 -#define SRS_CONSTS_HTTP_NotAcceptable_str "Not Acceptable "  
288 -#define SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str "Proxy Authentication Required " 287 +#define SRS_CONSTS_HTTP_NotAcceptable_str "Not Acceptable"
  288 +#define SRS_CONSTS_HTTP_ProxyAuthenticationRequired_str "Proxy Authentication Required"
289 #define SRS_CONSTS_HTTP_RequestTimeout_str "Request Timeout" 289 #define SRS_CONSTS_HTTP_RequestTimeout_str "Request Timeout"
290 #define SRS_CONSTS_HTTP_Conflict_str "Conflict" 290 #define SRS_CONSTS_HTTP_Conflict_str "Conflict"
291 #define SRS_CONSTS_HTTP_Gone_str "Gone" 291 #define SRS_CONSTS_HTTP_Gone_str "Gone"
292 #define SRS_CONSTS_HTTP_LengthRequired_str "Length Required" 292 #define SRS_CONSTS_HTTP_LengthRequired_str "Length Required"
293 #define SRS_CONSTS_HTTP_PreconditionFailed_str "Precondition Failed" 293 #define SRS_CONSTS_HTTP_PreconditionFailed_str "Precondition Failed"
294 -#define SRS_CONSTS_HTTP_RequestEntityTooLarge_str "Request Entity Too Large " 294 +#define SRS_CONSTS_HTTP_RequestEntityTooLarge_str "Request Entity Too Large"
295 #define SRS_CONSTS_HTTP_RequestURITooLarge_str "Request URI Too Large" 295 #define SRS_CONSTS_HTTP_RequestURITooLarge_str "Request URI Too Large"
296 #define SRS_CONSTS_HTTP_UnsupportedMediaType_str "Unsupported Media Type" 296 #define SRS_CONSTS_HTTP_UnsupportedMediaType_str "Unsupported Media Type"
297 #define SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str "Requested Range Not Satisfiable" 297 #define SRS_CONSTS_HTTP_RequestedRangeNotSatisfiable_str "Requested Range Not Satisfiable"
298 -#define SRS_CONSTS_HTTP_ExpectationFailed_str "Expectation Failed "  
299 -#define SRS_CONSTS_HTTP_InternalServerError_str "Internal Server Error " 298 +#define SRS_CONSTS_HTTP_ExpectationFailed_str "Expectation Failed"
  299 +#define SRS_CONSTS_HTTP_InternalServerError_str "Internal Server Error"
300 #define SRS_CONSTS_HTTP_NotImplemented_str "Not Implemented" 300 #define SRS_CONSTS_HTTP_NotImplemented_str "Not Implemented"
301 #define SRS_CONSTS_HTTP_BadGateway_str "Bad Gateway" 301 #define SRS_CONSTS_HTTP_BadGateway_str "Bad Gateway"
302 #define SRS_CONSTS_HTTP_ServiceUnavailable_str "Service Unavailable" 302 #define SRS_CONSTS_HTTP_ServiceUnavailable_str "Service Unavailable"
303 #define SRS_CONSTS_HTTP_GatewayTimeout_str "Gateway Timeout" 303 #define SRS_CONSTS_HTTP_GatewayTimeout_str "Gateway Timeout"
304 #define SRS_CONSTS_HTTP_HTTPVersionNotSupported_str "HTTP Version Not Supported" 304 #define SRS_CONSTS_HTTP_HTTPVersionNotSupported_str "HTTP Version Not Supported"
305 305
  306 +///////////////////////////////////////////////////////////
  307 +// RTSP consts values
  308 +///////////////////////////////////////////////////////////
  309 +// 7.1.1 Status Code and Reason Phrase
  310 +#define SRS_CONSTS_RTSP_Continue 100
  311 +#define SRS_CONSTS_RTSP_OK 200
  312 +#define SRS_CONSTS_RTSP_Created 201
  313 +#define SRS_CONSTS_RTSP_LowOnStorageSpace 250
  314 +#define SRS_CONSTS_RTSP_MultipleChoices 300
  315 +#define SRS_CONSTS_RTSP_MovedPermanently 301
  316 +#define SRS_CONSTS_RTSP_MovedTemporarily 302
  317 +#define SRS_CONSTS_RTSP_SeeOther 303
  318 +#define SRS_CONSTS_RTSP_NotModified 304
  319 +#define SRS_CONSTS_RTSP_UseProxy 305
  320 +#define SRS_CONSTS_RTSP_BadRequest 400
  321 +#define SRS_CONSTS_RTSP_Unauthorized 401
  322 +#define SRS_CONSTS_RTSP_PaymentRequired 402
  323 +#define SRS_CONSTS_RTSP_Forbidden 403
  324 +#define SRS_CONSTS_RTSP_NotFound 404
  325 +#define SRS_CONSTS_RTSP_MethodNotAllowed 405
  326 +#define SRS_CONSTS_RTSP_NotAcceptable 406
  327 +#define SRS_CONSTS_RTSP_ProxyAuthenticationRequired 407
  328 +#define SRS_CONSTS_RTSP_RequestTimeout 408
  329 +#define SRS_CONSTS_RTSP_Gone 410
  330 +#define SRS_CONSTS_RTSP_LengthRequired 411
  331 +#define SRS_CONSTS_RTSP_PreconditionFailed 412
  332 +#define SRS_CONSTS_RTSP_RequestEntityTooLarge 413
  333 +#define SRS_CONSTS_RTSP_RequestURITooLarge 414
  334 +#define SRS_CONSTS_RTSP_UnsupportedMediaType 415
  335 +#define SRS_CONSTS_RTSP_ParameterNotUnderstood 451
  336 +#define SRS_CONSTS_RTSP_ConferenceNotFound 452
  337 +#define SRS_CONSTS_RTSP_NotEnoughBandwidth 453
  338 +#define SRS_CONSTS_RTSP_SessionNotFound 454
  339 +#define SRS_CONSTS_RTSP_MethodNotValidInThisState 455
  340 +#define SRS_CONSTS_RTSP_HeaderFieldNotValidForResource 456
  341 +#define SRS_CONSTS_RTSP_InvalidRange 457
  342 +#define SRS_CONSTS_RTSP_ParameterIsReadOnly 458
  343 +#define SRS_CONSTS_RTSP_AggregateOperationNotAllowed 459
  344 +#define SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed 460
  345 +#define SRS_CONSTS_RTSP_UnsupportedTransport 461
  346 +#define SRS_CONSTS_RTSP_DestinationUnreachable 462
  347 +#define SRS_CONSTS_RTSP_InternalServerError 500
  348 +#define SRS_CONSTS_RTSP_NotImplemented 501
  349 +#define SRS_CONSTS_RTSP_BadGateway 502
  350 +#define SRS_CONSTS_RTSP_ServiceUnavailable 503
  351 +#define SRS_CONSTS_RTSP_GatewayTimeout 504
  352 +#define SRS_CONSTS_RTSP_RTSPVersionNotSupported 505
  353 +#define SRS_CONSTS_RTSP_OptionNotSupported 551
  354 +
  355 +#define SRS_CONSTS_RTSP_Continue_str "Continue"
  356 +#define SRS_CONSTS_RTSP_OK_str "OK"
  357 +#define SRS_CONSTS_RTSP_Created_str "Created"
  358 +#define SRS_CONSTS_RTSP_LowOnStorageSpace_str "Low on Storage Space"
  359 +#define SRS_CONSTS_RTSP_MultipleChoices_str "Multiple Choices"
  360 +#define SRS_CONSTS_RTSP_MovedPermanently_str "Moved Permanently"
  361 +#define SRS_CONSTS_RTSP_MovedTemporarily_str "Moved Temporarily"
  362 +#define SRS_CONSTS_RTSP_SeeOther_str "See Other"
  363 +#define SRS_CONSTS_RTSP_NotModified_str "Not Modified"
  364 +#define SRS_CONSTS_RTSP_UseProxy_str "Use Proxy"
  365 +#define SRS_CONSTS_RTSP_BadRequest_str "Bad Request"
  366 +#define SRS_CONSTS_RTSP_Unauthorized_str "Unauthorized"
  367 +#define SRS_CONSTS_RTSP_PaymentRequired_str "Payment Required"
  368 +#define SRS_CONSTS_RTSP_Forbidden_str "Forbidden"
  369 +#define SRS_CONSTS_RTSP_NotFound_str "Not Found"
  370 +#define SRS_CONSTS_RTSP_MethodNotAllowed_str "Method Not Allowed"
  371 +#define SRS_CONSTS_RTSP_NotAcceptable_str "Not Acceptable"
  372 +#define SRS_CONSTS_RTSP_ProxyAuthenticationRequired_str "Proxy Authentication Required"
  373 +#define SRS_CONSTS_RTSP_RequestTimeout_str "Request Timeout"
  374 +#define SRS_CONSTS_RTSP_Gone_str "Gone"
  375 +#define SRS_CONSTS_RTSP_LengthRequired_str "Length Required"
  376 +#define SRS_CONSTS_RTSP_PreconditionFailed_str "Precondition Failed"
  377 +#define SRS_CONSTS_RTSP_RequestEntityTooLarge_str "Request Entity Too Large"
  378 +#define SRS_CONSTS_RTSP_RequestURITooLarge_str "Request URI Too Large"
  379 +#define SRS_CONSTS_RTSP_UnsupportedMediaType_str "Unsupported Media Type"
  380 +#define SRS_CONSTS_RTSP_ParameterNotUnderstood_str "Invalid parameter"
  381 +#define SRS_CONSTS_RTSP_ConferenceNotFound_str "Illegal Conference Identifier"
  382 +#define SRS_CONSTS_RTSP_NotEnoughBandwidth_str "Not Enough Bandwidth"
  383 +#define SRS_CONSTS_RTSP_SessionNotFound_str "Session Not Found"
  384 +#define SRS_CONSTS_RTSP_MethodNotValidInThisState_str "Method Not Valid In This State"
  385 +#define SRS_CONSTS_RTSP_HeaderFieldNotValidForResource_str "Header Field Not Valid"
  386 +#define SRS_CONSTS_RTSP_InvalidRange_str "Invalid Range"
  387 +#define SRS_CONSTS_RTSP_ParameterIsReadOnly_str "Parameter Is Read-Only"
  388 +#define SRS_CONSTS_RTSP_AggregateOperationNotAllowed_str "Aggregate Operation Not Allowed"
  389 +#define SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed_str "Only Aggregate Operation Allowed"
  390 +#define SRS_CONSTS_RTSP_UnsupportedTransport_str "Unsupported Transport"
  391 +#define SRS_CONSTS_RTSP_DestinationUnreachable_str "Destination Unreachable"
  392 +#define SRS_CONSTS_RTSP_InternalServerError_str "Internal Server Error"
  393 +#define SRS_CONSTS_RTSP_NotImplemented_str "Not Implemented"
  394 +#define SRS_CONSTS_RTSP_BadGateway_str "Bad Gateway"
  395 +#define SRS_CONSTS_RTSP_ServiceUnavailable_str "Service Unavailable"
  396 +#define SRS_CONSTS_RTSP_GatewayTimeout_str "Gateway Timeout"
  397 +#define SRS_CONSTS_RTSP_RTSPVersionNotSupported_str "RTSP Version Not Supported"
  398 +#define SRS_CONSTS_RTSP_OptionNotSupported_str "Option not support"
  399 +
306 #endif 400 #endif
307 401
@@ -142,6 +142,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -142,6 +142,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
142 #define ERROR_OpenSslComputeSharedKey 2039 142 #define ERROR_OpenSslComputeSharedKey 2039
143 #define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED 2040 143 #define ERROR_RTMP_MIC_CHUNKSIZE_CHANGED 2040
144 #define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041 144 #define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041
  145 +#define ERROR_RTSP_TOKEN_NOT_NORMAL 2042
  146 +#define ERROR_RTSP_REQUEST_HEADER_EOF 2043
145 // 147 //
146 // system control message, 148 // system control message,
147 // not an error, but special control logic. 149 // not an error, but special control logic.
@@ -23,17 +23,465 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,17 +23,465 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_rtsp_stack.hpp> 24 #include <srs_rtsp_stack.hpp>
25 25
  26 +#include <stdlib.h>
  27 +#include <map>
  28 +using namespace std;
  29 +
26 #include <srs_rtmp_io.hpp> 30 #include <srs_rtmp_io.hpp>
  31 +#include <srs_kernel_buffer.hpp>
  32 +#include <srs_kernel_error.hpp>
  33 +#include <srs_kernel_log.hpp>
  34 +#include <srs_kernel_consts.hpp>
27 35
28 #ifdef SRS_AUTO_STREAM_CASTER 36 #ifdef SRS_AUTO_STREAM_CASTER
29 37
  38 +#define __SRS_RTSP_BUFFER 4096
  39 +
  40 +// get the status text of code.
  41 +string srs_generate_rtsp_status_text(int status)
  42 +{
  43 + static std::map<int, std::string> _status_map;
  44 + if (_status_map.empty()) {
  45 + _status_map[SRS_CONSTS_RTSP_Continue ] = SRS_CONSTS_RTSP_Continue_str ;
  46 + _status_map[SRS_CONSTS_RTSP_OK ] = SRS_CONSTS_RTSP_OK_str ;
  47 + _status_map[SRS_CONSTS_RTSP_Created ] = SRS_CONSTS_RTSP_Created_str ;
  48 + _status_map[SRS_CONSTS_RTSP_LowOnStorageSpace ] = SRS_CONSTS_RTSP_LowOnStorageSpace_str ;
  49 + _status_map[SRS_CONSTS_RTSP_MultipleChoices ] = SRS_CONSTS_RTSP_MultipleChoices_str ;
  50 + _status_map[SRS_CONSTS_RTSP_MovedPermanently ] = SRS_CONSTS_RTSP_MovedPermanently_str ;
  51 + _status_map[SRS_CONSTS_RTSP_MovedTemporarily ] = SRS_CONSTS_RTSP_MovedTemporarily_str ;
  52 + _status_map[SRS_CONSTS_RTSP_SeeOther ] = SRS_CONSTS_RTSP_SeeOther_str ;
  53 + _status_map[SRS_CONSTS_RTSP_NotModified ] = SRS_CONSTS_RTSP_NotModified_str ;
  54 + _status_map[SRS_CONSTS_RTSP_UseProxy ] = SRS_CONSTS_RTSP_UseProxy_str ;
  55 + _status_map[SRS_CONSTS_RTSP_BadRequest ] = SRS_CONSTS_RTSP_BadRequest_str ;
  56 + _status_map[SRS_CONSTS_RTSP_Unauthorized ] = SRS_CONSTS_RTSP_Unauthorized_str ;
  57 + _status_map[SRS_CONSTS_RTSP_PaymentRequired ] = SRS_CONSTS_RTSP_PaymentRequired_str ;
  58 + _status_map[SRS_CONSTS_RTSP_Forbidden ] = SRS_CONSTS_RTSP_Forbidden_str ;
  59 + _status_map[SRS_CONSTS_RTSP_NotFound ] = SRS_CONSTS_RTSP_NotFound_str ;
  60 + _status_map[SRS_CONSTS_RTSP_MethodNotAllowed ] = SRS_CONSTS_RTSP_MethodNotAllowed_str ;
  61 + _status_map[SRS_CONSTS_RTSP_NotAcceptable ] = SRS_CONSTS_RTSP_NotAcceptable_str ;
  62 + _status_map[SRS_CONSTS_RTSP_ProxyAuthenticationRequired ] = SRS_CONSTS_RTSP_ProxyAuthenticationRequired_str ;
  63 + _status_map[SRS_CONSTS_RTSP_RequestTimeout ] = SRS_CONSTS_RTSP_RequestTimeout_str ;
  64 + _status_map[SRS_CONSTS_RTSP_Gone ] = SRS_CONSTS_RTSP_Gone_str ;
  65 + _status_map[SRS_CONSTS_RTSP_LengthRequired ] = SRS_CONSTS_RTSP_LengthRequired_str ;
  66 + _status_map[SRS_CONSTS_RTSP_PreconditionFailed ] = SRS_CONSTS_RTSP_PreconditionFailed_str ;
  67 + _status_map[SRS_CONSTS_RTSP_RequestEntityTooLarge ] = SRS_CONSTS_RTSP_RequestEntityTooLarge_str ;
  68 + _status_map[SRS_CONSTS_RTSP_RequestURITooLarge ] = SRS_CONSTS_RTSP_RequestURITooLarge_str ;
  69 + _status_map[SRS_CONSTS_RTSP_UnsupportedMediaType ] = SRS_CONSTS_RTSP_UnsupportedMediaType_str ;
  70 + _status_map[SRS_CONSTS_RTSP_ParameterNotUnderstood ] = SRS_CONSTS_RTSP_ParameterNotUnderstood_str ;
  71 + _status_map[SRS_CONSTS_RTSP_ConferenceNotFound ] = SRS_CONSTS_RTSP_ConferenceNotFound_str ;
  72 + _status_map[SRS_CONSTS_RTSP_NotEnoughBandwidth ] = SRS_CONSTS_RTSP_NotEnoughBandwidth_str ;
  73 + _status_map[SRS_CONSTS_RTSP_SessionNotFound ] = SRS_CONSTS_RTSP_SessionNotFound_str ;
  74 + _status_map[SRS_CONSTS_RTSP_MethodNotValidInThisState ] = SRS_CONSTS_RTSP_MethodNotValidInThisState_str ;
  75 + _status_map[SRS_CONSTS_RTSP_HeaderFieldNotValidForResource ] = SRS_CONSTS_RTSP_HeaderFieldNotValidForResource_str ;
  76 + _status_map[SRS_CONSTS_RTSP_InvalidRange ] = SRS_CONSTS_RTSP_InvalidRange_str ;
  77 + _status_map[SRS_CONSTS_RTSP_ParameterIsReadOnly ] = SRS_CONSTS_RTSP_ParameterIsReadOnly_str ;
  78 + _status_map[SRS_CONSTS_RTSP_AggregateOperationNotAllowed ] = SRS_CONSTS_RTSP_AggregateOperationNotAllowed_str ;
  79 + _status_map[SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed ] = SRS_CONSTS_RTSP_OnlyAggregateOperationAllowed_str ;
  80 + _status_map[SRS_CONSTS_RTSP_UnsupportedTransport ] = SRS_CONSTS_RTSP_UnsupportedTransport_str ;
  81 + _status_map[SRS_CONSTS_RTSP_DestinationUnreachable ] = SRS_CONSTS_RTSP_DestinationUnreachable_str ;
  82 + _status_map[SRS_CONSTS_RTSP_InternalServerError ] = SRS_CONSTS_RTSP_InternalServerError_str ;
  83 + _status_map[SRS_CONSTS_RTSP_NotImplemented ] = SRS_CONSTS_RTSP_NotImplemented_str ;
  84 + _status_map[SRS_CONSTS_RTSP_BadGateway ] = SRS_CONSTS_RTSP_BadGateway_str ;
  85 + _status_map[SRS_CONSTS_RTSP_ServiceUnavailable ] = SRS_CONSTS_RTSP_ServiceUnavailable_str ;
  86 + _status_map[SRS_CONSTS_RTSP_GatewayTimeout ] = SRS_CONSTS_RTSP_GatewayTimeout_str ;
  87 + _status_map[SRS_CONSTS_RTSP_RTSPVersionNotSupported ] = SRS_CONSTS_RTSP_RTSPVersionNotSupported_str ;
  88 + _status_map[SRS_CONSTS_RTSP_OptionNotSupported ] = SRS_CONSTS_RTSP_OptionNotSupported_str ;
  89 + }
  90 +
  91 + std::string status_text;
  92 + if (_status_map.find(status) == _status_map.end()) {
  93 + status_text = "Status Unknown";
  94 + } else {
  95 + status_text = _status_map[status];
  96 + }
  97 +
  98 + return status_text;
  99 +}
  100 +
  101 +std::string srs_generate_rtsp_method_str(SrsRtspMethod method)
  102 +{
  103 + switch (method) {
  104 + case SrsRtspMethodDescribe: return __SRS_METHOD_DESCRIBE;
  105 + case SrsRtspMethodAnnounce: return __SRS_METHOD_ANNOUNCE;
  106 + case SrsRtspMethodGetParameter: return __SRS_METHOD_GET_PARAMETER;
  107 + case SrsRtspMethodOptions: return __SRS_METHOD_OPTIONS;
  108 + case SrsRtspMethodPause: return __SRS_METHOD_PAUSE;
  109 + case SrsRtspMethodPlay: return __SRS_METHOD_PLAY;
  110 + case SrsRtspMethodRecord: return __SRS_METHOD_RECORD;
  111 + case SrsRtspMethodRedirect: return __SRS_METHOD_REDIRECT;
  112 + case SrsRtspMethodSetup: return __SRS_METHOD_SETUP;
  113 + case SrsRtspMethodSetParameter: return __SRS_METHOD_SET_PARAMETER;
  114 + case SrsRtspMethodTeardown: return __SRS_METHOD_TEARDOWN;
  115 + default: return "Unknown";
  116 + }
  117 +}
  118 +
  119 +SrsRtspRequest::SrsRtspRequest()
  120 +{
  121 + seq = 0;
  122 +}
  123 +
  124 +SrsRtspRequest::~SrsRtspRequest()
  125 +{
  126 +}
  127 +
  128 +bool SrsRtspRequest::is_options()
  129 +{
  130 + return method == __SRS_METHOD_OPTIONS;
  131 +}
  132 +
  133 +SrsRtspResponse::SrsRtspResponse(int cseq)
  134 +{
  135 + seq = cseq;
  136 + status = SRS_CONSTS_RTSP_OK;
  137 +}
  138 +
  139 +SrsRtspResponse::~SrsRtspResponse()
  140 +{
  141 +}
  142 +
  143 +stringstream& SrsRtspResponse::encode(stringstream& ss)
  144 +{
  145 + // status line
  146 + ss << __SRS_VERSION << __SRS_RTSP_SP
  147 + << status << __SRS_RTSP_SP
  148 + << srs_generate_rtsp_status_text(status) << __SRS_RTSP_CRLF;
  149 +
  150 + // cseq
  151 + ss << __SRS_TOKEN_CSEQ << ":" << __SRS_RTSP_SP << seq << __SRS_RTSP_CRLF;
  152 +
  153 + // others.
  154 + ss << "Cache-Control: no-store" << __SRS_RTSP_CRLF
  155 + << "Pragma: no-cache" << __SRS_RTSP_CRLF
  156 + << "Server: " << RTMP_SIG_SRS_SERVER << __SRS_RTSP_CRLF;
  157 +
  158 + return ss;
  159 +}
  160 +
  161 +SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq)
  162 +{
  163 + methods = (SrsRtspMethod)(SrsRtspMethodDescribe | SrsRtspMethodOptions
  164 + | SrsRtspMethodPause | SrsRtspMethodPlay | SrsRtspMethodSetup | SrsRtspMethodTeardown
  165 + | SrsRtspMethodAnnounce | SrsRtspMethodRecord);
  166 +}
  167 +
  168 +SrsRtspOptionsResponse::~SrsRtspOptionsResponse()
  169 +{
  170 +}
  171 +
  172 +stringstream& SrsRtspOptionsResponse::encode(stringstream& ss)
  173 +{
  174 + SrsRtspResponse::encode(ss);
  175 +
  176 + SrsRtspMethod __methods[] = {
  177 + SrsRtspMethodDescribe,
  178 + SrsRtspMethodAnnounce,
  179 + SrsRtspMethodGetParameter,
  180 + SrsRtspMethodOptions,
  181 + SrsRtspMethodPause,
  182 + SrsRtspMethodPlay,
  183 + SrsRtspMethodRecord,
  184 + SrsRtspMethodRedirect,
  185 + SrsRtspMethodSetup,
  186 + SrsRtspMethodSetParameter,
  187 + SrsRtspMethodTeardown,
  188 + };
  189 +
  190 + ss << __SRS_TOKEN_PUBLIC << ":" << __SRS_RTSP_SP;
  191 +
  192 + bool appended = false;
  193 + int nb_methods = (int)(sizeof(__methods) / sizeof(SrsRtspMethod));
  194 + for (int i = 0; i < nb_methods; i++) {
  195 + SrsRtspMethod method = __methods[i];
  196 + if (((int)methods & (int)method) != (int)method) {
  197 + continue;
  198 + }
  199 +
  200 + if (appended) {
  201 + ss << ", ";
  202 + }
  203 + ss << srs_generate_rtsp_method_str(method);
  204 + appended = true;
  205 + }
  206 + ss << __SRS_RTSP_CRLF;
  207 +
  208 + // eof header.
  209 + ss << __SRS_RTSP_CRLF;
  210 +
  211 + return ss;
  212 +}
  213 +
30 SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s) 214 SrsRtspStack::SrsRtspStack(ISrsProtocolReaderWriter* s)
31 { 215 {
  216 + buf = new SrsSimpleBuffer();
32 skt = s; 217 skt = s;
33 } 218 }
34 219
35 SrsRtspStack::~SrsRtspStack() 220 SrsRtspStack::~SrsRtspStack()
36 { 221 {
  222 + srs_freep(buf);
  223 +}
  224 +
  225 +int SrsRtspStack::recv_message(SrsRtspRequest** preq)
  226 +{
  227 + int ret = ERROR_SUCCESS;
  228 +
  229 + SrsRtspRequest* req = new SrsRtspRequest();
  230 + if ((ret = do_recv_message(req)) != ERROR_SUCCESS) {
  231 + srs_freep(req);
  232 + return ret;
  233 + }
  234 +
  235 + *preq = req;
  236 +
  237 + return ret;
  238 +}
  239 +
  240 +int SrsRtspStack::send_message(SrsRtspResponse* res)
  241 +{
  242 + int ret = ERROR_SUCCESS;
  243 +
  244 + std::stringstream ss;
  245 + // encode the message to string.
  246 + res->encode(ss);
  247 +
  248 + std::string str = ss.str();
  249 + srs_assert(!str.empty());
  250 +
  251 + if ((ret = skt->write((char*)str.c_str(), (int)str.length(), NULL)) != ERROR_SUCCESS) {
  252 + if (!srs_is_client_gracefully_close(ret)) {
  253 + srs_error("rtsp: send response failed. ret=%d", ret);
  254 + }
  255 + return ret;
  256 + }
  257 + srs_info("rtsp: send response ok");
  258 +
  259 + return ret;
  260 +}
  261 +
  262 +int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
  263 +{
  264 + int ret = ERROR_SUCCESS;
  265 +
  266 + // parse request line.
  267 + if ((ret = recv_token_normal(req->method)) != ERROR_SUCCESS) {
  268 + if (!srs_is_client_gracefully_close(ret)) {
  269 + srs_error("rtsp: parse method failed. ret=%d", ret);
  270 + }
  271 + return ret;
  272 + }
  273 +
  274 + if ((ret = recv_token_normal(req->uri)) != ERROR_SUCCESS) {
  275 + if (!srs_is_client_gracefully_close(ret)) {
  276 + srs_error("rtsp: parse uri failed. ret=%d", ret);
  277 + }
  278 + return ret;
  279 + }
  280 +
  281 + if ((ret = recv_token_eof(req->version)) != ERROR_SUCCESS) {
  282 + if (!srs_is_client_gracefully_close(ret)) {
  283 + srs_error("rtsp: parse version failed. ret=%d", ret);
  284 + }
  285 + return ret;
  286 + }
  287 +
  288 + // parse headers.
  289 + for (;;) {
  290 + // parse the header name
  291 + std::string token;
  292 + if ((ret = recv_token_normal(token)) != ERROR_SUCCESS) {
  293 + if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
  294 + ret = ERROR_SUCCESS;
  295 + srs_info("rtsp: message header parsed");
  296 + break;
  297 + }
  298 + if (!srs_is_client_gracefully_close(ret)) {
  299 + srs_error("rtsp: parse token failed. ret=%d", ret);
  300 + }
  301 + return ret;
  302 + }
  303 +
  304 + // parse the header value according by header name
  305 + if (token == __SRS_TOKEN_CSEQ) {
  306 + std::string seq;
  307 + if ((ret = recv_token_eof(seq)) != ERROR_SUCCESS) {
  308 + if (!srs_is_client_gracefully_close(ret)) {
  309 + srs_error("rtsp: parse seq failed. ret=%d", ret);
  310 + }
  311 + return ret;
  312 + }
  313 + req->seq = ::atoi(seq.c_str());
  314 + } else {
  315 + // unknown header name, parse util EOF.
  316 + SrsRtspTokenState state = SrsRtspTokenStateNormal;
  317 + while (state == SrsRtspTokenStateNormal) {
  318 + std::string value;
  319 + if ((ret = recv_token(value, state)) != ERROR_SUCCESS) {
  320 + if (!srs_is_client_gracefully_close(ret)) {
  321 + srs_error("rtsp: parse token failed. ret=%d", ret);
  322 + }
  323 + return ret;
  324 + }
  325 + srs_trace("rtsp: ignore header %s=%s", token.c_str(), value.c_str());
  326 + }
  327 + }
  328 + }
  329 +
  330 + // parse body.
  331 +
  332 + return ret;
  333 +}
  334 +
  335 +int SrsRtspStack::recv_token_normal(std::string& token)
  336 +{
  337 + int ret = ERROR_SUCCESS;
  338 +
  339 + SrsRtspTokenState state;
  340 +
  341 + if ((ret = recv_token(token, state)) != ERROR_SUCCESS) {
  342 + if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
  343 + return ret;
  344 + }
  345 + if (!srs_is_client_gracefully_close(ret)) {
  346 + srs_error("rtsp: parse token failed. ret=%d", ret);
  347 + }
  348 + return ret;
  349 + }
  350 +
  351 + if (state != SrsRtspTokenStateNormal) {
  352 + ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
  353 + srs_error("rtsp: parse normal token failed, state=%d. ret=%d", state, ret);
  354 + return ret;
  355 + }
  356 +
  357 + return ret;
  358 +}
  359 +
  360 +int SrsRtspStack::recv_token_eof(std::string& token)
  361 +{
  362 + int ret = ERROR_SUCCESS;
  363 +
  364 + SrsRtspTokenState state;
  365 +
  366 + if ((ret = recv_token(token, state)) != ERROR_SUCCESS) {
  367 + if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
  368 + return ret;
  369 + }
  370 + if (!srs_is_client_gracefully_close(ret)) {
  371 + srs_error("rtsp: parse token failed. ret=%d", ret);
  372 + }
  373 + return ret;
  374 + }
  375 +
  376 + if (state != SrsRtspTokenStateEOF) {
  377 + ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
  378 + srs_error("rtsp: parse eof token failed, state=%d. ret=%d", state, ret);
  379 + return ret;
  380 + }
  381 +
  382 + return ret;
  383 +}
  384 +
  385 +int SrsRtspStack::recv_token_util_eof(std::string& token)
  386 +{
  387 + int ret = ERROR_SUCCESS;
  388 +
  389 + SrsRtspTokenState state;
  390 +
  391 + // use 0x00 as ignore the normal token flag.
  392 + if ((ret = recv_token(token, state, 0x00)) != ERROR_SUCCESS) {
  393 + if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
  394 + return ret;
  395 + }
  396 + if (!srs_is_client_gracefully_close(ret)) {
  397 + srs_error("rtsp: parse token failed. ret=%d", ret);
  398 + }
  399 + return ret;
  400 + }
  401 +
  402 + if (state != SrsRtspTokenStateEOF) {
  403 + ret = ERROR_RTSP_TOKEN_NOT_NORMAL;
  404 + srs_error("rtsp: parse eof token failed, state=%d. ret=%d", state, ret);
  405 + return ret;
  406 + }
  407 +
  408 + return ret;
  409 +}
  410 +
  411 +int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch)
  412 +{
  413 + int ret = ERROR_SUCCESS;
  414 +
  415 + // whatever, default to error state.
  416 + state = SrsRtspTokenStateError;
  417 +
  418 + // when buffer is empty, append bytes first.
  419 + bool append_bytes = buf->length() == 0;
  420 +
  421 + // parse util token.
  422 + for (;;) {
  423 + // append bytes if required.
  424 + if (append_bytes) {
  425 + append_bytes = false;
  426 +
  427 + char buffer[__SRS_RTSP_BUFFER];
  428 + ssize_t nb_read = 0;
  429 + if ((ret = skt->read(buffer, __SRS_RTSP_BUFFER, &nb_read)) != ERROR_SUCCESS) {
  430 + if (!srs_is_client_gracefully_close(ret)) {
  431 + srs_error("rtsp: io read failed. ret=%d", ret);
  432 + }
  433 + return ret;
  434 + }
  435 + srs_info("rtsp: io read %d bytes", nb_read);
  436 +
  437 + buf->append(buffer, nb_read);
  438 + }
  439 +
  440 + // parse one by one.
  441 + char* start = buf->bytes();
  442 + char* end = start + buf->length();
  443 + char* p = start;
  444 +
  445 + // find util SP/CR/LF, max 2 EOF, to finger out the EOF of message.
  446 + for (; p < end && p[0] != normal_ch && p[0] != __SRS_RTSP_CR && p[0] != __SRS_RTSP_LF; p++) {
  447 + }
  448 +
  449 + // matched.
  450 + if (p < end) {
  451 + // finger out the state.
  452 + if (p[0] == normal_ch) {
  453 + state = SrsRtspTokenStateNormal;
  454 + } else {
  455 + state = SrsRtspTokenStateEOF;
  456 + }
  457 +
  458 + // got the token.
  459 + int nb_token = p - start;
  460 + // trim last ':' character.
  461 + if (nb_token && p[-1] == ':') {
  462 + nb_token--;
  463 + }
  464 + if (nb_token) {
  465 + token.append(start, nb_token);
  466 + } else {
  467 + ret = ERROR_RTSP_REQUEST_HEADER_EOF;
  468 + }
  469 +
  470 + // ignore SP/CR/LF
  471 + for (int i = 0; i < 2 && p < end && (p[0] == normal_ch || p[0] == __SRS_RTSP_CR || p[0] == __SRS_RTSP_LF); p++, i++) {
  472 + }
  473 +
  474 + // consume the token bytes.
  475 + srs_assert(p - start);
  476 + buf->erase(p - start);
  477 + break;
  478 + }
  479 +
  480 + // append more and parse again.
  481 + append_bytes = true;
  482 + }
  483 +
  484 + return ret;
37 } 485 }
38 486
39 #endif 487 #endif
@@ -30,10 +30,213 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -30,10 +30,213 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 30
31 #include <srs_core.hpp> 31 #include <srs_core.hpp>
32 32
  33 +#include <string>
  34 +#include <sstream>
  35 +
  36 +#include <srs_kernel_consts.hpp>
  37 +
33 #ifdef SRS_AUTO_STREAM_CASTER 38 #ifdef SRS_AUTO_STREAM_CASTER
34 39
  40 +class SrsSimpleBuffer;
35 class ISrsProtocolReaderWriter; 41 class ISrsProtocolReaderWriter;
36 42
  43 +// rtsp specification
  44 +// CR = <US-ASCII CR, carriage return (13)>
  45 +#define __SRS_RTSP_CR SRS_CONSTS_CR // 0x0D
  46 +// LF = <US-ASCII LF, linefeed (10)>
  47 +#define __SRS_RTSP_LF SRS_CONSTS_LF // 0x0A
  48 +// SP = <US-ASCII SP, space (32)>
  49 +#define __SRS_RTSP_SP ' ' // 0x20
  50 +
  51 +// 4 RTSP Message
  52 +// Lines are terminated by CRLF, but
  53 +// receivers should be prepared to also interpret CR and LF by
  54 +// themselves as line terminators.
  55 +#define __SRS_RTSP_CRLF "\r\n" // 0x0D0A
  56 +#define __SRS_RTSP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
  57 +
  58 +// RTSP token
  59 +#define __SRS_TOKEN_CSEQ "CSeq"
  60 +#define __SRS_TOKEN_PUBLIC "Public"
  61 +
  62 +// RTSP methods
  63 +#define __SRS_METHOD_OPTIONS "OPTIONS"
  64 +#define __SRS_METHOD_DESCRIBE "DESCRIBE"
  65 +#define __SRS_METHOD_ANNOUNCE "ANNOUNCE"
  66 +#define __SRS_METHOD_SETUP "SETUP"
  67 +#define __SRS_METHOD_PLAY "PLAY"
  68 +#define __SRS_METHOD_PAUSE "PAUSE"
  69 +#define __SRS_METHOD_TEARDOWN "TEARDOWN"
  70 +#define __SRS_METHOD_GET_PARAMETER "GET_PARAMETER"
  71 +#define __SRS_METHOD_SET_PARAMETER "SET_PARAMETER"
  72 +#define __SRS_METHOD_REDIRECT "REDIRECT"
  73 +#define __SRS_METHOD_RECORD "RECORD"
  74 +// Embedded (Interleaved) Binary Data
  75 +
  76 +// RTSP-Version
  77 +#define __SRS_VERSION "RTSP/1.0"
  78 +
  79 +/**
  80 +* the rtsp request message.
  81 +* 6 Request
  82 +* A request message from a client to a server or vice versa includes,
  83 +* within the first line of that message, the method to be applied to
  84 +* the resource, the identifier of the resource, and the protocol
  85 +* version in use.
  86 +* Request = Request-Line ; Section 6.1
  87 +* *( general-header ; Section 5
  88 +* | request-header ; Section 6.2
  89 +* | entity-header ) ; Section 8.1
  90 +* CRLF
  91 +* [ message-body ] ; Section 4.3
  92 +*/
  93 +class SrsRtspRequest
  94 +{
  95 +public:
  96 + /**
  97 + * 6.1 Request Line
  98 + * Request-Line = Method SP Request-URI SP RTSP-Version CRLF
  99 + */
  100 + std::string method;
  101 + std::string uri;
  102 + std::string version;
  103 + /**
  104 + * 12.17 CSeq
  105 + * The CSeq field specifies the sequence number for an RTSP requestresponse
  106 + * pair. This field MUST be present in all requests and
  107 + * responses. For every RTSP request containing the given sequence
  108 + * number, there will be a corresponding response having the same
  109 + * number. Any retransmitted request must contain the same sequence
  110 + * number as the original (i.e. the sequence number is not incremented
  111 + * for retransmissions of the same request).
  112 + */
  113 + int seq;
  114 +public:
  115 + SrsRtspRequest();
  116 + virtual ~SrsRtspRequest();
  117 +public:
  118 + virtual bool is_options();
  119 +};
  120 +
  121 +/**
  122 +* the rtsp response message.
  123 +* 7 Response
  124 +* [H6] applies except that HTTP-Version is replaced by RTSP-Version.
  125 +* Also, RTSP defines additional status codes and does not define some
  126 +* HTTP codes. The valid response codes and the methods they can be used
  127 +* with are defined in Table 1.
  128 +* After receiving and interpreting a request message, the recipient
  129 +* responds with an RTSP response message.
  130 +* Response = Status-Line ; Section 7.1
  131 +* *( general-header ; Section 5
  132 +* | response-header ; Section 7.1.2
  133 +* | entity-header ) ; Section 8.1
  134 +* CRLF
  135 +* [ message-body ] ; Section 4.3
  136 +*/
  137 +class SrsRtspResponse
  138 +{
  139 +public:
  140 + /**
  141 + * 7.1 Status-Line
  142 + * The first line of a Response message is the Status-Line, consisting
  143 + * of the protocol version followed by a numeric status code, and the
  144 + * textual phrase associated with the status code, with each element
  145 + * separated by SP characters. No CR or LF is allowed except in the
  146 + * final CRLF sequence.
  147 + * Status-Line = RTSP-Version SP Status-Code SP Reason-Phrase CRLF
  148 + */
  149 + // @see about the version of rtsp, see __SRS_VERSION
  150 + // @see about the status of rtsp, see SRS_CONSTS_RTSP_OK
  151 + int status;
  152 + /**
  153 + * 12.17 CSeq
  154 + * The CSeq field specifies the sequence number for an RTSP requestresponse
  155 + * pair. This field MUST be present in all requests and
  156 + * responses. For every RTSP request containing the given sequence
  157 + * number, there will be a corresponding response having the same
  158 + * number. Any retransmitted request must contain the same sequence
  159 + * number as the original (i.e. the sequence number is not incremented
  160 + * for retransmissions of the same request).
  161 + */
  162 + int seq;
  163 +public:
  164 + SrsRtspResponse(int cseq);
  165 + virtual ~SrsRtspResponse();
  166 +public:
  167 + /**
  168 + * encode message to string.
  169 + */
  170 + virtual std::stringstream& encode(std::stringstream& ss);
  171 +};
  172 +
  173 +/**
  174 +* 10 Method Definitions
  175 +* The method token indicates the method to be performed on the resource
  176 +* identified by the Request-URI. The method is case-sensitive. New
  177 +* methods may be defined in the future. Method names may not start with
  178 +* a $ character (decimal 24) and must be a token. Methods are
  179 +* summarized in Table 2.
  180 +* Notes on Table 2: PAUSE is recommended, but not required in that a
  181 +* fully functional server can be built that does not support this
  182 +* method, for example, for live feeds. If a server does not support a
  183 +* particular method, it MUST return "501 Not Implemented" and a client
  184 +* SHOULD not try this method again for this server.
  185 +*/
  186 +enum SrsRtspMethod
  187 +{
  188 + SrsRtspMethodDescribe = 0x0001,
  189 + SrsRtspMethodAnnounce = 0x0002,
  190 + SrsRtspMethodGetParameter = 0x0004,
  191 + SrsRtspMethodOptions = 0x0008,
  192 + SrsRtspMethodPause = 0x0010,
  193 + SrsRtspMethodPlay = 0x0020,
  194 + SrsRtspMethodRecord = 0x0040,
  195 + SrsRtspMethodRedirect = 0x0080,
  196 + SrsRtspMethodSetup = 0x0100,
  197 + SrsRtspMethodSetParameter = 0x0200,
  198 + SrsRtspMethodTeardown = 0x0400,
  199 +};
  200 +
  201 +/**
  202 +* 10.1 OPTIONS
  203 +* The behavior is equivalent to that described in [H9.2]. An OPTIONS
  204 +* request may be issued at any time, e.g., if the client is about to
  205 +* try a nonstandard request. It does not influence server state.
  206 +*/
  207 +class SrsRtspOptionsResponse : public SrsRtspResponse
  208 +{
  209 +public:
  210 + /**
  211 + * join of SrsRtspMethod
  212 + */
  213 + SrsRtspMethod methods;
  214 +public:
  215 + SrsRtspOptionsResponse(int cseq);
  216 + virtual ~SrsRtspOptionsResponse();
  217 +public:
  218 + virtual std::stringstream& encode(std::stringstream& ss);
  219 +};
  220 +
  221 +/**
  222 +* the state of rtsp token.
  223 +*/
  224 +enum SrsRtspTokenState
  225 +{
  226 + /**
  227 + * parse token failed, default state.
  228 + */
  229 + SrsRtspTokenStateError = 100,
  230 + /**
  231 + * when SP follow the token.
  232 + */
  233 + SrsRtspTokenStateNormal = 101,
  234 + /**
  235 + * when CRLF follow the token.
  236 + */
  237 + SrsRtspTokenStateEOF = 102,
  238 +};
  239 +
37 /** 240 /**
38 * the rtsp protocol stack to parse the rtsp packets. 241 * the rtsp protocol stack to parse the rtsp packets.
39 */ 242 */
@@ -41,12 +244,57 @@ class SrsRtspStack @@ -41,12 +244,57 @@ class SrsRtspStack
41 { 244 {
42 private: 245 private:
43 /** 246 /**
  247 + * cached bytes buffer.
  248 + */
  249 + SrsSimpleBuffer* buf;
  250 + /**
44 * underlayer socket object, send/recv bytes. 251 * underlayer socket object, send/recv bytes.
45 */ 252 */
46 ISrsProtocolReaderWriter* skt; 253 ISrsProtocolReaderWriter* skt;
47 public: 254 public:
48 SrsRtspStack(ISrsProtocolReaderWriter* s); 255 SrsRtspStack(ISrsProtocolReaderWriter* s);
49 virtual ~SrsRtspStack(); 256 virtual ~SrsRtspStack();
  257 +public:
  258 + /**
  259 + * recv rtsp message from underlayer io.
  260 + * @param preq the output rtsp request message, which user must free it.
  261 + * @return an int error code.
  262 + * ERROR_RTSP_REQUEST_HEADER_EOF indicates request header EOF.
  263 + */
  264 + virtual int recv_message(SrsRtspRequest** preq);
  265 + /**
  266 + * send rtsp message over underlayer io.
  267 + * @param res the rtsp response message, which user should never free it.
  268 + * @return an int error code.
  269 + */
  270 + virtual int send_message(SrsRtspResponse* res);
  271 +private:
  272 + /**
  273 + * recv the rtsp message.
  274 + */
  275 + virtual int do_recv_message(SrsRtspRequest* req);
  276 + /**
  277 + * read a normal token from io, error when token state is not normal.
  278 + */
  279 + virtual int recv_token_normal(std::string& token);
  280 + /**
  281 + * read a normal token from io, error when token state is not eof.
  282 + */
  283 + virtual int recv_token_eof(std::string& token);
  284 + /**
  285 + * read the token util got eof, for example, to read the response status Reason-Phrase
  286 + */
  287 + virtual int recv_token_util_eof(std::string& token);
  288 + /**
  289 + * read a token from io, split by SP, endswith CRLF:
  290 + * token1 SP token2 SP ... tokenN CRLF
  291 + * @param normal_ch, the char to indicates the normal token.
  292 + * the SP use to indicates the normal token, @see __SRS_RTSP_SP
  293 + * the 0x00 use to ignore normal token flag. @see recv_token_util_eof
  294 + * @param token, output the read token.
  295 + * @param state, output the token parse state.
  296 + */
  297 + virtual int recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch = __SRS_RTSP_SP);
50 }; 298 };
51 299
52 #endif 300 #endif