$(LIBRTMP):
@$(MAKE) -C librtmp all CC="$(CC)" CFLAGS="$(CFLAGS)"
-rtmpdump: rtmpdump.o parseurl.o $(LIBRTMP)
+rtmpdump: rtmpdump.o $(LIBRTMP)
$(CC) $(LDFLAGS) $^ -o $@$(EXT) $(LIBS)
rtmpsrv: rtmpsrv.o thread.o $(LIBRTMP)
rtmpsuck: rtmpsuck.o thread.o $(LIBRTMP)
$(CC) $(LDFLAGS) $^ -o $@$(EXT) $(SLIBS)
-rtmpgw: rtmpgw.o parseurl.o thread.o $(LIBRTMP)
+rtmpgw: rtmpgw.o thread.o $(LIBRTMP)
$(CC) $(LDFLAGS) $^ -o $@$(EXT) $(SLIBS)
-parseurl.o: parseurl.c parseurl.h Makefile
rtmpgw.o: rtmpgw.c librtmp/rtmp.h librtmp/log.h librtmp/amf.h Makefile
rtmpdump.o: rtmpdump.c librtmp/rtmp.h librtmp/log.h librtmp/amf.h Makefile
rtmpsrv.o: rtmpsrv.c librtmp/rtmp.h librtmp/log.h librtmp/amf.h Makefile
clean:
rm -f *.o *.a
-librtmp.a: rtmp.o log.o amf.o hashswf.o
+librtmp.a: rtmp.o log.o amf.o hashswf.o parseurl.o
$(AR) rs $@ $?
log.o: log.c log.h Makefile
rtmp.o: rtmp.c rtmp.h handshake.h dh.h log.h amf.h Makefile
amf.o: amf.c amf.h bytes.h log.h Makefile
hashswf.o: hashswf.c http.h
+parseurl.o: parseurl.c
#define AVC(str) {str,sizeof(str)-1}
#define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))
+#ifndef __cplusplus
#undef bool
#undef true
#undef false
#define bool int
#define true 1
#define false 0
+#endif
struct AMFObjectProperty;
--- /dev/null
+/* RTMPDump
+ * Copyright (C) 2009 Andrej Stepanchuk
+ * Copyright (C) 2009-2010 Howard Chu
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RTMPDump; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+#include <ctype.h>
+
+#include "rtmp.h"
+
+bool RTMP_ParseURL(const char *url, int *protocol, char **host, unsigned int *port,
+ AVal *playpath, AVal *app)
+{
+ char *p, *end, *col, *ques, *slash;
+
+ Log(LOGDEBUG, "Parsing...");
+
+ *protocol = RTMP_PROTOCOL_RTMP;
+ playpath->av_len = 0;
+ playpath->av_val = NULL;
+ app->av_len = 0;
+ app->av_val = NULL;
+
+ // Old School Parsing
+
+ // look for usual :// pattern
+ p = strstr(url, "://");
+ if(!p) {
+ Log(LOGERROR, "RTMP URL: No :// in url!");
+ return false;
+ }
+ {
+ int len = (int)(p-url);
+
+ if(len == 4 && strncasecmp(url, "rtmp", 4)==0)
+ *protocol = RTMP_PROTOCOL_RTMP;
+ else if(len == 5 && strncasecmp(url, "rtmpt", 5)==0)
+ *protocol = RTMP_PROTOCOL_RTMPT;
+ else if(len == 5 && strncasecmp(url, "rtmps", 5)==0)
+ *protocol = RTMP_PROTOCOL_RTMPS;
+ else if(len == 5 && strncasecmp(url, "rtmpe", 5)==0)
+ *protocol = RTMP_PROTOCOL_RTMPE;
+ else if(len == 5 && strncasecmp(url, "rtmfp", 5)==0)
+ *protocol = RTMP_PROTOCOL_RTMFP;
+ else if(len == 6 && strncasecmp(url, "rtmpte", 6)==0)
+ *protocol = RTMP_PROTOCOL_RTMPTE;
+ else {
+ Log(LOGWARNING, "Unknown protocol!\n");
+ goto parsehost;
+ }
+ }
+
+ Log(LOGDEBUG, "Parsed protocol: %d", *protocol);
+
+parsehost:
+ // lets get the hostname
+ p+=3;
+
+ // check for sudden death
+ if(*p==0) {
+ Log(LOGWARNING, "No hostname in URL!");
+ return false;
+ }
+
+ end = p + strlen(p);
+ col = strchr(p, ':');
+ ques = strchr(p, '?');
+ slash = strchr(p, '/');
+
+ {
+ int hostlen;
+ if(col)
+ hostlen = col - p;
+ else if(slash)
+ hostlen = slash - p;
+ else
+ hostlen = end - p;
+
+ if(hostlen < 256) {
+ *host = malloc(hostlen+1);
+ strncpy(*host, p, hostlen);
+ (*host)[hostlen]=0;
+
+ Log(LOGDEBUG, "Parsed host : %s", *host);
+ } else {
+ Log(LOGWARNING, "Hostname exceeds 255 characters!");
+ }
+
+ p+=hostlen;
+ }
+
+ // get the port number if available
+ if(*p == ':') {
+ p++;
+ unsigned int p2 = atoi(p);
+ if(p2 > 65535) {
+ Log(LOGWARNING, "Invalid port number!");
+ } else {
+ if (p2 == 0)
+ p2 = 1935;
+ *port = p2;
+ }
+ }
+
+ if(!slash) {
+ Log(LOGWARNING, "No application or playpath in URL!");
+ return true;
+ }
+ p = slash+1;
+
+ {
+ // parse application
+ //
+ // rtmp://host[:port]/app[/appinstance][/...]
+ // application = app[/appinstance]
+
+ char *slash2, *slash3 = NULL;
+ int applen, appnamelen;
+
+ slash2 = strchr(p, '/');
+ if(slash2)
+ slash3 = strchr(slash2+1, '/');
+
+ applen = end-p; // ondemand, pass all parameters as app
+ appnamelen = 8; // ondemand length
+
+ if(ques && strstr(p, "slist=")) { // whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist=
+ appnamelen = ques-p;
+ }
+ else if(strncmp(p, "ondemand/", 9)==0) {
+ // app = ondemand/foobar, only pass app=ondemand
+ applen = 8;
+ }
+ else { // app!=ondemand, so app is app[/appinstance]
+ if(slash3)
+ appnamelen = slash3-p;
+ else if(slash2)
+ appnamelen = slash2-p;
+
+ applen = appnamelen;
+ }
+
+ app->av_val = p;
+ app->av_len = applen;
+ Log(LOGDEBUG, "Parsed app : %.*s", applen, p);
+
+ p += appnamelen;
+ }
+
+ if (*p == '/')
+ p++;
+
+ {
+ AVal av = {p, end-p};
+ RTMP_ParsePlaypath(&av, playpath);
+ }
+
+ return true;
+}
+
+/*
+ * Extracts playpath from RTMP URL. playpath is the file part of the
+ * URL, i.e. the part that comes after rtmp://host:port/app/
+ *
+ * Returns the stream name in a format understood by FMS. The name is
+ * the playpath part of the URL with formatting depending on the stream
+ * type:
+ *
+ * mp4 streams: prepend "mp4:", remove extension
+ * mp3 streams: prepend "mp3:", remove extension
+ * flv streams: remove extension
+ */
+void RTMP_ParsePlaypath(AVal *in, AVal *out) {
+ int addMP4 = 0;
+ int addMP3 = 0;
+ int subExt = 0;
+ const char *playpath = in->av_val;
+ const char *temp, *q, *ext = NULL;
+ const char *ppstart = playpath;
+
+ int pplen = in->av_len;
+
+ out->av_val = NULL;
+ out->av_len = 0;
+
+ if ((*ppstart == '?') &&
+ (temp=strstr(ppstart, "slist=")) != 0) {
+ ppstart = temp+6;
+ pplen = strlen(ppstart);
+
+ temp = strchr(ppstart, '&');
+ if (temp) {
+ pplen = temp-ppstart;
+ }
+ }
+
+ q = strchr(ppstart, '?');
+ if (pplen >= 4) {
+ if (q)
+ ext = q-4;
+ else
+ ext = &ppstart[pplen-4];
+ if ((strncmp(ext, ".f4v", 4) == 0) ||
+ (strncmp(ext, ".mp4", 4) == 0)) {
+ addMP4 = 1;
+ subExt = 1;
+ // Only remove .flv from rtmp URL, not slist params
+ } else if ((ppstart == playpath) &&
+ (strncmp(ext, ".flv", 4) == 0)) {
+ subExt = 1;
+ } else if (strncmp(ext, ".mp3", 4) == 0) {
+ addMP3 = 1;
+ subExt = 1;
+ }
+ }
+
+ char *streamname = (char *)malloc((pplen+4+1)*sizeof(char));
+ if (!streamname)
+ return;
+
+ char *destptr = streamname, *p;
+ if (addMP4 && (strncmp(ppstart, "mp4:", 4) != 0)) {
+ strcpy(destptr, "mp4:");
+ destptr += 4;
+ } else if (addMP3 && (strncmp(ppstart, "mp3:", 4) != 0)) {
+ strcpy(destptr, "mp3:");
+ destptr += 4;
+ }
+
+ for (p=(char *)ppstart; pplen >0;) {
+ /* skip extension */
+ if (subExt && p == ext) {
+ p += 4;
+ pplen -= 4;
+ }
+ if (*p == '%') {
+ int c;
+ sscanf(p+1, "%02x", &c);
+ *destptr++ = c;
+ pplen -= 3;
+ p += 3;
+ } else {
+ *destptr++ = *p++;
+ pplen--;
+ }
+ }
+ *destptr = '\0';
+
+ out->av_val = streamname;
+ out->av_len = destptr - streamname;
+}
if (pageUrl)
Log(LOGDEBUG, "pageUrl : %s", pageUrl->av_val);
if (app)
- Log(LOGDEBUG, "app : %s", app->av_val);
+ Log(LOGDEBUG, "app : %.*s", app->av_len, app->av_val);
if (auth)
Log(LOGDEBUG, "auth : %s", auth->av_val);
if (subscribepath)
r->Link.socksport = 0;
}
-
- r->Link.tcUrl = *tcUrl;
- r->Link.swfUrl = *swfUrl;
- r->Link.pageUrl = *pageUrl;
- r->Link.app = *app;
- r->Link.auth = *auth;
- r->Link.flashVer = *flashVer;
- r->Link.subscribepath = *subscribepath;
+ if (tcUrl)
+ r->Link.tcUrl = *tcUrl;
+ if (swfUrl)
+ r->Link.swfUrl = *swfUrl;
+ if (pageUrl)
+ r->Link.pageUrl = *pageUrl;
+ if (app)
+ r->Link.app = *app;
+ if (auth)
+ r->Link.auth = *auth;
+ if (flashVer)
+ r->Link.flashVer = *flashVer;
+ if (subscribepath)
+ r->Link.subscribepath = *subscribepath;
r->Link.seekTime = dTime;
r->Link.length = dLength;
r->Link.bLiveStream = bLiveStream;
#include "log.h"
#include "amf.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define RTMP_PROTOCOL_UNDEFINED -1
#define RTMP_PROTOCOL_RTMP 0
#define RTMP_PROTOCOL_RTMPT 1 // not yet supported
AVal flashVer;
AVal subscribepath;
AVal token;
- bool authflag;
+ AVal playpath0;
AMFObject extras;
double seekTime;
uint32_t length;
+ bool authflag;
bool bLiveStream;
- long int timeout; // number of seconds before connection times out
+ int timeout; // number of seconds before connection times out
const char *sockshost;
unsigned short socksport;
#define m_bTimedout m_sb.sb_timedout
} RTMP;
+bool RTMP_ParseURL(const char *url, int *protocol, char **host,
+ unsigned int *port, AVal *playpath, AVal *app);
+void RTMP_ParsePlaypath(AVal *in, AVal *out);
void RTMP_SetBufferMS(RTMP *r, int size);
void RTMP_UpdateBufferMS(RTMP *r);
int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age);
#endif
+#ifdef __cplusplus
+};
+#endif
+
#endif
+++ /dev/null
-/* RTMPDump
- * Copyright (C) 2009 Andrej Stepanchuk
- * Copyright (C) 2009 Howard Chu
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with RTMPDump; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <assert.h>
-#include <ctype.h>
-
-#include "librtmp/log.h"
-#include "parseurl.h"
-
-#define RTMP_PROTOCOL_UNDEFINED -1
-#define RTMP_PROTOCOL_RTMP 0
-#define RTMP_PROTOCOL_RTMPT 1 // not yet supported
-#define RTMP_PROTOCOL_RTMPS 2 // not yet supported
-#define RTMP_PROTOCOL_RTMPE 3
-#define RTMP_PROTOCOL_RTMPTE 4 // not yet supported
-#define RTMP_PROTOCOL_RTMFP 5 // not yet supported
-
-char *str2lower(char *str, int len)
-{
- char *res = (char *)malloc(len+1);
- char *p;
-
- for(p=res; p<res+len; p++, str++) {
- *p = tolower(*str);
- }
-
- *p = 0;
-
- return res;
-}
-
-int chr2hex(char c)
-{
- if(c <= 57 && c >= 48)
- return c-48;
- else if(c <= 102 && c >= 97)
- return c-97+10;
- return -1;
-}
-
-int hex2bin(char *str, char **hex)
-{
- if(!str || !hex)
- return 0;
-
- int len = strlen(str);
-
- if(len % 2 != 0)
- return 0;
-
- int ret = len/2;
-
- *hex = (char *)malloc(ret);
- if((*hex)==0)
- return 0;
-
- char *hexptr = *hex;
- char *lwo = str2lower(str, len);
- char *lw = lwo;
-
- len /= 2;
-
- while(len) {
- int d1 = chr2hex(*lw); lw++;
- int d2 = chr2hex(*lw); lw++;
-
- if(d1<0 || d2<0) {
- free(*hex);
- free(lwo);
- *hex=NULL;
- return -1;
- }
-
- *hexptr = (unsigned char)(d1*16+d2);
- hexptr++;
- len--;
- }
-
- free(lwo);
- return ret;
-}
-
-int ParseUrl(char *url, int *protocol, char **host, unsigned int *port, char **playpath, char **app)
-{
- assert(url != 0 && protocol != 0 && host != 0 && port != 0 && playpath != 0 && app != 0);
-
- Log(LOGDEBUG, "Parsing...");
-
- *protocol = 0; // default: RTMP
-
- // Old School Parsing
- char *lw = str2lower(url, 6);
- char *temp;
-
- // look for usual :// pattern
- char *p = strstr(url, "://");
- int len = (int)(p-url);
- if(p == 0) {
- Log(LOGWARNING, "RTMP URL: No :// in url!");
- free(lw);
- return 0;
- }
-
- if(len == 4 && strncmp(lw, "rtmp", 4)==0)
- *protocol = RTMP_PROTOCOL_RTMP;
- else if(len == 5 && strncmp(lw, "rtmpt", 5)==0)
- *protocol = RTMP_PROTOCOL_RTMPT;
- else if(len == 5 && strncmp(lw, "rtmps", 5)==0)
- *protocol = RTMP_PROTOCOL_RTMPS;
- else if(len == 5 && strncmp(lw, "rtmpe", 5)==0)
- *protocol = RTMP_PROTOCOL_RTMPE;
- else if(len == 5 && strncmp(lw, "rtmfp", 5)==0)
- *protocol = RTMP_PROTOCOL_RTMFP;
- else if(len == 6 && strncmp(lw, "rtmpte", 6)==0)
- *protocol = RTMP_PROTOCOL_RTMPTE;
- else {
- Log(LOGWARNING, "Unknown protocol!\n");
- goto parsehost;
- }
-
- Log(LOGDEBUG, "Parsed protocol: %d", *protocol);
-
-parsehost:
- free(lw);
-
- // lets get the hostname
- p+=3;
-
- // check for sudden death
- if(*p==0) {
- Log(LOGWARNING, "No hostname in URL!");
- return 0;
- }
-
- int iEnd = strlen(p);
- int iCol = iEnd+1;
- int iQues = iEnd+1;
- int iSlash = iEnd+1;
-
- if((temp=strstr(p, ":"))!=0)
- iCol = temp-p;
- if((temp=strstr(p, "?"))!=0)
- iQues = temp-p;
- if((temp=strstr(p, "/"))!=0)
- iSlash = temp-p;
-
- int min = iSlash < iEnd ? iSlash : iEnd+1;
- min = iQues < min ? iQues : min;
-
- int hostlen = iCol < min ? iCol : min;
-
- if(min < 256) {
- *host = (char *)malloc((hostlen+1)*sizeof(char));
- strncpy(*host, p, hostlen);
- (*host)[hostlen]=0;
-
- Log(LOGDEBUG, "Parsed host : %s", *host);
- } else {
- Log(LOGWARNING, "Hostname exceeds 255 characters!");
- }
-
- p+=hostlen; iEnd-=hostlen;
-
- // get the port number if available
- if(*p == ':') {
- p++; iEnd--;
-
- int portlen = min-hostlen-1;
- if(portlen < 6) {
- char portstr[6];
- strncpy(portstr,p,portlen);
- portstr[portlen]=0;
-
- *port = atoi(portstr);
- if(*port == 0)
- *port = 1935;
-
- Log(LOGDEBUG, "Parsed port : %d", *port);
- } else {
- Log(LOGWARNING, "Port number is longer than 5 characters!");
- }
-
- p+=portlen; iEnd-=portlen;
- }
-
- if(*p != '/') {
- Log(LOGWARNING, "No application or playpath in URL!");
- return 1;
- }
- p++; iEnd--;
-
- // parse application
- //
- // rtmp://host[:port]/app[/appinstance][/...]
- // application = app[/appinstance]
- int iSlash2 = iEnd+1; // 2nd slash
- int iSlash3 = iEnd+1; // 3rd slash
-
- if((temp=strstr(p, "/"))!=0)
- iSlash2 = temp-p;
-
- if((temp=strstr(p, "?"))!=0)
- iQues = temp-p;
-
- if(iSlash2 < iEnd)
- if((temp=strstr(p+iSlash2+1, "/"))!=0)
- iSlash3 = temp-p;
-
- //Log(LOGDEBUG, "p:%s, iEnd: %d\niSlash : %d\niSlash2: %d\niSlash3: %d", p, iEnd, iSlash, iSlash2, iSlash3);
-
- int applen = iEnd+1; // ondemand, pass all parameters as app
- int appnamelen = 8; // ondemand length
-
- if(iQues < iEnd && strstr(p, "slist=")) { // whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist=
- appnamelen = iQues;
- applen = iEnd+1; // pass the parameters as well
- }
- else if(strncmp(p, "ondemand/", 9)==0) {
- // app = ondemand/foobar, only pass app=ondemand
- applen = 8;
- }
- else { // app!=ondemand, so app is app[/appinstance]
- appnamelen = iSlash2 < iEnd ? iSlash2 : iEnd;
- if(iSlash3 < iEnd)
- appnamelen = iSlash3;
-
- applen = appnamelen;
- }
-
- *app = (char *)malloc((applen+1)*sizeof(char));
- strncpy(*app, p, applen);
- (*app)[applen]=0;
- Log(LOGDEBUG, "Parsed app : %s", *app);
-
- p += appnamelen;
- iEnd -= appnamelen;
-
- if (*p == '/') {
- p += 1;
- iEnd -= 1;
- }
-
- *playpath = ParsePlaypath(p);
-
- return 1;
-}
-
-/*
- * Extracts playpath from RTMP URL. playpath is the file part of the
- * URL, i.e. the part that comes after rtmp://host:port/app/
- *
- * Returns the stream name in a format understood by FMS. The name is
- * the playpath part of the URL with formating depending on the stream
- * type:
- *
- * mp4 streams: prepend "mp4:", remove extension
- * mp3 streams: prepend "mp3:", remove extension
- * flv streams: remove extension
- */
-char *ParsePlaypath(const char *playpath) {
- if (!playpath || !*playpath)
- return NULL;
-
- int addMP4 = 0;
- int addMP3 = 0;
- int subExt = 0;
- const char *temp, *q, *ext = NULL;
- const char *ppstart = playpath;
-
- int pplen = strlen(playpath);
-
- if ((*ppstart == '?') &&
- (temp=strstr(ppstart, "slist=")) != 0) {
- ppstart = temp+6;
- pplen = strlen(ppstart);
-
- temp = strchr(ppstart, '&');
- if (temp) {
- pplen = temp-ppstart;
- }
- }
-
- q = strchr(ppstart, '?');
- if (pplen >= 4) {
- if (q)
- ext = q-4;
- else
- ext = &ppstart[pplen-4];
- if ((strncmp(ext, ".f4v", 4) == 0) ||
- (strncmp(ext, ".mp4", 4) == 0)) {
- addMP4 = 1;
- subExt = 1;
- // Only remove .flv from rtmp URL, not slist params
- } else if ((ppstart == playpath) &&
- (strncmp(ext, ".flv", 4) == 0)) {
- subExt = 1;
- } else if (strncmp(ext, ".mp3", 4) == 0) {
- addMP3 = 1;
- subExt = 1;
- }
- }
-
- char *streamname = (char *)malloc((pplen+4+1)*sizeof(char));
- if (!streamname)
- return NULL;
-
- char *destptr = streamname, *p;
- if (addMP4 && (strncmp(ppstart, "mp4:", 4) != 0)) {
- strcpy(destptr, "mp4:");
- destptr += 4;
- } else if (addMP3 && (strncmp(ppstart, "mp3:", 4) != 0)) {
- strcpy(destptr, "mp3:");
- destptr += 4;
- }
-
- for (p=(char *)ppstart; pplen >0;) {
- /* skip extension */
- if (subExt && p == ext) {
- p += 4;
- pplen -= 4;
- }
- if (*p == '%') {
- int c;
- sscanf(p+1, "%02x", &c);
- *destptr++ = c;
- pplen -= 3;
- p += 3;
- } else {
- *destptr++ = *p++;
- pplen--;
- }
- }
- *destptr = '\0';
-
- return streamname;
-}
+++ /dev/null
-#ifndef _PARSEURL_H_
-#define _PARSEURL_H_
-/* RTMPDump
- * Copyright (C) 2009 Andrej Stepanchuk
- * Copyright (C) 2009 Howard Chu
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with RTMPDump; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int hex2bin(char *str, char **hex);
-int ParseUrl(char *url, int *protocol, char **host, unsigned int *port, char **playpath, char **app);
-char *ParsePlaypath(const char *playpath);
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
#include "librtmp/rtmp.h"
#include "librtmp/log.h"
-#include "parseurl.h"
#ifdef WIN32
#define fseeko fseeko64
#endif
}
+#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf))
+int hex2bin(char *str, char **hex)
+{
+ char *ptr;
+ int i, l = strlen(str);
+
+ if (l & 1)
+ return 0;
+
+ *hex = malloc(l/2);
+ ptr = *hex;
+ if (!ptr)
+ return 0;
+
+ for (i=0; i<l; i+=2)
+ *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i+1]);
+ return l/2;
+}
+
int
WriteHeader(char **buf, // target pointer, maybe preallocated
unsigned int len // length of buffer if preallocated
break;
case 'r':
{
- rtmpurl = optarg;
+ AVal parsedApp, parsedPlaypath;
char *parsedHost = 0;
unsigned int parsedPort = 0;
- char *parsedPlaypath = 0;
- char *parsedApp = 0;
int parsedProtocol = RTMP_PROTOCOL_UNDEFINED;
- if (!ParseUrl
+ rtmpurl = optarg;
+ if (!RTMP_ParseURL
(rtmpurl, &parsedProtocol, &parsedHost, &parsedPort,
&parsedPlaypath, &parsedApp))
{
hostname = parsedHost;
if (port == -1)
port = parsedPort;
- if (playpath.av_len == 0 && parsedPlaypath)
+ if (playpath.av_len == 0 && parsedPlaypath.av_len)
{
- STR2AVAL(playpath, parsedPlaypath);
+ playpath = parsedPlaypath;
}
if (protocol == RTMP_PROTOCOL_UNDEFINED)
protocol = parsedProtocol;
- if (app.av_len == 0 && parsedApp)
+ if (app.av_len == 0 && parsedApp.av_len)
{
- STR2AVAL(app, parsedApp);
+ app = parsedApp;
}
}
break;
#include <assert.h>
#include "librtmp/rtmp.h"
-#include "parseurl.h"
#include "thread.h"
signal(SIGINT, SIG_DFL);
}
+#define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf))
+int hex2bin(char *str, char **hex)
+{
+ char *ptr;
+ int i, l = strlen(str);
+
+ if (l & 1)
+ return 0;
+
+ *hex = malloc(l/2);
+ ptr = *hex;
+ if (!ptr)
+ return 0;
+
+ for (i=0; i<l; i+=2)
+ *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i+1]);
+ return l/2;
+}
+
// this will parse RTMP related options as needed
// excludes the following options: h, d, g
{
req->rtmpurl = arg;
+ AVal parsedPlaypath, parsedApp;
char *parsedHost = 0;
unsigned int parsedPort = 0;
- char *parsedPlaypath = 0;
- char *parsedApp = 0;
int parsedProtocol = RTMP_PROTOCOL_UNDEFINED;
- if (!ParseUrl
+ if (!RTMP_ParseURL
(req->rtmpurl, &parsedProtocol, &parsedHost, &parsedPort,
&parsedPlaypath, &parsedApp))
{
req->hostname = parsedHost;
if (req->rtmpport == -1)
req->rtmpport = parsedPort;
- if (req->playpath.av_len == 0 && parsedPlaypath)
+ if (req->playpath.av_len == 0 && parsedPlaypath.av_len)
{
- STR2AVAL(req->playpath, parsedPlaypath);
+ req->playpath = parsedPlaypath;
}
if (req->protocol == RTMP_PROTOCOL_UNDEFINED)
req->protocol = parsedProtocol;
- if (req->app.av_len == 0 && parsedApp)
+ if (req->app.av_len == 0 && parsedApp.av_len)
{
- STR2AVAL(req->app, parsedApp);
+ req->app = parsedApp;
}
}
break;