1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *      Copyright (C) 2008-2009 Andrej Stepanchuk
5  *      Copyright (C) 2009-2010 Howard Chu
6  *
7  *  This file is part of librtmp.
8  *
9  *  librtmp is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU Lesser General Public License as
11  *  published by the Free Software Foundation; either version 2.1,
12  *  or (at your option) any later version.
13  *
14  *  librtmp is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public License
20  *  along with librtmp see the file COPYING.  If not, write to
21  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA  02110-1301, USA.
23  *  http://www.gnu.org/copyleft/lgpl.html
24  */
25 
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <time.h>
31 
32 #include "rtmp_sys.h"
33 #include "log.h"
34 
35 #ifdef CRYPTO
36 #ifdef USE_POLARSSL
37 #include <polarssl/havege.h>
38 #include <polarssl/md5.h>
39 #include <polarssl/base64.h>
40 #define MD5_DIGEST_LENGTH 16
41 
42 static const char *my_dhm_P =
43     "E4004C1F94182000103D883A448B3F80" \
44     "2CE4B44A83301270002C20D0321CFD00" \
45     "11CCEF784C26A400F43DFB901BCA7538" \
46     "F2C6B176001CF5A0FD16D2C48B1D0C1C" \
47     "F6AC8E1DA6BCC3B4E1F96B0564965300" \
48     "FFA1D0B601EB2800F489AA512C4B248C" \
49     "01F76949A60BB7F00A40B1EAB64BDD48" \
50     "E8A700D60B7F1200FA8E77B0A979DABF";
51 
52 static const char *my_dhm_G = "4";
53 
54 #elif defined(USE_GNUTLS)
55 #include <gnutls/gnutls.h>
56 #define MD5_DIGEST_LENGTH 16
57 #include <nettle/base64.h>
58 #include <nettle/md5.h>
59 #else	/* USE_OPENSSL */
60 #include <openssl/ssl.h>
61 #include <openssl/rc4.h>
62 #include <openssl/md5.h>
63 #include <openssl/bio.h>
64 #include <openssl/buffer.h>
65 #endif
66 TLS_CTX RTMP_TLS_ctx;
67 #endif
68 
69 #define RTMP_SIG_SIZE 1536
70 #define RTMP_LARGE_HEADER_SIZE 12
71 
72 static const int packetSize[] = { 12, 8, 4, 1 };
73 
74 int RTMP_ctrlC;
75 
76 const char RTMPProtocolStrings[][7] = {
77   "RTMP",
78   "RTMPT",
79   "RTMPE",
80   "RTMPTE",
81   "RTMPS",
82   "RTMPTS",
83   "",
84   "",
85   "RTMFP"
86 };
87 
88 const char RTMPProtocolStringsLower[][7] = {
89   "rtmp",
90   "rtmpt",
91   "rtmpe",
92   "rtmpte",
93   "rtmps",
94   "rtmpts",
95   "",
96   "",
97   "rtmfp"
98 };
99 
100 static const char *RTMPT_cmds[] = {
101   "open",
102   "send",
103   "idle",
104   "close"
105 };
106 
107 typedef enum {
108   RTMPT_OPEN=0, RTMPT_SEND, RTMPT_IDLE, RTMPT_CLOSE
109 } RTMPTCmd;
110 
111 static int DumpMetaData(AMFObject *obj);
112 static int HandShake(RTMP *r, int FP9HandShake);
113 static int SocksNegotiate(RTMP *r);
114 
115 static int SendConnectPacket(RTMP *r, RTMPPacket *cp);
116 static int SendCheckBW(RTMP *r);
117 static int SendCheckBWResult(RTMP *r, double txn);
118 static int SendDeleteStream(RTMP *r, double dStreamId);
119 static int SendFCSubscribe(RTMP *r, AVal *subscribepath);
120 static int SendPlay(RTMP *r);
121 static int SendBytesReceived(RTMP *r);
122 static int SendUsherToken(RTMP *r, AVal *usherToken);
123 
124 #if 0				/* unused */
125 static int SendBGHasStream(RTMP *r, double dId, AVal *playpath);
126 #endif
127 
128 static int HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize);
129 static int HandleMetadata(RTMP *r, char *body, unsigned int len);
130 static void HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet);
131 static void HandleAudio(RTMP *r, const RTMPPacket *packet);
132 static void HandleVideo(RTMP *r, const RTMPPacket *packet);
133 static void HandleCtrl(RTMP *r, const RTMPPacket *packet);
134 static void HandleServerBW(RTMP *r, const RTMPPacket *packet);
135 static void HandleClientBW(RTMP *r, const RTMPPacket *packet);
136 
137 static int ReadN(RTMP *r, char *buffer, int n);
138 static int WriteN(RTMP *r, const char *buffer, int n);
139 
140 static void DecodeTEA(AVal *key, AVal *text);
141 
142 static int HTTP_Post(RTMP *r, RTMPTCmd cmd, const char *buf, int len);
143 static int HTTP_read(RTMP *r, int fill);
144 
145 static void CloseInternal(RTMP *r, int reconnect);
146 
147 #ifndef _WIN32
148 static int clk_tck;
149 #endif
150 
151 #ifdef CRYPTO
152 #include "handshake.h"
153 #endif
154 
155 uint32_t
RTMP_GetTime()156 RTMP_GetTime()
157 {
158 #ifdef _DEBUG
159   return 0;
160 #elif defined(_WIN32)
161   return timeGetTime();
162 #else
163   struct tms t;
164   if (!clk_tck) clk_tck = sysconf(_SC_CLK_TCK);
165   return times(&t) * 1000 / clk_tck;
166 #endif
167 }
168 
169 void
RTMP_UserInterrupt()170 RTMP_UserInterrupt()
171 {
172   RTMP_ctrlC = TRUE;
173 }
174 
175 void
RTMPPacket_Reset(RTMPPacket * p)176 RTMPPacket_Reset(RTMPPacket *p)
177 {
178   p->m_headerType = 0;
179   p->m_packetType = 0;
180   p->m_nChannel = 0;
181   p->m_nTimeStamp = 0;
182   p->m_nInfoField2 = 0;
183   p->m_hasAbsTimestamp = FALSE;
184   p->m_nBodySize = 0;
185   p->m_nBytesRead = 0;
186 }
187 
188 int
RTMPPacket_Alloc(RTMPPacket * p,uint32_t nSize)189 RTMPPacket_Alloc(RTMPPacket *p, uint32_t nSize)
190 {
191   char *ptr;
192   if (nSize > SIZE_MAX - RTMP_MAX_HEADER_SIZE)
193     return FALSE;
194   ptr = calloc(1, nSize + RTMP_MAX_HEADER_SIZE);
195   if (!ptr)
196     return FALSE;
197   p->m_body = ptr + RTMP_MAX_HEADER_SIZE;
198   p->m_nBytesRead = 0;
199   return TRUE;
200 }
201 
202 void
RTMPPacket_Free(RTMPPacket * p)203 RTMPPacket_Free(RTMPPacket *p)
204 {
205   if (p->m_body)
206     {
207       free(p->m_body - RTMP_MAX_HEADER_SIZE);
208       p->m_body = NULL;
209     }
210 }
211 
212 void
RTMPPacket_Dump(RTMPPacket * p)213 RTMPPacket_Dump(RTMPPacket *p)
214 {
215   RTMP_Log(RTMP_LOGDEBUG,
216       "RTMP PACKET: packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %u. body: 0x%02x",
217       p->m_packetType, p->m_nChannel, p->m_nTimeStamp, p->m_nInfoField2,
218       p->m_nBodySize, p->m_body ? (unsigned char)p->m_body[0] : 0);
219 }
220 
221 int
RTMP_LibVersion()222 RTMP_LibVersion()
223 {
224   return RTMP_LIB_VERSION;
225 }
226 
227 void
RTMP_TLS_Init()228 RTMP_TLS_Init()
229 {
230 #ifdef CRYPTO
231 #ifdef USE_POLARSSL
232   /* Do this regardless of NO_SSL, we use havege for rtmpe too */
233   RTMP_TLS_ctx = calloc(1,sizeof(struct tls_ctx));
234   havege_init(&RTMP_TLS_ctx->hs);
235 #elif defined(USE_GNUTLS) && !defined(NO_SSL)
236   /* Technically we need to initialize libgcrypt ourselves if
237    * we're not going to call gnutls_global_init(). Ignoring this
238    * for now.
239    */
240   gnutls_global_init();
241   RTMP_TLS_ctx = malloc(sizeof(struct tls_ctx));
242   gnutls_certificate_allocate_credentials(&RTMP_TLS_ctx->cred);
243   gnutls_priority_init(&RTMP_TLS_ctx->prios, "NORMAL", NULL);
244   gnutls_certificate_set_x509_trust_file(RTMP_TLS_ctx->cred,
245   	"ca.pem", GNUTLS_X509_FMT_PEM);
246 #elif !defined(NO_SSL) /* USE_OPENSSL */
247   /* libcrypto doesn't need anything special */
248   SSL_load_error_strings();
249   SSL_library_init();
250   OpenSSL_add_all_digests();
251   RTMP_TLS_ctx = SSL_CTX_new(SSLv23_method());
252   SSL_CTX_set_options(RTMP_TLS_ctx, SSL_OP_ALL);
253   SSL_CTX_set_default_verify_paths(RTMP_TLS_ctx);
254 #endif
255 #endif
256 }
257 
258 void *
RTMP_TLS_AllocServerContext(const char * cert,const char * key)259 RTMP_TLS_AllocServerContext(const char* cert, const char* key)
260 {
261   void *ctx = NULL;
262 #ifdef CRYPTO
263   if (!RTMP_TLS_ctx)
264     RTMP_TLS_Init();
265 #ifdef USE_POLARSSL
266   tls_server_ctx *tc = ctx = calloc(1, sizeof(struct tls_server_ctx));
267   tc->dhm_P = my_dhm_P;
268   tc->dhm_G = my_dhm_G;
269   tc->hs = &RTMP_TLS_ctx->hs;
270   if (x509parse_crtfile(&tc->cert, cert)) {
271       free(tc);
272       return NULL;
273   }
274   if (x509parse_keyfile(&tc->key, key, NULL)) {
275       x509_free(&tc->cert);
276       free(tc);
277       return NULL;
278   }
279 #elif defined(USE_GNUTLS) && !defined(NO_SSL)
280   gnutls_certificate_allocate_credentials((gnutls_certificate_credentials*) &ctx);
281   if (gnutls_certificate_set_x509_key_file(ctx, cert, key, GNUTLS_X509_FMT_PEM) != 0) {
282     gnutls_certificate_free_credentials(ctx);
283     return NULL;
284   }
285 #elif !defined(NO_SSL) /* USE_OPENSSL */
286   ctx = SSL_CTX_new(SSLv23_server_method());
287   if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) {
288       SSL_CTX_free(ctx);
289       return NULL;
290   }
291   if (!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
292       SSL_CTX_free(ctx);
293       return NULL;
294   }
295 #endif
296 #endif
297   return ctx;
298 }
299 
300 void
RTMP_TLS_FreeServerContext(void * ctx)301 RTMP_TLS_FreeServerContext(void *ctx)
302 {
303 #ifdef CRYPTO
304 #ifdef USE_POLARSSL
305   x509_free(&((tls_server_ctx*)ctx)->cert);
306   rsa_free(&((tls_server_ctx*)ctx)->key);
307   free(ctx);
308 #elif defined(USE_GNUTLS) && !defined(NO_SSL)
309   gnutls_certificate_free_credentials(ctx);
310 #elif !defined(NO_SSL) /* USE_OPENSSL */
311   SSL_CTX_free(ctx);
312 #endif
313 #endif
314 }
315 
316 RTMP *
RTMP_Alloc()317 RTMP_Alloc()
318 {
319   return calloc(1, sizeof(RTMP));
320 }
321 
322 void
RTMP_Free(RTMP * r)323 RTMP_Free(RTMP *r)
324 {
325   free(r);
326 }
327 
328 void
RTMP_Init(RTMP * r)329 RTMP_Init(RTMP *r)
330 {
331 #ifdef CRYPTO
332   if (!RTMP_TLS_ctx)
333     RTMP_TLS_Init();
334 #endif
335 
336   memset(r, 0, sizeof(RTMP));
337   r->m_sb.sb_socket = -1;
338   r->m_inChunkSize = RTMP_DEFAULT_CHUNKSIZE;
339   r->m_outChunkSize = RTMP_DEFAULT_CHUNKSIZE;
340   r->m_nBufferMS = 30000;
341   r->m_nClientBW = 2500000;
342   r->m_nClientBW2 = 2;
343   r->m_nServerBW = 2500000;
344   r->m_fAudioCodecs = 3191.0;
345   r->m_fVideoCodecs = 252.0;
346   r->Link.timeout = 30;
347   r->Link.swfAge = 30;
348 }
349 
350 void
RTMP_EnableWrite(RTMP * r)351 RTMP_EnableWrite(RTMP *r)
352 {
353   r->Link.protocol |= RTMP_FEATURE_WRITE;
354 }
355 
356 double
RTMP_GetDuration(RTMP * r)357 RTMP_GetDuration(RTMP *r)
358 {
359   return r->m_fDuration;
360 }
361 
362 int
RTMP_IsConnected(RTMP * r)363 RTMP_IsConnected(RTMP *r)
364 {
365   return r->m_sb.sb_socket != -1;
366 }
367 
368 int
RTMP_Socket(RTMP * r)369 RTMP_Socket(RTMP *r)
370 {
371   return r->m_sb.sb_socket;
372 }
373 
374 int
RTMP_IsTimedout(RTMP * r)375 RTMP_IsTimedout(RTMP *r)
376 {
377   return r->m_sb.sb_timedout;
378 }
379 
380 void
RTMP_SetBufferMS(RTMP * r,int size)381 RTMP_SetBufferMS(RTMP *r, int size)
382 {
383   r->m_nBufferMS = size;
384 }
385 
386 void
RTMP_UpdateBufferMS(RTMP * r)387 RTMP_UpdateBufferMS(RTMP *r)
388 {
389   RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
390 }
391 
392 #undef OSS
393 #ifdef _WIN32
394 #define OSS	"WIN"
395 #elif defined(__sun__)
396 #define OSS	"SOL"
397 #elif defined(__APPLE__)
398 #define OSS	"MAC"
399 #elif defined(__linux__)
400 #define OSS	"LNX"
401 #else
402 #define OSS	"GNU"
403 #endif
404 #define DEF_VERSTR	OSS " 10,0,32,18"
405 static const char DEFAULT_FLASH_VER[] = DEF_VERSTR;
406 const AVal RTMP_DefaultFlashVer =
407   { (char *)DEFAULT_FLASH_VER, sizeof(DEFAULT_FLASH_VER) - 1 };
408 
409 static void
SocksSetup(RTMP * r,AVal * sockshost)410 SocksSetup(RTMP *r, AVal *sockshost)
411 {
412   if (sockshost->av_len)
413     {
414       const char *socksport = strchr(sockshost->av_val, ':');
415       char *hostname = strdup(sockshost->av_val);
416 
417       if (socksport)
418 	hostname[socksport - sockshost->av_val] = '\0';
419       r->Link.sockshost.av_val = hostname;
420       r->Link.sockshost.av_len = strlen(hostname);
421 
422       r->Link.socksport = socksport ? atoi(socksport + 1) : 1080;
423       RTMP_Log(RTMP_LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", r->Link.sockshost.av_val,
424 	  r->Link.socksport);
425     }
426   else
427     {
428       r->Link.sockshost.av_val = NULL;
429       r->Link.sockshost.av_len = 0;
430       r->Link.socksport = 0;
431     }
432 }
433 
434 void
RTMP_SetupStream(RTMP * r,int protocol,AVal * host,unsigned int port,AVal * sockshost,AVal * playpath,AVal * tcUrl,AVal * swfUrl,AVal * pageUrl,AVal * app,AVal * auth,AVal * swfSHA256Hash,uint32_t swfSize,AVal * flashVer,AVal * subscribepath,AVal * usherToken,int dStart,int dStop,int bLiveStream,long int timeout)435 RTMP_SetupStream(RTMP *r,
436 		 int protocol,
437 		 AVal *host,
438 		 unsigned int port,
439 		 AVal *sockshost,
440 		 AVal *playpath,
441 		 AVal *tcUrl,
442 		 AVal *swfUrl,
443 		 AVal *pageUrl,
444 		 AVal *app,
445 		 AVal *auth,
446 		 AVal *swfSHA256Hash,
447 		 uint32_t swfSize,
448 		 AVal *flashVer,
449 		 AVal *subscribepath,
450 		 AVal *usherToken,
451 		 int dStart,
452 		 int dStop, int bLiveStream, long int timeout)
453 {
454   RTMP_Log(RTMP_LOGDEBUG, "Protocol : %s", RTMPProtocolStrings[protocol&7]);
455   RTMP_Log(RTMP_LOGDEBUG, "Hostname : %.*s", host->av_len, host->av_val);
456   RTMP_Log(RTMP_LOGDEBUG, "Port     : %d", port);
457   RTMP_Log(RTMP_LOGDEBUG, "Playpath : %s", playpath->av_val);
458 
459   if (tcUrl && tcUrl->av_val)
460     RTMP_Log(RTMP_LOGDEBUG, "tcUrl    : %s", tcUrl->av_val);
461   if (swfUrl && swfUrl->av_val)
462     RTMP_Log(RTMP_LOGDEBUG, "swfUrl   : %s", swfUrl->av_val);
463   if (pageUrl && pageUrl->av_val)
464     RTMP_Log(RTMP_LOGDEBUG, "pageUrl  : %s", pageUrl->av_val);
465   if (app && app->av_val)
466     RTMP_Log(RTMP_LOGDEBUG, "app      : %.*s", app->av_len, app->av_val);
467   if (auth && auth->av_val)
468     RTMP_Log(RTMP_LOGDEBUG, "auth     : %s", auth->av_val);
469   if (subscribepath && subscribepath->av_val)
470     RTMP_Log(RTMP_LOGDEBUG, "subscribepath : %s", subscribepath->av_val);
471   if (usherToken && usherToken->av_val)
472     RTMP_Log(RTMP_LOGDEBUG, "NetStream.Authenticate.UsherToken : %s", usherToken->av_val);
473   if (flashVer && flashVer->av_val)
474     RTMP_Log(RTMP_LOGDEBUG, "flashVer : %s", flashVer->av_val);
475   if (dStart > 0)
476     RTMP_Log(RTMP_LOGDEBUG, "StartTime     : %d msec", dStart);
477   if (dStop > 0)
478     RTMP_Log(RTMP_LOGDEBUG, "StopTime      : %d msec", dStop);
479 
480   RTMP_Log(RTMP_LOGDEBUG, "live     : %s", bLiveStream ? "yes" : "no");
481   RTMP_Log(RTMP_LOGDEBUG, "timeout  : %ld sec", timeout);
482 
483 #ifdef CRYPTO
484   if (swfSHA256Hash != NULL && swfSize > 0)
485     {
486       memcpy(r->Link.SWFHash, swfSHA256Hash->av_val, sizeof(r->Link.SWFHash));
487       r->Link.SWFSize = swfSize;
488       RTMP_Log(RTMP_LOGDEBUG, "SWFSHA256:");
489       RTMP_LogHex(RTMP_LOGDEBUG, r->Link.SWFHash, sizeof(r->Link.SWFHash));
490       RTMP_Log(RTMP_LOGDEBUG, "SWFSize  : %u", r->Link.SWFSize);
491     }
492   else
493     {
494       r->Link.SWFSize = 0;
495     }
496 #endif
497 
498   SocksSetup(r, sockshost);
499 
500   if (tcUrl && tcUrl->av_len)
501     r->Link.tcUrl = *tcUrl;
502   if (swfUrl && swfUrl->av_len)
503     r->Link.swfUrl = *swfUrl;
504   if (pageUrl && pageUrl->av_len)
505     r->Link.pageUrl = *pageUrl;
506   if (app && app->av_len)
507     r->Link.app = *app;
508   if (auth && auth->av_len)
509     {
510       r->Link.auth = *auth;
511       r->Link.lFlags |= RTMP_LF_AUTH;
512     }
513   if (flashVer && flashVer->av_len)
514     r->Link.flashVer = *flashVer;
515   else
516     r->Link.flashVer = RTMP_DefaultFlashVer;
517   if (subscribepath && subscribepath->av_len)
518     r->Link.subscribepath = *subscribepath;
519   if (usherToken && usherToken->av_len)
520     r->Link.usherToken = *usherToken;
521   r->Link.seekTime = dStart;
522   r->Link.stopTime = dStop;
523   if (bLiveStream)
524     r->Link.lFlags |= RTMP_LF_LIVE;
525   r->Link.timeout = timeout;
526 
527   r->Link.protocol = protocol;
528   r->Link.hostname = *host;
529   r->Link.port = port;
530   r->Link.playpath = *playpath;
531 
532   if (r->Link.port == 0)
533     {
534       if (protocol & RTMP_FEATURE_SSL)
535 	r->Link.port = 443;
536       else if (protocol & RTMP_FEATURE_HTTP)
537 	r->Link.port = 80;
538       else
539 	r->Link.port = 1935;
540     }
541 }
542 
543 enum { OPT_STR=0, OPT_INT, OPT_BOOL, OPT_CONN };
544 static const char *optinfo[] = {
545 	"string", "integer", "boolean", "AMF" };
546 
547 #define OFF(x)	offsetof(struct RTMP,x)
548 
549 static struct urlopt {
550   AVal name;
551   off_t off;
552   int otype;
553   int omisc;
554   char *use;
555 } options[] = {
556   { AVC("socks"),     OFF(Link.sockshost),     OPT_STR, 0,
557   	"Use the specified SOCKS proxy" },
558   { AVC("app"),       OFF(Link.app),           OPT_STR, 0,
559 	"Name of target app on server" },
560   { AVC("tcUrl"),     OFF(Link.tcUrl),         OPT_STR, 0,
561   	"URL to played stream" },
562   { AVC("pageUrl"),   OFF(Link.pageUrl),       OPT_STR, 0,
563   	"URL of played media's web page" },
564   { AVC("swfUrl"),    OFF(Link.swfUrl),        OPT_STR, 0,
565   	"URL to player SWF file" },
566   { AVC("flashver"),  OFF(Link.flashVer),      OPT_STR, 0,
567   	"Flash version string (default " DEF_VERSTR ")" },
568   { AVC("conn"),      OFF(Link.extras),        OPT_CONN, 0,
569   	"Append arbitrary AMF data to Connect message" },
570   { AVC("playpath"),  OFF(Link.playpath),      OPT_STR, 0,
571   	"Path to target media on server" },
572   { AVC("playlist"),  OFF(Link.lFlags),        OPT_BOOL, RTMP_LF_PLST,
573   	"Set playlist before play command" },
574   { AVC("live"),      OFF(Link.lFlags),        OPT_BOOL, RTMP_LF_LIVE,
575   	"Stream is live, no seeking possible" },
576   { AVC("subscribe"), OFF(Link.subscribepath), OPT_STR, 0,
577   	"Stream to subscribe to" },
578   { AVC("jtv"), OFF(Link.usherToken),          OPT_STR, 0,
579 	"Justin.tv authentication token" },
580   { AVC("token"),     OFF(Link.token),	       OPT_STR, 0,
581   	"Key for SecureToken response" },
582   { AVC("swfVfy"),    OFF(Link.lFlags),        OPT_BOOL, RTMP_LF_SWFV,
583   	"Perform SWF Verification" },
584   { AVC("swfAge"),    OFF(Link.swfAge),        OPT_INT, 0,
585   	"Number of days to use cached SWF hash" },
586   { AVC("start"),     OFF(Link.seekTime),      OPT_INT, 0,
587   	"Stream start position in milliseconds" },
588   { AVC("stop"),      OFF(Link.stopTime),      OPT_INT, 0,
589   	"Stream stop position in milliseconds" },
590   { AVC("buffer"),    OFF(m_nBufferMS),        OPT_INT, 0,
591   	"Buffer time in milliseconds" },
592   { AVC("timeout"),   OFF(Link.timeout),       OPT_INT, 0,
593   	"Session timeout in seconds" },
594   { AVC("pubUser"),   OFF(Link.pubUser),       OPT_STR, 0,
595         "Publisher username" },
596   { AVC("pubPasswd"), OFF(Link.pubPasswd),     OPT_STR, 0,
597         "Publisher password" },
598   { {NULL,0}, 0, 0}
599 };
600 
601 static const AVal truth[] = {
602 	AVC("1"),
603 	AVC("on"),
604 	AVC("yes"),
605 	AVC("true"),
606 	{0,0}
607 };
608 
RTMP_OptUsage()609 static void RTMP_OptUsage()
610 {
611   int i;
612 
613   RTMP_Log(RTMP_LOGERROR, "Valid RTMP options are:\n");
614   for (i=0; options[i].name.av_len; i++) {
615     RTMP_Log(RTMP_LOGERROR, "%10s %-7s  %s\n", options[i].name.av_val,
616     	optinfo[options[i].otype], options[i].use);
617   }
618 }
619 
620 static int
parseAMF(AMFObject * obj,AVal * av,int * depth)621 parseAMF(AMFObject *obj, AVal *av, int *depth)
622 {
623   AMFObjectProperty prop = {{0,0}};
624   int i;
625   char *p, *arg = av->av_val;
626 
627   if (arg[1] == ':')
628     {
629       p = (char *)arg+2;
630       switch(arg[0])
631 	{
632 	case 'B':
633 	  prop.p_type = AMF_BOOLEAN;
634 	  prop.p_vu.p_number = atoi(p);
635 	  break;
636 	case 'S':
637 	  prop.p_type = AMF_STRING;
638 	  prop.p_vu.p_aval.av_val = p;
639 	  prop.p_vu.p_aval.av_len = av->av_len - (p-arg);
640 	  break;
641 	case 'N':
642 	  prop.p_type = AMF_NUMBER;
643 	  prop.p_vu.p_number = strtod(p, NULL);
644 	  break;
645 	case 'Z':
646 	  prop.p_type = AMF_NULL;
647 	  break;
648 	case 'O':
649 	  i = atoi(p);
650 	  if (i)
651 	    {
652 	      prop.p_type = AMF_OBJECT;
653 	    }
654 	  else
655 	    {
656 	      (*depth)--;
657 	      return 0;
658 	    }
659 	  break;
660 	default:
661 	  return -1;
662 	}
663     }
664   else if (arg[2] == ':' && arg[0] == 'N')
665     {
666       p = strchr(arg+3, ':');
667       if (!p || !*depth)
668 	return -1;
669       prop.p_name.av_val = (char *)arg+3;
670       prop.p_name.av_len = p - (arg+3);
671 
672       p++;
673       switch(arg[1])
674 	{
675 	case 'B':
676 	  prop.p_type = AMF_BOOLEAN;
677 	  prop.p_vu.p_number = atoi(p);
678 	  break;
679 	case 'S':
680 	  prop.p_type = AMF_STRING;
681 	  prop.p_vu.p_aval.av_val = p;
682 	  prop.p_vu.p_aval.av_len = av->av_len - (p-arg);
683 	  break;
684 	case 'N':
685 	  prop.p_type = AMF_NUMBER;
686 	  prop.p_vu.p_number = strtod(p, NULL);
687 	  break;
688 	case 'O':
689 	  prop.p_type = AMF_OBJECT;
690 	  break;
691 	default:
692 	  return -1;
693 	}
694     }
695   else
696     return -1;
697 
698   if (*depth)
699     {
700       AMFObject *o2;
701       for (i=0; i<*depth; i++)
702 	{
703 	  o2 = &obj->o_props[obj->o_num-1].p_vu.p_object;
704 	  obj = o2;
705 	}
706     }
707   AMF_AddProp(obj, &prop);
708   if (prop.p_type == AMF_OBJECT)
709     (*depth)++;
710   return 0;
711 }
712 
RTMP_SetOpt(RTMP * r,const AVal * opt,AVal * arg)713 int RTMP_SetOpt(RTMP *r, const AVal *opt, AVal *arg)
714 {
715   int i;
716   void *v;
717 
718   for (i=0; options[i].name.av_len; i++) {
719     if (opt->av_len != options[i].name.av_len) continue;
720     if (strcasecmp(opt->av_val, options[i].name.av_val)) continue;
721     v = (char *)r + options[i].off;
722     switch(options[i].otype) {
723     case OPT_STR: {
724       AVal *aptr = v;
725       *aptr = *arg; }
726       break;
727     case OPT_INT: {
728       long l = strtol(arg->av_val, NULL, 0);
729       *(int *)v = l; }
730       break;
731     case OPT_BOOL: {
732       int j, fl;
733       fl = *(int *)v;
734       for (j=0; truth[j].av_len; j++) {
735         if (arg->av_len != truth[j].av_len) continue;
736         if (strcasecmp(arg->av_val, truth[j].av_val)) continue;
737         fl |= options[i].omisc; break; }
738       *(int *)v = fl;
739       }
740       break;
741     case OPT_CONN:
742       if (parseAMF(&r->Link.extras, arg, &r->Link.edepth))
743         return FALSE;
744       break;
745     }
746     break;
747   }
748   if (!options[i].name.av_len) {
749     RTMP_Log(RTMP_LOGERROR, "Unknown option %s", opt->av_val);
750     RTMP_OptUsage();
751     return FALSE;
752   }
753 
754   return TRUE;
755 }
756 
RTMP_SetupURL(RTMP * r,char * url)757 int RTMP_SetupURL(RTMP *r, char *url)
758 {
759   AVal opt, arg;
760   char *p1, *p2, *ptr = strchr(url, ' ');
761   int ret, len;
762   unsigned int port = 0;
763 
764   if (ptr)
765     *ptr = '\0';
766 
767   len = strlen(url);
768   ret = RTMP_ParseURL(url, &r->Link.protocol, &r->Link.hostname,
769   	&port, &r->Link.playpath0, &r->Link.app);
770   if (!ret)
771     return ret;
772   r->Link.port = port;
773   r->Link.playpath = r->Link.playpath0;
774 
775   while (ptr) {
776     *ptr++ = '\0';
777     p1 = ptr;
778     p2 = strchr(p1, '=');
779     if (!p2)
780       break;
781     opt.av_val = p1;
782     opt.av_len = p2 - p1;
783     *p2++ = '\0';
784     arg.av_val = p2;
785     ptr = strchr(p2, ' ');
786     if (ptr) {
787       *ptr = '\0';
788       arg.av_len = ptr - p2;
789       /* skip repeated spaces */
790       while(ptr[1] == ' ')
791       	*ptr++ = '\0';
792     } else {
793       arg.av_len = strlen(p2);
794     }
795 
796     /* unescape */
797     port = arg.av_len;
798     for (p1=p2; port >0;) {
799       if (*p1 == '\\') {
800 	unsigned int c;
801 	if (port < 3)
802 	  return FALSE;
803 	sscanf(p1+1, "%02x", &c);
804 	*p2++ = c;
805 	port -= 3;
806 	p1 += 3;
807       } else {
808 	*p2++ = *p1++;
809 	port--;
810       }
811     }
812     arg.av_len = p2 - arg.av_val;
813 
814     ret = RTMP_SetOpt(r, &opt, &arg);
815     if (!ret)
816       return ret;
817   }
818 
819   if (!r->Link.tcUrl.av_len)
820     {
821       r->Link.tcUrl.av_val = url;
822       if (r->Link.app.av_len)
823         {
824           if (r->Link.app.av_val < url + len)
825     	    {
826     	      /* if app is part of original url, just use it */
827               r->Link.tcUrl.av_len = r->Link.app.av_len + (r->Link.app.av_val - url);
828     	    }
829     	  else
830     	    {
831     	      len = r->Link.hostname.av_len + r->Link.app.av_len +
832     		  sizeof("rtmpte://:65535/");
833 	      r->Link.tcUrl.av_val = malloc(len);
834 	      r->Link.tcUrl.av_len = snprintf(r->Link.tcUrl.av_val, len,
835 		"%s://%.*s:%d/%.*s",
836 		RTMPProtocolStringsLower[r->Link.protocol],
837 		r->Link.hostname.av_len, r->Link.hostname.av_val,
838 		r->Link.port,
839 		r->Link.app.av_len, r->Link.app.av_val);
840 	      r->Link.lFlags |= RTMP_LF_FTCU;
841 	    }
842         }
843       else
844         {
845 	  r->Link.tcUrl.av_len = strlen(url);
846 	}
847     }
848 
849 #ifdef CRYPTO
850   if ((r->Link.lFlags & RTMP_LF_SWFV) && r->Link.swfUrl.av_len)
851     RTMP_HashSWF(r->Link.swfUrl.av_val, &r->Link.SWFSize,
852 	  (unsigned char *)r->Link.SWFHash, r->Link.swfAge);
853 #endif
854 
855   SocksSetup(r, &r->Link.sockshost);
856 
857   if (r->Link.port == 0)
858     {
859       if (r->Link.protocol & RTMP_FEATURE_SSL)
860 	r->Link.port = 443;
861       else if (r->Link.protocol & RTMP_FEATURE_HTTP)
862 	r->Link.port = 80;
863       else
864 	r->Link.port = 1935;
865     }
866   return TRUE;
867 }
868 
869 static int
add_addr_info(struct sockaddr_in * service,AVal * host,int port)870 add_addr_info(struct sockaddr_in *service, AVal *host, int port)
871 {
872   char *hostname;
873   int ret = TRUE;
874   if (host->av_val[host->av_len])
875     {
876       hostname = malloc(host->av_len+1);
877       memcpy(hostname, host->av_val, host->av_len);
878       hostname[host->av_len] = '\0';
879     }
880   else
881     {
882       hostname = host->av_val;
883     }
884 
885   service->sin_addr.s_addr = inet_addr(hostname);
886   if (service->sin_addr.s_addr == INADDR_NONE)
887     {
888       struct hostent *host = gethostbyname(hostname);
889       if (host == NULL || host->h_addr == NULL)
890 	{
891 	  RTMP_Log(RTMP_LOGERROR, "Problem accessing the DNS. (addr: %s)", hostname);
892 	  ret = FALSE;
893 	  goto finish;
894 	}
895       service->sin_addr = *(struct in_addr *)host->h_addr;
896     }
897 
898   service->sin_port = htons(port);
899 finish:
900   if (hostname != host->av_val)
901     free(hostname);
902   return ret;
903 }
904 
905 int
RTMP_Connect0(RTMP * r,struct sockaddr * service)906 RTMP_Connect0(RTMP *r, struct sockaddr * service)
907 {
908   int on = 1;
909   r->m_sb.sb_timedout = FALSE;
910   r->m_pausing = 0;
911   r->m_fDuration = 0.0;
912 
913   r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
914   if (r->m_sb.sb_socket != -1)
915     {
916       if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0)
917 	{
918 	  int err = GetSockError();
919 	  RTMP_Log(RTMP_LOGERROR, "%s, failed to connect socket. %d (%s)",
920 	      __FUNCTION__, err, strerror(err));
921 	  RTMP_Close(r);
922 	  return FALSE;
923 	}
924 
925       if (r->Link.socksport)
926 	{
927 	  RTMP_Log(RTMP_LOGDEBUG, "%s ... SOCKS negotiation", __FUNCTION__);
928 	  if (!SocksNegotiate(r))
929 	    {
930 	      RTMP_Log(RTMP_LOGERROR, "%s, SOCKS negotiation failed.", __FUNCTION__);
931 	      RTMP_Close(r);
932 	      return FALSE;
933 	    }
934 	}
935     }
936   else
937     {
938       RTMP_Log(RTMP_LOGERROR, "%s, failed to create socket. Error: %d", __FUNCTION__,
939 	  GetSockError());
940       return FALSE;
941     }
942 
943   /* set timeout */
944   {
945     SET_RCVTIMEO(tv, r->Link.timeout);
946     if (setsockopt
947         (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
948       {
949         RTMP_Log(RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!",
950 	    __FUNCTION__, r->Link.timeout);
951       }
952   }
953 
954   setsockopt(r->m_sb.sb_socket, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on));
955 
956   return TRUE;
957 }
958 
959 int
RTMP_TLS_Accept(RTMP * r,void * ctx)960 RTMP_TLS_Accept(RTMP *r, void *ctx)
961 {
962 #if defined(CRYPTO) && !defined(NO_SSL)
963   TLS_server(ctx, r->m_sb.sb_ssl);
964   TLS_setfd(r->m_sb.sb_ssl, r->m_sb.sb_socket);
965   if (TLS_accept(r->m_sb.sb_ssl) < 0)
966     {
967       RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__);
968       return FALSE;
969     }
970   return TRUE;
971 #else
972   return FALSE;
973 #endif
974 }
975 
976 int
RTMP_Connect1(RTMP * r,RTMPPacket * cp)977 RTMP_Connect1(RTMP *r, RTMPPacket *cp)
978 {
979   if (r->Link.protocol & RTMP_FEATURE_SSL)
980     {
981 #if defined(CRYPTO) && !defined(NO_SSL)
982       TLS_client(RTMP_TLS_ctx, r->m_sb.sb_ssl);
983       TLS_setfd(r->m_sb.sb_ssl, r->m_sb.sb_socket);
984       if (TLS_connect(r->m_sb.sb_ssl) < 0)
985 	{
986 	  RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__);
987 	  RTMP_Close(r);
988 	  return FALSE;
989 	}
990 #else
991       RTMP_Log(RTMP_LOGERROR, "%s, no SSL/TLS support", __FUNCTION__);
992       RTMP_Close(r);
993       return FALSE;
994 
995 #endif
996     }
997   if (r->Link.protocol & RTMP_FEATURE_HTTP)
998     {
999       r->m_msgCounter = 1;
1000       r->m_clientID.av_val = NULL;
1001       r->m_clientID.av_len = 0;
1002       HTTP_Post(r, RTMPT_OPEN, "", 1);
1003       if (HTTP_read(r, 1) != 0)
1004 	{
1005 	  r->m_msgCounter = 0;
1006 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Could not connect for handshake", __FUNCTION__);
1007 	  RTMP_Close(r);
1008 	  return 0;
1009 	}
1010       r->m_msgCounter = 0;
1011     }
1012   RTMP_Log(RTMP_LOGDEBUG, "%s, ... connected, handshaking", __FUNCTION__);
1013   if (!HandShake(r, TRUE))
1014     {
1015       RTMP_Log(RTMP_LOGERROR, "%s, handshake failed.", __FUNCTION__);
1016       RTMP_Close(r);
1017       return FALSE;
1018     }
1019   RTMP_Log(RTMP_LOGDEBUG, "%s, handshaked", __FUNCTION__);
1020 
1021   if (!SendConnectPacket(r, cp))
1022     {
1023       RTMP_Log(RTMP_LOGERROR, "%s, RTMP connect failed.", __FUNCTION__);
1024       RTMP_Close(r);
1025       return FALSE;
1026     }
1027   return TRUE;
1028 }
1029 
1030 int
RTMP_Connect(RTMP * r,RTMPPacket * cp)1031 RTMP_Connect(RTMP *r, RTMPPacket *cp)
1032 {
1033   struct sockaddr_in service;
1034   if (!r->Link.hostname.av_len)
1035     return FALSE;
1036 
1037   memset(&service, 0, sizeof(struct sockaddr_in));
1038   service.sin_family = AF_INET;
1039 
1040   if (r->Link.socksport)
1041     {
1042       /* Connect via SOCKS */
1043       if (!add_addr_info(&service, &r->Link.sockshost, r->Link.socksport))
1044 	return FALSE;
1045     }
1046   else
1047     {
1048       /* Connect directly */
1049       if (!add_addr_info(&service, &r->Link.hostname, r->Link.port))
1050 	return FALSE;
1051     }
1052 
1053   if (!RTMP_Connect0(r, (struct sockaddr *)&service))
1054     return FALSE;
1055 
1056   r->m_bSendCounter = TRUE;
1057 
1058   return RTMP_Connect1(r, cp);
1059 }
1060 
1061 static int
SocksNegotiate(RTMP * r)1062 SocksNegotiate(RTMP *r)
1063 {
1064   unsigned long addr;
1065   struct sockaddr_in service;
1066   memset(&service, 0, sizeof(struct sockaddr_in));
1067 
1068   add_addr_info(&service, &r->Link.hostname, r->Link.port);
1069   addr = htonl(service.sin_addr.s_addr);
1070 
1071   {
1072     char packet[] = {
1073       4, 1,			/* SOCKS 4, connect */
1074       (r->Link.port >> 8) & 0xFF,
1075       (r->Link.port) & 0xFF,
1076       (char)(addr >> 24) & 0xFF, (char)(addr >> 16) & 0xFF,
1077       (char)(addr >> 8) & 0xFF, (char)addr & 0xFF,
1078       0
1079     };				/* NULL terminate */
1080 
1081     WriteN(r, packet, sizeof packet);
1082 
1083     if (ReadN(r, packet, 8) != 8)
1084       return FALSE;
1085 
1086     if (packet[0] == 0 && packet[1] == 90)
1087       {
1088         return TRUE;
1089       }
1090     else
1091       {
1092         RTMP_Log(RTMP_LOGERROR, "%s, SOCKS returned error code %d", __FUNCTION__, packet[1]);
1093         return FALSE;
1094       }
1095   }
1096 }
1097 
1098 int
RTMP_ConnectStream(RTMP * r,int seekTime)1099 RTMP_ConnectStream(RTMP *r, int seekTime)
1100 {
1101   RTMPPacket packet = { 0 };
1102 
1103   /* seekTime was already set by SetupStream / SetupURL.
1104    * This is only needed by ReconnectStream.
1105    */
1106   if (seekTime > 0)
1107     r->Link.seekTime = seekTime;
1108 
1109   r->m_mediaChannel = 0;
1110 
1111   while (!r->m_bPlaying && RTMP_IsConnected(r) && RTMP_ReadPacket(r, &packet))
1112     {
1113       if (RTMPPacket_IsReady(&packet))
1114 	{
1115 	  if (!packet.m_nBodySize)
1116 	    continue;
1117 	  if ((packet.m_packetType == RTMP_PACKET_TYPE_AUDIO) ||
1118 	      (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO) ||
1119 	      (packet.m_packetType == RTMP_PACKET_TYPE_INFO))
1120 	    {
1121 	      RTMP_Log(RTMP_LOGWARNING, "Received FLV packet before play()! Ignoring.");
1122 	      RTMPPacket_Free(&packet);
1123 	      continue;
1124 	    }
1125 
1126 	  RTMP_ClientPacket(r, &packet);
1127 	  RTMPPacket_Free(&packet);
1128 	}
1129     }
1130 
1131   return r->m_bPlaying;
1132 }
1133 
1134 int
RTMP_ReconnectStream(RTMP * r,int seekTime)1135 RTMP_ReconnectStream(RTMP *r, int seekTime)
1136 {
1137   RTMP_DeleteStream(r);
1138 
1139   RTMP_SendCreateStream(r);
1140 
1141   return RTMP_ConnectStream(r, seekTime);
1142 }
1143 
1144 int
RTMP_ToggleStream(RTMP * r)1145 RTMP_ToggleStream(RTMP *r)
1146 {
1147   int res;
1148 
1149   if (!r->m_pausing)
1150     {
1151       if (RTMP_IsTimedout(r) && r->m_read.status == RTMP_READ_EOF)
1152         r->m_read.status = 0;
1153 
1154       res = RTMP_SendPause(r, TRUE, r->m_pauseStamp);
1155       if (!res)
1156 	return res;
1157 
1158       r->m_pausing = 1;
1159       sleep(1);
1160     }
1161   res = RTMP_SendPause(r, FALSE, r->m_pauseStamp);
1162   r->m_pausing = 3;
1163   return res;
1164 }
1165 
1166 void
RTMP_DeleteStream(RTMP * r)1167 RTMP_DeleteStream(RTMP *r)
1168 {
1169   if (r->m_stream_id < 0)
1170     return;
1171 
1172   r->m_bPlaying = FALSE;
1173 
1174   SendDeleteStream(r, r->m_stream_id);
1175   r->m_stream_id = -1;
1176 }
1177 
1178 int
RTMP_GetNextMediaPacket(RTMP * r,RTMPPacket * packet)1179 RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet)
1180 {
1181   int bHasMediaPacket = 0;
1182 
1183   while (!bHasMediaPacket && RTMP_IsConnected(r)
1184 	 && RTMP_ReadPacket(r, packet))
1185     {
1186       if (!RTMPPacket_IsReady(packet) || !packet->m_nBodySize)
1187 	{
1188 	  continue;
1189 	}
1190 
1191       bHasMediaPacket = RTMP_ClientPacket(r, packet);
1192 
1193       if (!bHasMediaPacket)
1194 	{
1195 	  RTMPPacket_Free(packet);
1196 	}
1197       else if (r->m_pausing == 3)
1198 	{
1199 	  if (packet->m_nTimeStamp <= r->m_mediaStamp)
1200 	    {
1201 	      bHasMediaPacket = 0;
1202 #ifdef _DEBUG
1203 	      RTMP_Log(RTMP_LOGDEBUG,
1204 		  "Skipped type: %02X, size: %d, TS: %d ms, abs TS: %d, pause: %d ms",
1205 		  packet->m_packetType, packet->m_nBodySize,
1206 		  packet->m_nTimeStamp, packet->m_hasAbsTimestamp,
1207 		  r->m_mediaStamp);
1208 #endif
1209 	      RTMPPacket_Free(packet);
1210 	      continue;
1211 	    }
1212 	  r->m_pausing = 0;
1213 	}
1214     }
1215 
1216   if (bHasMediaPacket)
1217     r->m_bPlaying = TRUE;
1218   else if (r->m_sb.sb_timedout && !r->m_pausing)
1219     r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
1220                       r->m_channelTimestamp[r->m_mediaChannel] : 0;
1221 
1222   return bHasMediaPacket;
1223 }
1224 
1225 int
RTMP_ClientPacket(RTMP * r,RTMPPacket * packet)1226 RTMP_ClientPacket(RTMP *r, RTMPPacket *packet)
1227 {
1228   int bHasMediaPacket = 0;
1229   switch (packet->m_packetType)
1230     {
1231     case RTMP_PACKET_TYPE_CHUNK_SIZE:
1232       /* chunk size */
1233       HandleChangeChunkSize(r, packet);
1234       break;
1235 
1236     case RTMP_PACKET_TYPE_BYTES_READ_REPORT:
1237       /* bytes read report */
1238       RTMP_Log(RTMP_LOGDEBUG, "%s, received: bytes read report", __FUNCTION__);
1239       break;
1240 
1241     case RTMP_PACKET_TYPE_CONTROL:
1242       /* ctrl */
1243       HandleCtrl(r, packet);
1244       break;
1245 
1246     case RTMP_PACKET_TYPE_SERVER_BW:
1247       /* server bw */
1248       HandleServerBW(r, packet);
1249       break;
1250 
1251     case RTMP_PACKET_TYPE_CLIENT_BW:
1252       /* client bw */
1253       HandleClientBW(r, packet);
1254       break;
1255 
1256     case RTMP_PACKET_TYPE_AUDIO:
1257       /* audio data */
1258       /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize); */
1259       HandleAudio(r, packet);
1260       bHasMediaPacket = 1;
1261       if (!r->m_mediaChannel)
1262 	r->m_mediaChannel = packet->m_nChannel;
1263       if (!r->m_pausing)
1264 	r->m_mediaStamp = packet->m_nTimeStamp;
1265       break;
1266 
1267     case RTMP_PACKET_TYPE_VIDEO:
1268       /* video data */
1269       /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize); */
1270       HandleVideo(r, packet);
1271       bHasMediaPacket = 1;
1272       if (!r->m_mediaChannel)
1273 	r->m_mediaChannel = packet->m_nChannel;
1274       if (!r->m_pausing)
1275 	r->m_mediaStamp = packet->m_nTimeStamp;
1276       break;
1277 
1278     case RTMP_PACKET_TYPE_FLEX_STREAM_SEND:
1279       /* flex stream send */
1280       RTMP_Log(RTMP_LOGDEBUG,
1281 	  "%s, flex stream send, size %u bytes, not supported, ignoring",
1282 	  __FUNCTION__, packet->m_nBodySize);
1283       break;
1284 
1285     case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT:
1286       /* flex shared object */
1287       RTMP_Log(RTMP_LOGDEBUG,
1288 	  "%s, flex shared object, size %u bytes, not supported, ignoring",
1289 	  __FUNCTION__, packet->m_nBodySize);
1290       break;
1291 
1292     case RTMP_PACKET_TYPE_FLEX_MESSAGE:
1293       /* flex message */
1294       {
1295 	RTMP_Log(RTMP_LOGDEBUG,
1296 	    "%s, flex message, size %u bytes, not fully supported",
1297 	    __FUNCTION__, packet->m_nBodySize);
1298 	/*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */
1299 
1300 	/* some DEBUG code */
1301 #if 0
1302 	   RTMP_LIB_AMFObject obj;
1303 	   int nRes = obj.Decode(packet.m_body+1, packet.m_nBodySize-1);
1304 	   if(nRes < 0) {
1305 	   RTMP_Log(RTMP_LOGERROR, "%s, error decoding AMF3 packet", __FUNCTION__);
1306 	   /*return; */
1307 	   }
1308 
1309 	   obj.Dump();
1310 #endif
1311 
1312 	if (HandleInvoke(r, packet->m_body + 1, packet->m_nBodySize - 1) == 1)
1313 	  bHasMediaPacket = 2;
1314 	break;
1315       }
1316     case RTMP_PACKET_TYPE_INFO:
1317       /* metadata (notify) */
1318       RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %u bytes", __FUNCTION__,
1319 	  packet->m_nBodySize);
1320       if (HandleMetadata(r, packet->m_body, packet->m_nBodySize))
1321 	bHasMediaPacket = 1;
1322       break;
1323 
1324     case RTMP_PACKET_TYPE_SHARED_OBJECT:
1325       RTMP_Log(RTMP_LOGDEBUG, "%s, shared object, not supported, ignoring",
1326 	  __FUNCTION__);
1327       break;
1328 
1329     case RTMP_PACKET_TYPE_INVOKE:
1330       /* invoke */
1331       RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__,
1332 	  packet->m_nBodySize);
1333       /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */
1334 
1335       if (HandleInvoke(r, packet->m_body, packet->m_nBodySize) == 1)
1336 	bHasMediaPacket = 2;
1337       break;
1338 
1339     case RTMP_PACKET_TYPE_FLASH_VIDEO:
1340       {
1341 	/* go through FLV packets and handle metadata packets */
1342 	unsigned int pos = 0;
1343 	uint32_t nTimeStamp = packet->m_nTimeStamp;
1344 
1345 	while (pos + 11 < packet->m_nBodySize)
1346 	  {
1347 	    uint32_t dataSize = AMF_DecodeInt24(packet->m_body + pos + 1);	/* size without header (11) and prevTagSize (4) */
1348 
1349 	    if (pos + 11 + dataSize + 4 > packet->m_nBodySize)
1350 	      {
1351 		RTMP_Log(RTMP_LOGWARNING, "Stream corrupt?!");
1352 		break;
1353 	      }
1354 	    if (packet->m_body[pos] == 0x12)
1355 	      {
1356 		HandleMetadata(r, packet->m_body + pos + 11, dataSize);
1357 	      }
1358 	    else if (packet->m_body[pos] == 8 || packet->m_body[pos] == 9)
1359 	      {
1360 		nTimeStamp = AMF_DecodeInt24(packet->m_body + pos + 4);
1361 		nTimeStamp |= (packet->m_body[pos + 7] << 24);
1362 	      }
1363 	    pos += (11 + dataSize + 4);
1364 	  }
1365 	if (!r->m_pausing)
1366 	  r->m_mediaStamp = nTimeStamp;
1367 
1368 	/* FLV tag(s) */
1369 	/*RTMP_Log(RTMP_LOGDEBUG, "%s, received: FLV tag(s) %lu bytes", __FUNCTION__, packet.m_nBodySize); */
1370 	bHasMediaPacket = 1;
1371 	break;
1372       }
1373     default:
1374       RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,
1375 	  packet->m_packetType);
1376 #ifdef _DEBUG
1377       RTMP_LogHex(RTMP_LOGDEBUG, packet->m_body, packet->m_nBodySize);
1378 #endif
1379     }
1380 
1381   return bHasMediaPacket;
1382 }
1383 
1384 #ifdef _DEBUG
1385 extern FILE *netstackdump;
1386 extern FILE *netstackdump_read;
1387 #endif
1388 
1389 static int
ReadN(RTMP * r,char * buffer,int n)1390 ReadN(RTMP *r, char *buffer, int n)
1391 {
1392   int nOriginalSize = n;
1393   int avail;
1394   char *ptr;
1395 
1396   r->m_sb.sb_timedout = FALSE;
1397 
1398 #ifdef _DEBUG
1399   memset(buffer, 0, n);
1400 #endif
1401 
1402   ptr = buffer;
1403   while (n > 0)
1404     {
1405       int nBytes = 0, nRead;
1406       if (r->Link.protocol & RTMP_FEATURE_HTTP)
1407         {
1408 	  int refill = 0;
1409 	  while (!r->m_resplen)
1410 	    {
1411 	      int ret;
1412 	      if (r->m_sb.sb_size < 13 || refill)
1413 	        {
1414 		  if (!r->m_unackd)
1415 		    HTTP_Post(r, RTMPT_IDLE, "", 1);
1416 		  if (RTMPSockBuf_Fill(&r->m_sb) < 1)
1417 		    {
1418 		      if (!r->m_sb.sb_timedout)
1419 		        RTMP_Close(r);
1420 		      return 0;
1421 		    }
1422 		}
1423 	      if ((ret = HTTP_read(r, 0)) == -1)
1424 		{
1425 		  RTMP_Log(RTMP_LOGDEBUG, "%s, No valid HTTP response found", __FUNCTION__);
1426 		  RTMP_Close(r);
1427 		  return 0;
1428 		}
1429               else if (ret == -2)
1430                 {
1431                   refill = 1;
1432                 }
1433               else
1434                 {
1435                   refill = 0;
1436                 }
1437 	    }
1438 	  if (r->m_resplen && !r->m_sb.sb_size)
1439 	    RTMPSockBuf_Fill(&r->m_sb);
1440           avail = r->m_sb.sb_size;
1441 	  if (avail > r->m_resplen)
1442 	    avail = r->m_resplen;
1443 	}
1444       else
1445         {
1446           avail = r->m_sb.sb_size;
1447 	  if (avail == 0)
1448 	    {
1449 	      if (RTMPSockBuf_Fill(&r->m_sb) < 1)
1450 	        {
1451 	          if (!r->m_sb.sb_timedout)
1452 	            RTMP_Close(r);
1453 	          return 0;
1454 		}
1455 	      avail = r->m_sb.sb_size;
1456 	    }
1457 	}
1458       nRead = ((n < avail) ? n : avail);
1459       if (nRead > 0)
1460 	{
1461 	  memcpy(ptr, r->m_sb.sb_start, nRead);
1462 	  r->m_sb.sb_start += nRead;
1463 	  r->m_sb.sb_size -= nRead;
1464 	  nBytes = nRead;
1465 	  r->m_nBytesIn += nRead;
1466 	  if (r->m_bSendCounter
1467 	      && r->m_nBytesIn > ( r->m_nBytesInSent + r->m_nClientBW / 10))
1468 	    if (!SendBytesReceived(r))
1469 	        return FALSE;
1470 	}
1471       /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d bytes\n", __FUNCTION__, nBytes); */
1472 #ifdef _DEBUG
1473       fwrite(ptr, 1, nBytes, netstackdump_read);
1474 #endif
1475 
1476       if (nBytes == 0)
1477 	{
1478 	  RTMP_Log(RTMP_LOGDEBUG, "%s, RTMP socket closed by peer", __FUNCTION__);
1479 	  /*goto again; */
1480 	  RTMP_Close(r);
1481 	  break;
1482 	}
1483 
1484       if (r->Link.protocol & RTMP_FEATURE_HTTP)
1485 	r->m_resplen -= nBytes;
1486 
1487 #ifdef CRYPTO
1488       if (r->Link.rc4keyIn)
1489 	{
1490 	  RC4_encrypt(r->Link.rc4keyIn, nBytes, ptr);
1491 	}
1492 #endif
1493 
1494       n -= nBytes;
1495       ptr += nBytes;
1496     }
1497 
1498   return nOriginalSize - n;
1499 }
1500 
1501 static int
WriteN(RTMP * r,const char * buffer,int n)1502 WriteN(RTMP *r, const char *buffer, int n)
1503 {
1504   const char *ptr = buffer;
1505 #ifdef CRYPTO
1506   char *encrypted = 0;
1507   char buf[RTMP_BUFFER_CACHE_SIZE];
1508 
1509   if (r->Link.rc4keyOut)
1510     {
1511       if (n > sizeof(buf))
1512 	encrypted = (char *)malloc(n);
1513       else
1514 	encrypted = (char *)buf;
1515       ptr = encrypted;
1516       RC4_encrypt2(r->Link.rc4keyOut, n, buffer, ptr);
1517     }
1518 #endif
1519 
1520   while (n > 0)
1521     {
1522       int nBytes;
1523 
1524       if (r->Link.protocol & RTMP_FEATURE_HTTP)
1525         nBytes = HTTP_Post(r, RTMPT_SEND, ptr, n);
1526       else
1527         nBytes = RTMPSockBuf_Send(&r->m_sb, ptr, n);
1528       /*RTMP_Log(RTMP_LOGDEBUG, "%s: %d\n", __FUNCTION__, nBytes); */
1529 
1530       if (nBytes < 0)
1531 	{
1532 	  int sockerr = GetSockError();
1533 	  RTMP_Log(RTMP_LOGERROR, "%s, RTMP send error %d (%d bytes)", __FUNCTION__,
1534 	      sockerr, n);
1535 
1536 	  if (sockerr == EINTR && !RTMP_ctrlC)
1537 	    continue;
1538 
1539 	  RTMP_Close(r);
1540 	  n = 1;
1541 	  break;
1542 	}
1543 
1544       if (nBytes == 0)
1545 	break;
1546 
1547       n -= nBytes;
1548       ptr += nBytes;
1549     }
1550 
1551 #ifdef CRYPTO
1552   if (encrypted && encrypted != buf)
1553     free(encrypted);
1554 #endif
1555 
1556   return n == 0;
1557 }
1558 
1559 #define SAVC(x)	static const AVal av_##x = AVC(#x)
1560 
1561 SAVC(app);
1562 SAVC(connect);
1563 SAVC(flashVer);
1564 SAVC(swfUrl);
1565 SAVC(pageUrl);
1566 SAVC(tcUrl);
1567 SAVC(fpad);
1568 SAVC(capabilities);
1569 SAVC(audioCodecs);
1570 SAVC(videoCodecs);
1571 SAVC(videoFunction);
1572 SAVC(objectEncoding);
1573 SAVC(secureToken);
1574 SAVC(secureTokenResponse);
1575 SAVC(type);
1576 SAVC(nonprivate);
1577 
1578 static int
SendConnectPacket(RTMP * r,RTMPPacket * cp)1579 SendConnectPacket(RTMP *r, RTMPPacket *cp)
1580 {
1581   RTMPPacket packet;
1582   char pbuf[4096], *pend = pbuf + sizeof(pbuf);
1583   char *enc;
1584 
1585   if (cp)
1586     return RTMP_SendPacket(r, cp, TRUE);
1587 
1588   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1589   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
1590   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1591   packet.m_nTimeStamp = 0;
1592   packet.m_nInfoField2 = 0;
1593   packet.m_hasAbsTimestamp = 0;
1594   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1595 
1596   enc = packet.m_body;
1597   enc = AMF_EncodeString(enc, pend, &av_connect);
1598   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1599   *enc++ = AMF_OBJECT;
1600 
1601   enc = AMF_EncodeNamedString(enc, pend, &av_app, &r->Link.app);
1602   if (!enc)
1603     return FALSE;
1604   if (r->Link.protocol & RTMP_FEATURE_WRITE)
1605     {
1606       enc = AMF_EncodeNamedString(enc, pend, &av_type, &av_nonprivate);
1607       if (!enc)
1608 	return FALSE;
1609     }
1610   if (r->Link.flashVer.av_len)
1611     {
1612       enc = AMF_EncodeNamedString(enc, pend, &av_flashVer, &r->Link.flashVer);
1613       if (!enc)
1614 	return FALSE;
1615     }
1616   if (r->Link.swfUrl.av_len)
1617     {
1618       enc = AMF_EncodeNamedString(enc, pend, &av_swfUrl, &r->Link.swfUrl);
1619       if (!enc)
1620 	return FALSE;
1621     }
1622   if (r->Link.tcUrl.av_len)
1623     {
1624       enc = AMF_EncodeNamedString(enc, pend, &av_tcUrl, &r->Link.tcUrl);
1625       if (!enc)
1626 	return FALSE;
1627     }
1628   if (!(r->Link.protocol & RTMP_FEATURE_WRITE))
1629     {
1630       enc = AMF_EncodeNamedBoolean(enc, pend, &av_fpad, FALSE);
1631       if (!enc)
1632 	return FALSE;
1633       enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 15.0);
1634       if (!enc)
1635 	return FALSE;
1636       enc = AMF_EncodeNamedNumber(enc, pend, &av_audioCodecs, r->m_fAudioCodecs);
1637       if (!enc)
1638 	return FALSE;
1639       enc = AMF_EncodeNamedNumber(enc, pend, &av_videoCodecs, r->m_fVideoCodecs);
1640       if (!enc)
1641 	return FALSE;
1642       enc = AMF_EncodeNamedNumber(enc, pend, &av_videoFunction, 1.0);
1643       if (!enc)
1644 	return FALSE;
1645       if (r->Link.pageUrl.av_len)
1646 	{
1647 	  enc = AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r->Link.pageUrl);
1648 	  if (!enc)
1649 	    return FALSE;
1650 	}
1651     }
1652   if (r->m_fEncoding != 0.0 || r->m_bSendEncoding)
1653     {	/* AMF0, AMF3 not fully supported yet */
1654       enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding);
1655       if (!enc)
1656 	return FALSE;
1657     }
1658   if (enc + 3 >= pend)
1659     return FALSE;
1660   *enc++ = 0;
1661   *enc++ = 0;			/* end of object - 0x00 0x00 0x09 */
1662   *enc++ = AMF_OBJECT_END;
1663 
1664   /* add auth string */
1665   if (r->Link.auth.av_len)
1666     {
1667       enc = AMF_EncodeBoolean(enc, pend, r->Link.lFlags & RTMP_LF_AUTH);
1668       if (!enc)
1669 	return FALSE;
1670       enc = AMF_EncodeString(enc, pend, &r->Link.auth);
1671       if (!enc)
1672 	return FALSE;
1673     }
1674   if (r->Link.extras.o_num)
1675     {
1676       int i;
1677       for (i = 0; i < r->Link.extras.o_num; i++)
1678 	{
1679 	  enc = AMFProp_Encode(&r->Link.extras.o_props[i], enc, pend);
1680 	  if (!enc)
1681 	    return FALSE;
1682 	}
1683     }
1684   packet.m_nBodySize = enc - packet.m_body;
1685 
1686   return RTMP_SendPacket(r, &packet, TRUE);
1687 }
1688 
1689 #if 0				/* unused */
1690 SAVC(bgHasStream);
1691 
1692 static int
1693 SendBGHasStream(RTMP *r, double dId, AVal *playpath)
1694 {
1695   RTMPPacket packet;
1696   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1697   char *enc;
1698 
1699   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1700   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1701   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1702   packet.m_nTimeStamp = 0;
1703   packet.m_nInfoField2 = 0;
1704   packet.m_hasAbsTimestamp = 0;
1705   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1706 
1707   enc = packet.m_body;
1708   enc = AMF_EncodeString(enc, pend, &av_bgHasStream);
1709   enc = AMF_EncodeNumber(enc, pend, dId);
1710   *enc++ = AMF_NULL;
1711 
1712   enc = AMF_EncodeString(enc, pend, playpath);
1713   if (enc == NULL)
1714     return FALSE;
1715 
1716   packet.m_nBodySize = enc - packet.m_body;
1717 
1718   return RTMP_SendPacket(r, &packet, TRUE);
1719 }
1720 #endif
1721 
1722 SAVC(createStream);
1723 
1724 int
RTMP_SendCreateStream(RTMP * r)1725 RTMP_SendCreateStream(RTMP *r)
1726 {
1727   RTMPPacket packet;
1728   char pbuf[256], *pend = pbuf + sizeof(pbuf);
1729   char *enc;
1730 
1731   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1732   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1733   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1734   packet.m_nTimeStamp = 0;
1735   packet.m_nInfoField2 = 0;
1736   packet.m_hasAbsTimestamp = 0;
1737   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1738 
1739   enc = packet.m_body;
1740   enc = AMF_EncodeString(enc, pend, &av_createStream);
1741   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1742   *enc++ = AMF_NULL;		/* NULL */
1743 
1744   packet.m_nBodySize = enc - packet.m_body;
1745 
1746   return RTMP_SendPacket(r, &packet, TRUE);
1747 }
1748 
1749 SAVC(FCSubscribe);
1750 
1751 static int
SendFCSubscribe(RTMP * r,AVal * subscribepath)1752 SendFCSubscribe(RTMP *r, AVal *subscribepath)
1753 {
1754   RTMPPacket packet;
1755   char pbuf[512], *pend = pbuf + sizeof(pbuf);
1756   char *enc;
1757   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1758   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1759   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1760   packet.m_nTimeStamp = 0;
1761   packet.m_nInfoField2 = 0;
1762   packet.m_hasAbsTimestamp = 0;
1763   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1764 
1765   RTMP_Log(RTMP_LOGDEBUG, "FCSubscribe: %s", subscribepath->av_val);
1766   enc = packet.m_body;
1767   enc = AMF_EncodeString(enc, pend, &av_FCSubscribe);
1768   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1769   *enc++ = AMF_NULL;
1770   enc = AMF_EncodeString(enc, pend, subscribepath);
1771 
1772   if (!enc)
1773     return FALSE;
1774 
1775   packet.m_nBodySize = enc - packet.m_body;
1776 
1777   return RTMP_SendPacket(r, &packet, TRUE);
1778 }
1779 
1780 /* Justin.tv specific authentication */
1781 static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken");
1782 
1783 static int
SendUsherToken(RTMP * r,AVal * usherToken)1784 SendUsherToken(RTMP *r, AVal *usherToken)
1785 {
1786   RTMPPacket packet;
1787   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1788   char *enc;
1789   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1790   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1791   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1792   packet.m_nTimeStamp = 0;
1793   packet.m_nInfoField2 = 0;
1794   packet.m_hasAbsTimestamp = 0;
1795   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1796 
1797   RTMP_Log(RTMP_LOGDEBUG, "UsherToken: %s", usherToken->av_val);
1798   enc = packet.m_body;
1799   enc = AMF_EncodeString(enc, pend, &av_NetStream_Authenticate_UsherToken);
1800   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1801   *enc++ = AMF_NULL;
1802   enc = AMF_EncodeString(enc, pend, usherToken);
1803 
1804   if (!enc)
1805     return FALSE;
1806 
1807   packet.m_nBodySize = enc - packet.m_body;
1808 
1809   return RTMP_SendPacket(r, &packet, FALSE);
1810 }
1811 /******************************************/
1812 
1813 SAVC(releaseStream);
1814 
1815 static int
SendReleaseStream(RTMP * r)1816 SendReleaseStream(RTMP *r)
1817 {
1818   RTMPPacket packet;
1819   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1820   char *enc;
1821 
1822   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1823   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1824   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1825   packet.m_nTimeStamp = 0;
1826   packet.m_nInfoField2 = 0;
1827   packet.m_hasAbsTimestamp = 0;
1828   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1829 
1830  enc = packet.m_body;
1831   enc = AMF_EncodeString(enc, pend, &av_releaseStream);
1832   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1833   *enc++ = AMF_NULL;
1834   enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
1835   if (!enc)
1836     return FALSE;
1837 
1838   packet.m_nBodySize = enc - packet.m_body;
1839 
1840   return RTMP_SendPacket(r, &packet, FALSE);
1841 }
1842 
1843 SAVC(FCPublish);
1844 
1845 static int
SendFCPublish(RTMP * r)1846 SendFCPublish(RTMP *r)
1847 {
1848   RTMPPacket packet;
1849   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1850   char *enc;
1851 
1852   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1853   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1854   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1855   packet.m_nTimeStamp = 0;
1856   packet.m_nInfoField2 = 0;
1857   packet.m_hasAbsTimestamp = 0;
1858   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1859 
1860   enc = packet.m_body;
1861   enc = AMF_EncodeString(enc, pend, &av_FCPublish);
1862   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1863   *enc++ = AMF_NULL;
1864   enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
1865   if (!enc)
1866     return FALSE;
1867 
1868   packet.m_nBodySize = enc - packet.m_body;
1869 
1870   return RTMP_SendPacket(r, &packet, FALSE);
1871 }
1872 
1873 SAVC(FCUnpublish);
1874 
1875 static int
SendFCUnpublish(RTMP * r)1876 SendFCUnpublish(RTMP *r)
1877 {
1878   RTMPPacket packet;
1879   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1880   char *enc;
1881 
1882   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1883   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1884   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1885   packet.m_nTimeStamp = 0;
1886   packet.m_nInfoField2 = 0;
1887   packet.m_hasAbsTimestamp = 0;
1888   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1889 
1890   enc = packet.m_body;
1891   enc = AMF_EncodeString(enc, pend, &av_FCUnpublish);
1892   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1893   *enc++ = AMF_NULL;
1894   enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
1895   if (!enc)
1896     return FALSE;
1897 
1898   packet.m_nBodySize = enc - packet.m_body;
1899 
1900   return RTMP_SendPacket(r, &packet, FALSE);
1901 }
1902 
1903 SAVC(publish);
1904 SAVC(live);
1905 SAVC(record);
1906 
1907 static int
SendPublish(RTMP * r)1908 SendPublish(RTMP *r)
1909 {
1910   RTMPPacket packet;
1911   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
1912   char *enc;
1913 
1914   packet.m_nChannel = 0x04;	/* source channel (invoke) */
1915   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
1916   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1917   packet.m_nTimeStamp = 0;
1918   packet.m_nInfoField2 = r->m_stream_id;
1919   packet.m_hasAbsTimestamp = 0;
1920   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1921 
1922   enc = packet.m_body;
1923   enc = AMF_EncodeString(enc, pend, &av_publish);
1924   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1925   *enc++ = AMF_NULL;
1926   enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
1927   if (!enc)
1928     return FALSE;
1929 
1930   /* FIXME: should we choose live based on Link.lFlags & RTMP_LF_LIVE? */
1931   enc = AMF_EncodeString(enc, pend, &av_live);
1932   if (!enc)
1933     return FALSE;
1934 
1935   packet.m_nBodySize = enc - packet.m_body;
1936 
1937   return RTMP_SendPacket(r, &packet, TRUE);
1938 }
1939 
1940 SAVC(deleteStream);
1941 
1942 static int
SendDeleteStream(RTMP * r,double dStreamId)1943 SendDeleteStream(RTMP *r, double dStreamId)
1944 {
1945   RTMPPacket packet;
1946   char pbuf[256], *pend = pbuf + sizeof(pbuf);
1947   char *enc;
1948 
1949   packet.m_nChannel = 0x03;	/* control channel (invoke) */
1950   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1951   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1952   packet.m_nTimeStamp = 0;
1953   packet.m_nInfoField2 = 0;
1954   packet.m_hasAbsTimestamp = 0;
1955   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1956 
1957   enc = packet.m_body;
1958   enc = AMF_EncodeString(enc, pend, &av_deleteStream);
1959   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1960   *enc++ = AMF_NULL;
1961   enc = AMF_EncodeNumber(enc, pend, dStreamId);
1962 
1963   packet.m_nBodySize = enc - packet.m_body;
1964 
1965   /* no response expected */
1966   return RTMP_SendPacket(r, &packet, FALSE);
1967 }
1968 
1969 SAVC(pause);
1970 
1971 int
RTMP_SendPause(RTMP * r,int DoPause,int iTime)1972 RTMP_SendPause(RTMP *r, int DoPause, int iTime)
1973 {
1974   RTMPPacket packet;
1975   char pbuf[256], *pend = pbuf + sizeof(pbuf);
1976   char *enc;
1977 
1978   packet.m_nChannel = 0x08;	/* video channel */
1979   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
1980   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
1981   packet.m_nTimeStamp = 0;
1982   packet.m_nInfoField2 = 0;
1983   packet.m_hasAbsTimestamp = 0;
1984   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
1985 
1986   enc = packet.m_body;
1987   enc = AMF_EncodeString(enc, pend, &av_pause);
1988   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
1989   *enc++ = AMF_NULL;
1990   enc = AMF_EncodeBoolean(enc, pend, DoPause);
1991   enc = AMF_EncodeNumber(enc, pend, (double)iTime);
1992 
1993   packet.m_nBodySize = enc - packet.m_body;
1994 
1995   RTMP_Log(RTMP_LOGDEBUG, "%s, %d, pauseTime=%d", __FUNCTION__, DoPause, iTime);
1996   return RTMP_SendPacket(r, &packet, TRUE);
1997 }
1998 
RTMP_Pause(RTMP * r,int DoPause)1999 int RTMP_Pause(RTMP *r, int DoPause)
2000 {
2001   if (DoPause)
2002     r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
2003                       r->m_channelTimestamp[r->m_mediaChannel] : 0;
2004   return RTMP_SendPause(r, DoPause, r->m_pauseStamp);
2005 }
2006 
2007 SAVC(seek);
2008 
2009 int
RTMP_SendSeek(RTMP * r,int iTime)2010 RTMP_SendSeek(RTMP *r, int iTime)
2011 {
2012   RTMPPacket packet;
2013   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2014   char *enc;
2015 
2016   packet.m_nChannel = 0x08;	/* video channel */
2017   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2018   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2019   packet.m_nTimeStamp = 0;
2020   packet.m_nInfoField2 = 0;
2021   packet.m_hasAbsTimestamp = 0;
2022   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2023 
2024   enc = packet.m_body;
2025   enc = AMF_EncodeString(enc, pend, &av_seek);
2026   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
2027   *enc++ = AMF_NULL;
2028   enc = AMF_EncodeNumber(enc, pend, (double)iTime);
2029 
2030   packet.m_nBodySize = enc - packet.m_body;
2031 
2032   r->m_read.flags |= RTMP_READ_SEEKING;
2033   r->m_read.nResumeTS = 0;
2034 
2035   return RTMP_SendPacket(r, &packet, TRUE);
2036 }
2037 
2038 int
RTMP_SendServerBW(RTMP * r)2039 RTMP_SendServerBW(RTMP *r)
2040 {
2041   RTMPPacket packet;
2042   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2043 
2044   packet.m_nChannel = 0x02;	/* control channel (invoke) */
2045   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
2046   packet.m_packetType = RTMP_PACKET_TYPE_SERVER_BW;
2047   packet.m_nTimeStamp = 0;
2048   packet.m_nInfoField2 = 0;
2049   packet.m_hasAbsTimestamp = 0;
2050   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2051 
2052   packet.m_nBodySize = 4;
2053 
2054   AMF_EncodeInt32(packet.m_body, pend, r->m_nServerBW);
2055   return RTMP_SendPacket(r, &packet, FALSE);
2056 }
2057 
2058 int
RTMP_SendClientBW(RTMP * r)2059 RTMP_SendClientBW(RTMP *r)
2060 {
2061   RTMPPacket packet;
2062   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2063 
2064   packet.m_nChannel = 0x02;	/* control channel (invoke) */
2065   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
2066   packet.m_packetType = RTMP_PACKET_TYPE_CLIENT_BW;
2067   packet.m_nTimeStamp = 0;
2068   packet.m_nInfoField2 = 0;
2069   packet.m_hasAbsTimestamp = 0;
2070   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2071 
2072   packet.m_nBodySize = 5;
2073 
2074   AMF_EncodeInt32(packet.m_body, pend, r->m_nClientBW);
2075   packet.m_body[4] = r->m_nClientBW2;
2076   return RTMP_SendPacket(r, &packet, FALSE);
2077 }
2078 
2079 static int
SendBytesReceived(RTMP * r)2080 SendBytesReceived(RTMP *r)
2081 {
2082   RTMPPacket packet;
2083   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2084 
2085   packet.m_nChannel = 0x02;	/* control channel (invoke) */
2086   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2087   packet.m_packetType = RTMP_PACKET_TYPE_BYTES_READ_REPORT;
2088   packet.m_nTimeStamp = 0;
2089   packet.m_nInfoField2 = 0;
2090   packet.m_hasAbsTimestamp = 0;
2091   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2092 
2093   packet.m_nBodySize = 4;
2094 
2095   AMF_EncodeInt32(packet.m_body, pend, r->m_nBytesIn);	/* hard coded for now */
2096   r->m_nBytesInSent = r->m_nBytesIn;
2097 
2098   /*RTMP_Log(RTMP_LOGDEBUG, "Send bytes report. 0x%x (%d bytes)", (unsigned int)m_nBytesIn, m_nBytesIn); */
2099   return RTMP_SendPacket(r, &packet, FALSE);
2100 }
2101 
2102 SAVC(_checkbw);
2103 
2104 static int
SendCheckBW(RTMP * r)2105 SendCheckBW(RTMP *r)
2106 {
2107   RTMPPacket packet;
2108   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2109   char *enc;
2110 
2111   packet.m_nChannel = 0x03;	/* control channel (invoke) */
2112   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
2113   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2114   packet.m_nTimeStamp = 0;	/* RTMP_GetTime(); */
2115   packet.m_nInfoField2 = 0;
2116   packet.m_hasAbsTimestamp = 0;
2117   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2118 
2119   enc = packet.m_body;
2120   enc = AMF_EncodeString(enc, pend, &av__checkbw);
2121   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
2122   *enc++ = AMF_NULL;
2123 
2124   packet.m_nBodySize = enc - packet.m_body;
2125 
2126   /* triggers _onbwcheck and eventually results in _onbwdone */
2127   return RTMP_SendPacket(r, &packet, FALSE);
2128 }
2129 
2130 SAVC(_result);
2131 
2132 static int
SendCheckBWResult(RTMP * r,double txn)2133 SendCheckBWResult(RTMP *r, double txn)
2134 {
2135   RTMPPacket packet;
2136   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2137   char *enc;
2138 
2139   packet.m_nChannel = 0x03;	/* control channel (invoke) */
2140   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2141   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2142   packet.m_nTimeStamp = 0x16 * r->m_nBWCheckCounter;	/* temp inc value. till we figure it out. */
2143   packet.m_nInfoField2 = 0;
2144   packet.m_hasAbsTimestamp = 0;
2145   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2146 
2147   enc = packet.m_body;
2148   enc = AMF_EncodeString(enc, pend, &av__result);
2149   enc = AMF_EncodeNumber(enc, pend, txn);
2150   *enc++ = AMF_NULL;
2151   enc = AMF_EncodeNumber(enc, pend, (double)r->m_nBWCheckCounter++);
2152 
2153   packet.m_nBodySize = enc - packet.m_body;
2154 
2155   return RTMP_SendPacket(r, &packet, FALSE);
2156 }
2157 
2158 SAVC(ping);
2159 SAVC(pong);
2160 
2161 static int
SendPong(RTMP * r,double txn)2162 SendPong(RTMP *r, double txn)
2163 {
2164   RTMPPacket packet;
2165   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2166   char *enc;
2167 
2168   packet.m_nChannel = 0x03;	/* control channel (invoke) */
2169   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2170   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2171   packet.m_nTimeStamp = 0x16 * r->m_nBWCheckCounter;	/* temp inc value. till we figure it out. */
2172   packet.m_nInfoField2 = 0;
2173   packet.m_hasAbsTimestamp = 0;
2174   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2175 
2176   enc = packet.m_body;
2177   enc = AMF_EncodeString(enc, pend, &av_pong);
2178   enc = AMF_EncodeNumber(enc, pend, txn);
2179   *enc++ = AMF_NULL;
2180 
2181   packet.m_nBodySize = enc - packet.m_body;
2182 
2183   return RTMP_SendPacket(r, &packet, FALSE);
2184 }
2185 
2186 SAVC(play);
2187 
2188 static int
SendPlay(RTMP * r)2189 SendPlay(RTMP *r)
2190 {
2191   RTMPPacket packet;
2192   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
2193   char *enc;
2194 
2195   packet.m_nChannel = 0x08;	/* we make 8 our stream channel */
2196   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
2197   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2198   packet.m_nTimeStamp = 0;
2199   packet.m_nInfoField2 = r->m_stream_id;	/*0x01000000; */
2200   packet.m_hasAbsTimestamp = 0;
2201   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2202 
2203   enc = packet.m_body;
2204   enc = AMF_EncodeString(enc, pend, &av_play);
2205   enc = AMF_EncodeNumber(enc, pend, ++r->m_numInvokes);
2206   *enc++ = AMF_NULL;
2207 
2208   RTMP_Log(RTMP_LOGDEBUG, "%s, seekTime=%d, stopTime=%d, sending play: %s",
2209       __FUNCTION__, r->Link.seekTime, r->Link.stopTime,
2210       r->Link.playpath.av_val);
2211   enc = AMF_EncodeString(enc, pend, &r->Link.playpath);
2212   if (!enc)
2213     return FALSE;
2214 
2215   /* Optional parameters start and len.
2216    *
2217    * start: -2, -1, 0, positive number
2218    *  -2: looks for a live stream, then a recorded stream,
2219    *      if not found any open a live stream
2220    *  -1: plays a live stream
2221    * >=0: plays a recorded streams from 'start' milliseconds
2222    */
2223   if (r->Link.lFlags & RTMP_LF_LIVE)
2224     enc = AMF_EncodeNumber(enc, pend, -1000.0);
2225   else
2226     {
2227       if (r->Link.seekTime > 0.0)
2228 	enc = AMF_EncodeNumber(enc, pend, r->Link.seekTime);	/* resume from here */
2229       else
2230 	enc = AMF_EncodeNumber(enc, pend, 0.0);	/*-2000.0);*/ /* recorded as default, -2000.0 is not reliable since that freezes the player if the stream is not found */
2231     }
2232   if (!enc)
2233     return FALSE;
2234 
2235   /* len: -1, 0, positive number
2236    *  -1: plays live or recorded stream to the end (default)
2237    *   0: plays a frame 'start' ms away from the beginning
2238    *  >0: plays a live or recoded stream for 'len' milliseconds
2239    */
2240   /*enc += EncodeNumber(enc, -1.0); */ /* len */
2241   if (r->Link.stopTime)
2242     {
2243       enc = AMF_EncodeNumber(enc, pend, r->Link.stopTime - r->Link.seekTime);
2244       if (!enc)
2245 	return FALSE;
2246     }
2247 
2248   packet.m_nBodySize = enc - packet.m_body;
2249 
2250   return RTMP_SendPacket(r, &packet, TRUE);
2251 }
2252 
2253 SAVC(set_playlist);
2254 SAVC(0);
2255 
2256 static int
SendPlaylist(RTMP * r)2257 SendPlaylist(RTMP *r)
2258 {
2259   RTMPPacket packet;
2260   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
2261   char *enc;
2262 
2263   packet.m_nChannel = 0x08;	/* we make 8 our stream channel */
2264   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
2265   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2266   packet.m_nTimeStamp = 0;
2267   packet.m_nInfoField2 = r->m_stream_id;	/*0x01000000; */
2268   packet.m_hasAbsTimestamp = 0;
2269   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2270 
2271   enc = packet.m_body;
2272   enc = AMF_EncodeString(enc, pend, &av_set_playlist);
2273   enc = AMF_EncodeNumber(enc, pend, 0);
2274   *enc++ = AMF_NULL;
2275   *enc++ = AMF_ECMA_ARRAY;
2276   *enc++ = 0;
2277   *enc++ = 0;
2278   *enc++ = 0;
2279   *enc++ = AMF_OBJECT;
2280   enc = AMF_EncodeNamedString(enc, pend, &av_0, &r->Link.playpath);
2281   if (!enc)
2282     return FALSE;
2283   if (enc + 3 >= pend)
2284     return FALSE;
2285   *enc++ = 0;
2286   *enc++ = 0;
2287   *enc++ = AMF_OBJECT_END;
2288 
2289   packet.m_nBodySize = enc - packet.m_body;
2290 
2291   return RTMP_SendPacket(r, &packet, TRUE);
2292 }
2293 
2294 static int
SendSecureTokenResponse(RTMP * r,AVal * resp)2295 SendSecureTokenResponse(RTMP *r, AVal *resp)
2296 {
2297   RTMPPacket packet;
2298   char pbuf[1024], *pend = pbuf + sizeof(pbuf);
2299   char *enc;
2300 
2301   packet.m_nChannel = 0x03;	/* control channel (invoke) */
2302   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2303   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
2304   packet.m_nTimeStamp = 0;
2305   packet.m_nInfoField2 = 0;
2306   packet.m_hasAbsTimestamp = 0;
2307   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2308 
2309   enc = packet.m_body;
2310   enc = AMF_EncodeString(enc, pend, &av_secureTokenResponse);
2311   enc = AMF_EncodeNumber(enc, pend, 0.0);
2312   *enc++ = AMF_NULL;
2313   enc = AMF_EncodeString(enc, pend, resp);
2314   if (!enc)
2315     return FALSE;
2316 
2317   packet.m_nBodySize = enc - packet.m_body;
2318 
2319   return RTMP_SendPacket(r, &packet, FALSE);
2320 }
2321 
2322 /*
2323 from http://jira.red5.org/confluence/display/docs/Ping:
2324 
2325 Ping is the most mysterious message in RTMP and till now we haven't fully interpreted it yet. In summary, Ping message is used as a special command that are exchanged between client and server. This page aims to document all known Ping messages. Expect the list to grow.
2326 
2327 The type of Ping packet is 0x4 and contains two mandatory parameters and two optional parameters. The first parameter is the type of Ping and in short integer. The second parameter is the target of the ping. As Ping is always sent in Channel 2 (control channel) and the target object in RTMP header is always 0 which means the Connection object, it's necessary to put an extra parameter to indicate the exact target object the Ping is sent to. The second parameter takes this responsibility. The value has the same meaning as the target object field in RTMP header. (The second value could also be used as other purposes, like RTT Ping/Pong. It is used as the timestamp.) The third and fourth parameters are optional and could be looked upon as the parameter of the Ping packet. Below is an unexhausted list of Ping messages.
2328 
2329     * type 0: Clear the stream. No third and fourth parameters. The second parameter could be 0. After the connection is established, a Ping 0,0 will be sent from server to client. The message will also be sent to client on the start of Play and in response of a Seek or Pause/Resume request. This Ping tells client to re-calibrate the clock with the timestamp of the next packet server sends.
2330     * type 1: Tell the stream to clear the playing buffer.
2331     * type 3: Buffer time of the client. The third parameter is the buffer time in millisecond.
2332     * type 4: Reset a stream. Used together with type 0 in the case of VOD. Often sent before type 0.
2333     * type 6: Ping the client from server. The second parameter is the current time.
2334     * type 7: Pong reply from client. The second parameter is the time the server sent with his ping request.
2335     * type 26: SWFVerification request
2336     * type 27: SWFVerification response
2337 */
2338 int
RTMP_SendCtrl(RTMP * r,short nType,unsigned int nObject,unsigned int nTime)2339 RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, unsigned int nTime)
2340 {
2341   RTMPPacket packet;
2342   char pbuf[256], *pend = pbuf + sizeof(pbuf);
2343   int nSize;
2344   char *buf;
2345 
2346   RTMP_Log(RTMP_LOGDEBUG, "sending ctrl. type: 0x%04x", (unsigned short)nType);
2347 
2348   packet.m_nChannel = 0x02;	/* control channel (ping) */
2349   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
2350   packet.m_packetType = RTMP_PACKET_TYPE_CONTROL;
2351   packet.m_nTimeStamp = 0;	/* RTMP_GetTime(); */
2352   packet.m_nInfoField2 = 0;
2353   packet.m_hasAbsTimestamp = 0;
2354   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
2355 
2356   switch(nType) {
2357   case 0x03: nSize = 10; break;	/* buffer time */
2358   case 0x1A: nSize = 3; break;	/* SWF verify request */
2359   case 0x1B: nSize = 44; break;	/* SWF verify response */
2360   default: nSize = 6; break;
2361   }
2362 
2363   packet.m_nBodySize = nSize;
2364 
2365   buf = packet.m_body;
2366   buf = AMF_EncodeInt16(buf, pend, nType);
2367 
2368   if (nType == 0x1B)
2369     {
2370 #ifdef CRYPTO
2371       memcpy(buf, r->Link.SWFVerificationResponse, 42);
2372       RTMP_Log(RTMP_LOGDEBUG, "Sending SWFVerification response: ");
2373       RTMP_LogHex(RTMP_LOGDEBUG, (uint8_t *)packet.m_body, packet.m_nBodySize);
2374 #endif
2375     }
2376   else if (nType == 0x1A)
2377     {
2378 	  *buf = nObject & 0xff;
2379 	}
2380   else
2381     {
2382       if (nSize > 2)
2383 	buf = AMF_EncodeInt32(buf, pend, nObject);
2384 
2385       if (nSize > 6)
2386 	buf = AMF_EncodeInt32(buf, pend, nTime);
2387     }
2388 
2389   return RTMP_SendPacket(r, &packet, FALSE);
2390 }
2391 
2392 static void
AV_erase(RTMP_METHOD * vals,int * num,int i,int freeit)2393 AV_erase(RTMP_METHOD *vals, int *num, int i, int freeit)
2394 {
2395   if (freeit)
2396     free(vals[i].name.av_val);
2397   (*num)--;
2398   for (; i < *num; i++)
2399     {
2400       vals[i] = vals[i + 1];
2401     }
2402   vals[i].name.av_val = NULL;
2403   vals[i].name.av_len = 0;
2404   vals[i].num = 0;
2405 }
2406 
2407 void
RTMP_DropRequest(RTMP * r,int i,int freeit)2408 RTMP_DropRequest(RTMP *r, int i, int freeit)
2409 {
2410   AV_erase(r->m_methodCalls, &r->m_numCalls, i, freeit);
2411 }
2412 
2413 static void
AV_queue(RTMP_METHOD ** vals,int * num,AVal * av,int txn)2414 AV_queue(RTMP_METHOD **vals, int *num, AVal *av, int txn)
2415 {
2416   char *tmp;
2417   if (!(*num & 0x0f))
2418     *vals = realloc(*vals, (*num + 16) * sizeof(RTMP_METHOD));
2419   tmp = malloc(av->av_len + 1);
2420   memcpy(tmp, av->av_val, av->av_len);
2421   tmp[av->av_len] = '\0';
2422   (*vals)[*num].num = txn;
2423   (*vals)[*num].name.av_len = av->av_len;
2424   (*vals)[(*num)++].name.av_val = tmp;
2425 }
2426 
2427 static void
AV_clear(RTMP_METHOD * vals,int num)2428 AV_clear(RTMP_METHOD *vals, int num)
2429 {
2430   int i;
2431   for (i = 0; i < num; i++)
2432     free(vals[i].name.av_val);
2433   free(vals);
2434 }
2435 
2436 
2437 #ifdef CRYPTO
2438 static int
b64enc(const unsigned char * input,int length,char * output,int maxsize)2439 b64enc(const unsigned char *input, int length, char *output, int maxsize)
2440 {
2441 #ifdef USE_POLARSSL
2442   size_t buf_size = maxsize;
2443   if(base64_encode((unsigned char *) output, &buf_size, input, length) == 0)
2444     {
2445       output[buf_size] = '\0';
2446       return 1;
2447     }
2448   else
2449     {
2450       RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
2451       return 0;
2452     }
2453 #elif defined(USE_GNUTLS)
2454   if (BASE64_ENCODE_RAW_LENGTH(length) <= maxsize)
2455     base64_encode_raw((uint8_t*) output, length, input);
2456   else
2457     {
2458       RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
2459       return 0;
2460     }
2461 #else   /* USE_OPENSSL */
2462   BIO *bmem, *b64;
2463   BUF_MEM *bptr;
2464 
2465   b64 = BIO_new(BIO_f_base64());
2466   bmem = BIO_new(BIO_s_mem());
2467   b64 = BIO_push(b64, bmem);
2468   BIO_write(b64, input, length);
2469   if (BIO_flush(b64) == 1)
2470     {
2471       BIO_get_mem_ptr(b64, &bptr);
2472       memcpy(output, bptr->data, bptr->length-1);
2473       output[bptr->length-1] = '\0';
2474     }
2475   else
2476     {
2477       RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
2478       return 0;
2479     }
2480   BIO_free_all(b64);
2481 #endif
2482   return 1;
2483 }
2484 
2485 #ifdef USE_POLARSSL
2486 #define MD5_CTX	md5_context
2487 #define MD5_Init(ctx)	md5_starts(ctx)
2488 #define MD5_Update(ctx,data,len)	md5_update(ctx,(unsigned char *)data,len)
2489 #define MD5_Final(dig,ctx)	md5_finish(ctx,dig)
2490 #elif defined(USE_GNUTLS)
2491 typedef struct md5_ctx	MD5_CTX;
2492 #define MD5_Init(ctx)	md5_init(ctx)
2493 #define MD5_Update(ctx,data,len)	md5_update(ctx,len,data)
2494 #define MD5_Final(dig,ctx)	md5_digest(ctx,MD5_DIGEST_LENGTH,dig)
2495 #else
2496 #endif
2497 
2498 static const AVal av_authmod_adobe = AVC("authmod=adobe");
2499 static const AVal av_authmod_llnw  = AVC("authmod=llnw");
2500 
hexenc(unsigned char * inbuf,int len,char * dst)2501 static void hexenc(unsigned char *inbuf, int len, char *dst)
2502 {
2503     char *ptr = dst;
2504     while(len--) {
2505         sprintf(ptr, "%02x", *inbuf++);
2506         ptr += 2;
2507     }
2508     *ptr = '\0';
2509 }
2510 
2511 static char *
AValChr(AVal * av,char c)2512 AValChr(AVal *av, char c)
2513 {
2514   int i;
2515   for (i = 0; i < av->av_len; i++)
2516     if (av->av_val[i] == c)
2517       return &av->av_val[i];
2518   return NULL;
2519 }
2520 
2521 static int
PublisherAuth(RTMP * r,AVal * description)2522 PublisherAuth(RTMP *r, AVal *description)
2523 {
2524   char *token_in = NULL;
2525   char *ptr;
2526   unsigned char md5sum_val[MD5_DIGEST_LENGTH+1];
2527   MD5_CTX md5ctx;
2528   int challenge2_data;
2529 #define RESPONSE_LEN 32
2530 #define CHALLENGE2_LEN 16
2531 #define SALTED2_LEN (32+8+8+8)
2532 #define B64DIGEST_LEN	24	/* 16 byte digest => 22 b64 chars + 2 chars padding */
2533 #define B64INT_LEN	8	/* 4 byte int => 6 b64 chars + 2 chars padding */
2534 #define HEXHASH_LEN	(2*MD5_DIGEST_LENGTH)
2535   char response[RESPONSE_LEN];
2536   char challenge2[CHALLENGE2_LEN];
2537   char salted2[SALTED2_LEN];
2538   AVal pubToken;
2539 
2540   if (strstr(description->av_val, av_authmod_adobe.av_val) != NULL)
2541     {
2542       if(strstr(description->av_val, "code=403 need auth") != NULL)
2543         {
2544             if (strstr(r->Link.app.av_val, av_authmod_adobe.av_val) != NULL) {
2545               RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__);
2546               return 0;
2547             } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) {
2548               pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_adobe.av_len + 8);
2549               pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s",
2550                       av_authmod_adobe.av_val,
2551                       r->Link.pubUser.av_val);
2552               RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val);
2553             } else {
2554               RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__);
2555               return 0;
2556             }
2557         }
2558       else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL)
2559         {
2560           char *par, *val = NULL, *orig_ptr;
2561 	  AVal user, salt, opaque, challenge, *aptr = NULL;
2562 	  opaque.av_len = 0;
2563 	  challenge.av_len = 0;
2564 
2565           ptr = orig_ptr = strdup(token_in);
2566           while (ptr)
2567             {
2568               par = ptr;
2569               ptr = strchr(par, '&');
2570               if(ptr)
2571                   *ptr++ = '\0';
2572 
2573               val =  strchr(par, '=');
2574               if(val)
2575                   *val++ = '\0';
2576 
2577 	      if (aptr) {
2578 		aptr->av_len = par - aptr->av_val - 1;
2579 		aptr = NULL;
2580 	      }
2581               if (strcmp(par, "user") == 0){
2582                   user.av_val = val;
2583 		  aptr = &user;
2584               } else if (strcmp(par, "salt") == 0){
2585                   salt.av_val = val;
2586 		  aptr = &salt;
2587               } else if (strcmp(par, "opaque") == 0){
2588                   opaque.av_val = val;
2589 		  aptr = &opaque;
2590               } else if (strcmp(par, "challenge") == 0){
2591                   challenge.av_val = val;
2592 		  aptr = &challenge;
2593               }
2594 
2595               RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
2596             }
2597 	  if (aptr)
2598 	    aptr->av_len = strlen(aptr->av_val);
2599 
2600 	  /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */
2601 	  MD5_Init(&md5ctx);
2602 	  MD5_Update(&md5ctx, user.av_val, user.av_len);
2603 	  MD5_Update(&md5ctx, salt.av_val, salt.av_len);
2604 	  MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
2605 	  MD5_Final(md5sum_val, &md5ctx);
2606           RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
2607 	    user.av_val, salt.av_val, r->Link.pubPasswd.av_val);
2608           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
2609 
2610           b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN);
2611           RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2);
2612 
2613             challenge2_data = rand();
2614 
2615             b64enc((unsigned char *) &challenge2_data, sizeof(int), challenge2, CHALLENGE2_LEN);
2616             RTMP_Log(RTMP_LOGDEBUG, "%s, b64(%d) = %s", __FUNCTION__, challenge2_data, challenge2);
2617 
2618 	  MD5_Init(&md5ctx);
2619 	  MD5_Update(&md5ctx, salted2, B64DIGEST_LEN);
2620             /* response = base64enc(md5(hash1 + opaque + challenge2)) */
2621 	  if (opaque.av_len)
2622 	    MD5_Update(&md5ctx, opaque.av_val, opaque.av_len);
2623 	  else if (challenge.av_len)
2624 	    MD5_Update(&md5ctx, challenge.av_val, challenge.av_len);
2625 	  MD5_Update(&md5ctx, challenge2, B64INT_LEN);
2626 	  MD5_Final(md5sum_val, &md5ctx);
2627 
2628           RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
2629 	    salted2, opaque.av_len ? opaque.av_val : "", challenge2);
2630           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
2631 
2632           b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN);
2633           RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response);
2634 
2635             /* have all hashes, create auth token for the end of app */
2636             pubToken.av_val = malloc(32 + B64INT_LEN + B64DIGEST_LEN + opaque.av_len);
2637             pubToken.av_len = sprintf(pubToken.av_val,
2638                     "&challenge=%s&response=%s&opaque=%s",
2639                     challenge2,
2640                     response,
2641                     opaque.av_len ? opaque.av_val : "");
2642             RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
2643             free(orig_ptr);
2644         }
2645       else if(strstr(description->av_val, "?reason=authfailed") != NULL)
2646         {
2647           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: wrong password", __FUNCTION__);
2648           return 0;
2649         }
2650       else if(strstr(description->av_val, "?reason=nosuchuser") != NULL)
2651         {
2652           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__);
2653           return 0;
2654         }
2655       else
2656         {
2657           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s",
2658                   __FUNCTION__, description->av_val);
2659           return 0;
2660         }
2661 
2662       ptr = malloc(r->Link.app.av_len + pubToken.av_len);
2663       strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len);
2664       strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len);
2665       r->Link.app.av_len += pubToken.av_len;
2666       if(r->Link.lFlags & RTMP_LF_FAPU)
2667           free(r->Link.app.av_val);
2668       r->Link.app.av_val = ptr;
2669 
2670       ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len);
2671       strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len);
2672       strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len);
2673       r->Link.tcUrl.av_len += pubToken.av_len;
2674       if(r->Link.lFlags & RTMP_LF_FTCU)
2675           free(r->Link.tcUrl.av_val);
2676       r->Link.tcUrl.av_val = ptr;
2677 
2678       free(pubToken.av_val);
2679       r->Link.lFlags |= RTMP_LF_FTCU | RTMP_LF_FAPU;
2680 
2681       RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__,
2682               r->Link.app.av_len, r->Link.app.av_val,
2683               r->Link.tcUrl.av_len, r->Link.tcUrl.av_val,
2684               r->Link.playpath.av_val);
2685     }
2686   else if (strstr(description->av_val, av_authmod_llnw.av_val) != NULL)
2687     {
2688       if(strstr(description->av_val, "code=403 need auth") != NULL)
2689         {
2690             /* This part seems to be the same for llnw and adobe */
2691 
2692             if (strstr(r->Link.app.av_val, av_authmod_llnw.av_val) != NULL) {
2693               RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__);
2694               return 0;
2695             } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) {
2696               pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_llnw.av_len + 8);
2697               pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s",
2698                       av_authmod_llnw.av_val,
2699                       r->Link.pubUser.av_val);
2700               RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val);
2701             } else {
2702               RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__);
2703               return 0;
2704             }
2705         }
2706       else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL)
2707         {
2708           char *orig_ptr;
2709           char *par, *val = NULL;
2710 	  char hash1[HEXHASH_LEN+1], hash2[HEXHASH_LEN+1], hash3[HEXHASH_LEN+1];
2711 	  AVal user, nonce, *aptr = NULL;
2712 	  AVal apptmp;
2713 
2714           /* llnw auth method
2715            * Seems to be closely based on HTTP Digest Auth:
2716            *    http://tools.ietf.org/html/rfc2617
2717            *    http://en.wikipedia.org/wiki/Digest_access_authentication
2718            */
2719 
2720           const char authmod[] = "llnw";
2721           const char realm[] = "live";
2722           const char method[] = "publish";
2723           const char qop[] = "auth";
2724           /* nc = 1..connection count (or rather, number of times cnonce has been reused) */
2725           int nc = 1;
2726           /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */
2727           char nchex[9];
2728           /* cnonce = hexenc(4 random bytes) (initialized on first connection) */
2729           char cnonce[9];
2730 
2731           ptr = orig_ptr = strdup(token_in);
2732           /* Extract parameters (we need user and nonce) */
2733           while (ptr)
2734             {
2735               par = ptr;
2736               ptr = strchr(par, '&');
2737               if(ptr)
2738                   *ptr++ = '\0';
2739 
2740               val =  strchr(par, '=');
2741               if(val)
2742                   *val++ = '\0';
2743 
2744 	      if (aptr) {
2745 		aptr->av_len = par - aptr->av_val - 1;
2746 		aptr = NULL;
2747 	      }
2748               if (strcmp(par, "user") == 0){
2749                 user.av_val = val;
2750 		aptr = &user;
2751               } else if (strcmp(par, "nonce") == 0){
2752                 nonce.av_val = val;
2753 		aptr = &nonce;
2754               }
2755 
2756               RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
2757             }
2758 	  if (aptr)
2759 	    aptr->av_len = strlen(aptr->av_val);
2760 
2761           /* FIXME: handle case where user==NULL or nonce==NULL */
2762 
2763           sprintf(nchex, "%08x", nc);
2764           sprintf(cnonce, "%08x", rand());
2765 
2766           /* hash1 = hexenc(md5(user + ":" + realm + ":" + password)) */
2767 	  MD5_Init(&md5ctx);
2768 	  MD5_Update(&md5ctx, user.av_val, user.av_len);
2769 	  MD5_Update(&md5ctx, ":", 1);
2770 	  MD5_Update(&md5ctx, realm, sizeof(realm)-1);
2771 	  MD5_Update(&md5ctx, ":", 1);
2772 	  MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
2773 	  MD5_Final(md5sum_val, &md5ctx);
2774           RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s) =>", __FUNCTION__,
2775 	    user.av_val, realm, r->Link.pubPasswd.av_val);
2776           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
2777           hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash1);
2778 
2779           /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */
2780           /* Extract appname + appinstance without query parameters */
2781 	  apptmp = r->Link.app;
2782 	  ptr = AValChr(&apptmp, '?');
2783 	  if (ptr)
2784 	    apptmp.av_len = ptr - apptmp.av_val;
2785 
2786 	  MD5_Init(&md5ctx);
2787 	  MD5_Update(&md5ctx, method, sizeof(method)-1);
2788 	  MD5_Update(&md5ctx, ":/", 2);
2789 	  MD5_Update(&md5ctx, apptmp.av_val, apptmp.av_len);
2790 	  if (!AValChr(&apptmp, '/'))
2791 	    MD5_Update(&md5ctx, "/_definst_", sizeof("/_definst_") - 1);
2792 	  MD5_Final(md5sum_val, &md5ctx);
2793           RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:/%.*s) =>", __FUNCTION__,
2794 	    method, apptmp.av_len, apptmp.av_val);
2795           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
2796           hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash2);
2797 
2798           /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */
2799 	  MD5_Init(&md5ctx);
2800 	  MD5_Update(&md5ctx, hash1, HEXHASH_LEN);
2801 	  MD5_Update(&md5ctx, ":", 1);
2802 	  MD5_Update(&md5ctx, nonce.av_val, nonce.av_len);
2803 	  MD5_Update(&md5ctx, ":", 1);
2804 	  MD5_Update(&md5ctx, nchex, sizeof(nchex)-1);
2805 	  MD5_Update(&md5ctx, ":", 1);
2806 	  MD5_Update(&md5ctx, cnonce, sizeof(cnonce)-1);
2807 	  MD5_Update(&md5ctx, ":", 1);
2808 	  MD5_Update(&md5ctx, qop, sizeof(qop)-1);
2809 	  MD5_Update(&md5ctx, ":", 1);
2810 	  MD5_Update(&md5ctx, hash2, HEXHASH_LEN);
2811 	  MD5_Final(md5sum_val, &md5ctx);
2812           RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s:%s:%s:%s) =>", __FUNCTION__,
2813 	    hash1, nonce.av_val, nchex, cnonce, qop, hash2);
2814           RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
2815           hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash3);
2816 
2817           /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */
2818           /* Append nonces and response to query string which already contains
2819            * user + authmod */
2820           pubToken.av_val = malloc(64 + sizeof(authmod)-1 + user.av_len + nonce.av_len + sizeof(cnonce)-1 + sizeof(nchex)-1 + HEXHASH_LEN);
2821           sprintf(pubToken.av_val,
2822                   "&nonce=%s&cnonce=%s&nc=%s&response=%s",
2823                   nonce.av_val, cnonce, nchex, hash3);
2824           pubToken.av_len = strlen(pubToken.av_val);
2825           RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
2826 
2827           free(orig_ptr);
2828         }
2829       else if(strstr(description->av_val, "?reason=authfail") != NULL)
2830         {
2831           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed", __FUNCTION__);
2832           return 0;
2833         }
2834       else if(strstr(description->av_val, "?reason=nosuchuser") != NULL)
2835         {
2836           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__);
2837           return 0;
2838         }
2839       else
2840         {
2841           RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s",
2842                   __FUNCTION__, description->av_val);
2843           return 0;
2844         }
2845 
2846       ptr = malloc(r->Link.app.av_len + pubToken.av_len);
2847       strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len);
2848       strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len);
2849       r->Link.app.av_len += pubToken.av_len;
2850       if(r->Link.lFlags & RTMP_LF_FAPU)
2851           free(r->Link.app.av_val);
2852       r->Link.app.av_val = ptr;
2853 
2854       ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len);
2855       strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len);
2856       strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len);
2857       r->Link.tcUrl.av_len += pubToken.av_len;
2858       if(r->Link.lFlags & RTMP_LF_FTCU)
2859           free(r->Link.tcUrl.av_val);
2860       r->Link.tcUrl.av_val = ptr;
2861 
2862       free(pubToken.av_val);
2863       r->Link.lFlags |= RTMP_LF_FTCU | RTMP_LF_FAPU;
2864 
2865       RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__,
2866               r->Link.app.av_len, r->Link.app.av_val,
2867               r->Link.tcUrl.av_len, r->Link.tcUrl.av_val,
2868               r->Link.playpath.av_val);
2869     }
2870   else
2871     {
2872       return 0;
2873     }
2874   return 1;
2875 }
2876 #endif
2877 
2878 
2879 SAVC(onBWDone);
2880 SAVC(onFCSubscribe);
2881 SAVC(onFCUnsubscribe);
2882 SAVC(_onbwcheck);
2883 SAVC(_onbwdone);
2884 SAVC(_error);
2885 SAVC(close);
2886 SAVC(code);
2887 SAVC(level);
2888 SAVC(description);
2889 SAVC(onStatus);
2890 SAVC(playlist_ready);
2891 static const AVal av_NetStream_Failed = AVC("NetStream.Failed");
2892 static const AVal av_NetStream_Play_Failed = AVC("NetStream.Play.Failed");
2893 static const AVal av_NetStream_Play_StreamNotFound =
2894 AVC("NetStream.Play.StreamNotFound");
2895 static const AVal av_NetConnection_Connect_InvalidApp =
2896 AVC("NetConnection.Connect.InvalidApp");
2897 static const AVal av_NetStream_Play_Start = AVC("NetStream.Play.Start");
2898 static const AVal av_NetStream_Play_Complete = AVC("NetStream.Play.Complete");
2899 static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop");
2900 static const AVal av_NetStream_Seek_Notify = AVC("NetStream.Seek.Notify");
2901 static const AVal av_NetStream_Pause_Notify = AVC("NetStream.Pause.Notify");
2902 static const AVal av_NetStream_Play_PublishNotify =
2903 AVC("NetStream.Play.PublishNotify");
2904 static const AVal av_NetStream_Play_UnpublishNotify =
2905 AVC("NetStream.Play.UnpublishNotify");
2906 static const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start");
2907 static const AVal av_NetConnection_Connect_Rejected =
2908 AVC("NetConnection.Connect.Rejected");
2909 
2910 /* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */
2911 static int
HandleInvoke(RTMP * r,const char * body,unsigned int nBodySize)2912 HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
2913 {
2914   AMFObject obj;
2915   AVal method;
2916   double txn;
2917   int ret = 0, nRes;
2918   if (body[0] != 0x02)		/* make sure it is a string method name we start with */
2919     {
2920       RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet",
2921 	  __FUNCTION__);
2922       return 0;
2923     }
2924 
2925   nRes = AMF_Decode(&obj, body, nBodySize, FALSE);
2926   if (nRes < 0)
2927     {
2928       RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__);
2929       return 0;
2930     }
2931 
2932   AMF_Dump(&obj);
2933   AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);
2934   txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1));
2935   RTMP_Log(RTMP_LOGDEBUG, "%s, server invoking <%s>", __FUNCTION__, method.av_val);
2936 
2937   if (AVMATCH(&method, &av__result))
2938     {
2939       AVal methodInvoked = {0};
2940       int i;
2941 
2942       for (i=0; i<r->m_numCalls; i++) {
2943 	if (r->m_methodCalls[i].num == (int)txn) {
2944 	  methodInvoked = r->m_methodCalls[i].name;
2945 	  AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE);
2946 	  break;
2947 	}
2948       }
2949       if (!methodInvoked.av_val) {
2950         RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request",
2951 	  __FUNCTION__, txn);
2952 	goto leave;
2953       }
2954 
2955       RTMP_Log(RTMP_LOGDEBUG, "%s, received result for method call <%s>", __FUNCTION__,
2956 	  methodInvoked.av_val);
2957 
2958       if (AVMATCH(&methodInvoked, &av_connect))
2959 	{
2960 	  if (r->Link.token.av_len)
2961 	    {
2962 	      AMFObjectProperty p;
2963 	      if (RTMP_FindFirstMatchingProperty(&obj, &av_secureToken, &p))
2964 		{
2965 		  DecodeTEA(&r->Link.token, &p.p_vu.p_aval);
2966 		  SendSecureTokenResponse(r, &p.p_vu.p_aval);
2967 		}
2968 	    }
2969 	  if (r->Link.protocol & RTMP_FEATURE_WRITE)
2970 	    {
2971 	      SendReleaseStream(r);
2972 	      SendFCPublish(r);
2973 	    }
2974 	  else
2975 	    {
2976 	      RTMP_SendServerBW(r);
2977 	      RTMP_SendCtrl(r, 3, 0, 300);
2978 	    }
2979 	  RTMP_SendCreateStream(r);
2980 
2981 	  if (!(r->Link.protocol & RTMP_FEATURE_WRITE))
2982 	    {
2983 	      /* Authenticate on Justin.tv legacy servers before sending FCSubscribe */
2984 	      if (r->Link.usherToken.av_len)
2985 	        SendUsherToken(r, &r->Link.usherToken);
2986 	      /* Send the FCSubscribe if live stream or if subscribepath is set */
2987 	      if (r->Link.subscribepath.av_len)
2988 	        SendFCSubscribe(r, &r->Link.subscribepath);
2989 	      else if (r->Link.lFlags & RTMP_LF_LIVE)
2990 	        SendFCSubscribe(r, &r->Link.playpath);
2991 	    }
2992 	}
2993       else if (AVMATCH(&methodInvoked, &av_createStream))
2994 	{
2995 	  r->m_stream_id = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3));
2996 
2997 	  if (r->Link.protocol & RTMP_FEATURE_WRITE)
2998 	    {
2999 	      SendPublish(r);
3000 	    }
3001 	  else
3002 	    {
3003 	      if (r->Link.lFlags & RTMP_LF_PLST)
3004 	        SendPlaylist(r);
3005 	      SendPlay(r);
3006 	      RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
3007 	    }
3008 	}
3009       else if (AVMATCH(&methodInvoked, &av_play) ||
3010       	AVMATCH(&methodInvoked, &av_publish))
3011 	{
3012 	  r->m_bPlaying = TRUE;
3013 	}
3014       free(methodInvoked.av_val);
3015     }
3016   else if (AVMATCH(&method, &av_onBWDone))
3017     {
3018 	  if (!r->m_nBWCheckCounter)
3019         SendCheckBW(r);
3020     }
3021   else if (AVMATCH(&method, &av_onFCSubscribe))
3022     {
3023       /* SendOnFCSubscribe(); */
3024     }
3025   else if (AVMATCH(&method, &av_onFCUnsubscribe))
3026     {
3027       RTMP_Close(r);
3028       ret = 1;
3029     }
3030   else if (AVMATCH(&method, &av_ping))
3031     {
3032       SendPong(r, txn);
3033     }
3034   else if (AVMATCH(&method, &av__onbwcheck))
3035     {
3036       SendCheckBWResult(r, txn);
3037     }
3038   else if (AVMATCH(&method, &av__onbwdone))
3039     {
3040       int i;
3041       for (i = 0; i < r->m_numCalls; i++)
3042 	if (AVMATCH(&r->m_methodCalls[i].name, &av__checkbw))
3043 	  {
3044 	    AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE);
3045 	    break;
3046 	  }
3047     }
3048   else if (AVMATCH(&method, &av__error))
3049     {
3050 #ifdef CRYPTO
3051       AVal methodInvoked = {0};
3052       int i;
3053 
3054       if (r->Link.protocol & RTMP_FEATURE_WRITE)
3055         {
3056           for (i=0; i<r->m_numCalls; i++)
3057             {
3058               if (r->m_methodCalls[i].num == txn)
3059                 {
3060                   methodInvoked = r->m_methodCalls[i].name;
3061                   AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE);
3062                   break;
3063                 }
3064             }
3065           if (!methodInvoked.av_val)
3066             {
3067               RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request",
3068                     __FUNCTION__, txn);
3069               goto leave;
3070             }
3071 
3072           RTMP_Log(RTMP_LOGDEBUG, "%s, received error for method call <%s>", __FUNCTION__,
3073           methodInvoked.av_val);
3074 
3075           if (AVMATCH(&methodInvoked, &av_connect))
3076             {
3077               AMFObject obj2;
3078               AVal code, level, description;
3079               AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2);
3080               AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code);
3081               AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level);
3082               AMFProp_GetString(AMF_GetProp(&obj2, &av_description, -1), &description);
3083               RTMP_Log(RTMP_LOGDEBUG, "%s, error description: %s", __FUNCTION__, description.av_val);
3084               /* if PublisherAuth returns 1, then reconnect */
3085               if (PublisherAuth(r, &description) == 1)
3086               {
3087                 CloseInternal(r, 1);
3088                 if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0))
3089                   goto leave;
3090               }
3091             }
3092         }
3093       else
3094         {
3095           RTMP_Log(RTMP_LOGERROR, "rtmp server sent error");
3096         }
3097       free(methodInvoked.av_val);
3098 #else
3099       RTMP_Log(RTMP_LOGERROR, "rtmp server sent error");
3100 #endif
3101     }
3102   else if (AVMATCH(&method, &av_close))
3103     {
3104       RTMP_Log(RTMP_LOGERROR, "rtmp server requested close");
3105       RTMP_Close(r);
3106     }
3107   else if (AVMATCH(&method, &av_onStatus))
3108     {
3109       AMFObject obj2;
3110       AVal code, level;
3111       AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2);
3112       AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code);
3113       AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level);
3114 
3115       RTMP_Log(RTMP_LOGDEBUG, "%s, onStatus: %s", __FUNCTION__, code.av_val);
3116       if (AVMATCH(&code, &av_NetStream_Failed)
3117 	  || AVMATCH(&code, &av_NetStream_Play_Failed)
3118 	  || AVMATCH(&code, &av_NetStream_Play_StreamNotFound)
3119 	  || AVMATCH(&code, &av_NetConnection_Connect_InvalidApp))
3120 	{
3121 	  r->m_stream_id = -1;
3122 	  RTMP_Close(r);
3123 	  RTMP_Log(RTMP_LOGERROR, "Closing connection: %s", code.av_val);
3124 	}
3125 
3126       else if (AVMATCH(&code, &av_NetStream_Play_Start)
3127            || AVMATCH(&code, &av_NetStream_Play_PublishNotify))
3128 	{
3129 	  int i;
3130 	  r->m_bPlaying = TRUE;
3131 	  for (i = 0; i < r->m_numCalls; i++)
3132 	    {
3133 	      if (AVMATCH(&r->m_methodCalls[i].name, &av_play))
3134 		{
3135 		  AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE);
3136 		  break;
3137 		}
3138 	    }
3139 	}
3140 
3141       else if (AVMATCH(&code, &av_NetStream_Publish_Start))
3142 	{
3143 	  int i;
3144 	  r->m_bPlaying = TRUE;
3145 	  for (i = 0; i < r->m_numCalls; i++)
3146 	    {
3147 	      if (AVMATCH(&r->m_methodCalls[i].name, &av_publish))
3148 		{
3149 		  AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE);
3150 		  break;
3151 		}
3152 	    }
3153 	}
3154 
3155       /* Return 1 if this is a Play.Complete or Play.Stop */
3156       else if (AVMATCH(&code, &av_NetStream_Play_Complete)
3157 	  || AVMATCH(&code, &av_NetStream_Play_Stop)
3158 	  || AVMATCH(&code, &av_NetStream_Play_UnpublishNotify))
3159 	{
3160 	  RTMP_Close(r);
3161 	  ret = 1;
3162 	}
3163 
3164       else if (AVMATCH(&code, &av_NetStream_Seek_Notify))
3165         {
3166 	  r->m_read.flags &= ~RTMP_READ_SEEKING;
3167 	}
3168 
3169       else if (AVMATCH(&code, &av_NetStream_Pause_Notify))
3170         {
3171 	  if (r->m_pausing == 1 || r->m_pausing == 2)
3172 	  {
3173 	    RTMP_SendPause(r, FALSE, r->m_pauseStamp);
3174 	    r->m_pausing = 3;
3175 	  }
3176 	}
3177     }
3178   else if (AVMATCH(&method, &av_playlist_ready))
3179     {
3180       int i;
3181       for (i = 0; i < r->m_numCalls; i++)
3182         {
3183           if (AVMATCH(&r->m_methodCalls[i].name, &av_set_playlist))
3184 	    {
3185 	      AV_erase(r->m_methodCalls, &r->m_numCalls, i, TRUE);
3186 	      break;
3187 	    }
3188         }
3189     }
3190   else
3191     {
3192 
3193     }
3194 leave:
3195   AMF_Reset(&obj);
3196   return ret;
3197 }
3198 
3199 int
RTMP_FindFirstMatchingProperty(AMFObject * obj,const AVal * name,AMFObjectProperty * p)3200 RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name,
3201 			       AMFObjectProperty * p)
3202 {
3203   int n;
3204   /* this is a small object search to locate the "duration" property */
3205   for (n = 0; n < obj->o_num; n++)
3206     {
3207       AMFObjectProperty *prop = AMF_GetProp(obj, NULL, n);
3208 
3209       if (AVMATCH(&prop->p_name, name))
3210 	{
3211 	  memcpy(p, prop, sizeof(*prop));
3212 	  return TRUE;
3213 	}
3214 
3215       if (prop->p_type == AMF_OBJECT || prop->p_type == AMF_ECMA_ARRAY)
3216 	{
3217 	  if (RTMP_FindFirstMatchingProperty(&prop->p_vu.p_object, name, p))
3218 	    return TRUE;
3219 	}
3220     }
3221   return FALSE;
3222 }
3223 
3224 /* Like above, but only check if name is a prefix of property */
3225 int
RTMP_FindPrefixProperty(AMFObject * obj,const AVal * name,AMFObjectProperty * p)3226 RTMP_FindPrefixProperty(AMFObject *obj, const AVal *name,
3227 			       AMFObjectProperty * p)
3228 {
3229   int n;
3230   for (n = 0; n < obj->o_num; n++)
3231     {
3232       AMFObjectProperty *prop = AMF_GetProp(obj, NULL, n);
3233 
3234       if (prop->p_name.av_len > name->av_len &&
3235       	  !memcmp(prop->p_name.av_val, name->av_val, name->av_len))
3236 	{
3237 	  memcpy(p, prop, sizeof(*prop));
3238 	  return TRUE;
3239 	}
3240 
3241       if (prop->p_type == AMF_OBJECT)
3242 	{
3243 	  if (RTMP_FindPrefixProperty(&prop->p_vu.p_object, name, p))
3244 	    return TRUE;
3245 	}
3246     }
3247   return FALSE;
3248 }
3249 
3250 static int
DumpMetaData(AMFObject * obj)3251 DumpMetaData(AMFObject *obj)
3252 {
3253   AMFObjectProperty *prop;
3254   int n, len;
3255   for (n = 0; n < obj->o_num; n++)
3256     {
3257       char str[256] = "";
3258       prop = AMF_GetProp(obj, NULL, n);
3259       switch (prop->p_type)
3260 	{
3261 	case AMF_OBJECT:
3262 	case AMF_ECMA_ARRAY:
3263 	case AMF_STRICT_ARRAY:
3264 	  if (prop->p_name.av_len)
3265 	    RTMP_Log(RTMP_LOGINFO, "%.*s:", prop->p_name.av_len, prop->p_name.av_val);
3266 	  DumpMetaData(&prop->p_vu.p_object);
3267 	  break;
3268 	case AMF_NUMBER:
3269 	  snprintf(str, 255, "%.2f", prop->p_vu.p_number);
3270 	  break;
3271 	case AMF_BOOLEAN:
3272 	  snprintf(str, 255, "%s",
3273 		   prop->p_vu.p_number != 0. ? "TRUE" : "FALSE");
3274 	  break;
3275 	case AMF_STRING:
3276 	  len = snprintf(str, 255, "%.*s", prop->p_vu.p_aval.av_len,
3277 		   prop->p_vu.p_aval.av_val);
3278 	  if (len >= 1 && str[len-1] == '\n')
3279 	    str[len-1] = '\0';
3280 	  break;
3281 	case AMF_DATE:
3282 	  snprintf(str, 255, "timestamp:%.2f", prop->p_vu.p_number);
3283 	  break;
3284 	default:
3285 	  snprintf(str, 255, "INVALID TYPE 0x%02x",
3286 		   (unsigned char)prop->p_type);
3287 	}
3288       if (str[0] && prop->p_name.av_len)
3289 	{
3290 	  RTMP_Log(RTMP_LOGINFO, "  %-22.*s%s", prop->p_name.av_len,
3291 		    prop->p_name.av_val, str);
3292 	}
3293     }
3294   return FALSE;
3295 }
3296 
3297 SAVC(onMetaData);
3298 SAVC(duration);
3299 SAVC(video);
3300 SAVC(audio);
3301 
3302 static int
HandleMetadata(RTMP * r,char * body,unsigned int len)3303 HandleMetadata(RTMP *r, char *body, unsigned int len)
3304 {
3305   /* allright we get some info here, so parse it and print it */
3306   /* also keep duration or filesize to make a nice progress bar */
3307 
3308   AMFObject obj;
3309   AVal metastring;
3310   int ret = FALSE;
3311 
3312   int nRes = AMF_Decode(&obj, body, len, FALSE);
3313   if (nRes < 0)
3314     {
3315       RTMP_Log(RTMP_LOGERROR, "%s, error decoding meta data packet", __FUNCTION__);
3316       return FALSE;
3317     }
3318 
3319   AMF_Dump(&obj);
3320   AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &metastring);
3321 
3322   if (AVMATCH(&metastring, &av_onMetaData))
3323     {
3324       AMFObjectProperty prop;
3325       /* Show metadata */
3326       RTMP_Log(RTMP_LOGINFO, "Metadata:");
3327       DumpMetaData(&obj);
3328       if (RTMP_FindFirstMatchingProperty(&obj, &av_duration, &prop))
3329 	{
3330 	  r->m_fDuration = prop.p_vu.p_number;
3331 	  /*RTMP_Log(RTMP_LOGDEBUG, "Set duration: %.2f", m_fDuration); */
3332 	}
3333       /* Search for audio or video tags */
3334       if (RTMP_FindPrefixProperty(&obj, &av_video, &prop))
3335         r->m_read.dataType |= 1;
3336       if (RTMP_FindPrefixProperty(&obj, &av_audio, &prop))
3337         r->m_read.dataType |= 4;
3338       ret = TRUE;
3339     }
3340   AMF_Reset(&obj);
3341   return ret;
3342 }
3343 
3344 static void
HandleChangeChunkSize(RTMP * r,const RTMPPacket * packet)3345 HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet)
3346 {
3347   if (packet->m_nBodySize >= 4)
3348     {
3349       r->m_inChunkSize = AMF_DecodeInt32(packet->m_body);
3350       RTMP_Log(RTMP_LOGDEBUG, "%s, received: chunk size change to %d", __FUNCTION__,
3351 	  r->m_inChunkSize);
3352     }
3353 }
3354 
3355 static void
HandleAudio(RTMP * r,const RTMPPacket * packet)3356 HandleAudio(RTMP *r, const RTMPPacket *packet)
3357 {
3358 }
3359 
3360 static void
HandleVideo(RTMP * r,const RTMPPacket * packet)3361 HandleVideo(RTMP *r, const RTMPPacket *packet)
3362 {
3363 }
3364 
3365 static void
HandleCtrl(RTMP * r,const RTMPPacket * packet)3366 HandleCtrl(RTMP *r, const RTMPPacket *packet)
3367 {
3368   short nType = -1;
3369   unsigned int tmp;
3370   if (packet->m_body && packet->m_nBodySize >= 2)
3371     nType = AMF_DecodeInt16(packet->m_body);
3372   RTMP_Log(RTMP_LOGDEBUG, "%s, received ctrl. type: %d, len: %d", __FUNCTION__, nType,
3373       packet->m_nBodySize);
3374   /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */
3375 
3376   if (packet->m_nBodySize >= 6)
3377     {
3378       switch (nType)
3379 	{
3380 	case 0:
3381 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3382 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream Begin %d", __FUNCTION__, tmp);
3383 	  break;
3384 
3385 	case 1:
3386 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3387 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream EOF %d", __FUNCTION__, tmp);
3388 	  if (r->m_pausing == 1)
3389 	    r->m_pausing = 2;
3390 	  break;
3391 
3392 	case 2:
3393 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3394 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream Dry %d", __FUNCTION__, tmp);
3395 	  break;
3396 
3397 	case 4:
3398 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3399 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream IsRecorded %d", __FUNCTION__, tmp);
3400 	  break;
3401 
3402 	case 6:		/* server ping. reply with pong. */
3403 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3404 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Ping %d", __FUNCTION__, tmp);
3405 	  RTMP_SendCtrl(r, 0x07, tmp, 0);
3406 	  break;
3407 
3408 	/* FMS 3.5 servers send the following two controls to let the client
3409 	 * know when the server has sent a complete buffer. I.e., when the
3410 	 * server has sent an amount of data equal to m_nBufferMS in duration.
3411 	 * The server meters its output so that data arrives at the client
3412 	 * in realtime and no faster.
3413 	 *
3414 	 * The rtmpdump program tries to set m_nBufferMS as large as
3415 	 * possible, to force the server to send data as fast as possible.
3416 	 * In practice, the server appears to cap this at about 1 hour's
3417 	 * worth of data. After the server has sent a complete buffer, and
3418 	 * sends this BufferEmpty message, it will wait until the play
3419 	 * duration of that buffer has passed before sending a new buffer.
3420 	 * The BufferReady message will be sent when the new buffer starts.
3421 	 * (There is no BufferReady message for the very first buffer;
3422 	 * presumably the Stream Begin message is sufficient for that
3423 	 * purpose.)
3424 	 *
3425 	 * If the network speed is much faster than the data bitrate, then
3426 	 * there may be long delays between the end of one buffer and the
3427 	 * start of the next.
3428 	 *
3429 	 * Since usually the network allows data to be sent at
3430 	 * faster than realtime, and rtmpdump wants to download the data
3431 	 * as fast as possible, we use this RTMP_LF_BUFX hack: when we
3432 	 * get the BufferEmpty message, we send a Pause followed by an
3433 	 * Unpause. This causes the server to send the next buffer immediately
3434 	 * instead of waiting for the full duration to elapse. (That's
3435 	 * also the purpose of the ToggleStream function, which rtmpdump
3436 	 * calls if we get a read timeout.)
3437 	 *
3438 	 * Media player apps don't need this hack since they are just
3439 	 * going to play the data in realtime anyway. It also doesn't work
3440 	 * for live streams since they obviously can only be sent in
3441 	 * realtime. And it's all moot if the network speed is actually
3442 	 * slower than the media bitrate.
3443 	 */
3444 	case 31:
3445 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3446 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream BufferEmpty %d", __FUNCTION__, tmp);
3447 	  if (!(r->Link.lFlags & RTMP_LF_BUFX))
3448 	    break;
3449 	  if (!r->m_pausing)
3450 	    {
3451 	      r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
3452 	                        r->m_channelTimestamp[r->m_mediaChannel] : 0;
3453 	      RTMP_SendPause(r, TRUE, r->m_pauseStamp);
3454 	      r->m_pausing = 1;
3455 	    }
3456 	  else if (r->m_pausing == 2)
3457 	    {
3458 	      RTMP_SendPause(r, FALSE, r->m_pauseStamp);
3459 	      r->m_pausing = 3;
3460 	    }
3461 	  break;
3462 
3463 	case 32:
3464 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3465 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream BufferReady %d", __FUNCTION__, tmp);
3466 	  break;
3467 
3468 	default:
3469 	  tmp = AMF_DecodeInt32(packet->m_body + 2);
3470 	  RTMP_Log(RTMP_LOGDEBUG, "%s, Stream xx %d", __FUNCTION__, tmp);
3471 	  break;
3472 	}
3473 
3474     }
3475 
3476   if (nType == 0x1A)
3477     {
3478       RTMP_Log(RTMP_LOGDEBUG, "%s, SWFVerification ping received: ", __FUNCTION__);
3479       if (packet->m_nBodySize > 2 && packet->m_body[2] > 0x01)
3480 	{
3481 	  RTMP_Log(RTMP_LOGERROR,
3482             "%s: SWFVerification Type %d request not supported! Patches welcome...",
3483 	    __FUNCTION__, packet->m_body[2]);
3484 	}
3485 #ifdef CRYPTO
3486       /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */
3487 
3488       /* respond with HMAC SHA256 of decompressed SWF, key is the 30byte player key, also the last 30 bytes of the server handshake are applied */
3489       else if (r->Link.SWFSize)
3490 	{
3491 	  RTMP_SendCtrl(r, 0x1B, 0, 0);
3492 	}
3493       else
3494 	{
3495 	  RTMP_Log(RTMP_LOGERROR,
3496 	      "%s: Ignoring SWFVerification request, use --swfVfy!",
3497 	      __FUNCTION__);
3498 	}
3499 #else
3500       RTMP_Log(RTMP_LOGERROR,
3501 	  "%s: Ignoring SWFVerification request, no CRYPTO support!",
3502 	  __FUNCTION__);
3503 #endif
3504     }
3505 }
3506 
3507 static void
HandleServerBW(RTMP * r,const RTMPPacket * packet)3508 HandleServerBW(RTMP *r, const RTMPPacket *packet)
3509 {
3510   r->m_nServerBW = AMF_DecodeInt32(packet->m_body);
3511   RTMP_Log(RTMP_LOGDEBUG, "%s: server BW = %d", __FUNCTION__, r->m_nServerBW);
3512 }
3513 
3514 static void
HandleClientBW(RTMP * r,const RTMPPacket * packet)3515 HandleClientBW(RTMP *r, const RTMPPacket *packet)
3516 {
3517   r->m_nClientBW = AMF_DecodeInt32(packet->m_body);
3518   if (packet->m_nBodySize > 4)
3519     r->m_nClientBW2 = packet->m_body[4];
3520   else
3521     r->m_nClientBW2 = -1;
3522   RTMP_Log(RTMP_LOGDEBUG, "%s: client BW = %d %d", __FUNCTION__, r->m_nClientBW,
3523       r->m_nClientBW2);
3524 }
3525 
3526 static int
DecodeInt32LE(const char * data)3527 DecodeInt32LE(const char *data)
3528 {
3529   unsigned char *c = (unsigned char *)data;
3530   unsigned int val;
3531 
3532   val = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
3533   return val;
3534 }
3535 
3536 static int
EncodeInt32LE(char * output,int nVal)3537 EncodeInt32LE(char *output, int nVal)
3538 {
3539   output[0] = nVal;
3540   nVal >>= 8;
3541   output[1] = nVal;
3542   nVal >>= 8;
3543   output[2] = nVal;
3544   nVal >>= 8;
3545   output[3] = nVal;
3546   return 4;
3547 }
3548 
3549 int
RTMP_ReadPacket(RTMP * r,RTMPPacket * packet)3550 RTMP_ReadPacket(RTMP *r, RTMPPacket *packet)
3551 {
3552   uint8_t hbuf[RTMP_MAX_HEADER_SIZE] = { 0 };
3553   char *header = (char *)hbuf;
3554   int nSize, hSize, nToRead, nChunk;
3555   int didAlloc = FALSE;
3556   int extendedTimestamp;
3557 
3558   RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d", __FUNCTION__, r->m_sb.sb_socket);
3559 
3560   if (ReadN(r, (char *)hbuf, 1) == 0)
3561     {
3562       RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header", __FUNCTION__);
3563       return FALSE;
3564     }
3565 
3566   packet->m_headerType = (hbuf[0] & 0xc0) >> 6;
3567   packet->m_nChannel = (hbuf[0] & 0x3f);
3568   header++;
3569   if (packet->m_nChannel == 0)
3570     {
3571       if (ReadN(r, (char *)&hbuf[1], 1) != 1)
3572 	{
3573 	  RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header 2nd byte",
3574 	      __FUNCTION__);
3575 	  return FALSE;
3576 	}
3577       packet->m_nChannel = hbuf[1];
3578       packet->m_nChannel += 64;
3579       header++;
3580     }
3581   else if (packet->m_nChannel == 1)
3582     {
3583       int tmp;
3584       if (ReadN(r, (char *)&hbuf[1], 2) != 2)
3585 	{
3586 	  RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header 3nd byte",
3587 	      __FUNCTION__);
3588 	  return FALSE;
3589 	}
3590       tmp = (hbuf[2] << 8) + hbuf[1];
3591       packet->m_nChannel = tmp + 64;
3592       RTMP_Log(RTMP_LOGDEBUG, "%s, m_nChannel: %0x", __FUNCTION__, packet->m_nChannel);
3593       header += 2;
3594     }
3595 
3596   nSize = packetSize[packet->m_headerType];
3597 
3598   if (packet->m_nChannel >= r->m_channelsAllocatedIn)
3599     {
3600       int n = packet->m_nChannel + 10;
3601       int *timestamp = realloc(r->m_channelTimestamp, sizeof(int) * n);
3602       RTMPPacket **packets = realloc(r->m_vecChannelsIn, sizeof(RTMPPacket*) * n);
3603       if (!timestamp)
3604         free(r->m_channelTimestamp);
3605       if (!packets)
3606         free(r->m_vecChannelsIn);
3607       r->m_channelTimestamp = timestamp;
3608       r->m_vecChannelsIn = packets;
3609       if (!timestamp || !packets) {
3610         r->m_channelsAllocatedIn = 0;
3611         return FALSE;
3612       }
3613       memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, sizeof(int) * (n - r->m_channelsAllocatedIn));
3614       memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn));
3615       r->m_channelsAllocatedIn = n;
3616     }
3617 
3618   if (nSize == RTMP_LARGE_HEADER_SIZE)	/* if we get a full header the timestamp is absolute */
3619     packet->m_hasAbsTimestamp = TRUE;
3620 
3621   else if (nSize < RTMP_LARGE_HEADER_SIZE)
3622     {				/* using values from the last message of this channel */
3623       if (r->m_vecChannelsIn[packet->m_nChannel])
3624 	memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel],
3625 	       sizeof(RTMPPacket));
3626     }
3627 
3628   nSize--;
3629 
3630   if (nSize > 0 && ReadN(r, header, nSize) != nSize)
3631     {
3632       RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header. type: %x",
3633 	  __FUNCTION__, (unsigned int)hbuf[0]);
3634       return FALSE;
3635     }
3636 
3637   hSize = nSize + (header - (char *)hbuf);
3638 
3639   if (nSize >= 3)
3640     {
3641       packet->m_nTimeStamp = AMF_DecodeInt24(header);
3642 
3643       /*RTMP_Log(RTMP_LOGDEBUG, "%s, reading RTMP packet chunk on channel %x, headersz %i, timestamp %i, abs timestamp %i", __FUNCTION__, packet.m_nChannel, nSize, packet.m_nTimeStamp, packet.m_hasAbsTimestamp); */
3644 
3645       if (nSize >= 6)
3646 	{
3647 	  packet->m_nBodySize = AMF_DecodeInt24(header + 3);
3648 	  packet->m_nBytesRead = 0;
3649 
3650 	  if (nSize > 6)
3651 	    {
3652 	      packet->m_packetType = header[6];
3653 
3654 	      if (nSize == 11)
3655 		packet->m_nInfoField2 = DecodeInt32LE(header + 7);
3656 	    }
3657 	}
3658     }
3659 
3660   extendedTimestamp = packet->m_nTimeStamp == 0xffffff;
3661   if (extendedTimestamp)
3662     {
3663       if (ReadN(r, header + nSize, 4) != 4)
3664 	{
3665 	  RTMP_Log(RTMP_LOGERROR, "%s, failed to read extended timestamp",
3666 	      __FUNCTION__);
3667 	  return FALSE;
3668 	}
3669       packet->m_nTimeStamp = AMF_DecodeInt32(header + nSize);
3670       hSize += 4;
3671     }
3672 
3673   RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)hbuf, hSize);
3674 
3675   if (packet->m_nBodySize > 0 && packet->m_body == NULL)
3676     {
3677       if (!RTMPPacket_Alloc(packet, packet->m_nBodySize))
3678 	{
3679 	  RTMP_Log(RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);
3680 	  return FALSE;
3681 	}
3682       didAlloc = TRUE;
3683       packet->m_headerType = (hbuf[0] & 0xc0) >> 6;
3684     }
3685 
3686   nToRead = packet->m_nBodySize - packet->m_nBytesRead;
3687   nChunk = r->m_inChunkSize;
3688   if (nToRead < nChunk)
3689     nChunk = nToRead;
3690 
3691   /* Does the caller want the raw chunk? */
3692   if (packet->m_chunk)
3693     {
3694       packet->m_chunk->c_headerSize = hSize;
3695       memcpy(packet->m_chunk->c_header, hbuf, hSize);
3696       packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead;
3697       packet->m_chunk->c_chunkSize = nChunk;
3698     }
3699 
3700   if (ReadN(r, packet->m_body + packet->m_nBytesRead, nChunk) != nChunk)
3701     {
3702       RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet body. len: %u",
3703 	  __FUNCTION__, packet->m_nBodySize);
3704       return FALSE;
3705     }
3706 
3707   RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)packet->m_body + packet->m_nBytesRead, nChunk);
3708 
3709   packet->m_nBytesRead += nChunk;
3710 
3711   /* keep the packet as ref for other packets on this channel */
3712   if (!r->m_vecChannelsIn[packet->m_nChannel])
3713     r->m_vecChannelsIn[packet->m_nChannel] = malloc(sizeof(RTMPPacket));
3714   memcpy(r->m_vecChannelsIn[packet->m_nChannel], packet, sizeof(RTMPPacket));
3715   if (extendedTimestamp)
3716     {
3717       r->m_vecChannelsIn[packet->m_nChannel]->m_nTimeStamp = 0xffffff;
3718     }
3719 
3720   if (RTMPPacket_IsReady(packet))
3721     {
3722       /* make packet's timestamp absolute */
3723       if (!packet->m_hasAbsTimestamp)
3724 	packet->m_nTimeStamp += r->m_channelTimestamp[packet->m_nChannel];	/* timestamps seem to be always relative!! */
3725 
3726       r->m_channelTimestamp[packet->m_nChannel] = packet->m_nTimeStamp;
3727 
3728       /* reset the data from the stored packet. we keep the header since we may use it later if a new packet for this channel */
3729       /* arrives and requests to re-use some info (small packet header) */
3730       r->m_vecChannelsIn[packet->m_nChannel]->m_body = NULL;
3731       r->m_vecChannelsIn[packet->m_nChannel]->m_nBytesRead = 0;
3732       r->m_vecChannelsIn[packet->m_nChannel]->m_hasAbsTimestamp = FALSE;	/* can only be false if we reuse header */
3733     }
3734   else
3735     {
3736       packet->m_body = NULL;	/* so it won't be erased on free */
3737     }
3738 
3739   return TRUE;
3740 }
3741 
3742 #ifndef CRYPTO
3743 static int
HandShake(RTMP * r,int FP9HandShake)3744 HandShake(RTMP *r, int FP9HandShake)
3745 {
3746   int i;
3747   uint32_t uptime, suptime;
3748   int bMatch;
3749   char type;
3750   char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf + 1;
3751   char serversig[RTMP_SIG_SIZE];
3752 
3753   clientbuf[0] = 0x03;		/* not encrypted */
3754 
3755   uptime = htonl(RTMP_GetTime());
3756   memcpy(clientsig, &uptime, 4);
3757 
3758   memset(&clientsig[4], 0, 4);
3759 
3760 #ifdef _DEBUG
3761   for (i = 8; i < RTMP_SIG_SIZE; i++)
3762     clientsig[i] = 0xff;
3763 #else
3764   for (i = 8; i < RTMP_SIG_SIZE; i++)
3765     clientsig[i] = (char)(rand() % 256);
3766 #endif
3767 
3768   if (!WriteN(r, clientbuf, RTMP_SIG_SIZE + 1))
3769     return FALSE;
3770 
3771   if (ReadN(r, &type, 1) != 1)	/* 0x03 or 0x06 */
3772     return FALSE;
3773 
3774   RTMP_Log(RTMP_LOGDEBUG, "%s: Type Answer   : %02X", __FUNCTION__, type);
3775 
3776   if (type != clientbuf[0])
3777     RTMP_Log(RTMP_LOGWARNING, "%s: Type mismatch: client sent %d, server answered %d",
3778 	__FUNCTION__, clientbuf[0], type);
3779 
3780   if (ReadN(r, serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
3781     return FALSE;
3782 
3783   /* decode server response */
3784 
3785   memcpy(&suptime, serversig, 4);
3786   suptime = ntohl(suptime);
3787 
3788   RTMP_Log(RTMP_LOGDEBUG, "%s: Server Uptime : %d", __FUNCTION__, suptime);
3789   RTMP_Log(RTMP_LOGDEBUG, "%s: FMS Version   : %d.%d.%d.%d", __FUNCTION__,
3790       serversig[4], serversig[5], serversig[6], serversig[7]);
3791 
3792   /* 2nd part of handshake */
3793   if (!WriteN(r, serversig, RTMP_SIG_SIZE))
3794     return FALSE;
3795 
3796   if (ReadN(r, serversig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
3797     return FALSE;
3798 
3799   bMatch = (memcmp(serversig, clientsig, RTMP_SIG_SIZE) == 0);
3800   if (!bMatch)
3801     {
3802       RTMP_Log(RTMP_LOGWARNING, "%s, client signature does not match!", __FUNCTION__);
3803     }
3804   return TRUE;
3805 }
3806 
3807 static int
SHandShake(RTMP * r)3808 SHandShake(RTMP *r)
3809 {
3810   int i;
3811   char serverbuf[RTMP_SIG_SIZE + 1], *serversig = serverbuf + 1;
3812   char clientsig[RTMP_SIG_SIZE];
3813   uint32_t uptime;
3814   int bMatch;
3815 
3816   if (ReadN(r, serverbuf, 1) != 1)	/* 0x03 or 0x06 */
3817     return FALSE;
3818 
3819   RTMP_Log(RTMP_LOGDEBUG, "%s: Type Request  : %02X", __FUNCTION__, serverbuf[0]);
3820 
3821   if (serverbuf[0] != 3)
3822     {
3823       RTMP_Log(RTMP_LOGERROR, "%s: Type unknown: client sent %02X",
3824 	  __FUNCTION__, serverbuf[0]);
3825       return FALSE;
3826     }
3827 
3828   uptime = htonl(RTMP_GetTime());
3829   memcpy(serversig, &uptime, 4);
3830 
3831   memset(&serversig[4], 0, 4);
3832 #ifdef _DEBUG
3833   for (i = 8; i < RTMP_SIG_SIZE; i++)
3834     serversig[i] = 0xff;
3835 #else
3836   for (i = 8; i < RTMP_SIG_SIZE; i++)
3837     serversig[i] = (char)(rand() % 256);
3838 #endif
3839 
3840   if (!WriteN(r, serverbuf, RTMP_SIG_SIZE + 1))
3841     return FALSE;
3842 
3843   if (ReadN(r, clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
3844     return FALSE;
3845 
3846   /* decode client response */
3847 
3848   memcpy(&uptime, clientsig, 4);
3849   uptime = ntohl(uptime);
3850 
3851   RTMP_Log(RTMP_LOGDEBUG, "%s: Client Uptime : %d", __FUNCTION__, uptime);
3852   RTMP_Log(RTMP_LOGDEBUG, "%s: Player Version: %d.%d.%d.%d", __FUNCTION__,
3853       clientsig[4], clientsig[5], clientsig[6], clientsig[7]);
3854 
3855   /* 2nd part of handshake */
3856   if (!WriteN(r, clientsig, RTMP_SIG_SIZE))
3857     return FALSE;
3858 
3859   if (ReadN(r, clientsig, RTMP_SIG_SIZE) != RTMP_SIG_SIZE)
3860     return FALSE;
3861 
3862   bMatch = (memcmp(serversig, clientsig, RTMP_SIG_SIZE) == 0);
3863   if (!bMatch)
3864     {
3865       RTMP_Log(RTMP_LOGWARNING, "%s, client signature does not match!", __FUNCTION__);
3866     }
3867   return TRUE;
3868 }
3869 #endif
3870 
3871 int
RTMP_SendChunk(RTMP * r,RTMPChunk * chunk)3872 RTMP_SendChunk(RTMP *r, RTMPChunk *chunk)
3873 {
3874   int wrote;
3875   char hbuf[RTMP_MAX_HEADER_SIZE];
3876 
3877   RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket,
3878       chunk->c_chunkSize);
3879   RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)chunk->c_header, chunk->c_headerSize);
3880   if (chunk->c_chunkSize)
3881     {
3882       char *ptr = chunk->c_chunk - chunk->c_headerSize;
3883       RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)chunk->c_chunk, chunk->c_chunkSize);
3884       /* save header bytes we're about to overwrite */
3885       memcpy(hbuf, ptr, chunk->c_headerSize);
3886       memcpy(ptr, chunk->c_header, chunk->c_headerSize);
3887       wrote = WriteN(r, ptr, chunk->c_headerSize + chunk->c_chunkSize);
3888       memcpy(ptr, hbuf, chunk->c_headerSize);
3889     }
3890   else
3891     wrote = WriteN(r, chunk->c_header, chunk->c_headerSize);
3892   return wrote;
3893 }
3894 
3895 int
RTMP_SendPacket(RTMP * r,RTMPPacket * packet,int queue)3896 RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue)
3897 {
3898   const RTMPPacket *prevPacket;
3899   uint32_t last = 0;
3900   int nSize;
3901   int hSize, cSize;
3902   char *header, *hptr, *hend, hbuf[RTMP_MAX_HEADER_SIZE], c;
3903   uint32_t t;
3904   char *buffer, *tbuf = NULL, *toff = NULL;
3905   int nChunkSize;
3906   int tlen;
3907 
3908   if (packet->m_nChannel >= r->m_channelsAllocatedOut)
3909     {
3910       int n = packet->m_nChannel + 10;
3911       RTMPPacket **packets = realloc(r->m_vecChannelsOut, sizeof(RTMPPacket*) * n);
3912       if (!packets) {
3913         free(r->m_vecChannelsOut);
3914         r->m_vecChannelsOut = NULL;
3915         r->m_channelsAllocatedOut = 0;
3916         return FALSE;
3917       }
3918       r->m_vecChannelsOut = packets;
3919       memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut));
3920       r->m_channelsAllocatedOut = n;
3921     }
3922 
3923   prevPacket = r->m_vecChannelsOut[packet->m_nChannel];
3924   if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE)
3925     {
3926       /* compress a bit by using the prev packet's attributes */
3927       if (prevPacket->m_nBodySize == packet->m_nBodySize
3928 	  && prevPacket->m_packetType == packet->m_packetType
3929 	  && packet->m_headerType == RTMP_PACKET_SIZE_MEDIUM)
3930 	packet->m_headerType = RTMP_PACKET_SIZE_SMALL;
3931 
3932       if (prevPacket->m_nTimeStamp == packet->m_nTimeStamp
3933 	  && packet->m_headerType == RTMP_PACKET_SIZE_SMALL)
3934 	packet->m_headerType = RTMP_PACKET_SIZE_MINIMUM;
3935       last = prevPacket->m_nTimeStamp;
3936     }
3937 
3938   if (packet->m_headerType > 3)	/* sanity */
3939     {
3940       RTMP_Log(RTMP_LOGERROR, "sanity failed!! trying to send header of type: 0x%02x.",
3941 	  (unsigned char)packet->m_headerType);
3942       return FALSE;
3943     }
3944 
3945   nSize = packetSize[packet->m_headerType];
3946   hSize = nSize; cSize = 0;
3947   t = packet->m_nTimeStamp - last;
3948 
3949   if (packet->m_body)
3950     {
3951       header = packet->m_body - nSize;
3952       hend = packet->m_body;
3953     }
3954   else
3955     {
3956       header = hbuf + 6;
3957       hend = hbuf + sizeof(hbuf);
3958     }
3959 
3960   if (packet->m_nChannel > 319)
3961     cSize = 2;
3962   else if (packet->m_nChannel > 63)
3963     cSize = 1;
3964   if (cSize)
3965     {
3966       header -= cSize;
3967       hSize += cSize;
3968     }
3969 
3970   if (t >= 0xffffff)
3971     {
3972       header -= 4;
3973       hSize += 4;
3974       RTMP_Log(RTMP_LOGWARNING, "Larger timestamp than 24-bit: 0x%x", t);
3975     }
3976 
3977   hptr = header;
3978   c = packet->m_headerType << 6;
3979   switch (cSize)
3980     {
3981     case 0:
3982       c |= packet->m_nChannel;
3983       break;
3984     case 1:
3985       break;
3986     case 2:
3987       c |= 1;
3988       break;
3989     }
3990   *hptr++ = c;
3991   if (cSize)
3992     {
3993       int tmp = packet->m_nChannel - 64;
3994       *hptr++ = tmp & 0xff;
3995       if (cSize == 2)
3996 	*hptr++ = tmp >> 8;
3997     }
3998 
3999   if (nSize > 1)
4000     {
4001       hptr = AMF_EncodeInt24(hptr, hend, t > 0xffffff ? 0xffffff : t);
4002     }
4003 
4004   if (nSize > 4)
4005     {
4006       hptr = AMF_EncodeInt24(hptr, hend, packet->m_nBodySize);
4007       *hptr++ = packet->m_packetType;
4008     }
4009 
4010   if (nSize > 8)
4011     hptr += EncodeInt32LE(hptr, packet->m_nInfoField2);
4012 
4013   if (t >= 0xffffff)
4014     hptr = AMF_EncodeInt32(hptr, hend, t);
4015 
4016   nSize = packet->m_nBodySize;
4017   buffer = packet->m_body;
4018   nChunkSize = r->m_outChunkSize;
4019 
4020   RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket,
4021       nSize);
4022   /* send all chunks in one HTTP request */
4023   if (r->Link.protocol & RTMP_FEATURE_HTTP)
4024     {
4025       int chunks = (nSize+nChunkSize-1) / nChunkSize;
4026       if (chunks > 1)
4027         {
4028 	  tlen = chunks * (cSize + 1) + nSize + hSize;
4029 	  tbuf = malloc(tlen);
4030 	  if (!tbuf)
4031 	    return FALSE;
4032 	  toff = tbuf;
4033 	}
4034     }
4035   while (nSize + hSize)
4036     {
4037       int wrote;
4038 
4039       if (nSize < nChunkSize)
4040 	nChunkSize = nSize;
4041 
4042       RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)header, hSize);
4043       RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)buffer, nChunkSize);
4044       if (tbuf)
4045         {
4046 	  memcpy(toff, header, nChunkSize + hSize);
4047 	  toff += nChunkSize + hSize;
4048 	}
4049       else
4050         {
4051 	  wrote = WriteN(r, header, nChunkSize + hSize);
4052 	  if (!wrote)
4053 	    return FALSE;
4054 	}
4055       nSize -= nChunkSize;
4056       buffer += nChunkSize;
4057       hSize = 0;
4058 
4059       if (nSize > 0)
4060 	{
4061 	  header = buffer - 1;
4062 	  hSize = 1;
4063 	  if (cSize)
4064 	    {
4065 	      header -= cSize;
4066 	      hSize += cSize;
4067 	    }
4068           if (t >= 0xffffff)
4069             {
4070               header -= 4;
4071               hSize += 4;
4072             }
4073 	  *header = (0xc0 | c);
4074 	  if (cSize)
4075 	    {
4076 	      int tmp = packet->m_nChannel - 64;
4077 	      header[1] = tmp & 0xff;
4078 	      if (cSize == 2)
4079 		header[2] = tmp >> 8;
4080 	    }
4081           if (t >= 0xffffff)
4082             {
4083               char* extendedTimestamp = header + 1 + cSize;
4084               AMF_EncodeInt32(extendedTimestamp, extendedTimestamp + 4, t);
4085             }
4086 	}
4087     }
4088   if (tbuf)
4089     {
4090       int wrote = WriteN(r, tbuf, toff-tbuf);
4091       free(tbuf);
4092       tbuf = NULL;
4093       if (!wrote)
4094         return FALSE;
4095     }
4096 
4097   /* we invoked a remote method */
4098   if (packet->m_packetType == RTMP_PACKET_TYPE_INVOKE)
4099     {
4100       AVal method;
4101       char *ptr;
4102       ptr = packet->m_body + 1;
4103       AMF_DecodeString(ptr, &method);
4104       RTMP_Log(RTMP_LOGDEBUG, "Invoking %s", method.av_val);
4105       /* keep it in call queue till result arrives */
4106       if (queue) {
4107         int txn;
4108         ptr += 3 + method.av_len;
4109         txn = (int)AMF_DecodeNumber(ptr);
4110 	AV_queue(&r->m_methodCalls, &r->m_numCalls, &method, txn);
4111       }
4112     }
4113 
4114   if (!r->m_vecChannelsOut[packet->m_nChannel])
4115     r->m_vecChannelsOut[packet->m_nChannel] = malloc(sizeof(RTMPPacket));
4116   memcpy(r->m_vecChannelsOut[packet->m_nChannel], packet, sizeof(RTMPPacket));
4117   return TRUE;
4118 }
4119 
4120 int
RTMP_Serve(RTMP * r)4121 RTMP_Serve(RTMP *r)
4122 {
4123   return SHandShake(r);
4124 }
4125 
4126 void
RTMP_Close(RTMP * r)4127 RTMP_Close(RTMP *r)
4128 {
4129   CloseInternal(r, 0);
4130 }
4131 
4132 static void
CloseInternal(RTMP * r,int reconnect)4133 CloseInternal(RTMP *r, int reconnect)
4134 {
4135   int i;
4136 
4137   if (RTMP_IsConnected(r))
4138     {
4139       if (r->m_stream_id > 0)
4140         {
4141 	  i = r->m_stream_id;
4142 	  r->m_stream_id = 0;
4143           if ((r->Link.protocol & RTMP_FEATURE_WRITE))
4144 	    SendFCUnpublish(r);
4145 	  SendDeleteStream(r, i);
4146 	}
4147       if (r->m_clientID.av_val)
4148         {
4149 	  HTTP_Post(r, RTMPT_CLOSE, "", 1);
4150 	  free(r->m_clientID.av_val);
4151 	  r->m_clientID.av_val = NULL;
4152 	  r->m_clientID.av_len = 0;
4153 	}
4154       RTMPSockBuf_Close(&r->m_sb);
4155     }
4156 
4157   r->m_stream_id = -1;
4158   r->m_sb.sb_socket = -1;
4159   r->m_nBWCheckCounter = 0;
4160   r->m_nBytesIn = 0;
4161   r->m_nBytesInSent = 0;
4162 
4163   if (r->m_read.flags & RTMP_READ_HEADER) {
4164     free(r->m_read.buf);
4165     r->m_read.buf = NULL;
4166   }
4167   r->m_read.dataType = 0;
4168   r->m_read.flags = 0;
4169   r->m_read.status = 0;
4170   r->m_read.nResumeTS = 0;
4171   r->m_read.nIgnoredFrameCounter = 0;
4172   r->m_read.nIgnoredFlvFrameCounter = 0;
4173 
4174   r->m_write.m_nBytesRead = 0;
4175   RTMPPacket_Free(&r->m_write);
4176 
4177   for (i = 0; i < r->m_channelsAllocatedIn; i++)
4178     {
4179       if (r->m_vecChannelsIn[i])
4180 	{
4181 	  RTMPPacket_Free(r->m_vecChannelsIn[i]);
4182 	  free(r->m_vecChannelsIn[i]);
4183 	  r->m_vecChannelsIn[i] = NULL;
4184 	}
4185     }
4186   free(r->m_vecChannelsIn);
4187   r->m_vecChannelsIn = NULL;
4188   free(r->m_channelTimestamp);
4189   r->m_channelTimestamp = NULL;
4190   r->m_channelsAllocatedIn = 0;
4191   for (i = 0; i < r->m_channelsAllocatedOut; i++)
4192     {
4193       if (r->m_vecChannelsOut[i])
4194 	{
4195 	  free(r->m_vecChannelsOut[i]);
4196 	  r->m_vecChannelsOut[i] = NULL;
4197 	}
4198     }
4199   free(r->m_vecChannelsOut);
4200   r->m_vecChannelsOut = NULL;
4201   r->m_channelsAllocatedOut = 0;
4202   AV_clear(r->m_methodCalls, r->m_numCalls);
4203   r->m_methodCalls = NULL;
4204   r->m_numCalls = 0;
4205   r->m_numInvokes = 0;
4206 
4207   r->m_bPlaying = FALSE;
4208   r->m_sb.sb_size = 0;
4209 
4210   r->m_msgCounter = 0;
4211   r->m_resplen = 0;
4212   r->m_unackd = 0;
4213 
4214   if (r->Link.lFlags & RTMP_LF_FTCU && !reconnect)
4215     {
4216       free(r->Link.tcUrl.av_val);
4217       r->Link.tcUrl.av_val = NULL;
4218       r->Link.lFlags ^= RTMP_LF_FTCU;
4219     }
4220   if (r->Link.lFlags & RTMP_LF_FAPU && !reconnect)
4221     {
4222       free(r->Link.app.av_val);
4223       r->Link.app.av_val = NULL;
4224       r->Link.lFlags ^= RTMP_LF_FAPU;
4225     }
4226 
4227   if (!reconnect)
4228     {
4229       free(r->Link.playpath0.av_val);
4230       r->Link.playpath0.av_val = NULL;
4231     }
4232 #ifdef CRYPTO
4233   if (r->Link.dh)
4234     {
4235       MDH_free(r->Link.dh);
4236       r->Link.dh = NULL;
4237     }
4238   if (r->Link.rc4keyIn)
4239     {
4240       RC4_free(r->Link.rc4keyIn);
4241       r->Link.rc4keyIn = NULL;
4242     }
4243   if (r->Link.rc4keyOut)
4244     {
4245       RC4_free(r->Link.rc4keyOut);
4246       r->Link.rc4keyOut = NULL;
4247     }
4248 #endif
4249 }
4250 
4251 int
RTMPSockBuf_Fill(RTMPSockBuf * sb)4252 RTMPSockBuf_Fill(RTMPSockBuf *sb)
4253 {
4254   int nBytes;
4255 
4256   if (!sb->sb_size)
4257     sb->sb_start = sb->sb_buf;
4258 
4259   while (1)
4260     {
4261       nBytes = sizeof(sb->sb_buf) - 1 - sb->sb_size - (sb->sb_start - sb->sb_buf);
4262 #if defined(CRYPTO) && !defined(NO_SSL)
4263       if (sb->sb_ssl)
4264 	{
4265 	  nBytes = TLS_read(sb->sb_ssl, sb->sb_start + sb->sb_size, nBytes);
4266 	}
4267       else
4268 #endif
4269 	{
4270 	  nBytes = recv(sb->sb_socket, sb->sb_start + sb->sb_size, nBytes, 0);
4271 	}
4272       if (nBytes != -1)
4273 	{
4274 	  sb->sb_size += nBytes;
4275 	}
4276       else
4277 	{
4278 	  int sockerr = GetSockError();
4279 	  RTMP_Log(RTMP_LOGDEBUG, "%s, recv returned %d. GetSockError(): %d (%s)",
4280 	      __FUNCTION__, nBytes, sockerr, strerror(sockerr));
4281 	  if (sockerr == EINTR && !RTMP_ctrlC)
4282 	    continue;
4283 
4284 	  if (sockerr == EWOULDBLOCK || sockerr == EAGAIN)
4285 	    {
4286 	      sb->sb_timedout = TRUE;
4287 	      nBytes = 0;
4288 	    }
4289 	}
4290       break;
4291     }
4292 
4293   return nBytes;
4294 }
4295 
4296 int
RTMPSockBuf_Send(RTMPSockBuf * sb,const char * buf,int len)4297 RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int len)
4298 {
4299   int rc;
4300 
4301 #ifdef _DEBUG
4302   fwrite(buf, 1, len, netstackdump);
4303 #endif
4304 
4305 #if defined(CRYPTO) && !defined(NO_SSL)
4306   if (sb->sb_ssl)
4307     {
4308       rc = TLS_write(sb->sb_ssl, buf, len);
4309     }
4310   else
4311 #endif
4312     {
4313       rc = send(sb->sb_socket, buf, len, 0);
4314     }
4315   return rc;
4316 }
4317 
4318 int
RTMPSockBuf_Close(RTMPSockBuf * sb)4319 RTMPSockBuf_Close(RTMPSockBuf *sb)
4320 {
4321 #if defined(CRYPTO) && !defined(NO_SSL)
4322   if (sb->sb_ssl)
4323     {
4324       TLS_shutdown(sb->sb_ssl);
4325       TLS_close(sb->sb_ssl);
4326       sb->sb_ssl = NULL;
4327     }
4328 #endif
4329   if (sb->sb_socket != -1)
4330       return closesocket(sb->sb_socket);
4331   return 0;
4332 }
4333 
4334 #define HEX2BIN(a)	(((a)&0x40)?((a)&0xf)+9:((a)&0xf))
4335 
4336 static void
DecodeTEA(AVal * key,AVal * text)4337 DecodeTEA(AVal *key, AVal *text)
4338 {
4339   uint32_t *v, k[4] = { 0 }, u;
4340   uint32_t z, y, sum = 0, e, DELTA = 0x9e3779b9;
4341   int32_t p, q;
4342   int i, n;
4343   unsigned char *ptr, *out;
4344 
4345   /* prep key: pack 1st 16 chars into 4 LittleEndian ints */
4346   ptr = (unsigned char *)key->av_val;
4347   u = 0;
4348   n = 0;
4349   v = k;
4350   p = key->av_len > 16 ? 16 : key->av_len;
4351   for (i = 0; i < p; i++)
4352     {
4353       u |= ptr[i] << (n * 8);
4354       if (n == 3)
4355 	{
4356 	  *v++ = u;
4357 	  u = 0;
4358 	  n = 0;
4359 	}
4360       else
4361 	{
4362 	  n++;
4363 	}
4364     }
4365   /* any trailing chars */
4366   if (u)
4367     *v = u;
4368 
4369   /* prep text: hex2bin, multiples of 4 */
4370   n = (text->av_len + 7) / 8;
4371   out = malloc(n * 8);
4372   ptr = (unsigned char *)text->av_val;
4373   v = (uint32_t *) out;
4374   for (i = 0; i < n; i++)
4375     {
4376       u = (HEX2BIN(ptr[0]) << 4) + HEX2BIN(ptr[1]);
4377       u |= ((HEX2BIN(ptr[2]) << 4) + HEX2BIN(ptr[3])) << 8;
4378       u |= ((HEX2BIN(ptr[4]) << 4) + HEX2BIN(ptr[5])) << 16;
4379       u |= ((HEX2BIN(ptr[6]) << 4) + HEX2BIN(ptr[7])) << 24;
4380       *v++ = u;
4381       ptr += 8;
4382     }
4383   v = (uint32_t *) out;
4384 
4385   /* http://www.movable-type.co.uk/scripts/tea-block.html */
4386 #define MX (((z>>5)^(y<<2)) + ((y>>3)^(z<<4))) ^ ((sum^y) + (k[(p&3)^e]^z));
4387   z = v[n - 1];
4388   y = v[0];
4389   q = 6 + 52 / n;
4390   sum = q * DELTA;
4391   while (sum != 0)
4392     {
4393       e = sum >> 2 & 3;
4394       for (p = n - 1; p > 0; p--)
4395 	z = v[p - 1], y = v[p] -= MX;
4396       z = v[n - 1];
4397       y = v[0] -= MX;
4398       sum -= DELTA;
4399     }
4400 
4401   text->av_len /= 2;
4402   memcpy(text->av_val, out, text->av_len);
4403   free(out);
4404 }
4405 
4406 static int
HTTP_Post(RTMP * r,RTMPTCmd cmd,const char * buf,int len)4407 HTTP_Post(RTMP *r, RTMPTCmd cmd, const char *buf, int len)
4408 {
4409   char hbuf[512];
4410   int hlen = snprintf(hbuf, sizeof(hbuf), "POST /%s%s/%d HTTP/1.1\r\n"
4411     "Host: %.*s:%d\r\n"
4412     "Accept: */*\r\n"
4413     "User-Agent: Shockwave Flash\r\n"
4414     "Connection: Keep-Alive\r\n"
4415     "Cache-Control: no-cache\r\n"
4416     "Content-type: application/x-fcs\r\n"
4417     "Content-length: %d\r\n\r\n", RTMPT_cmds[cmd],
4418     r->m_clientID.av_val ? r->m_clientID.av_val : "",
4419     r->m_msgCounter, r->Link.hostname.av_len, r->Link.hostname.av_val,
4420     r->Link.port, len);
4421   RTMPSockBuf_Send(&r->m_sb, hbuf, hlen);
4422   hlen = RTMPSockBuf_Send(&r->m_sb, buf, len);
4423   r->m_msgCounter++;
4424   r->m_unackd++;
4425   return hlen;
4426 }
4427 
4428 static int
HTTP_read(RTMP * r,int fill)4429 HTTP_read(RTMP *r, int fill)
4430 {
4431   char *ptr;
4432   long hlen;
4433 
4434 restart:
4435   if (fill)
4436     RTMPSockBuf_Fill(&r->m_sb);
4437   if (r->m_sb.sb_size < 13) {
4438     if (fill)
4439       goto restart;
4440     return -2;
4441   }
4442   if (strncmp(r->m_sb.sb_start, "HTTP/1.1 200 ", 13))
4443     return -1;
4444   r->m_sb.sb_start[r->m_sb.sb_size] = '\0';
4445   if (!strstr(r->m_sb.sb_start, "\r\n\r\n")) {
4446     if (fill)
4447       goto restart;
4448     return -2;
4449   }
4450 
4451   ptr = r->m_sb.sb_start + sizeof("HTTP/1.1 200");
4452   while ((ptr = strstr(ptr, "Content-"))) {
4453     if (!strncasecmp(ptr+8, "length:", 7)) break;
4454     ptr += 8;
4455   }
4456   if (!ptr)
4457     return -1;
4458   hlen = strtol(ptr+16, NULL, 10);
4459   if (hlen < 1 || hlen > INT_MAX)
4460     return -1;
4461   ptr = strstr(ptr+16, "\r\n\r\n");
4462   if (!ptr)
4463     return -1;
4464   ptr += 4;
4465   if (ptr + (r->m_clientID.av_val ? 1 : hlen) > r->m_sb.sb_start + r->m_sb.sb_size)
4466     {
4467       if (fill)
4468         goto restart;
4469       return -2;
4470     }
4471   r->m_sb.sb_size -= ptr - r->m_sb.sb_start;
4472   r->m_sb.sb_start = ptr;
4473   r->m_unackd--;
4474 
4475   if (!r->m_clientID.av_val)
4476     {
4477       r->m_clientID.av_len = hlen;
4478       r->m_clientID.av_val = malloc(hlen+1);
4479       if (!r->m_clientID.av_val)
4480         return -1;
4481       r->m_clientID.av_val[0] = '/';
4482       memcpy(r->m_clientID.av_val+1, ptr, hlen-1);
4483       r->m_clientID.av_val[hlen] = 0;
4484       r->m_sb.sb_size = 0;
4485     }
4486   else
4487     {
4488       r->m_polling = *ptr++;
4489       r->m_resplen = hlen - 1;
4490       r->m_sb.sb_start++;
4491       r->m_sb.sb_size--;
4492     }
4493   return 0;
4494 }
4495 
4496 #define MAX_IGNORED_FRAMES	50
4497 
4498 /* Read from the stream until we get a media packet.
4499  * Returns -3 if Play.Close/Stop, -2 if fatal error, -1 if no more media
4500  * packets, 0 if ignorable error, >0 if there is a media packet
4501  */
4502 static int
Read_1_Packet(RTMP * r,char * buf,unsigned int buflen)4503 Read_1_Packet(RTMP *r, char *buf, unsigned int buflen)
4504 {
4505   uint32_t prevTagSize = 0;
4506   int rtnGetNextMediaPacket = 0, ret = RTMP_READ_EOF;
4507   RTMPPacket packet = { 0 };
4508   int recopy = FALSE;
4509   unsigned int size;
4510   char *ptr, *pend;
4511   uint32_t nTimeStamp = 0;
4512   unsigned int len;
4513 
4514   rtnGetNextMediaPacket = RTMP_GetNextMediaPacket(r, &packet);
4515   while (rtnGetNextMediaPacket)
4516     {
4517       char *packetBody = packet.m_body;
4518       unsigned int nPacketLen = packet.m_nBodySize;
4519 
4520       /* Return RTMP_READ_COMPLETE if this was completed nicely with
4521        * invoke message Play.Stop or Play.Complete
4522        */
4523       if (rtnGetNextMediaPacket == 2)
4524 	{
4525 	  RTMP_Log(RTMP_LOGDEBUG,
4526 	      "Got Play.Complete or Play.Stop from server. "
4527 	      "Assuming stream is complete");
4528 	  ret = RTMP_READ_COMPLETE;
4529 	  break;
4530 	}
4531 
4532       r->m_read.dataType |= (((packet.m_packetType == RTMP_PACKET_TYPE_AUDIO) << 2) |
4533 			     (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO));
4534 
4535       if (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO && nPacketLen <= 5)
4536 	{
4537 	  RTMP_Log(RTMP_LOGDEBUG, "ignoring too small video packet: size: %d",
4538 	      nPacketLen);
4539 	  ret = RTMP_READ_IGNORE;
4540 	  break;
4541 	}
4542       if (packet.m_packetType == RTMP_PACKET_TYPE_AUDIO && nPacketLen <= 1)
4543 	{
4544 	  RTMP_Log(RTMP_LOGDEBUG, "ignoring too small audio packet: size: %d",
4545 	      nPacketLen);
4546 	  ret = RTMP_READ_IGNORE;
4547 	  break;
4548 	}
4549 
4550       if (r->m_read.flags & RTMP_READ_SEEKING)
4551 	{
4552 	  ret = RTMP_READ_IGNORE;
4553 	  break;
4554 	}
4555 #ifdef _DEBUG
4556       RTMP_Log(RTMP_LOGDEBUG, "type: %02X, size: %d, TS: %d ms, abs TS: %d",
4557 	  packet.m_packetType, nPacketLen, packet.m_nTimeStamp,
4558 	  packet.m_hasAbsTimestamp);
4559       if (packet.m_packetType == RTMP_PACKET_TYPE_VIDEO)
4560 	RTMP_Log(RTMP_LOGDEBUG, "frametype: %02X", (*packetBody & 0xf0));
4561 #endif
4562 
4563       if (r->m_read.flags & RTMP_READ_RESUME)
4564 	{
4565 	  /* check the header if we get one */
4566 	  if (packet.m_nTimeStamp == 0)
4567 	    {
4568 	      if (r->m_read.nMetaHeaderSize > 0
4569 		  && packet.m_packetType == RTMP_PACKET_TYPE_INFO)
4570 		{
4571 		  AMFObject metaObj;
4572 		  int nRes =
4573 		    AMF_Decode(&metaObj, packetBody, nPacketLen, FALSE);
4574 		  if (nRes >= 0)
4575 		    {
4576 		      AVal metastring;
4577 		      AMFProp_GetString(AMF_GetProp(&metaObj, NULL, 0),
4578 					&metastring);
4579 
4580 		      if (AVMATCH(&metastring, &av_onMetaData))
4581 			{
4582 			  /* compare */
4583 			  if ((r->m_read.nMetaHeaderSize != nPacketLen) ||
4584 			      (memcmp
4585 			       (r->m_read.metaHeader, packetBody,
4586 				r->m_read.nMetaHeaderSize) != 0))
4587 			    {
4588 			      ret = RTMP_READ_ERROR;
4589 			    }
4590 			}
4591 		      AMF_Reset(&metaObj);
4592 		      if (ret == RTMP_READ_ERROR)
4593 			break;
4594 		    }
4595 		}
4596 
4597 	      /* check first keyframe to make sure we got the right position
4598 	       * in the stream! (the first non ignored frame)
4599 	       */
4600 	      if (r->m_read.nInitialFrameSize > 0)
4601 		{
4602 		  /* video or audio data */
4603 		  if (packet.m_packetType == r->m_read.initialFrameType
4604 		      && r->m_read.nInitialFrameSize == nPacketLen)
4605 		    {
4606 		      /* we don't compare the sizes since the packet can
4607 		       * contain several FLV packets, just make sure the
4608 		       * first frame is our keyframe (which we are going
4609 		       * to rewrite)
4610 		       */
4611 		      if (memcmp
4612 			  (r->m_read.initialFrame, packetBody,
4613 			   r->m_read.nInitialFrameSize) == 0)
4614 			{
4615 			  RTMP_Log(RTMP_LOGDEBUG, "Checked keyframe successfully!");
4616 			  r->m_read.flags |= RTMP_READ_GOTKF;
4617 			  /* ignore it! (what about audio data after it? it is
4618 			   * handled by ignoring all 0ms frames, see below)
4619 			   */
4620 			  ret = RTMP_READ_IGNORE;
4621 			  break;
4622 			}
4623 		    }
4624 
4625 		  /* hande FLV streams, even though the server resends the
4626 		   * keyframe as an extra video packet it is also included
4627 		   * in the first FLV stream chunk and we have to compare
4628 		   * it and filter it out !!
4629 		   */
4630 		  if (packet.m_packetType == RTMP_PACKET_TYPE_FLASH_VIDEO)
4631 		    {
4632 		      /* basically we have to find the keyframe with the
4633 		       * correct TS being nResumeTS
4634 		       */
4635 		      unsigned int pos = 0;
4636 		      uint32_t ts = 0;
4637 
4638 		      while (pos + 11 < nPacketLen)
4639 			{
4640 			  /* size without header (11) and prevTagSize (4) */
4641 			  uint32_t dataSize =
4642 			    AMF_DecodeInt24(packetBody + pos + 1);
4643 			  ts = AMF_DecodeInt24(packetBody + pos + 4);
4644 			  ts |= (packetBody[pos + 7] << 24);
4645 
4646 #ifdef _DEBUG
4647 			  RTMP_Log(RTMP_LOGDEBUG,
4648 			      "keyframe search: FLV Packet: type %02X, dataSize: %d, timeStamp: %d ms",
4649 			      packetBody[pos], dataSize, ts);
4650 #endif
4651 			  /* ok, is it a keyframe?:
4652 			   * well doesn't work for audio!
4653 			   */
4654 			  if (packetBody[pos /*6928, test 0 */ ] ==
4655 			      r->m_read.initialFrameType
4656 			      /* && (packetBody[11]&0xf0) == 0x10 */ )
4657 			    {
4658 			      if (ts == r->m_read.nResumeTS)
4659 				{
4660 				  RTMP_Log(RTMP_LOGDEBUG,
4661 				      "Found keyframe with resume-keyframe timestamp!");
4662 				  if (r->m_read.nInitialFrameSize != dataSize
4663 				      || memcmp(r->m_read.initialFrame,
4664 						packetBody + pos + 11,
4665 						r->m_read.
4666 						nInitialFrameSize) != 0)
4667 				    {
4668 				      RTMP_Log(RTMP_LOGERROR,
4669 					  "FLV Stream: Keyframe doesn't match!");
4670 				      ret = RTMP_READ_ERROR;
4671 				      break;
4672 				    }
4673 				  r->m_read.flags |= RTMP_READ_GOTFLVK;
4674 
4675 				  /* skip this packet?
4676 				   * check whether skippable:
4677 				   */
4678 				  if (pos + 11 + dataSize + 4 > nPacketLen)
4679 				    {
4680 				      RTMP_Log(RTMP_LOGWARNING,
4681 					  "Non skipable packet since it doesn't end with chunk, stream corrupt!");
4682 				      ret = RTMP_READ_ERROR;
4683 				      break;
4684 				    }
4685 				  packetBody += (pos + 11 + dataSize + 4);
4686 				  nPacketLen -= (pos + 11 + dataSize + 4);
4687 
4688 				  goto stopKeyframeSearch;
4689 
4690 				}
4691 			      else if (r->m_read.nResumeTS < ts)
4692 				{
4693 				  /* the timestamp ts will only increase with
4694 				   * further packets, wait for seek
4695 				   */
4696 				  goto stopKeyframeSearch;
4697 				}
4698 			    }
4699 			  pos += (11 + dataSize + 4);
4700 			}
4701 		      if (ts < r->m_read.nResumeTS)
4702 			{
4703 			  RTMP_Log(RTMP_LOGERROR,
4704 			      "First packet does not contain keyframe, all "
4705 			      "timestamps are smaller than the keyframe "
4706 			      "timestamp; probably the resume seek failed?");
4707 			}
4708 		    stopKeyframeSearch:
4709 		      ;
4710 		      if (!(r->m_read.flags & RTMP_READ_GOTFLVK))
4711 			{
4712 			  RTMP_Log(RTMP_LOGERROR,
4713 			      "Couldn't find the seeked keyframe in this chunk!");
4714 			  ret = RTMP_READ_IGNORE;
4715 			  break;
4716 			}
4717 		    }
4718 		}
4719 	    }
4720 
4721 	  if (packet.m_nTimeStamp > 0
4722 	      && (r->m_read.flags & (RTMP_READ_GOTKF|RTMP_READ_GOTFLVK)))
4723 	    {
4724 	      /* another problem is that the server can actually change from
4725 	       * 09/08 video/audio packets to an FLV stream or vice versa and
4726 	       * our keyframe check will prevent us from going along with the
4727 	       * new stream if we resumed.
4728 	       *
4729 	       * in this case set the 'found keyframe' variables to true.
4730 	       * We assume that if we found one keyframe somewhere and were
4731 	       * already beyond TS > 0 we have written data to the output
4732 	       * which means we can accept all forthcoming data including the
4733 	       * change between 08/09 <-> FLV packets
4734 	       */
4735 	      r->m_read.flags |= (RTMP_READ_GOTKF|RTMP_READ_GOTFLVK);
4736 	    }
4737 
4738 	  /* skip till we find our keyframe
4739 	   * (seeking might put us somewhere before it)
4740 	   */
4741 	  if (!(r->m_read.flags & RTMP_READ_GOTKF) &&
4742 	  	packet.m_packetType != RTMP_PACKET_TYPE_FLASH_VIDEO)
4743 	    {
4744 	      RTMP_Log(RTMP_LOGWARNING,
4745 		  "Stream does not start with requested frame, ignoring data... ");
4746 	      r->m_read.nIgnoredFrameCounter++;
4747 	      if (r->m_read.nIgnoredFrameCounter > MAX_IGNORED_FRAMES)
4748 		ret = RTMP_READ_ERROR;	/* fatal error, couldn't continue stream */
4749 	      else
4750 		ret = RTMP_READ_IGNORE;
4751 	      break;
4752 	    }
4753 	  /* ok, do the same for FLV streams */
4754 	  if (!(r->m_read.flags & RTMP_READ_GOTFLVK) &&
4755 	  	packet.m_packetType == RTMP_PACKET_TYPE_FLASH_VIDEO)
4756 	    {
4757 	      RTMP_Log(RTMP_LOGWARNING,
4758 		  "Stream does not start with requested FLV frame, ignoring data... ");
4759 	      r->m_read.nIgnoredFlvFrameCounter++;
4760 	      if (r->m_read.nIgnoredFlvFrameCounter > MAX_IGNORED_FRAMES)
4761 		ret = RTMP_READ_ERROR;
4762 	      else
4763 		ret = RTMP_READ_IGNORE;
4764 	      break;
4765 	    }
4766 
4767 	  /* we have to ignore the 0ms frames since these are the first
4768 	   * keyframes; we've got these so don't mess around with multiple
4769 	   * copies sent by the server to us! (if the keyframe is found at a
4770 	   * later position there is only one copy and it will be ignored by
4771 	   * the preceding if clause)
4772 	   */
4773 	  if (!(r->m_read.flags & RTMP_READ_NO_IGNORE) &&
4774 	  	packet.m_packetType != RTMP_PACKET_TYPE_FLASH_VIDEO)
4775 	    {
4776               /* exclude type RTMP_PACKET_TYPE_FLASH_VIDEO since it can
4777                * contain several FLV packets
4778                */
4779 	      if (packet.m_nTimeStamp == 0)
4780 		{
4781 		  ret = RTMP_READ_IGNORE;
4782 		  break;
4783 		}
4784 	      else
4785 		{
4786 		  /* stop ignoring packets */
4787 		  r->m_read.flags |= RTMP_READ_NO_IGNORE;
4788 		}
4789 	    }
4790 	}
4791 
4792       /* calculate packet size and allocate slop buffer if necessary */
4793       size = nPacketLen +
4794 	((packet.m_packetType == RTMP_PACKET_TYPE_AUDIO
4795           || packet.m_packetType == RTMP_PACKET_TYPE_VIDEO
4796 	  || packet.m_packetType == RTMP_PACKET_TYPE_INFO) ? 11 : 0) +
4797 	(packet.m_packetType != RTMP_PACKET_TYPE_FLASH_VIDEO ? 4 : 0);
4798 
4799       if (size + 4 > buflen)
4800 	{
4801 	  /* the extra 4 is for the case of an FLV stream without a last
4802 	   * prevTagSize (we need extra 4 bytes to append it) */
4803 	  r->m_read.buf = malloc(size + 4);
4804 	  if (r->m_read.buf == 0)
4805 	    {
4806 	      RTMP_Log(RTMP_LOGERROR, "Couldn't allocate memory!");
4807 	      ret = RTMP_READ_ERROR;		/* fatal error */
4808 	      break;
4809 	    }
4810 	  recopy = TRUE;
4811 	  ptr = r->m_read.buf;
4812 	}
4813       else
4814 	{
4815 	  ptr = buf;
4816 	}
4817       pend = ptr + size + 4;
4818 
4819       /* use to return timestamp of last processed packet */
4820 
4821       /* audio (0x08), video (0x09) or metadata (0x12) packets :
4822        * construct 11 byte header then add rtmp packet's data */
4823       if (packet.m_packetType == RTMP_PACKET_TYPE_AUDIO
4824           || packet.m_packetType == RTMP_PACKET_TYPE_VIDEO
4825 	  || packet.m_packetType == RTMP_PACKET_TYPE_INFO)
4826 	{
4827 	  nTimeStamp = r->m_read.nResumeTS + packet.m_nTimeStamp;
4828 	  prevTagSize = 11 + nPacketLen;
4829 
4830 	  *ptr = packet.m_packetType;
4831 	  ptr++;
4832 	  ptr = AMF_EncodeInt24(ptr, pend, nPacketLen);
4833 
4834 #if 0
4835 	    if(packet.m_packetType == RTMP_PACKET_TYPE_VIDEO) {
4836 
4837 	     /* H264 fix: */
4838 	     if((packetBody[0] & 0x0f) == 7) { /* CodecId = H264 */
4839 	     uint8_t packetType = *(packetBody+1);
4840 
4841 	     uint32_t ts = AMF_DecodeInt24(packetBody+2); /* composition time */
4842 	     int32_t cts = (ts+0xff800000)^0xff800000;
4843 	     RTMP_Log(RTMP_LOGDEBUG, "cts  : %d\n", cts);
4844 
4845 	     nTimeStamp -= cts;
4846 	     /* get rid of the composition time */
4847 	     CRTMP::EncodeInt24(packetBody+2, 0);
4848 	     }
4849 	     RTMP_Log(RTMP_LOGDEBUG, "VIDEO: nTimeStamp: 0x%08X (%d)\n", nTimeStamp, nTimeStamp);
4850 	     }
4851 #endif
4852 
4853 	  ptr = AMF_EncodeInt24(ptr, pend, nTimeStamp);
4854 	  *ptr = (char)((nTimeStamp & 0xFF000000) >> 24);
4855 	  ptr++;
4856 
4857 	  /* stream id */
4858 	  ptr = AMF_EncodeInt24(ptr, pend, 0);
4859 	}
4860 
4861       memcpy(ptr, packetBody, nPacketLen);
4862       len = nPacketLen;
4863 
4864       /* correct tagSize and obtain timestamp if we have an FLV stream */
4865       if (packet.m_packetType == RTMP_PACKET_TYPE_FLASH_VIDEO)
4866 	{
4867 	  unsigned int pos = 0;
4868 	  int delta;
4869 
4870 	  /* grab first timestamp and see if it needs fixing */
4871 	  nTimeStamp = AMF_DecodeInt24(packetBody + 4);
4872 	  nTimeStamp |= (packetBody[7] << 24);
4873 	  delta = packet.m_nTimeStamp - nTimeStamp + r->m_read.nResumeTS;
4874 
4875 	  while (pos + 11 < nPacketLen)
4876 	    {
4877 	      /* size without header (11) and without prevTagSize (4) */
4878 	      uint32_t dataSize = AMF_DecodeInt24(packetBody + pos + 1);
4879 	      nTimeStamp = AMF_DecodeInt24(packetBody + pos + 4);
4880 	      nTimeStamp |= (packetBody[pos + 7] << 24);
4881 
4882 	      if (delta)
4883 		{
4884 		  nTimeStamp += delta;
4885 		  AMF_EncodeInt24(ptr+pos+4, pend, nTimeStamp);
4886 		  ptr[pos+7] = nTimeStamp>>24;
4887 		}
4888 
4889 	      /* set data type */
4890 	      r->m_read.dataType |= (((*(packetBody + pos) == 0x08) << 2) |
4891 				     (*(packetBody + pos) == 0x09));
4892 
4893 	      if (pos + 11 + dataSize + 4 > nPacketLen)
4894 		{
4895 		  if (pos + 11 + dataSize > nPacketLen)
4896 		    {
4897 		      RTMP_Log(RTMP_LOGERROR,
4898 			  "Wrong data size (%u), stream corrupted, aborting!",
4899 			  dataSize);
4900 		      ret = RTMP_READ_ERROR;
4901 		      break;
4902 		    }
4903 		  RTMP_Log(RTMP_LOGWARNING, "No tagSize found, appending!");
4904 
4905 		  /* we have to append a last tagSize! */
4906 		  prevTagSize = dataSize + 11;
4907 		  AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend,
4908 				  prevTagSize);
4909 		  size += 4;
4910 		  len += 4;
4911 		}
4912 	      else
4913 		{
4914 		  prevTagSize =
4915 		    AMF_DecodeInt32(packetBody + pos + 11 + dataSize);
4916 
4917 #ifdef _DEBUG
4918 		  RTMP_Log(RTMP_LOGDEBUG,
4919 		      "FLV Packet: type %02X, dataSize: %lu, tagSize: %lu, timeStamp: %lu ms",
4920 		      (unsigned char)packetBody[pos], dataSize, prevTagSize,
4921 		      nTimeStamp);
4922 #endif
4923 
4924 		  if (prevTagSize != (dataSize + 11))
4925 		    {
4926 #ifdef _DEBUG
4927 		      RTMP_Log(RTMP_LOGWARNING,
4928 			  "Tag and data size are not consitent, writing tag size according to dataSize+11: %d",
4929 			  dataSize + 11);
4930 #endif
4931 
4932 		      prevTagSize = dataSize + 11;
4933 		      AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend,
4934 				      prevTagSize);
4935 		    }
4936 		}
4937 
4938 	      pos += prevTagSize + 4;	/*(11+dataSize+4); */
4939 	    }
4940 	}
4941       ptr += len;
4942 
4943       if (packet.m_packetType != RTMP_PACKET_TYPE_FLASH_VIDEO)
4944 	{
4945 	  /* FLV tag packets contain their own prevTagSize */
4946 	  AMF_EncodeInt32(ptr, pend, prevTagSize);
4947 	}
4948 
4949       /* In non-live this nTimeStamp can contain an absolute TS.
4950        * Update ext timestamp with this absolute offset in non-live mode
4951        * otherwise report the relative one
4952        */
4953       /* RTMP_Log(RTMP_LOGDEBUG, "type: %02X, size: %d, pktTS: %dms, TS: %dms, bLiveStream: %d", packet.m_packetType, nPacketLen, packet.m_nTimeStamp, nTimeStamp, r->Link.lFlags & RTMP_LF_LIVE); */
4954       r->m_read.timestamp = (r->Link.lFlags & RTMP_LF_LIVE) ? packet.m_nTimeStamp : nTimeStamp;
4955 
4956       ret = size;
4957       break;
4958     }
4959 
4960   if (rtnGetNextMediaPacket)
4961     RTMPPacket_Free(&packet);
4962 
4963   if (recopy)
4964     {
4965       len = ret > buflen ? buflen : ret;
4966       memcpy(buf, r->m_read.buf, len);
4967       r->m_read.bufpos = r->m_read.buf + len;
4968       r->m_read.buflen = ret - len;
4969     }
4970   return ret;
4971 }
4972 
4973 static const char flvHeader[] = { 'F', 'L', 'V', 0x01,
4974   0x00,				/* 0x04 == audio, 0x01 == video */
4975   0x00, 0x00, 0x00, 0x09,
4976   0x00, 0x00, 0x00, 0x00
4977 };
4978 
4979 #define HEADERBUF	(128*1024)
4980 int
RTMP_Read(RTMP * r,char * buf,int size)4981 RTMP_Read(RTMP *r, char *buf, int size)
4982 {
4983   int nRead = 0, total = 0;
4984 
4985   /* can't continue */
4986 fail:
4987   switch (r->m_read.status) {
4988   case RTMP_READ_EOF:
4989   case RTMP_READ_COMPLETE:
4990     return 0;
4991   case RTMP_READ_ERROR:  /* corrupted stream, resume failed */
4992     SetSockError(EINVAL);
4993     return -1;
4994   default:
4995     break;
4996   }
4997 
4998   /* first time thru */
4999   if (!(r->m_read.flags & RTMP_READ_HEADER))
5000     {
5001       if (!(r->m_read.flags & RTMP_READ_RESUME))
5002 	{
5003 	  char *mybuf = malloc(HEADERBUF), *end = mybuf + HEADERBUF;
5004 	  int cnt = 0;
5005 	  r->m_read.buf = mybuf;
5006 	  r->m_read.buflen = HEADERBUF;
5007 
5008 	  memcpy(mybuf, flvHeader, sizeof(flvHeader));
5009 	  r->m_read.buf += sizeof(flvHeader);
5010 	  r->m_read.buflen -= sizeof(flvHeader);
5011 	  cnt += sizeof(flvHeader);
5012 
5013 	  while (r->m_read.timestamp == 0)
5014 	    {
5015 	      nRead = Read_1_Packet(r, r->m_read.buf, r->m_read.buflen);
5016 	      if (nRead < 0)
5017 		{
5018 		  free(mybuf);
5019 		  r->m_read.buf = NULL;
5020 		  r->m_read.buflen = 0;
5021 		  r->m_read.status = nRead;
5022 		  goto fail;
5023 		}
5024 	      /* buffer overflow, fix buffer and give up */
5025 	      if (r->m_read.buf < mybuf || r->m_read.buf > end) {
5026 	      	mybuf = realloc(mybuf, cnt + nRead);
5027 		memcpy(mybuf+cnt, r->m_read.buf, nRead);
5028 		free(r->m_read.buf);
5029 		r->m_read.buf = mybuf+cnt+nRead;
5030 	        break;
5031 	      }
5032 	      cnt += nRead;
5033 	      r->m_read.buf += nRead;
5034 	      r->m_read.buflen -= nRead;
5035 	      if (r->m_read.dataType == 5)
5036 	        break;
5037 	    }
5038 	  mybuf[4] = r->m_read.dataType;
5039 	  r->m_read.buflen = r->m_read.buf - mybuf;
5040 	  r->m_read.buf = mybuf;
5041 	  r->m_read.bufpos = mybuf;
5042 	}
5043       r->m_read.flags |= RTMP_READ_HEADER;
5044     }
5045 
5046   if ((r->m_read.flags & RTMP_READ_SEEKING) && r->m_read.buf)
5047     {
5048       /* drop whatever's here */
5049       free(r->m_read.buf);
5050       r->m_read.buf = NULL;
5051       r->m_read.bufpos = NULL;
5052       r->m_read.buflen = 0;
5053     }
5054 
5055   /* If there's leftover data buffered, use it up */
5056   if (r->m_read.buf)
5057     {
5058       nRead = r->m_read.buflen;
5059       if (nRead > size)
5060 	nRead = size;
5061       memcpy(buf, r->m_read.bufpos, nRead);
5062       r->m_read.buflen -= nRead;
5063       if (!r->m_read.buflen)
5064 	{
5065 	  free(r->m_read.buf);
5066 	  r->m_read.buf = NULL;
5067 	  r->m_read.bufpos = NULL;
5068 	}
5069       else
5070 	{
5071 	  r->m_read.bufpos += nRead;
5072 	}
5073       buf += nRead;
5074       total += nRead;
5075       size -= nRead;
5076     }
5077 
5078   while (size > 0 && (nRead = Read_1_Packet(r, buf, size)) >= 0)
5079     {
5080       if (!nRead) continue;
5081       buf += nRead;
5082       total += nRead;
5083       size -= nRead;
5084       break;
5085     }
5086   if (nRead < 0)
5087     r->m_read.status = nRead;
5088 
5089   if (size < 0)
5090     total += size;
5091   return total;
5092 }
5093 
5094 static const AVal av_setDataFrame = AVC("@setDataFrame");
5095 
5096 int
RTMP_Write(RTMP * r,const char * buf,int size)5097 RTMP_Write(RTMP *r, const char *buf, int size)
5098 {
5099   RTMPPacket *pkt = &r->m_write;
5100   char *pend, *enc;
5101   int s2 = size, ret, num;
5102 
5103   pkt->m_nChannel = 0x04;	/* source channel */
5104   pkt->m_nInfoField2 = r->m_stream_id;
5105 
5106   while (s2)
5107     {
5108       if (!pkt->m_nBytesRead)
5109 	{
5110 	  if (size < 11) {
5111 	    /* FLV pkt too small */
5112 	    return 0;
5113 	  }
5114 
5115 	  if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V')
5116 	    {
5117 	      buf += 13;
5118 	      s2 -= 13;
5119 	    }
5120 
5121 	  pkt->m_packetType = *buf++;
5122 	  pkt->m_nBodySize = AMF_DecodeInt24(buf);
5123 	  buf += 3;
5124 	  pkt->m_nTimeStamp = AMF_DecodeInt24(buf);
5125 	  buf += 3;
5126 	  pkt->m_nTimeStamp |= *buf++ << 24;
5127 	  buf += 3;
5128 	  s2 -= 11;
5129 
5130 	  if (((pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO
5131                 || pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) &&
5132             !pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
5133 	    {
5134 	      pkt->m_headerType = RTMP_PACKET_SIZE_LARGE;
5135 	      if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
5136 		pkt->m_nBodySize += 16;
5137 	    }
5138 	  else
5139 	    {
5140 	      pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
5141 	    }
5142 
5143 	  if (!RTMPPacket_Alloc(pkt, pkt->m_nBodySize))
5144 	    {
5145 	      RTMP_Log(RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);
5146 	      return FALSE;
5147 	    }
5148 	  enc = pkt->m_body;
5149 	  pend = enc + pkt->m_nBodySize;
5150 	  if (pkt->m_packetType == RTMP_PACKET_TYPE_INFO)
5151 	    {
5152 	      enc = AMF_EncodeString(enc, pend, &av_setDataFrame);
5153 	      pkt->m_nBytesRead = enc - pkt->m_body;
5154 	    }
5155 	}
5156       else
5157 	{
5158 	  enc = pkt->m_body + pkt->m_nBytesRead;
5159 	}
5160       num = pkt->m_nBodySize - pkt->m_nBytesRead;
5161       if (num > s2)
5162 	num = s2;
5163       memcpy(enc, buf, num);
5164       pkt->m_nBytesRead += num;
5165       s2 -= num;
5166       buf += num;
5167       if (pkt->m_nBytesRead == pkt->m_nBodySize)
5168 	{
5169 	  ret = RTMP_SendPacket(r, pkt, FALSE);
5170 	  RTMPPacket_Free(pkt);
5171 	  pkt->m_nBytesRead = 0;
5172 	  if (!ret)
5173 	    return -1;
5174 	  buf += 4;
5175 	  s2 -= 4;
5176 	  if (s2 < 0)
5177 	    break;
5178 	}
5179     }
5180   return size+s2;
5181 }
5182