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