mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
For #299, refine code.
This commit is contained in:
parent
62b7204514
commit
f32aab3d92
175 changed files with 15529 additions and 15935 deletions
|
@ -1,24 +1,24 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_http_stack.hpp>
|
||||
|
@ -247,15 +247,15 @@ int SrsHttpRedirectHandler::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessag
|
|||
}
|
||||
|
||||
string msg = "Redirect to" + location;
|
||||
|
||||
|
||||
w->header()->set_content_type("text/plain; charset=utf-8");
|
||||
w->header()->set_content_length(msg.length());
|
||||
w->header()->set("Location", location);
|
||||
w->write_header(code);
|
||||
|
||||
|
||||
w->write((char*)msg.data(), (int)msg.length());
|
||||
w->final_request();
|
||||
|
||||
|
||||
srs_info("redirect to %s.", location.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
@ -840,28 +840,28 @@ char* ISrsHttpMessage::http_ts_send_buffer()
|
|||
#endif
|
||||
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
//#include "http_parser.h"
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_HTTP_HPP
|
||||
#define SRS_PROTOCOL_HTTP_HPP
|
||||
|
||||
/*
|
||||
#include <srs_http_stack.hpp>
|
||||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
||||
// default http listen port.
|
||||
|
@ -232,10 +229,10 @@ public:
|
|||
* @param nb_read, the actual read size of bytes. NULL to ignore.
|
||||
* @remark when eof(), return error.
|
||||
* @remark for some server, the content-length not specified and not chunked,
|
||||
* which is actually the infinite chunked encoding, which after http header
|
||||
* which is actually the infinite chunked encoding, which after http header
|
||||
* is http response data, it's ok for browser. that is,
|
||||
* when user call this read, please ensure there is data to read(by content-length
|
||||
* or by chunked), because the sdk never know whether there is no data or
|
||||
* or by chunked), because the sdk never know whether there is no data or
|
||||
* infinite chunked.
|
||||
*/
|
||||
virtual int read(char* data, int nb_data, int* nb_read) = 0;
|
||||
|
@ -660,37 +657,37 @@ extern "C" {
|
|||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* webdav */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
/* subversion */ \
|
||||
XX(16, REPORT, REPORT) \
|
||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
||||
XX(18, CHECKOUT, CHECKOUT) \
|
||||
XX(19, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(20, MSEARCH, M-SEARCH) \
|
||||
XX(21, NOTIFY, NOTIFY) \
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(24, PATCH, PATCH) \
|
||||
XX(25, PURGE, PURGE) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* webdav */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
/* subversion */ \
|
||||
XX(16, REPORT, REPORT) \
|
||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
||||
XX(18, CHECKOUT, CHECKOUT) \
|
||||
XX(19, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(20, MSEARCH, M-SEARCH) \
|
||||
XX(21, NOTIFY, NOTIFY) \
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(24, PATCH, PATCH) \
|
||||
XX(25, PURGE, PURGE) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
|
@ -719,45 +716,45 @@ XX(25, PURGE, PURGE) \
|
|||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_status_complete, "the on_status_complete callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_status_complete, "the on_status_complete callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_kafka_stack.hpp>
|
||||
|
@ -850,7 +850,7 @@ int SrsKafkaBroker::encode(SrsBuffer* buf)
|
|||
return ret;
|
||||
}
|
||||
buf->write_4bytes(port);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_KAFKA_HPP
|
||||
#define SRS_PROTOCOL_KAFKA_HPP
|
||||
|
||||
/*
|
||||
#include <srs_kafka_stack.hpp>
|
||||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
@ -62,7 +59,7 @@ enum SrsKafkaApiKey
|
|||
};
|
||||
|
||||
/**
|
||||
* These types consist of a signed integer giving a length N followed by N bytes of content.
|
||||
* These types consist of a signed integer giving a length N followed by N bytes of content.
|
||||
* A length of -1 indicates null. string uses an int16 for its size, and bytes uses an int32.
|
||||
* @see https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-ProtocolPrimitiveTypes
|
||||
*/
|
||||
|
@ -117,11 +114,11 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* This is a notation for handling repeated structures. These will always be encoded as an
|
||||
* int32 size containing the length N followed by N repetitions of the structure which can
|
||||
* itself be made up of other primitive types. In the BNF grammars below we will show an
|
||||
* This is a notation for handling repeated structures. These will always be encoded as an
|
||||
* int32 size containing the length N followed by N repetitions of the structure which can
|
||||
* itself be made up of other primitive types. In the BNF grammars below we will show an
|
||||
* array of a structure foo as [foo].
|
||||
*
|
||||
*
|
||||
* Usage:
|
||||
* SrsKafkaArray<SrsKafkaBytes> body;
|
||||
* body.append(new SrsKafkaBytes());
|
||||
|
@ -260,7 +257,7 @@ public:
|
|||
{
|
||||
return elems.at(index);
|
||||
}
|
||||
// interface ISrsCodec
|
||||
// interface ISrsCodec
|
||||
public:
|
||||
virtual int nb_bytes()
|
||||
{
|
||||
|
@ -327,15 +324,15 @@ private:
|
|||
int32_t _size;
|
||||
private:
|
||||
/**
|
||||
* This is a numeric id for the API being invoked (i.e. is it
|
||||
* This is a numeric id for the API being invoked (i.e. is it
|
||||
* a metadata request, a produce request, a fetch request, etc).
|
||||
* @remark MetadataRequest | ProduceRequest | FetchRequest | OffsetRequest | OffsetCommitRequest | OffsetFetchRequest
|
||||
*/
|
||||
int16_t _api_key;
|
||||
/**
|
||||
* This is a numeric version number for this api. We version each API and
|
||||
* this version number allows the server to properly interpret the request
|
||||
* as the protocol evolves. Responses will always be in the format corresponding
|
||||
* This is a numeric version number for this api. We version each API and
|
||||
* this version number allows the server to properly interpret the request
|
||||
* as the protocol evolves. Responses will always be in the format corresponding
|
||||
* to the request version. Currently the supported version for all APIs is 0.
|
||||
*/
|
||||
int16_t api_version;
|
||||
|
@ -346,7 +343,7 @@ private:
|
|||
*/
|
||||
int32_t _correlation_id;
|
||||
/**
|
||||
* This is a user supplied identifier for the client application.
|
||||
* This is a user supplied identifier for the client application.
|
||||
* The user can use any identifier they like and it will be used
|
||||
* when logging errors, monitoring aggregates, etc. For example,
|
||||
* one might want to monitor not just the requests per second overall,
|
||||
|
@ -493,7 +490,7 @@ public:
|
|||
*/
|
||||
struct SrsKafkaRawMessage : public ISrsCodec
|
||||
{
|
||||
// metadata.
|
||||
// metadata.
|
||||
public:
|
||||
/**
|
||||
* This is the offset used in kafka as the log sequence number. When the
|
||||
|
@ -505,15 +502,15 @@ public:
|
|||
* the size of this message.
|
||||
*/
|
||||
int32_t message_size;
|
||||
// message.
|
||||
// message.
|
||||
public:
|
||||
/**
|
||||
* The CRC is the CRC32 of the remainder of the message bytes.
|
||||
* The CRC is the CRC32 of the remainder of the message bytes.
|
||||
* This is used to check the integrity of the message on the broker and consumer.
|
||||
*/
|
||||
int32_t crc;
|
||||
/**
|
||||
* This is a version id used to allow backwards compatible evolution
|
||||
* This is a version id used to allow backwards compatible evolution
|
||||
* of the message binary format. The current value is 0.
|
||||
*/
|
||||
int8_t magic_byte;
|
||||
|
@ -524,7 +521,7 @@ public:
|
|||
*/
|
||||
int8_t attributes;
|
||||
/**
|
||||
* The key is an optional message key that was used for
|
||||
* The key is an optional message key that was used for
|
||||
* partition assignment. The key can be null.
|
||||
*/
|
||||
SrsKafkaBytes* key;
|
||||
|
@ -592,7 +589,7 @@ public:
|
|||
*/
|
||||
virtual void update_header(int s);
|
||||
/**
|
||||
* get the correlation id of header for message.
|
||||
* get the correlation id of header for message.
|
||||
*/
|
||||
virtual int32_t correlation_id();
|
||||
/**
|
||||
|
@ -638,7 +635,7 @@ public:
|
|||
* What is the host and port for each of these brokers?
|
||||
* This is the only request that can be addressed to any broker in the cluster.
|
||||
*
|
||||
* Since there may be many topics the client can give an optional list of topic
|
||||
* Since there may be many topics the client can give an optional list of topic
|
||||
* names in order to only return metadata for a subset of topics.
|
||||
*
|
||||
* @see https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-MetadataAPI
|
||||
|
@ -713,9 +710,9 @@ public:
|
|||
|
||||
/**
|
||||
* response for the metadata request from broker.
|
||||
* The response contains metadata for each partition,
|
||||
* with partitions grouped together by topic. This
|
||||
* metadata refers to brokers by their broker id.
|
||||
* The response contains metadata for each partition,
|
||||
* with partitions grouped together by topic. This
|
||||
* metadata refers to brokers by their broker id.
|
||||
* The brokers each have a host and port.
|
||||
* @see https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-MetadataResponse
|
||||
*/
|
||||
|
@ -786,25 +783,25 @@ class SrsKafkaProducerRequest : public SrsKafkaRequest
|
|||
{
|
||||
public:
|
||||
/**
|
||||
* This field indicates how many acknowledgements the servers should receive
|
||||
* before responding to the request. If it is 0 the server will not send any
|
||||
* response (this is the only case where the server will not reply to a request).
|
||||
* If it is 1, the server will wait the data is written to the local log
|
||||
* before sending a response. If it is -1 the server will block until the
|
||||
* message is committed by all in sync replicas before sending a response.
|
||||
* For any number > 1 the server will block waiting for this number of
|
||||
* acknowledgements to occur (but the server will never wait for more
|
||||
* This field indicates how many acknowledgements the servers should receive
|
||||
* before responding to the request. If it is 0 the server will not send any
|
||||
* response (this is the only case where the server will not reply to a request).
|
||||
* If it is 1, the server will wait the data is written to the local log
|
||||
* before sending a response. If it is -1 the server will block until the
|
||||
* message is committed by all in sync replicas before sending a response.
|
||||
* For any number > 1 the server will block waiting for this number of
|
||||
* acknowledgements to occur (but the server will never wait for more
|
||||
* acknowledgements than there are in-sync replicas).
|
||||
*/
|
||||
int16_t required_acks;
|
||||
/**
|
||||
* This provides a maximum time in milliseconds the server can await the receipt
|
||||
* of the number of acknowledgements in RequiredAcks. The timeout is not an exact
|
||||
* limit on the request time for a few reasons: (1) it does not include network
|
||||
* latency, (2) the timer begins at the beginning of the processing of this request
|
||||
* so if many requests are queued due to server overload that wait time will not
|
||||
* be included, (3) we will not terminate a local write so if the local write
|
||||
* time exceeds this timeout it will not be respected. To get a hard timeout of
|
||||
* This provides a maximum time in milliseconds the server can await the receipt
|
||||
* of the number of acknowledgements in RequiredAcks. The timeout is not an exact
|
||||
* limit on the request time for a few reasons: (1) it does not include network
|
||||
* latency, (2) the timer begins at the beginning of the processing of this request
|
||||
* so if many requests are queued due to server overload that wait time will not
|
||||
* be included, (3) we will not terminate a local write so if the local write
|
||||
* time exceeds this timeout it will not be respected. To get a hard timeout of
|
||||
* this type the client should use the socket timeout.
|
||||
*/
|
||||
int32_t timeout;
|
||||
|
@ -824,8 +821,8 @@ public:
|
|||
|
||||
/**
|
||||
* the poll to discovery reponse.
|
||||
* @param CorrelationId This is a user-supplied integer. It will be passed back
|
||||
* in the response by the server, unmodified. It is useful for matching
|
||||
* @param CorrelationId This is a user-supplied integer. It will be passed back
|
||||
* in the response by the server, unmodified. It is useful for matching
|
||||
* request and response between the client and server.
|
||||
* @see https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-Requests
|
||||
*/
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_amf0.hpp>
|
||||
|
||||
|
@ -210,8 +210,8 @@ void srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level)
|
|||
} else if (any->is_string()) {
|
||||
ss << "String " << any->to_str() << endl;
|
||||
} else if (any->is_date()) {
|
||||
ss << "Date " << std::hex << any->to_date()
|
||||
<< "/" << std::hex << any->to_date_time_zone() << endl;
|
||||
ss << "Date " << std::hex << any->to_date()
|
||||
<< "/" << std::hex << any->to_date_time_zone() << endl;
|
||||
} else if (any->is_null()) {
|
||||
ss << "Null" << endl;
|
||||
} else if (any->is_ecma_array()) {
|
||||
|
@ -618,7 +618,7 @@ int SrsAmf0ObjectEOF::read(SrsBuffer* stream)
|
|||
if (temp != 0x00) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof value check failed. "
|
||||
"must be 0x00, actual is %#x, ret=%d", temp, ret);
|
||||
"must be 0x00, actual is %#x, ret=%d", temp, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -633,7 +633,7 @@ int SrsAmf0ObjectEOF::read(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_ObjectEnd) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check object eof marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read object eof marker success");
|
||||
|
@ -719,7 +719,7 @@ int SrsAmf0Object::read(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_Object) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check object marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read object marker success");
|
||||
|
@ -747,7 +747,7 @@ int SrsAmf0Object::read(SrsBuffer* stream)
|
|||
SrsAmf0Any* property_value = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 object read property_value failed. "
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
srs_freep(property_value);
|
||||
return ret;
|
||||
}
|
||||
|
@ -918,11 +918,11 @@ int SrsAmf0EcmaArray::read(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_EcmaArray) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check ecma_array marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_EcmaArray, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_EcmaArray, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read ecma_array marker success");
|
||||
|
||||
|
||||
// count
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
|
@ -935,7 +935,7 @@ int SrsAmf0EcmaArray::read(SrsBuffer* stream)
|
|||
|
||||
// value
|
||||
this->_count = count;
|
||||
|
||||
|
||||
while (!stream->empty()) {
|
||||
// detect whether is eof.
|
||||
if (srs_amf0_is_object_eof(stream)) {
|
||||
|
@ -958,7 +958,7 @@ int SrsAmf0EcmaArray::read(SrsBuffer* stream)
|
|||
SrsAmf0Any* property_value = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 ecma_array read property_value failed. "
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -981,7 +981,7 @@ int SrsAmf0EcmaArray::write(SrsBuffer* stream)
|
|||
|
||||
stream->write_1bytes(RTMP_AMF0_EcmaArray);
|
||||
srs_verbose("amf0 write ecma_array marker success");
|
||||
|
||||
|
||||
// count
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
|
@ -1130,11 +1130,11 @@ int SrsAmf0StrictArray::read(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_StrictArray) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check strict_array marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_StrictArray, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_StrictArray, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read strict_array marker success");
|
||||
|
||||
|
||||
// count
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
|
@ -1147,7 +1147,7 @@ int SrsAmf0StrictArray::read(SrsBuffer* stream)
|
|||
|
||||
// value
|
||||
this->_count = count;
|
||||
|
||||
|
||||
for (int i = 0; i < count && !stream->empty(); i++) {
|
||||
// property-value: any
|
||||
SrsAmf0Any* elem = NULL;
|
||||
|
@ -1175,7 +1175,7 @@ int SrsAmf0StrictArray::write(SrsBuffer* stream)
|
|||
|
||||
stream->write_1bytes(RTMP_AMF0_StrictArray);
|
||||
srs_verbose("amf0 write strict_array marker success");
|
||||
|
||||
|
||||
// count
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
|
@ -1454,14 +1454,14 @@ int SrsAmf0Date::read(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_Date) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check date marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Date, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Date, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read date marker success");
|
||||
|
||||
|
||||
// date value
|
||||
// An ActionScript Date is serialized as the number of milliseconds
|
||||
// elapsed since the epoch of midnight on 1st Jan 1970 in the UTC
|
||||
// An ActionScript Date is serialized as the number of milliseconds
|
||||
// elapsed since the epoch of midnight on 1st Jan 1970 in the UTC
|
||||
// time zone.
|
||||
if (!stream->require(8)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
|
@ -1473,9 +1473,9 @@ int SrsAmf0Date::read(SrsBuffer* stream)
|
|||
srs_verbose("amf0 read date success. date=%"PRId64, _date_value);
|
||||
|
||||
// time zone
|
||||
// While the design of this type reserves room for time zone offset
|
||||
// information, it should not be filled in, nor used, as it is unconventional
|
||||
// to change time zones when serializing dates on a network. It is suggested
|
||||
// While the design of this type reserves room for time zone offset
|
||||
// information, it should not be filled in, nor used, as it is unconventional
|
||||
// to change time zones when serializing dates on a network. It is suggested
|
||||
// that the time zone be queried independently as needed.
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
|
@ -1501,7 +1501,7 @@ int SrsAmf0Date::write(SrsBuffer* stream)
|
|||
|
||||
stream->write_1bytes(RTMP_AMF0_Date);
|
||||
srs_verbose("amf0 write date marker success");
|
||||
|
||||
|
||||
// date value
|
||||
if (!stream->require(8)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
|
@ -1511,7 +1511,7 @@ int SrsAmf0Date::write(SrsBuffer* stream)
|
|||
|
||||
stream->write_8bytes(_date_value);
|
||||
srs_verbose("amf0 write date success. date=%"PRId64, _date_value);
|
||||
|
||||
|
||||
// time zone
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
|
@ -1642,7 +1642,7 @@ int srs_amf0_read_string(SrsBuffer* stream, string& value)
|
|||
if (marker != RTMP_AMF0_String) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check string marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read string marker success");
|
||||
|
@ -1682,18 +1682,18 @@ int srs_amf0_read_boolean(SrsBuffer* stream, bool& value)
|
|||
if (marker != RTMP_AMF0_Boolean) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check bool marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read bool marker success");
|
||||
|
||||
|
||||
// value
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read bool value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
value = (stream->read_1bytes() != 0);
|
||||
|
||||
srs_verbose("amf0 read bool value success. value=%d", value);
|
||||
|
@ -1712,14 +1712,14 @@ int srs_amf0_write_boolean(SrsBuffer* stream, bool value)
|
|||
}
|
||||
stream->write_1bytes(RTMP_AMF0_Boolean);
|
||||
srs_verbose("amf0 write bool marker success");
|
||||
|
||||
|
||||
// value
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
srs_error("amf0 write bool value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (value) {
|
||||
stream->write_1bytes(0x01);
|
||||
} else {
|
||||
|
@ -1746,18 +1746,18 @@ int srs_amf0_read_number(SrsBuffer* stream, double& value)
|
|||
if (marker != RTMP_AMF0_Number) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check number marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read number marker success");
|
||||
|
||||
|
||||
// value
|
||||
if (!stream->require(8)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read number value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int64_t temp = stream->read_8bytes();
|
||||
memcpy(&value, &temp, 8);
|
||||
|
||||
|
@ -1778,14 +1778,14 @@ int srs_amf0_write_number(SrsBuffer* stream, double value)
|
|||
|
||||
stream->write_1bytes(RTMP_AMF0_Number);
|
||||
srs_verbose("amf0 write number marker success");
|
||||
|
||||
|
||||
// value
|
||||
if (!stream->require(8)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
srs_error("amf0 write number value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int64_t temp = 0x00;
|
||||
memcpy(&temp, &value, 8);
|
||||
stream->write_8bytes(temp);
|
||||
|
@ -1810,7 +1810,7 @@ int srs_amf0_read_null(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_Null) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check null marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read null success");
|
||||
|
@ -1849,7 +1849,7 @@ int srs_amf0_read_undefined(SrsBuffer* stream)
|
|||
if (marker != RTMP_AMF0_Undefined) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check undefined marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Undefined, ret);
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Undefined, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read undefined success");
|
||||
|
@ -1908,13 +1908,13 @@ namespace _srs_internal
|
|||
// UTF8-1 = %x00-7F
|
||||
// TODO: support other utf-8 strings
|
||||
/*for (int i = 0; i < len; i++) {
|
||||
char ch = *(str.data() + i);
|
||||
if ((ch & 0x80) != 0) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("ignored. only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret);
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
}*/
|
||||
char ch = *(str.data() + i);
|
||||
if ((ch & 0x80) != 0) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("ignored. only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret);
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
}*/
|
||||
|
||||
value = str;
|
||||
srs_verbose("amf0 read string data success. str=%s", str.c_str());
|
||||
|
@ -1952,7 +1952,7 @@ namespace _srs_internal
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool srs_amf0_is_object_eof(SrsBuffer* stream)
|
||||
bool srs_amf0_is_object_eof(SrsBuffer* stream)
|
||||
{
|
||||
// detect the object-eof specially
|
||||
if (stream->require(3)) {
|
||||
|
@ -1993,7 +1993,7 @@ namespace _srs_internal
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int srs_amf0_write_any(SrsBuffer* stream, SrsAmf0Any* value)
|
||||
{
|
||||
srs_assert(value != NULL);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,24 +1,24 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_format.hpp>
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_FORMAT_HPP
|
||||
#define SRS_PROTOCOL_FORMAT_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_format.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_kernel_codec.hpp>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_io.hpp>
|
||||
|
||||
|
|
|
@ -1,96 +1,92 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_IO_HPP
|
||||
#define SRS_PROTOCOL_IO_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_io.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_kernel_io.hpp>
|
||||
|
||||
/**
|
||||
* the system io reader/writer architecture:
|
||||
+---------------+ +---------------+
|
||||
| IStreamWriter | | IVectorWriter |
|
||||
+---------------+ +---------------+
|
||||
| + write() | | + writev() |
|
||||
+-------------+-+ ++--------------+
|
||||
+----------+ +--------------------+ /\ /\
|
||||
| IReader | | IStatistic | \ /
|
||||
+----------+ +--------------------+ V
|
||||
| + read() | | + get_recv_bytes() | +------+----+
|
||||
+------+---+ | + get_send_bytes() | | IWriter |
|
||||
/ \ +---+--------------+-+ +-------+---+
|
||||
| / \ / \ / \
|
||||
| | | |
|
||||
+------+-------------+------+ ++---------------------+--+
|
||||
| IProtocolReader | | IProtocolWriter |
|
||||
+---------------------------+ +-------------------------+
|
||||
| + readfully() | | + set_send_timeout() |
|
||||
| + set_recv_timeout() | +-------+-----------------+
|
||||
+------------+--------------+ / \
|
||||
/ \ |
|
||||
| |
|
||||
+--+-----------------------------+-+
|
||||
| IProtocolReaderWriter |
|
||||
+----------------------------------+
|
||||
| + is_never_timeout() |
|
||||
+----------------------------------+
|
||||
*/
|
||||
* the system io reader/writer architecture:
|
||||
* +---------------+ +---------------+
|
||||
* | IStreamWriter | | IVectorWriter |
|
||||
* +---------------+ +---------------+
|
||||
* | + write() | | + writev() |
|
||||
* +-------------+-+ ++--------------+
|
||||
* +----------+ +--------------------+ /\ /\
|
||||
* | IReader | | IStatistic | \ /
|
||||
* +----------+ +--------------------+ V
|
||||
* | + read() | | + get_recv_bytes() | +------+----+
|
||||
* +------+---+ | + get_send_bytes() | | IWriter |
|
||||
* / \ +---+--------------+-+ +-------+---+
|
||||
* | / \ / \ / \
|
||||
* | | | |
|
||||
* +------+-------------+------+ ++---------------------+--+
|
||||
* | IProtocolReader | | IProtocolWriter |
|
||||
* +---------------------------+ +-------------------------+
|
||||
* | + readfully() | | + set_send_timeout() |
|
||||
* | + set_recv_timeout() | +-------+-----------------+
|
||||
* +------------+--------------+ / \
|
||||
* / \ |
|
||||
* | |
|
||||
* +--+-----------------------------+-+
|
||||
* | IProtocolReaderWriter |
|
||||
* +----------------------------------+
|
||||
* | + is_never_timeout() |
|
||||
* +----------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
* get the statistic of channel.
|
||||
*/
|
||||
* get the statistic of channel.
|
||||
*/
|
||||
class ISrsProtocolStatistic
|
||||
{
|
||||
public:
|
||||
ISrsProtocolStatistic();
|
||||
virtual ~ISrsProtocolStatistic();
|
||||
// for protocol
|
||||
// for protocol
|
||||
public:
|
||||
/**
|
||||
* get the total recv bytes over underlay fd.
|
||||
*/
|
||||
* get the total recv bytes over underlay fd.
|
||||
*/
|
||||
virtual int64_t get_recv_bytes() = 0;
|
||||
/**
|
||||
* get the total send bytes over underlay fd.
|
||||
*/
|
||||
* get the total send bytes over underlay fd.
|
||||
*/
|
||||
virtual int64_t get_send_bytes() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* the reader for the protocol to read from whatever channel.
|
||||
*/
|
||||
* the reader for the protocol to read from whatever channel.
|
||||
*/
|
||||
class ISrsProtocolReader : public virtual ISrsReader, public virtual ISrsProtocolStatistic
|
||||
{
|
||||
public:
|
||||
ISrsProtocolReader();
|
||||
virtual ~ISrsProtocolReader();
|
||||
// for protocol
|
||||
// for protocol
|
||||
public:
|
||||
/**
|
||||
* Set the timeout tm in ms for recv bytes from peer.
|
||||
|
@ -99,26 +95,26 @@ public:
|
|||
virtual void set_recv_timeout(int64_t tm) = 0;
|
||||
/**
|
||||
* Get the timeout in ms for recv bytes from peer.
|
||||
*/
|
||||
*/
|
||||
virtual int64_t get_recv_timeout() = 0;
|
||||
// for handshake.
|
||||
// for handshake.
|
||||
public:
|
||||
/**
|
||||
* read specified size bytes of data
|
||||
* @param nread, the actually read size, NULL to ignore.
|
||||
*/
|
||||
* read specified size bytes of data
|
||||
* @param nread, the actually read size, NULL to ignore.
|
||||
*/
|
||||
virtual int read_fully(void* buf, size_t size, ssize_t* nread) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* the writer for the protocol to write to whatever channel.
|
||||
*/
|
||||
* the writer for the protocol to write to whatever channel.
|
||||
*/
|
||||
class ISrsProtocolWriter : public virtual ISrsWriter, public virtual ISrsProtocolStatistic
|
||||
{
|
||||
public:
|
||||
ISrsProtocolWriter();
|
||||
virtual ~ISrsProtocolWriter();
|
||||
// for protocol
|
||||
// for protocol
|
||||
public:
|
||||
/**
|
||||
* Set the timeout tm in ms for send bytes to peer.
|
||||
|
@ -132,14 +128,14 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* the reader and writer.
|
||||
*/
|
||||
* the reader and writer.
|
||||
*/
|
||||
class ISrsProtocolReaderWriter : public virtual ISrsProtocolReader, public virtual ISrsProtocolWriter
|
||||
{
|
||||
public:
|
||||
ISrsProtocolReaderWriter();
|
||||
virtual ~ISrsProtocolReaderWriter();
|
||||
// for protocol
|
||||
// for protocol
|
||||
public:
|
||||
/**
|
||||
* Whether the specified tm in ms is never timeout.
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_json.hpp>
|
||||
|
||||
|
@ -109,41 +109,41 @@ using namespace std;
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum nx_json_type {
|
||||
NX_JSON_NULL, // this is null value
|
||||
NX_JSON_OBJECT, // this is an object; properties can be found in child nodes
|
||||
NX_JSON_ARRAY, // this is an array; items can be found in child nodes
|
||||
NX_JSON_STRING, // this is a string; value can be found in text_value field
|
||||
NX_JSON_INTEGER, // this is an integer; value can be found in int_value field
|
||||
NX_JSON_DOUBLE, // this is a double; value can be found in dbl_value field
|
||||
NX_JSON_BOOL // this is a boolean; value can be found in int_value field
|
||||
} nx_json_type;
|
||||
|
||||
typedef struct nx_json {
|
||||
nx_json_type type; // type of json node, see above
|
||||
const char* key; // key of the property; for object's children only
|
||||
const char* text_value; // text value of STRING node
|
||||
long int_value; // the value of INTEGER or BOOL node
|
||||
double dbl_value; // the value of DOUBLE node
|
||||
int length; // number of children of OBJECT or ARRAY
|
||||
struct nx_json* child; // points to first child
|
||||
struct nx_json* next; // points to next child
|
||||
struct nx_json* last_child;
|
||||
} nx_json;
|
||||
|
||||
typedef int (*nx_json_unicode_encoder)(unsigned int codepoint, char* p, char** endp);
|
||||
|
||||
extern nx_json_unicode_encoder nx_json_unicode_to_utf8;
|
||||
|
||||
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder);
|
||||
const nx_json* nx_json_parse_utf8(char* text);
|
||||
void nx_json_free(const nx_json* js);
|
||||
const nx_json* nx_json_get(const nx_json* json, const char* key); // get object's property by key
|
||||
const nx_json* nx_json_item(const nx_json* json, int idx); // get array element by index
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum nx_json_type {
|
||||
NX_JSON_NULL, // this is null value
|
||||
NX_JSON_OBJECT, // this is an object; properties can be found in child nodes
|
||||
NX_JSON_ARRAY, // this is an array; items can be found in child nodes
|
||||
NX_JSON_STRING, // this is a string; value can be found in text_value field
|
||||
NX_JSON_INTEGER, // this is an integer; value can be found in int_value field
|
||||
NX_JSON_DOUBLE, // this is a double; value can be found in dbl_value field
|
||||
NX_JSON_BOOL // this is a boolean; value can be found in int_value field
|
||||
} nx_json_type;
|
||||
|
||||
typedef struct nx_json {
|
||||
nx_json_type type; // type of json node, see above
|
||||
const char* key; // key of the property; for object's children only
|
||||
const char* text_value; // text value of STRING node
|
||||
long int_value; // the value of INTEGER or BOOL node
|
||||
double dbl_value; // the value of DOUBLE node
|
||||
int length; // number of children of OBJECT or ARRAY
|
||||
struct nx_json* child; // points to first child
|
||||
struct nx_json* next; // points to next child
|
||||
struct nx_json* last_child;
|
||||
} nx_json;
|
||||
|
||||
typedef int (*nx_json_unicode_encoder)(unsigned int codepoint, char* p, char** endp);
|
||||
|
||||
extern nx_json_unicode_encoder nx_json_unicode_to_utf8;
|
||||
|
||||
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder);
|
||||
const nx_json* nx_json_parse_utf8(char* text);
|
||||
void nx_json_free(const nx_json* js);
|
||||
const nx_json* nx_json_get(const nx_json* json, const char* key); // get object's property by key
|
||||
const nx_json* nx_json_item(const nx_json* json, int idx); // get array element by index
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -165,15 +165,15 @@ class SrsJsonString : public SrsJsonAny
|
|||
{
|
||||
public:
|
||||
std::string value;
|
||||
|
||||
SrsJsonString(const char* _value)
|
||||
|
||||
SrsJsonString(const char* _value)
|
||||
{
|
||||
marker = SRS_JSON_String;
|
||||
if (_value) {
|
||||
value = _value;
|
||||
}
|
||||
}
|
||||
virtual ~SrsJsonString()
|
||||
virtual ~SrsJsonString()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -182,13 +182,13 @@ class SrsJsonBoolean : public SrsJsonAny
|
|||
{
|
||||
public:
|
||||
bool value;
|
||||
|
||||
SrsJsonBoolean(bool _value)
|
||||
|
||||
SrsJsonBoolean(bool _value)
|
||||
{
|
||||
marker = SRS_JSON_Boolean;
|
||||
value = _value;
|
||||
}
|
||||
virtual ~SrsJsonBoolean()
|
||||
virtual ~SrsJsonBoolean()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -197,13 +197,13 @@ class SrsJsonInteger : public SrsJsonAny
|
|||
{
|
||||
public:
|
||||
int64_t value;
|
||||
|
||||
SrsJsonInteger(int64_t _value)
|
||||
|
||||
SrsJsonInteger(int64_t _value)
|
||||
{
|
||||
marker = SRS_JSON_Integer;
|
||||
value = _value;
|
||||
}
|
||||
virtual ~SrsJsonInteger()
|
||||
virtual ~SrsJsonInteger()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -212,13 +212,13 @@ class SrsJsonNumber : public SrsJsonAny
|
|||
{
|
||||
public:
|
||||
double value;
|
||||
|
||||
SrsJsonNumber(double _value)
|
||||
|
||||
SrsJsonNumber(double _value)
|
||||
{
|
||||
marker = SRS_JSON_Number;
|
||||
value = _value;
|
||||
}
|
||||
virtual ~SrsJsonNumber()
|
||||
virtual ~SrsJsonNumber()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -477,7 +477,7 @@ SrsJsonAny* SrsJsonAny::loads(char* str)
|
|||
if (strlen(str) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// TODO: copy str for nx_json modify it.
|
||||
string s = str;
|
||||
const nx_json* o = nx_json_parse((char*)s.data(), 0);
|
||||
|
@ -665,30 +665,30 @@ SrsJsonAny* SrsJsonObject::ensure_property_boolean(string name)
|
|||
SrsJsonAny* SrsJsonObject::ensure_property_object(string name)
|
||||
{
|
||||
SrsJsonAny* prop = get_property(name);
|
||||
|
||||
|
||||
if (!prop) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!prop->is_object()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
SrsJsonAny* SrsJsonObject::ensure_property_array(string name)
|
||||
{
|
||||
SrsJsonAny* prop = get_property(name);
|
||||
|
||||
|
||||
if (!prop) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!prop->is_array()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
|
@ -794,365 +794,365 @@ SrsAmf0Any* SrsJsonArray::to_amf0()
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
//#include "nxjson.h"
|
||||
|
||||
// redefine NX_JSON_CALLOC & NX_JSON_FREE to use custom allocator
|
||||
|
||||
//#include "nxjson.h"
|
||||
|
||||
// redefine NX_JSON_CALLOC & NX_JSON_FREE to use custom allocator
|
||||
#ifndef NX_JSON_CALLOC
|
||||
#define NX_JSON_CALLOC() calloc(1, sizeof(nx_json))
|
||||
#define NX_JSON_FREE(json) free((void*)(json))
|
||||
#endif
|
||||
|
||||
// redefine NX_JSON_REPORT_ERROR to use custom error reporting
|
||||
|
||||
// redefine NX_JSON_REPORT_ERROR to use custom error reporting
|
||||
#ifndef NX_JSON_REPORT_ERROR
|
||||
#define NX_JSON_REPORT_ERROR(msg, p) srs_warn("NXJSON PARSE ERROR (%d): " msg " at %s", __LINE__, p)
|
||||
#endif
|
||||
|
||||
|
||||
#define IS_WHITESPACE(c) ((unsigned char)(c)<=(unsigned char)' ')
|
||||
|
||||
static const nx_json dummy={ NX_JSON_NULL };
|
||||
|
||||
static nx_json* create_json(nx_json_type type, const char* key, nx_json* parent) {
|
||||
nx_json* js=(nx_json*)NX_JSON_CALLOC();
|
||||
memset(js, 0, sizeof(nx_json));
|
||||
assert(js);
|
||||
js->type=type;
|
||||
js->key=key;
|
||||
if (!parent->last_child) {
|
||||
parent->child=parent->last_child=js;
|
||||
}
|
||||
else {
|
||||
parent->last_child->next=js;
|
||||
parent->last_child=js;
|
||||
}
|
||||
parent->length++;
|
||||
return js;
|
||||
}
|
||||
|
||||
void nx_json_free(const nx_json* js) {
|
||||
nx_json* p=js->child;
|
||||
nx_json* p1;
|
||||
while (p) {
|
||||
p1=p->next;
|
||||
nx_json_free(p);
|
||||
p=p1;
|
||||
}
|
||||
NX_JSON_FREE(js);
|
||||
}
|
||||
|
||||
static int unicode_to_utf8(unsigned int codepoint, char* p, char** endp) {
|
||||
// code from http://stackoverflow.com/a/4609989/697313
|
||||
if (codepoint<0x80) *p++=codepoint;
|
||||
else if (codepoint<0x800) *p++=192+codepoint/64, *p++=128+codepoint%64;
|
||||
else if (codepoint-0xd800u<0x800) return 0; // surrogate must have been treated earlier
|
||||
else if (codepoint<0x10000) *p++=224+codepoint/4096, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
|
||||
else if (codepoint<0x110000) *p++=240+codepoint/262144, *p++=128+codepoint/4096%64, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
|
||||
else return 0; // error
|
||||
*endp=p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
nx_json_unicode_encoder nx_json_unicode_to_utf8=unicode_to_utf8;
|
||||
|
||||
static inline int hex_val(char c) {
|
||||
if (c>='0' && c<='9') return c-'0';
|
||||
if (c>='a' && c<='f') return c-'a'+10;
|
||||
if (c>='A' && c<='F') return c-'A'+10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char* unescape_string(char* s, char** end, nx_json_unicode_encoder encoder) {
|
||||
char* p=s;
|
||||
char* d=s;
|
||||
char c;
|
||||
while ((c=*p++)) {
|
||||
if (c=='"') {
|
||||
*d='\0';
|
||||
*end=p;
|
||||
return s;
|
||||
}
|
||||
else if (c=='\\') {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
case '/':
|
||||
case '"':
|
||||
*d++=*p++;
|
||||
break;
|
||||
case 'b':
|
||||
*d++='\b'; p++;
|
||||
break;
|
||||
case 'f':
|
||||
*d++='\f'; p++;
|
||||
break;
|
||||
case 'n':
|
||||
*d++='\n'; p++;
|
||||
break;
|
||||
case 'r':
|
||||
*d++='\r'; p++;
|
||||
break;
|
||||
case 't':
|
||||
*d++='\t'; p++;
|
||||
break;
|
||||
case 'u': { // unicode
|
||||
if (!encoder) {
|
||||
// leave untouched
|
||||
*d++=c;
|
||||
break;
|
||||
}
|
||||
char* ps=p-1;
|
||||
int h1, h2, h3, h4;
|
||||
if ((h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode escape", p-1);
|
||||
return 0;
|
||||
}
|
||||
unsigned int codepoint=h1<<12|h2<<8|h3<<4|h4;
|
||||
if ((codepoint & 0xfc00)==0xd800) { // high surrogate; need one more unicode to succeed
|
||||
p+=6;
|
||||
if (p[-1]!='\\' || *p!='u' || (h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
|
||||
return 0;
|
||||
}
|
||||
unsigned int codepoint2=h1<<12|h2<<8|h3<<4|h4;
|
||||
if ((codepoint2 & 0xfc00)!=0xdc00) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
|
||||
return 0;
|
||||
}
|
||||
codepoint=0x10000+((codepoint-0xd800)<<10)+(codepoint2-0xdc00);
|
||||
}
|
||||
if (!encoder(codepoint, d, &d)) {
|
||||
NX_JSON_REPORT_ERROR("invalid codepoint", ps);
|
||||
return 0;
|
||||
}
|
||||
p+=5;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// leave untouched
|
||||
*d++=c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*d++=c;
|
||||
}
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("no closing quote for string", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char* skip_block_comment(char* p) {
|
||||
// assume p[-2]=='/' && p[-1]=='*'
|
||||
char* ps=p-2;
|
||||
if (!*p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0;
|
||||
}
|
||||
REPEAT:
|
||||
p=strchr(p+1, '/');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0;
|
||||
}
|
||||
if (p[-1]!='*') goto REPEAT;
|
||||
return p+1;
|
||||
}
|
||||
|
||||
static char* parse_key(const char** key, char* p, nx_json_unicode_encoder encoder) {
|
||||
// on '}' return with *p=='}'
|
||||
char c;
|
||||
while ((c=*p++)) {
|
||||
if (c=='"') {
|
||||
*key=unescape_string(p, &p, encoder);
|
||||
if (!*key) return 0; // propagate error
|
||||
while (*p && IS_WHITESPACE(*p)) p++;
|
||||
if (*p==':') return p+1;
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0;
|
||||
}
|
||||
else if (IS_WHITESPACE(c) || c==',') {
|
||||
// continue
|
||||
}
|
||||
else if (c=='}') {
|
||||
return p-1;
|
||||
}
|
||||
else if (c=='/') {
|
||||
if (*p=='/') { // line comment
|
||||
char* ps=p-1;
|
||||
p=strchr(p+1, '\n');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0; // error
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else if (*p=='*') { // block comment
|
||||
p=skip_block_comment(p+1);
|
||||
if (!p) return 0;
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
|
||||
static char* parse_value(nx_json* parent, const char* key, char* p, nx_json_unicode_encoder encoder) {
|
||||
nx_json* js;
|
||||
while (1) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
NX_JSON_REPORT_ERROR("unexpected end of text", p);
|
||||
return 0; // error
|
||||
case ' ': case '\t': case '\n': case '\r':
|
||||
case ',':
|
||||
// skip
|
||||
p++;
|
||||
break;
|
||||
case '{':
|
||||
js=create_json(NX_JSON_OBJECT, key, parent);
|
||||
p++;
|
||||
while (1) {
|
||||
const char* new_key;
|
||||
p=parse_key(&new_key, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
if (*p=='}') return p+1; // end of object
|
||||
p=parse_value(js, new_key, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
}
|
||||
case '[':
|
||||
js=create_json(NX_JSON_ARRAY, key, parent);
|
||||
p++;
|
||||
while (1) {
|
||||
p=parse_value(js, 0, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
if (*p==']') return p+1; // end of array
|
||||
}
|
||||
case ']':
|
||||
return p;
|
||||
case '"':
|
||||
p++;
|
||||
js=create_json(NX_JSON_STRING, key, parent);
|
||||
js->text_value=unescape_string(p, &p, encoder);
|
||||
if (!js->text_value) return 0; // propagate error
|
||||
return p;
|
||||
case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
js=create_json(NX_JSON_INTEGER, key, parent);
|
||||
char* pe;
|
||||
js->int_value=strtol(p, &pe, 0);
|
||||
if (pe==p) {
|
||||
NX_JSON_REPORT_ERROR("invalid number", p);
|
||||
return 0; // error
|
||||
}
|
||||
if (*pe=='.' || *pe=='e' || *pe=='E') { // double value
|
||||
js->type=NX_JSON_DOUBLE;
|
||||
js->dbl_value=strtod(p, &pe);
|
||||
if (pe==p) {
|
||||
NX_JSON_REPORT_ERROR("invalid number", p);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
else {
|
||||
js->dbl_value=js->int_value;
|
||||
}
|
||||
return pe;
|
||||
}
|
||||
case 't':
|
||||
if (!strncmp(p, "true", 4)) {
|
||||
js=create_json(NX_JSON_BOOL, key, parent);
|
||||
js->int_value=1;
|
||||
return p+4;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case 'f':
|
||||
if (!strncmp(p, "false", 5)) {
|
||||
js=create_json(NX_JSON_BOOL, key, parent);
|
||||
js->int_value=0;
|
||||
return p+5;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case 'n':
|
||||
if (!strncmp(p, "null", 4)) {
|
||||
create_json(NX_JSON_NULL, key, parent);
|
||||
return p+4;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case '/': // comment
|
||||
if (p[1]=='/') { // line comment
|
||||
char* ps=p;
|
||||
p=strchr(p+2, '\n');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0; // error
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else if (p[1]=='*') { // block comment
|
||||
p=skip_block_comment(p+2);
|
||||
if (!p) return 0;
|
||||
|
||||
static const nx_json dummy={ NX_JSON_NULL };
|
||||
|
||||
static nx_json* create_json(nx_json_type type, const char* key, nx_json* parent) {
|
||||
nx_json* js=(nx_json*)NX_JSON_CALLOC();
|
||||
memset(js, 0, sizeof(nx_json));
|
||||
assert(js);
|
||||
js->type=type;
|
||||
js->key=key;
|
||||
if (!parent->last_child) {
|
||||
parent->child=parent->last_child=js;
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
parent->last_child->next=js;
|
||||
parent->last_child=js;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
parent->length++;
|
||||
return js;
|
||||
}
|
||||
|
||||
void nx_json_free(const nx_json* js) {
|
||||
nx_json* p=js->child;
|
||||
nx_json* p1;
|
||||
while (p) {
|
||||
p1=p->next;
|
||||
nx_json_free(p);
|
||||
p=p1;
|
||||
}
|
||||
NX_JSON_FREE(js);
|
||||
}
|
||||
|
||||
static int unicode_to_utf8(unsigned int codepoint, char* p, char** endp) {
|
||||
// code from http://stackoverflow.com/a/4609989/697313
|
||||
if (codepoint<0x80) *p++=codepoint;
|
||||
else if (codepoint<0x800) *p++=192+codepoint/64, *p++=128+codepoint%64;
|
||||
else if (codepoint-0xd800u<0x800) return 0; // surrogate must have been treated earlier
|
||||
else if (codepoint<0x10000) *p++=224+codepoint/4096, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
|
||||
else if (codepoint<0x110000) *p++=240+codepoint/262144, *p++=128+codepoint/4096%64, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
|
||||
else return 0; // error
|
||||
*endp=p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
nx_json_unicode_encoder nx_json_unicode_to_utf8=unicode_to_utf8;
|
||||
|
||||
static inline int hex_val(char c) {
|
||||
if (c>='0' && c<='9') return c-'0';
|
||||
if (c>='a' && c<='f') return c-'a'+10;
|
||||
if (c>='A' && c<='F') return c-'A'+10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char* unescape_string(char* s, char** end, nx_json_unicode_encoder encoder) {
|
||||
char* p=s;
|
||||
char* d=s;
|
||||
char c;
|
||||
while ((c=*p++)) {
|
||||
if (c=='"') {
|
||||
*d='\0';
|
||||
*end=p;
|
||||
return s;
|
||||
}
|
||||
else if (c=='\\') {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
case '/':
|
||||
case '"':
|
||||
*d++=*p++;
|
||||
break;
|
||||
case 'b':
|
||||
*d++='\b'; p++;
|
||||
break;
|
||||
case 'f':
|
||||
*d++='\f'; p++;
|
||||
break;
|
||||
case 'n':
|
||||
*d++='\n'; p++;
|
||||
break;
|
||||
case 'r':
|
||||
*d++='\r'; p++;
|
||||
break;
|
||||
case 't':
|
||||
*d++='\t'; p++;
|
||||
break;
|
||||
case 'u': { // unicode
|
||||
if (!encoder) {
|
||||
// leave untouched
|
||||
*d++=c;
|
||||
break;
|
||||
}
|
||||
char* ps=p-1;
|
||||
int h1, h2, h3, h4;
|
||||
if ((h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode escape", p-1);
|
||||
return 0;
|
||||
}
|
||||
unsigned int codepoint=h1<<12|h2<<8|h3<<4|h4;
|
||||
if ((codepoint & 0xfc00)==0xd800) { // high surrogate; need one more unicode to succeed
|
||||
p+=6;
|
||||
if (p[-1]!='\\' || *p!='u' || (h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
|
||||
return 0;
|
||||
}
|
||||
unsigned int codepoint2=h1<<12|h2<<8|h3<<4|h4;
|
||||
if ((codepoint2 & 0xfc00)!=0xdc00) {
|
||||
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
|
||||
return 0;
|
||||
}
|
||||
codepoint=0x10000+((codepoint-0xd800)<<10)+(codepoint2-0xdc00);
|
||||
}
|
||||
if (!encoder(codepoint, d, &d)) {
|
||||
NX_JSON_REPORT_ERROR("invalid codepoint", ps);
|
||||
return 0;
|
||||
}
|
||||
p+=5;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// leave untouched
|
||||
*d++=c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
*d++=c;
|
||||
}
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("no closing quote for string", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char* skip_block_comment(char* p) {
|
||||
// assume p[-2]=='/' && p[-1]=='*'
|
||||
char* ps=p-2;
|
||||
if (!*p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0;
|
||||
}
|
||||
REPEAT:
|
||||
p=strchr(p+1, '/');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0;
|
||||
}
|
||||
if (p[-1]!='*') goto REPEAT;
|
||||
return p+1;
|
||||
}
|
||||
|
||||
static char* parse_key(const char** key, char* p, nx_json_unicode_encoder encoder) {
|
||||
// on '}' return with *p=='}'
|
||||
char c;
|
||||
while ((c=*p++)) {
|
||||
if (c=='"') {
|
||||
*key=unescape_string(p, &p, encoder);
|
||||
if (!*key) return 0; // propagate error
|
||||
while (*p && IS_WHITESPACE(*p)) p++;
|
||||
if (*p==':') return p+1;
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0;
|
||||
}
|
||||
else if (IS_WHITESPACE(c) || c==',') {
|
||||
// continue
|
||||
}
|
||||
else if (c=='}') {
|
||||
return p-1;
|
||||
}
|
||||
else if (c=='/') {
|
||||
if (*p=='/') { // line comment
|
||||
char* ps=p-1;
|
||||
p=strchr(p+1, '\n');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0; // error
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else if (*p=='*') { // block comment
|
||||
p=skip_block_comment(p+1);
|
||||
if (!p) return 0;
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nx_json* nx_json_parse_utf8(char* text) {
|
||||
return nx_json_parse(text, unicode_to_utf8);
|
||||
}
|
||||
|
||||
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder) {
|
||||
nx_json js;
|
||||
memset(&js, 0, sizeof(nx_json));
|
||||
if (!parse_value(&js, 0, text, encoder)) {
|
||||
if (js.child) nx_json_free(js.child);
|
||||
return 0;
|
||||
}
|
||||
return js.child;
|
||||
}
|
||||
|
||||
const nx_json* nx_json_get(const nx_json* json, const char* key) {
|
||||
if (!json || !key) return &dummy; // never return null
|
||||
nx_json* js;
|
||||
for (js=json->child; js; js=js->next) {
|
||||
if (js->key && !strcmp(js->key, key)) return js;
|
||||
}
|
||||
return &dummy; // never return null
|
||||
}
|
||||
|
||||
const nx_json* nx_json_item(const nx_json* json, int idx) {
|
||||
if (!json) return &dummy; // never return null
|
||||
nx_json* js;
|
||||
for (js=json->child; js; js=js->next) {
|
||||
if (!idx--) return js;
|
||||
}
|
||||
return &dummy; // never return null
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char* parse_value(nx_json* parent, const char* key, char* p, nx_json_unicode_encoder encoder) {
|
||||
nx_json* js;
|
||||
while (1) {
|
||||
switch (*p) {
|
||||
case '\0':
|
||||
NX_JSON_REPORT_ERROR("unexpected end of text", p);
|
||||
return 0; // error
|
||||
case ' ': case '\t': case '\n': case '\r':
|
||||
case ',':
|
||||
// skip
|
||||
p++;
|
||||
break;
|
||||
case '{':
|
||||
js=create_json(NX_JSON_OBJECT, key, parent);
|
||||
p++;
|
||||
while (1) {
|
||||
const char* new_key;
|
||||
p=parse_key(&new_key, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
if (*p=='}') return p+1; // end of object
|
||||
p=parse_value(js, new_key, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
}
|
||||
case '[':
|
||||
js=create_json(NX_JSON_ARRAY, key, parent);
|
||||
p++;
|
||||
while (1) {
|
||||
p=parse_value(js, 0, p, encoder);
|
||||
if (!p) return 0; // error
|
||||
if (*p==']') return p+1; // end of array
|
||||
}
|
||||
case ']':
|
||||
return p;
|
||||
case '"':
|
||||
p++;
|
||||
js=create_json(NX_JSON_STRING, key, parent);
|
||||
js->text_value=unescape_string(p, &p, encoder);
|
||||
if (!js->text_value) return 0; // propagate error
|
||||
return p;
|
||||
case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
{
|
||||
js=create_json(NX_JSON_INTEGER, key, parent);
|
||||
char* pe;
|
||||
js->int_value=strtol(p, &pe, 0);
|
||||
if (pe==p) {
|
||||
NX_JSON_REPORT_ERROR("invalid number", p);
|
||||
return 0; // error
|
||||
}
|
||||
if (*pe=='.' || *pe=='e' || *pe=='E') { // double value
|
||||
js->type=NX_JSON_DOUBLE;
|
||||
js->dbl_value=strtod(p, &pe);
|
||||
if (pe==p) {
|
||||
NX_JSON_REPORT_ERROR("invalid number", p);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
else {
|
||||
js->dbl_value=js->int_value;
|
||||
}
|
||||
return pe;
|
||||
}
|
||||
case 't':
|
||||
if (!strncmp(p, "true", 4)) {
|
||||
js=create_json(NX_JSON_BOOL, key, parent);
|
||||
js->int_value=1;
|
||||
return p+4;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case 'f':
|
||||
if (!strncmp(p, "false", 5)) {
|
||||
js=create_json(NX_JSON_BOOL, key, parent);
|
||||
js->int_value=0;
|
||||
return p+5;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case 'n':
|
||||
if (!strncmp(p, "null", 4)) {
|
||||
create_json(NX_JSON_NULL, key, parent);
|
||||
return p+4;
|
||||
}
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
case '/': // comment
|
||||
if (p[1]=='/') { // line comment
|
||||
char* ps=p;
|
||||
p=strchr(p+2, '\n');
|
||||
if (!p) {
|
||||
NX_JSON_REPORT_ERROR("endless comment", ps);
|
||||
return 0; // error
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else if (p[1]=='*') { // block comment
|
||||
p=skip_block_comment(p+2);
|
||||
if (!p) return 0;
|
||||
}
|
||||
else {
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NX_JSON_REPORT_ERROR("unexpected chars", p);
|
||||
return 0; // error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nx_json* nx_json_parse_utf8(char* text) {
|
||||
return nx_json_parse(text, unicode_to_utf8);
|
||||
}
|
||||
|
||||
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder) {
|
||||
nx_json js;
|
||||
memset(&js, 0, sizeof(nx_json));
|
||||
if (!parse_value(&js, 0, text, encoder)) {
|
||||
if (js.child) nx_json_free(js.child);
|
||||
return 0;
|
||||
}
|
||||
return js.child;
|
||||
}
|
||||
|
||||
const nx_json* nx_json_get(const nx_json* json, const char* key) {
|
||||
if (!json || !key) return &dummy; // never return null
|
||||
nx_json* js;
|
||||
for (js=json->child; js; js=js->next) {
|
||||
if (js->key && !strcmp(js->key, key)) return js;
|
||||
}
|
||||
return &dummy; // never return null
|
||||
}
|
||||
|
||||
const nx_json* nx_json_item(const nx_json* json, int idx) {
|
||||
if (!json) return &dummy; // never return null
|
||||
nx_json* js;
|
||||
for (js=json->child; js; js=js->next) {
|
||||
if (!idx--) return js;
|
||||
}
|
||||
return &dummy; // never return null
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_JSON_HPP
|
||||
#define SRS_PROTOCOL_JSON_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_json.hpp>
|
||||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -68,8 +65,8 @@ class SrsJsonAny
|
|||
{
|
||||
public:
|
||||
char marker;
|
||||
// donot directly create this object,
|
||||
// instead, for examle, use SrsJsonAny::str() to create a concreated one.
|
||||
// donot directly create this object,
|
||||
// instead, for examle, use SrsJsonAny::str() to create a concreated one.
|
||||
protected:
|
||||
SrsJsonAny();
|
||||
public:
|
||||
|
@ -84,40 +81,40 @@ public:
|
|||
virtual bool is_null();
|
||||
public:
|
||||
/**
|
||||
* get the string of any when is_string() indicates true.
|
||||
* user must ensure the type is a string, or assert failed.
|
||||
*/
|
||||
* get the string of any when is_string() indicates true.
|
||||
* user must ensure the type is a string, or assert failed.
|
||||
*/
|
||||
virtual std::string to_str();
|
||||
/**
|
||||
* get the boolean of any when is_boolean() indicates true.
|
||||
* user must ensure the type is a boolean, or assert failed.
|
||||
*/
|
||||
* get the boolean of any when is_boolean() indicates true.
|
||||
* user must ensure the type is a boolean, or assert failed.
|
||||
*/
|
||||
virtual bool to_boolean();
|
||||
/**
|
||||
* get the integer of any when is_integer() indicates true.
|
||||
* user must ensure the type is a integer, or assert failed.
|
||||
*/
|
||||
* get the integer of any when is_integer() indicates true.
|
||||
* user must ensure the type is a integer, or assert failed.
|
||||
*/
|
||||
virtual int64_t to_integer();
|
||||
/**
|
||||
* get the number of any when is_number() indicates true.
|
||||
* user must ensure the type is a number, or assert failed.
|
||||
*/
|
||||
* get the number of any when is_number() indicates true.
|
||||
* user must ensure the type is a number, or assert failed.
|
||||
*/
|
||||
virtual double to_number();
|
||||
/**
|
||||
* get the object of any when is_object() indicates true.
|
||||
* user must ensure the type is a object, or assert failed.
|
||||
*/
|
||||
* get the object of any when is_object() indicates true.
|
||||
* user must ensure the type is a object, or assert failed.
|
||||
*/
|
||||
virtual SrsJsonObject* to_object();
|
||||
/**
|
||||
* get the ecma array of any when is_ecma_array() indicates true.
|
||||
* user must ensure the type is a ecma array, or assert failed.
|
||||
*/
|
||||
* get the ecma array of any when is_ecma_array() indicates true.
|
||||
* user must ensure the type is a ecma array, or assert failed.
|
||||
*/
|
||||
virtual SrsJsonArray* to_array();
|
||||
public:
|
||||
virtual std::string dumps();
|
||||
virtual SrsAmf0Any* to_amf0();
|
||||
public:
|
||||
static SrsJsonAny* str(const char* value = NULL);
|
||||
static SrsJsonAny* str(const char* value = NULL);
|
||||
static SrsJsonAny* boolean(bool value = false);
|
||||
static SrsJsonAny* integer(int64_t value = 0);
|
||||
static SrsJsonAny* number(double value = 0.0);
|
||||
|
@ -126,9 +123,9 @@ public:
|
|||
static SrsJsonArray* array();
|
||||
public:
|
||||
/**
|
||||
* read json tree from str:char*
|
||||
* @return json object. NULL if error.
|
||||
*/
|
||||
* read json tree from str:char*
|
||||
* @return json object. NULL if error.
|
||||
*/
|
||||
static SrsJsonAny* loads(char* str);
|
||||
};
|
||||
|
||||
|
@ -167,7 +164,7 @@ class SrsJsonArray : public SrsJsonAny
|
|||
{
|
||||
private:
|
||||
std::vector<SrsJsonAny*> properties;
|
||||
|
||||
|
||||
private:
|
||||
// use SrsJsonAny::array() to create it.
|
||||
friend class SrsJsonAny;
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_kbps.hpp>
|
||||
|
||||
|
@ -208,7 +208,7 @@ int64_t SrsKbps::get_send_bytes()
|
|||
// When no active session, the last_bytes record the last valid bytes.
|
||||
// TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
|
||||
bytes += os.last_bytes - os.io_bytes_base;
|
||||
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ int64_t SrsKbps::get_recv_bytes()
|
|||
// When no active session, the last_bytes record the last valid bytes.
|
||||
// TODO: Maybe the bellow bytes is zero, because the ios.io.out is NULL.
|
||||
bytes += is.last_bytes - is.io_bytes_base;
|
||||
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,41 +1,37 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_KBPS_HPP
|
||||
#define SRS_PROTOCOL_KBPS_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_kbps.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_protocol_io.hpp>
|
||||
|
||||
/**
|
||||
* a kbps sample, for example, 1minute kbps,
|
||||
* 10minute kbps sample.
|
||||
*/
|
||||
* a kbps sample, for example, 1minute kbps,
|
||||
* 10minute kbps sample.
|
||||
*/
|
||||
class SrsKbpsSample
|
||||
{
|
||||
public:
|
||||
|
@ -47,20 +43,20 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* a slice of kbps statistic, for input or output.
|
||||
* a slice contains a set of sessions, which has a base offset of bytes,
|
||||
* where a slice is:
|
||||
* starttime(oldest session startup time)
|
||||
* bytes(total bytes of previous sessions)
|
||||
* io_bytes_base(bytes offset of current session)
|
||||
* last_bytes(bytes of current session)
|
||||
* so, the total send bytes now is:
|
||||
* send_bytes = bytes + last_bytes - io_bytes_base
|
||||
* so, the bytes sent duration current session is:
|
||||
* send_bytes = last_bytes - io_bytes_base
|
||||
* @remark use set_io to start new session.
|
||||
* @remakr the slice is a data collection object driven by SrsKbps.
|
||||
*/
|
||||
* a slice of kbps statistic, for input or output.
|
||||
* a slice contains a set of sessions, which has a base offset of bytes,
|
||||
* where a slice is:
|
||||
* starttime(oldest session startup time)
|
||||
* bytes(total bytes of previous sessions)
|
||||
* io_bytes_base(bytes offset of current session)
|
||||
* last_bytes(bytes of current session)
|
||||
* so, the total send bytes now is:
|
||||
* send_bytes = bytes + last_bytes - io_bytes_base
|
||||
* so, the bytes sent duration current session is:
|
||||
* send_bytes = last_bytes - io_bytes_base
|
||||
* @remark use set_io to start new session.
|
||||
* @remakr the slice is a data collection object driven by SrsKbps.
|
||||
*/
|
||||
class SrsKbpsSlice
|
||||
{
|
||||
private:
|
||||
|
@ -102,13 +98,13 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* the interface which provices delta of bytes.
|
||||
* for a delta, for example, a live stream connection, we can got the delta by:
|
||||
* IKbpsDelta* delta = ...;
|
||||
* delta->resample();
|
||||
* kbps->add_delta(delta);
|
||||
* delta->cleanup();
|
||||
*/
|
||||
* the interface which provices delta of bytes.
|
||||
* for a delta, for example, a live stream connection, we can got the delta by:
|
||||
* IKbpsDelta* delta = ...;
|
||||
* delta->resample();
|
||||
* kbps->add_delta(delta);
|
||||
* delta->cleanup();
|
||||
*/
|
||||
class IKbpsDelta
|
||||
{
|
||||
public:
|
||||
|
@ -116,17 +112,17 @@ public:
|
|||
virtual ~IKbpsDelta();
|
||||
public:
|
||||
/**
|
||||
* resample to generate the value of delta bytes.
|
||||
*/
|
||||
* resample to generate the value of delta bytes.
|
||||
*/
|
||||
virtual void resample() = 0;
|
||||
/**
|
||||
* get the send or recv bytes delta.
|
||||
*/
|
||||
* get the send or recv bytes delta.
|
||||
*/
|
||||
virtual int64_t get_send_bytes_delta() = 0;
|
||||
virtual int64_t get_recv_bytes_delta() = 0;
|
||||
/**
|
||||
* cleanup the value of delta bytes.
|
||||
*/
|
||||
* cleanup the value of delta bytes.
|
||||
*/
|
||||
virtual void cleanup() = 0;
|
||||
};
|
||||
|
||||
|
@ -188,9 +184,9 @@ public:
|
|||
virtual void set_io(ISrsProtocolStatistic* in, ISrsProtocolStatistic* out);
|
||||
public:
|
||||
/**
|
||||
* get total kbps, duration is from the startup of io.
|
||||
* @remark, use sample() to update data.
|
||||
*/
|
||||
* get total kbps, duration is from the startup of io.
|
||||
* @remark, use sample() to update data.
|
||||
*/
|
||||
virtual int get_send_kbps();
|
||||
virtual int get_recv_kbps();
|
||||
// 30s
|
||||
|
@ -211,19 +207,19 @@ public:
|
|||
virtual void cleanup();
|
||||
public:
|
||||
/**
|
||||
* add delta to kbps clac mechenism.
|
||||
* we donot know the total bytes, but know the delta, for instance,
|
||||
* for rtmp server to calc total bytes and kbps.
|
||||
* @remark user must invoke sample() to calc result after invoke this method.
|
||||
* @param delta, assert should never be NULL.
|
||||
*/
|
||||
* add delta to kbps clac mechenism.
|
||||
* we donot know the total bytes, but know the delta, for instance,
|
||||
* for rtmp server to calc total bytes and kbps.
|
||||
* @remark user must invoke sample() to calc result after invoke this method.
|
||||
* @param delta, assert should never be NULL.
|
||||
*/
|
||||
virtual void add_delta(IKbpsDelta* delta);
|
||||
/**
|
||||
* resample all samples, ignore if in/out is NULL.
|
||||
* used for user to calc the kbps, to sample new kbps value.
|
||||
* @remark if user, for instance, the rtmp server to calc the total bytes,
|
||||
* use the add_delta() is better solutions.
|
||||
*/
|
||||
* resample all samples, ignore if in/out is NULL.
|
||||
* used for user to calc the kbps, to sample new kbps value.
|
||||
* @remark if user, for instance, the rtmp server to calc the total bytes,
|
||||
* use the add_delta() is better solutions.
|
||||
*/
|
||||
virtual void sample();
|
||||
// interface ISrsMemorySizer
|
||||
public:
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_stream.hpp>
|
||||
|
||||
|
@ -84,13 +84,13 @@ void SrsFastStream::set_buffer(int buffer_size)
|
|||
{
|
||||
// never exceed the max size.
|
||||
if (buffer_size > SRS_MAX_SOCKET_BUFFER) {
|
||||
srs_warn("limit the user-space buffer from %d to %d",
|
||||
buffer_size, SRS_MAX_SOCKET_BUFFER);
|
||||
srs_warn("limit the user-space buffer from %d to %d",
|
||||
buffer_size, SRS_MAX_SOCKET_BUFFER);
|
||||
}
|
||||
|
||||
// the user-space buffer size limit to a max value.
|
||||
int nb_resize_buf = srs_min(buffer_size, SRS_MAX_SOCKET_BUFFER);
|
||||
|
||||
|
||||
// only realloc when buffer changed bigger
|
||||
if (nb_resize_buf <= nb_buffer) {
|
||||
return;
|
||||
|
@ -120,7 +120,7 @@ char* SrsFastStream::read_slice(int size)
|
|||
|
||||
char* ptr = p;
|
||||
p += size;
|
||||
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -134,16 +134,16 @@ void SrsFastStream::skip(int size)
|
|||
int SrsFastStream::grow(ISrsReader* reader, int required_size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// already got required size of bytes.
|
||||
if (end - p >= required_size) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// must be positive.
|
||||
srs_assert(required_size > 0);
|
||||
|
||||
// the free space of buffer,
|
||||
|
||||
// the free space of buffer,
|
||||
// buffer = consumed_bytes + exists_bytes + free_space.
|
||||
int nb_free_space = (int)(buffer + nb_buffer - end);
|
||||
|
||||
|
@ -154,7 +154,7 @@ int SrsFastStream::grow(ISrsReader* reader, int required_size)
|
|||
// resize the space when no left space.
|
||||
if (nb_free_space < required_size - nb_exists_bytes) {
|
||||
srs_verbose("move fast buffer %d bytes", nb_exists_bytes);
|
||||
|
||||
|
||||
// reset or move to get more space.
|
||||
if (!nb_exists_bytes) {
|
||||
// reset when buffer is empty.
|
||||
|
@ -172,12 +172,12 @@ int SrsFastStream::grow(ISrsReader* reader, int required_size)
|
|||
nb_free_space = (int)(buffer + nb_buffer - end);
|
||||
if (nb_free_space < required_size - nb_exists_bytes) {
|
||||
ret = ERROR_READER_BUFFER_OVERFLOW;
|
||||
srs_error("buffer overflow, required=%d, max=%d, left=%d, ret=%d",
|
||||
required_size, nb_buffer, nb_free_space, ret);
|
||||
srs_error("buffer overflow, required=%d, max=%d, left=%d, ret=%d",
|
||||
required_size, nb_buffer, nb_free_space, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// buffer is ok, read required size of bytes.
|
||||
while (end - p < required_size) {
|
||||
ssize_t nread;
|
||||
|
@ -187,11 +187,11 @@ int SrsFastStream::grow(ISrsReader* reader, int required_size)
|
|||
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
/**
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
if (merged_read && _handler) {
|
||||
_handler->on_read(nread);
|
||||
}
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_STREAM_HPP
|
||||
#define SRS_PROTOCOL_STREAM_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_stream.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_protocol_io.hpp>
|
||||
|
@ -36,11 +32,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
/**
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
class IMergeReadHandler
|
||||
{
|
||||
public:
|
||||
|
@ -48,24 +44,24 @@ public:
|
|||
virtual ~IMergeReadHandler();
|
||||
public:
|
||||
/**
|
||||
* when read from channel, notice the merge handler to sleep for
|
||||
* some small bytes.
|
||||
* @remark, it only for server-side, client srs-librtmp just ignore.
|
||||
*/
|
||||
* when read from channel, notice the merge handler to sleep for
|
||||
* some small bytes.
|
||||
* @remark, it only for server-side, client srs-librtmp just ignore.
|
||||
*/
|
||||
virtual void on_read(ssize_t nread) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* the buffer provices bytes cache for protocol. generally,
|
||||
* protocol recv data from socket, put into buffer, decode to RTMP message.
|
||||
* Usage:
|
||||
* ISrsReader* r = ......;
|
||||
* SrsFastStream* fb = ......;
|
||||
* fb->grow(r, 1024);
|
||||
* char* header = fb->read_slice(100);
|
||||
* char* payload = fb->read_payload(924);
|
||||
*/
|
||||
* the buffer provices bytes cache for protocol. generally,
|
||||
* protocol recv data from socket, put into buffer, decode to RTMP message.
|
||||
* Usage:
|
||||
* ISrsReader* r = ......;
|
||||
* SrsFastStream* fb = ......;
|
||||
* fb->grow(r, 1024);
|
||||
* char* header = fb->read_slice(100);
|
||||
* char* payload = fb->read_payload(924);
|
||||
*/
|
||||
// TODO: FIXME: add utest for it.
|
||||
class SrsFastStream
|
||||
{
|
||||
|
@ -92,64 +88,64 @@ public:
|
|||
virtual ~SrsFastStream();
|
||||
public:
|
||||
/**
|
||||
* get the size of current bytes in buffer.
|
||||
*/
|
||||
* get the size of current bytes in buffer.
|
||||
*/
|
||||
virtual int size();
|
||||
/**
|
||||
* get the current bytes in buffer.
|
||||
* @remark user should use read_slice() if possible,
|
||||
* the bytes() is used to test bytes, for example, to detect the bytes schema.
|
||||
*/
|
||||
* get the current bytes in buffer.
|
||||
* @remark user should use read_slice() if possible,
|
||||
* the bytes() is used to test bytes, for example, to detect the bytes schema.
|
||||
*/
|
||||
virtual char* bytes();
|
||||
/**
|
||||
* create buffer with specifeid size.
|
||||
* @param buffer the size of buffer. ignore when smaller than SRS_MAX_SOCKET_BUFFER.
|
||||
* @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
* @remark when buffer changed, the previous ptr maybe invalid.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
* create buffer with specifeid size.
|
||||
* @param buffer the size of buffer. ignore when smaller than SRS_MAX_SOCKET_BUFFER.
|
||||
* @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K.
|
||||
* @remark when buffer changed, the previous ptr maybe invalid.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
*/
|
||||
virtual void set_buffer(int buffer_size);
|
||||
public:
|
||||
/**
|
||||
* read 1byte from buffer, move to next bytes.
|
||||
* @remark assert buffer already grow(1).
|
||||
*/
|
||||
* read 1byte from buffer, move to next bytes.
|
||||
* @remark assert buffer already grow(1).
|
||||
*/
|
||||
virtual char read_1byte();
|
||||
/**
|
||||
* read a slice in size bytes, move to next bytes.
|
||||
* user can use this char* ptr directly, and should never free it.
|
||||
* @remark user can use the returned ptr util grow(size),
|
||||
* for the ptr returned maybe invalid after grow(x).
|
||||
*/
|
||||
* read a slice in size bytes, move to next bytes.
|
||||
* user can use this char* ptr directly, and should never free it.
|
||||
* @remark user can use the returned ptr util grow(size),
|
||||
* for the ptr returned maybe invalid after grow(x).
|
||||
*/
|
||||
virtual char* read_slice(int size);
|
||||
/**
|
||||
* skip some bytes in buffer.
|
||||
* @param size the bytes to skip. positive to next; negative to previous.
|
||||
* @remark assert buffer already grow(size).
|
||||
* @remark always use read_slice to consume bytes, which will reset for EOF.
|
||||
* while skip never consume bytes.
|
||||
*/
|
||||
* skip some bytes in buffer.
|
||||
* @param size the bytes to skip. positive to next; negative to previous.
|
||||
* @remark assert buffer already grow(size).
|
||||
* @remark always use read_slice to consume bytes, which will reset for EOF.
|
||||
* while skip never consume bytes.
|
||||
*/
|
||||
virtual void skip(int size);
|
||||
public:
|
||||
/**
|
||||
* grow buffer to the required size, loop to read from skt to fill.
|
||||
* @param reader, read more bytes from reader to fill the buffer to required size.
|
||||
* @param required_size, loop to fill to ensure buffer size to required.
|
||||
* @return an int error code, error if required_size negative.
|
||||
* @remark, we actually maybe read more than required_size, maybe 4k for example.
|
||||
*/
|
||||
* grow buffer to the required size, loop to read from skt to fill.
|
||||
* @param reader, read more bytes from reader to fill the buffer to required size.
|
||||
* @param required_size, loop to fill to ensure buffer size to required.
|
||||
* @return an int error code, error if required_size negative.
|
||||
* @remark, we actually maybe read more than required_size, maybe 4k for example.
|
||||
*/
|
||||
virtual int grow(ISrsReader* reader, int required_size);
|
||||
public:
|
||||
#ifdef SRS_PERF_MERGED_READ
|
||||
/**
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @param v true to ename merged read.
|
||||
* @param handler the handler when merge read is enabled.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
* @remark the merged read is optional, ignore if not specifies.
|
||||
*/
|
||||
* to improve read performance, merge some packets then read,
|
||||
* when it on and read small bytes, we sleep to wait more data.,
|
||||
* that is, we merge some data to read together.
|
||||
* @param v true to ename merged read.
|
||||
* @param handler the handler when merge read is enabled.
|
||||
* @see https://github.com/ossrs/srs/issues/241
|
||||
* @remark the merged read is optional, ignore if not specifies.
|
||||
*/
|
||||
virtual void set_merge_read(bool v, IMergeReadHandler* handler);
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
|
@ -82,10 +82,10 @@ void srs_vhost_resolve(string& vhost, string& app, string& param)
|
|||
}
|
||||
|
||||
void srs_discovery_tc_url(
|
||||
string tcUrl,
|
||||
string& schema, string& host, string& vhost,
|
||||
string& app, int& port, string& param
|
||||
) {
|
||||
string tcUrl,
|
||||
string& schema, string& host, string& vhost,
|
||||
string& app, int& port, string& param
|
||||
) {
|
||||
size_t pos = std::string::npos;
|
||||
std::string url = tcUrl;
|
||||
|
||||
|
@ -100,19 +100,19 @@ void srs_discovery_tc_url(
|
|||
url = url.substr(host.length() + 1);
|
||||
srs_info("discovery host=%s", host.c_str());
|
||||
}
|
||||
|
||||
|
||||
port = SRS_CONSTS_RTMP_DEFAULT_PORT;
|
||||
if ((pos = host.find(":")) != std::string::npos) {
|
||||
srs_parse_hostport(host, host, port);
|
||||
srs_info("discovery host=%s, port=%d", host.c_str(), port);
|
||||
}
|
||||
|
||||
|
||||
if (url.empty()) {
|
||||
app = SRS_CONSTS_RTMP_DEFAULT_APP;
|
||||
} else {
|
||||
app = url;
|
||||
}
|
||||
|
||||
|
||||
vhost = host;
|
||||
srs_vhost_resolve(vhost, app, param);
|
||||
}
|
||||
|
@ -232,22 +232,22 @@ int srs_do_rtmp_create_msg(char type, uint32_t timestamp, char* data, int size,
|
|||
srs_error("rtmp unknown tag type=%#x. ret=%d", type, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
*ppmsg = msg;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srs_rtmp_create_msg(char type, uint32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// only when failed, we must free the data.
|
||||
if ((ret = srs_do_rtmp_create_msg(type, timestamp, data, size, stream_id, ppmsg)) != ERROR_SUCCESS) {
|
||||
srs_freepa(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ string srs_generate_stream_url(string vhost, string app, string stream)
|
|||
url += app;
|
||||
url += "/";
|
||||
url += stream;
|
||||
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_UTILITY_HPP
|
||||
#define SRS_PROTOCOL_UTILITY_HPP
|
||||
|
||||
/*
|
||||
#include <srs_protocol_utility.hpp>
|
||||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||
|
@ -46,100 +43,75 @@ class SrsCommonMessage;
|
|||
class ISrsProtocolReaderWriter;
|
||||
|
||||
/**
|
||||
* parse the tcUrl, output the schema, host, vhost, app and port.
|
||||
* @param tcUrl, the input tcUrl, for example,
|
||||
* rtmp://192.168.1.10:19350/live?vhost=vhost.ossrs.net
|
||||
* @param schema, for example, rtmp
|
||||
* @param host, for example, 192.168.1.10
|
||||
* @param vhost, for example, vhost.ossrs.net.
|
||||
* vhost default to host, when user not set vhost in query of app.
|
||||
* @param app, for example, live
|
||||
* @param port, for example, 19350
|
||||
* default to 1935 if not specified.
|
||||
* param param, for example, vhost=vhost.ossrs.net
|
||||
*/
|
||||
extern void srs_discovery_tc_url(
|
||||
std::string tcUrl,
|
||||
std::string& schema, std::string& host, std::string& vhost,
|
||||
std::string& app, int& port, std::string& param
|
||||
);
|
||||
* parse the tcUrl, output the schema, host, vhost, app and port.
|
||||
* @param tcUrl, the input tcUrl, for example,
|
||||
* rtmp://192.168.1.10:19350/live?vhost=vhost.ossrs.net
|
||||
* @param schema, for example, rtmp
|
||||
* @param host, for example, 192.168.1.10
|
||||
* @param vhost, for example, vhost.ossrs.net.
|
||||
* vhost default to host, when user not set vhost in query of app.
|
||||
* @param app, for example, live
|
||||
* @param port, for example, 19350
|
||||
* default to 1935 if not specified.
|
||||
* param param, for example, vhost=vhost.ossrs.net
|
||||
*/
|
||||
extern void srs_discovery_tc_url(std::string tcUrl, std::string& schema, std::string& host, std::string& vhost, std::string& app, int& port, std::string& param);
|
||||
|
||||
// parse query string to map(k,v).
|
||||
// must format as key=value&...&keyN=valueN
|
||||
extern void srs_parse_query_string(std::string q, std::map<std::string, std::string>& query);
|
||||
|
||||
/**
|
||||
* generate ramdom data for handshake.
|
||||
*/
|
||||
* generate ramdom data for handshake.
|
||||
*/
|
||||
extern void srs_random_generate(char* bytes, int size);
|
||||
|
||||
/**
|
||||
* generate the tcUrl.
|
||||
* @param param, the app parameters in tcUrl. for example, ?key=xxx,vhost=xxx
|
||||
* @return the tcUrl generated from ip/vhost/app/port.
|
||||
* @remark when vhost equals to __defaultVhost__, use ip as vhost.
|
||||
* @remark ignore port if port equals to default port 1935.
|
||||
*/
|
||||
extern std::string srs_generate_tc_url(
|
||||
std::string ip, std::string vhost, std::string app, int port,
|
||||
std::string param
|
||||
);
|
||||
* generate the tcUrl.
|
||||
* @param param, the app parameters in tcUrl. for example, ?key=xxx,vhost=xxx
|
||||
* @return the tcUrl generated from ip/vhost/app/port.
|
||||
* @remark when vhost equals to __defaultVhost__, use ip as vhost.
|
||||
* @remark ignore port if port equals to default port 1935.
|
||||
*/
|
||||
extern std::string srs_generate_tc_url(std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
|
||||
/**
|
||||
* srs_detect_tools generate the normal tcUrl
|
||||
*/
|
||||
extern std::string srs_generate_normal_tc_url(
|
||||
std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
extern std::string srs_generate_normal_tc_url(std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
|
||||
/**
|
||||
* srs_detect_tools generate the normal tcUrl
|
||||
*/
|
||||
extern std::string srs_generate_via_tc_url(
|
||||
std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
extern std::string srs_generate_via_tc_url(std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
|
||||
/**
|
||||
* srs_detect_tools generate the vis/vis2 tcUrl
|
||||
*/
|
||||
extern std::string srs_generate_vis_tc_url(
|
||||
std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
extern std::string srs_generate_vis_tc_url(std::string ip, std::string vhost, std::string app, int port, std::string param);
|
||||
|
||||
/**
|
||||
* create shared ptr message from bytes.
|
||||
* @param data the packet bytes. user should never free it.
|
||||
* @param ppmsg output the shared ptr message. user should free it.
|
||||
*/
|
||||
extern int srs_rtmp_create_msg(
|
||||
char type, uint32_t timestamp, char* data, int size, int stream_id,
|
||||
SrsSharedPtrMessage** ppmsg
|
||||
);
|
||||
extern int srs_rtmp_create_msg(
|
||||
char type, uint32_t timestamp, char* data, int size, int stream_id,
|
||||
SrsCommonMessage** ppmsg
|
||||
);
|
||||
* create shared ptr message from bytes.
|
||||
* @param data the packet bytes. user should never free it.
|
||||
* @param ppmsg output the shared ptr message. user should free it.
|
||||
*/
|
||||
extern int srs_rtmp_create_msg(char type, uint32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg);
|
||||
extern int srs_rtmp_create_msg(char type, uint32_t timestamp, char* data, int size, int stream_id, SrsCommonMessage** ppmsg);
|
||||
|
||||
// get the stream identify, vhost/app/stream.
|
||||
extern std::string srs_generate_stream_url(
|
||||
std::string vhost, std::string app, std::string stream
|
||||
);
|
||||
extern std::string srs_generate_stream_url(std::string vhost, std::string app, std::string stream);
|
||||
|
||||
// parse the rtmp url to tcUrl/stream,
|
||||
// for example, rtmp://v.ossrs.net/live/livestream to
|
||||
// tcUrl: rtmp://v.ossrs.net/live
|
||||
// stream: livestream
|
||||
extern void srs_parse_rtmp_url(
|
||||
std::string url, std::string& tcUrl, std::string& stream
|
||||
);
|
||||
extern void srs_parse_rtmp_url(std::string url, std::string& tcUrl, std::string& stream);
|
||||
|
||||
// genereate the rtmp url, for instance, rtmp://server:port/app...vhost...vhost/stream
|
||||
extern std::string srs_generate_rtmp_url(
|
||||
std::string server, int port, std::string vhost, std::string app, std::string stream
|
||||
);
|
||||
extern std::string srs_generate_rtmp_url(std::string server, int port, std::string vhost, std::string app, std::string stream);
|
||||
|
||||
// write large numbers of iovs.
|
||||
extern int srs_write_large_iovs(
|
||||
ISrsProtocolReaderWriter* skt, iovec* iovs, int size,
|
||||
ssize_t* pnwrite = NULL
|
||||
);
|
||||
extern int srs_write_large_iovs(ISrsProtocolReaderWriter* skt, iovec* iovs, int size, ssize_t* pnwrite = NULL);
|
||||
|
||||
// join string in vector with indicated separator
|
||||
extern std::string srs_join_vector_string(std::vector<std::string>& vs, std::string separator);
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_raw_avc.hpp>
|
||||
|
||||
|
@ -44,10 +44,10 @@ SrsRawH264Stream::~SrsRawH264Stream()
|
|||
int SrsRawH264Stream::annexb_demux(SrsBuffer* stream, char** pframe, int* pnb_frame)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
*pframe = NULL;
|
||||
*pnb_frame = 0;
|
||||
|
||||
|
||||
while (!stream->empty()) {
|
||||
// each frame must prefixed by annexb format.
|
||||
// about annexb, @see ISO_IEC_14496-10-AVC-2003.pdf, page 211.
|
||||
|
@ -71,7 +71,7 @@ int SrsRawH264Stream::annexb_demux(SrsBuffer* stream, char** pframe, int* pnb_fr
|
|||
*pframe = stream->data() + start;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,11 @@ bool SrsRawH264Stream::is_sps(char* frame, int nb_frame)
|
|||
{
|
||||
srs_assert(nb_frame > 0);
|
||||
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// ISO_IEC_14496-10-AVC-2003.pdf, page 44.
|
||||
// 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
|
||||
uint8_t nal_unit_type = (char)frame[0] & 0x1f;
|
||||
|
||||
|
||||
return nal_unit_type == 7;
|
||||
}
|
||||
|
||||
|
@ -91,23 +91,23 @@ bool SrsRawH264Stream::is_pps(char* frame, int nb_frame)
|
|||
{
|
||||
srs_assert(nb_frame > 0);
|
||||
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// 5bits, 7.3.1 NAL unit syntax,
|
||||
// ISO_IEC_14496-10-AVC-2003.pdf, page 44.
|
||||
// 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
|
||||
uint8_t nal_unit_type = (char)frame[0] & 0x1f;
|
||||
|
||||
|
||||
return nal_unit_type == 8;
|
||||
}
|
||||
|
||||
int SrsRawH264Stream::sps_demux(char* frame, int nb_frame, string& sps)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// atleast 1bytes for SPS to decode the type, profile, constrain and level.
|
||||
if (nb_frame < 4) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
sps = "";
|
||||
if (nb_frame > 0) {
|
||||
sps.append(frame, nb_frame);
|
||||
|
@ -117,31 +117,31 @@ int SrsRawH264Stream::sps_demux(char* frame, int nb_frame, string& sps)
|
|||
if (sps.empty()) {
|
||||
return ERROR_STREAM_CASTER_AVC_SPS;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRawH264Stream::pps_demux(char* frame, int nb_frame, string& pps)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
pps = "";
|
||||
if (nb_frame > 0) {
|
||||
pps.append(frame, nb_frame);
|
||||
}
|
||||
|
||||
|
||||
// should never be empty.
|
||||
if (pps.empty()) {
|
||||
return ERROR_STREAM_CASTER_AVC_PPS;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRawH264Stream::mux_sequence_header(string sps, string pps, uint32_t dts, uint32_t pts, string& sh)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// 5bytes sps/pps header:
|
||||
// configurationVersion, AVCProfileIndication, profile_compatibility,
|
||||
// AVCLevelIndication, lengthSizeMinusOne
|
||||
|
@ -153,24 +153,24 @@ int SrsRawH264Stream::mux_sequence_header(string sps, string pps, uint32_t dts,
|
|||
// numOfPictureParameterSets, pictureParameterSetLength
|
||||
// Nbytes of pps:
|
||||
// pictureParameterSetNALUnit
|
||||
int nb_packet = 5
|
||||
+ 3 + (int)sps.length()
|
||||
+ 3 + (int)pps.length();
|
||||
int nb_packet = 5
|
||||
+ 3 + (int)sps.length()
|
||||
+ 3 + (int)pps.length();
|
||||
char* packet = new char[nb_packet];
|
||||
SrsAutoFreeA(char, packet);
|
||||
|
||||
|
||||
// use stream to generate the h264 packet.
|
||||
SrsBuffer stream;
|
||||
if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// decode the SPS:
|
||||
// decode the SPS:
|
||||
// @see: 7.3.2.1.1, ISO_IEC_14496-10-AVC-2012.pdf, page 62
|
||||
if (true) {
|
||||
srs_assert((int)sps.length() >= 4);
|
||||
char* frame = (char*)sps.data();
|
||||
|
||||
|
||||
// @see: Annex A Profiles and levels, ISO_IEC_14496-10-AVC-2003.pdf, page 205
|
||||
// Baseline profile profile_idc is 66(0x42).
|
||||
// Main profile profile_idc is 77(0x4d).
|
||||
|
@ -215,14 +215,14 @@ int SrsRawH264Stream::mux_sequence_header(string sps, string pps, uint32_t dts,
|
|||
// pictureParameterSetNALUnit
|
||||
stream.write_string(pps);
|
||||
}
|
||||
|
||||
|
||||
// TODO: FIXME: for more profile.
|
||||
// 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
|
||||
// profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144
|
||||
|
||||
|
||||
sh = "";
|
||||
sh.append(packet, nb_packet);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -243,21 +243,21 @@ int SrsRawH264Stream::mux_ipb_frame(char* frame, int nb_frame, string& ibp)
|
|||
if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
|
||||
// lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size
|
||||
uint32_t NAL_unit_length = nb_frame;
|
||||
|
||||
// mux the avc NALU in "ISO Base Media File Format"
|
||||
// mux the avc NALU in "ISO Base Media File Format"
|
||||
// from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
|
||||
// NALUnitLength
|
||||
stream.write_4bytes(NAL_unit_length);
|
||||
// NALUnit
|
||||
stream.write_bytes(frame, nb_frame);
|
||||
|
||||
|
||||
ibp = "";
|
||||
ibp.append(packet, nb_packet);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -282,9 +282,9 @@ int SrsRawH264Stream::mux_avc2flv(string video, int8_t frame_type, int8_t avc_pa
|
|||
|
||||
// AVCPacketType
|
||||
*p++ = avc_packet_type;
|
||||
|
||||
|
||||
// CompositionTime
|
||||
// pts = dts + cts, or
|
||||
// pts = dts + cts, or
|
||||
// cts = pts - dts.
|
||||
// where cts is the header in rtmp video packet payload header.
|
||||
uint32_t cts = pts - dts;
|
||||
|
@ -295,10 +295,10 @@ int SrsRawH264Stream::mux_avc2flv(string video, int8_t frame_type, int8_t avc_pa
|
|||
|
||||
// h.264 raw data.
|
||||
memcpy(p, video.data(), video.length());
|
||||
|
||||
|
||||
*flv = data;
|
||||
*nb_flv = size;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -358,9 +358,9 @@ int SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* pnb_frame
|
|||
int8_t protection_absent = pav & 0x01;
|
||||
|
||||
/**
|
||||
* ID: MPEG identifier, set to '1' if the audio data in the ADTS stream are MPEG-2 AAC (See ISO/IEC 13818-7)
|
||||
* and set to '0' if the audio data are MPEG-4. See also ISO/IEC 11172-3, subclause 2.4.2.3.
|
||||
*/
|
||||
* ID: MPEG identifier, set to '1' if the audio data in the ADTS stream are MPEG-2 AAC (See ISO/IEC 13818-7)
|
||||
* and set to '0' if the audio data are MPEG-4. See also ISO/IEC 11172-3, subclause 2.4.2.3.
|
||||
*/
|
||||
if (id != 0x01) {
|
||||
srs_info("adts: id must be 1(aac), actual 0(mp4a). ret=%d", ret);
|
||||
|
||||
|
@ -447,22 +447,22 @@ int SrsRawAacStream::adts_demux(SrsBuffer* stream, char** pframe, int* pnb_frame
|
|||
codec.sound_type = srs_max(0, srs_min(1, channel_configuration - 1));
|
||||
// TODO: FIXME: finger it out the sound size by adts.
|
||||
codec.sound_size = 1; // 0(8bits) or 1(16bits).
|
||||
|
||||
|
||||
// frame data.
|
||||
*pframe = stream->data() + stream->pos();
|
||||
*pnb_frame = raw_data_size;
|
||||
stream->skip(raw_data_size);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// only support aac profile 1-4.
|
||||
if (codec->aac_object == SrsAacObjectTypeReserved) {
|
||||
return ERROR_AAC_DATA_INVALID;
|
||||
|
@ -471,22 +471,22 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
|
|||
SrsAacObjectType audioObjectType = codec->aac_object;
|
||||
char channelConfiguration = codec->channel_configuration;
|
||||
char samplingFrequencyIndex = codec->sampling_frequency_index;
|
||||
|
||||
|
||||
// override the aac samplerate by user specified.
|
||||
// @see https://github.com/ossrs/srs/issues/212#issuecomment-64146899
|
||||
switch (codec->sound_rate) {
|
||||
case SrsAudioSampleRate11025:
|
||||
case SrsAudioSampleRate11025:
|
||||
samplingFrequencyIndex = 0x0a; break;
|
||||
case SrsAudioSampleRate22050:
|
||||
case SrsAudioSampleRate22050:
|
||||
samplingFrequencyIndex = 0x07; break;
|
||||
case SrsAudioSampleRate44100:
|
||||
case SrsAudioSampleRate44100:
|
||||
samplingFrequencyIndex = 0x04; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sh = "";
|
||||
|
||||
|
||||
char ch = 0;
|
||||
// @see ISO_IEC_14496-3-AAC-2001.pdf
|
||||
// AudioSpecificConfig (), page 33
|
||||
|
@ -494,7 +494,7 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
|
|||
// audioObjectType; 5 bslbf
|
||||
ch = (audioObjectType << 3) & 0xf8;
|
||||
// 3bits left.
|
||||
|
||||
|
||||
// samplingFrequencyIndex; 4 bslbf
|
||||
ch |= (samplingFrequencyIndex >> 1) & 0x07;
|
||||
sh += ch;
|
||||
|
@ -503,31 +503,31 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
|
|||
return ERROR_AAC_DATA_INVALID;
|
||||
}
|
||||
// 7bits left.
|
||||
|
||||
|
||||
// channelConfiguration; 4 bslbf
|
||||
ch |= (channelConfiguration << 3) & 0x78;
|
||||
// 3bits left.
|
||||
|
||||
|
||||
// GASpecificConfig(), page 451
|
||||
// 4.4.1 Decoder configuration (GASpecificConfig)
|
||||
// frameLengthFlag; 1 bslbf
|
||||
// dependsOnCoreCoder; 1 bslbf
|
||||
// extensionFlag; 1 bslbf
|
||||
sh += ch;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRawAacStream::mux_aac2flv(char* frame, int nb_frame, SrsRawAacStreamCodec* codec, uint32_t dts, char** flv, int* nb_flv)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
char sound_format = codec->sound_format;
|
||||
char sound_type = codec->sound_type;
|
||||
char sound_size = codec->sound_size;
|
||||
char sound_rate = codec->sound_rate;
|
||||
char aac_packet_type = codec->aac_packet_type;
|
||||
|
||||
|
||||
// for audio frame, there is 1 or 2 bytes header:
|
||||
// 1bytes, SoundFormat|SoundRate|SoundSize|SoundType
|
||||
// 1bytes, AACPacketType for SoundFormat == 10, 0 is sequence header.
|
||||
|
@ -550,10 +550,10 @@ int SrsRawAacStream::mux_aac2flv(char* frame, int nb_frame, SrsRawAacStreamCodec
|
|||
}
|
||||
|
||||
memcpy(p, frame, nb_frame);
|
||||
|
||||
|
||||
*flv = data;
|
||||
*nb_flv = size;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_RAW_AVC_HPP
|
||||
#define SRS_PROTOCOL_RAW_AVC_HPP
|
||||
|
||||
/*
|
||||
#include <srs_raw_avc.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -37,8 +33,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
class SrsBuffer;
|
||||
|
||||
/**
|
||||
* the raw h.264 stream, in annexb.
|
||||
*/
|
||||
* the raw h.264 stream, in annexb.
|
||||
*/
|
||||
class SrsRawH264Stream
|
||||
{
|
||||
public:
|
||||
|
@ -46,51 +42,51 @@ public:
|
|||
virtual ~SrsRawH264Stream();
|
||||
public:
|
||||
/**
|
||||
* demux the stream in annexb format.
|
||||
* @param stream the input stream bytes.
|
||||
* @param pframe the output h.264 frame in stream. user should never free it.
|
||||
* @param pnb_frame the output h.264 frame size.
|
||||
*/
|
||||
* demux the stream in annexb format.
|
||||
* @param stream the input stream bytes.
|
||||
* @param pframe the output h.264 frame in stream. user should never free it.
|
||||
* @param pnb_frame the output h.264 frame size.
|
||||
*/
|
||||
virtual int annexb_demux(SrsBuffer* stream, char** pframe, int* pnb_frame);
|
||||
/**
|
||||
* whether the frame is sps or pps.
|
||||
*/
|
||||
* whether the frame is sps or pps.
|
||||
*/
|
||||
virtual bool is_sps(char* frame, int nb_frame);
|
||||
virtual bool is_pps(char* frame, int nb_frame);
|
||||
/**
|
||||
* demux the sps or pps to string.
|
||||
* @param sps/pps output the sps/pps.
|
||||
*/
|
||||
* demux the sps or pps to string.
|
||||
* @param sps/pps output the sps/pps.
|
||||
*/
|
||||
virtual int sps_demux(char* frame, int nb_frame, std::string& sps);
|
||||
virtual int pps_demux(char* frame, int nb_frame, std::string& pps);
|
||||
public:
|
||||
/**
|
||||
* h264 raw data to h264 packet, without flv payload header.
|
||||
* mux the sps/pps to flv sequence header packet.
|
||||
* @param sh output the sequence header.
|
||||
*/
|
||||
* h264 raw data to h264 packet, without flv payload header.
|
||||
* mux the sps/pps to flv sequence header packet.
|
||||
* @param sh output the sequence header.
|
||||
*/
|
||||
virtual int mux_sequence_header(std::string sps, std::string pps, uint32_t dts, uint32_t pts, std::string& sh);
|
||||
/**
|
||||
* h264 raw data to h264 packet, without flv payload header.
|
||||
* mux the ibp to flv ibp packet.
|
||||
* @param ibp output the packet.
|
||||
* @param frame_type output the frame type.
|
||||
*/
|
||||
* h264 raw data to h264 packet, without flv payload header.
|
||||
* mux the ibp to flv ibp packet.
|
||||
* @param ibp output the packet.
|
||||
* @param frame_type output the frame type.
|
||||
*/
|
||||
virtual int mux_ipb_frame(char* frame, int nb_frame, std::string& ibp);
|
||||
/**
|
||||
* mux the avc video packet to flv video packet.
|
||||
* @param frame_type, SrsVideoAvcFrameTypeKeyFrame or SrsVideoAvcFrameTypeInterFrame.
|
||||
* @param avc_packet_type, SrsVideoAvcFrameTraitSequenceHeader or SrsVideoAvcFrameTraitNALU.
|
||||
* @param video the h.264 raw data.
|
||||
* @param flv output the muxed flv packet.
|
||||
* @param nb_flv output the muxed flv size.
|
||||
*/
|
||||
* mux the avc video packet to flv video packet.
|
||||
* @param frame_type, SrsVideoAvcFrameTypeKeyFrame or SrsVideoAvcFrameTypeInterFrame.
|
||||
* @param avc_packet_type, SrsVideoAvcFrameTraitSequenceHeader or SrsVideoAvcFrameTraitNALU.
|
||||
* @param video the h.264 raw data.
|
||||
* @param flv output the muxed flv packet.
|
||||
* @param nb_flv output the muxed flv size.
|
||||
*/
|
||||
virtual int mux_avc2flv(std::string video, int8_t frame_type, int8_t avc_packet_type, uint32_t dts, uint32_t pts, char** flv, int* nb_flv);
|
||||
};
|
||||
|
||||
/**
|
||||
* the header of adts sample.
|
||||
*/
|
||||
* the header of adts sample.
|
||||
*/
|
||||
struct SrsRawAacStreamCodec
|
||||
{
|
||||
int8_t protection_absent;
|
||||
|
@ -98,7 +94,7 @@ struct SrsRawAacStreamCodec
|
|||
int8_t sampling_frequency_index;
|
||||
int8_t channel_configuration;
|
||||
int16_t frame_length;
|
||||
|
||||
|
||||
char sound_format;
|
||||
char sound_rate;
|
||||
char sound_size;
|
||||
|
@ -108,8 +104,8 @@ struct SrsRawAacStreamCodec
|
|||
};
|
||||
|
||||
/**
|
||||
* the raw aac stream, in adts.
|
||||
*/
|
||||
* the raw aac stream, in adts.
|
||||
*/
|
||||
class SrsRawAacStream
|
||||
{
|
||||
public:
|
||||
|
@ -117,27 +113,27 @@ public:
|
|||
virtual ~SrsRawAacStream();
|
||||
public:
|
||||
/**
|
||||
* demux the stream in adts format.
|
||||
* @param stream the input stream bytes.
|
||||
* @param pframe the output aac frame in stream. user should never free it.
|
||||
* @param pnb_frame the output aac frame size.
|
||||
* @param codec the output codec info.
|
||||
*/
|
||||
* demux the stream in adts format.
|
||||
* @param stream the input stream bytes.
|
||||
* @param pframe the output aac frame in stream. user should never free it.
|
||||
* @param pnb_frame the output aac frame size.
|
||||
* @param codec the output codec info.
|
||||
*/
|
||||
virtual int adts_demux(SrsBuffer* stream, char** pframe, int* pnb_frame, SrsRawAacStreamCodec& codec);
|
||||
/**
|
||||
* aac raw data to aac packet, without flv payload header.
|
||||
* mux the aac specific config to flv sequence header packet.
|
||||
* @param sh output the sequence header.
|
||||
*/
|
||||
* aac raw data to aac packet, without flv payload header.
|
||||
* mux the aac specific config to flv sequence header packet.
|
||||
* @param sh output the sequence header.
|
||||
*/
|
||||
virtual int mux_sequence_header(SrsRawAacStreamCodec* codec, std::string& sh);
|
||||
/**
|
||||
* mux the aac audio packet to flv audio packet.
|
||||
* @param frame the aac raw data.
|
||||
* @param nb_frame the count of aac frame.
|
||||
* @param codec the codec info of aac.
|
||||
* @param flv output the muxed flv packet.
|
||||
* @param nb_flv output the muxed flv size.
|
||||
*/
|
||||
* mux the aac audio packet to flv audio packet.
|
||||
* @param frame the aac raw data.
|
||||
* @param nb_frame the count of aac frame.
|
||||
* @param codec the codec info of aac.
|
||||
* @param flv output the muxed flv packet.
|
||||
* @param nb_flv output the muxed flv size.
|
||||
*/
|
||||
virtual int mux_aac2flv(char* frame, int nb_frame, SrsRawAacStreamCodec* codec, uint32_t dts, char** flv, int* nb_flv);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_rtmp_handshake.hpp>
|
||||
|
||||
|
@ -137,7 +137,7 @@ namespace _srs_internal
|
|||
0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
|
||||
}; // 62
|
||||
|
||||
int do_openssl_HMACsha256(HMAC_CTX* ctx, const void* data, int data_size, void* digest, unsigned int* digest_size)
|
||||
int do_openssl_HMACsha256(HMAC_CTX* ctx, const void* data, int data_size, void* digest, unsigned int* digest_size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
@ -145,7 +145,7 @@ namespace _srs_internal
|
|||
ret = ERROR_OpenSslSha256Update;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if (HMAC_Final(ctx, (unsigned char *) digest, digest_size) < 0) {
|
||||
ret = ERROR_OpenSslSha256Final;
|
||||
return ret;
|
||||
|
@ -154,11 +154,11 @@ namespace _srs_internal
|
|||
return ret;
|
||||
}
|
||||
/**
|
||||
* sha256 digest algorithm.
|
||||
* @param key the sha256 key, NULL to use EVP_Digest, for instance,
|
||||
* hashlib.sha256(data).digest().
|
||||
*/
|
||||
int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest)
|
||||
* sha256 digest algorithm.
|
||||
* @param key the sha256 key, NULL to use EVP_Digest, for instance,
|
||||
* hashlib.sha256(data).digest().
|
||||
*/
|
||||
int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
@ -180,8 +180,8 @@ namespace _srs_internal
|
|||
// use key-data to digest.
|
||||
HMAC_CTX *ctx = HMAC_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
ret = ERROR_OpenSslCreateHMAC;
|
||||
return ret;
|
||||
ret = ERROR_OpenSslCreateHMAC;
|
||||
return ret;
|
||||
}
|
||||
// @remark, if no key, use EVP_Digest to digest,
|
||||
// for instance, in python, hashlib.sha256(data).digest().
|
||||
|
@ -207,13 +207,13 @@ namespace _srs_internal
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define RFC2409_PRIME_1024 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
#define RFC2409_PRIME_1024 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
|
||||
SrsDH::SrsDH()
|
||||
{
|
||||
|
@ -326,26 +326,26 @@ namespace _srs_internal
|
|||
|
||||
//1. Create the DH
|
||||
if ((pdh = DH_new()) == NULL) {
|
||||
ret = ERROR_OpenSslCreateDH;
|
||||
ret = ERROR_OpenSslCreateDH;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//2. Create his internal p and g
|
||||
BIGNUM *p, *g;
|
||||
if ((p = BN_new()) == NULL) {
|
||||
ret = ERROR_OpenSslCreateP;
|
||||
ret = ERROR_OpenSslCreateP;
|
||||
return ret;
|
||||
}
|
||||
if ((g = BN_new()) == NULL) {
|
||||
ret = ERROR_OpenSslCreateG;
|
||||
ret = ERROR_OpenSslCreateG;
|
||||
BN_free(p);
|
||||
return ret;
|
||||
}
|
||||
DH_set0_pqg(pdh, p, NULL, g);
|
||||
|
||||
|
||||
//3. initialize p and g, @see ./test/ectest.c:260
|
||||
if (!BN_hex2bn(&p, RFC2409_PRIME_1024)) {
|
||||
ret = ERROR_OpenSslParseP1024;
|
||||
ret = ERROR_OpenSslParseP1024;
|
||||
return ret;
|
||||
}
|
||||
// @see ./test/bntest.c:1764
|
||||
|
@ -353,10 +353,10 @@ namespace _srs_internal
|
|||
ret = ERROR_OpenSslSetG;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// 4. Set the key length
|
||||
DH_set_length(pdh, bits_count);
|
||||
|
||||
|
||||
// 5. Generate private and public key
|
||||
// @see ./test/dhtest.c:152
|
||||
if (!DH_generate_key(pdh)) {
|
||||
|
@ -405,7 +405,7 @@ namespace _srs_internal
|
|||
|
||||
// the key must be 764 bytes.
|
||||
srs_assert(stream->require(764));
|
||||
|
||||
|
||||
// read the last offset first, 760-763
|
||||
stream->skip(764 - sizeof(int32_t));
|
||||
offset = stream->read_4bytes();
|
||||
|
@ -445,7 +445,7 @@ namespace _srs_internal
|
|||
valid_offset += *pp++;
|
||||
valid_offset += *pp++;
|
||||
valid_offset += *pp++;
|
||||
|
||||
|
||||
return valid_offset % max_offset_size;
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,7 @@ namespace _srs_internal
|
|||
srs_freepa(random0);
|
||||
srs_freepa(random1);
|
||||
}
|
||||
|
||||
|
||||
int digest_block::parse(SrsBuffer* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
@ -522,7 +522,7 @@ namespace _srs_internal
|
|||
valid_offset += *pp++;
|
||||
valid_offset += *pp++;
|
||||
valid_offset += *pp++;
|
||||
|
||||
|
||||
return valid_offset % max_offset_size;
|
||||
}
|
||||
|
||||
|
@ -592,7 +592,7 @@ namespace _srs_internal
|
|||
int c1s1_strategy::s1_create(c1s1* owner, c1s1* c1)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
SrsDH dh;
|
||||
|
||||
// ensure generate 128bytes public key.
|
||||
|
@ -607,13 +607,13 @@ namespace _srs_internal
|
|||
srs_error("calc s1 key failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// although the public key is always 128bytes, but the share key maybe not.
|
||||
// we just ignore the actual key size, but if need to use the key, must use the actual size.
|
||||
// TODO: FIXME: use the actual key size.
|
||||
//srs_assert(pkey_size == 128);
|
||||
srs_verbose("calc s1 key success.");
|
||||
|
||||
|
||||
char* s1_digest = NULL;
|
||||
if ((ret = calc_s1_digest(owner, s1_digest)) != ERROR_SUCCESS) {
|
||||
srs_error("calc s1 digest failed. ret=%d", ret);
|
||||
|
@ -652,14 +652,14 @@ namespace _srs_internal
|
|||
int c1s1_strategy::calc_c1_digest(c1s1* owner, char*& c1_digest)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
/**
|
||||
* c1s1 is splited by digest:
|
||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||
* digest-data: 32bytes
|
||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||
* @return a new allocated bytes, user must free it.
|
||||
*/
|
||||
* c1s1 is splited by digest:
|
||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||
* digest-data: 32bytes
|
||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||
* @return a new allocated bytes, user must free it.
|
||||
*/
|
||||
char* c1s1_joined_bytes = new char[1536 -32];
|
||||
SrsAutoFreeA(char, c1s1_joined_bytes);
|
||||
if ((ret = copy_to(owner, c1s1_joined_bytes, 1536 - 32, false)) != ERROR_SUCCESS) {
|
||||
|
@ -680,14 +680,14 @@ namespace _srs_internal
|
|||
int c1s1_strategy::calc_s1_digest(c1s1* owner, char*& s1_digest)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
/**
|
||||
* c1s1 is splited by digest:
|
||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||
* digest-data: 32bytes
|
||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||
* @return a new allocated bytes, user must free it.
|
||||
*/
|
||||
* c1s1 is splited by digest:
|
||||
* c1s1-part1: n bytes (time, version, key and digest-part1).
|
||||
* digest-data: 32bytes
|
||||
* c1s1-part2: (1536-n-32)bytes (digest-part2)
|
||||
* @return a new allocated bytes, user must free it.
|
||||
*/
|
||||
char* c1s1_joined_bytes = new char[1536 -32];
|
||||
SrsAutoFreeA(char, c1s1_joined_bytes);
|
||||
if ((ret = copy_to(owner, c1s1_joined_bytes, 1536 - 32, false)) != ERROR_SUCCESS) {
|
||||
|
@ -701,7 +701,7 @@ namespace _srs_internal
|
|||
return ret;
|
||||
}
|
||||
srs_verbose("digest calculated for s1");
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -711,7 +711,7 @@ namespace _srs_internal
|
|||
|
||||
// 4bytes time
|
||||
stream->write_4bytes(owner->time);
|
||||
|
||||
|
||||
// 4bytes version
|
||||
stream->write_4bytes(owner->version);
|
||||
}
|
||||
|
@ -800,7 +800,7 @@ namespace _srs_internal
|
|||
if ((ret = stream.initialize(_c1s1 + 8 + 764, 764)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if ((ret = digest.parse(&stream)) != ERROR_SUCCESS) {
|
||||
srs_error("parse the c1 digest failed. ret=%d", ret);
|
||||
return ret;
|
||||
|
@ -860,7 +860,7 @@ namespace _srs_internal
|
|||
if ((ret = stream.initialize(_c1s1 + 8, 764)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if ((ret = digest.parse(&stream)) != ERROR_SUCCESS) {
|
||||
srs_error("parse the c1 digest failed. ret=%d", ret);
|
||||
return ret;
|
||||
|
@ -966,7 +966,7 @@ namespace _srs_internal
|
|||
} else {
|
||||
payload = new c1s1_strategy_schema1();
|
||||
}
|
||||
|
||||
|
||||
return payload->parse(_c1s1, size);
|
||||
}
|
||||
|
||||
|
@ -983,7 +983,7 @@ namespace _srs_internal
|
|||
// client c1 time and version
|
||||
time = (int32_t)::time(NULL);
|
||||
version = 0x80000702; // client c1 version
|
||||
|
||||
|
||||
// generate signature by schema
|
||||
srs_freep(payload);
|
||||
if (schema == srs_schema0) {
|
||||
|
@ -1181,7 +1181,7 @@ int SrsSimpleHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsP
|
|||
if ((ret = hs_bytes->read_c0c1(io)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// plain text required.
|
||||
if (hs_bytes->c0c1[0] != 0x03) {
|
||||
ret = ERROR_RTMP_PLAIN_REQUIRED;
|
||||
|
@ -1274,7 +1274,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* /*hs_bytes*/,
|
|||
int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
ssize_t nsize;
|
||||
|
||||
if ((ret = hs_bytes->read_c0c1(io)) != ERROR_SUCCESS) {
|
||||
|
@ -1382,7 +1382,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* /*hs_bytes*/,
|
|||
int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
ssize_t nsize;
|
||||
|
||||
// complex handshake
|
||||
|
@ -1399,7 +1399,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs
|
|||
if ((ret = c1.dump(hs_bytes->c0c1 + 1, 1536)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// verify c1
|
||||
bool is_valid;
|
||||
if ((ret = c1.c1_validate_digest(is_valid)) != ERROR_SUCCESS || !is_valid) {
|
||||
|
@ -1439,12 +1439,12 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs
|
|||
if ((ret = hs_bytes->create_c2()) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
c2s2 c2;
|
||||
if ((ret = c2.c2_create(&s1)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if ((ret = c2.dump(hs_bytes->c2, 1536)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_HANDSHAKE_HPP
|
||||
#define SRS_PROTOCOL_HANDSHAKE_HPP
|
||||
|
||||
/*
|
||||
#include <srs_rtmp_handshake.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
class ISrsProtocolReaderWriter;
|
||||
|
@ -43,15 +39,15 @@ class SrsBuffer;
|
|||
namespace _srs_internal
|
||||
{
|
||||
// the digest key generate size.
|
||||
#define SRS_OpensslHashSize 512
|
||||
#define SRS_OpensslHashSize 512
|
||||
extern uint8_t SrsGenuineFMSKey[];
|
||||
extern uint8_t SrsGenuineFPKey[];
|
||||
int openssl_HMACsha256(const void* key, int key_size, const void* data, int data_size, void* digest);
|
||||
int openssl_generate_key(char* public_key, int32_t size);
|
||||
|
||||
/**
|
||||
* the DH wrapper.
|
||||
*/
|
||||
* the DH wrapper.
|
||||
*/
|
||||
class SrsDH
|
||||
{
|
||||
private:
|
||||
|
@ -63,61 +59,61 @@ namespace _srs_internal
|
|||
virtual void close();
|
||||
public:
|
||||
/**
|
||||
* initialize dh, generate the public and private key.
|
||||
* @param ensure_128bytes_public_key whether ensure public key is 128bytes,
|
||||
* sometimes openssl generate 127bytes public key.
|
||||
* default to false to donot ensure.
|
||||
*/
|
||||
* initialize dh, generate the public and private key.
|
||||
* @param ensure_128bytes_public_key whether ensure public key is 128bytes,
|
||||
* sometimes openssl generate 127bytes public key.
|
||||
* default to false to donot ensure.
|
||||
*/
|
||||
virtual int initialize(bool ensure_128bytes_public_key = false);
|
||||
/**
|
||||
* copy the public key.
|
||||
* @param pkey the bytes to copy the public key.
|
||||
* @param pkey_size the max public key size, output the actual public key size.
|
||||
* user should never ignore this size.
|
||||
* @remark, when ensure_128bytes_public_key, the size always 128.
|
||||
*/
|
||||
* copy the public key.
|
||||
* @param pkey the bytes to copy the public key.
|
||||
* @param pkey_size the max public key size, output the actual public key size.
|
||||
* user should never ignore this size.
|
||||
* @remark, when ensure_128bytes_public_key, the size always 128.
|
||||
*/
|
||||
virtual int copy_public_key(char* pkey, int32_t& pkey_size);
|
||||
/**
|
||||
* generate and copy the shared key.
|
||||
* generate the shared key with peer public key.
|
||||
* @param ppkey peer public key.
|
||||
* @param ppkey_size the size of ppkey.
|
||||
* @param skey the computed shared key.
|
||||
* @param skey_size the max shared key size, output the actual shared key size.
|
||||
* user should never ignore this size.
|
||||
*/
|
||||
* generate and copy the shared key.
|
||||
* generate the shared key with peer public key.
|
||||
* @param ppkey peer public key.
|
||||
* @param ppkey_size the size of ppkey.
|
||||
* @param skey the computed shared key.
|
||||
* @param skey_size the max shared key size, output the actual shared key size.
|
||||
* user should never ignore this size.
|
||||
*/
|
||||
virtual int copy_shared_key(const char* ppkey, int32_t ppkey_size, char* skey, int32_t& skey_size);
|
||||
private:
|
||||
virtual int do_initialize();
|
||||
};
|
||||
/**
|
||||
* the schema type.
|
||||
*/
|
||||
enum srs_schema_type
|
||||
* the schema type.
|
||||
*/
|
||||
enum srs_schema_type
|
||||
{
|
||||
srs_schema_invalid = 2,
|
||||
|
||||
/**
|
||||
* key-digest sequence
|
||||
*/
|
||||
* key-digest sequence
|
||||
*/
|
||||
srs_schema0 = 0,
|
||||
|
||||
/**
|
||||
* digest-key sequence
|
||||
* @remark, FMS requires the schema1(digest-key), or connect failed.
|
||||
*/
|
||||
//
|
||||
* digest-key sequence
|
||||
* @remark, FMS requires the schema1(digest-key), or connect failed.
|
||||
*/
|
||||
//
|
||||
srs_schema1 = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* 764bytes key structure
|
||||
* random-data: (offset)bytes
|
||||
* key-data: 128bytes
|
||||
* random-data: (764-offset-128-4)bytes
|
||||
* offset: 4bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
* 764bytes key structure
|
||||
* random-data: (offset)bytes
|
||||
* key-data: 128bytes
|
||||
* random-data: (764-offset-128-4)bytes
|
||||
* offset: 4bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
class key_block
|
||||
{
|
||||
public:
|
||||
|
@ -149,13 +145,13 @@ namespace _srs_internal
|
|||
};
|
||||
|
||||
/**
|
||||
* 764bytes digest structure
|
||||
* offset: 4bytes
|
||||
* random-data: (offset)bytes
|
||||
* digest-data: 32bytes
|
||||
* random-data: (764-4-offset-32)bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
* 764bytes digest structure
|
||||
* offset: 4bytes
|
||||
* random-data: (offset)bytes
|
||||
* digest-data: 32bytes
|
||||
* random-data: (764-4-offset-32)bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
class digest_block
|
||||
{
|
||||
public:
|
||||
|
@ -189,10 +185,10 @@ namespace _srs_internal
|
|||
class c1s1;
|
||||
|
||||
/**
|
||||
* the c1s1 strategy, use schema0 or schema1.
|
||||
* the template method class to defines common behaviors,
|
||||
* while the concrete class to implements in schema0 or schema1.
|
||||
*/
|
||||
* the c1s1 strategy, use schema0 or schema1.
|
||||
* the template method class to defines common behaviors,
|
||||
* while the concrete class to implements in schema0 or schema1.
|
||||
*/
|
||||
class c1s1_strategy
|
||||
{
|
||||
protected:
|
||||
|
@ -203,113 +199,113 @@ namespace _srs_internal
|
|||
virtual ~c1s1_strategy();
|
||||
public:
|
||||
/**
|
||||
* get the scema.
|
||||
*/
|
||||
* get the scema.
|
||||
*/
|
||||
virtual srs_schema_type schema() = 0;
|
||||
/**
|
||||
* get the digest.
|
||||
*/
|
||||
* get the digest.
|
||||
*/
|
||||
virtual char* get_digest();
|
||||
/**
|
||||
* get the key.
|
||||
*/
|
||||
* get the key.
|
||||
*/
|
||||
virtual char* get_key();
|
||||
/**
|
||||
* copy to bytes.
|
||||
* @param size must be 1536.
|
||||
*/
|
||||
* copy to bytes.
|
||||
* @param size must be 1536.
|
||||
*/
|
||||
virtual int dump(c1s1* owner, char* _c1s1, int size);
|
||||
/**
|
||||
* server: parse the c1s1, discovery the key and digest by schema.
|
||||
* use the c1_validate_digest() to valid the digest of c1.
|
||||
*/
|
||||
* server: parse the c1s1, discovery the key and digest by schema.
|
||||
* use the c1_validate_digest() to valid the digest of c1.
|
||||
*/
|
||||
virtual int parse(char* _c1s1, int size) = 0;
|
||||
public:
|
||||
/**
|
||||
* client: create and sign c1 by schema.
|
||||
* sign the c1, generate the digest.
|
||||
* calc_c1_digest(c1, schema) {
|
||||
* get c1s1-joined from c1 by specified schema
|
||||
* digest-data = HMACsha256(c1s1-joined, FPKey, 30)
|
||||
* return digest-data;
|
||||
* }
|
||||
* random fill 1536bytes c1 // also fill the c1-128bytes-key
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
|
||||
* schema = choose schema0 or schema1
|
||||
* digest-data = calc_c1_digest(c1, schema)
|
||||
* copy digest-data to c1
|
||||
*/
|
||||
* client: create and sign c1 by schema.
|
||||
* sign the c1, generate the digest.
|
||||
* calc_c1_digest(c1, schema) {
|
||||
* get c1s1-joined from c1 by specified schema
|
||||
* digest-data = HMACsha256(c1s1-joined, FPKey, 30)
|
||||
* return digest-data;
|
||||
* }
|
||||
* random fill 1536bytes c1 // also fill the c1-128bytes-key
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
|
||||
* schema = choose schema0 or schema1
|
||||
* digest-data = calc_c1_digest(c1, schema)
|
||||
* copy digest-data to c1
|
||||
*/
|
||||
virtual int c1_create(c1s1* owner);
|
||||
/**
|
||||
* server: validate the parsed c1 schema
|
||||
*/
|
||||
* server: validate the parsed c1 schema
|
||||
*/
|
||||
virtual int c1_validate_digest(c1s1* owner, bool& is_valid);
|
||||
/**
|
||||
* server: create and sign the s1 from c1.
|
||||
* // decode c1 try schema0 then schema1
|
||||
* c1-digest-data = get-c1-digest-data(schema0)
|
||||
* if c1-digest-data equals to calc_c1_digest(c1, schema0) {
|
||||
* c1-key-data = get-c1-key-data(schema0)
|
||||
* schema = schema0
|
||||
* } else {
|
||||
* c1-digest-data = get-c1-digest-data(schema1)
|
||||
* if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
|
||||
* switch to simple handshake.
|
||||
* return
|
||||
* }
|
||||
* c1-key-data = get-c1-key-data(schema1)
|
||||
* schema = schema1
|
||||
* }
|
||||
*
|
||||
* // generate s1
|
||||
* random fill 1536bytes s1
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
|
||||
* s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
|
||||
* get c1s1-joined by specified schema
|
||||
* s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
|
||||
* copy s1-digest-data and s1-key-data to s1.
|
||||
* @param c1, to get the peer_pub_key of client.
|
||||
*/
|
||||
* server: create and sign the s1 from c1.
|
||||
* // decode c1 try schema0 then schema1
|
||||
* c1-digest-data = get-c1-digest-data(schema0)
|
||||
* if c1-digest-data equals to calc_c1_digest(c1, schema0) {
|
||||
* c1-key-data = get-c1-key-data(schema0)
|
||||
* schema = schema0
|
||||
* } else {
|
||||
* c1-digest-data = get-c1-digest-data(schema1)
|
||||
* if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
|
||||
* switch to simple handshake.
|
||||
* return
|
||||
* }
|
||||
* c1-key-data = get-c1-key-data(schema1)
|
||||
* schema = schema1
|
||||
* }
|
||||
*
|
||||
* // generate s1
|
||||
* random fill 1536bytes s1
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
|
||||
* s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
|
||||
* get c1s1-joined by specified schema
|
||||
* s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
|
||||
* copy s1-digest-data and s1-key-data to s1.
|
||||
* @param c1, to get the peer_pub_key of client.
|
||||
*/
|
||||
virtual int s1_create(c1s1* owner, c1s1* c1);
|
||||
/**
|
||||
* server: validate the parsed s1 schema
|
||||
*/
|
||||
* server: validate the parsed s1 schema
|
||||
*/
|
||||
virtual int s1_validate_digest(c1s1* owner, bool& is_valid);
|
||||
public:
|
||||
/**
|
||||
* calc the digest for c1
|
||||
*/
|
||||
* calc the digest for c1
|
||||
*/
|
||||
virtual int calc_c1_digest(c1s1* owner, char*& c1_digest);
|
||||
/**
|
||||
* calc the digest for s1
|
||||
*/
|
||||
* calc the digest for s1
|
||||
*/
|
||||
virtual int calc_s1_digest(c1s1* owner, char*& s1_digest);
|
||||
/**
|
||||
* copy whole c1s1 to bytes.
|
||||
* @param size must always be 1536 with digest, and 1504 without digest.
|
||||
*/
|
||||
* copy whole c1s1 to bytes.
|
||||
* @param size must always be 1536 with digest, and 1504 without digest.
|
||||
*/
|
||||
virtual int copy_to(c1s1* owner, char* bytes, int size, bool with_digest) = 0;
|
||||
/**
|
||||
* copy time and version to stream.
|
||||
*/
|
||||
* copy time and version to stream.
|
||||
*/
|
||||
virtual void copy_time_version(SrsBuffer* stream, c1s1* owner);
|
||||
/**
|
||||
* copy key to stream.
|
||||
*/
|
||||
* copy key to stream.
|
||||
*/
|
||||
virtual void copy_key(SrsBuffer* stream);
|
||||
/**
|
||||
* copy digest to stream.
|
||||
*/
|
||||
* copy digest to stream.
|
||||
*/
|
||||
virtual void copy_digest(SrsBuffer* stream, bool with_digest);
|
||||
};
|
||||
|
||||
/**
|
||||
* c1s1 schema0
|
||||
* key: 764bytes
|
||||
* digest: 764bytes
|
||||
*/
|
||||
* c1s1 schema0
|
||||
* key: 764bytes
|
||||
* digest: 764bytes
|
||||
*/
|
||||
class c1s1_strategy_schema0 : public c1s1_strategy
|
||||
{
|
||||
public:
|
||||
|
@ -323,10 +319,10 @@ namespace _srs_internal
|
|||
};
|
||||
|
||||
/**
|
||||
* c1s1 schema1
|
||||
* digest: 764bytes
|
||||
* key: 764bytes
|
||||
*/
|
||||
* c1s1 schema1
|
||||
* digest: 764bytes
|
||||
* key: 764bytes
|
||||
*/
|
||||
class c1s1_strategy_schema1 : public c1s1_strategy
|
||||
{
|
||||
public:
|
||||
|
@ -338,20 +334,20 @@ namespace _srs_internal
|
|||
public:
|
||||
virtual int copy_to(c1s1* owner, char* bytes, int size, bool with_digest);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* c1s1 schema0
|
||||
* time: 4bytes
|
||||
* version: 4bytes
|
||||
* key: 764bytes
|
||||
* digest: 764bytes
|
||||
* c1s1 schema1
|
||||
* time: 4bytes
|
||||
* version: 4bytes
|
||||
* digest: 764bytes
|
||||
* key: 764bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
* c1s1 schema0
|
||||
* time: 4bytes
|
||||
* version: 4bytes
|
||||
* key: 764bytes
|
||||
* digest: 764bytes
|
||||
* c1s1 schema1
|
||||
* time: 4bytes
|
||||
* version: 4bytes
|
||||
* digest: 764bytes
|
||||
* key: 764bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
class c1s1
|
||||
{
|
||||
public:
|
||||
|
@ -366,91 +362,91 @@ namespace _srs_internal
|
|||
virtual ~c1s1();
|
||||
public:
|
||||
/**
|
||||
* get the scema.
|
||||
*/
|
||||
* get the scema.
|
||||
*/
|
||||
virtual srs_schema_type schema();
|
||||
/**
|
||||
* get the digest key.
|
||||
*/
|
||||
* get the digest key.
|
||||
*/
|
||||
virtual char* get_digest();
|
||||
/**
|
||||
* get the key.
|
||||
*/
|
||||
* get the key.
|
||||
*/
|
||||
virtual char* get_key();
|
||||
public:
|
||||
/**
|
||||
* copy to bytes.
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
* copy to bytes.
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
virtual int dump(char* _c1s1, int size);
|
||||
/**
|
||||
* server: parse the c1s1, discovery the key and digest by schema.
|
||||
* @param size, must always be 1536.
|
||||
* use the c1_validate_digest() to valid the digest of c1.
|
||||
* use the s1_validate_digest() to valid the digest of s1.
|
||||
*/
|
||||
* server: parse the c1s1, discovery the key and digest by schema.
|
||||
* @param size, must always be 1536.
|
||||
* use the c1_validate_digest() to valid the digest of c1.
|
||||
* use the s1_validate_digest() to valid the digest of s1.
|
||||
*/
|
||||
virtual int parse(char* _c1s1, int size, srs_schema_type _schema);
|
||||
public:
|
||||
/**
|
||||
* client: create and sign c1 by schema.
|
||||
* sign the c1, generate the digest.
|
||||
* calc_c1_digest(c1, schema) {
|
||||
* get c1s1-joined from c1 by specified schema
|
||||
* digest-data = HMACsha256(c1s1-joined, FPKey, 30)
|
||||
* return digest-data;
|
||||
* }
|
||||
* random fill 1536bytes c1 // also fill the c1-128bytes-key
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
|
||||
* schema = choose schema0 or schema1
|
||||
* digest-data = calc_c1_digest(c1, schema)
|
||||
* copy digest-data to c1
|
||||
*/
|
||||
* client: create and sign c1 by schema.
|
||||
* sign the c1, generate the digest.
|
||||
* calc_c1_digest(c1, schema) {
|
||||
* get c1s1-joined from c1 by specified schema
|
||||
* digest-data = HMACsha256(c1s1-joined, FPKey, 30)
|
||||
* return digest-data;
|
||||
* }
|
||||
* random fill 1536bytes c1 // also fill the c1-128bytes-key
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
|
||||
* schema = choose schema0 or schema1
|
||||
* digest-data = calc_c1_digest(c1, schema)
|
||||
* copy digest-data to c1
|
||||
*/
|
||||
virtual int c1_create(srs_schema_type _schema);
|
||||
/**
|
||||
* server: validate the parsed c1 schema
|
||||
*/
|
||||
* server: validate the parsed c1 schema
|
||||
*/
|
||||
virtual int c1_validate_digest(bool& is_valid);
|
||||
public:
|
||||
/**
|
||||
* server: create and sign the s1 from c1.
|
||||
* // decode c1 try schema0 then schema1
|
||||
* c1-digest-data = get-c1-digest-data(schema0)
|
||||
* if c1-digest-data equals to calc_c1_digest(c1, schema0) {
|
||||
* c1-key-data = get-c1-key-data(schema0)
|
||||
* schema = schema0
|
||||
* } else {
|
||||
* c1-digest-data = get-c1-digest-data(schema1)
|
||||
* if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
|
||||
* switch to simple handshake.
|
||||
* return
|
||||
* }
|
||||
* c1-key-data = get-c1-key-data(schema1)
|
||||
* schema = schema1
|
||||
* }
|
||||
*
|
||||
* // generate s1
|
||||
* random fill 1536bytes s1
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
|
||||
* s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
|
||||
* get c1s1-joined by specified schema
|
||||
* s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
|
||||
* copy s1-digest-data and s1-key-data to s1.
|
||||
*/
|
||||
* server: create and sign the s1 from c1.
|
||||
* // decode c1 try schema0 then schema1
|
||||
* c1-digest-data = get-c1-digest-data(schema0)
|
||||
* if c1-digest-data equals to calc_c1_digest(c1, schema0) {
|
||||
* c1-key-data = get-c1-key-data(schema0)
|
||||
* schema = schema0
|
||||
* } else {
|
||||
* c1-digest-data = get-c1-digest-data(schema1)
|
||||
* if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
|
||||
* switch to simple handshake.
|
||||
* return
|
||||
* }
|
||||
* c1-key-data = get-c1-key-data(schema1)
|
||||
* schema = schema1
|
||||
* }
|
||||
*
|
||||
* // generate s1
|
||||
* random fill 1536bytes s1
|
||||
* time = time() // c1[0-3]
|
||||
* version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
|
||||
* s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
|
||||
* get c1s1-joined by specified schema
|
||||
* s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
|
||||
* copy s1-digest-data and s1-key-data to s1.
|
||||
*/
|
||||
virtual int s1_create(c1s1* c1);
|
||||
/**
|
||||
* server: validate the parsed s1 schema
|
||||
*/
|
||||
* server: validate the parsed s1 schema
|
||||
*/
|
||||
virtual int s1_validate_digest(bool& is_valid);
|
||||
};
|
||||
|
||||
/**
|
||||
* the c2s2 complex handshake structure.
|
||||
* random-data: 1504bytes
|
||||
* digest-data: 32bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
* the c2s2 complex handshake structure.
|
||||
* random-data: 1504bytes
|
||||
* digest-data: 32bytes
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
class c2s2
|
||||
{
|
||||
public:
|
||||
|
@ -461,44 +457,44 @@ namespace _srs_internal
|
|||
virtual ~c2s2();
|
||||
public:
|
||||
/**
|
||||
* copy to bytes.
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
* copy to bytes.
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
virtual int dump(char* _c2s2, int size);
|
||||
/**
|
||||
* parse the c2s2
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
* parse the c2s2
|
||||
* @param size, must always be 1536.
|
||||
*/
|
||||
virtual int parse(char* _c2s2, int size);
|
||||
public:
|
||||
/**
|
||||
* create c2.
|
||||
* random fill c2s2 1536 bytes
|
||||
*
|
||||
* // client generate C2, or server valid C2
|
||||
* temp-key = HMACsha256(s1-digest, FPKey, 62)
|
||||
* c2-digest-data = HMACsha256(c2-random-data, temp-key, 32)
|
||||
*/
|
||||
* create c2.
|
||||
* random fill c2s2 1536 bytes
|
||||
*
|
||||
* // client generate C2, or server valid C2
|
||||
* temp-key = HMACsha256(s1-digest, FPKey, 62)
|
||||
* c2-digest-data = HMACsha256(c2-random-data, temp-key, 32)
|
||||
*/
|
||||
virtual int c2_create(c1s1* s1);
|
||||
|
||||
/**
|
||||
* validate the c2 from client.
|
||||
*/
|
||||
* validate the c2 from client.
|
||||
*/
|
||||
virtual int c2_validate(c1s1* s1, bool& is_valid);
|
||||
public:
|
||||
/**
|
||||
* create s2.
|
||||
* random fill c2s2 1536 bytes
|
||||
*
|
||||
* // server generate S2, or client valid S2
|
||||
* temp-key = HMACsha256(c1-digest, FMSKey, 68)
|
||||
* s2-digest-data = HMACsha256(s2-random-data, temp-key, 32)
|
||||
*/
|
||||
* create s2.
|
||||
* random fill c2s2 1536 bytes
|
||||
*
|
||||
* // server generate S2, or client valid S2
|
||||
* temp-key = HMACsha256(c1-digest, FMSKey, 68)
|
||||
* s2-digest-data = HMACsha256(s2-random-data, temp-key, 32)
|
||||
*/
|
||||
virtual int s2_create(c1s1* c1);
|
||||
|
||||
/**
|
||||
* validate the s2 from server.
|
||||
*/
|
||||
* validate the s2 from server.
|
||||
*/
|
||||
virtual int s2_validate(c1s1* c1, bool& is_valid);
|
||||
};
|
||||
}
|
||||
|
@ -506,10 +502,10 @@ namespace _srs_internal
|
|||
#endif
|
||||
|
||||
/**
|
||||
* simple handshake.
|
||||
* user can try complex handshake first,
|
||||
* rollback to simple handshake if error ERROR_RTMP_TRY_SIMPLE_HS
|
||||
*/
|
||||
* simple handshake.
|
||||
* user can try complex handshake first,
|
||||
* rollback to simple handshake if error ERROR_RTMP_TRY_SIMPLE_HS
|
||||
*/
|
||||
class SrsSimpleHandshake
|
||||
{
|
||||
public:
|
||||
|
@ -517,17 +513,17 @@ public:
|
|||
virtual ~SrsSimpleHandshake();
|
||||
public:
|
||||
/**
|
||||
* simple handshake.
|
||||
*/
|
||||
* simple handshake.
|
||||
*/
|
||||
virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
|
||||
virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
|
||||
};
|
||||
|
||||
/**
|
||||
* rtmp complex handshake,
|
||||
* @see also crtmp(crtmpserver) or librtmp,
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
* rtmp complex handshake,
|
||||
* @see also crtmp(crtmpserver) or librtmp,
|
||||
* @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
*/
|
||||
class SrsComplexHandshake
|
||||
{
|
||||
public:
|
||||
|
@ -535,12 +531,12 @@ public:
|
|||
virtual ~SrsComplexHandshake();
|
||||
public:
|
||||
/**
|
||||
* complex hanshake.
|
||||
* @return user must:
|
||||
* continue connect app if success,
|
||||
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
|
||||
* otherwise, disconnect
|
||||
*/
|
||||
* complex hanshake.
|
||||
* @return user must:
|
||||
* continue connect app if success,
|
||||
* try simple handshake if error is ERROR_RTMP_TRY_SIMPLE_HS,
|
||||
* otherwise, disconnect
|
||||
*/
|
||||
virtual int handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
|
||||
virtual int handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrsProtocolReaderWriter* io);
|
||||
};
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_rtmp_msg_array.hpp>
|
||||
|
||||
|
|
|
@ -1,74 +1,70 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_MESSAGE_ARRAY_HPP
|
||||
#define SRS_PROTOCOL_MESSAGE_ARRAY_HPP
|
||||
|
||||
/*
|
||||
#include <srs_rtmp_msg_array.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
class SrsSharedPtrMessage;
|
||||
|
||||
/**
|
||||
* the class to auto free the shared ptr message array.
|
||||
* when need to get some messages, for instance, from Consumer queue,
|
||||
* create a message array, whose msgs can used to accept the msgs,
|
||||
* then send each message and set to NULL.
|
||||
*
|
||||
* @remark: user must free all msgs in array, for the SRS2.0 protocol stack
|
||||
* provides an api to send messages, @see send_and_free_messages
|
||||
*/
|
||||
* the class to auto free the shared ptr message array.
|
||||
* when need to get some messages, for instance, from Consumer queue,
|
||||
* create a message array, whose msgs can used to accept the msgs,
|
||||
* then send each message and set to NULL.
|
||||
*
|
||||
* @remark: user must free all msgs in array, for the SRS2.0 protocol stack
|
||||
* provides an api to send messages, @see send_and_free_messages
|
||||
*/
|
||||
class SrsMessageArray
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* when user already send the msg in msgs, please set to NULL,
|
||||
* for instance, msg= msgs.msgs[i], msgs.msgs[i]=NULL, send(msg),
|
||||
* where send(msg) will always send and free it.
|
||||
*/
|
||||
* when user already send the msg in msgs, please set to NULL,
|
||||
* for instance, msg= msgs.msgs[i], msgs.msgs[i]=NULL, send(msg),
|
||||
* where send(msg) will always send and free it.
|
||||
*/
|
||||
SrsSharedPtrMessage** msgs;
|
||||
int max;
|
||||
public:
|
||||
/**
|
||||
* create msg array, initialize array to NULL ptrs.
|
||||
*/
|
||||
* create msg array, initialize array to NULL ptrs.
|
||||
*/
|
||||
SrsMessageArray(int max_msgs);
|
||||
/**
|
||||
* free the msgs not sent out(not NULL).
|
||||
*/
|
||||
* free the msgs not sent out(not NULL).
|
||||
*/
|
||||
virtual ~SrsMessageArray();
|
||||
public:
|
||||
/**
|
||||
* free specified count of messages.
|
||||
*/
|
||||
* free specified count of messages.
|
||||
*/
|
||||
virtual void free(int count);
|
||||
private:
|
||||
/**
|
||||
* zero initialize the message array.
|
||||
*/
|
||||
* zero initialize the message array.
|
||||
*/
|
||||
virtual void zero(int count);
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,25 +1,25 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_rtsp_stack.hpp>
|
||||
|
||||
|
@ -48,50 +48,50 @@ 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;
|
||||
_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;
|
||||
|
@ -104,7 +104,7 @@ string srs_generate_rtsp_status_text(int status)
|
|||
return status_text;
|
||||
}
|
||||
|
||||
std::string srs_generate_rtsp_method_str(SrsRtspMethod method)
|
||||
std::string srs_generate_rtsp_method_str(SrsRtspMethod method)
|
||||
{
|
||||
switch (method) {
|
||||
case SrsRtspMethodDescribe: return SRS_METHOD_DESCRIBE;
|
||||
|
@ -129,12 +129,12 @@ SrsRtpPacket::SrsRtpPacket()
|
|||
extension = 0;
|
||||
csrc_count = 0;
|
||||
marker = 1;
|
||||
|
||||
|
||||
payload_type = 0;
|
||||
sequence_number = 0;
|
||||
timestamp = 0;
|
||||
ssrc = 0;
|
||||
|
||||
|
||||
payload = new SrsSimpleStream();
|
||||
audio = new SrsAudioFrame();
|
||||
chunked = false;
|
||||
|
@ -158,7 +158,7 @@ void SrsRtpPacket::copy(SrsRtpPacket* src)
|
|||
sequence_number = src->sequence_number;
|
||||
timestamp = src->timestamp;
|
||||
ssrc = src->ssrc;
|
||||
|
||||
|
||||
chunked = src->chunked;
|
||||
completed = src->completed;
|
||||
|
||||
|
@ -169,7 +169,7 @@ void SrsRtpPacket::copy(SrsRtpPacket* src)
|
|||
void SrsRtpPacket::reap(SrsRtpPacket* src)
|
||||
{
|
||||
copy(src);
|
||||
|
||||
|
||||
srs_freep(payload);
|
||||
payload = src->payload;
|
||||
src->payload = NULL;
|
||||
|
@ -182,112 +182,112 @@ void SrsRtpPacket::reap(SrsRtpPacket* src)
|
|||
int SrsRtpPacket::decode(SrsBuffer* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// 12bytes header
|
||||
if (!stream->require(12)) {
|
||||
ret = ERROR_RTP_HEADER_CORRUPT;
|
||||
srs_error("rtsp: rtp header corrupt. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int8_t vv = stream->read_1bytes();
|
||||
version = (vv >> 6) & 0x03;
|
||||
padding = (vv >> 5) & 0x01;
|
||||
extension = (vv >> 4) & 0x01;
|
||||
csrc_count = vv & 0x0f;
|
||||
|
||||
|
||||
int8_t mv = stream->read_1bytes();
|
||||
marker = (mv >> 7) & 0x01;
|
||||
payload_type = mv & 0x7f;
|
||||
|
||||
|
||||
sequence_number = stream->read_2bytes();
|
||||
timestamp = stream->read_4bytes();
|
||||
ssrc = stream->read_4bytes();
|
||||
|
||||
|
||||
// TODO: FIXME: check sequence number.
|
||||
|
||||
|
||||
// video codec.
|
||||
if (payload_type == 96) {
|
||||
return decode_96(stream);
|
||||
} else if (payload_type == 97) {
|
||||
return decode_97(stream);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRtpPacket::decode_97(SrsBuffer* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// atleast 2bytes content.
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTP_TYPE97_CORRUPT;
|
||||
srs_error("rtsp: rtp type97 corrupt. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int8_t hasv = stream->read_1bytes();
|
||||
int8_t lasv = stream->read_1bytes();
|
||||
uint16_t au_size = ((hasv << 5) & 0xE0) | ((lasv >> 3) & 0x1f);
|
||||
|
||||
|
||||
if (!stream->require(au_size)) {
|
||||
ret = ERROR_RTP_TYPE97_CORRUPT;
|
||||
srs_error("rtsp: rtp type97 au_size corrupt. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int required_size = 0;
|
||||
|
||||
|
||||
// append left bytes to payload.
|
||||
payload->append(
|
||||
stream->data() + stream->pos() + au_size,
|
||||
stream->size() - stream->pos() - au_size
|
||||
);
|
||||
stream->data() + stream->pos() + au_size,
|
||||
stream->size() - stream->pos() - au_size
|
||||
);
|
||||
char* p = payload->bytes();
|
||||
|
||||
|
||||
for (int i = 0; i < au_size; i += 2) {
|
||||
hasv = stream->read_1bytes();
|
||||
lasv = stream->read_1bytes();
|
||||
|
||||
|
||||
uint16_t sample_size = ((hasv << 5) & 0xE0) | ((lasv >> 3) & 0x1f);
|
||||
// TODO: FIXME: finger out how to parse the size of sample.
|
||||
if (sample_size < 0x100 && stream->require(required_size + sample_size + 0x100)) {
|
||||
sample_size = sample_size | 0x100;
|
||||
}
|
||||
|
||||
|
||||
char* sample = p + required_size;
|
||||
required_size += sample_size;
|
||||
|
||||
|
||||
if (!stream->require(required_size)) {
|
||||
ret = ERROR_RTP_TYPE97_CORRUPT;
|
||||
srs_error("rtsp: rtp type97 samples corrupt. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
if ((ret = audio->add_sample(sample, sample_size)) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: rtp type97 add sample failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parsed ok.
|
||||
completed = true;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsRtpPacket::decode_96(SrsBuffer* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// atleast 2bytes content.
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTP_TYPE96_CORRUPT;
|
||||
srs_error("rtsp: rtp type96 corrupt. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// frame type
|
||||
// 0... .... reserverd
|
||||
// .11. .... NALU[0]&0x60
|
||||
|
@ -296,7 +296,7 @@ int SrsRtpPacket::decode_96(SrsBuffer* stream)
|
|||
int8_t ftv = stream->read_1bytes();
|
||||
int8_t nalu_0x60 = ftv & 0x60;
|
||||
int8_t fu_indicator = ftv & 0x1c;
|
||||
|
||||
|
||||
// nri, whatever
|
||||
// 10.. .... first chunk.
|
||||
// 00.. .... continous chunk.
|
||||
|
@ -307,12 +307,12 @@ int SrsRtpPacket::decode_96(SrsBuffer* stream)
|
|||
bool last_chunk = (nriv & 0xC0) == 0x40;
|
||||
bool contious_chunk = (nriv & 0xC0) == 0x00;
|
||||
int8_t nalu_0x1f = nriv & 0x1f;
|
||||
|
||||
|
||||
// chunked, generate the first byte NALU.
|
||||
if (fu_indicator == 0x1c && (first_chunk || last_chunk || contious_chunk)) {
|
||||
chunked = true;
|
||||
completed = last_chunk;
|
||||
|
||||
|
||||
// generate and append the first byte NALU.
|
||||
if (first_chunk) {
|
||||
int8_t nalu_byte0 = nalu_0x60 | nalu_0x1f;
|
||||
|
@ -322,12 +322,12 @@ int SrsRtpPacket::decode_96(SrsBuffer* stream)
|
|||
payload->append(stream->data() + stream->pos(), stream->size() - stream->pos());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// no chunked, append to payload.
|
||||
stream->skip(-2);
|
||||
payload->append(stream->data() + stream->pos(), stream->size() - stream->pos());
|
||||
completed = true;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -343,18 +343,18 @@ SrsRtspSdp::~SrsRtspSdp()
|
|||
int SrsRtspSdp::parse(string token)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
if (token.empty()) {
|
||||
srs_info("rtsp: ignore empty token.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t pos = string::npos;
|
||||
|
||||
|
||||
char* start = (char*)token.data();
|
||||
char* end = start + (int)token.length();
|
||||
char* p = start;
|
||||
|
||||
|
||||
// key, first 2bytes.
|
||||
// v=0
|
||||
// o=- 0 0 IN IP4 127.0.0.1
|
||||
|
@ -374,13 +374,13 @@ int SrsRtspSdp::parse(string token)
|
|||
// a=control:streamid=1
|
||||
char key = p[0];
|
||||
p += 2;
|
||||
|
||||
|
||||
// left bytes as attr string.
|
||||
std::string attr_str;
|
||||
if (end - p) {
|
||||
attr_str.append(p, end - p);
|
||||
}
|
||||
|
||||
|
||||
// parse the attributes from left bytes.
|
||||
std::vector<std::string> attrs;
|
||||
while (p < end) {
|
||||
|
@ -395,7 +395,7 @@ int SrsRtspSdp::parse(string token)
|
|||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
|
||||
// parse the first attr as desc, update the first elem for desc.
|
||||
// for example, the value can be "tool", "AS", "rtpmap", "fmtp", "control"
|
||||
std::string desc_key;
|
||||
|
@ -410,7 +410,7 @@ int SrsRtspSdp::parse(string token)
|
|||
desc_key = attr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// interpret the attribute according by key.
|
||||
switch (key) {
|
||||
case 'v': version = attr_str; break;
|
||||
|
@ -492,7 +492,7 @@ int SrsRtspSdp::parse(string token)
|
|||
case 't':
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -502,7 +502,7 @@ int SrsRtspSdp::parse_fmtp_attribute(string attr)
|
|||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
|
@ -511,13 +511,13 @@ int SrsRtspSdp::parse_fmtp_attribute(string attr)
|
|||
} else {
|
||||
token = "";
|
||||
}
|
||||
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
if ((pos = item.find("=")) != string::npos) {
|
||||
item_key = item.substr(0, pos);
|
||||
item_value = item.substr(pos + 1);
|
||||
}
|
||||
|
||||
|
||||
if (state == SrsRtspSdpStateVideo) {
|
||||
if (item_key == "packetization-mode") {
|
||||
video_packetization_mode = item_value;
|
||||
|
@ -548,7 +548,7 @@ int SrsRtspSdp::parse_fmtp_attribute(string attr)
|
|||
srs_error("rtsp: audio config failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char* tmp_sh = new char[item_value.length()];
|
||||
SrsAutoFreeA(char, tmp_sh);
|
||||
int nb_tmp_sh = ff_hex_to_data((uint8_t*)tmp_sh, item_value.c_str());
|
||||
|
@ -557,7 +557,7 @@ int SrsRtspSdp::parse_fmtp_attribute(string attr)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -567,7 +567,7 @@ int SrsRtspSdp::parse_control_attribute(string attr)
|
|||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
|
@ -576,13 +576,13 @@ int SrsRtspSdp::parse_control_attribute(string attr)
|
|||
} else {
|
||||
token = "";
|
||||
}
|
||||
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
if ((pos = item.find("=")) != string::npos) {
|
||||
item_key = item.substr(0, pos);
|
||||
item_value = item.substr(pos + 1);
|
||||
}
|
||||
|
||||
|
||||
if (state == SrsRtspSdpStateVideo) {
|
||||
if (item_key == "streamid") {
|
||||
video_stream_id = item_value;
|
||||
|
@ -593,7 +593,7 @@ int SrsRtspSdp::parse_control_attribute(string attr)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -602,16 +602,16 @@ string SrsRtspSdp::base64_decode(string value)
|
|||
if (value.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
int nb_output = (int)(value.length() * 2);
|
||||
uint8_t* output = new uint8_t[nb_output];
|
||||
SrsAutoFreeA(uint8_t, output);
|
||||
|
||||
|
||||
int ret = srs_av_base64_decode(output, (char*)value.c_str(), nb_output);
|
||||
if (ret <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
std::string plaintext;
|
||||
plaintext.append((char*)output, ret);
|
||||
return plaintext;
|
||||
|
@ -633,7 +633,7 @@ int SrsRtspTransport::parse(string attr)
|
|||
|
||||
size_t pos = string::npos;
|
||||
std::string token = attr;
|
||||
|
||||
|
||||
while (!token.empty()) {
|
||||
std::string item = token;
|
||||
if ((pos = item.find(";")) != string::npos) {
|
||||
|
@ -642,13 +642,13 @@ int SrsRtspTransport::parse(string attr)
|
|||
} else {
|
||||
token = "";
|
||||
}
|
||||
|
||||
|
||||
std::string item_key = item, item_value;
|
||||
if ((pos = item.find("=")) != string::npos) {
|
||||
item_key = item.substr(0, pos);
|
||||
item_value = item.substr(pos + 1);
|
||||
}
|
||||
|
||||
|
||||
if (transport.empty()) {
|
||||
transport = item_key;
|
||||
if ((pos = transport.find("/")) != string::npos) {
|
||||
|
@ -660,7 +660,7 @@ int SrsRtspTransport::parse(string attr)
|
|||
profile = profile.substr(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (item_key == "unicast" || item_key == "multicast") {
|
||||
cast_type = item_key;
|
||||
} else if (item_key == "mode") {
|
||||
|
@ -676,7 +676,7 @@ int SrsRtspTransport::parse(string attr)
|
|||
client_port_max = ::atoi(eport.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -728,33 +728,33 @@ SrsRtspResponse::~SrsRtspResponse()
|
|||
int SrsRtspResponse::encode(stringstream& ss)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
// status line
|
||||
ss << SRS_RTSP_VERSION << SRS_RTSP_SP
|
||||
<< status << SRS_RTSP_SP
|
||||
<< srs_generate_rtsp_status_text(status) << SRS_RTSP_CRLF;
|
||||
|
||||
ss << SRS_RTSP_VERSION << SRS_RTSP_SP
|
||||
<< status << SRS_RTSP_SP
|
||||
<< srs_generate_rtsp_status_text(status) << SRS_RTSP_CRLF;
|
||||
|
||||
// cseq
|
||||
ss << SRS_RTSP_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;
|
||||
|
||||
<< "Pragma: no-cache" << SRS_RTSP_CRLF
|
||||
<< "Server: " << RTMP_SIG_SRS_SERVER << SRS_RTSP_CRLF;
|
||||
|
||||
// session if specified.
|
||||
if (!session.empty()) {
|
||||
ss << SRS_RTSP_TOKEN_SESSION << ":" << session << SRS_RTSP_CRLF;
|
||||
}
|
||||
|
||||
|
||||
if ((ret = encode_header(ss)) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: encode header failed. ret=%d", ret);
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
// header EOF.
|
||||
ss << SRS_RTSP_CRLF;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -765,7 +765,7 @@ int SrsRtspResponse::encode_header(std::stringstream& ss)
|
|||
|
||||
SrsRtspOptionsResponse::SrsRtspOptionsResponse(int cseq) : SrsRtspResponse(cseq)
|
||||
{
|
||||
methods = (SrsRtspMethod)(SrsRtspMethodDescribe | SrsRtspMethodOptions
|
||||
methods = (SrsRtspMethod)(SrsRtspMethodDescribe | SrsRtspMethodOptions
|
||||
| SrsRtspMethodPause | SrsRtspMethodPlay | SrsRtspMethodSetup | SrsRtspMethodTeardown
|
||||
| SrsRtspMethodAnnounce | SrsRtspMethodRecord);
|
||||
}
|
||||
|
@ -789,9 +789,9 @@ int SrsRtspOptionsResponse::encode_header(stringstream& ss)
|
|||
SrsRtspMethodSetParameter,
|
||||
SrsRtspMethodTeardown,
|
||||
};
|
||||
|
||||
|
||||
ss << SRS_RTSP_TOKEN_PUBLIC << ":" << SRS_RTSP_SP;
|
||||
|
||||
|
||||
bool appended = false;
|
||||
int nb_methods = (int)(sizeof(rtsp_methods) / sizeof(SrsRtspMethod));
|
||||
for (int i = 0; i < nb_methods; i++) {
|
||||
|
@ -799,7 +799,7 @@ int SrsRtspOptionsResponse::encode_header(stringstream& ss)
|
|||
if (((int)methods & (int)method) != (int)method) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (appended) {
|
||||
ss << ", ";
|
||||
}
|
||||
|
@ -807,7 +807,7 @@ int SrsRtspOptionsResponse::encode_header(stringstream& ss)
|
|||
appended = true;
|
||||
}
|
||||
ss << SRS_RTSP_CRLF;
|
||||
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -824,10 +824,10 @@ SrsRtspSetupResponse::~SrsRtspSetupResponse()
|
|||
int SrsRtspSetupResponse::encode_header(stringstream& ss)
|
||||
{
|
||||
ss << SRS_RTSP_TOKEN_SESSION << ":" << SRS_RTSP_SP << session << SRS_RTSP_CRLF;
|
||||
ss << SRS_RTSP_TOKEN_TRANSPORT << ":" << SRS_RTSP_SP
|
||||
<< "RTP/AVP;unicast;client_port=" << client_port_min << "-" << client_port_max << ";"
|
||||
<< "server_port=" << local_port_min << "-" << local_port_max
|
||||
<< SRS_RTSP_CRLF;
|
||||
ss << SRS_RTSP_TOKEN_TRANSPORT << ":" << SRS_RTSP_SP
|
||||
<< "RTP/AVP;unicast;client_port=" << client_port_min << "-" << client_port_max << ";"
|
||||
<< "server_port=" << local_port_min << "-" << local_port_max
|
||||
<< SRS_RTSP_CRLF;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -845,29 +845,29 @@ SrsRtspStack::~SrsRtspStack()
|
|||
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);
|
||||
|
@ -875,14 +875,14 @@ int SrsRtspStack::send_message(SrsRtspResponse* res)
|
|||
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)) {
|
||||
|
@ -890,21 +890,21 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
}
|
||||
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
|
||||
|
@ -920,7 +920,7 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// parse the header value according by header name
|
||||
if (token == SRS_RTSP_TOKEN_CSEQ) {
|
||||
std::string seq;
|
||||
|
@ -986,7 +986,7 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// for setup, parse the stream id from uri.
|
||||
if (req->is_setup()) {
|
||||
size_t pos = string::npos;
|
||||
|
@ -997,14 +997,14 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
req->stream_id = ::atoi(stream_id.c_str());
|
||||
srs_info("rtsp: setup stream id=%d", req->stream_id);
|
||||
}
|
||||
|
||||
|
||||
// parse rdp body.
|
||||
long consumed = 0;
|
||||
while (consumed < req->content_length) {
|
||||
if (!req->sdp) {
|
||||
req->sdp = new SrsRtspSdp();
|
||||
}
|
||||
|
||||
|
||||
int nb_token = 0;
|
||||
std::string token;
|
||||
if ((ret = recv_token_util_eof(token, &nb_token)) != ERROR_SUCCESS) {
|
||||
|
@ -1014,7 +1014,7 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
return ret;
|
||||
}
|
||||
consumed += nb_token;
|
||||
|
||||
|
||||
if ((ret = req->sdp->parse(token)) != ERROR_SUCCESS) {
|
||||
srs_error("rtsp: sdp parse token failed, token=%s. ret=%d", token.c_str(), ret);
|
||||
return ret;
|
||||
|
@ -1022,16 +1022,16 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
|
|||
srs_info("rtsp: %s", token.c_str());
|
||||
}
|
||||
srs_info("rtsp: sdp parsed, size=%d", consumed);
|
||||
|
||||
|
||||
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;
|
||||
|
@ -1041,22 +1041,22 @@ int SrsRtspStack::recv_token_normal(std::string& token)
|
|||
}
|
||||
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;
|
||||
|
@ -1066,22 +1066,22 @@ int SrsRtspStack::recv_token_eof(std::string& token)
|
|||
}
|
||||
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* pconsumed)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
|
||||
SrsRtspTokenState state;
|
||||
|
||||
|
||||
// use 0x00 as ignore the normal token flag.
|
||||
if ((ret = recv_token(token, state, 0x00, pconsumed)) != ERROR_SUCCESS) {
|
||||
if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
|
||||
|
@ -1092,32 +1092,32 @@ int SrsRtspStack::recv_token_util_eof(std::string& token, int* pconsumed)
|
|||
}
|
||||
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* pconsumed)
|
||||
{
|
||||
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) {
|
||||
|
@ -1127,19 +1127,19 @@ int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char
|
|||
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.
|
||||
|
@ -1160,11 +1160,11 @@ int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char
|
|||
} 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);
|
||||
|
@ -1173,11 +1173,11 @@ int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// append more and parse again.
|
||||
append_bytes = true;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2017 SRS(ossrs)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 SRS(ossrs)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_PROTOCOL_RTSP_HPP
|
||||
#define SRS_PROTOCOL_RTSP_HPP
|
||||
|
||||
/*
|
||||
#include <srs_rtsp_stack.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#if !defined(SRS_EXPORT_LIBRTMP)
|
||||
|
@ -85,37 +81,37 @@ class ISrsProtocolReaderWriter;
|
|||
#define SRS_RTSP_VERSION "RTSP/1.0"
|
||||
|
||||
/**
|
||||
* the rtsp sdp parse state.
|
||||
*/
|
||||
* the rtsp sdp parse state.
|
||||
*/
|
||||
enum SrsRtspSdpState
|
||||
{
|
||||
/**
|
||||
* other sdp properties.
|
||||
*/
|
||||
* other sdp properties.
|
||||
*/
|
||||
SrsRtspSdpStateOthers,
|
||||
/**
|
||||
* parse sdp audio state.
|
||||
*/
|
||||
* parse sdp audio state.
|
||||
*/
|
||||
SrsRtspSdpStateAudio,
|
||||
/**
|
||||
* parse sdp video state.
|
||||
*/
|
||||
* parse sdp video state.
|
||||
*/
|
||||
SrsRtspSdpStateVideo,
|
||||
};
|
||||
|
||||
/**
|
||||
* 10 Method Definitions, @see rfc2326-1998-rtsp.pdf, page 57
|
||||
* 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.
|
||||
*/
|
||||
* 10 Method Definitions, @see rfc2326-1998-rtsp.pdf, page 57
|
||||
* 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,
|
||||
|
@ -132,161 +128,161 @@ enum SrsRtspMethod
|
|||
};
|
||||
|
||||
/**
|
||||
* the state of rtsp token.
|
||||
*/
|
||||
* the state of rtsp token.
|
||||
*/
|
||||
enum SrsRtspTokenState
|
||||
{
|
||||
/**
|
||||
* parse token failed, default state.
|
||||
*/
|
||||
* parse token failed, default state.
|
||||
*/
|
||||
SrsRtspTokenStateError = 100,
|
||||
/**
|
||||
* when SP follow the token.
|
||||
*/
|
||||
* when SP follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateNormal = 101,
|
||||
/**
|
||||
* when CRLF follow the token.
|
||||
*/
|
||||
* when CRLF follow the token.
|
||||
*/
|
||||
SrsRtspTokenStateEOF = 102,
|
||||
};
|
||||
|
||||
/**
|
||||
* the rtp packet.
|
||||
* 5. RTP Data Transfer Protocol, @see rfc3550-2003-rtp.pdf, page 12
|
||||
*/
|
||||
* the rtp packet.
|
||||
* 5. RTP Data Transfer Protocol, @see rfc3550-2003-rtp.pdf, page 12
|
||||
*/
|
||||
class SrsRtpPacket
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* version (V): 2 bits
|
||||
* This eld identies the version of RTP. The version dened by this specication is two (2).
|
||||
* (The value 1 is used by the rst draft version of RTP and the value 0 is used by the protocol
|
||||
* initially implemented in the \vat" audio tool.)
|
||||
*/
|
||||
* version (V): 2 bits
|
||||
* This field identifies the version of RTP. The version defined by this specification is two (2).
|
||||
* (The value 1 is used by the first draft version of RTP and the value 0 is used by the protocol
|
||||
* initially implemented in the \vat" audio tool.)
|
||||
*/
|
||||
int8_t version; //2bits
|
||||
/**
|
||||
* padding (P): 1 bit
|
||||
* If the padding bit is set, the packet contains one or more additional padding octets at the
|
||||
* end which are not part of the payload. The last octet of the padding contains a count of
|
||||
* how many padding octets should be ignored, including itself. Padding may be needed by
|
||||
* some encryption algorithms with xed block sizes or for carrying several RTP packets in a
|
||||
* lower-layer protocol data unit.
|
||||
*/
|
||||
* padding (P): 1 bit
|
||||
* If the padding bit is set, the packet contains one or more additional padding octets at the
|
||||
* end which are not part of the payload. The last octet of the padding contains a count of
|
||||
* how many padding octets should be ignored, including itself. Padding may be needed by
|
||||
* some encryption algorithms with fixed block sizes or for carrying several RTP packets in a
|
||||
* lower-layer protocol data unit.
|
||||
*/
|
||||
int8_t padding; //1bit
|
||||
/**
|
||||
* extension (X): 1 bit
|
||||
* If the extension bit is set, the xed header must be followed by exactly one header extension,
|
||||
* with a format dened in Section 5.3.1.
|
||||
*/
|
||||
* extension (X): 1 bit
|
||||
* If the extension bit is set, the fixed header must be followed by exactly one header extension,
|
||||
* with a format defined in Section 5.3.1.
|
||||
*/
|
||||
int8_t extension; //1bit
|
||||
/**
|
||||
* CSRC count (CC): 4 bits
|
||||
* The CSRC count contains the number of CSRC identiers that follow the xed header.
|
||||
*/
|
||||
* CSRC count (CC): 4 bits
|
||||
* The CSRC count contains the number of CSRC identifiers that follow the fixed header.
|
||||
*/
|
||||
int8_t csrc_count; //4bits
|
||||
/**
|
||||
* marker (M): 1 bit
|
||||
* The interpretation of the marker is dened by a prole. It is intended to allow signicant
|
||||
* events such as frame boundaries to be marked in the packet stream. A prole may dene
|
||||
* additional marker bits or specify that there is no marker bit by changing the number of bits
|
||||
* in the payload type eld (see Section 5.3).
|
||||
*/
|
||||
* marker (M): 1 bit
|
||||
* The interpretation of the marker is defined by a profile. It is intended to allow significant
|
||||
* events such as frame boundaries to be marked in the packet stream. A profile may define
|
||||
* additional marker bits or specify that there is no marker bit by changing the number of bits
|
||||
* in the payload type field (see Section 5.3).
|
||||
*/
|
||||
int8_t marker; //1bit
|
||||
/**
|
||||
* payload type (PT): 7 bits
|
||||
* This eld identies the format of the RTP payload and determines its interpretation by the
|
||||
* application. A prole may specify a default static mapping of payload type codes to payload
|
||||
* formats. Additional payload type codes may be dened dynamically through non-RTP means
|
||||
* (see Section 3). A set of default mappings for audio and video is specied in the companion
|
||||
* RFC 3551 [1]. An RTP source may change the payload type during a session, but this eld
|
||||
* should not be used for multiplexing separate media streams (see Section 5.2).
|
||||
* A receiver must ignore packets with payload types that it does not understand.
|
||||
*/
|
||||
* payload type (PT): 7 bits
|
||||
* This field identifies the format of the RTP payload and determines its interpretation by the
|
||||
* application. A profile may specify a default static mapping of payload type codes to payload
|
||||
* formats. Additional payload type codes may be defined dynamically through non-RTP means
|
||||
* (see Section 3). A set of default mappings for audio and video is specified in the companion
|
||||
* RFC 3551 [1]. An RTP source may change the payload type during a session, but this field
|
||||
* should not be used for multiplexing separate media streams (see Section 5.2).
|
||||
* A receiver must ignore packets with payload types that it does not understand.
|
||||
*/
|
||||
int8_t payload_type; //7bits
|
||||
/**
|
||||
* sequence number: 16 bits
|
||||
* The sequence number increments by one for each RTP data packet sent, and may be used
|
||||
* by the receiver to detect packet loss and to restore packet sequence. The initial value of the
|
||||
* sequence number should be random (unpredictable) to make known-plaintext attacks on
|
||||
* encryption more dicult, even if the source itself does not encrypt according to the method
|
||||
* in Section 9.1, because the packets may flow through a translator that does. Techniques for
|
||||
* choosing unpredictable numbers are discussed in [17].
|
||||
*/
|
||||
* sequence number: 16 bits
|
||||
* The sequence number increments by one for each RTP data packet sent, and may be used
|
||||
* by the receiver to detect packet loss and to restore packet sequence. The initial value of the
|
||||
* sequence number should be random (unpredictable) to make known-plaintext attacks on
|
||||
* encryption more dicult, even if the source itself does not encrypt according to the method
|
||||
* in Section 9.1, because the packets may flow through a translator that does. Techniques for
|
||||
* choosing unpredictable numbers are discussed in [17].
|
||||
*/
|
||||
uint16_t sequence_number; //16bits
|
||||
/**
|
||||
* timestamp: 32 bits
|
||||
* The timestamp reflects the sampling instant of the rst octet in the RTP data packet. The
|
||||
* sampling instant must be derived from a clock that increments monotonically and linearly
|
||||
* in time to allow synchronization and jitter calculations (see Section 6.4.1). The resolution
|
||||
* of the clock must be sucient for the desired synchronization accuracy and for measuring
|
||||
* packet arrival jitter (one tick per video frame is typically not sucient). The clock frequency
|
||||
* is dependent on the format of data carried as payload and is specied statically in the prole
|
||||
* or payload format specication that denes the format, or may be specied dynamically for
|
||||
* payload formats dened through non-RTP means. If RTP packets are generated periodically,
|
||||
* the nominal sampling instant as determined from the sampling clock is to be used, not a
|
||||
* reading of the system clock. As an example, for xed-rate audio the timestamp clock would
|
||||
* likely increment by one for each sampling period. If an audio application reads blocks covering
|
||||
* 160 sampling periods from the input device, the timestamp would be increased by 160 for
|
||||
* each such block, regardless of whether the block is transmitted in a packet or dropped as
|
||||
* silent.
|
||||
*
|
||||
* The initial value of the timestamp should be random, as for the sequence number. Several
|
||||
* consecutive RTP packets will have equal timestamps if they are (logically) generated at once,
|
||||
* e.g., belong to the same video frame. Consecutive RTP packets may contain timestamps that
|
||||
* are not monotonic if the data is not transmitted in the order it was sampled, as in the case
|
||||
* of MPEG interpolated video frames. (The sequence numbers of the packets as transmitted
|
||||
* will still be monotonic.)
|
||||
*
|
||||
* RTP timestamps from dierent media streams may advance at dierent rates and usually
|
||||
* have independent, random osets. Therefore, although these timestamps are sucient to
|
||||
* reconstruct the timing of a single stream, directly comparing RTP timestamps from dierent
|
||||
* media is not eective for synchronization. Instead, for each medium the RTP timestamp
|
||||
* is related to the sampling instant by pairing it with a timestamp from a reference clock
|
||||
* (wallclock) that represents the time when the data corresponding to the RTP timestamp was
|
||||
* sampled. The reference clock is shared by all media to be synchronized. The timestamp
|
||||
* pairs are not transmitted in every data packet, but at a lower rate in RTCP SR packets as
|
||||
* described in Section 6.4.
|
||||
*
|
||||
* The sampling instant is chosen as the point of reference for the RTP timestamp because it is
|
||||
* known to the transmitting endpoint and has a common denition for all media, independent
|
||||
* of encoding delays or other processing. The purpose is to allow synchronized presentation of
|
||||
* all media sampled at the same time.
|
||||
*
|
||||
* Applications transmitting stored data rather than data sampled in real time typically use a
|
||||
* virtual presentation timeline derived from wallclock time to determine when the next frame
|
||||
* or other unit of each medium in the stored data should be presented. In this case, the RTP
|
||||
* timestamp would reflect the presentation time for each unit. That is, the RTP timestamp for
|
||||
* each unit would be related to the wallclock time at which the unit becomes current on the
|
||||
* virtual presentation timeline. Actual presentation occurs some time later as determined by
|
||||
* the receiver.
|
||||
*
|
||||
* An example describing live audio narration of prerecorded video illustrates the signicance
|
||||
* of choosing the sampling instant as the reference point. In this scenario, the video would
|
||||
* be presented locally for the narrator to view and would be simultaneously transmitted using
|
||||
* RTP. The \sampling instant" of a video frame transmitted in RTP would be established by
|
||||
* referencing its timestamp to the wallclock time when that video frame was presented to the
|
||||
* narrator. The sampling instant for the audio RTP packets containing the narrator's speech
|
||||
* would be established by referencing the same wallclock time when the audio was sampled.
|
||||
* The audio and video may even be transmitted by dierent hosts if the reference clocks on
|
||||
* the two hosts are synchronized by some means such as NTP. A receiver can then synchronize
|
||||
* presentation of the audio and video packets by relating their RTP timestamps using the
|
||||
* timestamp pairs in RTCP SR packets.
|
||||
*/
|
||||
* timestamp: 32 bits
|
||||
* The timestamp reflects the sampling instant of the first octet in the RTP data packet. The
|
||||
* sampling instant must be derived from a clock that increments monotonically and linearly
|
||||
* in time to allow synchronization and jitter calculations (see Section 6.4.1). The resolution
|
||||
* of the clock must be sucient for the desired synchronization accuracy and for measuring
|
||||
* packet arrival jitter (one tick per video frame is typically not sucient). The clock frequency
|
||||
* is dependent on the format of data carried as payload and is specified statically in the profile
|
||||
* or payload format specification that defines the format, or may be specified dynamically for
|
||||
* payload formats defined through non-RTP means. If RTP packets are generated periodically,
|
||||
* the nominal sampling instant as determined from the sampling clock is to be used, not a
|
||||
* reading of the system clock. As an example, for fixed-rate audio the timestamp clock would
|
||||
* likely increment by one for each sampling period. If an audio application reads blocks covering
|
||||
* 160 sampling periods from the input device, the timestamp would be increased by 160 for
|
||||
* each such block, regardless of whether the block is transmitted in a packet or dropped as
|
||||
* silent.
|
||||
*
|
||||
* The initial value of the timestamp should be random, as for the sequence number. Several
|
||||
* consecutive RTP packets will have equal timestamps if they are (logically) generated at once,
|
||||
* e.g., belong to the same video frame. Consecutive RTP packets may contain timestamps that
|
||||
* are not monotonic if the data is not transmitted in the order it was sampled, as in the case
|
||||
* of MPEG interpolated video frames. (The sequence numbers of the packets as transmitted
|
||||
* will still be monotonic.)
|
||||
*
|
||||
* RTP timestamps from different media streams may advance at different rates and usually
|
||||
* have independent, random offsets. Therefore, although these timestamps are sucient to
|
||||
* reconstruct the timing of a single stream, directly comparing RTP timestamps from different
|
||||
* media is not effective for synchronization. Instead, for each medium the RTP timestamp
|
||||
* is related to the sampling instant by pairing it with a timestamp from a reference clock
|
||||
* (wallclock) that represents the time when the data corresponding to the RTP timestamp was
|
||||
* sampled. The reference clock is shared by all media to be synchronized. The timestamp
|
||||
* pairs are not transmitted in every data packet, but at a lower rate in RTCP SR packets as
|
||||
* described in Section 6.4.
|
||||
*
|
||||
* The sampling instant is chosen as the point of reference for the RTP timestamp because it is
|
||||
* known to the transmitting endpoint and has a common definition for all media, independent
|
||||
* of encoding delays or other processing. The purpose is to allow synchronized presentation of
|
||||
* all media sampled at the same time.
|
||||
*
|
||||
* Applications transmitting stored data rather than data sampled in real time typically use a
|
||||
* virtual presentation timeline derived from wallclock time to determine when the next frame
|
||||
* or other unit of each medium in the stored data should be presented. In this case, the RTP
|
||||
* timestamp would reflect the presentation time for each unit. That is, the RTP timestamp for
|
||||
* each unit would be related to the wallclock time at which the unit becomes current on the
|
||||
* virtual presentation timeline. Actual presentation occurs some time later as determined by
|
||||
* the receiver.
|
||||
*
|
||||
* An example describing live audio narration of prerecorded video illustrates the significance
|
||||
* of choosing the sampling instant as the reference point. In this scenario, the video would
|
||||
* be presented locally for the narrator to view and would be simultaneously transmitted using
|
||||
* RTP. The sampling instant" of a video frame transmitted in RTP would be established by
|
||||
* referencing its timestamp to the wallclock time when that video frame was presented to the
|
||||
* narrator. The sampling instant for the audio RTP packets containing the narrator's speech
|
||||
* would be established by referencing the same wallclock time when the audio was sampled.
|
||||
* The audio and video may even be transmitted by different hosts if the reference clocks on
|
||||
* the two hosts are synchronized by some means such as NTP. A receiver can then synchronize
|
||||
* presentation of the audio and video packets by relating their RTP timestamps using the
|
||||
* timestamp pairs in RTCP SR packets.
|
||||
*/
|
||||
uint32_t timestamp; //32bits
|
||||
/**
|
||||
* SSRC: 32 bits
|
||||
* The SSRC eld identies the synchronization source. This identier should be chosen
|
||||
* randomly, with the intent that no two synchronization sources within the same RTP session
|
||||
* will have the same SSRC identier. An example algorithm for generating a random identier
|
||||
* is presented in Appendix A.6. Although the probability of multiple sources choosing the same
|
||||
* identier is low, all RTP implementations must be prepared to detect and resolve collisions.
|
||||
* Section 8 describes the probability of collision along with a mechanism for resolving collisions
|
||||
* and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identier. If
|
||||
* a source changes its source transport address, it must also choose a new SSRC identier to
|
||||
* avoid being interpreted as a looped source (see Section 8.2).
|
||||
*/
|
||||
* SSRC: 32 bits
|
||||
* The SSRC field identifies the synchronization source. This identifier should be chosen
|
||||
* randomly, with the intent that no two synchronization sources within the same RTP session
|
||||
* will have the same SSRC identifier. An example algorithm for generating a random identifier
|
||||
* is presented in Appendix A.6. Although the probability of multiple sources choosing the same
|
||||
* identifier is low, all RTP implementations must be prepared to detect and resolve collisions.
|
||||
* Section 8 describes the probability of collision along with a mechanism for resolving collisions
|
||||
* and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identifier. If
|
||||
* a source changes its source transport address, it must also choose a new SSRC identifier to
|
||||
* avoid being interpreted as a looped source (see Section 8.2).
|
||||
*/
|
||||
uint32_t ssrc; //32bits
|
||||
|
||||
|
||||
// the payload.
|
||||
SrsSimpleStream* payload;
|
||||
// whether transport in chunked payload.
|
||||
|
@ -295,26 +291,26 @@ public:
|
|||
// normal message always completed.
|
||||
// while chunked completed when the last chunk arriaved.
|
||||
bool completed;
|
||||
|
||||
|
||||
/**
|
||||
* the audio samples, one rtp packets may contains multiple audio samples.
|
||||
*/
|
||||
* the audio samples, one rtp packets may contains multiple audio samples.
|
||||
*/
|
||||
SrsAudioFrame* audio;
|
||||
public:
|
||||
SrsRtpPacket();
|
||||
virtual ~SrsRtpPacket();
|
||||
public:
|
||||
/**
|
||||
* copy the header from src.
|
||||
*/
|
||||
* copy the header from src.
|
||||
*/
|
||||
virtual void copy(SrsRtpPacket* src);
|
||||
/**
|
||||
* reap the src to this packet, reap the payload.
|
||||
*/
|
||||
* reap the src to this packet, reap the payload.
|
||||
*/
|
||||
virtual void reap(SrsRtpPacket* src);
|
||||
/**
|
||||
* decode rtp packet from stream.
|
||||
*/
|
||||
* decode rtp packet from stream.
|
||||
*/
|
||||
virtual int decode(SrsBuffer* stream);
|
||||
private:
|
||||
virtual int decode_97(SrsBuffer* stream);
|
||||
|
@ -322,23 +318,23 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* the sdp in announce, @see rfc2326-1998-rtsp.pdf, page 159
|
||||
* Appendix C: Use of SDP for RTSP Session Descriptions
|
||||
* The Session Description Protocol (SDP, RFC 2327 [6]) may be used to
|
||||
* describe streams or presentations in RTSP.
|
||||
*/
|
||||
* the sdp in announce, @see rfc2326-1998-rtsp.pdf, page 159
|
||||
* Appendix C: Use of SDP for RTSP Session Descriptions
|
||||
* The Session Description Protocol (SDP, RFC 2327 [6]) may be used to
|
||||
* describe streams or presentations in RTSP.
|
||||
*/
|
||||
class SrsRtspSdp
|
||||
{
|
||||
private:
|
||||
SrsRtspSdpState state;
|
||||
public:
|
||||
/**
|
||||
* the version of sdp.
|
||||
*/
|
||||
* the version of sdp.
|
||||
*/
|
||||
std::string version;
|
||||
/**
|
||||
* the owner/creator of sdp.
|
||||
*/
|
||||
* the owner/creator of sdp.
|
||||
*/
|
||||
std::string owner_username;
|
||||
std::string owner_session_id;
|
||||
std::string owner_session_version;
|
||||
|
@ -346,22 +342,22 @@ public:
|
|||
std::string owner_address_type;
|
||||
std::string owner_address;
|
||||
/**
|
||||
* the session name of sdp.
|
||||
*/
|
||||
* the session name of sdp.
|
||||
*/
|
||||
std::string session_name;
|
||||
/**
|
||||
* the connection info of sdp.
|
||||
*/
|
||||
* the connection info of sdp.
|
||||
*/
|
||||
std::string connection_network_type;
|
||||
std::string connection_address_type;
|
||||
std::string connection_address;
|
||||
/**
|
||||
* the tool attribute of sdp.
|
||||
*/
|
||||
* the tool attribute of sdp.
|
||||
*/
|
||||
std::string tool;
|
||||
/**
|
||||
* the video attribute of sdp.
|
||||
*/
|
||||
* the video attribute of sdp.
|
||||
*/
|
||||
std::string video_port;
|
||||
std::string video_protocol;
|
||||
std::string video_transport_format;
|
||||
|
@ -374,8 +370,8 @@ public:
|
|||
std::string video_sps; // sequence header: sps.
|
||||
std::string video_pps; // sequence header: pps.
|
||||
/**
|
||||
* the audio attribute of sdp.
|
||||
*/
|
||||
* the audio attribute of sdp.
|
||||
*/
|
||||
std::string audio_port;
|
||||
std::string audio_protocol;
|
||||
std::string audio_transport_format;
|
||||
|
@ -396,33 +392,33 @@ public:
|
|||
virtual ~SrsRtspSdp();
|
||||
public:
|
||||
/**
|
||||
* parse a line of token for sdp.
|
||||
*/
|
||||
* parse a line of token for sdp.
|
||||
*/
|
||||
virtual int parse(std::string token);
|
||||
private:
|
||||
/**
|
||||
* generally, the fmtp is the sequence header for video or audio.
|
||||
*/
|
||||
* generally, the fmtp is the sequence header for video or audio.
|
||||
*/
|
||||
virtual int parse_fmtp_attribute(std::string attr);
|
||||
/**
|
||||
* generally, the control is the stream info for video or audio.
|
||||
*/
|
||||
* generally, the control is the stream info for video or audio.
|
||||
*/
|
||||
virtual int parse_control_attribute(std::string attr);
|
||||
/**
|
||||
* decode the string by base64.
|
||||
*/
|
||||
* decode the string by base64.
|
||||
*/
|
||||
virtual std::string base64_decode(std::string value);
|
||||
};
|
||||
|
||||
/**
|
||||
* the rtsp transport.
|
||||
* 12.39 Transport, @see rfc2326-1998-rtsp.pdf, page 115
|
||||
* This request header indicates which transport protocol is to be used
|
||||
* and configures its parameters such as destination address,
|
||||
* compression, multicast time-to-live and destination port for a single
|
||||
* stream. It sets those values not already determined by a presentation
|
||||
* description.
|
||||
*/
|
||||
* the rtsp transport.
|
||||
* 12.39 Transport, @see rfc2326-1998-rtsp.pdf, page 115
|
||||
* This request header indicates which transport protocol is to be used
|
||||
* and configures its parameters such as destination address,
|
||||
* compression, multicast time-to-live and destination port for a single
|
||||
* stream. It sets those values not already determined by a presentation
|
||||
* description.
|
||||
*/
|
||||
class SrsRtspTransport
|
||||
{
|
||||
public:
|
||||
|
@ -456,78 +452,78 @@ public:
|
|||
virtual ~SrsRtspTransport();
|
||||
public:
|
||||
/**
|
||||
* parse a line of token for transport.
|
||||
*/
|
||||
* parse a line of token for transport.
|
||||
*/
|
||||
virtual int parse(std::string attr);
|
||||
};
|
||||
|
||||
/**
|
||||
* the rtsp request message.
|
||||
* 6 Request, @see rfc2326-1998-rtsp.pdf, page 39
|
||||
* 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
|
||||
*/
|
||||
* the rtsp request message.
|
||||
* 6 Request, @see rfc2326-1998-rtsp.pdf, page 39
|
||||
* 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
|
||||
*/
|
||||
* 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).
|
||||
*/
|
||||
* 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).
|
||||
*/
|
||||
long seq;
|
||||
/**
|
||||
* 12.16 Content-Type, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* See [H14.18]. Note that the content types suitable for RTSP are
|
||||
* likely to be restricted in practice to presentation descriptions and
|
||||
* parameter-value types.
|
||||
*/
|
||||
* 12.16 Content-Type, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* See [H14.18]. Note that the content types suitable for RTSP are
|
||||
* likely to be restricted in practice to presentation descriptions and
|
||||
* parameter-value types.
|
||||
*/
|
||||
std::string content_type;
|
||||
/**
|
||||
* 12.14 Content-Length, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* This field contains the length of the content of the method (i.e.
|
||||
* after the double CRLF following the last header). Unlike HTTP, it
|
||||
* MUST be included in all messages that carry content beyond the header
|
||||
* portion of the message. If it is missing, a default value of zero is
|
||||
* assumed. It is interpreted according to [H14.14].
|
||||
*/
|
||||
* 12.14 Content-Length, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* This field contains the length of the content of the method (i.e.
|
||||
* after the double CRLF following the last header). Unlike HTTP, it
|
||||
* MUST be included in all messages that carry content beyond the header
|
||||
* portion of the message. If it is missing, a default value of zero is
|
||||
* assumed. It is interpreted according to [H14.14].
|
||||
*/
|
||||
long content_length;
|
||||
/**
|
||||
* the session id.
|
||||
*/
|
||||
* the session id.
|
||||
*/
|
||||
std::string session;
|
||||
|
||||
|
||||
/**
|
||||
* the sdp in announce, NULL for no sdp.
|
||||
*/
|
||||
* the sdp in announce, NULL for no sdp.
|
||||
*/
|
||||
SrsRtspSdp* sdp;
|
||||
/**
|
||||
* the transport in setup, NULL for no transport.
|
||||
*/
|
||||
* the transport in setup, NULL for no transport.
|
||||
*/
|
||||
SrsRtspTransport* transport;
|
||||
/**
|
||||
* for setup message, parse the stream id from uri.
|
||||
*/
|
||||
* for setup message, parse the stream id from uri.
|
||||
*/
|
||||
int stream_id;
|
||||
public:
|
||||
SrsRtspRequest();
|
||||
|
@ -540,78 +536,78 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* the rtsp response message.
|
||||
* 7 Response, @see rfc2326-1998-rtsp.pdf, page 43
|
||||
* [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
|
||||
*/
|
||||
* the rtsp response message.
|
||||
* 7 Response, @see rfc2326-1998-rtsp.pdf, page 43
|
||||
* [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
|
||||
*/
|
||||
* 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_RTSP_VERSION
|
||||
// @see about the status of rtsp, see SRS_CONSTS_RTSP_OK
|
||||
int status;
|
||||
/**
|
||||
* 12.17 CSeq, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* 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).
|
||||
*/
|
||||
* 12.17 CSeq, @see rfc2326-1998-rtsp.pdf, page 99
|
||||
* 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).
|
||||
*/
|
||||
long seq;
|
||||
/**
|
||||
* the session id.
|
||||
*/
|
||||
* the session id.
|
||||
*/
|
||||
std::string session;
|
||||
public:
|
||||
SrsRtspResponse(int cseq);
|
||||
virtual ~SrsRtspResponse();
|
||||
public:
|
||||
/**
|
||||
* encode message to string.
|
||||
*/
|
||||
* encode message to string.
|
||||
*/
|
||||
virtual int encode(std::stringstream& ss);
|
||||
protected:
|
||||
/**
|
||||
* sub classes override this to encode the headers.
|
||||
*/
|
||||
* sub classes override this to encode the headers.
|
||||
*/
|
||||
virtual int encode_header(std::stringstream& ss);
|
||||
};
|
||||
|
||||
/**
|
||||
* 10.1 OPTIONS, @see rfc2326-1998-rtsp.pdf, page 59
|
||||
* 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.
|
||||
*/
|
||||
* 10.1 OPTIONS, @see rfc2326-1998-rtsp.pdf, page 59
|
||||
* 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
|
||||
*/
|
||||
* join of SrsRtspMethod
|
||||
*/
|
||||
SrsRtspMethod methods;
|
||||
public:
|
||||
SrsRtspOptionsResponse(int cseq);
|
||||
|
@ -621,16 +617,16 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* 10.4 SETUP, @see rfc2326-1998-rtsp.pdf, page 65
|
||||
* The SETUP request for a URI specifies the transport mechanism to be
|
||||
* used for the streamed media. A client can issue a SETUP request for a
|
||||
* stream that is already playing to change transport parameters, which
|
||||
* a server MAY allow. If it does not allow this, it MUST respond with
|
||||
* error "455 Method Not Valid In This State". For the benefit of any
|
||||
* intervening firewalls, a client must indicate the transport
|
||||
* parameters even if it has no influence over these parameters, for
|
||||
* example, where the server advertises a fixed multicast address.
|
||||
*/
|
||||
* 10.4 SETUP, @see rfc2326-1998-rtsp.pdf, page 65
|
||||
* The SETUP request for a URI specifies the transport mechanism to be
|
||||
* used for the streamed media. A client can issue a SETUP request for a
|
||||
* stream that is already playing to change transport parameters, which
|
||||
* a server MAY allow. If it does not allow this, it MUST respond with
|
||||
* error "455 Method Not Valid In This State". For the benefit of any
|
||||
* intervening firewalls, a client must indicate the transport
|
||||
* parameters even if it has no influence over these parameters, for
|
||||
* example, where the server advertises a fixed multicast address.
|
||||
*/
|
||||
class SrsRtspSetupResponse : public SrsRtspResponse
|
||||
{
|
||||
public:
|
||||
|
@ -651,64 +647,64 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* the rtsp protocol stack to parse the rtsp packets.
|
||||
*/
|
||||
* the rtsp protocol stack to parse the rtsp packets.
|
||||
*/
|
||||
class SrsRtspStack
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* cached bytes buffer.
|
||||
*/
|
||||
* cached bytes buffer.
|
||||
*/
|
||||
SrsSimpleStream* buf;
|
||||
/**
|
||||
* underlayer socket object, send/recv bytes.
|
||||
*/
|
||||
* underlayer socket object, send/recv bytes.
|
||||
*/
|
||||
ISrsProtocolReaderWriter* skt;
|
||||
public:
|
||||
SrsRtspStack(ISrsProtocolReaderWriter* s);
|
||||
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.
|
||||
*/
|
||||
* 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.
|
||||
*/
|
||||
* 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.
|
||||
*/
|
||||
* recv the rtsp message.
|
||||
*/
|
||||
virtual int do_recv_message(SrsRtspRequest* req);
|
||||
/**
|
||||
* read a normal token from io, error when token state is not normal.
|
||||
*/
|
||||
* 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.
|
||||
*/
|
||||
* 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
|
||||
* @param pconsumed, output the token parsed length. NULL to ignore.
|
||||
*/
|
||||
* read the token util got eof, for example, to read the response status Reason-Phrase
|
||||
* @param pconsumed, output the token parsed length. NULL to ignore.
|
||||
*/
|
||||
virtual int recv_token_util_eof(std::string& token, int* pconsumed = NULL);
|
||||
/**
|
||||
* read a token from io, split by SP, endswith CRLF:
|
||||
* token1 SP token2 SP ... tokenN CRLF
|
||||
* @param token, output the read token.
|
||||
* @param state, output the token parse state.
|
||||
* @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 pconsumed, output the token parsed length. NULL to ignore.
|
||||
*/
|
||||
* read a token from io, split by SP, endswith CRLF:
|
||||
* token1 SP token2 SP ... tokenN CRLF
|
||||
* @param token, output the read token.
|
||||
* @param state, output the token parse state.
|
||||
* @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 pconsumed, output the token parsed length. NULL to ignore.
|
||||
*/
|
||||
virtual int recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch = SRS_RTSP_SP, int* pconsumed = NULL);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue