[SCM] rtmpdump/master: Imported Upstream version 2.4+20111222.git4e06e21

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jan 8 11:16:13 UTC 2012


The following commit has been merged in the master branch:
commit 8eb3ee9bca73a6b586da187a4de95a86380b682b
Author: Reinhard Tartler <siretart at tauware.de>
Date:   Sun Jan 8 11:58:49 2012 +0100

    Imported Upstream version 2.4+20111222.git4e06e21

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/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/Makefile b/librtmp/Makefile
index d61e7a4..a0125f1 100644
--- a/librtmp/Makefile
+++ b/librtmp/Makefile
@@ -52,11 +52,16 @@ 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_mingw=-shared
+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))
 
+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)
@@ -76,7 +81,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 $@ $?
@@ -100,7 +105,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
@@ -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)
 
diff --git a/librtmp/amf.c b/librtmp/amf.c
index 7fa289e..659421e 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;
     }
@@ -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!");
@@ -772,7 +768,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;
     }
@@ -1111,7 +1107,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/dh.h b/librtmp/dh.h
index 8e285a6..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)
@@ -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)
 {
@@ -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/hashswf.c b/librtmp/hashswf.c
index 3c56b69..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);
@@ -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;
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/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/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);
diff --git a/librtmp/rtmp.c b/librtmp/rtmp.c
index 5ef3ae9..52d0254 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);
@@ -184,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);
 }
@@ -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)
@@ -363,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)
@@ -372,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
     {
@@ -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,
@@ -966,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;
       }
   }
@@ -1153,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;
 
@@ -1168,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); */
 
@@ -1190,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;
@@ -1203,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); */
 
@@ -1329,8 +1337,9 @@ 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)
-	    SendBytesReceived(r);
+	      && r->m_nBytesIn > ( r->m_nBytesInSent + r->m_nClientBW / 10))
+	    if (!SendBytesReceived(r))
+	        return FALSE;
 	}
       /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d bytes\n", __FUNCTION__, nBytes); */
 #ifdef _DEBUG
@@ -1641,6 +1650,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");
+
+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
@@ -2297,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 */
     {
@@ -2315,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))
@@ -2324,14 +2366,14 @@ 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;
 	}
       }
       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;
       }
@@ -2364,6 +2406,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);
@@ -2539,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;
 	}
 
@@ -2565,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;
 	}
 
@@ -3010,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;
     }
@@ -3581,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))
@@ -4129,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;
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/librtmp/rtmp_sys.h b/librtmp/rtmp_sys.h
index 6a3f215..c3fd4a6 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
@@ -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)
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.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 c1cd95b..34bfdba 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 */
@@ -444,7 +445,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 +506,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
@@ -683,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");
@@ -692,9 +695,11 @@ 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",
+	    ("--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",
@@ -738,6 +743,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 +845,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 +1058,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]);
@@ -1142,13 +1152,14 @@ main(int argc, char **argv)
 
   if (tcUrl.av_len == 0)
     {
-      char str[512] = { 0 };
-
-      tcUrl.av_len = snprintf(str, 511, "%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);
+	  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);
-      tcUrl.av_val = (char *) malloc(tcUrl.av_len + 1);
-      strcpy(tcUrl.av_val, str);
     }
 
   int first = 1;
@@ -1167,7 +1178,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))
@@ -1244,7 +1255,7 @@ main(int argc, char **argv)
 
 	  if (!RTMP_Connect(&rtmp, NULL))
 	    {
-	      nStatus = RD_FAILED;
+	      nStatus = RD_NO_CONNECT;
 	      break;
 	    }
 
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.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 10a99e8..0cf56bb 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)
@@ -562,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__);
@@ -737,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;
     }
@@ -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)
@@ -1096,7 +1101,9 @@ main(int argc, char **argv)
 	  RTMP_LogPrintf
 	    ("--token|-T key          Key for SecureToken response\n");
 	  RTMP_LogPrintf
-	    ("--buffer|-b             Buffer time in milliseconds (default: %lu)\n\n",
+	    ("--jtv|-j JSON           Authentication token for Justin.tv legacy servers\n");
+	  RTMP_LogPrintf
+	    ("--buffer|-b             Buffer time in milliseconds (default: %u)\n\n",
 	     defaultRTMPRequest.bufferTime);
 
 	  RTMP_LogPrintf
diff --git a/rtmpsrv.c b/rtmpsrv.c
index f1b6c66..b662d54 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,6 +95,10 @@ STREAMING_SERVER *rtmpServer = 0;	// server structure pointer
 
 STREAMING_SERVER *startStreaming(const char *address, int port);
 void stopStreaming(STREAMING_SERVER * server);
+void AVreplace(AVal *src, const AVal *orig, const AVal *repl);
+
+static const AVal av_dquote = AVC("\"");
+static const AVal av_escdquote = AVC("\\\"");
 
 typedef struct
 {
@@ -261,6 +265,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 +580,15 @@ ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int
     {
       SendResultNumber(r, txn, 10.0);
     }
+  else if (AVMATCH(&method, &av_NetStream_Authenticate_UsherToken))
+    {
+      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))
     {
       char *file, *p, *q, *cmd, *ptr;
@@ -640,6 +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)
+	    {
+	      argv[argc].av_val = ptr + 1;
+	      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);
@@ -740,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)
@@ -787,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);
 
@@ -815,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);
 
@@ -911,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:
@@ -1023,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;
     }
@@ -1111,3 +1141,43 @@ main(int argc, char **argv)
 #endif
   return nStatus;
 }
+
+void
+AVreplace(AVal *src, const AVal *orig, const AVal *repl)
+{
+  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)))
+    {
+      n++;
+      sptr += orig->av_len;
+    }
+  if (!n)
+    return;
+
+  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);
+      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);
+  dptr += n;
+  *dptr = '\0';
+  src->av_val = dest;
+  src->av_len = dptr - dest;
+}
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;
     }

-- 
rtmpdump packaging



More information about the pkg-multimedia-commits mailing list