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