diff options
Diffstat (limited to 'src/librtmp-2-master.patch')
-rw-r--r-- | src/librtmp-2-master.patch | 5371 |
1 files changed, 0 insertions, 5371 deletions
diff --git a/src/librtmp-2-master.patch b/src/librtmp-2-master.patch deleted file mode 100644 index 19ec2e5..0000000 --- a/src/librtmp-2-master.patch +++ /dev/null @@ -1,5371 +0,0 @@ -This file is part of MXE. -See index.html for further information. - -From dc762e41a090b5c238bd7daedab13def69eb140b Mon Sep 17 00:00:00 2001 -From: toine512 <toine512@gmail.com> -Date: Thu, 21 Jul 2011 17:10:13 -0700 -Subject: [PATCH 01/64] Squashed commit of the following: - -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) - -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 -@@ -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)) -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; --- -1.7.10.4 - - -From a2fb387404cb0da99cf439d58478fff701398700 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Thu, 21 Jul 2011 17:31:14 -0700 -Subject: [PATCH 02/64] Regenerate HTML docs, minor tweaks - - -diff --git a/librtmp/librtmp.3.html b/librtmp/librtmp.3.html -index e5e6f4b..6f59851 100644 ---- a/librtmp/librtmp.3.html -+++ b/librtmp/librtmp.3.html -@@ -6,10 +6,10 @@ - <tr><td>LIBRTMP(3)<td align="center"><td align="right">LIBRTMP(3) - </thead> - <tfoot> --<tr><td>RTMPDump v2.3<td align="center">2010-07-03<td align="right">LIBRTMP(3) -+<tr><td>RTMPDump v2.4<td align="center">2011-07-20<td align="right">LIBRTMP(3) - </tfoot> - <tbody><tr><td colspan="3"><br><br><ul> --<!-- Copyright 2010 Howard Chu. -+<!-- Copyright 2011 Howard Chu. - Copying permitted according to the GNU General Public License V2.--> - </ul> - -@@ -238,6 +238,12 @@ authentication. - </dl> - <p> - <dl compact><dt> -+<b>jtv=</b><i>JSON</i> -+<dd> -+JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken -+</dl> -+<p> -+<dl compact><dt> - <b>swfVfy=</b><i>0|1</i> - <dd> - If the value is 1 or TRUE, the SWF player is retrieved from the -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index adcff1f..8d76164 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -484,7 +484,7 @@ static struct urlopt { - { AVC("subscribe"), OFF(Link.subscribepath), OPT_STR, 0, - "Stream to subscribe to" }, - { AVC("jtv"), OFF(Link.usherToken), OPT_STR, 0, -- "Justin.tv authentication token" }, -+ "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, -@@ -1649,8 +1649,8 @@ 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 -+/* Justin.tv specific authentication */ -+static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken"); - - static int - SendUsherToken(RTMP *r, AVal *usherToken) -diff --git a/rtmpdump.1.html b/rtmpdump.1.html -index 7f17636..826f722 100644 ---- a/rtmpdump.1.html -+++ b/rtmpdump.1.html -@@ -6,10 +6,10 @@ - <tr><td>RTMPDUMP(1)<td align="center"><td align="right">RTMPDUMP(1) - </thead> - <tfoot> --<tr><td>RTMPDump v2.2e<td align="center">2010-05-02<td align="right">RTMPDUMP(1) -+<tr><td>RTMPDump v2.4<td align="center">2011-07-20<td align="right">RTMPDUMP(1) - </tfoot> - <tbody><tr><td colspan="3"><br><br><ul> --<!-- Copyright 2010 Howard Chu. -+<!-- Copyright 2011 Howard Chu. - Copying permitted according to the GNU General Public License V2.--> - </ul> - -@@ -42,6 +42,7 @@ rtmpdump − RTMP streaming media client - [<b>−b</b><i> buffer</i>] - [<b>−m</b><i> timeout</i>] - [<b>−T</b><i> key</i>] -+[<b>−j</b><i> JSON</i>] - [<b>−w</b><i> swfHash</i>] - [<b>−x</b><i> swfSize</i>] - [<b>−W</b><i> swfUrl</i>] -@@ -275,6 +276,12 @@ authentication. - </dl> - <p> - <dl compact><dt> -+<b>−−jtv −j</b> <i>JSON</i> -+<dd> -+JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken -+</dl> -+<p> -+<dl compact><dt> - <b>−−swfhash −w</b> <i>hexstring</i> - <dd> - SHA256 hash of the decompressed SWF file. This option may be needed if -diff --git a/rtmpdump.c b/rtmpdump.c -index ec1de85..89c053a 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -1055,9 +1055,9 @@ main(int argc, char **argv) - case 'S': - STR2AVAL(sockshost, optarg); - break; -- case 'j': -- STR2AVAL(usherToken, optarg); -- break; -+ case 'j': -+ STR2AVAL(usherToken, optarg); -+ break; - default: - RTMP_LogPrintf("unknown option: %c\n", opt); - usage(argv[0]); -diff --git a/rtmpgw.8.html b/rtmpgw.8.html -index 58b8f35..68d6734 100644 ---- a/rtmpgw.8.html -+++ b/rtmpgw.8.html -@@ -6,10 +6,10 @@ - <tr><td>RTMPGW(8)<td align="center"><td align="right">RTMPGW(8) - </thead> - <tfoot> --<tr><td>RTMPDump v2.2e<td align="center">2010-05-02<td align="right">RTMPGW(8) -+<tr><td>RTMPDump v2.4<td align="center">2011-07-20<td align="right">RTMPGW(8) - </tfoot> - <tbody><tr><td colspan="3"><br><br><ul> --<!-- Copyright 2010 Howard Chu. -+<!-- Copyright 2011 Howard Chu. - Copying permitted according to the GNU General Public License V2.--> - </ul> - -@@ -41,6 +41,7 @@ rtmpgw − RTMP streaming media gateway - [<b>−b</b><i> buffer</i>] - [<b>−m</b><i> timeout</i>] - [<b>−T</b><i> key</i>] -+[<b>−j</b><i> JSON</i>] - [<b>−w</b><i> swfHash</i>] - [<b>−x</b><i> swfSize</i>] - [<b>−W</b><i> swfUrl</i>] -@@ -249,6 +250,12 @@ authentication. - </dl> - <p> - <dl compact><dt> -+<b>−−jtv −j</b> <i>JSON</i> -+<dd> -+JSON token used by legacy Justin.tv servers. Invokes NetStream.Authenticate.UsherToken -+</dl> -+<p> -+<dl compact><dt> - <b>−−swfhash −w</b> <i>hexstring</i> - <dd> - SHA256 hash of the decompressed SWF file. This option may be needed if -diff --git a/rtmpgw.c b/rtmpgw.c -index ce7319a..733e105 100644 ---- a/rtmpgw.c -+++ b/rtmpgw.c -@@ -1100,7 +1100,7 @@ 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 -+ 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", -diff --git a/rtmpsrv.c b/rtmpsrv.c -index cf52bfa..f1b6c66 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -116,7 +116,6 @@ typedef struct - AVal swfHash; - AVal flashVer; - AVal subscribepath; -- AVal usherToken; - uint32_t swfSize; - - uint32_t dStartOffset; --- -1.7.10.4 - - -From ed99ad05b34031fac74230760c77d4d1a6a9e706 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sat, 30 Apr 2011 14:29:58 +0300 -Subject: [PATCH 03/64] Remove the generated pkg-config file on make clean - - -diff --git a/librtmp/Makefile b/librtmp/Makefile -index d61e7a4..c95c8a6 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -76,7 +76,7 @@ OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o - all: librtmp.a $(SO_LIB) - - clean: -- rm -f *.o *.a *.$(SOX) *.$(SO_EXT) -+ rm -f *.o *.a *.$(SOX) *.$(SO_EXT) librtmp.pc - - librtmp.a: $(OBJS) - $(AR) rs $@ $? --- -1.7.10.4 - - -From 749018b7c7c4e0090ea17c104dc094ab74326c08 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sat, 30 Apr 2011 14:30:00 +0300 -Subject: [PATCH 04/64] Create the SODIR, too - -When SYS=mingw, this differs from LIBDIR. - -diff --git a/librtmp/Makefile b/librtmp/Makefile -index c95c8a6..aa4a339 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -100,7 +100,7 @@ librtmp.pc: librtmp.pc.in Makefile - install: install_base $(SO_INST) - - install_base: librtmp.a librtmp.pc -- -mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 -+ -mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 $(SODIR) - cp amf.h http.h log.h rtmp.h $(INCDIR) - cp librtmp.a $(LIBDIR) - cp librtmp.pc $(LIBDIR)/pkgconfig --- -1.7.10.4 - - -From 9931c44867d157621ae10cf489ba336091dfab6b Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sat, 30 Apr 2011 14:30:01 +0300 -Subject: [PATCH 05/64] Generate and install an import lib for the built DLL - - -diff --git a/librtmp/Makefile b/librtmp/Makefile -index aa4a339..b88baf4 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -54,9 +54,14 @@ SODIR=$(SODIR_$(SYS)) - SO_LDFLAGS_posix=-shared -Wl,-soname,$@ - SO_LDFLAGS_darwin=-dynamiclib -flat_namespace -undefined suppress -fno-common \ - -headerpad_max_install_names --SO_LDFLAGS_mingw=-shared -+SO_LDFLAGS_mingw=-shared -Wl,--out-implib,librtmp.dll.a - SO_LDFLAGS=$(SO_LDFLAGS_$(SYS)) - -+INSTALL_IMPLIB_posix= -+INSTALL_IMPLIB_darwin= -+INSTALL_IMPLIB_mingw=cp librtmp.dll.a $(LIBDIR) -+INSTALL_IMPLIB=$(INSTALL_IMPLIB_$(SYS)) -+ - SHARED=yes - SODEF_yes=-fPIC - SOLIB_yes=librtmp.$(SO_EXT) -@@ -108,5 +113,6 @@ install_base: librtmp.a librtmp.pc - - install_so: librtmp.$(SO_EXT) - cp librtmp.$(SO_EXT) $(SODIR) -+ $(INSTALL_IMPLIB) - cd $(SODIR); ln -sf librtmp.$(SO_EXT) librtmp.$(SOX) - --- -1.7.10.4 - - -From 060206d121657d7e45c01ac022dd071c877b4caa Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Fri, 15 Jul 2011 13:46:02 +0300 -Subject: [PATCH 06/64] Check the return value from RTMP_SendBytesReceived() - -This avoids double frees in RTMP_Close(), if the -RTMP_SendBytesReceived() call failed, which earlier led -to RTMP_ReadPacket() writing back an already freed buffer -(freed by RTMP_Close() within WriteN()) into m_vecChannelsIn. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 8d76164..f85cd83 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -1338,7 +1338,8 @@ ReadN(RTMP *r, char *buffer, int n) - r->m_nBytesIn += nRead; - if (r->m_bSendCounter - && r->m_nBytesIn > r->m_nBytesInSent + r->m_nClientBW / 2) -- SendBytesReceived(r); -+ if (!SendBytesReceived(r)) -+ return FALSE; - } - /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d bytes\n", __FUNCTION__, nBytes); */ - #ifdef _DEBUG --- -1.7.10.4 - - -From 159a06ebe6d82ef20f2c77c497d55af00d2e0b78 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Fri, 15 Jul 2011 13:46:03 +0300 -Subject: [PATCH 07/64] Don't try to close an already closed socket - -This could happen if WriteN() (called within SendBytesReceived()) -failed. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index f85cd83..df2cb27 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -3626,7 +3626,9 @@ RTMPSockBuf_Close(RTMPSockBuf *sb) - sb->sb_ssl = NULL; - } - #endif -- return closesocket(sb->sb_socket); -+ if (sb->sb_socket != -1) -+ return closesocket(sb->sb_socket); -+ return 0; - } - - #define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) --- -1.7.10.4 - - -From 530d02fccf24f98e2e318418b2fa3e3420056fda Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Fri, 22 Jul 2011 18:04:05 -0700 -Subject: [PATCH 08/64] Fix MDH_free() for PolarSSL - -Reported by Reijo Tomperi <aggro80@users.sourceforge.net> - -diff --git a/librtmp/dh.h b/librtmp/dh.h -index 8e285a6..efef0fd 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -53,7 +53,7 @@ typedef struct MDH { - } MDH; - - #define MDH_new() calloc(1,sizeof(MDH)) --#define MDH_free(vp) {MDH *dh = vp; dhm_free(&dh->ctx); MP_free(dh->p); MP_free(dh->g); MP_free(dh->pub_key); MP_free(dh->priv_key); free(dh);} -+#define MDH_free(vp) {MDH *_dh = vp; dhm_free(&_dh->ctx); MP_free(_dh->p); MP_free(_dh->g); MP_free(_dh->pub_key); MP_free(_dh->priv_key); free(_dh);} - - static int MDH_generate_key(MDH *dh) - { --- -1.7.10.4 - - -From b627335dc37fd5265ac6d23a441ee2d89ab503c8 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Fri, 22 Jul 2011 18:06:27 -0700 -Subject: [PATCH 09/64] Plug potential memleak - -Reported by Reijo Tomperi <aggro80@users.sourceforge.net> - -diff --git a/rtmpdump.c b/rtmpdump.c -index 89c053a..e506fa9 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -444,7 +444,7 @@ Download(RTMP * rtmp, // connected RTMP object - { - int32_t now, lastUpdate; - int bufferSize = 64 * 1024; -- char *buffer = (char *) malloc(bufferSize); -+ char *buffer; - int nRead = 0; - off_t size = ftello(file); - unsigned long lastPercent = 0; -@@ -505,6 +505,8 @@ Download(RTMP * rtmp, // connected RTMP object - rtmp->m_read.nMetaHeaderSize = nMetaHeaderSize; - rtmp->m_read.nInitialFrameSize = nInitialFrameSize; - -+ buffer = (char *) malloc(bufferSize); -+ - now = RTMP_GetTime(); - lastUpdate = now - 1000; - do --- -1.7.10.4 - - -From ec422962d58b8e0d9bfcf0af6e450e0e349947da Mon Sep 17 00:00:00 2001 -From: "Scott D. Davilla" <davilla@xbmc.org> -Date: Fri, 29 Jul 2011 11:26:35 -0700 -Subject: [PATCH 10/64] Darwin dylib updates - -Bring in line with current practice for Darwin dynamic libs - -diff --git a/librtmp/Makefile b/librtmp/Makefile -index b88baf4..a0125f1 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -52,8 +52,8 @@ SODIR_mingw=$(BINDIR) - SODIR=$(SODIR_$(SYS)) - - SO_LDFLAGS_posix=-shared -Wl,-soname,$@ --SO_LDFLAGS_darwin=-dynamiclib -flat_namespace -undefined suppress -fno-common \ -- -headerpad_max_install_names -+SO_LDFLAGS_darwin=-dynamiclib -twolevel_namespace -undefined dynamic_lookup \ -+ -fno-common -headerpad_max_install_names -install_name $(libdir)/$@ - SO_LDFLAGS_mingw=-shared -Wl,--out-implib,librtmp.dll.a - SO_LDFLAGS=$(SO_LDFLAGS_$(SYS)) - --- -1.7.10.4 - - -From 024d201c36e1b40f4f4d473e87d405e1b411230f Mon Sep 17 00:00:00 2001 -From: KSV <faltuvisitor@yahoo.co.in> -Date: Sun, 31 Jul 2011 12:33:46 -0700 -Subject: [PATCH 11/64] Justin.TV usherToken detection - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index f1b6c66..805ce0d 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -95,6 +95,7 @@ STREAMING_SERVER *rtmpServer = 0; // server structure pointer - - STREAMING_SERVER *startStreaming(const char *address, int port); - void stopStreaming(STREAMING_SERVER * server); -+char *strreplace(char *srcstr, int srclen, char *orig, char *repl); - - typedef struct - { -@@ -261,6 +262,7 @@ static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop"); - static const AVal av_Stopped_playing = AVC("Stopped playing"); - SAVC(details); - SAVC(clientid); -+static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken"); - - static int - SendPlayStart(RTMP *r) -@@ -575,6 +577,13 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - { - SendResultNumber(r, txn, 10.0); - } -+ else if (AVMATCH(&method, &av_NetStream_Authenticate_UsherToken)) -+ { -+ AMFObjectProperty *prop = AMF_GetProp(&obj, NULL, 3); -+ AMFProp_GetString(prop, &r->Link.usherToken); -+ prop->p_vu.p_aval.av_len = 0; -+ prop->p_vu.p_aval.av_val = NULL; -+ } - else if (AVMATCH(&method, &av_play)) - { - char *file, *p, *q, *cmd, *ptr; -@@ -591,10 +600,11 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - if (r->Link.tcUrl.av_len) - { - len = server->arglen + r->Link.playpath.av_len + 4 + -- sizeof("rtmpdump") + r->Link.playpath.av_len + 12; -+ sizeof("rtmpdump") + r->Link.playpath.av_len + 12 + -+ r->Link.usherToken.av_len + 64; - server->argc += 5; - -- cmd = malloc(len + server->argc * sizeof(AVal)); -+ cmd = malloc(len + (server->argc + 2) * sizeof(AVal)); - ptr = cmd; - argv = (AVal *)(cmd + len); - argv[0].av_val = cmd; -@@ -640,6 +650,17 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - ptr += sprintf(ptr, " -p \"%s\"", r->Link.pageUrl.av_val); - argv[argc++].av_len = r->Link.pageUrl.av_len; - } -+ if (r->Link.usherToken.av_val) -+ { -+ char *usherToken = strreplace(r->Link.usherToken.av_val, r->Link.usherToken.av_len, "\"", "\\\""); -+ argv[argc].av_val = ptr + 1; -+ argv[argc++].av_len = 5; -+ argv[argc].av_val = ptr + 8; -+ ptr += sprintf(ptr, " --jtv \"%s\"", usherToken); -+ argv[argc++].av_len = strlen(usherToken); -+ server->argc += 2; -+ free(usherToken); -+ } - if (r->Link.extras.o_num) { - ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc); - AMF_Reset(&r->Link.extras); -@@ -1111,3 +1132,39 @@ main(int argc, char **argv) - #endif - return nStatus; - } -+ -+char * -+strreplace(char *srcstr, int srclen, char *orig, char *repl) -+{ -+ char *ptr = NULL, *srcstrstart = srcstr; -+ int origlen = strlen(orig); -+ int repllen = strlen(repl); -+ if (!srclen) -+ srclen = strlen(srcstr); -+ char *srcend = srcstr + srclen; -+ int deststrbuffer = srclen / origlen * repllen; -+ if (deststrbuffer < srclen) -+ deststrbuffer = srclen; -+ char *deststr = calloc(deststrbuffer + 1, sizeof(char)); -+ char *deststrstart = deststr; -+ -+ if ( (ptr = strstr(srcstr, orig)) ) -+ { -+ do -+ { -+ int len = ptr - srcstrstart; -+ memcpy(deststrstart, srcstrstart, len); -+ srcstrstart += len + origlen; -+ deststrstart += len; -+ memcpy(deststrstart, repl, repllen); -+ deststrstart += repllen; -+ ptr = strstr(srcstrstart, orig); -+ } -+ while (ptr && (ptr < srcend)); -+ strncpy(deststrstart, srcstrstart, srcend-srcstrstart); -+ return deststr; -+ } -+ -+ strncpy(deststr, srcstr, srclen); -+ return deststr; -+} --- -1.7.10.4 - - -From f1abda046ca5a3f1efa63033c542e686b43dbcf3 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Sun, 31 Jul 2011 13:21:12 -0700 -Subject: [PATCH 12/64] Cleanup previous commit - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index 805ce0d..b45aae3 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -1,6 +1,6 @@ - /* Simple RTMP Server - * Copyright (C) 2009 Andrej Stepanchuk -- * Copyright (C) 2009 Howard Chu -+ * Copyright (C) 2009-2011 Howard Chu - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -95,7 +95,10 @@ STREAMING_SERVER *rtmpServer = 0; // server structure pointer - - STREAMING_SERVER *startStreaming(const char *address, int port); - void stopStreaming(STREAMING_SERVER * server); --char *strreplace(char *srcstr, int srclen, char *orig, char *repl); -+void AVreplace(AVal *src, const AVal *orig, const AVal *repl); -+ -+static const AVal av_dquote = AVC("\""); -+static const AVal av_escdquote = AVC("\\\""); - - typedef struct - { -@@ -579,10 +582,12 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - } - else if (AVMATCH(&method, &av_NetStream_Authenticate_UsherToken)) - { -- AMFObjectProperty *prop = AMF_GetProp(&obj, NULL, 3); -- AMFProp_GetString(prop, &r->Link.usherToken); -- prop->p_vu.p_aval.av_len = 0; -- prop->p_vu.p_aval.av_val = NULL; -+ AVal usherToken; -+ AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &usherToken); -+ AVreplace(&usherToken, &av_dquote, &av_escdquote); -+ server->arglen += 6 + usherToken.av_len; -+ server->argc += 2; -+ r->Link.usherToken = usherToken; - } - else if (AVMATCH(&method, &av_play)) - { -@@ -600,11 +605,10 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - if (r->Link.tcUrl.av_len) - { - len = server->arglen + r->Link.playpath.av_len + 4 + -- sizeof("rtmpdump") + r->Link.playpath.av_len + 12 + -- r->Link.usherToken.av_len + 64; -+ sizeof("rtmpdump") + r->Link.playpath.av_len + 12; - server->argc += 5; - -- cmd = malloc(len + (server->argc + 2) * sizeof(AVal)); -+ cmd = malloc(len + server->argc * sizeof(AVal)); - ptr = cmd; - argv = (AVal *)(cmd + len); - argv[0].av_val = cmd; -@@ -650,17 +654,17 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int - ptr += sprintf(ptr, " -p \"%s\"", r->Link.pageUrl.av_val); - argv[argc++].av_len = r->Link.pageUrl.av_len; - } -- if (r->Link.usherToken.av_val) -- { -- char *usherToken = strreplace(r->Link.usherToken.av_val, r->Link.usherToken.av_len, "\"", "\\\""); -+ if (r->Link.usherToken.av_val) -+ { - argv[argc].av_val = ptr + 1; -- argv[argc++].av_len = 5; -- argv[argc].av_val = ptr + 8; -- ptr += sprintf(ptr, " --jtv \"%s\"", usherToken); -- argv[argc++].av_len = strlen(usherToken); -- server->argc += 2; -- free(usherToken); -- } -+ argv[argc++].av_len = 2; -+ argv[argc].av_val = ptr + 5; -+ ptr += sprintf(ptr, " -j \"%s\"", r->Link.usherToken.av_val); -+ argv[argc++].av_len = r->Link.usherToken.av_len; -+ free(r->Link.usherToken.av_val); -+ r->Link.usherToken.av_val = NULL; -+ r->Link.usherToken.av_len = 0; -+ } - if (r->Link.extras.o_num) { - ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc); - AMF_Reset(&r->Link.extras); -@@ -932,6 +936,11 @@ cleanup: - rtmp.Link.pageUrl.av_val = NULL; - rtmp.Link.app.av_val = NULL; - rtmp.Link.flashVer.av_val = NULL; -+ if (rtmp.Link.usherToken.av_val) -+ { -+ free(rtmp.Link.usherToken.av_val); -+ rtmp.Link.usherToken.av_val = NULL; -+ } - RTMP_LogPrintf("done!\n\n"); - - quit: -@@ -1133,38 +1142,42 @@ main(int argc, char **argv) - return nStatus; - } - --char * --strreplace(char *srcstr, int srclen, char *orig, char *repl) -+void -+AVreplace(AVal *src, const AVal *orig, const AVal *repl) - { -- char *ptr = NULL, *srcstrstart = srcstr; -- int origlen = strlen(orig); -- int repllen = strlen(repl); -- if (!srclen) -- srclen = strlen(srcstr); -- char *srcend = srcstr + srclen; -- int deststrbuffer = srclen / origlen * repllen; -- if (deststrbuffer < srclen) -- deststrbuffer = srclen; -- char *deststr = calloc(deststrbuffer + 1, sizeof(char)); -- char *deststrstart = deststr; -- -- if ( (ptr = strstr(srcstr, orig)) ) -- { -- do -+ char *srcbeg = src->av_val; -+ char *srcend = src->av_val + src->av_len; -+ char *dest, *sptr, *dptr; -+ int n = 0; -+ -+ /* count occurrences of orig in src */ -+ sptr = src->av_val; -+ while (sptr < srcend && (sptr = strstr(sptr, orig->av_val))) - { -- int len = ptr - srcstrstart; -- memcpy(deststrstart, srcstrstart, len); -- srcstrstart += len + origlen; -- deststrstart += len; -- memcpy(deststrstart, repl, repllen); -- deststrstart += repllen; -- ptr = strstr(srcstrstart, orig); -+ n++; -+ sptr += orig->av_len; - } -- while (ptr && (ptr < srcend)); -- strncpy(deststrstart, srcstrstart, srcend-srcstrstart); -- return deststr; -- } -+ if (!n) -+ return; - -- strncpy(deststr, srcstr, srclen); -- return deststr; -+ dest = malloc(src->av_len + 1 + (repl->av_len - orig->av_len) * n); -+ -+ sptr = src->av_val; -+ dptr = dest; -+ while (sptr < srcend && (sptr = strstr(sptr, orig->av_val))) -+ { -+ n = sptr - srcbeg; -+ memcpy(dptr, srcbeg, n); -+ srcbeg += n; -+ dptr += n; -+ memcpy(dptr, repl->av_val, repl->av_len); -+ dptr += repl->av_len; -+ sptr += orig->av_len; -+ } -+ n = srcend - srcbeg; -+ memcpy(dptr, srcbeg, n); -+ dptr += n; -+ *dptr = '\0'; -+ src->av_val = dest; -+ src->av_len = dptr - dest; - } --- -1.7.10.4 - - -From 8880d1456b282ee79979adbe7b6a6eb8ad371081 Mon Sep 17 00:00:00 2001 -From: Chris Larsen <clarsen@euphoriaaudio.com> -Date: Tue, 2 Aug 2011 12:33:44 -0400 -Subject: [PATCH 13/64] Unexpected BW Response Fix - -Bug: SendCheckBWResult sends an invalid bw response due to casting issues -from a double to an int. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index df2cb27..5311a8a 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2339,7 +2339,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) - { - AMFObject obj; - AVal method; -- int txn; -+ double txn; - int ret = 0, nRes; - if (body[0] != 0x02) /* make sure it is a string method name we start with */ - { -@@ -2357,7 +2357,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) - - AMF_Dump(&obj); - AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method); -- txn = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1)); -+ txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1)); - RTMP_Log(RTMP_LOGDEBUG, "%s, server invoking <%s>", __FUNCTION__, method.av_val); - - if (AVMATCH(&method, &av__result)) -@@ -2366,7 +2366,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) - int i; - - for (i=0; i<r->m_numCalls; i++) { -- if (r->m_methodCalls[i].num == txn) { -+ if (r->m_methodCalls[i].num == (int)txn) { - methodInvoked = r->m_methodCalls[i].name; - AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE); - break; --- -1.7.10.4 - - -From c528451068de033d7cc76eb1c5a606c10215fcfb Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Wed, 3 Aug 2011 11:46:07 -0700 -Subject: [PATCH 14/64] Fix <arpa/inet.h> include order - - -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 6a3f215..638374f 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -46,10 +46,10 @@ - #include <sys/socket.h> - #include <sys/times.h> - #include <netdb.h> --#include <arpa/inet.h> - #include <unistd.h> - #include <netinet/in.h> - #include <netinet/tcp.h> -+#include <arpa/inet.h> - #define GetSockError() errno - #define SetSockError(e) errno = e - #undef closesocket --- -1.7.10.4 - - -From a1114e09bf0d74ef1d575eb88f3aa36bc7c6d790 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 9 Aug 2011 14:44:14 -0700 -Subject: [PATCH 15/64] Fix AVreplace for usherToken - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index b45aae3..91fc4da 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -1168,11 +1168,11 @@ AVreplace(AVal *src, const AVal *orig, const AVal *repl) - { - n = sptr - srcbeg; - memcpy(dptr, srcbeg, n); -- srcbeg += n; - dptr += n; - memcpy(dptr, repl->av_val, repl->av_len); - dptr += repl->av_len; - sptr += orig->av_len; -+ srcbeg = sptr; - } - n = srcend - srcbeg; - memcpy(dptr, srcbeg, n); --- -1.7.10.4 - - -From c58cfb3e9208c6e6bc1aa18f1b1d650d799084e5 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Thu, 11 Aug 2011 18:02:10 -0700 -Subject: [PATCH 16/64] Add RD_NO_CONNECT return code for Connect failures - - -diff --git a/rtmpdump.c b/rtmpdump.c -index e506fa9..01decf9 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -46,6 +46,7 @@ - #define RD_SUCCESS 0 - #define RD_FAILED 1 - #define RD_INCOMPLETE 2 -+#define RD_NO_CONNECT 3 - - #define DEF_TIMEOUT 30 /* seconds */ - #define DEF_BUFTIME (10 * 60 * 60 * 1000) /* 10 hours default */ -@@ -1253,7 +1254,7 @@ main(int argc, char **argv) - - if (!RTMP_Connect(&rtmp, NULL)) - { -- nStatus = RD_FAILED; -+ nStatus = RD_NO_CONNECT; - break; - } - --- -1.7.10.4 - - -From 6230845ab0fba07289d4b2d9b97269e4b2d90766 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Sun, 25 Sep 2011 03:07:14 -0700 -Subject: [PATCH 17/64] PolarSSL support now requires version 1.0.0. - - -diff --git a/README b/README -index 865c6c4..dcf5f52 100644 ---- a/README -+++ b/README -@@ -50,6 +50,7 @@ library. You can also turn it off if desired - The rtmpdump programs still link to the static library, regardless. - - Note that if using OpenSSL, you must have version 0.9.8 or newer. -+For Polar SSL you must have version 1.0.0 or newer. - - Credit goes to team boxee for the XBMC RTMP code originally used in RTMPDumper. - The current code is based on the XBMC code but rewritten in C by Howard Chu. -diff --git a/librtmp/dh.h b/librtmp/dh.h -index efef0fd..a9f3763 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -30,14 +30,14 @@ - #ifdef USE_POLARSSL - #include <polarssl/dhm.h> - typedef mpi * MP_t; --#define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m, NULL) -+#define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m) - #define MP_set_w(mpi, w) mpi_lset(mpi, w) - #define MP_cmp(u, v) mpi_cmp_mpi(u, v) - #define MP_set(u, v) mpi_copy(u, v) - #define MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w) - #define MP_cmp_1(mpi) mpi_cmp_int(mpi, 1) - #define MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL) --#define MP_free(mpi) mpi_free(mpi, NULL); free(mpi) -+#define MP_free(mpi) mpi_free(mpi); free(mpi) - #define MP_gethex(u, hex, res) MP_new(u); res = mpi_read_string(u, 16, hex) == 0 - #define MP_bytes(u) mpi_size(u) - #define MP_setbin(u,buf,len) mpi_write_binary(u,buf,len) -@@ -71,9 +71,8 @@ static int MDH_generate_key(MDH *dh) - - static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) - { -- int n = len; - MP_set(&dh->ctx.GY, pub); -- dhm_calc_secret(&dh->ctx, secret, &n); -+ dhm_calc_secret(&dh->ctx, secret, &len); - return 0; - } - -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 638374f..c3fd4a6 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -71,7 +71,8 @@ typedef struct tls_ctx { - #define TLS_CTX tls_ctx * - #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ - ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ -- ssl_set_rng(s, havege_rand, &ctx->hs); ssl_set_ciphers(s, ssl_default_ciphers);\ -+ ssl_set_rng(s, havege_rand, &ctx->hs);\ -+ ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ - ssl_set_session(s, 1, 600, &ctx->ssn) - #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) - #define TLS_connect(s) ssl_handshake(s) --- -1.7.10.4 - - -From 60218d0af0f4bd683ecdebe49986f188820cf8ce Mon Sep 17 00:00:00 2001 -From: Kirill Zorin <cyril.zorin@gmail.com> -Date: Fri, 30 Sep 2011 13:38:23 -0400 -Subject: [PATCH 18/64] fixed undefined behaviour due to union assignment - - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index 7fa289e..ae920e4 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -1111,7 +1111,7 @@ AMF_AddProp(AMFObject *obj, const AMFObjectProperty *prop) - if (!(obj->o_num & 0x0f)) - obj->o_props = - realloc(obj->o_props, (obj->o_num + 16) * sizeof(AMFObjectProperty)); -- obj->o_props[obj->o_num++] = *prop; -+ memcpy(&obj->o_props[obj->o_num++], prop, sizeof(AMFObjectProperty)); - } - - int -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 5311a8a..4b17a49 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2584,7 +2584,7 @@ RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name, - - if (AVMATCH(&prop->p_name, name)) - { -- *p = *prop; -+ memcpy(p, prop, sizeof(*prop)); - return TRUE; - } - -@@ -2610,7 +2610,7 @@ RTMP_FindPrefixProperty(AMFObject *obj, const AVal *name, - if (prop->p_name.av_len > name->av_len && - !memcmp(prop->p_name.av_val, name->av_val, name->av_len)) - { -- *p = *prop; -+ memcpy(p, prop, sizeof(*prop)); - return TRUE; - } - --- -1.7.10.4 - - -From c90c05892cbaebfb1b2095759597d9fb38238c64 Mon Sep 17 00:00:00 2001 -From: KSV <faltuvistor@yahoo.co.in> -Date: Mon, 7 Nov 2011 11:38:27 -0800 -Subject: [PATCH 19/64] Fix bytes-received report - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 4b17a49..a9c1bc1 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -1337,7 +1337,7 @@ ReadN(RTMP *r, char *buffer, int n) - nBytes = nRead; - r->m_nBytesIn += nRead; - if (r->m_bSendCounter -- && r->m_nBytesIn > r->m_nBytesInSent + r->m_nClientBW / 2) -+ && r->m_nBytesIn > ( r->m_nBytesInSent + r->m_nClientBW / 10)) - if (!SendBytesReceived(r)) - return FALSE; - } --- -1.7.10.4 - - -From b3467069ad7c26d748ca13ce0ee88a41f85b22dd Mon Sep 17 00:00:00 2001 -From: Jeff Johnson <jeff@rogueamoeba.com> -Date: Mon, 7 Nov 2011 11:43:26 -0800 -Subject: [PATCH 20/64] Fix getting swf hash with https URLs - - -diff --git a/librtmp/hashswf.c b/librtmp/hashswf.c -index 3c56b69..5576730 100644 ---- a/librtmp/hashswf.c -+++ b/librtmp/hashswf.c -@@ -163,7 +163,7 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb) - #else - TLS_client(RTMP_TLS_ctx, sb.sb_ssl); - TLS_setfd(sb.sb_ssl, sb.sb_socket); -- if ((i = TLS_connect(sb.sb_ssl)) < 0) -+ if (TLS_connect(sb.sb_ssl) < 0) - { - RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__); - ret = HTTPRES_LOST_CONNECTION; --- -1.7.10.4 - - -From 90799efbb67f415ff930d68905e8267d5aa5dc4e Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 8 Nov 2011 02:04:01 -0800 -Subject: [PATCH 21/64] Increase tcUrl buffer size - - -diff --git a/rtmpdump.c b/rtmpdump.c -index 01decf9..a8fa128 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -1152,9 +1152,9 @@ main(int argc, char **argv) - - if (tcUrl.av_len == 0) - { -- char str[512] = { 0 }; -+ char str[1024]; - -- tcUrl.av_len = snprintf(str, 511, "%s://%.*s:%d/%.*s", -+ tcUrl.av_len = snprintf(str, sizeof(str), "%s://%.*s:%d/%.*s", - RTMPProtocolStringsLower[protocol], hostname.av_len, - hostname.av_val, port, app.av_len, app.av_val); - tcUrl.av_val = (char *) malloc(tcUrl.av_len + 1); --- -1.7.10.4 - - -From 9df7959a71ec33cc9c83c9d3ef25c17b1c527f0e Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 8 Nov 2011 02:05:01 -0800 -Subject: [PATCH 22/64] Spell Referer according to RFC1945 - - -diff --git a/librtmp/hashswf.c b/librtmp/hashswf.c -index 5576730..0320480 100644 ---- a/librtmp/hashswf.c -+++ b/librtmp/hashswf.c -@@ -141,7 +141,7 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb) - return HTTPRES_LOST_CONNECTION; - i = - sprintf(sb.sb_buf, -- "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferrer: %.*s\r\n", -+ "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferer: %.*s\r\n", - path, AGENT, host, (int)(path - url + 1), url); - if (http->date[0]) - i += sprintf(sb.sb_buf + i, "If-Modified-Since: %s\r\n", http->date); --- -1.7.10.4 - - -From 1c77ff43439068981d2ad9872952922a1ee37f89 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 8 Nov 2011 02:13:14 -0800 -Subject: [PATCH 23/64] Calculate tcUrl length - - -diff --git a/rtmpdump.c b/rtmpdump.c -index a8fa128..892a8bc 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -1152,13 +1152,12 @@ main(int argc, char **argv) - - if (tcUrl.av_len == 0) - { -- char str[1024]; -- -- tcUrl.av_len = snprintf(str, sizeof(str), "%s://%.*s:%d/%.*s", -+ tcUrl.av_len = strlen(RTMPProtocolStringsLower[protocol]) + -+ hostname.av_len + app.av_len + sizeof("://:65535/"); -+ tcUrl.av_val = (char *) malloc(tcUrl.av_len); -+ tcUrl.av_len = snprintf(tcUrl.av_val, tcUrl.av_len, "%s://%.*s:%d/%.*s", - RTMPProtocolStringsLower[protocol], hostname.av_len, - hostname.av_val, port, app.av_len, app.av_val); -- tcUrl.av_val = (char *) malloc(tcUrl.av_len + 1); -- strcpy(tcUrl.av_val, str); - } - - int first = 1; --- -1.7.10.4 - - -From 30fcf46fc82f96ca41b710fc38bbc15f2489795e Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 8 Nov 2011 02:14:21 -0800 -Subject: [PATCH 24/64] Check for malloc failure in prev commit - - -diff --git a/rtmpdump.c b/rtmpdump.c -index 892a8bc..c37def2 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -1155,6 +1155,8 @@ main(int argc, char **argv) - tcUrl.av_len = strlen(RTMPProtocolStringsLower[protocol]) + - hostname.av_len + app.av_len + sizeof("://:65535/"); - tcUrl.av_val = (char *) malloc(tcUrl.av_len); -+ if (!tcUrl.av_val) -+ return RD_FAILED; - tcUrl.av_len = snprintf(tcUrl.av_val, tcUrl.av_len, "%s://%.*s:%d/%.*s", - RTMPProtocolStringsLower[protocol], hostname.av_len, - hostname.av_val, port, app.av_len, app.av_val); --- -1.7.10.4 - - -From 83e701eef0d7947713280fe3e7561bed1e7195f5 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 14 Nov 2011 16:09:26 -0800 -Subject: [PATCH 25/64] Fix missing log message parameter - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index a9c1bc1..4da318b 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -974,7 +974,7 @@ SocksNegotiate(RTMP *r) - } - else - { -- RTMP_Log(RTMP_LOGERROR, "%s, SOCKS returned error code %d", packet[1]); -+ RTMP_Log(RTMP_LOGERROR, "%s, SOCKS returned error code %d", __FUNCTION__, packet[1]); - return FALSE; - } - } --- -1.7.10.4 - - -From 949da84ab1f659597d6e7fa1ef0ab8fc1ca8e246 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 14 Nov 2011 16:11:13 -0800 -Subject: [PATCH 26/64] Tell gcc about log format strings - - -diff --git a/librtmp/log.h b/librtmp/log.h -index 97c9aac..2adb111 100644 ---- a/librtmp/log.h -+++ b/librtmp/log.h -@@ -48,9 +48,15 @@ extern RTMP_LogLevel RTMP_debuglevel; - typedef void (RTMP_LogCallback)(int level, const char *fmt, va_list); - void RTMP_LogSetCallback(RTMP_LogCallback *cb); - void RTMP_LogSetOutput(FILE *file); -+#ifdef __GNUC__ -+void RTMP_LogPrintf(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); -+void RTMP_LogStatus(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2))); -+void RTMP_Log(int level, const char *format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -+#else - void RTMP_LogPrintf(const char *format, ...); - void RTMP_LogStatus(const char *format, ...); - void RTMP_Log(int level, const char *format, ...); -+#endif - void RTMP_LogHex(int level, const uint8_t *data, unsigned long len); - void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len); - void RTMP_LogSetLevel(RTMP_LogLevel lvl); --- -1.7.10.4 - - -From 45556fb3b372402d7bd5235832176f58dede90ae Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 14 Nov 2011 16:12:26 -0800 -Subject: [PATCH 27/64] Fix mismatched format string conversions - - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index ae920e4..f9ecf21 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -586,7 +586,7 @@ AMF3Prop_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - case AMF3_ARRAY: - case AMF3_BYTE_ARRAY: - default: -- RTMP_Log(RTMP_LOGDEBUG, "%s - AMF3 unknown/unsupported datatype 0x%02x, @0x%08X", -+ RTMP_Log(RTMP_LOGDEBUG, "%s - AMF3 unknown/unsupported datatype 0x%02x, @%p", - __FUNCTION__, (unsigned char)(*pBuffer), pBuffer); - return -1; - } -@@ -772,7 +772,7 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - break; - } - default: -- RTMP_Log(RTMP_LOGDEBUG, "%s - unknown datatype 0x%02x, @0x%08X", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s - unknown datatype 0x%02x, @%p", __FUNCTION__, - prop->p_type, pBuffer - 1); - return -1; - } -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 4da318b..52d0254 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -185,7 +185,7 @@ void - RTMPPacket_Dump(RTMPPacket *p) - { - RTMP_Log(RTMP_LOGDEBUG, -- "RTMP PACKET: packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %lu. body: 0x%02x", -+ "RTMP PACKET: packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %u. body: 0x%02x", - p->m_packetType, p->m_nChannel, p->m_nTimeStamp, p->m_nInfoField2, - p->m_nBodySize, p->m_body ? (unsigned char)p->m_body[0] : 0); - } -@@ -367,7 +367,7 @@ RTMP_SetupStream(RTMP *r, - RTMP_Log(RTMP_LOGDEBUG, "StopTime : %d msec", dStop); - - RTMP_Log(RTMP_LOGDEBUG, "live : %s", bLiveStream ? "yes" : "no"); -- RTMP_Log(RTMP_LOGDEBUG, "timeout : %d sec", timeout); -+ RTMP_Log(RTMP_LOGDEBUG, "timeout : %ld sec", timeout); - - #ifdef CRYPTO - if (swfSHA256Hash != NULL && swfSize > 0) -@@ -376,7 +376,7 @@ RTMP_SetupStream(RTMP *r, - r->Link.SWFSize = swfSize; - RTMP_Log(RTMP_LOGDEBUG, "SWFSHA256:"); - RTMP_LogHex(RTMP_LOGDEBUG, r->Link.SWFHash, sizeof(r->Link.SWFHash)); -- RTMP_Log(RTMP_LOGDEBUG, "SWFSize : %lu", r->Link.SWFSize); -+ RTMP_Log(RTMP_LOGDEBUG, "SWFSize : %u", r->Link.SWFSize); - } - else - { -@@ -1161,14 +1161,14 @@ RTMP_ClientPacket(RTMP *r, RTMPPacket *packet) - case RTMP_PACKET_TYPE_FLEX_STREAM_SEND: - /* flex stream send */ - RTMP_Log(RTMP_LOGDEBUG, -- "%s, flex stream send, size %lu bytes, not supported, ignoring", -+ "%s, flex stream send, size %u bytes, not supported, ignoring", - __FUNCTION__, packet->m_nBodySize); - break; - - case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT: - /* flex shared object */ - RTMP_Log(RTMP_LOGDEBUG, -- "%s, flex shared object, size %lu bytes, not supported, ignoring", -+ "%s, flex shared object, size %u bytes, not supported, ignoring", - __FUNCTION__, packet->m_nBodySize); - break; - -@@ -1176,7 +1176,7 @@ RTMP_ClientPacket(RTMP *r, RTMPPacket *packet) - /* flex message */ - { - RTMP_Log(RTMP_LOGDEBUG, -- "%s, flex message, size %lu bytes, not fully supported", -+ "%s, flex message, size %u bytes, not fully supported", - __FUNCTION__, packet->m_nBodySize); - /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ - -@@ -1198,7 +1198,7 @@ RTMP_ClientPacket(RTMP *r, RTMPPacket *packet) - } - case RTMP_PACKET_TYPE_INFO: - /* metadata (notify) */ -- RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %lu bytes", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %u bytes", __FUNCTION__, - packet->m_nBodySize); - if (HandleMetadata(r, packet->m_body, packet->m_nBodySize)) - bHasMediaPacket = 1; -@@ -1211,7 +1211,7 @@ RTMP_ClientPacket(RTMP *r, RTMPPacket *packet) - - case RTMP_PACKET_TYPE_INVOKE: - /* invoke */ -- RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %lu bytes", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__, - packet->m_nBodySize); - /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */ - -@@ -2373,7 +2373,7 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) - } - } - if (!methodInvoked.av_val) { -- RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %d without matching request", -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request", - __FUNCTION__, txn); - goto leave; - } -@@ -3055,7 +3055,7 @@ RTMP_ReadPacket(RTMP *r, RTMPPacket *packet) - - if (ReadN(r, packet->m_body + packet->m_nBytesRead, nChunk) != nChunk) - { -- RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet body. len: %lu", -+ RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet body. len: %u", - __FUNCTION__, packet->m_nBodySize); - return FALSE; - } -@@ -4176,7 +4176,7 @@ Read_1_Packet(RTMP *r, char *buf, unsigned int buflen) - if (pos + 11 + dataSize > nPacketLen) - { - RTMP_Log(RTMP_LOGERROR, -- "Wrong data size (%lu), stream corrupted, aborting!", -+ "Wrong data size (%u), stream corrupted, aborting!", - dataSize); - ret = RTMP_READ_ERROR; - break; --- -1.7.10.4 - - -From 5d03a4f0d6216da92830306436eae7eb318d5115 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Mon, 14 Nov 2011 16:17:27 -0800 -Subject: [PATCH 28/64] Fix log messages - - -diff --git a/rtmpdump.c b/rtmpdump.c -index c37def2..34bfdba 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -686,7 +686,7 @@ void usage(char *prog) - RTMP_LogPrintf - ("--resume|-e Resume a partial RTMP download\n"); - RTMP_LogPrintf -- ("--timeout|-m num Timeout connection num seconds (default: %lu)\n", -+ ("--timeout|-m num Timeout connection num seconds (default: %u)\n", - DEF_TIMEOUT); - RTMP_LogPrintf - ("--start|-A num Start at num seconds into stream (not valid when using --live)\n"); -@@ -699,7 +699,7 @@ void usage(char *prog) - RTMP_LogPrintf - ("--hashes|-# Display progress with hashes, not with the byte counter\n"); - RTMP_LogPrintf -- ("--buffer|-b Buffer time in milliseconds (default: %lu)\n", -+ ("--buffer|-b Buffer time in milliseconds (default: %u)\n", - DEF_BUFTIME); - RTMP_LogPrintf - ("--skip|-k num Skip num keyframes when looking for last keyframe to resume from. Useful if resume fails (default: %d)\n\n", -diff --git a/rtmpgw.c b/rtmpgw.c -index 733e105..0cf56bb 100644 ---- a/rtmpgw.c -+++ b/rtmpgw.c -@@ -563,7 +563,7 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou - rtmp.Link.token = req.token; - rtmp.m_read.timestamp = dSeek; - -- RTMP_LogPrintf("Connecting ... port: %d, app: %s\n", req.rtmpport, req.app); -+ RTMP_LogPrintf("Connecting ... port: %d, app: %s\n", req.rtmpport, req.app.av_val); - if (!RTMP_Connect(&rtmp, NULL)) - { - RTMP_LogPrintf("%s, failed to connect!\n", __FUNCTION__); -@@ -738,7 +738,7 @@ stopStreaming(STREAMING_SERVER * server) - - if (closesocket(server->socket)) - RTMP_Log(RTMP_LOGERROR, "%s: Failed to close listening socket, error %d", -- GetSockError()); -+ __FUNCTION__, GetSockError()); - - server->state = STREAMING_STOPPED; - } -@@ -1103,7 +1103,7 @@ main(int argc, char **argv) - 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", -+ ("--buffer|-b Buffer time in milliseconds (default: %u)\n\n", - defaultRTMPRequest.bufferTime); - - RTMP_LogPrintf -diff --git a/rtmpsrv.c b/rtmpsrv.c -index 91fc4da..b662d54 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -765,7 +765,7 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - { - int ret = 0; - -- RTMP_Log(RTMP_LOGDEBUG, "%s, received packet type %02X, size %lu bytes", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received packet type %02X, size %u bytes", __FUNCTION__, - packet->m_packetType, packet->m_nBodySize); - - switch (packet->m_packetType) -@@ -812,7 +812,7 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - - case 0x11: // flex message - { -- RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %lu bytes, not fully supported", -+ RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %u bytes, not fully supported", - __FUNCTION__, packet->m_nBodySize); - //RTMP_LogHex(packet.m_body, packet.m_nBodySize); - -@@ -840,7 +840,7 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - - case 0x14: - // invoke -- RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %lu bytes", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__, - packet->m_nBodySize); - //RTMP_LogHex(packet.m_body, packet.m_nBodySize); - -@@ -1053,7 +1053,7 @@ stopStreaming(STREAMING_SERVER * server) - - if (closesocket(server->socket)) - RTMP_Log(RTMP_LOGERROR, "%s: Failed to close listening socket, error %d", -- GetSockError()); -+ __FUNCTION__, GetSockError()); - - server->state = STREAMING_STOPPED; - } -diff --git a/rtmpsuck.c b/rtmpsuck.c -index 661e64b..e886179 100644 ---- a/rtmpsuck.c -+++ b/rtmpsuck.c -@@ -456,7 +456,7 @@ ServePacket(STREAMING_SERVER *server, int which, RTMPPacket *packet) - { - int ret = 0; - -- RTMP_Log(RTMP_LOGDEBUG, "%s, %s sent packet type %02X, size %lu bytes", __FUNCTION__, -+ RTMP_Log(RTMP_LOGDEBUG, "%s, %s sent packet type %02X, size %u bytes", __FUNCTION__, - cst[which], packet->m_packetType, packet->m_nBodySize); - - switch (packet->m_packetType) -@@ -649,7 +649,7 @@ WriteStream(char **buf, // target pointer, maybe preallocated - if (pos + 11 + dataSize > nPacketLen) - { - RTMP_Log(RTMP_LOGERROR, -- "Wrong data size (%lu), stream corrupted, aborting!", -+ "Wrong data size (%u), stream corrupted, aborting!", - dataSize); - ret = -2; - break; -@@ -1117,7 +1117,7 @@ stopStreaming(STREAMING_SERVER * server) - - if (fd && closesocket(fd)) - RTMP_Log(RTMP_LOGERROR, "%s: Failed to close listening socket, error %d", -- GetSockError()); -+ __FUNCTION__, GetSockError()); - - server->state = STREAMING_STOPPED; - } --- -1.7.10.4 - - -From 4e06e218e230a86608637b613499984703a342cf Mon Sep 17 00:00:00 2001 -From: Antti Ajanki <antti.ajanki@iki.fi> -Date: Thu, 22 Dec 2011 17:54:10 -0800 -Subject: [PATCH 29/64] Support decoding AMF_XML_DOC - -MF_XML_DOC data is an XML document which is encoded similarly to a -long string. - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index f9ecf21..659421e 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -735,13 +735,15 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - break; - } - case AMF_LONG_STRING: -+ case AMF_XML_DOC: - { - unsigned int nStringSize = AMF_DecodeInt32(pBuffer); - if (nSize < (long)nStringSize + 4) - return -1; - AMF_DecodeLongString(pBuffer, &prop->p_vu.p_aval); - nSize -= (4 + nStringSize); -- prop->p_type = AMF_STRING; -+ if (prop->p_type == AMF_LONG_STRING) -+ prop->p_type = AMF_STRING; - break; - } - case AMF_RECORDSET: -@@ -750,12 +752,6 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - return -1; - break; - } -- case AMF_XML_DOC: -- { -- RTMP_Log(RTMP_LOGERROR, "AMF_XML_DOC not supported!"); -- return -1; -- break; -- } - case AMF_TYPED_OBJECT: - { - RTMP_Log(RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!"); --- -1.7.10.4 - - -From adb77ff4d72cea92b7c307ccb64e9aa930d866da Mon Sep 17 00:00:00 2001 -From: Joshua Allmann <joshua.allmann@gmail.com> -Date: Fri, 24 Feb 2012 13:44:29 -0800 -Subject: [PATCH 30/64] Remove extra object end tag in Connect reply - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index b662d54..9aa62f3 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -223,9 +223,6 @@ SendConnectResult(RTMP *r, double txn) - *enc++ = 0; - *enc++ = 0; - *enc++ = AMF_OBJECT_END; -- *enc++ = 0; -- *enc++ = 0; -- *enc++ = AMF_OBJECT_END; - - packet.m_nBodySize = enc - packet.m_body; - --- -1.7.10.4 - - -From 2ad1d5d133a46ceeaaa05c9375e293f332871f3b Mon Sep 17 00:00:00 2001 -From: Josh Allmann <joshua.allmann@gmail.com> -Date: Fri, 24 Feb 2012 13:46:59 -0800 -Subject: [PATCH 31/64] Fix upper bound check in AMF_GetProp - - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index 659421e..ce84f81 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -1121,7 +1121,7 @@ AMF_GetProp(AMFObject *obj, const AVal *name, int nIndex) - { - if (nIndex >= 0) - { -- if (nIndex <= obj->o_num) -+ if (nIndex < obj->o_num) - return &obj->o_props[nIndex]; - } - else --- -1.7.10.4 - - -From eea470fa5f9a5481a36dedd257549595ef7480d6 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Thu, 8 Mar 2012 23:10:11 -0800 -Subject: [PATCH 32/64] Add support for building with gnutls with nettle as - backend - - -diff --git a/Makefile b/Makefile -index 6ef5742..0cf41be 100644 ---- a/Makefile -+++ b/Makefile -@@ -13,6 +13,7 @@ CRYPTO=OPENSSL - #CRYPTO=GNUTLS - LIBZ=-lz - LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ) -+LIB_GNUTLS_NETTLE=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) - LIB_OPENSSL=-lssl -lcrypto $(LIBZ) - LIB_POLARSSL=-lpolarssl $(LIBZ) - CRYPTO_LIB=$(LIB_$(CRYPTO)) -diff --git a/librtmp/Makefile b/librtmp/Makefile -index a0125f1..353c6c8 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -21,14 +21,17 @@ CRYPTO=OPENSSL - DEF_POLARSSL=-DUSE_POLARSSL - DEF_OPENSSL=-DUSE_OPENSSL - DEF_GNUTLS=-DUSE_GNUTLS -+DEF_GNUTLS_NETTLE=-DUSE_GNUTLS_NETTLE - DEF_=-DNO_CRYPTO - REQ_GNUTLS=gnutls -+REQ_GNUTLS_NETTLE=gnutls - REQ_OPENSSL=libssl,libcrypto - LIBZ=-lz - LIBS_posix= - LIBS_darwin= - LIBS_mingw=-lws2_32 -lwinmm -lgdi32 - LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ) -+LIB_GNUTLS_NETTLE=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) - LIB_OPENSSL=-lssl -lcrypto $(LIBZ) - LIB_POLARSSL=-lpolarssl $(LIBZ) - PRIVATE_LIBS=$(LIBS_$(SYS)) -diff --git a/librtmp/dh.h b/librtmp/dh.h -index a9f3763..830000e 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -76,7 +76,8 @@ static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) - return 0; - } - --#elif defined(USE_GNUTLS) -+#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) -+#ifdef USE_GNUTLS - #include <gcrypt.h> - typedef gcry_mpi_t MP_t; - #define MP_new(m) m = gcry_mpi_new(1) -@@ -91,6 +92,23 @@ typedef gcry_mpi_t MP_t; - #define MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8 - #define MP_setbin(u,buf,len) gcry_mpi_print(GCRYMPI_FMT_USG,buf,len,NULL,u) - #define MP_getbin(u,buf,len) gcry_mpi_scan(&u,GCRYMPI_FMT_USG,buf,len,NULL) -+#else -+#include <gmp.h> -+#include <nettle/bignum.h> -+typedef mpz_ptr MP_t; -+#define MP_new(m) m = malloc(sizeof(*m)); mpz_init2(m, 1) -+#define MP_set_w(mpi, w) mpz_set_ui(mpi, w) -+#define MP_cmp(u, v) mpz_cmp(u, v) -+#define MP_set(u, v) mpz_set(u, v) -+#define MP_sub_w(mpi, w) mpz_sub_ui(mpi, mpi, w) -+#define MP_cmp_1(mpi) mpz_cmp_ui(mpi, 1) -+#define MP_modexp(r, y, q, p) mpz_powm(r, y, q, p) -+#define MP_free(mpi) mpz_clear(mpi); free(mpi) -+#define MP_gethex(u, hex, res) u = malloc(sizeof(*u)); mpz_init2(u, 1); res = (mpz_set_str(u, hex, 16) == 0) -+#define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8 -+#define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u) -+#define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf) -+#endif - - typedef struct MDH { - MP_t p; -diff --git a/librtmp/handshake.h b/librtmp/handshake.h -index 98bf3c8..4c2ea7f 100644 ---- a/librtmp/handshake.h -+++ b/librtmp/handshake.h -@@ -59,6 +59,26 @@ typedef gcry_cipher_hd_t RC4_handle; - #define RC4_encrypt2(h,l,s,d) gcry_cipher_encrypt(h,(void *)d,l,(void *)s,l) - #define RC4_free(h) gcry_cipher_close(h) - -+#elif defined(USE_GNUTLS_NETTLE) -+#include <nettle/hmac.h> -+#include <nettle/arcfour.h> -+#ifndef SHA256_DIGEST_LENGTH -+#define SHA256_DIGEST_LENGTH 32 -+#endif -+#undef HMAC_CTX -+#define HMAC_CTX struct hmac_sha256_ctx -+#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key) -+#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf) -+#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig) -+#define HMAC_close(ctx) -+ -+typedef struct arcfour_ctx* RC4_handle; -+#define RC4_alloc(h) *h = malloc(sizeof(struct arcfour_ctx)) -+#define RC4_setkey(h,l,k) arcfour_set_key(h, l, k) -+#define RC4_encrypt(h,l,d) arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)d) -+#define RC4_encrypt2(h,l,s,d) arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)s) -+#define RC4_free(h) free(h) -+ - #else /* USE_OPENSSL */ - #include <openssl/sha.h> - #include <openssl/hmac.h> -diff --git a/librtmp/hashswf.c b/librtmp/hashswf.c -index 0320480..8cefd3b 100644 ---- a/librtmp/hashswf.c -+++ b/librtmp/hashswf.c -@@ -52,6 +52,17 @@ - #define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len) - #define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; memcpy(dig, gcry_md_read(ctx, 0), dlen) - #define HMAC_close(ctx) gcry_md_close(ctx) -+#elif defined(USE_GNUTLS_NETTLE) -+#include <nettle/hmac.h> -+#ifndef SHA256_DIGEST_LENGTH -+#define SHA256_DIGEST_LENGTH 32 -+#endif -+#undef HMAC_CTX -+#define HMAC_CTX struct hmac_sha256_ctx -+#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key) -+#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf) -+#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig) -+#define HMAC_close(ctx) - #else /* USE_OPENSSL */ - #include <openssl/ssl.h> - #include <openssl/sha.h> -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 52d0254..5cd7b8d 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -34,7 +34,7 @@ - #ifdef CRYPTO - #ifdef USE_POLARSSL - #include <polarssl/havege.h> --#elif defined(USE_GNUTLS) -+#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) - #include <gnutls/gnutls.h> - #else /* USE_OPENSSL */ - #include <openssl/ssl.h> -@@ -204,7 +204,7 @@ RTMP_TLS_Init() - /* Do this regardless of NO_SSL, we use havege for rtmpe too */ - RTMP_TLS_ctx = calloc(1,sizeof(struct tls_ctx)); - havege_init(&RTMP_TLS_ctx->hs); --#elif defined(USE_GNUTLS) && !defined(NO_SSL) -+#elif (defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE)) && !defined(NO_SSL) - /* Technically we need to initialize libgcrypt ourselves if - * we're not going to call gnutls_global_init(). Ignoring this - * for now. -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index c3fd4a6..478c59f 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -81,7 +81,7 @@ typedef struct tls_ctx { - #define TLS_shutdown(s) ssl_close_notify(s) - #define TLS_close(s) ssl_free(s); free(s) - --#elif defined(USE_GNUTLS) -+#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) - #include <gnutls/gnutls.h> - typedef struct tls_ctx { - gnutls_certificate_credentials_t cred; --- -1.7.10.4 - - -From 7340f6dbc6b3c8e552baab2e5a891c2de75cddcc Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Thu, 8 Mar 2012 23:19:45 -0800 -Subject: [PATCH 33/64] Cleanup prev commit, drop gcrypt support - - -diff --git a/Makefile b/Makefile -index 0cf41be..a1595a8 100644 ---- a/Makefile -+++ b/Makefile -@@ -12,8 +12,7 @@ CRYPTO=OPENSSL - #CRYPTO=POLARSSL - #CRYPTO=GNUTLS - LIBZ=-lz --LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ) --LIB_GNUTLS_NETTLE=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) -+LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) - LIB_OPENSSL=-lssl -lcrypto $(LIBZ) - LIB_POLARSSL=-lpolarssl $(LIBZ) - CRYPTO_LIB=$(LIB_$(CRYPTO)) -diff --git a/librtmp/Makefile b/librtmp/Makefile -index 353c6c8..74ee3b5 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -21,17 +21,14 @@ CRYPTO=OPENSSL - DEF_POLARSSL=-DUSE_POLARSSL - DEF_OPENSSL=-DUSE_OPENSSL - DEF_GNUTLS=-DUSE_GNUTLS --DEF_GNUTLS_NETTLE=-DUSE_GNUTLS_NETTLE - DEF_=-DNO_CRYPTO - REQ_GNUTLS=gnutls --REQ_GNUTLS_NETTLE=gnutls - REQ_OPENSSL=libssl,libcrypto - LIBZ=-lz - LIBS_posix= - LIBS_darwin= - LIBS_mingw=-lws2_32 -lwinmm -lgdi32 --LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ) --LIB_GNUTLS_NETTLE=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) -+LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ) - LIB_OPENSSL=-lssl -lcrypto $(LIBZ) - LIB_POLARSSL=-lpolarssl $(LIBZ) - PRIVATE_LIBS=$(LIBS_$(SYS)) -diff --git a/librtmp/dh.h b/librtmp/dh.h -index 830000e..9959532 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -76,23 +76,7 @@ static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) - return 0; - } - --#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) --#ifdef USE_GNUTLS --#include <gcrypt.h> --typedef gcry_mpi_t MP_t; --#define MP_new(m) m = gcry_mpi_new(1) --#define MP_set_w(mpi, w) gcry_mpi_set_ui(mpi, w) --#define MP_cmp(u, v) gcry_mpi_cmp(u, v) --#define MP_set(u, v) gcry_mpi_set(u, v) --#define MP_sub_w(mpi, w) gcry_mpi_sub_ui(mpi, mpi, w) --#define MP_cmp_1(mpi) gcry_mpi_cmp_ui(mpi, 1) --#define MP_modexp(r, y, q, p) gcry_mpi_powm(r, y, q, p) --#define MP_free(mpi) gcry_mpi_release(mpi) --#define MP_gethex(u, hex, res) res = (gcry_mpi_scan(&u, GCRYMPI_FMT_HEX, hex, 0, 0) == 0) --#define MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8 --#define MP_setbin(u,buf,len) gcry_mpi_print(GCRYMPI_FMT_USG,buf,len,NULL,u) --#define MP_getbin(u,buf,len) gcry_mpi_scan(&u,GCRYMPI_FMT_USG,buf,len,NULL) --#else -+#elif defined(USE_GNUTLS) - #include <gmp.h> - #include <nettle/bignum.h> - typedef mpz_ptr MP_t; -@@ -108,7 +92,6 @@ typedef mpz_ptr MP_t; - #define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8 - #define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u) - #define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf) --#endif - - typedef struct MDH { - MP_t p; -diff --git a/librtmp/handshake.h b/librtmp/handshake.h -index 4c2ea7f..0438486 100644 ---- a/librtmp/handshake.h -+++ b/librtmp/handshake.h -@@ -43,27 +43,10 @@ typedef arc4_context * RC4_handle; - #define RC4_free(h) free(h) - - #elif defined(USE_GNUTLS) --#include <gcrypt.h> --#ifndef SHA256_DIGEST_LENGTH --#define SHA256_DIGEST_LENGTH 32 --#endif --#define HMAC_CTX gcry_md_hd_t --#define HMAC_setup(ctx, key, len) gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); gcry_md_setkey(ctx, key, len) --#define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len) --#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; memcpy(dig, gcry_md_read(ctx, 0), dlen); gcry_md_close(ctx) -- --typedef gcry_cipher_hd_t RC4_handle; --#define RC4_alloc(h) gcry_cipher_open(h, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0) --#define RC4_setkey(h,l,k) gcry_cipher_setkey(h,k,l) --#define RC4_encrypt(h,l,d) gcry_cipher_encrypt(h,(void *)d,l,NULL,0) --#define RC4_encrypt2(h,l,s,d) gcry_cipher_encrypt(h,(void *)d,l,(void *)s,l) --#define RC4_free(h) gcry_cipher_close(h) -- --#elif defined(USE_GNUTLS_NETTLE) - #include <nettle/hmac.h> - #include <nettle/arcfour.h> - #ifndef SHA256_DIGEST_LENGTH --#define SHA256_DIGEST_LENGTH 32 -+#define SHA256_DIGEST_LENGTH 32 - #endif - #undef HMAC_CTX - #define HMAC_CTX struct hmac_sha256_ctx -diff --git a/librtmp/hashswf.c b/librtmp/hashswf.c -index 8cefd3b..9f4e2c0 100644 ---- a/librtmp/hashswf.c -+++ b/librtmp/hashswf.c -@@ -42,17 +42,6 @@ - #define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig) - #define HMAC_close(ctx) - #elif defined(USE_GNUTLS) --#include <gnutls/gnutls.h> --#include <gcrypt.h> --#ifndef SHA256_DIGEST_LENGTH --#define SHA256_DIGEST_LENGTH 32 --#endif --#define HMAC_CTX gcry_md_hd_t --#define HMAC_setup(ctx, key, len) gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); gcry_md_setkey(ctx, key, len) --#define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len) --#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; memcpy(dig, gcry_md_read(ctx, 0), dlen) --#define HMAC_close(ctx) gcry_md_close(ctx) --#elif defined(USE_GNUTLS_NETTLE) - #include <nettle/hmac.h> - #ifndef SHA256_DIGEST_LENGTH - #define SHA256_DIGEST_LENGTH 32 -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 5cd7b8d..52d0254 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -34,7 +34,7 @@ - #ifdef CRYPTO - #ifdef USE_POLARSSL - #include <polarssl/havege.h> --#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) -+#elif defined(USE_GNUTLS) - #include <gnutls/gnutls.h> - #else /* USE_OPENSSL */ - #include <openssl/ssl.h> -@@ -204,7 +204,7 @@ RTMP_TLS_Init() - /* Do this regardless of NO_SSL, we use havege for rtmpe too */ - RTMP_TLS_ctx = calloc(1,sizeof(struct tls_ctx)); - havege_init(&RTMP_TLS_ctx->hs); --#elif (defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE)) && !defined(NO_SSL) -+#elif defined(USE_GNUTLS) && !defined(NO_SSL) - /* Technically we need to initialize libgcrypt ourselves if - * we're not going to call gnutls_global_init(). Ignoring this - * for now. -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 478c59f..c3fd4a6 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -81,7 +81,7 @@ typedef struct tls_ctx { - #define TLS_shutdown(s) ssl_close_notify(s) - #define TLS_close(s) ssl_free(s); free(s) - --#elif defined(USE_GNUTLS) || defined(USE_GNUTLS_NETTLE) -+#elif defined(USE_GNUTLS) - #include <gnutls/gnutls.h> - typedef struct tls_ctx { - gnutls_certificate_credentials_t cred; --- -1.7.10.4 - - -From 603ff20e9e717a70b5b0c011f3413cf376d0c2f6 Mon Sep 17 00:00:00 2001 -From: Ulrik Dickow <u.dickow@gmail.com> -Date: Thu, 26 Jul 2012 04:57:23 -0700 -Subject: [PATCH 34/64] Add .gitignore to ignore generated files - - -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..c7ec44f ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,9 @@ -+*.[oa] -+*.exe -+*.so -+*.so.[0-9] -+*.dylib -+rtmpdump -+rtmpgw -+rtmpsrv -+rtmpsuck --- -1.7.10.4 - - -From e0056c51cc1710c9a44d2a2c4e2f344fa9cabcf4 Mon Sep 17 00:00:00 2001 -From: Ulrik Dickow <u.dickow@gmail.com> -Date: Tue, 24 Jul 2012 17:17:26 +0200 -Subject: [PATCH 35/64] Add option --realtime (-R) to rtmpdump to disable the - BUFX hack - - -diff --git a/rtmpdump.1 b/rtmpdump.1 -index 0d9de8d..7bb5328 100644 ---- a/rtmpdump.1 -+++ b/rtmpdump.1 -@@ -1,4 +1,4 @@ --.TH RTMPDUMP 1 "2011-07-20" "RTMPDump v2.4" -+.TH RTMPDUMP 1 "2012-07-24" "RTMPDump v2.4" - .\" Copyright 2011 Howard Chu. - .\" Copying permitted according to the GNU General Public License V2. - .SH NAME -@@ -177,6 +177,12 @@ live streams is possible. - Name of live stream to subscribe to. Defaults to - .IR playpath . - .TP -+.B \-\-realtime \-R -+Download approximately in realtime, without attempting to speed up via -+Pause/Unpause commands ("the BUFX hack"). -+Useful for servers that jump backwards in time at the Unpause command. -+Resuming and seeking in realtime streams is still possible. -+.TP - .B \-\-resume \-e - Resume an incomplete RTMP download. - .TP -diff --git a/rtmpdump.1.html b/rtmpdump.1.html -index 826f722..4c39b35 100644 ---- a/rtmpdump.1.html -+++ b/rtmpdump.1.html -@@ -6,7 +6,7 @@ - <tr><td>RTMPDUMP(1)<td align="center"><td align="right">RTMPDUMP(1) - </thead> - <tfoot> --<tr><td>RTMPDump v2.4<td align="center">2011-07-20<td align="right">RTMPDUMP(1) -+<tr><td>RTMPDump v2.4<td align="center">2012-07-24<td align="right">RTMPDUMP(1) - </tfoot> - <tbody><tr><td colspan="3"><br><br><ul> - <!-- Copyright 2011 Howard Chu. -@@ -34,6 +34,7 @@ rtmpdump − RTMP streaming media client - [<b>−y</b><i> playpath</i>] - [<b>−Y</b>] - [<b>−v</b>] -+[<b>−R</b>] - [<b>−d</b><i> subscription</i>] - [<b>−e</b>] - [<b>−k</b><i> skip</i>] -@@ -218,6 +219,15 @@ Name of live stream to subscribe to. Defaults to - </dl> - <p> - <dl compact><dt> -+<b>−−realtime −R</b> -+<dd> -+Download approximately in realtime, without attempting to speed up via -+Pause/Unpause commands ("the BUFX hack"). -+Useful for servers that jump backwards in time at the Unpause command. -+Resuming and seeking in realtime streams is still possible. -+</dl> -+<p> -+<dl compact><dt> - <b>−−resume −e</b> - <dd> - Resume an incomplete RTMP download. -diff --git a/rtmpdump.c b/rtmpdump.c -index 34bfdba..e52f7d4 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -441,7 +441,7 @@ GetLastKeyframe(FILE * file, // output file [in] - - int - Download(RTMP * rtmp, // connected RTMP object -- FILE * file, uint32_t dSeek, uint32_t dStopOffset, double duration, int bResume, char *metaHeader, uint32_t nMetaHeaderSize, char *initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, int bStdoutMode, int bLiveStream, int bHashes, int bOverrideBufferTime, uint32_t bufferTime, double *percent) // percentage downloaded [out] -+ FILE * file, uint32_t dSeek, uint32_t dStopOffset, double duration, int bResume, char *metaHeader, uint32_t nMetaHeaderSize, char *initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, int bStdoutMode, int bLiveStream, int bRealtimeStream, int bHashes, int bOverrideBufferTime, uint32_t bufferTime, double *percent) // percentage downloaded [out] - { - int32_t now, lastUpdate; - int bufferSize = 64 * 1024; -@@ -492,6 +492,8 @@ Download(RTMP * rtmp, // connected RTMP object - bResume ? "Resuming" : "Starting", - (double) size / 1024.0); - } -+ if (bRealtimeStream) -+ RTMP_LogPrintf(" in approximately realtime (disabled BUFX speedup hack)\n"); - } - - if (dStopOffset > 0) -@@ -682,6 +684,8 @@ void usage(char *prog) - RTMP_LogPrintf - ("--subscribe|-d string Stream name to subscribe to (otherwise defaults to playpath if live is specifed)\n"); - RTMP_LogPrintf -+ ("--realtime|-R Don't attempt to speed up download via the Pause/Unpause BUFX hack\n"); -+ RTMP_LogPrintf - ("--flv|-o string FLV output file name, if the file name is - print stream to stdout\n"); - RTMP_LogPrintf - ("--resume|-e Resume a partial RTMP download\n"); -@@ -748,6 +752,7 @@ main(int argc, char **argv) - int protocol = RTMP_PROTOCOL_UNDEFINED; - int retries = 0; - int bLiveStream = FALSE; // is it a live stream? then we can't seek/resume -+ int bRealtimeStream = FALSE; // If true, disable the BUFX hack (be patient) - int bHashes = FALSE; // display byte counters not hashes by default - - long int timeout = DEF_TIMEOUT; // timeout connection after 120 seconds -@@ -832,6 +837,7 @@ main(int argc, char **argv) - #endif - {"flashVer", 1, NULL, 'f'}, - {"live", 0, NULL, 'v'}, -+ {"realtime", 0, NULL, 'R'}, - {"flv", 1, NULL, 'o'}, - {"resume", 0, NULL, 'e'}, - {"timeout", 1, NULL, 'm'}, -@@ -851,7 +857,7 @@ main(int argc, char **argv) - - 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:#j:", -+ "hVveqzRr: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) -@@ -936,6 +942,9 @@ main(int argc, char **argv) - case 'v': - bLiveStream = TRUE; // no seeking or resuming possible! - break; -+ case 'R': -+ bRealtimeStream = TRUE; // seeking and resuming is still possible -+ break; - case 'd': - STR2AVAL(subscribepath, optarg); - break; -@@ -1181,7 +1190,7 @@ main(int argc, char **argv) - &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout); - - /* Try to keep the stream moving if it pauses on us */ -- if (!bLiveStream && !(protocol & RTMP_FEATURE_HTTP)) -+ if (!bLiveStream && !bRealtimeStream && !(protocol & RTMP_FEATURE_HTTP)) - rtmp.Link.lFlags |= RTMP_LF_BUFX; - - off_t size = 0; -@@ -1348,8 +1357,8 @@ main(int argc, char **argv) - - nStatus = Download(&rtmp, file, dSeek, dStopOffset, duration, bResume, - metaHeader, nMetaHeaderSize, initialFrame, -- initialFrameType, nInitialFrameSize, -- nSkipKeyFrames, bStdoutMode, bLiveStream, bHashes, -+ initialFrameType, nInitialFrameSize, nSkipKeyFrames, -+ bStdoutMode, bLiveStream, bRealtimeStream, bHashes, - bOverrideBufferTime, bufferTime, &percent); - free(initialFrame); - initialFrame = NULL; --- -1.7.10.4 - - -From 87d47b876f818fe5c949e08c699238bc22a3c7b1 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera <hadess@hadess.net> -Date: Tue, 30 Oct 2012 08:16:36 -0700 -Subject: [PATCH 36/64] Make rtmpdump handle full RTMP URLs with "-i" - - -diff --git a/rtmpdump.c b/rtmpdump.c -index e52f7d4..2b30eb2 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -640,6 +640,8 @@ void usage(char *prog) - ("\n%s: This program dumps the media content streamed over RTMP.\n\n", prog); - RTMP_LogPrintf("--help|-h Prints this help screen.\n"); - RTMP_LogPrintf -+ ("--url|-i url URL with options included (e.g. rtmp://host[:port]/path swfUrl=url tcUrl=url)\n"); -+ RTMP_LogPrintf - ("--rtmp|-r url URL (e.g. rtmp://host[:port]/path)\n"); - RTMP_LogPrintf - ("--host|-n hostname Overrides the hostname in the rtmp url\n"); -@@ -760,6 +762,7 @@ main(int argc, char **argv) - uint32_t dStopOffset = 0; - RTMP rtmp = { 0 }; - -+ AVal fullUrl = { 0, 0 }; - AVal swfUrl = { 0, 0 }; - AVal tcUrl = { 0, 0 }; - AVal pageUrl = { 0, 0 }; -@@ -822,6 +825,7 @@ main(int argc, char **argv) - {"protocol", 1, NULL, 'l'}, - {"playpath", 1, NULL, 'y'}, - {"playlist", 0, NULL, 'Y'}, -+ {"url", 1, NULL, 'i'}, - {"rtmp", 1, NULL, 'r'}, - {"swfUrl", 1, NULL, 's'}, - {"tcUrl", 1, NULL, 't'}, -@@ -857,7 +861,7 @@ main(int argc, char **argv) - - while ((opt = - getopt_long(argc, argv, -- "hVveqzRr: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:", -+ "hVveqzRr:s:t:i: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) -@@ -1000,6 +1004,9 @@ main(int argc, char **argv) - } - break; - } -+ case 'i': -+ STR2AVAL(fullUrl, optarg); -+ break; - case 's': - STR2AVAL(swfUrl, optarg); - break; -@@ -1078,32 +1085,32 @@ main(int argc, char **argv) - } - } - -- if (!hostname.av_len) -+ if (!hostname.av_len && !fullUrl.av_len) - { - RTMP_Log(RTMP_LOGERROR, - "You must specify a hostname (--host) or url (-r \"rtmp://host[:port]/playpath\") containing a hostname"); - return RD_FAILED; - } -- if (playpath.av_len == 0) -+ if (playpath.av_len == 0 && !fullUrl.av_len) - { - RTMP_Log(RTMP_LOGERROR, - "You must specify a playpath (--playpath) or url (-r \"rtmp://host[:port]/playpath\") containing a playpath"); - return RD_FAILED; - } - -- if (protocol == RTMP_PROTOCOL_UNDEFINED) -+ if (protocol == RTMP_PROTOCOL_UNDEFINED && !fullUrl.av_len) - { - RTMP_Log(RTMP_LOGWARNING, - "You haven't specified a protocol (--protocol) or rtmp url (-r), using default protocol RTMP"); - protocol = RTMP_PROTOCOL_RTMP; - } -- if (port == -1) -+ if (port == -1 && !fullUrl.av_len) - { - RTMP_Log(RTMP_LOGWARNING, - "You haven't specified a port (--port) or rtmp url (-r), using default port 1935"); - port = 0; - } -- if (port == 0) -+ if (port == 0 && !fullUrl.av_len) - { - if (protocol & RTMP_FEATURE_SSL) - port = 443; -@@ -1185,9 +1192,20 @@ main(int argc, char **argv) - } - } - -- RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath, -- &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize, -- &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout); -+ if (!fullUrl.av_len) -+ { -+ RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath, -+ &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize, -+ &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout); -+ } -+ else -+ { -+ if (RTMP_SetupURL(&rtmp, fullUrl.av_val) == FALSE) -+ { -+ RTMP_Log(RTMP_LOGERROR, "Couldn't parse URL: %s", fullUrl.av_val); -+ return RD_FAILED; -+ } -+ } - - /* Try to keep the stream moving if it pauses on us */ - if (!bLiveStream && !bRealtimeStream && !(protocol & RTMP_FEATURE_HTTP)) --- -1.7.10.4 - - -From 3fcbcb9a0bae6de03401f32939d3d243cdd7b865 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera <hadess@hadess.net> -Date: Thu, 19 Jul 2012 17:22:03 +0100 -Subject: [PATCH 37/64] Make rtmpgw handle full RTMP URLs with "-i" - -or --url. Just as rtmpdump and librtmp already can. - -diff --git a/rtmpgw.c b/rtmpgw.c -index 0cf56bb..ab255d4 100644 ---- a/rtmpgw.c -+++ b/rtmpgw.c -@@ -85,6 +85,7 @@ typedef struct - uint32_t bufferTime; - - char *rtmpurl; -+ AVal fullUrl; - AVal playpath; - AVal swfUrl; - AVal tcUrl; -@@ -469,14 +470,14 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou - } - - // do necessary checks right here to make sure the combined request of default values and GET parameters is correct -- if (!req.hostname.av_len) -+ if (!req.hostname.av_len && !req.fullUrl.av_len) - { - RTMP_Log(RTMP_LOGERROR, - "You must specify a hostname (--host) or url (-r \"rtmp://host[:port]/playpath\") containing a hostname"); - status = "400 Missing Hostname"; - goto filenotfound; - } -- if (req.playpath.av_len == 0) -+ if (req.playpath.av_len == 0 && !req.fullUrl.av_len) - { - RTMP_Log(RTMP_LOGERROR, - "You must specify a playpath (--playpath) or url (-r \"rtmp://host[:port]/playpath\") containing a playpath"); -@@ -484,19 +485,19 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou - goto filenotfound;; - } - -- if (req.protocol == RTMP_PROTOCOL_UNDEFINED) -+ if (req.protocol == RTMP_PROTOCOL_UNDEFINED && !req.fullUrl.av_len) - { - RTMP_Log(RTMP_LOGWARNING, - "You haven't specified a protocol (--protocol) or rtmp url (-r), using default protocol RTMP"); - req.protocol = RTMP_PROTOCOL_RTMP; - } -- if (req.rtmpport == -1) -+ if (req.rtmpport == -1 && !req.fullUrl.av_len) - { - RTMP_Log(RTMP_LOGWARNING, - "You haven't specified a port (--port) or rtmp url (-r), using default port"); - req.rtmpport = 0; - } -- if (req.rtmpport == 0) -+ if (req.rtmpport == 0 && !req.fullUrl.av_len) - { - if (req.protocol & RTMP_FEATURE_SSL) - req.rtmpport = 443; -@@ -552,9 +553,20 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou - RTMP_Log(RTMP_LOGDEBUG, "Setting buffer time to: %dms", req.bufferTime); - 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, &req.usherToken, dSeek, req.dStopOffset, -- req.bLiveStream, req.timeout); -+ if (!req.fullUrl.av_len) -+ { -+ 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, &req.usherToken, dSeek, req.dStopOffset, -+ req.bLiveStream, req.timeout); -+ } -+ else -+ { -+ if (RTMP_SetupURL(&rtmp, req.fullUrl.av_val) == FALSE) -+ { -+ RTMP_Log(RTMP_LOGERROR, "Couldn't parse URL: %s", req.fullUrl.av_val); -+ return; -+ } -+ } - /* backward compatibility, we always sent this as true before */ - if (req.auth.av_len) - rtmp.Link.lFlags |= RTMP_LF_AUTH; -@@ -908,6 +920,9 @@ ParseOption(char opt, char *arg, RTMP_REQUEST * req) - } - break; - } -+ case 'i': -+ STR2AVAL(req->fullUrl, optarg); -+ break; - case 's': - STR2AVAL(req->swfUrl, arg); - break; -@@ -993,6 +1008,7 @@ main(int argc, char **argv) - int opt; - struct option longopts[] = { - {"help", 0, NULL, 'h'}, -+ {"url", 1, NULL, 'i'}, - {"host", 1, NULL, 'n'}, - {"port", 1, NULL, 'c'}, - {"socks", 1, NULL, 'S'}, -@@ -1040,7 +1056,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:j:", longopts, -+ "hvqVzr:s:t:i: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) -@@ -1050,6 +1066,8 @@ main(int argc, char **argv) - ("\nThis program serves media content streamed from RTMP onto HTTP.\n\n"); - RTMP_LogPrintf("--help|-h Prints this help screen.\n"); - RTMP_LogPrintf -+ ("--url|-i url URL with options included (e.g. rtmp://host[:port]/path swfUrl=url tcUrl=url)\n"); -+ RTMP_LogPrintf - ("--rtmp|-r url URL (e.g. rtmp://host[:port]/path)\n"); - RTMP_LogPrintf - ("--host|-n hostname Overrides the hostname in the rtmp url\n"); --- -1.7.10.4 - - -From 75a6167863bc415845b9130d6f8f437cbdc185f7 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 08:20:14 -0700 -Subject: [PATCH 38/64] Fix bogus optarg refs in prev commit - - -diff --git a/rtmpgw.c b/rtmpgw.c -index ab255d4..3e47602 100644 ---- a/rtmpgw.c -+++ b/rtmpgw.c -@@ -921,7 +921,7 @@ ParseOption(char opt, char *arg, RTMP_REQUEST * req) - break; - } - case 'i': -- STR2AVAL(req->fullUrl, optarg); -+ STR2AVAL(req->fullUrl, arg); - break; - case 's': - STR2AVAL(req->swfUrl, arg); -@@ -942,7 +942,7 @@ ParseOption(char opt, char *arg, RTMP_REQUEST * req) - STR2AVAL(req->auth, arg); - break; - case 'C': -- parseAMF(&req->extras, optarg, &req->edepth); -+ parseAMF(&req->extras, arg, &req->edepth); - break; - case 'm': - req->timeout = atoi(arg); --- -1.7.10.4 - - -From dc1ddd3b3f567c036f6909af7f1bfdc135331439 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 08:28:15 -0700 -Subject: [PATCH 39/64] Fix rare infinite loop on EOF - -reported by Matt Robison <rtmpdump@nerdoftheherd.com> - -diff --git a/rtmpdump.c b/rtmpdump.c -index 2b30eb2..13741a7 100644 ---- a/rtmpdump.c -+++ b/rtmpdump.c -@@ -580,12 +580,14 @@ Download(RTMP * rtmp, // connected RTMP object - } - } - } --#ifdef _DEBUG - else - { -+#ifdef _DEBUG - RTMP_Log(RTMP_LOGDEBUG, "zero read!"); -- } - #endif -+ if (rtmp->m_read.status == RTMP_READ_EOF) -+ break; -+ } - - } - while (!RTMP_ctrlC && nRead > -1 && RTMP_IsConnected(rtmp) && !RTMP_IsTimedout(rtmp)); --- -1.7.10.4 - - -From a312ac7770207bd7d07725c1aef43725206e803a Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 08:41:49 -0700 -Subject: [PATCH 40/64] Fix compat with PolarSSL >= 1.1.0 - - -diff --git a/librtmp/dh.h b/librtmp/dh.h -index 9959532..fa264f8 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -29,6 +29,9 @@ - - #ifdef USE_POLARSSL - #include <polarssl/dhm.h> -+#if POLARSSL_VERSION_NUMBER < 0x01010100 -+#define havege_random havege_rand -+#endif - typedef mpi * MP_t; - #define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m) - #define MP_set_w(mpi, w) mpi_lset(mpi, w) -@@ -61,7 +64,7 @@ static int MDH_generate_key(MDH *dh) - MP_set(&dh->ctx.P, dh->p); - MP_set(&dh->ctx.G, dh->g); - dh->ctx.len = 128; -- dhm_make_public(&dh->ctx, 1024, out, 1, havege_rand, &RTMP_TLS_ctx->hs); -+ dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs); - MP_new(dh->pub_key); - MP_new(dh->priv_key); - MP_set(dh->pub_key, &dh->ctx.GX); -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 52d0254..76a6b4f 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -33,6 +33,7 @@ - - #ifdef CRYPTO - #ifdef USE_POLARSSL -+#include <polarssl/version.h> - #include <polarssl/havege.h> - #elif defined(USE_GNUTLS) - #include <gnutls/gnutls.h> -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index c3fd4a6..1bf0735 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -61,9 +61,13 @@ - #include "rtmp.h" - - #ifdef USE_POLARSSL -+#include <polarssl/version.h> - #include <polarssl/net.h> - #include <polarssl/ssl.h> - #include <polarssl/havege.h> -+#if POLARSSL_VERSION_NUMBER < 0x01010100 -+#define havege_random havege_rand -+#endif - typedef struct tls_ctx { - havege_state hs; - ssl_session ssn; -@@ -71,7 +75,7 @@ typedef struct tls_ctx { - #define TLS_CTX tls_ctx * - #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ - ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ -- ssl_set_rng(s, havege_rand, &ctx->hs);\ -+ ssl_set_rng(s, havege_random, &ctx->hs);\ - ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ - ssl_set_session(s, 1, 600, &ctx->ssn) - #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) --- -1.7.10.4 - - -From 1d07cfa60402ace8472f4661112595f1fe661913 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett <mjg59@srcf.ucam.org> -Date: Sun, 8 Jul 2012 16:26:14 -0400 -Subject: [PATCH 41/64] Fix socks support for SetupURL - -SetupURL assigns sockshost but never parses the data. This patch factors -the code out from SetupStream into a common function and adds it to -SetupURL. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 76a6b4f..682e3b8 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -321,6 +321,31 @@ static const char DEFAULT_FLASH_VER[] = DEF_VERSTR; - const AVal RTMP_DefaultFlashVer = - { (char *)DEFAULT_FLASH_VER, sizeof(DEFAULT_FLASH_VER) - 1 }; - -+static void -+SocksSetup(RTMP *r, AVal *sockshost) -+{ -+ if (sockshost->av_len) -+ { -+ const char *socksport = strchr(sockshost->av_val, ':'); -+ char *hostname = strdup(sockshost->av_val); -+ -+ if (socksport) -+ hostname[socksport - sockshost->av_val] = '\0'; -+ r->Link.sockshost.av_val = hostname; -+ r->Link.sockshost.av_len = strlen(hostname); -+ -+ r->Link.socksport = socksport ? atoi(socksport + 1) : 1080; -+ RTMP_Log(RTMP_LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", r->Link.sockshost.av_val, -+ r->Link.socksport); -+ } -+ else -+ { -+ r->Link.sockshost.av_val = NULL; -+ r->Link.sockshost.av_len = 0; -+ r->Link.socksport = 0; -+ } -+} -+ - void - RTMP_SetupStream(RTMP *r, - int protocol, -@@ -385,26 +410,7 @@ RTMP_SetupStream(RTMP *r, - } - #endif - -- if (sockshost->av_len) -- { -- const char *socksport = strchr(sockshost->av_val, ':'); -- char *hostname = strdup(sockshost->av_val); -- -- if (socksport) -- hostname[socksport - sockshost->av_val] = '\0'; -- r->Link.sockshost.av_val = hostname; -- r->Link.sockshost.av_len = strlen(hostname); -- -- r->Link.socksport = socksport ? atoi(socksport + 1) : 1080; -- RTMP_Log(RTMP_LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", r->Link.sockshost.av_val, -- r->Link.socksport); -- } -- else -- { -- r->Link.sockshost.av_val = NULL; -- r->Link.sockshost.av_len = 0; -- r->Link.socksport = 0; -- } -+ SocksSetup(r, sockshost); - - if (tcUrl && tcUrl->av_len) - r->Link.tcUrl = *tcUrl; -@@ -757,6 +763,8 @@ int RTMP_SetupURL(RTMP *r, char *url) - (unsigned char *)r->Link.SWFHash, r->Link.swfAge); - #endif - -+ SocksSetup(r, &r->Link.sockshost); -+ - if (r->Link.port == 0) - { - if (r->Link.protocol & RTMP_FEATURE_SSL) --- -1.7.10.4 - - -From b77a7dc719f8b04274db91f6344f4358a78d9c5f Mon Sep 17 00:00:00 2001 -From: goggle1 <goggle1@163.com> -Date: Tue, 30 Oct 2012 08:47:19 -0700 -Subject: [PATCH 42/64] Handle AMF_ECMA_ARRAY and AMF_STRICT_ARRAY objects - - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index ce84f81..1406be4 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -396,6 +396,14 @@ AMFProp_Encode(AMFObjectProperty *prop, char *pBuffer, char *pBufEnd) - pBuffer = AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd); - break; - -+ case AMF_ECMA_ARRAY: -+ pBuffer = AMF_EncodeEcmaArray(&prop->p_vu.p_object, pBuffer, pBufEnd); -+ break; -+ -+ case AMF_STRICT_ARRAY: -+ pBuffer = AMF_EncodeArray(&prop->p_vu.p_object, pBuffer, pBufEnd); -+ break; -+ - default: - RTMP_Log(RTMP_LOGERROR, "%s, invalid type. %d", __FUNCTION__, prop->p_type); - pBuffer = NULL; -@@ -700,7 +708,7 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - if (nRes == -1) - return -1; - nSize -= nRes; -- prop->p_type = AMF_OBJECT; -+ //prop->p_type = AMF_OBJECT; - break; - } - case AMF_OBJECT_END: -@@ -718,7 +726,7 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - if (nRes == -1) - return -1; - nSize -= nRes; -- prop->p_type = AMF_OBJECT; -+ //prop->p_type = AMF_OBJECT; - break; - } - case AMF_DATE: -@@ -815,6 +823,18 @@ AMFProp_Dump(AMFObjectProperty *prop) - AMF_Dump(&prop->p_vu.p_object); - return; - } -+ else if (prop->p_type == AMF_ECMA_ARRAY) -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "Property: <%sECMA_ARRAY>", strRes); -+ AMF_Dump(&prop->p_vu.p_object); -+ return; -+ } -+ else if (prop->p_type == AMF_STRICT_ARRAY) -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "Property: <%sSTRICT_ARRAY>", strRes); -+ AMF_Dump(&prop->p_vu.p_object); -+ return; -+ } - - switch (prop->p_type) - { -@@ -888,6 +908,76 @@ AMF_Encode(AMFObject *obj, char *pBuffer, char *pBufEnd) - return pBuffer; - } - -+char * -+AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd) -+{ -+ int i; -+ -+ if (pBuffer+4 >= pBufEnd) -+ return NULL; -+ -+ *pBuffer++ = AMF_ECMA_ARRAY; -+ -+ pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num); -+ -+ for (i = 0; i < obj->o_num; i++) -+ { -+ char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); -+ if (res == NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d", -+ i); -+ break; -+ } -+ else -+ { -+ pBuffer = res; -+ } -+ } -+ -+ if (pBuffer + 3 >= pBufEnd) -+ return NULL; /* no room for the end marker */ -+ -+ pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END); -+ -+ return pBuffer; -+} -+ -+char * -+AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd) -+{ -+ int i; -+ -+ if (pBuffer+4 >= pBufEnd) -+ return NULL; -+ -+ *pBuffer++ = AMF_STRICT_ARRAY; -+ -+ pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num); -+ -+ for (i = 0; i < obj->o_num; i++) -+ { -+ char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); -+ if (res == NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d", -+ i); -+ break; -+ } -+ else -+ { -+ pBuffer = res; -+ } -+ } -+ -+ //if (pBuffer + 3 >= pBufEnd) -+ // return NULL; /* no room for the end marker */ -+ -+ //pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END); -+ -+ return pBuffer; -+} -+ - int - AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int nSize, - int nArrayLen, int bDecodeName) -diff --git a/librtmp/amf.h b/librtmp/amf.h -index b945beb..5a47d77 100644 ---- a/librtmp/amf.h -+++ b/librtmp/amf.h -@@ -104,6 +104,9 @@ extern "C" - double AMF_DecodeNumber(const char *data); - - char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd); -+ char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd); -+ char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd); -+ - int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize, - int bDecodeName); - int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize, --- -1.7.10.4 - - -From 294135e6eafeb1ac338ac4bb11ebd5ef62c748b9 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 08:50:34 -0700 -Subject: [PATCH 43/64] Cleanup prev commit - - -diff --git a/librtmp/amf.c b/librtmp/amf.c -index 1406be4..563486c 100644 ---- a/librtmp/amf.c -+++ b/librtmp/amf.c -@@ -396,14 +396,14 @@ AMFProp_Encode(AMFObjectProperty *prop, char *pBuffer, char *pBufEnd) - pBuffer = AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd); - break; - -- case AMF_ECMA_ARRAY: -+ case AMF_ECMA_ARRAY: - pBuffer = AMF_EncodeEcmaArray(&prop->p_vu.p_object, pBuffer, pBufEnd); - break; -- -- case AMF_STRICT_ARRAY: -+ -+ case AMF_STRICT_ARRAY: - pBuffer = AMF_EncodeArray(&prop->p_vu.p_object, pBuffer, pBufEnd); - break; -- -+ - default: - RTMP_Log(RTMP_LOGERROR, "%s, invalid type. %d", __FUNCTION__, prop->p_type); - pBuffer = NULL; -@@ -708,7 +708,6 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - if (nRes == -1) - return -1; - nSize -= nRes; -- //prop->p_type = AMF_OBJECT; - break; - } - case AMF_OBJECT_END: -@@ -726,7 +725,6 @@ AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, - if (nRes == -1) - return -1; - nSize -= nRes; -- //prop->p_type = AMF_OBJECT; - break; - } - case AMF_DATE: -diff --git a/librtmp/amf.h b/librtmp/amf.h -index 5a47d77..5de414b 100644 ---- a/librtmp/amf.h -+++ b/librtmp/amf.h -@@ -106,7 +106,7 @@ extern "C" - char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd); - char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd); - char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd); -- -+ - int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize, - int bDecodeName); - int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize, --- -1.7.10.4 - - -From d70c3f677d3d80763adf54c4e1329c57ed8af3ba Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sun, 20 May 2012 23:36:57 +0300 -Subject: [PATCH 44/64] Allocate the RTMP struct dynamically - -This struct is over 1 MB in size, and doesn't fit on the stack -on OS X. - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index 9aa62f3..956abab 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -886,7 +886,7 @@ void doServe(STREAMING_SERVER * server, // server socket and state (our listenin - { - server->state = STREAMING_IN_PROGRESS; - -- RTMP rtmp = { 0 }; /* our session with the real client */ -+ RTMP *rtmp = RTMP_Alloc(); /* our session with the real client */ - RTMPPacket packet = { 0 }; - - // timeout for http requests -@@ -906,38 +906,39 @@ void doServe(STREAMING_SERVER * server, // server socket and state (our listenin - } - else - { -- RTMP_Init(&rtmp); -- rtmp.m_sb.sb_socket = sockfd; -- if (!RTMP_Serve(&rtmp)) -+ RTMP_Init(rtmp); -+ rtmp->m_sb.sb_socket = sockfd; -+ if (!RTMP_Serve(rtmp)) - { - RTMP_Log(RTMP_LOGERROR, "Handshake failed"); - goto cleanup; - } - } - server->arglen = 0; -- while (RTMP_IsConnected(&rtmp) && RTMP_ReadPacket(&rtmp, &packet)) -+ while (RTMP_IsConnected(rtmp) && RTMP_ReadPacket(rtmp, &packet)) - { - if (!RTMPPacket_IsReady(&packet)) - continue; -- ServePacket(server, &rtmp, &packet); -+ ServePacket(server, rtmp, &packet); - RTMPPacket_Free(&packet); - } - - cleanup: - RTMP_LogPrintf("Closing connection... "); -- RTMP_Close(&rtmp); -+ RTMP_Close(rtmp); - /* Should probably be done by RTMP_Close() ... */ -- rtmp.Link.playpath.av_val = NULL; -- rtmp.Link.tcUrl.av_val = NULL; -- rtmp.Link.swfUrl.av_val = NULL; -- rtmp.Link.pageUrl.av_val = NULL; -- rtmp.Link.app.av_val = NULL; -- rtmp.Link.flashVer.av_val = NULL; -- if (rtmp.Link.usherToken.av_val) -+ rtmp->Link.playpath.av_val = NULL; -+ rtmp->Link.tcUrl.av_val = NULL; -+ rtmp->Link.swfUrl.av_val = NULL; -+ rtmp->Link.pageUrl.av_val = NULL; -+ rtmp->Link.app.av_val = NULL; -+ rtmp->Link.flashVer.av_val = NULL; -+ if (rtmp->Link.usherToken.av_val) - { -- free(rtmp.Link.usherToken.av_val); -- rtmp.Link.usherToken.av_val = NULL; -+ free(rtmp->Link.usherToken.av_val); -+ rtmp->Link.usherToken.av_val = NULL; - } -+ RTMP_Free(rtmp); - RTMP_LogPrintf("done!\n\n"); - - quit: --- -1.7.10.4 - - -From f14b6ac18d779cfb1431c59344bd59a0b0445e08 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sun, 20 May 2012 23:36:58 +0300 -Subject: [PATCH 45/64] Replace hardcoded constants and comments with proper - named constants - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index 956abab..fc727bc 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -767,47 +767,40 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - - switch (packet->m_packetType) - { -- case 0x01: -- // chunk size -+ case RTMP_PACKET_TYPE_CHUNK_SIZE: - // HandleChangeChunkSize(r, packet); - break; - -- case 0x03: -- // bytes read report -+ case RTMP_PACKET_TYPE_BYTES_READ_REPORT: - break; - -- case 0x04: -- // ctrl -+ case RTMP_PACKET_TYPE_CONTROL: - // HandleCtrl(r, packet); - break; - -- case 0x05: -- // server bw -+ case RTMP_PACKET_TYPE_SERVER_BW: - // HandleServerBW(r, packet); - break; - -- case 0x06: -- // client bw -+ case RTMP_PACKET_TYPE_CLIENT_BW: - // HandleClientBW(r, packet); - break; - -- case 0x08: -- // audio data -+ case RTMP_PACKET_TYPE_AUDIO: - //RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize); - break; - -- case 0x09: -- // video data -+ case RTMP_PACKET_TYPE_VIDEO: - //RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize); - break; - -- case 0x0F: // flex stream send -+ case RTMP_PACKET_TYPE_FLEX_STREAM_SEND: - break; - -- case 0x10: // flex shared object -+ case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT: - break; - -- case 0x11: // flex message -+ case RTMP_PACKET_TYPE_FLEX_MESSAGE: - { - RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %u bytes, not fully supported", - __FUNCTION__, packet->m_nBodySize); -@@ -827,16 +820,13 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - RTMP_Close(r); - break; - } -- case 0x12: -- // metadata (notify) -+ case RTMP_PACKET_TYPE_INFO: - break; - -- case 0x13: -- /* shared object */ -+ case RTMP_PACKET_TYPE_SHARED_OBJECT: - break; - -- case 0x14: -- // invoke -+ case RTMP_PACKET_TYPE_INVOKE: - RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__, - packet->m_nBodySize); - //RTMP_LogHex(packet.m_body, packet.m_nBodySize); -@@ -845,8 +835,7 @@ ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet) - RTMP_Close(r); - break; - -- case 0x16: -- /* flv */ -+ case RTMP_PACKET_TYPE_FLASH_VIDEO: - break; - default: - RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__, --- -1.7.10.4 - - -From 6df3b1f2015f928d74a675bda542c354b893c2c2 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Tue, 30 Oct 2012 08:57:43 -0700 -Subject: [PATCH 46/64] Add functions for doing server side TLS initialization - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 682e3b8..cba8b6c 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -35,6 +35,19 @@ - #ifdef USE_POLARSSL - #include <polarssl/version.h> - #include <polarssl/havege.h> -+ -+static const char *my_dhm_P = -+ "E4004C1F94182000103D883A448B3F80" \ -+ "2CE4B44A83301270002C20D0321CFD00" \ -+ "11CCEF784C26A400F43DFB901BCA7538" \ -+ "F2C6B176001CF5A0FD16D2C48B1D0C1C" \ -+ "F6AC8E1DA6BCC3B4E1F96B0564965300" \ -+ "FFA1D0B601EB2800F489AA512C4B248C" \ -+ "01F76949A60BB7F00A40B1EAB64BDD48" \ -+ "E8A700D60B7F1200FA8E77B0A979DABF"; -+ -+static const char *my_dhm_G = "4"; -+ - #elif defined(USE_GNUTLS) - #include <gnutls/gnutls.h> - #else /* USE_OPENSSL */ -@@ -228,6 +241,82 @@ RTMP_TLS_Init() - #endif - } - -+void * -+RTMP_TLS_AllocServerContext(const char* cert, const char* key) -+{ -+ void *ctx = NULL; -+#ifdef CRYPTO -+ if (!RTMP_TLS_ctx) -+ RTMP_TLS_Init(); -+#ifdef USE_POLARSSL -+ tls_server_ctx *tc = ctx = calloc(1, sizeof(struct tls_server_ctx)); -+ tc->dhm_P = my_dhm_P; -+ tc->dhm_G = my_dhm_G; -+ tc->hs = &RTMP_TLS_ctx->hs; -+ if (x509parse_crtfile(&tc->cert, cert)) { -+ free(tc); -+ return NULL; -+ } -+ if (x509parse_keyfile(&tc->key, key, NULL)) { -+ x509_free(&tc->cert); -+ free(tc); -+ return NULL; -+ } -+#elif defined(USE_GNUTLS) && !defined(NO_SSL) -+ gnutls_certificate_allocate_credentials((gnutls_certificate_credentials*) &ctx); -+ if (gnutls_certificate_set_x509_key_file(ctx, cert, key, GNUTLS_X509_FMT_PEM) != 0) { -+ gnutls_certificate_free_credentials(ctx); -+ return NULL; -+ } -+#elif !defined(NO_SSL) /* USE_OPENSSL */ -+ ctx = SSL_CTX_new(SSLv23_server_method()); -+ FILE *f = fopen(key, "r"); -+ if (!f) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ EVP_PKEY *k = PEM_read_PrivateKey(f, NULL, NULL, NULL); -+ fclose(f); -+ if (!k) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ SSL_CTX_use_PrivateKey(ctx, k); -+ EVP_PKEY_free(k); -+ f = fopen(cert, "r"); -+ if (!f) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ X509 *c = PEM_read_X509(f, NULL, NULL, NULL); -+ fclose(f); -+ if (!c) { -+ SSL_CTX_free(ctx); -+ return NULL; -+ } -+ SSL_CTX_use_certificate(ctx, c); -+ X509_free(c); -+#endif -+#endif -+ return ctx; -+} -+ -+void -+RTMP_TLS_FreeServerContext(void *ctx) -+{ -+#ifdef CRYPTO -+#ifdef USE_POLARSSL -+ x509_free(&((tls_server_ctx*)ctx)->cert); -+ rsa_free(&((tls_server_ctx*)ctx)->key); -+ free(ctx); -+#elif defined(USE_GNUTLS) && !defined(NO_SSL) -+ gnutls_certificate_free_credentials(ctx); -+#elif !defined(NO_SSL) /* USE_OPENSSL */ -+ SSL_CTX_free(ctx); -+#endif -+#endif -+} -+ - RTMP * - RTMP_Alloc() - { -@@ -868,6 +957,23 @@ RTMP_Connect0(RTMP *r, struct sockaddr * service) - } - - int -+RTMP_TLS_Accept(RTMP *r, void *ctx) -+{ -+#if defined(CRYPTO) && !defined(NO_SSL) -+ TLS_server(ctx, r->m_sb.sb_ssl); -+ TLS_setfd(r->m_sb.sb_ssl, r->m_sb.sb_socket); -+ if (TLS_accept(r->m_sb.sb_ssl) < 0) -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__); -+ return FALSE; -+ } -+ return TRUE; -+#else -+ return FALSE; -+#endif -+} -+ -+int - RTMP_Connect1(RTMP *r, RTMPPacket *cp) - { - if (r->Link.protocol & RTMP_FEATURE_SSL) -diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h -index 6b2ae5b..76e01fd 100644 ---- a/librtmp/rtmp.h -+++ b/librtmp/rtmp.h -@@ -307,6 +307,7 @@ extern "C" - int RTMP_Connect0(RTMP *r, struct sockaddr *svc); - int RTMP_Connect1(RTMP *r, RTMPPacket *cp); - int RTMP_Serve(RTMP *r); -+ int RTMP_TLS_Accept(RTMP *r, void *ctx); - - int RTMP_ReadPacket(RTMP *r, RTMPPacket *packet); - int RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue); -@@ -329,6 +330,9 @@ extern "C" - void RTMP_Free(RTMP *r); - void RTMP_EnableWrite(RTMP *r); - -+ void *RTMP_TLS_AllocServerContext(const char* cert, const char* key); -+ void RTMP_TLS_FreeServerContext(void *ctx); -+ - int RTMP_LibVersion(void); - void RTMP_UserInterrupt(void); /* user typed Ctrl-C */ - -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 1bf0735..2cdb705 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -72,14 +72,30 @@ typedef struct tls_ctx { - havege_state hs; - ssl_session ssn; - } tls_ctx; -+typedef struct tls_server_ctx { -+ havege_state *hs; -+ x509_cert cert; -+ rsa_context key; -+ ssl_session ssn; -+ const char *dhm_P, *dhm_G; -+} tls_server_ctx; -+ - #define TLS_CTX tls_ctx * - #define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ - ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ - ssl_set_rng(s, havege_random, &ctx->hs);\ - ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ - ssl_set_session(s, 1, 600, &ctx->ssn) -+#define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ -+ ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\ -+ ssl_set_rng(s, havege_rand, ((tls_server_ctx*)ctx)->hs);\ -+ ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ -+ ssl_set_session(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\ -+ ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\ -+ ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G) - #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) - #define TLS_connect(s) ssl_handshake(s) -+#define TLS_accept(s) ssl_handshake(s) - #define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l) - #define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l) - #define TLS_shutdown(s) ssl_close_notify(s) -@@ -93,8 +109,10 @@ typedef struct tls_ctx { - } tls_ctx; - #define TLS_CTX tls_ctx * - #define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred) -+#define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx) - #define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd) - #define TLS_connect(s) gnutls_handshake(s) -+#define TLS_accept(s) gnutls_handshake(s) - #define TLS_read(s,b,l) gnutls_record_recv(s,b,l) - #define TLS_write(s,b,l) gnutls_record_send(s,b,l) - #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR) -@@ -103,8 +121,10 @@ typedef struct tls_ctx { - #else /* USE_OPENSSL */ - #define TLS_CTX SSL_CTX * - #define TLS_client(ctx,s) s = SSL_new(ctx) -+#define TLS_server(ctx,s) s = SSL_new(ctx) - #define TLS_setfd(s,fd) SSL_set_fd(s,fd) - #define TLS_connect(s) SSL_connect(s) -+#define TLS_accept(s) SSL_accept(s) - #define TLS_read(s,b,l) SSL_read(s,b,l) - #define TLS_write(s,b,l) SSL_write(s,b,l) - #define TLS_shutdown(s) SSL_shutdown(s) --- -1.7.10.4 - - -From 002ef6f6be2bbdf852ff64ab6981d709435a9045 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Sun, 20 May 2012 23:37:35 +0300 -Subject: [PATCH 47/64] Support rtmps in rtmpsrv - - -diff --git a/rtmpsrv.c b/rtmpsrv.c -index fc727bc..a9e9045 100644 ---- a/rtmpsrv.c -+++ b/rtmpsrv.c -@@ -92,6 +92,7 @@ typedef struct - } STREAMING_SERVER; - - STREAMING_SERVER *rtmpServer = 0; // server structure pointer -+void *sslCtx = NULL; - - STREAMING_SERVER *startStreaming(const char *address, int port); - void stopStreaming(STREAMING_SERVER * server); -@@ -897,6 +898,11 @@ void doServe(STREAMING_SERVER * server, // server socket and state (our listenin - { - RTMP_Init(rtmp); - rtmp->m_sb.sb_socket = sockfd; -+ if (sslCtx && !RTMP_TLS_Accept(rtmp, sslCtx)) -+ { -+ RTMP_Log(RTMP_LOGERROR, "TLS handshake failed"); -+ goto cleanup; -+ } - if (!RTMP_Serve(rtmp)) - { - RTMP_Log(RTMP_LOGERROR, "Handshake failed"); -@@ -1061,20 +1067,32 @@ int - main(int argc, char **argv) - { - int nStatus = RD_SUCCESS; -+ int i; - - // http streaming server - char DEFAULT_HTTP_STREAMING_DEVICE[] = "0.0.0.0"; // 0.0.0.0 is any device - - char *rtmpStreamingDevice = DEFAULT_HTTP_STREAMING_DEVICE; // streaming device, default 0.0.0.0 - int nRtmpStreamingPort = 1935; // port -+ char *cert = NULL, *key = NULL; - - RTMP_LogPrintf("RTMP Server %s\n", RTMPDUMP_VERSION); - RTMP_LogPrintf("(c) 2010 Andrej Stepanchuk, Howard Chu; license: GPL\n\n"); - - RTMP_debuglevel = RTMP_LOGINFO; - -- if (argc > 1 && !strcmp(argv[1], "-z")) -- RTMP_debuglevel = RTMP_LOGALL; -+ for (i = 1; i < argc; i++) -+ { -+ if (!strcmp(argv[i], "-z")) -+ RTMP_debuglevel = RTMP_LOGALL; -+ else if (!strcmp(argv[i], "-c") && i + 1 < argc) -+ cert = argv[++i]; -+ else if (!strcmp(argv[i], "-k") && i + 1 < argc) -+ key = argv[++i]; -+ } -+ -+ if (cert && key) -+ sslCtx = RTMP_TLS_AllocServerContext(cert, key); - - // init request - memset(&defaultRTMPRequest, 0, sizeof(RTMP_REQUEST)); -@@ -1118,6 +1136,9 @@ main(int argc, char **argv) - } - RTMP_Log(RTMP_LOGDEBUG, "Done, exiting..."); - -+ if (sslCtx) -+ RTMP_TLS_FreeServerContext(sslCtx); -+ - CleanupSockets(); - - #ifdef _DEBUG --- -1.7.10.4 - - -From 8e527f61afbcb72eb7d8ae1f507765cdc2df2785 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 21 May 2012 18:17:29 +0300 -Subject: [PATCH 48/64] Add null termination to buffers before using strstr - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index cba8b6c..83f3247 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -3673,7 +3673,7 @@ RTMPSockBuf_Fill(RTMPSockBuf *sb) - - while (1) - { -- nBytes = sizeof(sb->sb_buf) - sb->sb_size - (sb->sb_start - sb->sb_buf); -+ nBytes = sizeof(sb->sb_buf) - 1 - sb->sb_size - (sb->sb_start - sb->sb_buf); - #if defined(CRYPTO) && !defined(NO_SSL) - if (sb->sb_ssl) - { -@@ -3852,6 +3852,7 @@ HTTP_read(RTMP *r, int fill) - return -2; - if (strncmp(r->m_sb.sb_start, "HTTP/1.1 200 ", 13)) - return -1; -+ r->m_sb.sb_start[r->m_sb.sb_size] = '\0'; - ptr = r->m_sb.sb_start + sizeof("HTTP/1.1 200"); - while ((ptr = strstr(ptr, "Content-"))) { - if (!strncasecmp(ptr+8, "length:", 7)) break; --- -1.7.10.4 - - -From 895392a7161ceb37ac32b3fb4a910b350361b13f Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 21 May 2012 18:17:30 +0300 -Subject: [PATCH 49/64] Buffer more data before returning successfully from - HTTP_read, if needed - -This fixes issues if the http header and the payload data -are sent in separate packets (as they normally are), and the -buffer contains the full header but none of the payload. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 83f3247..0d28666 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -3846,6 +3846,7 @@ HTTP_read(RTMP *r, int fill) - char *ptr; - int hlen; - -+restart: - if (fill) - RTMPSockBuf_Fill(&r->m_sb); - if (r->m_sb.sb_size < 144) -@@ -3865,6 +3866,12 @@ HTTP_read(RTMP *r, int fill) - if (!ptr) - return -1; - ptr += 4; -+ if (ptr + (r->m_clientID.av_val ? 1 : hlen) > r->m_sb.sb_start + r->m_sb.sb_size) -+ { -+ if (fill) -+ goto restart; -+ return -2; -+ } - r->m_sb.sb_size -= ptr - r->m_sb.sb_start; - r->m_sb.sb_start = ptr; - r->m_unackd--; --- -1.7.10.4 - - -From 4ded9e053744e54286ab9af4e9657f5926a79a2c Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 21 May 2012 18:17:31 +0300 -Subject: [PATCH 50/64] Don't require 144 bytes to be buffered before - proceeding with HTTP_read - -This makes the code more flexible, if servers were to use -smaller headers. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 0d28666..21e2c18 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -3849,11 +3849,20 @@ HTTP_read(RTMP *r, int fill) - restart: - if (fill) - RTMPSockBuf_Fill(&r->m_sb); -- if (r->m_sb.sb_size < 144) -+ if (r->m_sb.sb_size < 13) { -+ if (fill) -+ goto restart; - return -2; -+ } - if (strncmp(r->m_sb.sb_start, "HTTP/1.1 200 ", 13)) - return -1; - r->m_sb.sb_start[r->m_sb.sb_size] = '\0'; -+ if (!strstr(r->m_sb.sb_start, "\r\n\r\n")) { -+ if (fill) -+ goto restart; -+ return -2; -+ } -+ - ptr = r->m_sb.sb_start + sizeof("HTTP/1.1 200"); - while ((ptr = strstr(ptr, "Content-"))) { - if (!strncasecmp(ptr+8, "length:", 7)) break; --- -1.7.10.4 - - -From 91921dda7002ea8ffed9dfb74ad2913dfdd0b1ed Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 21 May 2012 18:17:32 +0300 -Subject: [PATCH 51/64] Refill if HTTP_read indicated it needs more data - -HTTP_read wants to skip past the first payload byte, so -it actually needs to have at least 144 + 1 bytes buffered. - -This also avoids relying on the magic 144 byte constant altogether, -which could easily break if servers include less reply headers. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 21e2c18..6183d20 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -1403,9 +1403,11 @@ ReadN(RTMP *r, char *buffer, int n) - int nBytes = 0, nRead; - if (r->Link.protocol & RTMP_FEATURE_HTTP) - { -+ int refill = 0; - while (!r->m_resplen) - { -- if (r->m_sb.sb_size < 144) -+ int ret; -+ if (r->m_sb.sb_size < 13 || refill) - { - if (!r->m_unackd) - HTTP_Post(r, RTMPT_IDLE, "", 1); -@@ -1416,12 +1418,20 @@ ReadN(RTMP *r, char *buffer, int n) - return 0; - } - } -- if (HTTP_read(r, 0) == -1) -+ if ((ret = HTTP_read(r, 0)) == -1) - { - RTMP_Log(RTMP_LOGDEBUG, "%s, No valid HTTP response found", __FUNCTION__); - RTMP_Close(r); - return 0; - } -+ else if (ret == -2) -+ { -+ refill = 1; -+ } -+ else -+ { -+ refill = 0; -+ } - } - if (r->m_resplen && !r->m_sb.sb_size) - RTMPSockBuf_Fill(&r->m_sb); --- -1.7.10.4 - - -From 4a08069f086b68e99f33e931583148f4090960a3 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Mon, 21 May 2012 23:52:11 +0300 -Subject: [PATCH 52/64] Use CRLF newlines consistently for all HTTP POST - headers - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 6183d20..ab52c49 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -3835,8 +3835,8 @@ HTTP_Post(RTMP *r, RTMPTCmd cmd, const char *buf, int len) - int hlen = snprintf(hbuf, sizeof(hbuf), "POST /%s%s/%d HTTP/1.1\r\n" - "Host: %.*s:%d\r\n" - "Accept: */*\r\n" -- "User-Agent: Shockwave Flash\n" -- "Connection: Keep-Alive\n" -+ "User-Agent: Shockwave Flash\r\n" -+ "Connection: Keep-Alive\r\n" - "Cache-Control: no-cache\r\n" - "Content-type: application/x-fcs\r\n" - "Content-length: %d\r\n\r\n", RTMPT_cmds[cmd], --- -1.7.10.4 - - -From 0fb1d9936fb25f0755bb8b4afc95db048efe4526 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Wed, 30 May 2012 22:06:57 +0300 -Subject: [PATCH 53/64] Free skipped packets in RTMP_GetNextMediaPacket - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index ab52c49..d35b58a 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -1206,6 +1206,7 @@ RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet) - packet->m_nTimeStamp, packet->m_hasAbsTimestamp, - r->m_mediaStamp); - #endif -+ RTMPPacket_Free(packet); - continue; - } - r->m_pausing = 0; --- -1.7.10.4 - - -From a9282329c3be3bb95f31137867fad9920b682d6d Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Wed, 30 May 2012 22:07:23 +0300 -Subject: [PATCH 54/64] Allocate the channel arrays dynamically - -This avoids having to allocate space for all theoretical channels -if most of them aren't used. This drops the size of the full -RTMP struct from over 1200 KB to 16 KB (on 64 bit), and as long as -only channels with a low number are used, the amount of total -allocated memory stays far below what it was before. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index d35b58a..6f6e97b 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -1216,7 +1216,8 @@ RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet) - if (bHasMediaPacket) - r->m_bPlaying = TRUE; - else if (r->m_sb.sb_timedout && !r->m_pausing) -- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel]; -+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ? -+ r->m_channelTimestamp[r->m_mediaChannel] : 0; - - return bHasMediaPacket; - } -@@ -1998,7 +1999,8 @@ RTMP_SendPause(RTMP *r, int DoPause, int iTime) - int RTMP_Pause(RTMP *r, int DoPause) - { - if (DoPause) -- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel]; -+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ? -+ r->m_channelTimestamp[r->m_mediaChannel] : 0; - return RTMP_SendPause(r, DoPause, r->m_pauseStamp); - } - -@@ -2953,7 +2955,8 @@ HandleCtrl(RTMP *r, const RTMPPacket *packet) - break; - if (!r->m_pausing) - { -- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel]; -+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ? -+ r->m_channelTimestamp[r->m_mediaChannel] : 0; - RTMP_SendPause(r, TRUE, r->m_pauseStamp); - r->m_pausing = 1; - } -@@ -3098,6 +3101,26 @@ RTMP_ReadPacket(RTMP *r, RTMPPacket *packet) - - nSize = packetSize[packet->m_headerType]; - -+ if (packet->m_nChannel >= r->m_channelsAllocatedIn) -+ { -+ int n = packet->m_nChannel + 10; -+ int *timestamp = realloc(r->m_channelTimestamp, sizeof(int) * n); -+ RTMPPacket **packets = realloc(r->m_vecChannelsIn, sizeof(RTMPPacket*) * n); -+ if (!timestamp) -+ free(r->m_channelTimestamp); -+ if (!packets) -+ free(r->m_vecChannelsIn); -+ r->m_channelTimestamp = timestamp; -+ r->m_vecChannelsIn = packets; -+ if (!timestamp || !packets) { -+ r->m_channelsAllocatedIn = 0; -+ return FALSE; -+ } -+ memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, sizeof(int) * (n - r->m_channelsAllocatedIn)); -+ memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn)); -+ r->m_channelsAllocatedIn = n; -+ } -+ - if (nSize == RTMP_LARGE_HEADER_SIZE) /* if we get a full header the timestamp is absolute */ - packet->m_hasAbsTimestamp = TRUE; - -@@ -3373,7 +3396,7 @@ RTMP_SendChunk(RTMP *r, RTMPChunk *chunk) - int - RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue) - { -- const RTMPPacket *prevPacket = r->m_vecChannelsOut[packet->m_nChannel]; -+ const RTMPPacket *prevPacket; - uint32_t last = 0; - int nSize; - int hSize, cSize; -@@ -3383,6 +3406,22 @@ RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue) - int nChunkSize; - int tlen; - -+ if (packet->m_nChannel >= r->m_channelsAllocatedOut) -+ { -+ int n = packet->m_nChannel + 10; -+ RTMPPacket **packets = realloc(r->m_vecChannelsOut, sizeof(RTMPPacket*) * n); -+ if (!packets) { -+ free(r->m_vecChannelsOut); -+ r->m_vecChannelsOut = NULL; -+ r->m_channelsAllocatedOut = 0; -+ return FALSE; -+ } -+ r->m_vecChannelsOut = packets; -+ memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut)); -+ r->m_channelsAllocatedOut = n; -+ } -+ -+ prevPacket = r->m_vecChannelsOut[packet->m_nChannel]; - if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE) - { - /* compress a bit by using the prev packet's attributes */ -@@ -3619,7 +3658,7 @@ RTMP_Close(RTMP *r) - r->m_write.m_nBytesRead = 0; - RTMPPacket_Free(&r->m_write); - -- for (i = 0; i < RTMP_CHANNELS; i++) -+ for (i = 0; i < r->m_channelsAllocatedIn; i++) - { - if (r->m_vecChannelsIn[i]) - { -@@ -3627,12 +3666,23 @@ RTMP_Close(RTMP *r) - free(r->m_vecChannelsIn[i]); - r->m_vecChannelsIn[i] = NULL; - } -+ } -+ free(r->m_vecChannelsIn); -+ r->m_vecChannelsIn = NULL; -+ free(r->m_channelTimestamp); -+ r->m_channelTimestamp = NULL; -+ r->m_channelsAllocatedIn = 0; -+ for (i = 0; i < r->m_channelsAllocatedOut; i++) -+ { - if (r->m_vecChannelsOut[i]) - { - free(r->m_vecChannelsOut[i]); - r->m_vecChannelsOut[i] = NULL; - } - } -+ free(r->m_vecChannelsOut); -+ r->m_vecChannelsOut = NULL; -+ r->m_channelsAllocatedOut = 0; - AV_clear(r->m_methodCalls, r->m_numCalls); - r->m_methodCalls = NULL; - r->m_numCalls = 0; -diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h -index 76e01fd..8cb6e45 100644 ---- a/librtmp/rtmp.h -+++ b/librtmp/rtmp.h -@@ -253,9 +253,11 @@ extern "C" - int m_numCalls; - RTMP_METHOD *m_methodCalls; /* remote method calls queue */ - -- RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS]; -- RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS]; -- int m_channelTimestamp[RTMP_CHANNELS]; /* abs timestamp of last packet */ -+ int m_channelsAllocatedIn; -+ int m_channelsAllocatedOut; -+ RTMPPacket **m_vecChannelsIn; -+ RTMPPacket **m_vecChannelsOut; -+ int *m_channelTimestamp; /* abs timestamp of last packet */ - - double m_fAudioCodecs; /* audioCodecs for the connect packet */ - double m_fVideoCodecs; /* videoCodecs for the connect packet */ --- -1.7.10.4 - - -From 630c8db7d1ee2889d0c26a77d95050c01caf5d5a Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Tue, 30 Oct 2012 09:09:25 -0700 -Subject: [PATCH 55/64] Add adobe authentication support - -From: Sergiy <piratfm@gmail.com> - -To use this, add flashver=FMLE/3.0\20(compatible;\20FMSc/1.0) -and pubUser=<username> pubUser=<password> to the RTMP url. - -This should both work for generic adobe authentication, and for -publishing to akamai. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 6f6e97b..391a3b4 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -27,6 +27,7 @@ - #include <stdlib.h> - #include <string.h> - #include <assert.h> -+#include <time.h> - - #include "rtmp_sys.h" - #include "log.h" -@@ -35,6 +36,9 @@ - #ifdef USE_POLARSSL - #include <polarssl/version.h> - #include <polarssl/havege.h> -+#include <polarssl/md5.h> -+#include <polarssl/base64.h> -+#define MD5_DIGEST_LENGTH 16 - - static const char *my_dhm_P = - "E4004C1F94182000103D883A448B3F80" \ -@@ -50,9 +54,15 @@ static const char *my_dhm_G = "4"; - - #elif defined(USE_GNUTLS) - #include <gnutls/gnutls.h> -+#define MD5_DIGEST_LENGTH 16 -+#include <nettle/base64.h> -+#include <nettle/md5.h> - #else /* USE_OPENSSL */ - #include <openssl/ssl.h> - #include <openssl/rc4.h> -+#include <openssl/md5.h> -+#include <openssl/bio.h> -+#include <openssl/buffer.h> - #endif - TLS_CTX RTMP_TLS_ctx; - #endif -@@ -595,6 +605,10 @@ static struct urlopt { - "Buffer time in milliseconds" }, - { AVC("timeout"), OFF(Link.timeout), OPT_INT, 0, - "Session timeout in seconds" }, -+ { AVC("pubUser"), OFF(Link.pubUser), OPT_STR, 0, -+ "Publisher username" }, -+ { AVC("pubPasswd"), OFF(Link.pubPasswd), OPT_STR, 0, -+ "Publisher password" }, - { {NULL,0}, 0, 0} - }; - -@@ -2433,6 +2447,239 @@ AV_clear(RTMP_METHOD *vals, int num) - free(vals); - } - -+ -+#ifdef CRYPTO -+static int -+b64enc(const unsigned char *input, int length, char *output, int maxsize) -+{ -+#ifdef USE_POLARSSL -+ int buf_size = maxsize; -+ if(base64_encode((unsigned char *) output, &buf_size, input, length) == 0) -+ { -+ output[buf_size] = '\0'; -+ return 1; -+ } -+ else -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__); -+ return 0; -+ } -+#elif defined(USE_GNUTLS) -+ if (BASE64_ENCODE_RAW_LENGTH(length) <= maxsize) -+ base64_encode_raw((uint8_t*) output, length, input); -+ else -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__); -+ return 0; -+ } -+#else /* USE_OPENSSL */ -+ BIO *bmem, *b64; -+ BUF_MEM *bptr; -+ -+ b64 = BIO_new(BIO_f_base64()); -+ bmem = BIO_new(BIO_s_mem()); -+ b64 = BIO_push(b64, bmem); -+ BIO_write(b64, input, length); -+ if (BIO_flush(b64) == 1) -+ { -+ BIO_get_mem_ptr(b64, &bptr); -+ memcpy(output, bptr->data, bptr->length-1); -+ output[bptr->length-1] = '\0'; -+ } -+ else -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__); -+ return 0; -+ } -+ BIO_free_all(b64); -+#endif -+ return 1; -+} -+ -+#ifdef USE_POLARSSL -+#define md5sum(x,y,z) md5(x,y,z); -+#elif defined(USE_GNUTLS) -+static void md5sum(const unsigned char *data, int len, unsigned char *out) -+{ -+ struct md5_ctx ctx; -+ md5_init(&ctx); -+ md5_update(&ctx, len, data); -+ md5_digest(&ctx, MD5_DIGEST_LENGTH, out); -+} -+#else -+#define md5sum(x,y,z) MD5(x,y,z); -+#endif -+ -+static const AVal av_authmod_adobe = AVC("authmod=adobe"); -+ -+static int -+PublisherAuth(RTMP *r, AVal *description) -+{ -+ char *token_in = NULL; -+ char *ptr; -+ unsigned char md5sum_val[MD5_DIGEST_LENGTH+1]; -+ int challenge2_data; -+#define RESPONSE_LEN 32 -+#define CHALLENGE2_LEN 16 -+#define SALTED2_LEN (32+8+8+8) -+ char response[RESPONSE_LEN]; -+ char challenge2[CHALLENGE2_LEN]; -+ char salted2[SALTED2_LEN]; -+ AVal pubToken; -+ -+ if (strstr(description->av_val, av_authmod_adobe.av_val) != NULL) -+ { -+ if(strstr(description->av_val, "code=403 need auth") != NULL) -+ { -+ if (strstr(r->Link.app.av_val, av_authmod_adobe.av_val) != NULL) { -+ RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) { -+ pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_adobe.av_len + 8); -+ pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s", -+ av_authmod_adobe.av_val, -+ r->Link.pubUser.av_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val); -+ r->Link.pFlags |= RTMP_PUB_NAME; -+ } else { -+ RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ } -+ else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL) -+ { -+ char *par, *val = NULL, *orig_ptr; -+ char *user = NULL; -+ char *salt = NULL; -+ char *opaque = NULL; -+ char *challenge = NULL; -+ char *salted1; -+ -+ ptr = orig_ptr = strdup(token_in); -+ while (ptr) -+ { -+ par = ptr; -+ ptr = strchr(par, '&'); -+ if(ptr) -+ *ptr++ = '\0'; -+ -+ val = strchr(par, '='); -+ if(val) -+ *val++ = '\0'; -+ -+ if (strcmp(par, "user") == 0){ -+ user = val; -+ } else if (strcmp(par, "salt") == 0){ -+ salt = val; -+ } else if (strcmp(par, "opaque") == 0){ -+ opaque = val; -+ } else if (strcmp(par, "challenge") == 0){ -+ challenge = val; -+ } -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val); -+ } -+ -+ /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */ -+ salted1 = malloc(strlen(user)+strlen(salt)+r->Link.pubPasswd.av_len+1); -+ strcpy(salted1, user); -+ strcat(salted1, salt); -+ strcat(salted1, r->Link.pubPasswd.av_val); -+ md5sum((unsigned char*) salted1, strlen(salted1), md5sum_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted1); -+ free(salted1); -+ -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ -+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2); -+ -+ srand( time(NULL) ); -+ challenge2_data = rand(); -+ -+ b64enc((unsigned char *) &challenge2_data, sizeof(int), challenge2, CHALLENGE2_LEN); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(%d) = %s", __FUNCTION__, challenge2_data, challenge2); -+ -+ /* response = base64enc(md5(hash1 + opaque + challenge2)) */ -+ if (opaque) -+ strcat(salted2, opaque); -+ if (challenge) -+ strcat(salted2, challenge); -+ strcat(salted2, challenge2); -+ -+ md5sum((unsigned char*) salted2, strlen(salted2), md5sum_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted2); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ -+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response); -+ -+ /* have all hashes, create auth token for the end of app */ -+ pubToken.av_val = malloc(32 + strlen(challenge2) + strlen(response) + (opaque ? strlen(opaque) : 0)); -+ pubToken.av_len = sprintf(pubToken.av_val, -+ "&challenge=%s&response=%s&opaque=%s", -+ challenge2, -+ response, -+ opaque ? opaque : ""); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val); -+ free(orig_ptr); -+ r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE; -+ } -+ else if(strstr(description->av_val, "?reason=authfailed") != NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: wrong password", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ else if(strstr(description->av_val, "?reason=nosuchuser") != NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ else -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s", -+ __FUNCTION__, description->av_val); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ -+ ptr = malloc(r->Link.app.av_len + pubToken.av_len); -+ strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len); -+ strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len); -+ r->Link.app.av_len += pubToken.av_len; -+ if(r->Link.pFlags & RTMP_PUB_ALLOC) -+ free(r->Link.app.av_val); -+ r->Link.app.av_val = ptr; -+ -+ ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len); -+ strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len); -+ strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len); -+ r->Link.tcUrl.av_len += pubToken.av_len; -+ if(r->Link.pFlags & RTMP_PUB_ALLOC) -+ free(r->Link.tcUrl.av_val); -+ r->Link.tcUrl.av_val = ptr; -+ -+ free(pubToken.av_val); -+ r->Link.pFlags |= RTMP_PUB_ALLOC; -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__, -+ r->Link.app.av_len, r->Link.app.av_val, -+ r->Link.tcUrl.av_len, r->Link.tcUrl.av_val, -+ r->Link.playpath.av_val); -+ } -+ else -+ { -+ return 0; -+ } -+ return 1; -+} -+#endif -+ -+ - SAVC(onBWDone); - SAVC(onFCSubscribe); - SAVC(onFCUnsubscribe); -@@ -2442,6 +2689,7 @@ SAVC(_error); - SAVC(close); - SAVC(code); - SAVC(level); -+SAVC(description); - SAVC(onStatus); - SAVC(playlist_ready); - static const AVal av_NetStream_Failed = AVC("NetStream.Failed"); -@@ -2460,6 +2708,8 @@ AVC("NetStream.Play.PublishNotify"); - static const AVal av_NetStream_Play_UnpublishNotify = - AVC("NetStream.Play.UnpublishNotify"); - static const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start"); -+static const AVal av_NetConnection_Connect_Rejected = -+AVC("NetConnection.Connect.Rejected"); - - /* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */ - static int -@@ -2601,12 +2851,73 @@ HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize) - } - else if (AVMATCH(&method, &av__error)) - { -+#ifdef CRYPTO -+ AVal methodInvoked = {0}; -+ int i; -+ -+ if (r->Link.protocol & RTMP_FEATURE_WRITE) -+ { -+ for (i=0; i<r->m_numCalls; i++) -+ { -+ if (r->m_methodCalls[i].num == txn) -+ { -+ methodInvoked = r->m_methodCalls[i].name; -+ AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE); -+ break; -+ } -+ } -+ if (!methodInvoked.av_val) -+ { -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request", -+ __FUNCTION__, txn); -+ goto leave; -+ } -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, received error for method call <%s>", __FUNCTION__, -+ methodInvoked.av_val); -+ -+ if (AVMATCH(&methodInvoked, &av_connect)) -+ { -+ AMFObject obj2; -+ AVal code, level, description; -+ AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2); -+ AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code); -+ AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level); -+ AMFProp_GetString(AMF_GetProp(&obj2, &av_description, -1), &description); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, error description: %s", __FUNCTION__, description.av_val); -+ /* if PublisherAuth returns 1, then reconnect */ -+ PublisherAuth(r, &description); -+ } -+ } -+ else -+ { -+ RTMP_Log(RTMP_LOGERROR, "rtmp server sent error"); -+ } -+ free(methodInvoked.av_val); -+#else - RTMP_Log(RTMP_LOGERROR, "rtmp server sent error"); -+#endif - } - else if (AVMATCH(&method, &av_close)) - { - RTMP_Log(RTMP_LOGERROR, "rtmp server requested close"); - RTMP_Close(r); -+#ifdef CRYPTO -+ if ((r->Link.protocol & RTMP_FEATURE_WRITE) && -+ !(r->Link.pFlags & RTMP_PUB_CLEAN) && -+ ( !(r->Link.pFlags & RTMP_PUB_NAME) || -+ !(r->Link.pFlags & RTMP_PUB_RESP) || -+ (r->Link.pFlags & RTMP_PUB_CLATE) ) ) -+ { -+ /* clean later */ -+ if(r->Link.pFlags & RTMP_PUB_CLATE) -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ RTMP_Log(RTMP_LOGERROR, "authenticating publisher"); -+ -+ if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) -+ goto leave; -+ } -+#endif - } - else if (AVMATCH(&method, &av_onStatus)) - { -@@ -3695,9 +4006,6 @@ RTMP_Close(RTMP *r) - r->m_resplen = 0; - r->m_unackd = 0; - -- free(r->Link.playpath0.av_val); -- r->Link.playpath0.av_val = NULL; -- - if (r->Link.lFlags & RTMP_LF_FTCU) - { - free(r->Link.tcUrl.av_val); -@@ -3706,6 +4014,20 @@ RTMP_Close(RTMP *r) - } - - #ifdef CRYPTO -+ if (!(r->Link.protocol & RTMP_FEATURE_WRITE) || (r->Link.pFlags & RTMP_PUB_CLEAN)) -+ { -+ free(r->Link.playpath0.av_val); -+ r->Link.playpath0.av_val = NULL; -+ } -+ if ((r->Link.protocol & RTMP_FEATURE_WRITE) && -+ (r->Link.pFlags & RTMP_PUB_CLEAN) && -+ (r->Link.pFlags & RTMP_PUB_ALLOC)) -+ { -+ free(r->Link.app.av_val); -+ r->Link.app.av_val = NULL; -+ free(r->Link.tcUrl.av_val); -+ r->Link.tcUrl.av_val = NULL; -+ } - if (r->Link.dh) - { - MDH_free(r->Link.dh); -@@ -3721,6 +4043,9 @@ RTMP_Close(RTMP *r) - RC4_free(r->Link.rc4keyOut); - r->Link.rc4keyOut = NULL; - } -+#else -+ free(r->Link.playpath0.av_val); -+ r->Link.playpath0.av_val = NULL; - #endif - } - -diff --git a/librtmp/rtmp.h b/librtmp/rtmp.h -index 8cb6e45..d723070 100644 ---- a/librtmp/rtmp.h -+++ b/librtmp/rtmp.h -@@ -157,6 +157,8 @@ extern "C" - AVal subscribepath; - AVal usherToken; - AVal token; -+ AVal pubUser; -+ AVal pubPasswd; - AMFObject extras; - int edepth; - -@@ -176,6 +178,13 @@ extern "C" - int protocol; - int timeout; /* connection timeout in seconds */ - -+#define RTMP_PUB_NAME 0x0001 /* send login to server */ -+#define RTMP_PUB_RESP 0x0002 /* send salted password hash */ -+#define RTMP_PUB_ALLOC 0x0004 /* allocated data for new tcUrl & app */ -+#define RTMP_PUB_CLEAN 0x0008 /* need to free allocated data for newer tcUrl & app at exit */ -+#define RTMP_PUB_CLATE 0x0010 /* late clean tcUrl & app at exit */ -+ int pFlags; -+ - unsigned short socksport; - unsigned short port; - --- -1.7.10.4 - - -From 9ecf540e4d5bdc85c17668fa7ead93cc375111ca Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Axelsson?= <bjorn.axelsson@intinor.se> -Date: Tue, 20 Mar 2012 19:12:23 +0200 -Subject: [PATCH 56/64] Add support for limelight authentication - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 391a3b4..5ea1c76 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2511,6 +2511,18 @@ static void md5sum(const unsigned char *data, int len, unsigned char *out) - #endif - - static const AVal av_authmod_adobe = AVC("authmod=adobe"); -+static const AVal av_authmod_llnw = AVC("authmod=llnw"); -+ -+static char *hexenc(unsigned char *inbuf, int len) -+{ -+ char *dst = malloc(len * 2 + 1), *ptr = dst; -+ while(len--) { -+ sprintf(ptr, "%02x", *inbuf++); -+ ptr += 2; -+ } -+ *ptr = '\0'; -+ return dst; -+} - - static int - PublisherAuth(RTMP *r, AVal *description) -@@ -2671,6 +2683,178 @@ PublisherAuth(RTMP *r, AVal *description) - r->Link.tcUrl.av_len, r->Link.tcUrl.av_val, - r->Link.playpath.av_val); - } -+ else if (strstr(description->av_val, av_authmod_llnw.av_val) != NULL) -+ { -+ if(strstr(description->av_val, "code=403 need auth") != NULL) -+ { -+ /* This part seems to be the same for llnw and adobe */ -+ -+ if (strstr(r->Link.app.av_val, av_authmod_llnw.av_val) != NULL) { -+ RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) { -+ pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_llnw.av_len + 8); -+ pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s", -+ av_authmod_llnw.av_val, -+ r->Link.pubUser.av_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val); -+ r->Link.pFlags |= RTMP_PUB_NAME; -+ } else { -+ RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ } -+ else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL) -+ { -+ char *orig_ptr; -+ char *par, *val = NULL; -+ char *user = NULL; -+ char *nonce = NULL; -+ -+ ptr = orig_ptr = strdup(token_in); -+ /* Extract parameters (we need user and nonce) */ -+ while (ptr) -+ { -+ par = ptr; -+ ptr = strchr(par, '&'); -+ if(ptr) -+ *ptr++ = '\0'; -+ -+ val = strchr(par, '='); -+ if(val) -+ *val++ = '\0'; -+ -+ if (strcmp(par, "user") == 0){ -+ user = val; -+ } else if (strcmp(par, "nonce") == 0){ -+ nonce = val; -+ } -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val); -+ } -+ -+ // FIXME: handle case where user==NULL or nonce==NULL -+ -+ /* llnw auth method -+ * Seems to be closely based on HTTP Digest Auth: -+ * http://tools.ietf.org/html/rfc2617 -+ * http://en.wikipedia.org/wiki/Digest_access_authentication -+ */ -+ -+ const char *authmod = "llnw"; -+ const char *realm = "live"; -+ const char *method = "publish"; -+ const char *qop = "auth"; -+ char *tmpbuf; -+ -+ /* nc = 1..connection count (or rather, number of times cnonce has been reused) */ -+ int nc = 1; -+ /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */ -+ char nchex[9]; -+ sprintf(nchex, "%08x", nc); -+ /* cnonce = hexenc(4 random bytes) (initialized on first connection) */ -+ char cnonce[9]; -+ srand( time(NULL) ); // FIXME: a lib shouldn't call srand() -+ sprintf(cnonce, "%08x", rand()); -+ -+ /* hash1 = hexenc(md5(user + ":" + realm + ":" + password)) */ -+ tmpbuf = malloc(strlen(user) + 1 + strlen(realm) + 1 + r->Link.pubPasswd.av_len + 1); -+ sprintf(tmpbuf, "%s:%s:%s", user, realm, r->Link.pubPasswd.av_val); -+ md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ free(tmpbuf); -+ char *hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ -+ /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */ -+ /* Extract appname + appinstance without query parameters */ -+ char *apptmp = malloc(r->Link.app.av_len + 1), *qpos; -+ memcpy(apptmp, r->Link.app.av_val, r->Link.app.av_len); -+ apptmp[r->Link.app.av_len] = '\0'; -+ if((qpos = strchr(apptmp, '?'))) -+ *qpos = '\0'; -+ -+ tmpbuf = malloc(strlen(method) + 2 + strlen(apptmp) + 1); -+ sprintf(tmpbuf, "%s:/%s", method, apptmp); -+ md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ free(tmpbuf); -+ char *hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ -+ free(apptmp); -+ -+ /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */ -+ tmpbuf = malloc(strlen(hash1) + 1 + strlen(nonce) + 1 + strlen(nchex) + 1 + strlen(cnonce) + 1 + strlen(qop) + 1 + strlen(hash2) + 1); -+ sprintf(tmpbuf, "%s:%s:%s:%s:%s:%s", hash1, nonce, nchex, cnonce, qop, hash2); -+ md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ free(tmpbuf); -+ char *hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ -+ /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */ -+ /* Append nonces and response to query string which already contains -+ * user + authmod */ -+ pubToken.av_val = malloc(64 + strlen(authmod) + strlen(user) + strlen(nonce) + strlen(cnonce) + strlen(nchex) + strlen(hash3)); -+ sprintf(pubToken.av_val, -+ "&nonce=%s&cnonce=%s&nc=%s&response=%s", -+ nonce, cnonce, nchex, hash3); -+ pubToken.av_len = strlen(pubToken.av_val); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val); -+ r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE; -+ -+ free(hash1); -+ free(hash2); -+ free(hash3); -+ free(orig_ptr); -+ } -+ else if(strstr(description->av_val, "?reason=authfail") != NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ else if(strstr(description->av_val, "?reason=nosuchuser") != NULL) -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ else -+ { -+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s", -+ __FUNCTION__, description->av_val); -+ r->Link.pFlags |= RTMP_PUB_CLEAN; -+ return 0; -+ } -+ -+ ptr = malloc(r->Link.app.av_len + pubToken.av_len); -+ strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len); -+ strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len); -+ r->Link.app.av_len += pubToken.av_len; -+ if(r->Link.pFlags & RTMP_PUB_ALLOC) -+ free(r->Link.app.av_val); -+ r->Link.app.av_val = ptr; -+ -+ ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len); -+ strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len); -+ strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len); -+ r->Link.tcUrl.av_len += pubToken.av_len; -+ if(r->Link.pFlags & RTMP_PUB_ALLOC) -+ free(r->Link.tcUrl.av_val); -+ r->Link.tcUrl.av_val = ptr; -+ -+ free(pubToken.av_val); -+ r->Link.pFlags |= RTMP_PUB_ALLOC; -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__, -+ r->Link.app.av_len, r->Link.app.av_val, -+ r->Link.tcUrl.av_len, r->Link.tcUrl.av_val, -+ r->Link.playpath.av_val); -+ } - else - { - return 0; --- -1.7.10.4 - - -From 883c33489403ed360a01d1a47ec76d476525b49e Mon Sep 17 00:00:00 2001 -From: LRN <lrn1986@gmail.com> -Date: Sat, 5 May 2012 21:15:36 +0400 -Subject: [PATCH 57/64] Fix dll name to have SO_VERSION - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -subj is attached - -Changes librtmp.dll into librtmp-$(SO_VERSION).dll, the same form that -libtool uses. -librtmp.dll is still created from librtmp-$(SO_VERSION).dll via `ln -- -sf'; obviously, it makes a hardlink when called in MSYS, but that's -no worse than what we have right now. - -Please, CC me, since i'm not subscibed to this list ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.11 (MingW32) -Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ - -iQEcBAEBAgAGBQJPpWA2AAoJEOs4Jb6SI2Cw+xIH/jqI7SbM1nMHBhFDSDtDFxim -zzlX5zsU9Ss45ZX9VMdzXLSDvxsuB6a97svMlipU2HOs4Ba1rcO8fdNII/8lD7nt -yIWiGDcyZNXP7xBXJOVahYwzDzpyGhOychl2XlgW8/9lY7V1DYFjlPUSWdfw8IH0 -iUX6PKMjrN3n4TTIh1kTwG0YHBRq2JdsRAaTB1uQDwBwNFkNPegWTO8oVvtlb1sc -gxhmN08o/S7nWAJRs5+Ah9eYSvWJral5yzIcxeOISGkZJxLs16F0b5iVtd2J1xN4 -3mNQH4W3n7q/EcsF18/UwI8VjcAZnyCXMGI1VXp9frFEvm8//Bv9jSrWKfrZPwI= -=/n61 ------END PGP SIGNATURE----- - -From 4d885c0ef9eab89ec7ed1383fd5cba5587a6a311 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1=D1?= - =?UTF-8?q?=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= <lrn1986@gmail.com> -Date: Sat, 5 May 2012 21:05:30 +0400 -Subject: [PATCH] Fix dll name to have SO_VERSION - -diff --git a/librtmp/Makefile b/librtmp/Makefile -index 74ee3b5..96c076b 100644 ---- a/librtmp/Makefile -+++ b/librtmp/Makefile -@@ -39,11 +39,11 @@ CRYPTO_DEF=$(DEF_$(CRYPTO)) - SO_VERSION=0 - SOX_posix=so - SOX_darwin=dylib --SOX_mingw=so # useless -+SOX_mingw=dll - SOX=$(SOX_$(SYS)) --SO_posix=$(SOX).$(SO_VERSION) --SO_darwin=$(SO_VERSION).$(SOX) --SO_mingw=dll -+SO_posix=.$(SOX).$(SO_VERSION) -+SO_darwin=.$(SO_VERSION).$(SOX) -+SO_mingw=-$(SO_VERSION).$(SOX) - SO_EXT=$(SO_$(SYS)) - - SODIR_posix=$(LIBDIR) -@@ -64,7 +64,7 @@ INSTALL_IMPLIB=$(INSTALL_IMPLIB_$(SYS)) - - SHARED=yes - SODEF_yes=-fPIC --SOLIB_yes=librtmp.$(SO_EXT) -+SOLIB_yes=librtmp$(SO_EXT) - SOINST_yes=install_so - SO_DEF=$(SODEF_$(SHARED)) - SO_LIB=$(SOLIB_$(SHARED)) -@@ -81,12 +81,12 @@ OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o - all: librtmp.a $(SO_LIB) - - clean: -- rm -f *.o *.a *.$(SOX) *.$(SO_EXT) librtmp.pc -+ rm -f *.o *.a *.$(SOX) *$(SO_EXT) librtmp.pc - - librtmp.a: $(OBJS) - $(AR) rs $@ $? - --librtmp.$(SO_EXT): $(OBJS) -+librtmp$(SO_EXT): $(OBJS) - $(CC) $(SO_LDFLAGS) $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB) - ln -sf $@ librtmp.$(SOX) - -@@ -111,8 +111,8 @@ install_base: librtmp.a librtmp.pc - cp librtmp.pc $(LIBDIR)/pkgconfig - cp librtmp.3 $(MANDIR)/man3 - --install_so: librtmp.$(SO_EXT) -- cp librtmp.$(SO_EXT) $(SODIR) -+install_so: librtmp$(SO_EXT) -+ cp librtmp$(SO_EXT) $(SODIR) - $(INSTALL_IMPLIB) -- cd $(SODIR); ln -sf librtmp.$(SO_EXT) librtmp.$(SOX) -+ cd $(SODIR); ln -sf librtmp$(SO_EXT) librtmp.$(SOX) - --- -1.7.10.4 - - -From e42b5d0926b1a668d7fbd794a70f31040c5f198d Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 11:17:41 -0700 -Subject: [PATCH 58/64] Cleanup authentication code - -from commit 9ecf540e4d5bdc85c17668fa7ead93cc375111ca - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 5ea1c76..6d04708 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2497,17 +2497,16 @@ b64enc(const unsigned char *input, int length, char *output, int maxsize) - } - - #ifdef USE_POLARSSL --#define md5sum(x,y,z) md5(x,y,z); -+#define MD5_CTX md5_context -+#define MD5_Init(ctx) md5_starts(ctx) -+#define MD5_Update(ctx,data,len) md5_update(ctx,data,len) -+#define MD5_Final(dig,ctx) md5_finish(ctx,dig) - #elif defined(USE_GNUTLS) --static void md5sum(const unsigned char *data, int len, unsigned char *out) --{ -- struct md5_ctx ctx; -- md5_init(&ctx); -- md5_update(&ctx, len, data); -- md5_digest(&ctx, MD5_DIGEST_LENGTH, out); --} -+typedef struct md5_ctx MD5_CTX -+#define MD5_Init(ctx) md5_init(ctx) -+#define MD5_Update(ctx,data,len) md5_update(ctx,len,data) -+#define MD5_Final(dig,ctx) md5_digest(ctx,MD5_DIGEST_LENGTH,dig) - #else --#define md5sum(x,y,z) MD5(x,y,z); - #endif - - static const AVal av_authmod_adobe = AVC("authmod=adobe"); -@@ -2530,10 +2529,14 @@ PublisherAuth(RTMP *r, AVal *description) - char *token_in = NULL; - char *ptr; - unsigned char md5sum_val[MD5_DIGEST_LENGTH+1]; -+ MD5_CTX md5ctx; - int challenge2_data; - #define RESPONSE_LEN 32 - #define CHALLENGE2_LEN 16 - #define SALTED2_LEN (32+8+8+8) -+#define B64DIGEST_LEN 22 /* 16 byte digest => 22 b64 chars */ -+#define B64INT_LEN 6 /* 4 byte int => 6 b64 chars */ -+#define HEXHASH_LEN (2*MD5_DIGEST_LENGTH) - char response[RESPONSE_LEN]; - char challenge2[CHALLENGE2_LEN]; - char salted2[SALTED2_LEN]; -@@ -2563,11 +2566,9 @@ PublisherAuth(RTMP *r, AVal *description) - else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL) - { - char *par, *val = NULL, *orig_ptr; -- char *user = NULL; -- char *salt = NULL; -- char *opaque = NULL; -- char *challenge = NULL; -- char *salted1; -+ AVal user, salt, opaque, challenge, *aptr = NULL; -+ opaque.av_len = 0; -+ challenge.av_len = 0; - - ptr = orig_ptr = strdup(token_in); - while (ptr) -@@ -2581,60 +2582,72 @@ PublisherAuth(RTMP *r, AVal *description) - if(val) - *val++ = '\0'; - -+ if (aptr) { -+ aptr->av_len = par - aptr->av_val - 1; -+ aptr = NULL; -+ } - if (strcmp(par, "user") == 0){ -- user = val; -+ user.av_val = val; -+ aptr = &user; - } else if (strcmp(par, "salt") == 0){ -- salt = val; -+ salt.av_val = val; -+ aptr = &salt; - } else if (strcmp(par, "opaque") == 0){ -- opaque = val; -+ opaque.av_val = val; -+ aptr = &opaque; - } else if (strcmp(par, "challenge") == 0){ -- challenge = val; -+ challenge.av_val = val; -+ aptr = &challenge; - } - - RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val); - } -+ if (aptr) -+ aptr->av_len = strlen(aptr->av_val); -+ -+ /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */ -+ MD5_Init(&md5ctx); -+ MD5_Update(&md5ctx, user.av_val, user.av_len); -+ MD5_Update(&md5ctx, salt.av_val, salt.av_len); -+ MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len); -+ MD5_Final(md5sum_val, &md5ctx); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__, -+ user.av_val, salt.av_val, r->Link.pubPasswd.av_val); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); - -- /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */ -- salted1 = malloc(strlen(user)+strlen(salt)+r->Link.pubPasswd.av_len+1); -- strcpy(salted1, user); -- strcat(salted1, salt); -- strcat(salted1, r->Link.pubPasswd.av_val); -- md5sum((unsigned char*) salted1, strlen(salted1), md5sum_val); -- RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted1); -- free(salted1); -- -- RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- -- b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN); -- RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2); -+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2); - -- srand( time(NULL) ); -+ /* FIXME: what byte order does this depend on? */ - challenge2_data = rand(); - - b64enc((unsigned char *) &challenge2_data, sizeof(int), challenge2, CHALLENGE2_LEN); - RTMP_Log(RTMP_LOGDEBUG, "%s, b64(%d) = %s", __FUNCTION__, challenge2_data, challenge2); - -+ MD5_Init(&md5ctx); -+ MD5_Update(&md5ctx, salted2, B64DIGEST_LEN); - /* response = base64enc(md5(hash1 + opaque + challenge2)) */ -- if (opaque) -- strcat(salted2, opaque); -- if (challenge) -- strcat(salted2, challenge); -- strcat(salted2, challenge2); -- -- md5sum((unsigned char*) salted2, strlen(salted2), md5sum_val); -- RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, salted2); -- RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -+ if (opaque.av_len) -+ MD5_Update(&md5ctx, opaque.av_val, opaque.av_len); -+ if (challenge.av_len) -+ MD5_Update(&md5ctx, challenge.av_val, challenge.av_len); -+ MD5_Update(&md5ctx, challenge2, B64INT_LEN); -+ MD5_Final(md5sum_val, &md5ctx); -+ -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__, -+ salted2, opaque.av_len ? opaque.av_val : "", challenge2); -+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); - -- b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN); -- RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response); -+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response); - - /* have all hashes, create auth token for the end of app */ -- pubToken.av_val = malloc(32 + strlen(challenge2) + strlen(response) + (opaque ? strlen(opaque) : 0)); -+ pubToken.av_val = malloc(32 + B64INT_LEN + B64DIGEST_LEN + opaque.av_len); - pubToken.av_len = sprintf(pubToken.av_val, - "&challenge=%s&response=%s&opaque=%s", - challenge2, - response, -- opaque ? opaque : ""); -+ opaque.av_len ? opaque.av_val : ""); - RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val); - free(orig_ptr); - r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE; -@@ -2710,8 +2723,26 @@ PublisherAuth(RTMP *r, AVal *description) - { - char *orig_ptr; - char *par, *val = NULL; -- char *user = NULL; -- char *nonce = NULL; -+ char *hash1, *hash2, *hash3; -+ AVal user, nonce, *aptr = NULL; -+ AVal apptmp; -+ -+ /* llnw auth method -+ * Seems to be closely based on HTTP Digest Auth: -+ * http://tools.ietf.org/html/rfc2617 -+ * http://en.wikipedia.org/wiki/Digest_access_authentication -+ */ -+ -+ const char authmod[] = "llnw"; -+ const char realm[] = "live"; -+ const char method[] = "publish"; -+ const char qop[] = "auth"; -+ /* nc = 1..connection count (or rather, number of times cnonce has been reused) */ -+ int nc = 1; -+ /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */ -+ char nchex[9]; -+ /* cnonce = hexenc(4 random bytes) (initialized on first connection) */ -+ char cnonce[9]; - - ptr = orig_ptr = strdup(token_in); - /* Extract parameters (we need user and nonce) */ -@@ -2726,82 +2757,84 @@ PublisherAuth(RTMP *r, AVal *description) - if(val) - *val++ = '\0'; - -+ if (aptr) { -+ aptr->av_len = par - aptr->av_val - 1; -+ aptr = NULL; -+ } - if (strcmp(par, "user") == 0){ -- user = val; -+ user.av_val = val; -+ aptr = &user; - } else if (strcmp(par, "nonce") == 0){ -- nonce = val; -+ nonce.av_val = val; -+ aptr = &nonce; - } - - RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val); - } -+ if (aptr) -+ aptr->av_len = strlen(aptr->av_val); - -- // FIXME: handle case where user==NULL or nonce==NULL -- -- /* llnw auth method -- * Seems to be closely based on HTTP Digest Auth: -- * http://tools.ietf.org/html/rfc2617 -- * http://en.wikipedia.org/wiki/Digest_access_authentication -- */ -- -- const char *authmod = "llnw"; -- const char *realm = "live"; -- const char *method = "publish"; -- const char *qop = "auth"; -- char *tmpbuf; -+ /* FIXME: handle case where user==NULL or nonce==NULL */ - -- /* nc = 1..connection count (or rather, number of times cnonce has been reused) */ -- int nc = 1; -- /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */ -- char nchex[9]; - sprintf(nchex, "%08x", nc); -- /* cnonce = hexenc(4 random bytes) (initialized on first connection) */ -- char cnonce[9]; -- srand( time(NULL) ); // FIXME: a lib shouldn't call srand() - sprintf(cnonce, "%08x", rand()); - - /* hash1 = hexenc(md5(user + ":" + realm + ":" + password)) */ -- tmpbuf = malloc(strlen(user) + 1 + strlen(realm) + 1 + r->Link.pubPasswd.av_len + 1); -- sprintf(tmpbuf, "%s:%s:%s", user, realm, r->Link.pubPasswd.av_val); -- md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -- RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ MD5_Init(&md5ctx); -+ MD5_Update(&md5ctx, user.av_val, user.av_len); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, realm, sizeof(realm)-1); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len); -+ MD5_Final(md5sum_val, &md5ctx); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s) =>", __FUNCTION__, -+ user.av_val, realm, r->Link.pubPasswd.av_val); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- free(tmpbuf); -- char *hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); - - /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */ - /* Extract appname + appinstance without query parameters */ -- char *apptmp = malloc(r->Link.app.av_len + 1), *qpos; -- memcpy(apptmp, r->Link.app.av_val, r->Link.app.av_len); -- apptmp[r->Link.app.av_len] = '\0'; -- if((qpos = strchr(apptmp, '?'))) -- *qpos = '\0'; -- -- tmpbuf = malloc(strlen(method) + 2 + strlen(apptmp) + 1); -- sprintf(tmpbuf, "%s:/%s", method, apptmp); -- md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -- RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ apptmp = r->Link.app; -+ ptr = strchr(apptmp.av_val, '?'); -+ if (ptr) -+ apptmp.av_len = ptr - apptmp.av_val; -+ -+ MD5_Init(&md5ctx); -+ MD5_Update(&md5ctx, method, sizeof(method)-1); -+ MD5_Update(&md5ctx, ":/", 2); -+ MD5_Update(&md5ctx, apptmp.av_val, apptmp.av_len); -+ MD5_Final(md5sum_val, &md5ctx); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:/%.*s) =>", __FUNCTION__, -+ method, apptmp.av_len, apptmp.av_val); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- free(tmpbuf); -- char *hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -- -- free(apptmp); -+ hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); - - /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */ -- tmpbuf = malloc(strlen(hash1) + 1 + strlen(nonce) + 1 + strlen(nchex) + 1 + strlen(cnonce) + 1 + strlen(qop) + 1 + strlen(hash2) + 1); -- sprintf(tmpbuf, "%s:%s:%s:%s:%s:%s", hash1, nonce, nchex, cnonce, qop, hash2); -- md5sum((unsigned char*)tmpbuf, strlen(tmpbuf), md5sum_val); -- RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s) =>", __FUNCTION__, tmpbuf); -+ MD5_Init(&md5ctx); -+ MD5_Update(&md5ctx, hash1, HEXHASH_LEN); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, nonce.av_val, nonce.av_len); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, nchex, sizeof(nchex)-1); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, cnonce, sizeof(cnonce)-1); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, qop, sizeof(qop)-1); -+ MD5_Update(&md5ctx, ":", 1); -+ MD5_Update(&md5ctx, hash2, HEXHASH_LEN); -+ MD5_Final(md5sum_val, &md5ctx); -+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s:%s:%s:%s) =>", __FUNCTION__, -+ hash1, nonce.av_val, nchex, cnonce, qop, hash2); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- free(tmpbuf); -- char *hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); - - /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */ - /* Append nonces and response to query string which already contains - * user + authmod */ -- pubToken.av_val = malloc(64 + strlen(authmod) + strlen(user) + strlen(nonce) + strlen(cnonce) + strlen(nchex) + strlen(hash3)); -+ pubToken.av_val = malloc(64 + sizeof(authmod)-1 + user.av_len + nonce.av_len + sizeof(cnonce)-1 + sizeof(nchex)-1 + HEXHASH_LEN); - sprintf(pubToken.av_val, - "&nonce=%s&cnonce=%s&nc=%s&response=%s", -- nonce, cnonce, nchex, hash3); -+ nonce.av_val, cnonce, nchex, hash3); - pubToken.av_len = strlen(pubToken.av_val); - RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val); - r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE; --- -1.7.10.4 - - -From 1f6c6434d6794b3ba14540a141bab358eba48b13 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 11:30:07 -0700 -Subject: [PATCH 59/64] More authentication cleanup - - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 6d04708..4858e24 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2512,15 +2512,14 @@ typedef struct md5_ctx MD5_CTX - static const AVal av_authmod_adobe = AVC("authmod=adobe"); - static const AVal av_authmod_llnw = AVC("authmod=llnw"); - --static char *hexenc(unsigned char *inbuf, int len) -+static void hexenc(unsigned char *inbuf, int len, char *dst) - { -- char *dst = malloc(len * 2 + 1), *ptr = dst; -+ char *ptr = dst; - while(len--) { - sprintf(ptr, "%02x", *inbuf++); - ptr += 2; - } - *ptr = '\0'; -- return dst; - } - - static int -@@ -2723,7 +2722,7 @@ PublisherAuth(RTMP *r, AVal *description) - { - char *orig_ptr; - char *par, *val = NULL; -- char *hash1, *hash2, *hash3; -+ char hash1[HEXHASH_LEN+1], hash2[HEXHASH_LEN+1], hash3[HEXHASH_LEN+1]; - AVal user, nonce, *aptr = NULL; - AVal apptmp; - -@@ -2790,7 +2789,7 @@ PublisherAuth(RTMP *r, AVal *description) - RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s) =>", __FUNCTION__, - user.av_val, realm, r->Link.pubPasswd.av_val); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- hash1 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash1); - - /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */ - /* Extract appname + appinstance without query parameters */ -@@ -2807,7 +2806,7 @@ PublisherAuth(RTMP *r, AVal *description) - RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:/%.*s) =>", __FUNCTION__, - method, apptmp.av_len, apptmp.av_val); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- hash2 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash2); - - /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */ - MD5_Init(&md5ctx); -@@ -2826,7 +2825,7 @@ PublisherAuth(RTMP *r, AVal *description) - RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s:%s:%s:%s) =>", __FUNCTION__, - hash1, nonce.av_val, nchex, cnonce, qop, hash2); - RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH); -- hash3 = hexenc(md5sum_val, MD5_DIGEST_LENGTH); -+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash3); - - /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */ - /* Append nonces and response to query string which already contains -@@ -2839,9 +2838,6 @@ PublisherAuth(RTMP *r, AVal *description) - RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val); - r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE; - -- free(hash1); -- free(hash2); -- free(hash3); - free(orig_ptr); - } - else if(strstr(description->av_val, "?reason=authfail") != NULL) --- -1.7.10.4 - - -From 9d6dc72d7c43554dbe8cdb02f450807230df8c25 Mon Sep 17 00:00:00 2001 -From: Martin Storsjo <martin@martin.st> -Date: Tue, 30 Oct 2012 19:22:16 +0200 -Subject: [PATCH 60/64] Simplify initializing the TLS server context - -This does the same thing, but I wasn't aware of these functions -when I initially wrote this. - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 4858e24..d72f105 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -280,32 +280,14 @@ RTMP_TLS_AllocServerContext(const char* cert, const char* key) - } - #elif !defined(NO_SSL) /* USE_OPENSSL */ - ctx = SSL_CTX_new(SSLv23_server_method()); -- FILE *f = fopen(key, "r"); -- if (!f) { -+ if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) { - SSL_CTX_free(ctx); - return NULL; - } -- EVP_PKEY *k = PEM_read_PrivateKey(f, NULL, NULL, NULL); -- fclose(f); -- if (!k) { -+ if (!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) { - SSL_CTX_free(ctx); - return NULL; - } -- SSL_CTX_use_PrivateKey(ctx, k); -- EVP_PKEY_free(k); -- f = fopen(cert, "r"); -- if (!f) { -- SSL_CTX_free(ctx); -- return NULL; -- } -- X509 *c = PEM_read_X509(f, NULL, NULL, NULL); -- fclose(f); -- if (!c) { -- SSL_CTX_free(ctx); -- return NULL; -- } -- SSL_CTX_use_certificate(ctx, c); -- X509_free(c); - #endif - #endif - return ctx; --- -1.7.10.4 - - -From f3e3e6b507ac0df89a11764abd15cc9535593735 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Axelsson?= <bjorn.axelsson@intinor.se> -Date: Tue, 30 Oct 2012 19:31:01 +0200 -Subject: [PATCH 61/64] Look for a fourth slash when splitting the url into - app+playpath - - -diff --git a/librtmp/parseurl.c b/librtmp/parseurl.c -index 0183958..646c70c 100644 ---- a/librtmp/parseurl.c -+++ b/librtmp/parseurl.c -@@ -137,12 +137,14 @@ parsehost: - * application = app[/appinstance] - */ - -- char *slash2, *slash3 = NULL; -+ char *slash2, *slash3 = NULL, *slash4 = NULL; - int applen, appnamelen; - - slash2 = strchr(p, '/'); - if(slash2) - slash3 = strchr(slash2+1, '/'); -+ if(slash3) -+ slash4 = strchr(slash3+1, '/'); - - applen = end-p; /* ondemand, pass all parameters as app */ - appnamelen = applen; /* ondemand length */ -@@ -156,7 +158,9 @@ parsehost: - appnamelen = 8; - } - else { /* app!=ondemand, so app is app[/appinstance] */ -- if(slash3) -+ if(slash4) -+ appnamelen = slash4-p; -+ else if(slash3) - appnamelen = slash3-p; - else if(slash2) - appnamelen = slash2-p; --- -1.7.10.4 - - -From e79a07c8625b56ebb182c12343518faff4902de7 Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Tue, 30 Oct 2012 14:40:14 -0700 -Subject: [PATCH 62/64] PolarSSL version fixes - -Fix commit a312ac7770207bd7d07725c1aef43725206e803a - -diff --git a/librtmp/dh.h b/librtmp/dh.h -index fa264f8..e29587b 100644 ---- a/librtmp/dh.h -+++ b/librtmp/dh.h -@@ -29,9 +29,6 @@ - - #ifdef USE_POLARSSL - #include <polarssl/dhm.h> --#if POLARSSL_VERSION_NUMBER < 0x01010100 --#define havege_random havege_rand --#endif - typedef mpi * MP_t; - #define MP_new(m) m = malloc(sizeof(mpi)); mpi_init(m) - #define MP_set_w(mpi, w) mpi_lset(mpi, w) -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index d72f105..720669e 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -34,7 +34,6 @@ - - #ifdef CRYPTO - #ifdef USE_POLARSSL --#include <polarssl/version.h> - #include <polarssl/havege.h> - #include <polarssl/md5.h> - #include <polarssl/base64.h> -@@ -2435,7 +2434,7 @@ static int - b64enc(const unsigned char *input, int length, char *output, int maxsize) - { - #ifdef USE_POLARSSL -- int buf_size = maxsize; -+ size_t buf_size = maxsize; - if(base64_encode((unsigned char *) output, &buf_size, input, length) == 0) - { - output[buf_size] = '\0'; -@@ -2481,7 +2480,7 @@ b64enc(const unsigned char *input, int length, char *output, int maxsize) - #ifdef USE_POLARSSL - #define MD5_CTX md5_context - #define MD5_Init(ctx) md5_starts(ctx) --#define MD5_Update(ctx,data,len) md5_update(ctx,data,len) -+#define MD5_Update(ctx,data,len) md5_update(ctx,(unsigned char *)data,len) - #define MD5_Final(dig,ctx) md5_finish(ctx,dig) - #elif defined(USE_GNUTLS) - typedef struct md5_ctx MD5_CTX -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 2cdb705..6e2356a 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -65,7 +65,7 @@ - #include <polarssl/net.h> - #include <polarssl/ssl.h> - #include <polarssl/havege.h> --#if POLARSSL_VERSION_NUMBER < 0x01010100 -+#if POLARSSL_VERSION_NUMBER < 0x01010000 - #define havege_random havege_rand - #endif - typedef struct tls_ctx { -@@ -88,7 +88,7 @@ typedef struct tls_server_ctx { - ssl_set_session(s, 1, 600, &ctx->ssn) - #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ - ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\ -- ssl_set_rng(s, havege_rand, ((tls_server_ctx*)ctx)->hs);\ -+ ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\ - ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ - ssl_set_session(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\ - ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\ --- -1.7.10.4 - - -From feb81c8b3e0102b2eed18a34cbfb1e8a513e99ae Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Thu, 1 Nov 2012 17:00:31 -0700 -Subject: [PATCH 63/64] Fix gnutls build - -Missing semicolon in e42b5d0926b1a668d7fbd794a70f31040c5f198d - -diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c -index 720669e..0e00059 100644 ---- a/librtmp/rtmp.c -+++ b/librtmp/rtmp.c -@@ -2483,7 +2483,7 @@ b64enc(const unsigned char *input, int length, char *output, int maxsize) - #define MD5_Update(ctx,data,len) md5_update(ctx,(unsigned char *)data,len) - #define MD5_Final(dig,ctx) md5_finish(ctx,dig) - #elif defined(USE_GNUTLS) --typedef struct md5_ctx MD5_CTX -+typedef struct md5_ctx MD5_CTX; - #define MD5_Init(ctx) md5_init(ctx) - #define MD5_Update(ctx,data,len) md5_update(ctx,len,data) - #define MD5_Final(dig,ctx) md5_digest(ctx,MD5_DIGEST_LENGTH,dig) --- -1.7.10.4 - - -From 19d36368f6c1ec6fa55df319173ca93048309f9a Mon Sep 17 00:00:00 2001 -From: Howard Chu <hyc@highlandsun.com> -Date: Fri, 9 Nov 2012 07:58:08 -0800 -Subject: [PATCH 64/64] PolarSSL 1.2.x compat - - -diff --git a/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h -index 6e2356a..85d7e53 100644 ---- a/librtmp/rtmp_sys.h -+++ b/librtmp/rtmp_sys.h -@@ -68,6 +68,11 @@ - #if POLARSSL_VERSION_NUMBER < 0x01010000 - #define havege_random havege_rand - #endif -+#if POLARSSL_VERSION_NUMBER >= 0x01020000 -+#define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,ctx) -+#else -+#define SSL_SET_SESSION(S,resume,timeout,ctx) ssl_set_session(S,resume,timeout,ctx) -+#endif - typedef struct tls_ctx { - havege_state hs; - ssl_session ssn; -@@ -85,12 +90,12 @@ typedef struct tls_server_ctx { - ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\ - ssl_set_rng(s, havege_random, &ctx->hs);\ - ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ -- ssl_set_session(s, 1, 600, &ctx->ssn) -+ SSL_SET_SESSION(s, 1, 600, &ctx->ssn) - #define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\ - ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\ - ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\ - ssl_set_ciphersuites(s, ssl_default_ciphersuites);\ -- ssl_set_session(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\ -+ SSL_SET_SESSION(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\ - ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\ - ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G) - #define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) --- -1.7.10.4 - |