diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 933fca7c6..aa350dc0f 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -60,6 +60,8 @@ SRS_ARM_UBUNTU12=NO SRS_MIPS_UBUNTU12=NO # dev, open all features for dev, no gperf/prof/arm. SRS_DEV=NO +# dev, open main server feature for dev, no bwtc/utest/research/librtmp +SRS_FAST_DEV=NO # raspberry-pi, open hls/ssl/static SRS_PI=NO # cubieboard, donot open ffmpeg/nginx. @@ -151,6 +153,7 @@ Presets: --rtmp-hls only support RTMP+HLS with ssl. --disable-all disable all features, only support vp6 RTMP. --dev for dev, open all features, no nginx/gperf/gprof/arm. + --fast-dev for dev fast compile, the RTMP server, without bwtc/librtmp/utest/research. --full enable all features, no gperf/gprof/arm. Conflicts: @@ -232,6 +235,7 @@ function parse_user_option() { --pi) SRS_PI=YES ;; --cubie) SRS_CUBIE=YES ;; --dev) SRS_DEV=YES ;; + --fast-dev) SRS_FAST_DEV=YES ;; --fast) SRS_FAST=YES ;; --disable-all) SRS_DISABLE_ALL=YES ;; --pure-rtmp) SRS_PURE_RTMP=YES ;; @@ -282,12 +286,14 @@ function apply_user_presets() { if [ $SRS_DISABLE_ALL = NO ]; then if [ $SRS_ENABLE_ALL = NO ]; then if [ $SRS_DEV = NO ]; then - if [ $SRS_ARM_UBUNTU12 = NO ]; then - if [ $SRS_MIPS_UBUNTU12 = NO ]; then - if [ $SRS_PI = NO ]; then - if [ $SRS_CUBIE = NO ]; then - if [ $SRS_X86_X64 = NO ]; then - SRS_X86_X64=YES; opt="--x86-x64 $opt"; + if [ $SRS_FAST_DEV = NO ]; then + if [ $SRS_ARM_UBUNTU12 = NO ]; then + if [ $SRS_MIPS_UBUNTU12 = NO ]; then + if [ $SRS_PI = NO ]; then + if [ $SRS_CUBIE = NO ]; then + if [ $SRS_X86_X64 = NO ]; then + SRS_X86_X64=YES; opt="--x86-x64 $opt"; + fi fi fi fi @@ -534,6 +540,31 @@ function apply_user_presets() { SRS_STATIC=NO fi + # if fast dev specified, open main server features. + if [ $SRS_FAST_DEV = YES ]; then + SRS_HLS=YES + SRS_DVR=YES + SRS_NGINX=NO + SRS_SSL=YES + SRS_FFMPEG_TOOL=NO + SRS_TRANSCODE=YES + SRS_INGEST=YES + SRS_HTTP_PARSER=YES + SRS_HTTP_CALLBACK=YES + SRS_HTTP_SERVER=YES + SRS_HTTP_API=YES + SRS_LIBRTMP=NO + SRS_BWTC=NO + SRS_RESEARCH=NO + SRS_UTEST=NO + SRS_GPERF=NO + SRS_GPERF_MC=NO + SRS_GPERF_MP=NO + SRS_GPERF_CP=NO + SRS_GPROF=NO + SRS_STATIC=NO + fi + # if raspberry-pi specified, open ssl/hls/static features if [ $SRS_PI = YES ]; then SRS_HLS=YES diff --git a/trunk/scripts/test_configure.sh b/trunk/scripts/test_configure.sh index 8a1a8507c..befba6257 100755 --- a/trunk/scripts/test_configure.sh +++ b/trunk/scripts/test_configure.sh @@ -182,6 +182,12 @@ ok_msg "test \" ${item} \"" ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi ok_msg "test \" ${item} \" success" +item="./configure --fast-dev" +ok_msg "test \" ${item} \"" +(./configure --dev && make) >>$log 2>&1 +ret=$?; if [[ $ret -ne 0 ]]; then failed_msg "test \" ${item} \" failed. ret=$ret"; exit $ret; fi +ok_msg "test \" ${item} \" success" + item="./configure --full" ok_msg "test \" ${item} \"" (./configure --dev && make) >>$log 2>&1 diff --git a/trunk/src/app/srs_app_edge.cpp b/trunk/src/app/srs_app_edge.cpp index c50a7cea8..501f097ab 100644 --- a/trunk/src/app/srs_app_edge.cpp +++ b/trunk/src/app/srs_app_edge.cpp @@ -129,7 +129,7 @@ int SrsEdgeIngester::cycle() srs_error("handshake with server failed. ret=%d", ret); return ret; } - if ((ret = client->connect_app(req->app, req->tcUrl)) != ERROR_SUCCESS) { + if ((ret = client->connect_app(req->app, req->tcUrl, req)) != ERROR_SUCCESS) { srs_error("connect with server failed, tcUrl=%s. ret=%d", req->tcUrl.c_str(), ret); return ret; } diff --git a/trunk/src/app/srs_app_edge.hpp b/trunk/src/app/srs_app_edge.hpp index acaf346fa..a5d0e2997 100644 --- a/trunk/src/app/srs_app_edge.hpp +++ b/trunk/src/app/srs_app_edge.hpp @@ -165,6 +165,11 @@ public: SrsPlayEdge(); virtual ~SrsPlayEdge(); public: + /** + * always use the req of source, + * for we assume all client to edge is invalid, + * if auth open, edge must valid it from origin, then service it. + */ virtual int initialize(SrsSource* source, SrsRequest* req); /** * when client play stream on edge. diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 615d7230d..55412e019 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -146,10 +146,10 @@ int SrsRtmpConn::do_cycle() srs_verbose("check vhost success."); srs_trace("connect app, " - "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s", + "tcUrl=%s, pageUrl=%s, swfUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, args=%s", req->tcUrl.c_str(), req->pageUrl.c_str(), req->swfUrl.c_str(), req->schema.c_str(), req->vhost.c_str(), req->port.c_str(), - req->app.c_str()); + req->app.c_str(), (req->args? "(obj)":"null")); ret = service_cycle(); http_hooks_on_close(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 547ce466b..bd6dcaaa8 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "0" #define VERSION_MINOR "9" -#define VERSION_REVISION "127" +#define VERSION_REVISION "128" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 018ce2a4c..39dd99230 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -915,94 +915,15 @@ void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value) obj->append(any); } -void __srs_fill_level_spaces(stringstream& ss, int level) -{ - for (int i = 0; i < level; i++) { - ss << " "; - } -} -void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level) -{ - if (any->is_boolean()) { - ss << "Boolean " << (any->to_boolean()? "true":"false") << endl; - } else if (any->is_number()) { - ss << "Number " << std::fixed << any->to_number() << endl; - } else if (any->is_string()) { - ss << "String " << any->to_str() << endl; - } else if (any->is_null()) { - ss << "Null" << endl; - } else if (any->is_ecma_array()) { - SrsAmf0EcmaArray* obj = any->to_ecma_array(); - ss << "EcmaArray " << "(" << obj->count() << " items)" << endl; - for (int i = 0; i < obj->count(); i++) { - __srs_fill_level_spaces(ss, level + 1); - ss << "Elem '" << obj->key_at(i) << "' "; - if (obj->value_at(i)->is_complex_object()) { - __srs_amf0_do_print(obj->value_at(i), ss, level + 1); - } else { - __srs_amf0_do_print(obj->value_at(i), ss, 0); - } - } - } else if (any->is_strict_array()) { - SrsAmf0StrictArray* obj = any->to_strict_array(); - ss << "StrictArray " << "(" << obj->count() << " items)" << endl; - for (int i = 0; i < obj->count(); i++) { - __srs_fill_level_spaces(ss, level + 1); - ss << "Elem "; - if (obj->at(i)->is_complex_object()) { - __srs_amf0_do_print(obj->at(i), ss, level + 1); - } else { - __srs_amf0_do_print(obj->at(i), ss, 0); - } - } - } else if (any->is_object()) { - SrsAmf0Object* obj = any->to_object(); - ss << "Object " << "(" << obj->count() << " items)" << endl; - for (int i = 0; i < obj->count(); i++) { - __srs_fill_level_spaces(ss, level + 1); - ss << "Property '" << obj->key_at(i) << "' "; - if (obj->value_at(i)->is_complex_object()) { - __srs_amf0_do_print(obj->value_at(i), ss, level + 1); - } else { - __srs_amf0_do_print(obj->value_at(i), ss, 0); - } - } - } else { - ss << "Unknown" << endl; - } -} - char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) { if (!amf0) { return NULL; } - stringstream ss; - - ss.precision(1); - SrsAmf0Any* any = (SrsAmf0Any*)amf0; - __srs_amf0_do_print(any, ss, 0); - - string str = ss.str(); - if (str.empty()) { - return NULL; - } - - char* data = new char[str.length() + 1]; - memcpy(data, str.data(), str.length()); - data[str.length()] = 0; - - if (pdata) { - *pdata = data; - } - if (psize) { - *psize = str.length(); - } - - return data; + return any->human_print(pdata, psize); } #ifdef __cplusplus diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index d5bf52f98..d85da62af 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -244,9 +244,9 @@ srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index); void srs_amf0_strict_array_append(srs_amf0_t amf0, srs_amf0_t value); /** * human readable print -* @param pdata, output the heap data, +* @param pdata, output the heap data, NULL to ignore. * user must use srs_amf0_free_bytes to free it. -* @return return the *pdata for print. +* @return return the *pdata for print. NULL to ignore. */ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); diff --git a/trunk/src/rtmp/srs_protocol_amf0.cpp b/trunk/src/rtmp/srs_protocol_amf0.cpp index bba998a5b..aa0dc8d1c 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.cpp +++ b/trunk/src/rtmp/srs_protocol_amf0.cpp @@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include using namespace std; #include @@ -330,6 +331,90 @@ bool SrsAmf0Any::is_object_eof() return marker == RTMP_AMF0_ObjectEnd; } +void __srs_fill_level_spaces(stringstream& ss, int level) +{ + for (int i = 0; i < level; i++) { + ss << " "; + } +} +void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level) +{ + if (any->is_boolean()) { + ss << "Boolean " << (any->to_boolean()? "true":"false") << endl; + } else if (any->is_number()) { + ss << "Number " << std::fixed << any->to_number() << endl; + } else if (any->is_string()) { + ss << "String " << any->to_str() << endl; + } else if (any->is_null()) { + ss << "Null" << endl; + } else if (any->is_ecma_array()) { + SrsAmf0EcmaArray* obj = any->to_ecma_array(); + ss << "EcmaArray " << "(" << obj->count() << " items)" << endl; + for (int i = 0; i < obj->count(); i++) { + __srs_fill_level_spaces(ss, level + 1); + ss << "Elem '" << obj->key_at(i) << "' "; + if (obj->value_at(i)->is_complex_object()) { + __srs_amf0_do_print(obj->value_at(i), ss, level + 1); + } else { + __srs_amf0_do_print(obj->value_at(i), ss, 0); + } + } + } else if (any->is_strict_array()) { + SrsAmf0StrictArray* obj = any->to_strict_array(); + ss << "StrictArray " << "(" << obj->count() << " items)" << endl; + for (int i = 0; i < obj->count(); i++) { + __srs_fill_level_spaces(ss, level + 1); + ss << "Elem "; + if (obj->at(i)->is_complex_object()) { + __srs_amf0_do_print(obj->at(i), ss, level + 1); + } else { + __srs_amf0_do_print(obj->at(i), ss, 0); + } + } + } else if (any->is_object()) { + SrsAmf0Object* obj = any->to_object(); + ss << "Object " << "(" << obj->count() << " items)" << endl; + for (int i = 0; i < obj->count(); i++) { + __srs_fill_level_spaces(ss, level + 1); + ss << "Property '" << obj->key_at(i) << "' "; + if (obj->value_at(i)->is_complex_object()) { + __srs_amf0_do_print(obj->value_at(i), ss, level + 1); + } else { + __srs_amf0_do_print(obj->value_at(i), ss, 0); + } + } + } else { + ss << "Unknown" << endl; + } +} + +char* SrsAmf0Any::human_print(char** pdata, int* psize) +{ + stringstream ss; + + ss.precision(1); + + __srs_amf0_do_print(this, ss, 0); + + string str = ss.str(); + if (str.empty()) { + return NULL; + } + + char* data = new char[str.length() + 1]; + memcpy(data, str.data(), str.length()); + data[str.length()] = 0; + + if (pdata) { + *pdata = data; + } + if (psize) { + *psize = str.length(); + } + + return data; +} + SrsAmf0Any* SrsAmf0Any::str(const char* value) { return new __SrsAmf0String(value); diff --git a/trunk/src/rtmp/srs_protocol_amf0.hpp b/trunk/src/rtmp/srs_protocol_amf0.hpp index 549eb174a..016e7b526 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.hpp +++ b/trunk/src/rtmp/srs_protocol_amf0.hpp @@ -151,6 +151,14 @@ public: virtual int read(SrsStream* stream) = 0; virtual int write(SrsStream* stream) = 0; virtual SrsAmf0Any* copy() = 0; +public: + /** + * human readable print + * @param pdata, output the heap data, NULL to ignore. + * user must use srs_amf0_free_bytes to free it. + * @return return the *pdata for print. NULL to ignore. + */ + virtual char* human_print(char** pdata, int* psize); public: static SrsAmf0Any* str(const char* value = NULL); static SrsAmf0Any* boolean(bool value = false); diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp index e888bbb80..98d669d3a 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp @@ -78,10 +78,12 @@ SrsRequest::SrsRequest() { objectEncoding = RTMP_SIG_AMF0_VER; duration = -1; + args = NULL; } SrsRequest::~SrsRequest() { + srs_freep(args); } SrsRequest* SrsRequest::copy() @@ -99,6 +101,9 @@ SrsRequest* SrsRequest::copy() cp->tcUrl = tcUrl; cp->vhost = vhost; cp->duration = duration; + if (args) { + cp->args = args->copy()->to_object(); + } return cp; } @@ -451,7 +456,7 @@ int SrsRtmpClient::complex_handshake() return ret; } -int SrsRtmpClient::connect_app(string app, string tc_url) +int SrsRtmpClient::connect_app(string app, string tc_url, SrsRequest* req) { int ret = ERROR_SUCCESS; @@ -461,16 +466,29 @@ int SrsRtmpClient::connect_app(string app, string tc_url) pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); pkt->command_object->set("flashVer", SrsAmf0Any::str("WIN 12,0,0,41")); - pkt->command_object->set("swfUrl", SrsAmf0Any::str()); + if (req) { + pkt->command_object->set("swfUrl", SrsAmf0Any::str(req->swfUrl.c_str())); + } else { + pkt->command_object->set("swfUrl", SrsAmf0Any::str()); + } pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); pkt->command_object->set("fpad", SrsAmf0Any::boolean(false)); pkt->command_object->set("capabilities", SrsAmf0Any::number(239)); pkt->command_object->set("audioCodecs", SrsAmf0Any::number(3575)); pkt->command_object->set("videoCodecs", SrsAmf0Any::number(252)); pkt->command_object->set("videoFunction", SrsAmf0Any::number(1)); - pkt->command_object->set("pageUrl", SrsAmf0Any::str()); + if (req) { + pkt->command_object->set("pageUrl", SrsAmf0Any::str(req->pageUrl.c_str())); + } else { + pkt->command_object->set("pageUrl", SrsAmf0Any::str()); + } pkt->command_object->set("objectEncoding", SrsAmf0Any::number(0)); + if (req && req->args) { + srs_freep(pkt->args); + pkt->args = req->args->copy()->to_object(); + } + if ((ret = protocol->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { return ret; } @@ -825,6 +843,12 @@ int SrsRtmpServer::connect_app(SrsRequest* req) req->objectEncoding = prop->to_number(); } + if (pkt->args) { + srs_freep(req->args); + req->args = pkt->args->copy()->to_object(); + srs_info("copy edge traverse to origin auth args."); + } + srs_info("get connect app message params success."); return req->discovery_app(); diff --git a/trunk/src/rtmp/srs_protocol_rtmp.hpp b/trunk/src/rtmp/srs_protocol_rtmp.hpp index 37c5d7984..0979b8be0 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.hpp @@ -43,6 +43,7 @@ class SrsOnMetaDataPacket; class SrsPlayPacket; class SrsMessage; class SrsPacket; +class SrsAmf0Object; /** * the original request from client. @@ -74,6 +75,11 @@ public: // in ms. double duration; + // the token in the connect request, + // used for edge traverse to origin authentication, + // @see https://github.com/winlinvip/simple-rtmp-server/issues/104 + SrsAmf0Object* args; + SrsRequest(); virtual ~SrsRequest(); @@ -173,7 +179,10 @@ public: virtual int simple_handshake(); // only use complex handshake virtual int complex_handshake(); - virtual int connect_app(std::string app, std::string tc_url); + // set req to use the original request of client: + // pageUrl and swfUrl for refer antisuck. + // args for edge to origin traverse auth, @see SrsRequest.args + virtual int connect_app(std::string app, std::string tc_url, SrsRequest* req=NULL); virtual int create_stream(int& stream_id); virtual int play(std::string stream, int stream_id); // flash publish schema: diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp index f5a2cdef2..ebba78217 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp @@ -1749,11 +1749,14 @@ SrsConnectAppPacket::SrsConnectAppPacket() command_name = RTMP_AMF0_COMMAND_CONNECT; transaction_id = 1; command_object = SrsAmf0Any::object(); + // optional + args = NULL; } SrsConnectAppPacket::~SrsConnectAppPacket() { srs_freep(command_object); + srs_freep(args); } int SrsConnectAppPacket::decode(SrsStream* stream) @@ -1789,6 +1792,15 @@ int SrsConnectAppPacket::decode(SrsStream* stream) return ret; } + if (!stream->empty()) { + srs_freep(args); + args = SrsAmf0Any::object(); + if ((ret = args->read(stream)) != ERROR_SUCCESS) { + srs_error("amf0 decode connect args failed. ret=%d", ret); + return ret; + } + } + srs_info("amf0 decode connect packet success"); return ret; @@ -1806,8 +1818,16 @@ int SrsConnectAppPacket::get_message_type() int SrsConnectAppPacket::get_size() { - return SrsAmf0Size::str(command_name) + SrsAmf0Size::number() - + SrsAmf0Size::object(command_object); + int size = 0; + + size += SrsAmf0Size::str(command_name); + size += SrsAmf0Size::number(); + size += SrsAmf0Size::object(command_object); + if (args) { + size += SrsAmf0Size::object(args); + } + + return size; } int SrsConnectAppPacket::encode_packet(SrsStream* stream) @@ -1832,6 +1852,12 @@ int SrsConnectAppPacket::encode_packet(SrsStream* stream) } srs_verbose("encode command_object success."); + if (args && (ret = args->write(stream)) != ERROR_SUCCESS) { + srs_error("encode args failed. ret=%d", ret); + return ret; + } + srs_verbose("encode args success."); + srs_info("encode connect app request packet success."); return ret; diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp index 7222aebde..ebdc57581 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.hpp @@ -486,6 +486,11 @@ public: * so, directly use it, never alloc again. */ SrsAmf0Object* command_object; + /** + * Object + * Any optional information + */ + SrsAmf0Object* args; public: SrsConnectAppPacket(); virtual ~SrsConnectAppPacket();