2 * Copyright (C) 2009 Andrej Stepanchuk
3 * Copyright (C) 2009-2010 Howard Chu
5 * This file is part of librtmp.
7 * librtmp is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1,
10 * or (at your option) any later version.
12 * librtmp is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with librtmp see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/lgpl.html
33 int RTMP_ParseURL(const char *url
, int *protocol
, AVal
*host
, unsigned int *port
,
34 AVal
*playpath
, AVal
*app
)
36 char *p
, *end
, *col
, *ques
, *slash
;
38 RTMP_Log(RTMP_LOGDEBUG
, "Parsing...");
40 *protocol
= RTMP_PROTOCOL_RTMP
;
43 playpath
->av_val
= NULL
;
47 /* Old School Parsing */
49 /* look for usual :// pattern */
50 p
= strstr(url
, "://");
52 RTMP_Log(RTMP_LOGERROR
, "RTMP URL: No :// in url!");
56 int len
= (int)(p
-url
);
58 if(len
== 4 && strncasecmp(url
, "rtmp", 4)==0)
59 *protocol
= RTMP_PROTOCOL_RTMP
;
60 else if(len
== 5 && strncasecmp(url
, "rtmpt", 5)==0)
61 *protocol
= RTMP_PROTOCOL_RTMPT
;
62 else if(len
== 5 && strncasecmp(url
, "rtmps", 5)==0)
63 *protocol
= RTMP_PROTOCOL_RTMPS
;
64 else if(len
== 5 && strncasecmp(url
, "rtmpe", 5)==0)
65 *protocol
= RTMP_PROTOCOL_RTMPE
;
66 else if(len
== 5 && strncasecmp(url
, "rtmfp", 5)==0)
67 *protocol
= RTMP_PROTOCOL_RTMFP
;
68 else if(len
== 6 && strncasecmp(url
, "rtmpte", 6)==0)
69 *protocol
= RTMP_PROTOCOL_RTMPTE
;
70 else if(len
== 6 && strncasecmp(url
, "rtmpts", 6)==0)
71 *protocol
= RTMP_PROTOCOL_RTMPTS
;
73 RTMP_Log(RTMP_LOGWARNING
, "Unknown protocol!\n");
78 RTMP_Log(RTMP_LOGDEBUG
, "Parsed protocol: %d", *protocol
);
81 /* let's get the hostname */
84 /* check for sudden death */
86 RTMP_Log(RTMP_LOGWARNING
, "No hostname in URL!");
92 ques
= strchr(p
, '?');
93 slash
= strchr(p
, '/');
101 if(col
&& col
-p
< hostlen
)
106 host
->av_len
= hostlen
;
107 RTMP_Log(RTMP_LOGDEBUG
, "Parsed host : %.*s", hostlen
, host
->av_val
);
109 RTMP_Log(RTMP_LOGWARNING
, "Hostname exceeds 255 characters!");
115 /* get the port number if available */
121 RTMP_Log(RTMP_LOGWARNING
, "Invalid port number!");
128 RTMP_Log(RTMP_LOGWARNING
, "No application or playpath in URL!");
136 * rtmp://host[:port]/app[/appinstance][/...]
137 * application = app[/appinstance]
140 char *slash2
, *slash3
= NULL
, *slash4
= NULL
;
141 int applen
, appnamelen
;
143 slash2
= strchr(p
, '/');
145 slash3
= strchr(slash2
+1, '/');
147 slash4
= strchr(slash3
+1, '/');
149 applen
= end
-p
; /* ondemand, pass all parameters as app */
150 appnamelen
= applen
; /* ondemand length */
152 if(ques
&& strstr(p
, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */
155 else if(strncmp(p
, "ondemand/", 9)==0) {
156 /* app = ondemand/foobar, only pass app=ondemand */
160 else { /* app!=ondemand, so app is app[/appinstance] */
162 appnamelen
= slash4
-p
;
164 appnamelen
= slash3
-p
;
166 appnamelen
= slash2
-p
;
172 app
->av_len
= applen
;
173 RTMP_Log(RTMP_LOGDEBUG
, "Parsed app : %.*s", applen
, p
);
182 AVal av
= {p
, end
-p
};
183 RTMP_ParsePlaypath(&av
, playpath
);
190 * Extracts playpath from RTMP URL. playpath is the file part of the
191 * URL, i.e. the part that comes after rtmp://host:port/app/
193 * Returns the stream name in a format understood by FMS. The name is
194 * the playpath part of the URL with formatting depending on the stream
197 * mp4 streams: prepend "mp4:", remove extension
198 * mp3 streams: prepend "mp3:", remove extension
199 * flv streams: remove extension
201 void RTMP_ParsePlaypath(AVal
*in
, AVal
*out
) {
205 const char *playpath
= in
->av_val
;
206 const char *temp
, *q
, *ext
= NULL
;
207 const char *ppstart
= playpath
;
208 char *streamname
, *destptr
, *p
;
210 int pplen
= in
->av_len
;
215 if ((*ppstart
== '?') &&
216 (temp
=strstr(ppstart
, "slist=")) != 0) {
218 pplen
= strlen(ppstart
);
220 temp
= strchr(ppstart
, '&');
222 pplen
= temp
-ppstart
;
226 q
= strchr(ppstart
, '?');
231 ext
= &ppstart
[pplen
-4];
232 if ((strncmp(ext
, ".f4v", 4) == 0) ||
233 (strncmp(ext
, ".mp4", 4) == 0)) {
236 /* Only remove .flv from rtmp URL, not slist params */
237 } else if ((ppstart
== playpath
) &&
238 (strncmp(ext
, ".flv", 4) == 0)) {
240 } else if (strncmp(ext
, ".mp3", 4) == 0) {
246 streamname
= (char *)malloc((pplen
+4+1)*sizeof(char));
250 destptr
= streamname
;
252 if (strncmp(ppstart
, "mp4:", 4)) {
253 strcpy(destptr
, "mp4:");
259 if (strncmp(ppstart
, "mp3:", 4)) {
260 strcpy(destptr
, "mp3:");
267 for (p
=(char *)ppstart
; pplen
>0;) {
269 if (subExt
&& p
== ext
) {
276 sscanf(p
+1, "%02x", &c
);
287 out
->av_val
= streamname
;
288 out
->av_len
= destptr
- streamname
;