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