Squashed commit of the following:
authortoine512 <toine512@gmail.com>
Fri, 22 Jul 2011 00:10:13 +0000 (17:10 -0700)
committerHoward Chu <hyc@symas.com>
Fri, 22 Jul 2011 00:11:02 +0000 (17:11 -0700)
commit 84b160fdc8e6aaff9b5b214d90e8f002cc4185dd
Author: toine512 <toine512@gmail.com>
Date:   Wed Jul 20 23:09:26 2011 +0200

    Updates man .. again

commit 717c562b844595f5b24da268a5f5203d921ebc89
Author: toine512 <toine512@gmail.com>
Date:   Wed Jul 20 21:00:44 2011 +0200

    More updates in man files, regenerating HTML files needed

commit 8196cf03b2ff7b9483166302bf79a0760fed2772
Author: toine512 <toine512@gmail.com>
Date:   Wed Jul 20 20:42:41 2011 +0200

    Updates ChangeLog

commit 7a6931cffd0ffd2d0997ffed2bd7609e9a043387
Author: toine512 <toine512@gmail.com>
Date:   Wed Jul 20 20:37:40 2011 +0200

    Updates man files, regenerating HTML files is needed

commit 1cb67af20bb4085b87123299956c6b4d2d2b1484
Author: toine512 <toine512@gmail.com>
Date:   Wed Jul 20 20:03:16 2011 +0200

    Implements Justin.tv support (NetStream.Authenticate.UsherToken)

ChangeLog
librtmp/librtmp.3
librtmp/rtmp.c
librtmp/rtmp.h
rtmpdump.1
rtmpdump.c
rtmpgw.8
rtmpgw.c
rtmpsrv.c

index fb2319f..c3b1a14 100644 (file)
--- 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
 
index 66197d5..7c424aa 100644 (file)
@@ -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
index 5ef3ae9..adcff1f 100644 (file)
@@ -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);
index 1ece207..6b2ae5b 100644 (file)
@@ -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);
 
index 2395de9..0d9de8d 100644 (file)
@@ -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
index c1cd95b..ec1de85 100644 (file)
@@ -692,6 +692,8 @@ void usage(char *prog)
          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
            ("--buffer|-b             Buffer time in milliseconds (default: %lu)\n",
@@ -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))
index 197a2d6..0a231b4 100644 (file)
--- 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
index 10a99e8..ce7319a 100644 (file)
--- 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);
index f1b6c66..cf52bfa 100644 (file)
--- 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;