From 632255f08f8c5b88613f1889965f24d73744607d Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 21 Dec 2013 21:13:55 +0800 Subject: [PATCH] update the signature, when connect to server, parse the response. --- trunk/research/players/js/srs.js | 2 +- .../players/srs_player/release/srs_player.swf | Bin 5138 -> 5260 bytes .../players/srs_player/src/srs_player.as | 12 + .../srs_publisher/release/srs_publisher.swf | Bin 4244 -> 4435 bytes .../srs_publisher/src/srs_publisher.as | 13 + trunk/src/core/srs_core_rtmp.cpp | 2315 +++++++++-------- 6 files changed, 1184 insertions(+), 1158 deletions(-) mode change 100644 => 100755 trunk/src/core/srs_core_rtmp.cpp diff --git a/trunk/research/players/js/srs.js b/trunk/research/players/js/srs.js index e76ab2b9e..ceaf46150 100755 --- a/trunk/research/players/js/srs.js +++ b/trunk/research/players/js/srs.js @@ -90,7 +90,7 @@ function srs_get_player_width() { return srs_get_player_modal() - 30; } function srs_get_player_height() { return srs_get_player_width() * 9 / 19; } // to query the swf anti cache. -function srs_get_version_code() { return "1.0"; } +function srs_get_version_code() { return "1.1"; } /** * initialize the page. diff --git a/trunk/research/players/srs_player/release/srs_player.swf b/trunk/research/players/srs_player/release/srs_player.swf index 9db9c8ac66a2154ead01c6edde69a62061db7917..389ffd88ebe2127d7f4d6115b4c6ee23de81b0e8 100755 GIT binary patch literal 5260 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 SYW%J|^}qF9K>rV}i9GAk4{PlJ literal 5138 zcmV+t6z%InS5poVApih)0ex8ud|XwTKi|D~=4K|(CTUt)paX=Klr)*ivk7g?&}2$W zUo>e;u*3Au%)OauCo^&GojlY+XaNNZii^dqptZaNp@8E0)>Tkf9y&>FadlNza6wnM zSA6U$y50Xdck-&;=Jz}IJKyts=lj0%os(pYDZgN>>`}%R6YE)U0b}gus+WkdHQBh) zxxFXk8yiZc%}!uzS0pTJxU;cwbab>~w7DUZ9c&DAbaXWOn;M&%RzYHwIi9w(u~ljF zvK3vzK#y+5vdLj9nMwP&K`oleS!-9UC|HfhW{eK!vMFIQ9&6N7`jDQs%*H@N0EXhR zP9u{Y(yT6RcsP}eY1~}n*eWxTiR~NJM)XxiN;4B{8fOK$j+L}hdRH)>iR!*kN+0vJ z_=2|NS$bEG9`iK?>U~ZAK(pfpr><$_ z(VY|R0tE@|Vr3P%3$|=swJq4!w`=S69+odhmgoKSRJ-Nsw5Zs;B zOZs#&~2Gs}kbcv6cD>6RAPEX~!Q9MZGJBHax+E15Ej9RZ8e z-F?H^q@|ZS?0C}TOO(elX)BvaMGP}Cq?!9%riJ*rdPh)TC61)d=Vn>3r>D0k(!Vv* z*B@NpTVsx!mOd28q$6599xQoyz)%MVwwrW~ChI6(rGLnqznc{Vbpgv}8*3-G7Lg;0zkE*HlSI?_~PNy(x=M#IJ z0&yJTd(@K1=d$@i8?ei)7PFEgx+A!BK7XE(3mu*=>ZwzNmGd<#hOXe+YewKGGUHT! z1g#)GUJ2^iq*;8r?ibFJnx@XNCF*~^EkW{%1LGvPf5Yb9?d7v&Ed=;+$XZ@gx40yl zbLFf678O3$%?1~3Fgb#T(>W_O_jD*DnPhxH?-*j1)>0yNh8EMy3UMjWJ=%ztOli@S z?y?YDeeqt?m(Ex|u~@y&%8vU|SR>ouj)+*5z!8*wN+89&jDbY8*go)0D>FR9=ZFd& z4OLt^qr|bI2)1J8hV-&&vV*!Jk+_yEo+e@rNdyDkqH3Dxpb<0qUT%hCQESGGgDTv; z%g-AoSQGmzaT=Cs0UNr^0lp*xfP-4^!|~5#b)QI$Pt;Mv5`-pcjQbEIUh8vN3P(z! zIm6JioAmUcmALf0J_y~S>GCO#;Ur~-#EF$N(Y;Cx9ie>AVdorAU)J0v8on!-&1&Or zbe9o5Thu2&r%xHqnF-MhvPtxnOtzF8D9k&3iz1Oh1Wfc15y1!+!uglsr+YM+P9@WI zJa#;rzQ3<~pMgTr;|)IU+S>C6czRo2-twI0SQClpV|pxS=@HS_c(RbImIopsI#WTE?1=%-iv!SGLAECKh`T~3h^+N9u6!(^`+cyU{ zEkDoFb6T=Xl(_F4!qY`71l&%MUveHfM?y~LhUB=OE)m;Ah$0}&BH&zn9vhIClWEJ9 z)lr8kx_Jx{EfuD4=?ZH3G*;lAYoF7u&pB`IK9o{=u-GZ_2(MqYYmvC}Bosv|NxZak{P#bpg z3$vjI&ZSK}Qr9K$p3~>F)afEE6DpdOGevJM*3y~u_z*7R+NNr-aE8)2C9qIf=c0MU zh62B#FBgmHrscQj5yQR0Ezis+=^vQT^EBwM$lj*oV zw$)JhokWerct_(B7bLfti=sWb#Fh$AE)gkrWHcGK5-#yoBMCh@n6TUqDAz1YizR0L zF^BLJNFayk1o5mk8i}TG)Fb@74`wsDbi5Rq63GzDdYy*21+Rsf7Rz0$^%sc>g5Pd2 z8FfIS3I{T4`K*kOi}}DuPpbEguEi&@wscZAp%9`7A-$bvsYAsz@X^jCZa+r(rgobD4Q}x7#aTBj_XD;o#aOV6_y&7hcl+!zPedn-P$U51pIPG+iE4? zZwn}aKx-R59nDIhsSTfIKhPF`3qGy*v^IC(!?|rOt@v~_DS`GDsCBgXm8O;^ztZCO zw<@iHmUgAJy`x=eZ)$E*+S>wc%IYQvuWoH?Q9Asq{Ypn$b3p0nXkP6K_?ucec@za{~6<(7|&z80NL*V{s1G7F@TQ9?^c?a zpj$`^?CiUfCT^z>5CyKkhb9gY3*3ia{sR)s?2)+Y9_c`(0=d5Hzd;9%(P!u>f|T!D zT{fyfS)+v-yHB$ z2mH(dKX<@u4)}Km{K5gRJKzlm{L%sc;ea0srNI(+;p5 z@H+>*?SS7q;13S?qXYirfd6*D|2W{!4)}`$-k}Kzo4!R7n?4}XouqiYj4rF~W;;tt zh%I*@UEx4!r32*=2P&i8tWT23HReF~bq-XwJFuwVk@M_uaPRJJHV(VRUENFrEE(u# z`v6O+oB0@($=yfw6s0QO6kJZAX`8etq-zFx_D!dRnf8yK~_z^gA`;7 z>5^=a)zGE*tI{HDzlWG~S?yv*ROFHK{`DZsK6DO!wsdr>T8HsL#E@0hB;GIR+YuJpp+o#9LC8#i7`vOSQWGA`3`{U=&i&p*|$;NSP5fLFy6&K-J!KgoqapOu1j%wyno`6I7HmC z#tzYGisCXjO)=>RzH#|cvhSw+q(=6KDIBafHU?=YODTKP`4&$(|1 zy)Tpf6@=MsTzj|@e`&VA%Cj&kvhXz|<(q=HDZJU(Y*bZOLf~7RBJeHRrV8%f3p11| zZIk^SzDyBrL9Y+Xyo6=!mm$zKB96r?d>YyccYeU-JkxSNrxZy?2q>+D}rek!ruev^3hZz!CZx43e#1mzV_ep@KtPV8+c z<8FML?B8?ce)|txd58T+E?&Yzv>f8^2yxts?~wgh$2Fd{zwzm$w#z=lrAsC3bPuF& zm9T@`q`WaOQpw|VyM&H15V`^7^Z_aF(+2E2z(g1pfO#jMhTe_s-Nkub_T3=tc6j&j zso;Hx^LE?!N?50ik=N_SIuCQKT$YN9J9+DSRs!v_5|Z{&q(5xjcvR%>IY}V(_fvH# z*898^j)cjePz3ILiCd^pT3T=@}c*UD2kK}U!lk#y#}Z3y4VA%v)sJtEnUa@!v# zouz2j{NoUD@cIX+O2GrTM~>EiiH_!t(WCWW=5WlZ zjH6OM)Q-YCCgsE98^;+6>>*xpA~O&3nGx$Q)7~p816bI}OGP0sKY*Jln#l`q8F{Yc z3%w6HSpjqk5?H;K;ZtA8iG+>XC%7E6U0l>Yi7>egMmt%GNqsEMs#5A)*n(&>p-vB}o;7z+2PW)1u1i{#^ z?YG|)tm8ARw;a|@+D-Ovgo&GLSsB;)EoTfEH$&&NU`(L$%6L1q9nJ(n=l9a&HH=lM zc<=p%`}gO9e`k=N38Dis?@Q7_+5QV`^dBBsIkEunm%6;Mqm~^XspMzn9h{XjNCUq( zPTB|Lym6g*%039V-F(%)O`bx*^Ec1!@}zMSI3EP%Of`4$4#>ETTL{EM@`-}j-4NRk z#Sekvh<#Xy9Uu_z!?eHt+f;oKV?2O|3oIVN`wP~b5I!L1r*I$bho{GC;}2o!!i+C@ z04e1QhYpgv&VEov2dU;E_!tktF+BMA=Gnty^YjQnOnMBx3JY9kp0pnU+zy`~lc#UX z$K}a__fN5 zcwW6BD4{zDP2x?=U65Y|4M+a10tFUkG=5c}IXb`QE-aGpi@?=+{z9oii}o2lfA}sk z?jnEq5E+L6?k3}IfP2We2S70t@wuK|Bz_Wi^1M~UQh61A%bfdP>u#X`2mg!p@XbUq A`Tzg` diff --git a/trunk/research/players/srs_player/src/srs_player.as b/trunk/research/players/srs_player/src/srs_player.as index c1cc708fd..5802fb317 100755 --- a/trunk/research/players/srs_player/src/srs_player.as +++ b/trunk/research/players/srs_player/src/srs_player.as @@ -293,6 +293,18 @@ package this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void { trace ("NetConnection: code=" + evt.info.code); + if (evt.info.hasOwnProperty("data") && evt.info.data) { + // for context menu + var customItems:Array = [new ContextMenuItem("SrsPlayer")]; + if (evt.info.data.hasOwnProperty("srs_server")) { + customItems.push(new ContextMenuItem("Server: " + evt.info.data.srs_server)); + } + if (evt.info.data.hasOwnProperty("srs_contributor")) { + customItems.push(new ContextMenuItem("Contributor: " + evt.info.data.srs_contributor)); + } + contextMenu.customItems = customItems; + } + // TODO: FIXME: failed event. if (evt.info.code != "NetConnection.Connect.Success") { return; diff --git a/trunk/research/players/srs_publisher/release/srs_publisher.swf b/trunk/research/players/srs_publisher/release/srs_publisher.swf index b0f1b7bbe0f2f627cda5b7bdf6ce69980e75364d..382bf3c83cead9ad87076af60b52a4fc47143bf3 100755 GIT binary patch literal 4435 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 Z{+GNRB}1qvRQvw_vKb_V{4W@K@fP%tz%2j( literal 4244 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 diff --git a/trunk/research/players/srs_publisher/src/srs_publisher.as b/trunk/research/players/srs_publisher/src/srs_publisher.as index 194972b85..cc9dc9508 100755 --- a/trunk/research/players/srs_publisher/src/srs_publisher.as +++ b/trunk/research/players/srs_publisher/src/srs_publisher.as @@ -14,6 +14,7 @@ package import flash.net.NetConnection; import flash.net.NetStream; import flash.ui.ContextMenu; + import flash.ui.ContextMenuItem; import flash.utils.setTimeout; public class srs_publisher extends Sprite @@ -159,6 +160,18 @@ package this.media_conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void { trace ("NetConnection: code=" + evt.info.code); + if (evt.info.hasOwnProperty("data") && evt.info.data) { + // for context menu + var customItems:Array = [new ContextMenuItem("SrsPlayer")]; + if (evt.info.data.hasOwnProperty("srs_server")) { + customItems.push(new ContextMenuItem("Server: " + evt.info.data.srs_server)); + } + if (evt.info.data.hasOwnProperty("srs_contributor")) { + customItems.push(new ContextMenuItem("Contributor: " + evt.info.data.srs_contributor)); + } + contextMenu.customItems = customItems; + } + // TODO: FIXME: failed event. if (evt.info.code != "NetConnection.Connect.Success") { return; diff --git a/trunk/src/core/srs_core_rtmp.cpp b/trunk/src/core/srs_core_rtmp.cpp old mode 100644 new mode 100755 index ba70ec643..2db58dc2b --- a/trunk/src/core/srs_core_rtmp.cpp +++ b/trunk/src/core/srs_core_rtmp.cpp @@ -1,1157 +1,1158 @@ -/* -The MIT License (MIT) - -Copyright (c) 2013 winlin - -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 - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -/** -* the signature for packets to client. -*/ -#define RTMP_SIG_FMS_VER "3,5,3,888" -#define RTMP_SIG_AMF0_VER 0 -#define RTMP_SIG_CLIENT_ID "ASAICiss" - -/** -* onStatus consts. -*/ -#define StatusLevel "level" -#define StatusCode "code" -#define StatusDescription "description" -#define StatusDetails "details" -#define StatusClientId "clientid" -// status value -#define StatusLevelStatus "status" -// code value -#define StatusCodeConnectSuccess "NetConnection.Connect.Success" -#define StatusCodeStreamReset "NetStream.Play.Reset" -#define StatusCodeStreamStart "NetStream.Play.Start" -#define StatusCodeStreamPause "NetStream.Pause.Notify" -#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" -#define StatusCodePublishStart "NetStream.Publish.Start" -#define StatusCodeDataStart "NetStream.Data.Start" -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" - -// FMLE -#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" -#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" - -// default stream id for response the createStream request. -#define SRS_DEFAULT_SID 1 - -SrsRequest::SrsRequest() -{ - objectEncoding = RTMP_SIG_AMF0_VER; -} - -SrsRequest::~SrsRequest() -{ -} - -SrsRequest* SrsRequest::copy() -{ - SrsRequest* cp = new SrsRequest(); - - cp->app = app; - cp->objectEncoding = objectEncoding; - cp->pageUrl = pageUrl; - cp->port = port; - cp->schema = schema; - cp->stream = stream; - cp->swfUrl = swfUrl; - cp->tcUrl = tcUrl; - cp->vhost = vhost; - - return cp; -} - -int SrsRequest::discovery_app() -{ - int ret = ERROR_SUCCESS; - - size_t pos = std::string::npos; - std::string url = tcUrl; - - if ((pos = url.find("://")) != std::string::npos) { - schema = url.substr(0, pos); - url = url.substr(schema.length() + 3); - srs_verbose("discovery schema=%s", schema.c_str()); - } - - if ((pos = url.find("/")) != std::string::npos) { - vhost = url.substr(0, pos); - url = url.substr(vhost.length() + 1); - srs_verbose("discovery vhost=%s", vhost.c_str()); - } - - port = RTMP_DEFAULT_PORTS; - if ((pos = vhost.find(":")) != std::string::npos) { - port = vhost.substr(pos + 1); - vhost = vhost.substr(0, pos); - srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); - } - - app = url; - srs_vhost_resolve(vhost, app); - - // resolve the vhost from config - SrsConfDirective* parsed_vhost = config->get_vhost(vhost); - if (parsed_vhost) { - vhost = parsed_vhost->arg0(); - } - - // TODO: discovery the params of vhost. - - srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", - schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); - - if (schema.empty() || vhost.empty() || port.empty() || app.empty()) { - ret = ERROR_RTMP_REQ_TCURL; - srs_error("discovery tcUrl failed. " - "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", - tcUrl.c_str(), schema.c_str(), vhost.c_str(), port.c_str(), app.c_str(), ret); - return ret; - } - - strip(); - - return ret; -} - -string SrsRequest::get_stream_url() -{ - std::string url = ""; - - url += vhost; - url += "/"; - url += app; - url += "/"; - url += stream; - - return url; -} - -void SrsRequest::strip() -{ - trim(vhost, "/ \n\r\t"); - trim(app, "/ \n\r\t"); - trim(stream, "/ \n\r\t"); -} - -std::string& SrsRequest::trim(string& str, string chs) -{ - for (int i = 0; i < (int)chs.length(); i++) { - char ch = chs.at(i); - - for (std::string::iterator it = str.begin(); it != str.end();) { - if (ch == *it) { - it = str.erase(it); - } else { - ++it; - } - } - } - - return str; -} - -SrsResponse::SrsResponse() -{ - stream_id = SRS_DEFAULT_SID; -} - -SrsResponse::~SrsResponse() -{ -} - -SrsRtmpClient::SrsRtmpClient(st_netfd_t _stfd) -{ - stfd = _stfd; - protocol = new SrsProtocol(stfd); -} - -SrsRtmpClient::~SrsRtmpClient() -{ - srs_freep(protocol); -} - -void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) -{ - protocol->set_recv_timeout(timeout_us); -} - -void SrsRtmpClient::set_send_timeout(int64_t timeout_us) -{ - protocol->set_send_timeout(timeout_us); -} - -int64_t SrsRtmpClient::get_recv_bytes() -{ - return protocol->get_recv_bytes(); -} - -int64_t SrsRtmpClient::get_send_bytes() -{ - return protocol->get_send_bytes(); -} - -int SrsRtmpClient::get_recv_kbps() -{ - return protocol->get_recv_kbps(); -} - -int SrsRtmpClient::get_send_kbps() -{ - return protocol->get_send_kbps(); -} - -int SrsRtmpClient::recv_message(SrsCommonMessage** pmsg) -{ - return protocol->recv_message(pmsg); -} - -int SrsRtmpClient::send_message(ISrsMessage* msg) -{ - return protocol->send_message(msg); -} - -int SrsRtmpClient::handshake() -{ - int ret = ERROR_SUCCESS; - - SrsSocket skt(stfd); - - skt.set_recv_timeout(protocol->get_recv_timeout()); - skt.set_send_timeout(protocol->get_send_timeout()); - - SrsComplexHandshake complex_hs; - SrsSimpleHandshake simple_hs; - if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -int SrsRtmpClient::connect_app(string app, string tc_url) -{ - int ret = ERROR_SUCCESS; - - // Connect(vhost, app) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); - msg->set_packet(pkt, 0); - - pkt->command_object = new SrsAmf0Object(); - pkt->command_object->set("app", new SrsAmf0String(app.c_str())); - pkt->command_object->set("swfUrl", new SrsAmf0String()); - pkt->command_object->set("tcUrl", new SrsAmf0String(tc_url.c_str())); - pkt->command_object->set("fpad", new SrsAmf0Boolean(false)); - pkt->command_object->set("capabilities", new SrsAmf0Number(239)); - pkt->command_object->set("audioCodecs", new SrsAmf0Number(3575)); - pkt->command_object->set("videoCodecs", new SrsAmf0Number(252)); - pkt->command_object->set("videoFunction", new SrsAmf0Number(1)); - pkt->command_object->set("pageUrl", new SrsAmf0String()); - pkt->command_object->set("objectEncoding", new SrsAmf0Number(0)); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } - - // Set Window Acknowledgement size(2500000) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); - - pkt->ackowledgement_window_size = 2500000; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } - - // expect connect _result - SrsCommonMessage* msg = NULL; - SrsConnectAppResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect connect app response message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get connect app response message"); - - return ret; -} - -int SrsRtmpClient::create_stream(int& stream_id) -{ - int ret = ERROR_SUCCESS; - - // CreateStream - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - return ret; - } - } - - // CreateStream _result. - if (true) { - SrsCommonMessage* msg = NULL; - SrsCreateStreamResPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect create stream response message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get create stream response message"); - - stream_id = (int)pkt->stream_id; - } - - return ret; -} - -int SrsRtmpClient::play(string stream, int stream_id) -{ - int ret = ERROR_SUCCESS; - - // Play(stream) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsPlayPacket* pkt = new SrsPlayPacket(); - - pkt->stream_name = stream; - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send play stream failed. " - "stream=%s, stream_id=%d, ret=%d", - stream.c_str(), stream_id, ret); - return ret; - } - } - - // SetBufferLength(1000ms) - int buffer_length_ms = 1000; - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCSetBufferLength; - pkt->event_data = stream_id; - pkt->extra_data = buffer_length_ms; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set buffer length failed. " - "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", - stream.c_str(), stream_id, buffer_length_ms, ret); - return ret; - } - } - - return ret; -} - -int SrsRtmpClient::publish(string stream, int stream_id) -{ - int ret = ERROR_SUCCESS; - - // publish(stream) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsPublishPacket* pkt = new SrsPublishPacket(); - - pkt->stream_name = stream; - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send publish message failed. " - "stream=%s, stream_id=%d, ret=%d", - stream.c_str(), stream_id, ret); - return ret; - } - } - - return ret; -} - -SrsRtmp::SrsRtmp(st_netfd_t client_stfd) -{ - protocol = new SrsProtocol(client_stfd); - stfd = client_stfd; -} - -SrsRtmp::~SrsRtmp() -{ - srs_freep(protocol); -} - -SrsProtocol* SrsRtmp::get_protocol() -{ - return protocol; -} - -void SrsRtmp::set_recv_timeout(int64_t timeout_us) -{ - protocol->set_recv_timeout(timeout_us); -} - -int64_t SrsRtmp::get_recv_timeout() -{ - return protocol->get_recv_timeout(); -} - -void SrsRtmp::set_send_timeout(int64_t timeout_us) -{ - protocol->set_send_timeout(timeout_us); -} - -int64_t SrsRtmp::get_send_timeout() -{ - return protocol->get_send_timeout(); -} - -int64_t SrsRtmp::get_recv_bytes() -{ - return protocol->get_recv_bytes(); -} - -int64_t SrsRtmp::get_send_bytes() -{ - return protocol->get_send_bytes(); -} - -int SrsRtmp::get_recv_kbps() -{ - return protocol->get_recv_kbps(); -} - -int SrsRtmp::get_send_kbps() -{ - return protocol->get_send_kbps(); -} - -int SrsRtmp::recv_message(SrsCommonMessage** pmsg) -{ - return protocol->recv_message(pmsg); -} - -int SrsRtmp::send_message(ISrsMessage* msg) -{ - return protocol->send_message(msg); -} - -int SrsRtmp::handshake() -{ - int ret = ERROR_SUCCESS; - - SrsSocket skt(stfd); - - skt.set_recv_timeout(protocol->get_recv_timeout()); - skt.set_send_timeout(protocol->get_send_timeout()); - - SrsComplexHandshake complex_hs; - SrsSimpleHandshake simple_hs; - if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { - return ret; - } - - return ret; -} - -int SrsRtmp::connect_app(SrsRequest* req) -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = NULL; - SrsConnectAppPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("expect connect app message failed. ret=%d", ret); - return ret; - } - SrsAutoFree(SrsCommonMessage, msg, false); - srs_info("get connect app message"); - - SrsAmf0Any* prop = NULL; - - if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { - ret = ERROR_RTMP_REQ_CONNECT; - srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); - return ret; - } - req->tcUrl = srs_amf0_convert(prop)->value; - - if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { - req->pageUrl = srs_amf0_convert(prop)->value; - } - - if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { - req->swfUrl = srs_amf0_convert(prop)->value; - } - - if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { - req->objectEncoding = srs_amf0_convert(prop)->value; - } - - srs_info("get connect app message params success."); - - return req->discovery_app(); -} - -int SrsRtmp::set_window_ack_size(int ack_size) -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); - - pkt->ackowledgement_window_size = ack_size; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send ack size message failed. ret=%d", ret); - return ret; - } - srs_info("send ack size message success. ack_size=%d", ack_size); - - return ret; -} - -int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); - - pkt->bandwidth = bandwidth; - pkt->type = type; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set bandwidth message failed. ret=%d", ret); - return ret; - } - srs_info("send set bandwidth message " - "success. bandwidth=%d, type=%d", bandwidth, type); - - return ret; -} - -int SrsRtmp::response_connect_app(SrsRequest* req) -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); - - pkt->props->set("fmsVer", new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER)); - pkt->props->set("capabilities", new SrsAmf0Number(127)); - pkt->props->set("mode", new SrsAmf0Number(1)); - - pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess)); - pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded")); - pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); - SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); - pkt->info->set("data", data); - - data->set("srs_version", new SrsAmf0String(RTMP_SIG_FMS_VER)); - data->set("srs_server", new SrsAmf0String(RTMP_SIG_SRS_NAME)); - data->set("srs_license", new SrsAmf0String(RTMP_SIG_SRS_LICENSE)); - data->set("srs_role", new SrsAmf0String(RTMP_SIG_SRS_ROLE)); - data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL)); - data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION)); - data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB)); - data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); - data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send connect app response message failed. ret=%d", ret); - return ret; - } - srs_info("send connect app response message success."); - - return ret; -} - -int SrsRtmp::on_bw_done() -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onBWDone message failed. ret=%d", ret); - return ret; - } - srs_info("send onBWDone message success."); - - return ret; -} - -int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name) -{ - type = SrsClientUnknown; - int ret = ERROR_SUCCESS; - - while (true) { - SrsCommonMessage* msg = NULL; - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("recv identify client message failed. ret=%d", ret); - return ret; - } - - SrsAutoFree(SrsCommonMessage, msg, false); - - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { - srs_trace("identify ignore messages except " - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); - continue; - } - - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { - srs_error("identify decode message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - srs_info("identify client by create stream, play or flash publish."); - return identify_create_stream_client( - dynamic_cast(pkt), stream_id, type, stream_name); - } - if (dynamic_cast(pkt)) { - srs_info("identify client by releaseStream, fmle publish."); - return identify_fmle_publish_client( - dynamic_cast(pkt), type, stream_name); - } - - srs_trace("ignore AMF0/AMF3 command message."); - } - - return ret; -} - -int SrsRtmp::set_chunk_size(int chunk_size) -{ - int ret = ERROR_SUCCESS; - - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); - - pkt->chunk_size = chunk_size; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send set chunk size message failed. ret=%d", ret); - return ret; - } - srs_info("send set chunk size message success. chunk_size=%d", chunk_size); - - return ret; -} - -int SrsRtmp::start_play(int stream_id) -{ - int ret = ERROR_SUCCESS; - - // StreamBegin - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamBegin; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreamBegin) message success."); - } - - // onStatus(NetStream.Play.Reset) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamReset)); - pkt->data->set(StatusDescription, new SrsAmf0String("Playing and resetting stream.")); - pkt->data->set(StatusDetails, new SrsAmf0String("stream")); - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Play.Reset) message success."); - } - - // onStatus(NetStream.Play.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamStart)); - pkt->data->set(StatusDescription, new SrsAmf0String("Started playing stream.")); - pkt->data->set(StatusDetails, new SrsAmf0String("stream")); - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Play.Reset) message success."); - } - - // |RtmpSampleAccess(false, false) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); - return ret; - } - srs_info("send |RtmpSampleAccess(false, false) message success."); - } - - // onStatus(NetStream.Data.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); - - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeDataStart)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Data.Start) message success."); - } - - srs_info("start play success."); - - return ret; -} - -int SrsRtmp::on_play_client_pause(int stream_id, bool is_pause) -{ - int ret = ERROR_SUCCESS; - - if (is_pause) { - // onStatus(NetStream.Pause.Notify) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamPause)); - pkt->data->set(StatusDescription, new SrsAmf0String("Paused stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Pause.Notify) message success."); - } - // StreamEOF - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamEOF; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreamEOF) message success."); - } - } else { - // onStatus(NetStream.Unpause.Notify) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamUnpause)); - pkt->data->set(StatusDescription, new SrsAmf0String("Unpaused stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Unpause.Notify) message success."); - } - // StreanBegin - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsUserControlPacket* pkt = new SrsUserControlPacket(); - - pkt->event_type = SrcPCUCStreamBegin; - pkt->event_data = stream_id; - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); - return ret; - } - srs_info("send PCUC(StreanBegin) message success."); - } - } - - return ret; -} - -int SrsRtmp::start_fmle_publish(int stream_id) -{ - int ret = ERROR_SUCCESS; - - // FCPublish - double fc_publish_tid = 0; - if (true) { - SrsCommonMessage* msg = NULL; - SrsFMLEStartPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv FCPublish message failed. ret=%d", ret); - return ret; - } - srs_info("recv FCPublish request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - fc_publish_tid = pkt->transaction_id; - } - // FCPublish response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FCPublish response message failed. ret=%d", ret); - return ret; - } - srs_info("send FCPublish response message success."); - } - - // createStream - double create_stream_tid = 0; - if (true) { - SrsCommonMessage* msg = NULL; - SrsCreateStreamPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv createStream message failed. ret=%d", ret); - return ret; - } - srs_info("recv createStream request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - create_stream_tid = pkt->transaction_id; - } - // createStream response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send createStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send createStream response message success."); - } - - // publish - if (true) { - SrsCommonMessage* msg = NULL; - SrsPublishPacket* pkt = NULL; - if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { - srs_error("recv publish message failed. ret=%d", ret); - return ret; - } - srs_info("recv publish request message success."); - - SrsAutoFree(SrsCommonMessage, msg, false); - } - // publish response onFCPublish(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onFCPublish(NetStream.Publish.Start) message success."); - } - // publish response onStatus(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Publish.Start) message success."); - } - - srs_info("FMLE publish success."); - - return ret; -} - -int SrsRtmp::fmle_unpublish(int stream_id, double unpublish_tid) -{ - int ret = ERROR_SUCCESS; - - // publish response onFCUnpublish(NetStream.unpublish.Success) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); - pkt->data->set(StatusDescription, new SrsAmf0String("Stop publishing stream.")); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); - return ret; - } - srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); - } - // FCUnpublish response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send FCUnpublish response message failed. ret=%d", ret); - return ret; - } - srs_info("send FCUnpublish response message success."); - } - // publish response onStatus(NetStream.Unpublish.Success) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); - pkt->data->set(StatusDescription, new SrsAmf0String("Stream is now unpublished")); - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Unpublish.Success) message success."); - } - - srs_info("FMLE unpublish success."); - - return ret; -} - -int SrsRtmp::start_flash_publish(int stream_id) -{ - int ret = ERROR_SUCCESS; - - // publish response onStatus(NetStream.Publish.Start) - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); - - pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); - pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); - pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); - pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); - - msg->set_packet(pkt, stream_id); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); - return ret; - } - srs_info("send onStatus(NetStream.Publish.Start) message success."); - } - - srs_info("flash publish success."); - - return ret; -} - -int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, string& stream_name) -{ - int ret = ERROR_SUCCESS; - - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send createStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send createStream response message success."); - } - - while (true) { - SrsCommonMessage* msg = NULL; - if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { - srs_error("recv identify client message failed. ret=%d", ret); - return ret; - } - - SrsAutoFree(SrsCommonMessage, msg, false); - - if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { - srs_trace("identify ignore messages except " - "AMF0/AMF3 command message. type=%#x", msg->header.message_type); - continue; - } - - if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { - srs_error("identify decode message failed. ret=%d", ret); - return ret; - } - - SrsPacket* pkt = msg->get_packet(); - if (dynamic_cast(pkt)) { - SrsPlayPacket* play = dynamic_cast(pkt); - type = SrsClientPlay; - stream_name = play->stream_name; - srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); - return ret; - } - if (dynamic_cast(pkt)) { - srs_info("identify client by publish, falsh publish."); - return identify_flash_publish_client( - dynamic_cast(pkt), type, stream_name); - } - - srs_trace("ignore AMF0/AMF3 command message."); - } - - return ret; -} - -int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, string& stream_name) -{ - int ret = ERROR_SUCCESS; - - type = SrsClientFMLEPublish; - stream_name = req->stream_name; - - // releaseStream response - if (true) { - SrsCommonMessage* msg = new SrsCommonMessage(); - SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); - - msg->set_packet(pkt, 0); - - if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { - srs_error("send releaseStream response message failed. ret=%d", ret); - return ret; - } - srs_info("send releaseStream response message success."); - } - - return ret; -} - -int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, string& stream_name) -{ - int ret = ERROR_SUCCESS; - - type = SrsClientFlashPublish; - stream_name = req->stream_name; - - return ret; -} - +/* +The MIT License (MIT) + +Copyright (c) 2013 winlin + +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 + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/** +* the signature for packets to client. +*/ +#define RTMP_SIG_FMS_VER "3,5,3,888" +#define RTMP_SIG_AMF0_VER 0 +#define RTMP_SIG_CLIENT_ID "ASAICiss" + +/** +* onStatus consts. +*/ +#define StatusLevel "level" +#define StatusCode "code" +#define StatusDescription "description" +#define StatusDetails "details" +#define StatusClientId "clientid" +// status value +#define StatusLevelStatus "status" +// code value +#define StatusCodeConnectSuccess "NetConnection.Connect.Success" +#define StatusCodeStreamReset "NetStream.Play.Reset" +#define StatusCodeStreamStart "NetStream.Play.Start" +#define StatusCodeStreamPause "NetStream.Pause.Notify" +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" +#define StatusCodePublishStart "NetStream.Publish.Start" +#define StatusCodeDataStart "NetStream.Data.Start" +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" + +// FMLE +#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" +#define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" + +// default stream id for response the createStream request. +#define SRS_DEFAULT_SID 1 + +SrsRequest::SrsRequest() +{ + objectEncoding = RTMP_SIG_AMF0_VER; +} + +SrsRequest::~SrsRequest() +{ +} + +SrsRequest* SrsRequest::copy() +{ + SrsRequest* cp = new SrsRequest(); + + cp->app = app; + cp->objectEncoding = objectEncoding; + cp->pageUrl = pageUrl; + cp->port = port; + cp->schema = schema; + cp->stream = stream; + cp->swfUrl = swfUrl; + cp->tcUrl = tcUrl; + cp->vhost = vhost; + + return cp; +} + +int SrsRequest::discovery_app() +{ + int ret = ERROR_SUCCESS; + + size_t pos = std::string::npos; + std::string url = tcUrl; + + if ((pos = url.find("://")) != std::string::npos) { + schema = url.substr(0, pos); + url = url.substr(schema.length() + 3); + srs_verbose("discovery schema=%s", schema.c_str()); + } + + if ((pos = url.find("/")) != std::string::npos) { + vhost = url.substr(0, pos); + url = url.substr(vhost.length() + 1); + srs_verbose("discovery vhost=%s", vhost.c_str()); + } + + port = RTMP_DEFAULT_PORTS; + if ((pos = vhost.find(":")) != std::string::npos) { + port = vhost.substr(pos + 1); + vhost = vhost.substr(0, pos); + srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); + } + + app = url; + srs_vhost_resolve(vhost, app); + + // resolve the vhost from config + SrsConfDirective* parsed_vhost = config->get_vhost(vhost); + if (parsed_vhost) { + vhost = parsed_vhost->arg0(); + } + + // TODO: discovery the params of vhost. + + srs_info("discovery app success. schema=%s, vhost=%s, port=%s, app=%s", + schema.c_str(), vhost.c_str(), port.c_str(), app.c_str()); + + if (schema.empty() || vhost.empty() || port.empty() || app.empty()) { + ret = ERROR_RTMP_REQ_TCURL; + srs_error("discovery tcUrl failed. " + "tcUrl=%s, schema=%s, vhost=%s, port=%s, app=%s, ret=%d", + tcUrl.c_str(), schema.c_str(), vhost.c_str(), port.c_str(), app.c_str(), ret); + return ret; + } + + strip(); + + return ret; +} + +string SrsRequest::get_stream_url() +{ + std::string url = ""; + + url += vhost; + url += "/"; + url += app; + url += "/"; + url += stream; + + return url; +} + +void SrsRequest::strip() +{ + trim(vhost, "/ \n\r\t"); + trim(app, "/ \n\r\t"); + trim(stream, "/ \n\r\t"); +} + +std::string& SrsRequest::trim(string& str, string chs) +{ + for (int i = 0; i < (int)chs.length(); i++) { + char ch = chs.at(i); + + for (std::string::iterator it = str.begin(); it != str.end();) { + if (ch == *it) { + it = str.erase(it); + } else { + ++it; + } + } + } + + return str; +} + +SrsResponse::SrsResponse() +{ + stream_id = SRS_DEFAULT_SID; +} + +SrsResponse::~SrsResponse() +{ +} + +SrsRtmpClient::SrsRtmpClient(st_netfd_t _stfd) +{ + stfd = _stfd; + protocol = new SrsProtocol(stfd); +} + +SrsRtmpClient::~SrsRtmpClient() +{ + srs_freep(protocol); +} + +void SrsRtmpClient::set_recv_timeout(int64_t timeout_us) +{ + protocol->set_recv_timeout(timeout_us); +} + +void SrsRtmpClient::set_send_timeout(int64_t timeout_us) +{ + protocol->set_send_timeout(timeout_us); +} + +int64_t SrsRtmpClient::get_recv_bytes() +{ + return protocol->get_recv_bytes(); +} + +int64_t SrsRtmpClient::get_send_bytes() +{ + return protocol->get_send_bytes(); +} + +int SrsRtmpClient::get_recv_kbps() +{ + return protocol->get_recv_kbps(); +} + +int SrsRtmpClient::get_send_kbps() +{ + return protocol->get_send_kbps(); +} + +int SrsRtmpClient::recv_message(SrsCommonMessage** pmsg) +{ + return protocol->recv_message(pmsg); +} + +int SrsRtmpClient::send_message(ISrsMessage* msg) +{ + return protocol->send_message(msg); +} + +int SrsRtmpClient::handshake() +{ + int ret = ERROR_SUCCESS; + + SrsSocket skt(stfd); + + skt.set_recv_timeout(protocol->get_recv_timeout()); + skt.set_send_timeout(protocol->get_send_timeout()); + + SrsComplexHandshake complex_hs; + SrsSimpleHandshake simple_hs; + if ((ret = simple_hs.handshake_with_server(skt, complex_hs)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +int SrsRtmpClient::connect_app(string app, string tc_url) +{ + int ret = ERROR_SUCCESS; + + // Connect(vhost, app) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); + msg->set_packet(pkt, 0); + + pkt->command_object = new SrsAmf0Object(); + pkt->command_object->set("app", new SrsAmf0String(app.c_str())); + pkt->command_object->set("swfUrl", new SrsAmf0String()); + pkt->command_object->set("tcUrl", new SrsAmf0String(tc_url.c_str())); + pkt->command_object->set("fpad", new SrsAmf0Boolean(false)); + pkt->command_object->set("capabilities", new SrsAmf0Number(239)); + pkt->command_object->set("audioCodecs", new SrsAmf0Number(3575)); + pkt->command_object->set("videoCodecs", new SrsAmf0Number(252)); + pkt->command_object->set("videoFunction", new SrsAmf0Number(1)); + pkt->command_object->set("pageUrl", new SrsAmf0String()); + pkt->command_object->set("objectEncoding", new SrsAmf0Number(0)); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } + + // Set Window Acknowledgement size(2500000) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); + + pkt->ackowledgement_window_size = 2500000; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } + + // expect connect _result + SrsCommonMessage* msg = NULL; + SrsConnectAppResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect connect app response message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get connect app response message"); + + return ret; +} + +int SrsRtmpClient::create_stream(int& stream_id) +{ + int ret = ERROR_SUCCESS; + + // CreateStream + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + return ret; + } + } + + // CreateStream _result. + if (true) { + SrsCommonMessage* msg = NULL; + SrsCreateStreamResPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect create stream response message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get create stream response message"); + + stream_id = (int)pkt->stream_id; + } + + return ret; +} + +int SrsRtmpClient::play(string stream, int stream_id) +{ + int ret = ERROR_SUCCESS; + + // Play(stream) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsPlayPacket* pkt = new SrsPlayPacket(); + + pkt->stream_name = stream; + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send play stream failed. " + "stream=%s, stream_id=%d, ret=%d", + stream.c_str(), stream_id, ret); + return ret; + } + } + + // SetBufferLength(1000ms) + int buffer_length_ms = 1000; + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCSetBufferLength; + pkt->event_data = stream_id; + pkt->extra_data = buffer_length_ms; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set buffer length failed. " + "stream=%s, stream_id=%d, bufferLength=%d, ret=%d", + stream.c_str(), stream_id, buffer_length_ms, ret); + return ret; + } + } + + return ret; +} + +int SrsRtmpClient::publish(string stream, int stream_id) +{ + int ret = ERROR_SUCCESS; + + // publish(stream) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsPublishPacket* pkt = new SrsPublishPacket(); + + pkt->stream_name = stream; + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send publish message failed. " + "stream=%s, stream_id=%d, ret=%d", + stream.c_str(), stream_id, ret); + return ret; + } + } + + return ret; +} + +SrsRtmp::SrsRtmp(st_netfd_t client_stfd) +{ + protocol = new SrsProtocol(client_stfd); + stfd = client_stfd; +} + +SrsRtmp::~SrsRtmp() +{ + srs_freep(protocol); +} + +SrsProtocol* SrsRtmp::get_protocol() +{ + return protocol; +} + +void SrsRtmp::set_recv_timeout(int64_t timeout_us) +{ + protocol->set_recv_timeout(timeout_us); +} + +int64_t SrsRtmp::get_recv_timeout() +{ + return protocol->get_recv_timeout(); +} + +void SrsRtmp::set_send_timeout(int64_t timeout_us) +{ + protocol->set_send_timeout(timeout_us); +} + +int64_t SrsRtmp::get_send_timeout() +{ + return protocol->get_send_timeout(); +} + +int64_t SrsRtmp::get_recv_bytes() +{ + return protocol->get_recv_bytes(); +} + +int64_t SrsRtmp::get_send_bytes() +{ + return protocol->get_send_bytes(); +} + +int SrsRtmp::get_recv_kbps() +{ + return protocol->get_recv_kbps(); +} + +int SrsRtmp::get_send_kbps() +{ + return protocol->get_send_kbps(); +} + +int SrsRtmp::recv_message(SrsCommonMessage** pmsg) +{ + return protocol->recv_message(pmsg); +} + +int SrsRtmp::send_message(ISrsMessage* msg) +{ + return protocol->send_message(msg); +} + +int SrsRtmp::handshake() +{ + int ret = ERROR_SUCCESS; + + SrsSocket skt(stfd); + + skt.set_recv_timeout(protocol->get_recv_timeout()); + skt.set_send_timeout(protocol->get_send_timeout()); + + SrsComplexHandshake complex_hs; + SrsSimpleHandshake simple_hs; + if ((ret = simple_hs.handshake_with_client(skt, complex_hs)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + +int SrsRtmp::connect_app(SrsRequest* req) +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = NULL; + SrsConnectAppPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("expect connect app message failed. ret=%d", ret); + return ret; + } + SrsAutoFree(SrsCommonMessage, msg, false); + srs_info("get connect app message"); + + SrsAmf0Any* prop = NULL; + + if ((prop = pkt->command_object->ensure_property_string("tcUrl")) == NULL) { + ret = ERROR_RTMP_REQ_CONNECT; + srs_error("invalid request, must specifies the tcUrl. ret=%d", ret); + return ret; + } + req->tcUrl = srs_amf0_convert(prop)->value; + + if ((prop = pkt->command_object->ensure_property_string("pageUrl")) != NULL) { + req->pageUrl = srs_amf0_convert(prop)->value; + } + + if ((prop = pkt->command_object->ensure_property_string("swfUrl")) != NULL) { + req->swfUrl = srs_amf0_convert(prop)->value; + } + + if ((prop = pkt->command_object->ensure_property_number("objectEncoding")) != NULL) { + req->objectEncoding = srs_amf0_convert(prop)->value; + } + + srs_info("get connect app message params success."); + + return req->discovery_app(); +} + +int SrsRtmp::set_window_ack_size(int ack_size) +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); + + pkt->ackowledgement_window_size = ack_size; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send ack size message failed. ret=%d", ret); + return ret; + } + srs_info("send ack size message success. ack_size=%d", ack_size); + + return ret; +} + +int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); + + pkt->bandwidth = bandwidth; + pkt->type = type; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set bandwidth message failed. ret=%d", ret); + return ret; + } + srs_info("send set bandwidth message " + "success. bandwidth=%d, type=%d", bandwidth, type); + + return ret; +} + +int SrsRtmp::response_connect_app(SrsRequest* req) +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); + + pkt->props->set("fmsVer", new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER)); + pkt->props->set("capabilities", new SrsAmf0Number(127)); + pkt->props->set("mode", new SrsAmf0Number(1)); + + pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess)); + pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded")); + pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); + SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); + pkt->info->set("data", data); + + data->set("srs_version", new SrsAmf0String(RTMP_SIG_FMS_VER)); + data->set("srs_server", new SrsAmf0String(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")")); + data->set("srs_license", new SrsAmf0String(RTMP_SIG_SRS_LICENSE)); + data->set("srs_role", new SrsAmf0String(RTMP_SIG_SRS_ROLE)); + data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL)); + data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION)); + data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB)); + data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); + data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); + data->set("srs_contributor", new SrsAmf0String(RTMP_SIG_SRS_CONTRIBUTOR)); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send connect app response message failed. ret=%d", ret); + return ret; + } + srs_info("send connect app response message success."); + + return ret; +} + +int SrsRtmp::on_bw_done() +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onBWDone message failed. ret=%d", ret); + return ret; + } + srs_info("send onBWDone message success."); + + return ret; +} + +int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name) +{ + type = SrsClientUnknown; + int ret = ERROR_SUCCESS; + + while (true) { + SrsCommonMessage* msg = NULL; + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("recv identify client message failed. ret=%d", ret); + return ret; + } + + SrsAutoFree(SrsCommonMessage, msg, false); + + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { + srs_trace("identify ignore messages except " + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); + continue; + } + + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { + srs_error("identify decode message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + srs_info("identify client by create stream, play or flash publish."); + return identify_create_stream_client( + dynamic_cast(pkt), stream_id, type, stream_name); + } + if (dynamic_cast(pkt)) { + srs_info("identify client by releaseStream, fmle publish."); + return identify_fmle_publish_client( + dynamic_cast(pkt), type, stream_name); + } + + srs_trace("ignore AMF0/AMF3 command message."); + } + + return ret; +} + +int SrsRtmp::set_chunk_size(int chunk_size) +{ + int ret = ERROR_SUCCESS; + + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); + + pkt->chunk_size = chunk_size; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send set chunk size message failed. ret=%d", ret); + return ret; + } + srs_info("send set chunk size message success. chunk_size=%d", chunk_size); + + return ret; +} + +int SrsRtmp::start_play(int stream_id) +{ + int ret = ERROR_SUCCESS; + + // StreamBegin + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamBegin; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreamBegin) message success."); + } + + // onStatus(NetStream.Play.Reset) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamReset)); + pkt->data->set(StatusDescription, new SrsAmf0String("Playing and resetting stream.")); + pkt->data->set(StatusDetails, new SrsAmf0String("stream")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Play.Reset) message success."); + } + + // onStatus(NetStream.Play.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamStart)); + pkt->data->set(StatusDescription, new SrsAmf0String("Started playing stream.")); + pkt->data->set(StatusDetails, new SrsAmf0String("stream")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Play.Reset) message success."); + } + + // |RtmpSampleAccess(false, false) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); + return ret; + } + srs_info("send |RtmpSampleAccess(false, false) message success."); + } + + // onStatus(NetStream.Data.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); + + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeDataStart)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Data.Start) message success."); + } + + srs_info("start play success."); + + return ret; +} + +int SrsRtmp::on_play_client_pause(int stream_id, bool is_pause) +{ + int ret = ERROR_SUCCESS; + + if (is_pause) { + // onStatus(NetStream.Pause.Notify) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamPause)); + pkt->data->set(StatusDescription, new SrsAmf0String("Paused stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Pause.Notify) message success."); + } + // StreamEOF + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamEOF; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreamEOF) message success."); + } + } else { + // onStatus(NetStream.Unpause.Notify) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamUnpause)); + pkt->data->set(StatusDescription, new SrsAmf0String("Unpaused stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Unpause.Notify) message success."); + } + // StreanBegin + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsUserControlPacket* pkt = new SrsUserControlPacket(); + + pkt->event_type = SrcPCUCStreamBegin; + pkt->event_data = stream_id; + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret); + return ret; + } + srs_info("send PCUC(StreanBegin) message success."); + } + } + + return ret; +} + +int SrsRtmp::start_fmle_publish(int stream_id) +{ + int ret = ERROR_SUCCESS; + + // FCPublish + double fc_publish_tid = 0; + if (true) { + SrsCommonMessage* msg = NULL; + SrsFMLEStartPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv FCPublish message failed. ret=%d", ret); + return ret; + } + srs_info("recv FCPublish request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + fc_publish_tid = pkt->transaction_id; + } + // FCPublish response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FCPublish response message failed. ret=%d", ret); + return ret; + } + srs_info("send FCPublish response message success."); + } + + // createStream + double create_stream_tid = 0; + if (true) { + SrsCommonMessage* msg = NULL; + SrsCreateStreamPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv createStream message failed. ret=%d", ret); + return ret; + } + srs_info("recv createStream request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + create_stream_tid = pkt->transaction_id; + } + // createStream response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send createStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send createStream response message success."); + } + + // publish + if (true) { + SrsCommonMessage* msg = NULL; + SrsPublishPacket* pkt = NULL; + if ((ret = srs_rtmp_expect_message(protocol, &msg, &pkt)) != ERROR_SUCCESS) { + srs_error("recv publish message failed. ret=%d", ret); + return ret; + } + srs_info("recv publish request message success."); + + SrsAutoFree(SrsCommonMessage, msg, false); + } + // publish response onFCPublish(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH; + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onFCPublish(NetStream.Publish.Start) message success."); + } + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Publish.Start) message success."); + } + + srs_info("FMLE publish success."); + + return ret; +} + +int SrsRtmp::fmle_unpublish(int stream_id, double unpublish_tid) +{ + int ret = ERROR_SUCCESS; + + // publish response onFCUnpublish(NetStream.unpublish.Success) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH; + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); + pkt->data->set(StatusDescription, new SrsAmf0String("Stop publishing stream.")); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onFCUnpublish(NetStream.unpublish.Success) message failed. ret=%d", ret); + return ret; + } + srs_info("send onFCUnpublish(NetStream.unpublish.Success) message success."); + } + // FCUnpublish response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(unpublish_tid); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send FCUnpublish response message failed. ret=%d", ret); + return ret; + } + srs_info("send FCUnpublish response message success."); + } + // publish response onStatus(NetStream.Unpublish.Success) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeUnpublishSuccess)); + pkt->data->set(StatusDescription, new SrsAmf0String("Stream is now unpublished")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Unpublish.Success) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Unpublish.Success) message success."); + } + + srs_info("FMLE unpublish success."); + + return ret; +} + +int SrsRtmp::start_flash_publish(int stream_id) +{ + int ret = ERROR_SUCCESS; + + // publish response onStatus(NetStream.Publish.Start) + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); + + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart)); + pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream.")); + pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID)); + + msg->set_packet(pkt, stream_id); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret); + return ret; + } + srs_info("send onStatus(NetStream.Publish.Start) message success."); + } + + srs_info("flash publish success."); + + return ret; +} + +int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, string& stream_name) +{ + int ret = ERROR_SUCCESS; + + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send createStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send createStream response message success."); + } + + while (true) { + SrsCommonMessage* msg = NULL; + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) { + srs_error("recv identify client message failed. ret=%d", ret); + return ret; + } + + SrsAutoFree(SrsCommonMessage, msg, false); + + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) { + srs_trace("identify ignore messages except " + "AMF0/AMF3 command message. type=%#x", msg->header.message_type); + continue; + } + + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) { + srs_error("identify decode message failed. ret=%d", ret); + return ret; + } + + SrsPacket* pkt = msg->get_packet(); + if (dynamic_cast(pkt)) { + SrsPlayPacket* play = dynamic_cast(pkt); + type = SrsClientPlay; + stream_name = play->stream_name; + srs_trace("identity client type=play, stream_name=%s", stream_name.c_str()); + return ret; + } + if (dynamic_cast(pkt)) { + srs_info("identify client by publish, falsh publish."); + return identify_flash_publish_client( + dynamic_cast(pkt), type, stream_name); + } + + srs_trace("ignore AMF0/AMF3 command message."); + } + + return ret; +} + +int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, string& stream_name) +{ + int ret = ERROR_SUCCESS; + + type = SrsClientFMLEPublish; + stream_name = req->stream_name; + + // releaseStream response + if (true) { + SrsCommonMessage* msg = new SrsCommonMessage(); + SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); + + msg->set_packet(pkt, 0); + + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { + srs_error("send releaseStream response message failed. ret=%d", ret); + return ret; + } + srs_info("send releaseStream response message success."); + } + + return ret; +} + +int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, string& stream_name) +{ + int ret = ERROR_SUCCESS; + + type = SrsClientFlashPublish; + stream_name = req->stream_name; + + return ret; +} +