From: toine512 Date: Fri, 22 Jul 2011 00:10:13 +0000 (-0700) Subject: Squashed commit of the following: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc762e41a090b5c238bd7daedab13def69eb140b;p=rtmpdump Squashed commit of the following: commit 84b160fdc8e6aaff9b5b214d90e8f002cc4185dd Author: toine512 Date: Wed Jul 20 23:09:26 2011 +0200 Updates man .. again commit 717c562b844595f5b24da268a5f5203d921ebc89 Author: toine512 Date: Wed Jul 20 21:00:44 2011 +0200 More updates in man files, regenerating HTML files needed commit 8196cf03b2ff7b9483166302bf79a0760fed2772 Author: toine512 Date: Wed Jul 20 20:42:41 2011 +0200 Updates ChangeLog commit 7a6931cffd0ffd2d0997ffed2bd7609e9a043387 Author: toine512 Date: Wed Jul 20 20:37:40 2011 +0200 Updates man files, regenerating HTML files is needed commit 1cb67af20bb4085b87123299956c6b4d2d2b1484 Author: toine512 Date: Wed Jul 20 20:03:16 2011 +0200 Implements Justin.tv support (NetStream.Authenticate.UsherToken) --- diff --git a/ChangeLog b/ChangeLog index fb2319f..c3b1a14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,9 @@ Copyright 2009-2011 Howard Chu Copyright 2009 The Flvstreamer Team http://rtmpdump.mplayerhq.hu/ +20 July 2011 +- add NetStream.Authenticate.UsherToken for Justin.tv + 11 July 2011, v2.4 - add RTMPE type 9 handshake support diff --git a/librtmp/librtmp.3 b/librtmp/librtmp.3 index 66197d5..7c424aa 100644 --- a/librtmp/librtmp.3 +++ b/librtmp/librtmp.3 @@ -1,5 +1,5 @@ -.TH LIBRTMP 3 "2010-07-03" "RTMPDump v2.3" -.\" Copyright 2010 Howard Chu. +.TH LIBRTMP 3 "2011-07-20" "RTMPDump v2.4" +.\" Copyright 2011 Howard Chu. .\" Copying permitted according to the GNU General Public License V2. .SH NAME librtmp \- RTMPDump Real-Time Messaging Protocol API @@ -161,6 +161,9 @@ These options handle additional authentication requests from the server. Key for SecureToken response, used if the server requires SecureToken authentication. .TP +.BI jtv= JSON +JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken +.TP .BI swfVfy= 0|1 If the value is 1 or TRUE, the SWF player is retrieved from the specified diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c index 5ef3ae9..adcff1f 100644 --- a/librtmp/rtmp.c +++ b/librtmp/rtmp.c @@ -96,6 +96,7 @@ static int SendDeleteStream(RTMP *r, double dStreamId); static int SendFCSubscribe(RTMP *r, AVal *subscribepath); static int SendPlay(RTMP *r); static int SendBytesReceived(RTMP *r); +static int SendUsherToken(RTMP *r, AVal *usherToken); #if 0 /* unused */ static int SendBGHasStream(RTMP *r, double dId, AVal *playpath); @@ -335,6 +336,7 @@ RTMP_SetupStream(RTMP *r, uint32_t swfSize, AVal *flashVer, AVal *subscribepath, + AVal *usherToken, int dStart, int dStop, int bLiveStream, long int timeout) { @@ -355,6 +357,8 @@ RTMP_SetupStream(RTMP *r, RTMP_Log(RTMP_LOGDEBUG, "auth : %s", auth->av_val); if (subscribepath && subscribepath->av_val) RTMP_Log(RTMP_LOGDEBUG, "subscribepath : %s", subscribepath->av_val); + if (usherToken && usherToken->av_val) + RTMP_Log(RTMP_LOGDEBUG, "NetStream.Authenticate.UsherToken : %s", usherToken->av_val); if (flashVer && flashVer->av_val) RTMP_Log(RTMP_LOGDEBUG, "flashVer : %s", flashVer->av_val); if (dStart > 0) @@ -420,6 +424,8 @@ RTMP_SetupStream(RTMP *r, r->Link.flashVer = RTMP_DefaultFlashVer; if (subscribepath && subscribepath->av_len) r->Link.subscribepath = *subscribepath; + if (usherToken && usherToken->av_len) + r->Link.usherToken = *usherToken; r->Link.seekTime = dStart; r->Link.stopTime = dStop; if (bLiveStream) @@ -477,6 +483,8 @@ static struct urlopt { "Stream is live, no seeking possible" }, { AVC("subscribe"), OFF(Link.subscribepath), OPT_STR, 0, "Stream to subscribe to" }, + { AVC("jtv"), OFF(Link.usherToken), OPT_STR, 0, + "Justin.tv authentication token" }, { AVC("token"), OFF(Link.token), OPT_STR, 0, "Key for SecureToken response" }, { AVC("swfVfy"), OFF(Link.lFlags), OPT_BOOL, RTMP_LF_SWFV, @@ -1641,6 +1649,39 @@ SendFCSubscribe(RTMP *r, AVal *subscribepath) return RTMP_SendPacket(r, &packet, TRUE); } +//Justin.tv specific authentication +static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken"); //SAVC() isn't suitable for that + +static int +SendUsherToken(RTMP *r, AVal *usherToken) +{ + RTMPPacket packet; + char pbuf[1024], *pend = pbuf + sizeof(pbuf); + char *enc; + packet.m_nChannel = 0x03; /* control channel (invoke) */ + packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; + packet.m_packetType = RTMP_PACKET_TYPE_INVOKE; + packet.m_nTimeStamp = 0; + packet.m_nInfoField2 = 0; + packet.m_hasAbsTimestamp = 0; + packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE; + + RTMP_Log(RTMP_LOGDEBUG, "UsherToken: %s", usherToken->av_val); + enc = packet.m_body; + enc = AMF_EncodeString(enc, pend, &av_NetStream_Authenticate_UsherToken); + enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes); + *enc++ = AMF_NULL; + enc = AMF_EncodeString(enc, pend, usherToken); + + if (!enc) + return FALSE; + + packet.m_nBodySize = enc - packet.m_body; + + return RTMP_SendPacket(r, &packet, FALSE); +} +/******************************************/ + SAVC(releaseStream); static int @@ -2364,6 +2405,9 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) if (!(r->Link.protocol & RTMP_FEATURE_WRITE)) { + /* Authenticate on Justin.tv legacy servers before sending FCSubscribe */ + if (r->Link.usherToken.av_len) + SendUsherToken(r, &r->Link.usherToken); /* Send the FCSubscribe if live stream or if subscribepath is set */ if (r->Link.subscribepath.av_len) SendFCSubscribe(r, &r->Link.subscribepath); diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h index 1ece207..6b2ae5b 100644 --- a/librtmp/rtmp.h +++ b/librtmp/rtmp.h @@ -155,6 +155,7 @@ extern "C" AVal auth; AVal flashVer; AVal subscribepath; + AVal usherToken; AVal token; AMFObject extras; int edepth; @@ -297,6 +298,7 @@ extern "C" uint32_t swfSize, AVal *flashVer, AVal *subscribepath, + AVal *usherToken, int dStart, int dStop, int bLiveStream, long int timeout); diff --git a/rtmpdump.1 b/rtmpdump.1 index 2395de9..0d9de8d 100644 --- a/rtmpdump.1 +++ b/rtmpdump.1 @@ -1,5 +1,5 @@ -.TH RTMPDUMP 1 "2010-05-02" "RTMPDump v2.2e" -.\" Copyright 2010 Howard Chu. +.TH RTMPDUMP 1 "2011-07-20" "RTMPDump v2.4" +.\" Copyright 2011 Howard Chu. .\" Copying permitted according to the GNU General Public License V2. .SH NAME rtmpdump \- RTMP streaming media client @@ -51,6 +51,8 @@ rtmpdump \- RTMP streaming media client [\c .BI \-T \ key\fR] [\c +.BI \-j \ JSON\fR] +[\c .BI \-w \ swfHash\fR] [\c .BI \-x \ swfSize\fR] @@ -210,6 +212,9 @@ These options handle additional authentication requests from the server. Key for SecureToken response, used if the server requires SecureToken authentication. .TP +\fB\-\-jtv \-j\fP\ \fIJSON\fP +JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken +.TP \fB\-\-swfhash \-w\fP\ \fIhexstring\fP SHA256 hash of the decompressed SWF file. This option may be needed if the server uses SWF Verification, but see the diff --git a/rtmpdump.c b/rtmpdump.c index c1cd95b..ec1de85 100644 --- a/rtmpdump.c +++ b/rtmpdump.c @@ -691,6 +691,8 @@ void usage(char *prog) ("--stop|-B num Stop at num seconds into stream\n"); RTMP_LogPrintf ("--token|-T key Key for SecureToken response\n"); + RTMP_LogPrintf + ("--jtv|-j JSON Authentication token for Justin.tv legacy servers\n"); RTMP_LogPrintf ("--hashes|-# Display progress with hashes, not with the byte counter\n"); RTMP_LogPrintf @@ -738,6 +740,7 @@ main(int argc, char **argv) AVal hostname = { 0, 0 }; AVal playpath = { 0, 0 }; AVal subscribepath = { 0, 0 }; + AVal usherToken = { 0, 0 }; //Justin.tv auth token int port = -1; int protocol = RTMP_PROTOCOL_UNDEFINED; int retries = 0; @@ -839,12 +842,13 @@ main(int argc, char **argv) {"debug", 0, NULL, 'z'}, {"quiet", 0, NULL, 'q'}, {"verbose", 0, NULL, 'V'}, + {"jtv", 1, NULL, 'j'}, {0, 0, 0, 0} }; while ((opt = getopt_long(argc, argv, - "hVveqzr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#", + "hVveqzr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:", longopts, NULL)) != -1) { switch (opt) @@ -1051,6 +1055,9 @@ main(int argc, char **argv) case 'S': STR2AVAL(sockshost, optarg); break; + case 'j': + STR2AVAL(usherToken, optarg); + break; default: RTMP_LogPrintf("unknown option: %c\n", opt); usage(argv[0]); @@ -1167,7 +1174,7 @@ main(int argc, char **argv) RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath, &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize, - &flashVer, &subscribepath, dSeek, dStopOffset, bLiveStream, timeout); + &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout); /* Try to keep the stream moving if it pauses on us */ if (!bLiveStream && !(protocol & RTMP_FEATURE_HTTP)) diff --git a/rtmpgw.8 b/rtmpgw.8 index 197a2d6..0a231b4 100644 --- a/rtmpgw.8 +++ b/rtmpgw.8 @@ -1,5 +1,5 @@ -.TH RTMPGW 8 "2010-05-02" "RTMPDump v2.2e" -.\" Copyright 2010 Howard Chu. +.TH RTMPGW 8 "2011-07-20" "RTMPDump v2.4" +.\" Copyright 2011 Howard Chu. .\" Copying permitted according to the GNU General Public License V2. .SH NAME rtmpgw \- RTMP streaming media gateway @@ -50,6 +50,8 @@ rtmpgw \- RTMP streaming media gateway [\c .BI \-T \ key\fR] [\c +.BI \-j \ JSON\fR] +[\c .BI \-w \ swfHash\fR] [\c .BI \-x \ swfSize\fR] @@ -193,6 +195,9 @@ These options handle additional authentication requests from the server. Key for SecureToken response, used if the server requires SecureToken authentication. .TP +\fB\-\-jtv \-j\fP\ \fIJSON\fP +JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken +.TP \fB\-\-swfhash \-w\fP\ \fIhexstring\fP SHA256 hash of the decompressed SWF file. This option may be needed if the server uses SWF Verification, but see the diff --git a/rtmpgw.c b/rtmpgw.c index 10a99e8..ce7319a 100644 --- a/rtmpgw.c +++ b/rtmpgw.c @@ -95,6 +95,7 @@ typedef struct AVal flashVer; AVal token; AVal subscribepath; + AVal usherToken; //Justin.tv auth token AVal sockshost; AMFObject extras; int edepth; @@ -552,7 +553,7 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou RTMP_Init(&rtmp); RTMP_SetBufferMS(&rtmp, req.bufferTime); RTMP_SetupStream(&rtmp, req.protocol, &req.hostname, req.rtmpport, &req.sockshost, - &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, dSeek, req.dStopOffset, + &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, &req.usherToken, dSeek, req.dStopOffset, req.bLiveStream, req.timeout); /* backward compatibility, we always sent this as true before */ if (req.auth.av_len) @@ -953,6 +954,9 @@ ParseOption(char opt, char *arg, RTMP_REQUEST * req) case 'z': RTMP_debuglevel = RTMP_LOGALL; break; + case 'j': + STR2AVAL(req->usherToken, arg); + break; default: RTMP_LogPrintf("unknown option: %c, arg: %s\n", opt, arg); return FALSE; @@ -1023,6 +1027,7 @@ main(int argc, char **argv) {"debug", 0, NULL, 'z'}, {"quiet", 0, NULL, 'q'}, {"verbose", 0, NULL, 'V'}, + {"jtv", 1, NULL, 'j'}, {0, 0, 0, 0} }; @@ -1035,7 +1040,7 @@ main(int argc, char **argv) while ((opt = getopt_long(argc, argv, - "hvqVzr:s:t:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:", longopts, + "hvqVzr:s:t:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:j:", longopts, NULL)) != -1) { switch (opt) @@ -1095,6 +1100,8 @@ main(int argc, char **argv) ("--stop|-B num Stop at num seconds into stream\n"); RTMP_LogPrintf ("--token|-T key Key for SecureToken response\n"); + RTMP_LogPrintf + ("--jtv|-j JSON Authentication token for Justin.tv legacy servers\n"); RTMP_LogPrintf ("--buffer|-b Buffer time in milliseconds (default: %lu)\n\n", defaultRTMPRequest.bufferTime); diff --git a/rtmpsrv.c b/rtmpsrv.c index f1b6c66..cf52bfa 100644 --- a/rtmpsrv.c +++ b/rtmpsrv.c @@ -116,6 +116,7 @@ typedef struct AVal swfHash; AVal flashVer; AVal subscribepath; + AVal usherToken; uint32_t swfSize; uint32_t dStartOffset;