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