1
0
Fork 0
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:
winlin 2017-03-25 17:21:39 +08:00
parent 62b7204514
commit f32aab3d92
175 changed files with 15529 additions and 15935 deletions

View file

@ -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>

View file

@ -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 */

View file

@ -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;
}

View file

@ -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
*/

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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:

View file

@ -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);
}

View file

@ -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
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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>

View file

@ -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

View file

@ -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;
}

View file

@ -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 identi es the version of RTP. The version de ned by this speci cation 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 de ned 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 identi ers 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 de ned by a pro le. It is intended to allow signi cant
* events such as frame boundaries to be marked in the packet stream. A pro le may de ne
* 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 identi es the format of the RTP payload and determines its interpretation by the
* application. A pro le may specify a default static mapping of payload type codes to payload
* formats. Additional payload type codes may be de ned dynamically through non-RTP means
* (see Section 3). A set of default mappings for audio and video is speci ed 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 speci ed statically in the pro le
* or payload format speci cation that de nes the format, or may be speci ed dynamically for
* payload formats de ned 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 di erent media streams may advance at di erent rates and usually
* have independent, random o sets. Therefore, although these timestamps are sucient to
* reconstruct the timing of a single stream, directly comparing RTP timestamps from di erent
* media is not e ective 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 de nition 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 signi cance
* 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 di erent 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 identi es the synchronization source. This identi er should be chosen
* randomly, with the intent that no two synchronization sources within the same RTP session
* will have the same SSRC identi er. An example algorithm for generating a random identi er
* is presented in Appendix A.6. Although the probability of multiple sources choosing the same
* identi er 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 identi er. If
* a source changes its source transport address, it must also choose a new SSRC identi er 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);
};