1 /*  Simple RTMP Server
2  *  Copyright (C) 2009 Andrej Stepanchuk
3  *  Copyright (C) 2009-2011 Howard Chu
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with RTMPDump; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  *  Boston, MA  02110-1301, USA.
19  *  http://www.gnu.org/copyleft/gpl.html
20  *
21  */
22 
23 /* This is just a stub for an RTMP server. It doesn't do anything
24  * beyond obtaining the connection parameters from the client.
25  */
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include <limits.h>
31 
32 #include <signal.h>
33 #include <getopt.h>
34 
35 #include <assert.h>
36 
37 #include "librtmp/rtmp_sys.h"
38 #include "librtmp/log.h"
39 
40 #include "thread.h"
41 
42 #ifdef linux
43 #include <linux/netfilter_ipv4.h>
44 #endif
45 
46 #ifndef WIN32
47 #include <sys/types.h>
48 #include <sys/wait.h>
49 #endif
50 
51 #define RD_SUCCESS		0
52 #define RD_FAILED		1
53 #define RD_INCOMPLETE		2
54 
55 #define PACKET_SIZE 1024*1024
56 
57 #ifdef WIN32
58 #define InitSockets()	{\
59 	WORD version;			\
60 	WSADATA wsaData;		\
61 					\
62 	version = MAKEWORD(1,1);	\
63 	WSAStartup(version, &wsaData);	}
64 
65 #define	CleanupSockets()	WSACleanup()
66 #else
67 #define InitSockets()
68 #define	CleanupSockets()
69 #endif
70 
71 #define DUPTIME	5000	/* interval we disallow duplicate requests, in msec */
72 
73 enum
74 {
75   STREAMING_ACCEPTING,
76   STREAMING_IN_PROGRESS,
77   STREAMING_STOPPING,
78   STREAMING_STOPPED
79 };
80 
81 typedef struct
82 {
83   int socket;
84   int state;
85   int streamID;
86   int arglen;
87   int argc;
88   uint32_t filetime;	/* time of last download we started */
89   AVal filename;	/* name of last download */
90   char *connect;
91 
92 } STREAMING_SERVER;
93 
94 STREAMING_SERVER *rtmpServer = 0;	// server structure pointer
95 void *sslCtx = NULL;
96 
97 STREAMING_SERVER *startStreaming(const char *address, int port);
98 void stopStreaming(STREAMING_SERVER * server);
99 void AVreplace(AVal *src, const AVal *orig, const AVal *repl);
100 
101 static const AVal av_dquote = AVC("\"");
102 static const AVal av_escdquote = AVC("\\\"");
103 
104 typedef struct
105 {
106   char *hostname;
107   int rtmpport;
108   int protocol;
109   int bLiveStream;		// is it a live stream? then we can't seek/resume
110 
111   long int timeout;		// timeout connection afte 300 seconds
112   uint32_t bufferTime;
113 
114   char *rtmpurl;
115   AVal playpath;
116   AVal swfUrl;
117   AVal tcUrl;
118   AVal pageUrl;
119   AVal app;
120   AVal auth;
121   AVal swfHash;
122   AVal flashVer;
123   AVal subscribepath;
124   uint32_t swfSize;
125 
126   uint32_t dStartOffset;
127   uint32_t dStopOffset;
128   uint32_t nTimeStamp;
129 } RTMP_REQUEST;
130 
131 #define STR2AVAL(av,str)	av.av_val = str; av.av_len = strlen(av.av_val)
132 
133 /* this request is formed from the parameters and used to initialize a new request,
134  * thus it is a default settings list. All settings can be overriden by specifying the
135  * parameters in the GET request. */
136 RTMP_REQUEST defaultRTMPRequest;
137 
138 #ifdef _DEBUG
139 uint32_t debugTS = 0;
140 
141 int pnum = 0;
142 
143 FILE *netstackdump = NULL;
144 FILE *netstackdump_read = NULL;
145 #endif
146 
147 #define SAVC(x) static const AVal av_##x = AVC(#x)
148 
149 SAVC(app);
150 SAVC(connect);
151 SAVC(flashVer);
152 SAVC(swfUrl);
153 SAVC(pageUrl);
154 SAVC(tcUrl);
155 SAVC(fpad);
156 SAVC(capabilities);
157 SAVC(audioCodecs);
158 SAVC(videoCodecs);
159 SAVC(videoFunction);
160 SAVC(objectEncoding);
161 SAVC(_result);
162 SAVC(createStream);
163 SAVC(getStreamLength);
164 SAVC(play);
165 SAVC(fmsVer);
166 SAVC(mode);
167 SAVC(level);
168 SAVC(code);
169 SAVC(description);
170 SAVC(secureToken);
171 
172 static int
SendConnectResult(RTMP * r,double txn)173 SendConnectResult(RTMP *r, double txn)
174 {
175   RTMPPacket packet;
176   char pbuf[384], *pend = pbuf+sizeof(pbuf);
177   AMFObject obj;
178   AMFObjectProperty p, op;
179   AVal av;
180 
181   packet.m_nChannel = 0x03;     // control channel (invoke)
182   packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */
183   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
184   packet.m_nTimeStamp = 0;
185   packet.m_nInfoField2 = 0;
186   packet.m_hasAbsTimestamp = 0;
187   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
188 
189   char *enc = packet.m_body;
190   enc = AMF_EncodeString(enc, pend, &av__result);
191   enc = AMF_EncodeNumber(enc, pend, txn);
192   *enc++ = AMF_OBJECT;
193 
194   STR2AVAL(av, "FMS/3,5,1,525");
195   enc = AMF_EncodeNamedString(enc, pend, &av_fmsVer, &av);
196   enc = AMF_EncodeNamedNumber(enc, pend, &av_capabilities, 31.0);
197   enc = AMF_EncodeNamedNumber(enc, pend, &av_mode, 1.0);
198   *enc++ = 0;
199   *enc++ = 0;
200   *enc++ = AMF_OBJECT_END;
201 
202   *enc++ = AMF_OBJECT;
203 
204   STR2AVAL(av, "status");
205   enc = AMF_EncodeNamedString(enc, pend, &av_level, &av);
206   STR2AVAL(av, "NetConnection.Connect.Success");
207   enc = AMF_EncodeNamedString(enc, pend, &av_code, &av);
208   STR2AVAL(av, "Connection succeeded.");
209   enc = AMF_EncodeNamedString(enc, pend, &av_description, &av);
210   enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding);
211 #if 0
212   STR2AVAL(av, "58656322c972d6cdf2d776167575045f8484ea888e31c086f7b5ffbd0baec55ce442c2fb");
213   enc = AMF_EncodeNamedString(enc, pend, &av_secureToken, &av);
214 #endif
215   STR2AVAL(p.p_name, "version");
216   STR2AVAL(p.p_vu.p_aval, "3,5,1,525");
217   p.p_type = AMF_STRING;
218   obj.o_num = 1;
219   obj.o_props = &p;
220   op.p_type = AMF_OBJECT;
221   STR2AVAL(op.p_name, "data");
222   op.p_vu.p_object = obj;
223   enc = AMFProp_Encode(&op, enc, pend);
224   *enc++ = 0;
225   *enc++ = 0;
226   *enc++ = AMF_OBJECT_END;
227 
228   packet.m_nBodySize = enc - packet.m_body;
229 
230   return RTMP_SendPacket(r, &packet, FALSE);
231 }
232 
233 static int
SendResultNumber(RTMP * r,double txn,double ID)234 SendResultNumber(RTMP *r, double txn, double ID)
235 {
236   RTMPPacket packet;
237   char pbuf[256], *pend = pbuf+sizeof(pbuf);
238 
239   packet.m_nChannel = 0x03;     // control channel (invoke)
240   packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */
241   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
242   packet.m_nTimeStamp = 0;
243   packet.m_nInfoField2 = 0;
244   packet.m_hasAbsTimestamp = 0;
245   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
246 
247   char *enc = packet.m_body;
248   enc = AMF_EncodeString(enc, pend, &av__result);
249   enc = AMF_EncodeNumber(enc, pend, txn);
250   *enc++ = AMF_NULL;
251   enc = AMF_EncodeNumber(enc, pend, ID);
252 
253   packet.m_nBodySize = enc - packet.m_body;
254 
255   return RTMP_SendPacket(r, &packet, FALSE);
256 }
257 
258 SAVC(onStatus);
259 SAVC(status);
260 static const AVal av_NetStream_Play_Start = AVC("NetStream.Play.Start");
261 static const AVal av_Started_playing = AVC("Started playing");
262 static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop");
263 static const AVal av_Stopped_playing = AVC("Stopped playing");
264 SAVC(details);
265 SAVC(clientid);
266 static const AVal av_NetStream_Authenticate_UsherToken = AVC("NetStream.Authenticate.UsherToken");
267 
268 static int
SendPlayStart(RTMP * r)269 SendPlayStart(RTMP *r)
270 {
271   RTMPPacket packet;
272   char pbuf[512], *pend = pbuf+sizeof(pbuf);
273 
274   packet.m_nChannel = 0x03;     // control channel (invoke)
275   packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */
276   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
277   packet.m_nTimeStamp = 0;
278   packet.m_nInfoField2 = 0;
279   packet.m_hasAbsTimestamp = 0;
280   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
281 
282   char *enc = packet.m_body;
283   enc = AMF_EncodeString(enc, pend, &av_onStatus);
284   enc = AMF_EncodeNumber(enc, pend, 0);
285   *enc++ = AMF_OBJECT;
286 
287   enc = AMF_EncodeNamedString(enc, pend, &av_level, &av_status);
288   enc = AMF_EncodeNamedString(enc, pend, &av_code, &av_NetStream_Play_Start);
289   enc = AMF_EncodeNamedString(enc, pend, &av_description, &av_Started_playing);
290   enc = AMF_EncodeNamedString(enc, pend, &av_details, &r->Link.playpath);
291   enc = AMF_EncodeNamedString(enc, pend, &av_clientid, &av_clientid);
292   *enc++ = 0;
293   *enc++ = 0;
294   *enc++ = AMF_OBJECT_END;
295 
296   packet.m_nBodySize = enc - packet.m_body;
297   return RTMP_SendPacket(r, &packet, FALSE);
298 }
299 
300 static int
SendPlayStop(RTMP * r)301 SendPlayStop(RTMP *r)
302 {
303   RTMPPacket packet;
304   char pbuf[512], *pend = pbuf+sizeof(pbuf);
305 
306   packet.m_nChannel = 0x03;     // control channel (invoke)
307   packet.m_headerType = 1; /* RTMP_PACKET_SIZE_MEDIUM; */
308   packet.m_packetType = RTMP_PACKET_TYPE_INVOKE;
309   packet.m_nTimeStamp = 0;
310   packet.m_nInfoField2 = 0;
311   packet.m_hasAbsTimestamp = 0;
312   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
313 
314   char *enc = packet.m_body;
315   enc = AMF_EncodeString(enc, pend, &av_onStatus);
316   enc = AMF_EncodeNumber(enc, pend, 0);
317   *enc++ = AMF_OBJECT;
318 
319   enc = AMF_EncodeNamedString(enc, pend, &av_level, &av_status);
320   enc = AMF_EncodeNamedString(enc, pend, &av_code, &av_NetStream_Play_Stop);
321   enc = AMF_EncodeNamedString(enc, pend, &av_description, &av_Stopped_playing);
322   enc = AMF_EncodeNamedString(enc, pend, &av_details, &r->Link.playpath);
323   enc = AMF_EncodeNamedString(enc, pend, &av_clientid, &av_clientid);
324   *enc++ = 0;
325   *enc++ = 0;
326   *enc++ = AMF_OBJECT_END;
327 
328   packet.m_nBodySize = enc - packet.m_body;
329   return RTMP_SendPacket(r, &packet, FALSE);
330 }
331 
332 static void
spawn_dumper(int argc,AVal * av,char * cmd)333 spawn_dumper(int argc, AVal *av, char *cmd)
334 {
335 #ifdef WIN32
336   STARTUPINFO si = {0};
337   PROCESS_INFORMATION pi = {0};
338 
339   si.cb = sizeof(si);
340   if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
341     &si, &pi))
342     {
343       CloseHandle(pi.hThread);
344       CloseHandle(pi.hProcess);
345     }
346 #else
347   /* reap any dead children */
348   while (waitpid(-1, NULL, WNOHANG) > 0);
349 
350   if (fork() == 0) {
351     char **argv = malloc((argc+1) * sizeof(char *));
352     int i;
353 
354     for (i=0; i<argc; i++) {
355       argv[i] = av[i].av_val;
356       argv[i][av[i].av_len] = '\0';
357     }
358     argv[i] = NULL;
359     if ((i = execvp(argv[0], argv)))
360       _exit(i);
361   }
362 #endif
363 }
364 
365 static int
countAMF(AMFObject * obj,int * argc)366 countAMF(AMFObject *obj, int *argc)
367 {
368   int i, len;
369 
370   for (i=0, len=0; i < obj->o_num; i++)
371     {
372       AMFObjectProperty *p = &obj->o_props[i];
373       len += 4;
374       (*argc)+= 2;
375       if (p->p_name.av_val)
376 	len += 1;
377       len += 2;
378       if (p->p_name.av_val)
379 	len += p->p_name.av_len + 1;
380       switch(p->p_type)
381 	{
382 	case AMF_BOOLEAN:
383 	  len += 1;
384 	  break;
385 	case AMF_STRING:
386 	  len += p->p_vu.p_aval.av_len;
387 	  break;
388 	case AMF_NUMBER:
389 	  len += 40;
390 	  break;
391 	case AMF_OBJECT:
392 	  len += 9;
393 	  len += countAMF(&p->p_vu.p_object, argc);
394 	  (*argc) += 2;
395 	  break;
396 	case AMF_NULL:
397 	default:
398 	  break;
399 	}
400     }
401   return len;
402 }
403 
404 static char *
dumpAMF(AMFObject * obj,char * ptr,AVal * argv,int * argc)405 dumpAMF(AMFObject *obj, char *ptr, AVal *argv, int *argc)
406 {
407   int i, ac = *argc;
408   const char opt[] = "NBSO Z";
409 
410   for (i=0; i < obj->o_num; i++)
411     {
412       AMFObjectProperty *p = &obj->o_props[i];
413       argv[ac].av_val = ptr+1;
414       argv[ac++].av_len = 2;
415       ptr += sprintf(ptr, " -C ");
416       argv[ac].av_val = ptr;
417       if (p->p_name.av_val)
418 	*ptr++ = 'N';
419       *ptr++ = opt[p->p_type];
420       *ptr++ = ':';
421       if (p->p_name.av_val)
422 	ptr += sprintf(ptr, "%.*s:", p->p_name.av_len, p->p_name.av_val);
423       switch(p->p_type)
424 	{
425 	case AMF_BOOLEAN:
426 	  *ptr++ = p->p_vu.p_number != 0 ? '1' : '0';
427 	  argv[ac].av_len = ptr - argv[ac].av_val;
428 	  break;
429 	case AMF_STRING:
430 	  memcpy(ptr, p->p_vu.p_aval.av_val, p->p_vu.p_aval.av_len);
431 	  ptr += p->p_vu.p_aval.av_len;
432 	  argv[ac].av_len = ptr - argv[ac].av_val;
433 	  break;
434 	case AMF_NUMBER:
435 	  ptr += sprintf(ptr, "%f", p->p_vu.p_number);
436 	  argv[ac].av_len = ptr - argv[ac].av_val;
437 	  break;
438 	case AMF_OBJECT:
439 	  *ptr++ = '1';
440 	  argv[ac].av_len = ptr - argv[ac].av_val;
441 	  ac++;
442 	  *argc = ac;
443 	  ptr = dumpAMF(&p->p_vu.p_object, ptr, argv, argc);
444 	  ac = *argc;
445 	  argv[ac].av_val = ptr+1;
446 	  argv[ac++].av_len = 2;
447 	  argv[ac].av_val = ptr+4;
448 	  argv[ac].av_len = 3;
449 	  ptr += sprintf(ptr, " -C O:0");
450 	  break;
451 	case AMF_NULL:
452 	default:
453 	  argv[ac].av_len = ptr - argv[ac].av_val;
454 	  break;
455 	}
456       ac++;
457     }
458   *argc = ac;
459   return ptr;
460 }
461 
462 // Returns 0 for OK/Failed/error, 1 for 'Stop or Complete'
463 int
ServeInvoke(STREAMING_SERVER * server,RTMP * r,RTMPPacket * packet,unsigned int offset)464 ServeInvoke(STREAMING_SERVER *server, RTMP * r, RTMPPacket *packet, unsigned int offset)
465 {
466   const char *body;
467   unsigned int nBodySize;
468   int ret = 0, nRes;
469 
470   body = packet->m_body + offset;
471   nBodySize = packet->m_nBodySize - offset;
472 
473   if (body[0] != 0x02)		// make sure it is a string method name we start with
474     {
475       RTMP_Log(RTMP_LOGWARNING, "%s, Sanity failed. no string method in invoke packet",
476 	  __FUNCTION__);
477       return 0;
478     }
479 
480   AMFObject obj;
481   nRes = AMF_Decode(&obj, body, nBodySize, FALSE);
482   if (nRes < 0)
483     {
484       RTMP_Log(RTMP_LOGERROR, "%s, error decoding invoke packet", __FUNCTION__);
485       return 0;
486     }
487 
488   AMF_Dump(&obj);
489   AVal method;
490   AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);
491   double txn = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 1));
492   RTMP_Log(RTMP_LOGDEBUG, "%s, client invoking <%s>", __FUNCTION__, method.av_val);
493 
494   if (AVMATCH(&method, &av_connect))
495     {
496       AMFObject cobj;
497       AVal pname, pval;
498       int i;
499 
500       server->connect = packet->m_body;
501       packet->m_body = NULL;
502 
503       AMFProp_GetObject(AMF_GetProp(&obj, NULL, 2), &cobj);
504       for (i=0; i<cobj.o_num; i++)
505 	{
506 	  pname = cobj.o_props[i].p_name;
507 	  pval.av_val = NULL;
508 	  pval.av_len = 0;
509 	  if (cobj.o_props[i].p_type == AMF_STRING)
510 	    pval = cobj.o_props[i].p_vu.p_aval;
511 	  if (AVMATCH(&pname, &av_app))
512 	    {
513 	      r->Link.app = pval;
514 	      pval.av_val = NULL;
515 	      if (!r->Link.app.av_val)
516 	        r->Link.app.av_val = "";
517 	      server->arglen += 6 + pval.av_len;
518 	      server->argc += 2;
519 	    }
520 	  else if (AVMATCH(&pname, &av_flashVer))
521 	    {
522 	      r->Link.flashVer = pval;
523 	      pval.av_val = NULL;
524 	      server->arglen += 6 + pval.av_len;
525 	      server->argc += 2;
526 	    }
527 	  else if (AVMATCH(&pname, &av_swfUrl))
528 	    {
529 	      r->Link.swfUrl = pval;
530 	      pval.av_val = NULL;
531 	      server->arglen += 6 + pval.av_len;
532 	      server->argc += 2;
533 	    }
534 	  else if (AVMATCH(&pname, &av_tcUrl))
535 	    {
536 	      r->Link.tcUrl = pval;
537 	      pval.av_val = NULL;
538 	      server->arglen += 6 + pval.av_len;
539 	      server->argc += 2;
540 	    }
541 	  else if (AVMATCH(&pname, &av_pageUrl))
542 	    {
543 	      r->Link.pageUrl = pval;
544 	      pval.av_val = NULL;
545 	      server->arglen += 6 + pval.av_len;
546 	      server->argc += 2;
547 	    }
548 	  else if (AVMATCH(&pname, &av_audioCodecs))
549 	    {
550 	      r->m_fAudioCodecs = cobj.o_props[i].p_vu.p_number;
551 	    }
552 	  else if (AVMATCH(&pname, &av_videoCodecs))
553 	    {
554 	      r->m_fVideoCodecs = cobj.o_props[i].p_vu.p_number;
555 	    }
556 	  else if (AVMATCH(&pname, &av_objectEncoding))
557 	    {
558 	      r->m_fEncoding = cobj.o_props[i].p_vu.p_number;
559 	    }
560 	}
561       /* Still have more parameters? Copy them */
562       if (obj.o_num > 3)
563 	{
564 	  int i = obj.o_num - 3;
565 	  r->Link.extras.o_num = i;
566 	  r->Link.extras.o_props = malloc(i*sizeof(AMFObjectProperty));
567 	  memcpy(r->Link.extras.o_props, obj.o_props+3, i*sizeof(AMFObjectProperty));
568 	  obj.o_num = 3;
569 	  server->arglen += countAMF(&r->Link.extras, &server->argc);
570 	}
571       SendConnectResult(r, txn);
572     }
573   else if (AVMATCH(&method, &av_createStream))
574     {
575       SendResultNumber(r, txn, ++server->streamID);
576     }
577   else if (AVMATCH(&method, &av_getStreamLength))
578     {
579       SendResultNumber(r, txn, 10.0);
580     }
581   else if (AVMATCH(&method, &av_NetStream_Authenticate_UsherToken))
582     {
583       AVal usherToken;
584       AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &usherToken);
585       AVreplace(&usherToken, &av_dquote, &av_escdquote);
586       server->arglen += 6 + usherToken.av_len;
587       server->argc += 2;
588       r->Link.usherToken = usherToken;
589     }
590   else if (AVMATCH(&method, &av_play))
591     {
592       char *file, *p, *q, *cmd, *ptr;
593       AVal *argv, av;
594       int len, argc;
595       uint32_t now;
596       RTMPPacket pc = {0};
597       AMFProp_GetString(AMF_GetProp(&obj, NULL, 3), &r->Link.playpath);
598       if (!r->Link.playpath.av_len)
599         return 0;
600       /*
601       r->Link.seekTime = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 4));
602       if (obj.o_num > 5)
603 	r->Link.length = AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 5));
604       */
605       if (r->Link.tcUrl.av_len)
606 	{
607 	  len = server->arglen + r->Link.playpath.av_len + 4 +
608 	    sizeof("rtmpdump") + r->Link.playpath.av_len + 12;
609 	  server->argc += 5;
610 
611 	  cmd = malloc(len + server->argc * sizeof(AVal));
612 	  ptr = cmd;
613 	  argv = (AVal *)(cmd + len);
614 	  argv[0].av_val = cmd;
615 	  argv[0].av_len = sizeof("rtmpdump")-1;
616 	  ptr += sprintf(ptr, "rtmpdump");
617 	  argc = 1;
618 
619 	  argv[argc].av_val = ptr + 1;
620 	  argv[argc++].av_len = 2;
621 	  argv[argc].av_val = ptr + 5;
622 	  ptr += sprintf(ptr," -r \"%s\"", r->Link.tcUrl.av_val);
623 	  argv[argc++].av_len = r->Link.tcUrl.av_len;
624 
625 	  if (r->Link.app.av_val)
626 	    {
627 	      argv[argc].av_val = ptr + 1;
628 	      argv[argc++].av_len = 2;
629 	      argv[argc].av_val = ptr + 5;
630 	      ptr += sprintf(ptr, " -a \"%s\"", r->Link.app.av_val);
631 	      argv[argc++].av_len = r->Link.app.av_len;
632 	    }
633 	  if (r->Link.flashVer.av_val)
634 	    {
635 	      argv[argc].av_val = ptr + 1;
636 	      argv[argc++].av_len = 2;
637 	      argv[argc].av_val = ptr + 5;
638 	      ptr += sprintf(ptr, " -f \"%s\"", r->Link.flashVer.av_val);
639 	      argv[argc++].av_len = r->Link.flashVer.av_len;
640 	    }
641 	  if (r->Link.swfUrl.av_val)
642 	    {
643 	      argv[argc].av_val = ptr + 1;
644 	      argv[argc++].av_len = 2;
645 	      argv[argc].av_val = ptr + 5;
646 	      ptr += sprintf(ptr, " -W \"%s\"", r->Link.swfUrl.av_val);
647 	      argv[argc++].av_len = r->Link.swfUrl.av_len;
648 	    }
649 	  if (r->Link.pageUrl.av_val)
650 	    {
651 	      argv[argc].av_val = ptr + 1;
652 	      argv[argc++].av_len = 2;
653 	      argv[argc].av_val = ptr + 5;
654 	      ptr += sprintf(ptr, " -p \"%s\"", r->Link.pageUrl.av_val);
655 	      argv[argc++].av_len = r->Link.pageUrl.av_len;
656 	    }
657 	  if (r->Link.usherToken.av_val)
658 	    {
659 	      argv[argc].av_val = ptr + 1;
660 	      argv[argc++].av_len = 2;
661 	      argv[argc].av_val = ptr + 5;
662 	      ptr += sprintf(ptr, " -j \"%s\"", r->Link.usherToken.av_val);
663 	      argv[argc++].av_len = r->Link.usherToken.av_len;
664 	      free(r->Link.usherToken.av_val);
665 	      r->Link.usherToken.av_val = NULL;
666 	      r->Link.usherToken.av_len = 0;
667 	    }
668 	  if (r->Link.extras.o_num) {
669 	    ptr = dumpAMF(&r->Link.extras, ptr, argv, &argc);
670 	    AMF_Reset(&r->Link.extras);
671 	  }
672 	  argv[argc].av_val = ptr + 1;
673 	  argv[argc++].av_len = 2;
674 	  argv[argc].av_val = ptr + 5;
675 	  ptr += sprintf(ptr, " -y \"%.*s\"",
676 	    r->Link.playpath.av_len, r->Link.playpath.av_val);
677 	  argv[argc++].av_len = r->Link.playpath.av_len;
678 
679 	  av = r->Link.playpath;
680 	  /* strip trailing URL parameters */
681 	  q = memchr(av.av_val, '?', av.av_len);
682 	  if (q)
683 	    {
684 	      if (q == av.av_val)
685 		{
686 		  av.av_val++;
687 		  av.av_len--;
688 		}
689 	      else
690 		{
691 		  av.av_len = q - av.av_val;
692 		}
693 	    }
694 	  /* strip leading slash components */
695 	  for (p=av.av_val+av.av_len-1; p>=av.av_val; p--)
696 	    if (*p == '/')
697 	      {
698 		p++;
699 		av.av_len -= p - av.av_val;
700 		av.av_val = p;
701 		break;
702 	      }
703 	  /* skip leading dot */
704 	  if (av.av_val[0] == '.')
705 	    {
706 	      av.av_val++;
707 	      av.av_len--;
708 	    }
709 	  file = malloc(av.av_len+5);
710 
711 	  memcpy(file, av.av_val, av.av_len);
712 	  file[av.av_len] = '\0';
713 	  for (p=file; *p; p++)
714 	    if (*p == ':')
715 	      *p = '_';
716 
717 	  /* Add extension if none present */
718 	  if (file[av.av_len - 4] != '.')
719 	    {
720 	      av.av_len += 4;
721 	    }
722 	  /* Always use flv extension, regardless of original */
723 	  if (strcmp(file+av.av_len-4, ".flv"))
724 	    {
725 	      strcpy(file+av.av_len-4, ".flv");
726 	    }
727 	  argv[argc].av_val = ptr + 1;
728 	  argv[argc++].av_len = 2;
729 	  argv[argc].av_val = file;
730 	  argv[argc].av_len = av.av_len;
731 	  ptr += sprintf(ptr, " -o %s", file);
732 	  now = RTMP_GetTime();
733 	  if (now - server->filetime < DUPTIME && AVMATCH(&argv[argc], &server->filename))
734 	    {
735 	      printf("Duplicate request, skipping.\n");
736 	      free(file);
737 	    }
738 	  else
739 	    {
740 	      printf("\n%s\n\n", cmd);
741 	      fflush(stdout);
742 	      server->filetime = now;
743 	      free(server->filename.av_val);
744 	      server->filename = argv[argc++];
745 	      spawn_dumper(argc, argv, cmd);
746 	    }
747 
748 	  free(cmd);
749 	}
750       pc.m_body = server->connect;
751       server->connect = NULL;
752       RTMPPacket_Free(&pc);
753       ret = 1;
754 	  RTMP_SendCtrl(r, 0, 1, 0);
755 	  SendPlayStart(r);
756 	  RTMP_SendCtrl(r, 1, 1, 0);
757 	  SendPlayStop(r);
758     }
759   AMF_Reset(&obj);
760   return ret;
761 }
762 
763 int
ServePacket(STREAMING_SERVER * server,RTMP * r,RTMPPacket * packet)764 ServePacket(STREAMING_SERVER *server, RTMP *r, RTMPPacket *packet)
765 {
766   int ret = 0;
767 
768   RTMP_Log(RTMP_LOGDEBUG, "%s, received packet type %02X, size %u bytes", __FUNCTION__,
769     packet->m_packetType, packet->m_nBodySize);
770 
771   switch (packet->m_packetType)
772     {
773     case RTMP_PACKET_TYPE_CHUNK_SIZE:
774 //      HandleChangeChunkSize(r, packet);
775       break;
776 
777     case RTMP_PACKET_TYPE_BYTES_READ_REPORT:
778       break;
779 
780     case RTMP_PACKET_TYPE_CONTROL:
781 //      HandleCtrl(r, packet);
782       break;
783 
784     case RTMP_PACKET_TYPE_SERVER_BW:
785 //      HandleServerBW(r, packet);
786       break;
787 
788     case RTMP_PACKET_TYPE_CLIENT_BW:
789  //     HandleClientBW(r, packet);
790       break;
791 
792     case RTMP_PACKET_TYPE_AUDIO:
793       //RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize);
794       break;
795 
796     case RTMP_PACKET_TYPE_VIDEO:
797       //RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize);
798       break;
799 
800     case RTMP_PACKET_TYPE_FLEX_STREAM_SEND:
801       break;
802 
803     case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT:
804       break;
805 
806     case RTMP_PACKET_TYPE_FLEX_MESSAGE:
807       {
808 	RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %u bytes, not fully supported",
809 	    __FUNCTION__, packet->m_nBodySize);
810 	//RTMP_LogHex(packet.m_body, packet.m_nBodySize);
811 
812 	// some DEBUG code
813 	/*RTMP_LIB_AMFObject obj;
814 	   int nRes = obj.Decode(packet.m_body+1, packet.m_nBodySize-1);
815 	   if(nRes < 0) {
816 	   RTMP_Log(RTMP_LOGERROR, "%s, error decoding AMF3 packet", __FUNCTION__);
817 	   //return;
818 	   }
819 
820 	   obj.Dump(); */
821 
822 	if (ServeInvoke(server, r, packet, 1))
823 	  RTMP_Close(r);
824 	break;
825       }
826     case RTMP_PACKET_TYPE_INFO:
827       break;
828 
829     case RTMP_PACKET_TYPE_SHARED_OBJECT:
830       break;
831 
832     case RTMP_PACKET_TYPE_INVOKE:
833       RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__,
834 	  packet->m_nBodySize);
835       //RTMP_LogHex(packet.m_body, packet.m_nBodySize);
836 
837       if (ServeInvoke(server, r, packet, 0))
838 	RTMP_Close(r);
839       break;
840 
841     case RTMP_PACKET_TYPE_FLASH_VIDEO:
842 	break;
843     default:
844       RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,
845 	  packet->m_packetType);
846 #ifdef _DEBUG
847       RTMP_LogHex(RTMP_LOGDEBUG, packet->m_body, packet->m_nBodySize);
848 #endif
849     }
850   return ret;
851 }
852 
853 TFTYPE
controlServerThread(void * unused)854 controlServerThread(void *unused)
855 {
856   char ich;
857   while (1)
858     {
859       ich = getchar();
860       switch (ich)
861 	{
862 	case 'q':
863 	  RTMP_LogPrintf("Exiting\n");
864 	  stopStreaming(rtmpServer);
865 	  exit(0);
866 	  break;
867 	default:
868 	  RTMP_LogPrintf("Unknown command \'%c\', ignoring\n", ich);
869 	}
870     }
871   TFRET();
872 }
873 
874 
doServe(STREAMING_SERVER * server,int sockfd)875 void doServe(STREAMING_SERVER * server,	// server socket and state (our listening socket)
876   int sockfd	// client connection socket
877   )
878 {
879   server->state = STREAMING_IN_PROGRESS;
880 
881   RTMP *rtmp = RTMP_Alloc();		/* our session with the real client */
882   RTMPPacket packet = { 0 };
883 
884   // timeout for http requests
885   fd_set fds;
886   struct timeval tv;
887 
888   memset(&tv, 0, sizeof(struct timeval));
889   tv.tv_sec = 5;
890 
891   FD_ZERO(&fds);
892   FD_SET(sockfd, &fds);
893 
894   if (select(sockfd + 1, &fds, NULL, NULL, &tv) <= 0)
895     {
896       RTMP_Log(RTMP_LOGERROR, "Request timeout/select failed, ignoring request");
897       goto quit;
898     }
899   else
900     {
901       RTMP_Init(rtmp);
902       rtmp->m_sb.sb_socket = sockfd;
903       if (sslCtx && !RTMP_TLS_Accept(rtmp, sslCtx))
904         {
905 	  RTMP_Log(RTMP_LOGERROR, "TLS handshake failed");
906 	  goto cleanup;
907         }
908       if (!RTMP_Serve(rtmp))
909 	{
910 	  RTMP_Log(RTMP_LOGERROR, "Handshake failed");
911 	  goto cleanup;
912 	}
913     }
914   server->arglen = 0;
915   while (RTMP_IsConnected(rtmp) && RTMP_ReadPacket(rtmp, &packet))
916     {
917       if (!RTMPPacket_IsReady(&packet))
918 	continue;
919       ServePacket(server, rtmp, &packet);
920       RTMPPacket_Free(&packet);
921     }
922 
923 cleanup:
924   RTMP_LogPrintf("Closing connection... ");
925   RTMP_Close(rtmp);
926   /* Should probably be done by RTMP_Close() ... */
927   rtmp->Link.playpath.av_val = NULL;
928   rtmp->Link.tcUrl.av_val = NULL;
929   rtmp->Link.swfUrl.av_val = NULL;
930   rtmp->Link.pageUrl.av_val = NULL;
931   rtmp->Link.app.av_val = NULL;
932   rtmp->Link.flashVer.av_val = NULL;
933   if (rtmp->Link.usherToken.av_val)
934     {
935       free(rtmp->Link.usherToken.av_val);
936       rtmp->Link.usherToken.av_val = NULL;
937     }
938   RTMP_Free(rtmp);
939   RTMP_LogPrintf("done!\n\n");
940 
941 quit:
942   if (server->state == STREAMING_IN_PROGRESS)
943     server->state = STREAMING_ACCEPTING;
944 
945   return;
946 }
947 
948 TFTYPE
serverThread(void * arg)949 serverThread(void *arg)
950 {
951   STREAMING_SERVER *server = arg;
952   server->state = STREAMING_ACCEPTING;
953 
954   while (server->state == STREAMING_ACCEPTING)
955     {
956       struct sockaddr_in addr;
957       socklen_t addrlen = sizeof(struct sockaddr_in);
958       int sockfd =
959 	accept(server->socket, (struct sockaddr *) &addr, &addrlen);
960 
961       if (sockfd > 0)
962 	{
963 #ifdef linux
964 	  struct sockaddr_in dest;
965 	  char destch[16];
966 	  socklen_t destlen = sizeof(struct sockaddr_in);
967 	  getsockopt(sockfd, SOL_IP, SO_ORIGINAL_DST, &dest, &destlen);
968 	  strcpy(destch, inet_ntoa(dest.sin_addr));
969 	  RTMP_Log(RTMP_LOGDEBUG, "%s: accepted connection from %s to %s\n", __FUNCTION__,
970 	      inet_ntoa(addr.sin_addr), destch);
971 #else
972 	  RTMP_Log(RTMP_LOGDEBUG, "%s: accepted connection from %s\n", __FUNCTION__,
973 	      inet_ntoa(addr.sin_addr));
974 #endif
975 	  /* Create a new thread and transfer the control to that */
976 	  doServe(server, sockfd);
977 	  RTMP_Log(RTMP_LOGDEBUG, "%s: processed request\n", __FUNCTION__);
978 	}
979       else
980 	{
981 	  RTMP_Log(RTMP_LOGERROR, "%s: accept failed", __FUNCTION__);
982 	}
983     }
984   server->state = STREAMING_STOPPED;
985   TFRET();
986 }
987 
988 STREAMING_SERVER *
startStreaming(const char * address,int port)989 startStreaming(const char *address, int port)
990 {
991   struct sockaddr_in addr;
992   int sockfd, tmp;
993   STREAMING_SERVER *server;
994 
995   sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
996   if (sockfd == -1)
997     {
998       RTMP_Log(RTMP_LOGERROR, "%s, couldn't create socket", __FUNCTION__);
999       return 0;
1000     }
1001 
1002   tmp = 1;
1003   setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
1004 				(char *) &tmp, sizeof(tmp) );
1005 
1006   addr.sin_family = AF_INET;
1007   addr.sin_addr.s_addr = inet_addr(address);	//htonl(INADDR_ANY);
1008   addr.sin_port = htons(port);
1009 
1010   if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) ==
1011       -1)
1012     {
1013       RTMP_Log(RTMP_LOGERROR, "%s, TCP bind failed for port number: %d", __FUNCTION__,
1014 	  port);
1015       return 0;
1016     }
1017 
1018   if (listen(sockfd, 10) == -1)
1019     {
1020       RTMP_Log(RTMP_LOGERROR, "%s, listen failed", __FUNCTION__);
1021       closesocket(sockfd);
1022       return 0;
1023     }
1024 
1025   server = (STREAMING_SERVER *) calloc(1, sizeof(STREAMING_SERVER));
1026   server->socket = sockfd;
1027 
1028   ThreadCreate(serverThread, server);
1029 
1030   return server;
1031 }
1032 
1033 void
stopStreaming(STREAMING_SERVER * server)1034 stopStreaming(STREAMING_SERVER * server)
1035 {
1036   assert(server);
1037 
1038   if (server->state != STREAMING_STOPPED)
1039     {
1040       if (server->state == STREAMING_IN_PROGRESS)
1041 	{
1042 	  server->state = STREAMING_STOPPING;
1043 
1044 	  // wait for streaming threads to exit
1045 	  while (server->state != STREAMING_STOPPED)
1046 	    msleep(1);
1047 	}
1048 
1049       if (closesocket(server->socket))
1050 	RTMP_Log(RTMP_LOGERROR, "%s: Failed to close listening socket, error %d",
1051 	    __FUNCTION__, GetSockError());
1052 
1053       server->state = STREAMING_STOPPED;
1054     }
1055 }
1056 
1057 
1058 void
sigIntHandler(int sig)1059 sigIntHandler(int sig)
1060 {
1061   RTMP_ctrlC = TRUE;
1062   RTMP_LogPrintf("Caught signal: %d, cleaning up, just a second...\n", sig);
1063   if (rtmpServer)
1064     stopStreaming(rtmpServer);
1065   signal(SIGINT, SIG_DFL);
1066 }
1067 
1068 int
main(int argc,char ** argv)1069 main(int argc, char **argv)
1070 {
1071   int nStatus = RD_SUCCESS;
1072   int i;
1073 
1074   // http streaming server
1075   char DEFAULT_HTTP_STREAMING_DEVICE[] = "0.0.0.0";	// 0.0.0.0 is any device
1076 
1077   char *rtmpStreamingDevice = DEFAULT_HTTP_STREAMING_DEVICE;	// streaming device, default 0.0.0.0
1078   int nRtmpStreamingPort = 1935;	// port
1079   char *cert = NULL, *key = NULL;
1080 
1081   RTMP_LogPrintf("RTMP Server %s\n", RTMPDUMP_VERSION);
1082   RTMP_LogPrintf("(c) 2010 Andrej Stepanchuk, Howard Chu; license: GPL\n\n");
1083 
1084   RTMP_debuglevel = RTMP_LOGINFO;
1085 
1086   for (i = 1; i < argc; i++)
1087     {
1088       if (!strcmp(argv[i], "-z"))
1089         RTMP_debuglevel = RTMP_LOGALL;
1090       else if (!strcmp(argv[i], "-c") && i + 1 < argc)
1091         cert = argv[++i];
1092       else if (!strcmp(argv[i], "-k") && i + 1 < argc)
1093         key = argv[++i];
1094     }
1095 
1096   if (cert && key)
1097     sslCtx = RTMP_TLS_AllocServerContext(cert, key);
1098 
1099   // init request
1100   memset(&defaultRTMPRequest, 0, sizeof(RTMP_REQUEST));
1101 
1102   defaultRTMPRequest.rtmpport = -1;
1103   defaultRTMPRequest.protocol = RTMP_PROTOCOL_UNDEFINED;
1104   defaultRTMPRequest.bLiveStream = FALSE;	// is it a live stream? then we can't seek/resume
1105 
1106   defaultRTMPRequest.timeout = 300;	// timeout connection afte 300 seconds
1107   defaultRTMPRequest.bufferTime = 20 * 1000;
1108 
1109 
1110   signal(SIGINT, sigIntHandler);
1111 #ifndef WIN32
1112   signal(SIGPIPE, SIG_IGN);
1113 #endif
1114 
1115 #ifdef _DEBUG
1116   netstackdump = fopen("netstackdump", "wb");
1117   netstackdump_read = fopen("netstackdump_read", "wb");
1118 #endif
1119 
1120   InitSockets();
1121 
1122   // start text UI
1123   ThreadCreate(controlServerThread, 0);
1124 
1125   // start http streaming
1126   if ((rtmpServer =
1127        startStreaming(rtmpStreamingDevice, nRtmpStreamingPort)) == 0)
1128     {
1129       RTMP_Log(RTMP_LOGERROR, "Failed to start RTMP server, exiting!");
1130       return RD_FAILED;
1131     }
1132   RTMP_LogPrintf("Streaming on rtmp://%s:%d\n", rtmpStreamingDevice,
1133 	    nRtmpStreamingPort);
1134 
1135   while (rtmpServer->state != STREAMING_STOPPED)
1136     {
1137       sleep(1);
1138     }
1139   RTMP_Log(RTMP_LOGDEBUG, "Done, exiting...");
1140 
1141   if (sslCtx)
1142     RTMP_TLS_FreeServerContext(sslCtx);
1143 
1144   CleanupSockets();
1145 
1146 #ifdef _DEBUG
1147   if (netstackdump != 0)
1148     fclose(netstackdump);
1149   if (netstackdump_read != 0)
1150     fclose(netstackdump_read);
1151 #endif
1152   return nStatus;
1153 }
1154 
1155 void
AVreplace(AVal * src,const AVal * orig,const AVal * repl)1156 AVreplace(AVal *src, const AVal *orig, const AVal *repl)
1157 {
1158   char *srcbeg = src->av_val;
1159   char *srcend = src->av_val + src->av_len;
1160   char *dest, *sptr, *dptr;
1161   int n = 0;
1162 
1163   /* count occurrences of orig in src */
1164   sptr = src->av_val;
1165   while (sptr < srcend && (sptr = strstr(sptr, orig->av_val)))
1166     {
1167       n++;
1168       sptr += orig->av_len;
1169     }
1170   if (!n)
1171     return;
1172 
1173   dest = malloc(src->av_len + 1 + (repl->av_len - orig->av_len) * n);
1174 
1175   sptr = src->av_val;
1176   dptr = dest;
1177   while (sptr < srcend && (sptr = strstr(sptr, orig->av_val)))
1178     {
1179       n = sptr - srcbeg;
1180       memcpy(dptr, srcbeg, n);
1181       dptr += n;
1182       memcpy(dptr, repl->av_val, repl->av_len);
1183       dptr += repl->av_len;
1184       sptr += orig->av_len;
1185       srcbeg = sptr;
1186     }
1187   n = srcend - srcbeg;
1188   memcpy(dptr, srcbeg, n);
1189   dptr += n;
1190   *dptr = '\0';
1191   src->av_val = dest;
1192   src->av_len = dptr - dest;
1193 }
1194