Mercurial > mplayer.hg
annotate stream/librtsp/rtsp.c @ 35173:95ad1e516f03
mp_property_deinterlace: Signalize control() failure
Always having to do a GET after a SET to check if the state was
really changed, seems not very friendly from the perspective of
the client application that changes the property.
Return M_PROPERTY_UNAVAILABLE to signalize that the control() was
not positively consumed by the filter/vo chain.
Based on a patch by Vicente Sendra >visenri yahoo.es<
author | al |
---|---|
date | Thu, 25 Oct 2012 18:26:45 +0000 |
parents | 8fa2f43cb760 |
children | 389d43c448b3 |
rev | line source |
---|---|
18799 | 1 /* |
2 * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48 | |
3 */ | |
4 | |
5 /* | |
6 * Copyright (C) 2000-2002 the xine project | |
7 * | |
8 * This file is part of xine, a free video player. | |
9 * | |
10 * xine is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * xine is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
23 * | |
24 * | |
25 * a minimalistic implementation of rtsp protocol, | |
26 * *not* RFC 2326 compilant yet. | |
27 * | |
28 * 2006, Benjamin Zores and Vincent Mussard | |
29 * fixed a lot of RFC compliance issues. | |
30 */ | |
31 | |
32 #include <unistd.h> | |
33 #include <stdio.h> | |
34 #include <assert.h> | |
35 #include "config.h" | |
36 #include <string.h> | |
37 #include <sys/stat.h> | |
38 #include <fcntl.h> | |
39 #include <errno.h> | |
40 #include <stdlib.h> | |
41 #include <time.h> | |
42 #include <sys/time.h> | |
43 #include <sys/types.h> | |
44 #include <inttypes.h> | |
28402 | 45 #if HAVE_WINSOCK2_H |
27109 | 46 #include <winsock2.h> |
27320
44341e4d5621
Do not include sys/socket.h when using winsock2, it is pointless
reimar
parents:
27202
diff
changeset
|
47 #else |
44341e4d5621
Do not include sys/socket.h when using winsock2, it is pointless
reimar
parents:
27202
diff
changeset
|
48 #include <sys/socket.h> |
27109 | 49 #endif |
18799 | 50 #include "mp_msg.h" |
51 #include "rtsp.h" | |
52 #include "rtsp_session.h" | |
53 #include "osdep/timer.h" | |
31500 | 54 #include "stream/network.h" |
18799 | 55 |
56 /* | |
57 #define LOG | |
58 */ | |
59 | |
60 /* | |
61 * network utilities | |
62 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
63 |
18799 | 64 static int write_stream(int s, const char *buf, int len) { |
65 int total, timeout; | |
66 | |
67 total = 0; timeout = 30; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
68 while (total < len){ |
18799 | 69 int n; |
70 | |
31500 | 71 n = send (s, &buf[total], len - total, DEFAULT_SEND_FLAGS); |
18799 | 72 |
73 if (n > 0) | |
74 total += n; | |
75 else if (n < 0) { | |
28402 | 76 #if !HAVE_WINSOCK2_H |
18799 | 77 if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) { |
78 #else | |
79 if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) { | |
80 #endif | |
81 usec_sleep (1000000); timeout--; | |
82 } else | |
83 return -1; | |
84 } | |
85 } | |
86 | |
87 return total; | |
88 } | |
89 | |
90 static ssize_t read_stream(int fd, void *buf, size_t count) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
91 |
18799 | 92 ssize_t ret, total; |
93 | |
94 total = 0; | |
95 | |
96 while (total < count) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
97 |
18799 | 98 ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0); |
99 | |
100 if (ret<0) { | |
101 if(errno == EAGAIN) { | |
102 fd_set rset; | |
103 struct timeval timeout; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
104 |
18799 | 105 FD_ZERO (&rset); |
106 FD_SET (fd, &rset); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
107 |
18799 | 108 timeout.tv_sec = 30; |
109 timeout.tv_usec = 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
110 |
18799 | 111 if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) { |
112 return -1; | |
113 } | |
114 continue; | |
115 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
116 |
18799 | 117 mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n"); |
118 return ret; | |
119 } else | |
120 total += ret; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
121 |
18799 | 122 /* end of stream */ |
123 if (!ret) break; | |
124 } | |
125 | |
126 return total; | |
127 } | |
128 | |
129 /* | |
130 * rtsp_get gets a line from stream | |
131 * and returns a null terminated string. | |
132 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
133 |
18799 | 134 static char *rtsp_get(rtsp_t *s) { |
135 | |
136 int n=1; | |
137 char *buffer = malloc(BUF_SIZE); | |
138 char *string = NULL; | |
139 | |
140 read_stream(s->s, buffer, 1); | |
141 while (n<BUF_SIZE) { | |
142 read_stream(s->s, &(buffer[n]), 1); | |
143 if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break; | |
144 n++; | |
145 } | |
146 | |
147 if (n>=BUF_SIZE) { | |
148 mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n"); | |
149 exit(1); | |
150 } | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
151 string=malloc(n); |
18799 | 152 memcpy(string,buffer,n-1); |
153 string[n-1]=0; | |
154 | |
155 #ifdef LOG | |
156 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string); | |
157 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
158 |
18799 | 159 |
160 free(buffer); | |
161 return string; | |
162 } | |
163 | |
164 /* | |
165 * rtsp_put puts a line on stream | |
166 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
167 |
18799 | 168 static void rtsp_put(rtsp_t *s, const char *string) { |
169 | |
170 int len=strlen(string); | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
171 char *buf=malloc(len+2); |
18799 | 172 |
173 #ifdef LOG | |
174 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string); | |
175 #endif | |
176 | |
177 memcpy(buf,string,len); | |
178 buf[len]=0x0d; | |
179 buf[len+1]=0x0a; | |
180 | |
181 write_stream(s->s, buf, len+2); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
182 |
18799 | 183 #ifdef LOG |
184 mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n"); | |
185 #endif | |
186 | |
187 free(buf); | |
188 } | |
189 | |
190 /* | |
191 * extract server status code | |
192 */ | |
193 | |
194 static int rtsp_get_code(const char *string) { | |
195 | |
196 char buf[4]; | |
197 int code=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
198 |
18799 | 199 if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION))) |
200 { | |
201 memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3); | |
202 buf[3]=0; | |
203 code=atoi(buf); | |
204 } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8)) | |
205 { | |
206 return RTSP_STATUS_SET_PARAMETER; | |
207 } | |
208 | |
209 if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string); | |
210 | |
211 return code; | |
212 } | |
213 | |
214 /* | |
215 * send a request | |
216 */ | |
217 | |
218 static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) { | |
219 | |
220 char **payload=s->scheduled; | |
221 char *buf; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
222 |
18799 | 223 buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
224 |
18799 | 225 sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION); |
226 rtsp_put(s,buf); | |
227 free(buf); | |
228 if (payload) | |
229 while (*payload) { | |
230 rtsp_put(s,*payload); | |
231 payload++; | |
232 } | |
233 rtsp_put(s,""); | |
234 rtsp_unschedule_all(s); | |
235 } | |
236 | |
237 /* | |
238 * schedule standard fields | |
239 */ | |
240 | |
241 static void rtsp_schedule_standard(rtsp_t *s) { | |
242 | |
18853
1ec19da0c642
increase buffer size, "CSeq: %u" has a worst case of 17 (fix 1.18 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.17&r2=1.18)
ben
parents:
18852
diff
changeset
|
243 char tmp[17]; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
244 |
18853
1ec19da0c642
increase buffer size, "CSeq: %u" has a worst case of 17 (fix 1.18 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.17&r2=1.18)
ben
parents:
18852
diff
changeset
|
245 snprintf(tmp, 17, "CSeq: %u", s->cseq); |
18799 | 246 rtsp_schedule_field(s, tmp); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
247 |
18799 | 248 if (s->session) { |
249 char *buf; | |
250 buf = malloc(strlen(s->session)+15); | |
251 sprintf(buf, "Session: %s", s->session); | |
252 rtsp_schedule_field(s, buf); | |
253 free(buf); | |
254 } | |
255 } | |
256 /* | |
257 * get the answers, if server responses with something != 200, return NULL | |
258 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
259 |
18799 | 260 static int rtsp_get_answers(rtsp_t *s) { |
261 | |
262 char *answer=NULL; | |
263 unsigned int answer_seq; | |
264 char **answer_ptr=s->answers; | |
265 int code; | |
266 int ans_count = 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
267 |
18799 | 268 answer=rtsp_get(s); |
269 if (!answer) | |
270 return 0; | |
271 code=rtsp_get_code(answer); | |
272 free(answer); | |
273 | |
274 rtsp_free_answers(s); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
275 |
18799 | 276 do { /* while we get answer lines */ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
277 |
18799 | 278 answer=rtsp_get(s); |
279 if (!answer) | |
280 return 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
281 |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
282 if (!strncasecmp(answer,"CSeq:",5)) { |
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
283 sscanf(answer,"%*s %u",&answer_seq); |
18799 | 284 if (s->cseq != answer_seq) { |
285 #ifdef LOG | |
286 mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq); | |
287 #endif | |
288 s->cseq=answer_seq; | |
289 } | |
290 } | |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
291 if (!strncasecmp(answer,"Server:",7)) { |
18799 | 292 char *buf = malloc(strlen(answer)); |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
293 sscanf(answer,"%*s %s",buf); |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
31500
diff
changeset
|
294 free(s->server); |
18799 | 295 s->server=strdup(buf); |
296 free(buf); | |
297 } | |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
298 if (!strncasecmp(answer,"Session:",8)) { |
18799 | 299 char *buf = calloc(1, strlen(answer)); |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
300 sscanf(answer,"%*s %s",buf); |
18799 | 301 if (s->session) { |
302 if (strcmp(buf, s->session)) { | |
303 mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf); | |
304 free(s->session); | |
305 s->session=strdup(buf); | |
306 } | |
307 } else | |
308 { | |
309 #ifdef LOG | |
310 mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf); | |
311 #endif | |
312 s->session=strdup(buf); | |
313 } | |
314 free(buf); | |
315 } | |
316 *answer_ptr=answer; | |
317 answer_ptr++; | |
318 } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS)); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
319 |
18799 | 320 s->cseq++; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
321 |
18799 | 322 *answer_ptr=NULL; |
323 rtsp_schedule_standard(s); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
324 |
18799 | 325 return code; |
326 } | |
327 | |
328 /* | |
329 * send an ok message | |
330 */ | |
331 | |
332 int rtsp_send_ok(rtsp_t *s) { | |
333 char cseq[16]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
334 |
18799 | 335 rtsp_put(s, "RTSP/1.0 200 OK"); |
336 sprintf(cseq,"CSeq: %u", s->cseq); | |
337 rtsp_put(s, cseq); | |
338 rtsp_put(s, ""); | |
339 return 0; | |
340 } | |
341 | |
342 /* | |
343 * implementation of must-have rtsp requests; functions return | |
344 * server status code. | |
345 */ | |
346 | |
347 int rtsp_request_options(rtsp_t *s, const char *what) { | |
348 | |
349 char *buf; | |
350 | |
351 if (what) { | |
352 buf=strdup(what); | |
353 } else | |
354 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
355 buf=malloc(strlen(s->host)+16); |
18799 | 356 sprintf(buf,"rtsp://%s:%i", s->host, s->port); |
357 } | |
358 rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf); | |
359 free(buf); | |
360 | |
361 return rtsp_get_answers(s); | |
362 } | |
363 | |
364 int rtsp_request_describe(rtsp_t *s, const char *what) { | |
365 | |
366 char *buf; | |
367 | |
368 if (what) { | |
369 buf=strdup(what); | |
370 } else | |
371 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
372 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 373 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
374 } | |
375 rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf); | |
376 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
377 |
18799 | 378 return rtsp_get_answers(s); |
379 } | |
380 | |
381 int rtsp_request_setup(rtsp_t *s, const char *what, char *control) { | |
382 | |
383 char *buf = NULL; | |
384 | |
385 if (what) | |
386 buf = strdup (what); | |
387 else | |
388 { | |
389 int len = strlen (s->host) + strlen (s->path) + 16; | |
390 if (control) | |
391 len += strlen (control) + 1; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
392 |
18799 | 393 buf = malloc (len); |
394 sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path, | |
395 control ? "/" : "", control ? control : ""); | |
396 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
397 |
18799 | 398 rtsp_send_request (s, RTSP_METHOD_SETUP, buf); |
399 free (buf); | |
400 return rtsp_get_answers (s); | |
401 } | |
402 | |
403 int rtsp_request_setparameter(rtsp_t *s, const char *what) { | |
404 | |
405 char *buf; | |
406 | |
407 if (what) { | |
408 buf=strdup(what); | |
409 } else | |
410 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
411 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 412 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
413 } | |
414 rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf); | |
415 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
416 |
18799 | 417 return rtsp_get_answers(s); |
418 } | |
419 | |
420 int rtsp_request_play(rtsp_t *s, const char *what) { | |
421 | |
422 char *buf; | |
423 int ret; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
424 |
18799 | 425 if (what) { |
426 buf=strdup(what); | |
427 } else | |
428 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
429 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 430 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
431 } | |
432 rtsp_send_request(s,RTSP_METHOD_PLAY,buf); | |
433 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
434 |
18799 | 435 ret = rtsp_get_answers (s); |
436 if (ret == RTSP_STATUS_OK) | |
437 s->server_state = RTSP_PLAYING; | |
438 | |
439 return ret; | |
440 } | |
441 | |
442 int rtsp_request_teardown(rtsp_t *s, const char *what) { | |
443 | |
444 char *buf; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
445 |
18799 | 446 if (what) |
447 buf = strdup (what); | |
448 else | |
449 { | |
450 buf = | |
451 malloc (strlen (s->host) + strlen (s->path) + 16); | |
452 sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path); | |
453 } | |
454 rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf); | |
455 free (buf); | |
18801 | 456 |
457 /* after teardown we're done with RTSP streaming, no need to get answer as | |
458 reading more will only result to garbage and buffer overflow */ | |
459 return RTSP_STATUS_OK; | |
18799 | 460 } |
461 | |
462 /* | |
463 * read opaque data from stream | |
464 */ | |
465 | |
466 int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) { | |
467 | |
468 int i,seq; | |
469 | |
470 if (size>=4) { | |
471 i=read_stream(s->s, buffer, 4); | |
472 if (i<4) return i; | |
473 if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) || | |
474 ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS | |
475 { | |
476 char *rest=rtsp_get(s); | |
477 if (!rest) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
478 return -1; |
18799 | 479 |
480 seq=-1; | |
481 do { | |
482 free(rest); | |
483 rest=rtsp_get(s); | |
484 if (!rest) | |
485 return -1; | |
18852
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
486 if (!strncasecmp(rest,"CSeq:",5)) |
b17648e2762e
be more tolerant on server responses parameters case (fix 1.17 from xine, see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.16&r2=1.17)
ben
parents:
18851
diff
changeset
|
487 sscanf(rest,"%*s %u",&seq); |
18799 | 488 } while (strlen(rest)!=0); |
489 free(rest); | |
490 if (seq<0) { | |
491 #ifdef LOG | |
492 mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n"); | |
493 #endif | |
494 seq=1; | |
495 } | |
496 /* let's make the server happy */ | |
497 rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood"); | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
498 rest=malloc(17); |
18799 | 499 sprintf(rest,"CSeq: %u", seq); |
500 rtsp_put(s, rest); | |
18855
a60bcf4969c3
coverity report #179 from xine: variable "rest" not freed or pointed-to in function "rtsp_put" (see http://xine.cvs.sourceforge.net/xine/xine-lib/src/input/librtsp/rtsp.c?r1=1.19&r2=1.20)
ben
parents:
18854
diff
changeset
|
501 free(rest); |
18799 | 502 rtsp_put(s, ""); |
503 i=read_stream(s->s, buffer, size); | |
504 } else | |
505 { | |
506 i=read_stream(s->s, buffer+4, size-4); | |
507 i+=4; | |
508 } | |
509 } else | |
510 i=read_stream(s->s, buffer, size); | |
511 #ifdef LOG | |
512 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size); | |
513 #endif | |
514 | |
515 return i; | |
516 } | |
517 | |
518 /* | |
519 * connect to a rtsp server | |
520 */ | |
521 | |
522 //rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) { | |
523 rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) { | |
524 | |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
525 rtsp_t *s; |
18799 | 526 int i; |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
527 |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
528 if (fd < 0) { |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
529 mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: failed to connect to '%s'\n", host); |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
530 return NULL; |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
531 } |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
532 |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
533 s = malloc(sizeof(rtsp_t)); |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
534 |
18799 | 535 for (i=0; i<MAX_FIELDS; i++) { |
536 s->answers[i]=NULL; | |
537 s->scheduled[i]=NULL; | |
538 } | |
539 | |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
540 s->s = fd; |
18799 | 541 s->server=NULL; |
542 s->server_state=0; | |
543 s->server_caps=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
544 |
18799 | 545 s->cseq=0; |
546 s->session=NULL; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
547 |
18799 | 548 if (user_agent) |
549 s->user_agent=strdup(user_agent); | |
550 else | |
551 s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)"); | |
552 | |
553 s->mrl = strdup(mrl); | |
554 s->host = strdup(host); | |
555 s->port = port; | |
556 s->path = strdup(path); | |
557 while (*path == '/') | |
558 path++; | |
559 if ((s->param = strchr(s->path, '?')) != NULL) | |
560 s->param++; | |
561 //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path); | |
562 //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL"); | |
563 | |
564 s->server_state=RTSP_CONNECTED; | |
565 | |
566 /* now let's send an options request. */ | |
567 rtsp_schedule_field(s, "CSeq: 1"); | |
568 rtsp_schedule_field(s, s->user_agent); | |
569 rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7"); | |
570 rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]"); | |
571 rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw=="); | |
572 rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000"); | |
573 rtsp_schedule_field(s, "RegionData: 0"); | |
574 rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); | |
575 /*rtsp_schedule_field(s, "Pragma: initiate-session");*/ | |
576 rtsp_request_options(s, NULL); | |
577 | |
578 return s; | |
579 } | |
580 | |
581 | |
582 /* | |
583 * search in answers for tags. returns a pointer to the content | |
584 * after the first matched tag. returns NULL if no match found. | |
585 */ | |
586 | |
587 char *rtsp_search_answers(rtsp_t *s, const char *tag) { | |
588 | |
589 char **answer; | |
590 char *ptr; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
591 |
18799 | 592 if (!s->answers) return NULL; |
593 answer=s->answers; | |
594 | |
595 while (*answer) { | |
596 if (!strncasecmp(*answer,tag,strlen(tag))) { | |
597 ptr=strchr(*answer,':'); | |
598 if (!ptr) return NULL; | |
599 ptr++; | |
600 while(*ptr==' ') ptr++; | |
601 return ptr; | |
602 } | |
603 answer++; | |
604 } | |
605 | |
606 return NULL; | |
607 } | |
608 | |
609 /* | |
610 * session id management | |
611 */ | |
612 | |
613 void rtsp_set_session(rtsp_t *s, const char *id) { | |
614 | |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
31500
diff
changeset
|
615 free(s->session); |
18799 | 616 |
617 s->session=strdup(id); | |
618 | |
619 } | |
620 | |
621 char *rtsp_get_session(rtsp_t *s) { | |
622 | |
623 return s->session; | |
624 | |
625 } | |
626 | |
627 char *rtsp_get_mrl(rtsp_t *s) { | |
628 | |
629 return s->mrl; | |
630 | |
631 } | |
632 | |
19108
5e767cabf4cd
marks several read-only string parameters and function return-values which can only be used read-only as const. Patch by Stefan Huehner, stefan _AT huener-org
reynaldo
parents:
18855
diff
changeset
|
633 char *rtsp_get_param(rtsp_t *s, const char *p) { |
18799 | 634 int len; |
635 char *param; | |
636 if (!s->param) | |
637 return NULL; | |
638 if (!p) | |
639 return strdup(s->param); | |
640 len = strlen(p); | |
641 param = s->param; | |
642 while (param && *param) { | |
643 char *nparam = strchr(param, '&'); | |
644 if (strncmp(param, p, len) == 0 && param[len] == '=') { | |
645 param += len + 1; | |
646 len = nparam ? nparam - param : strlen(param); | |
647 nparam = malloc(len + 1); | |
648 memcpy(nparam, param, len); | |
649 nparam[len] = 0; | |
650 return nparam; | |
651 } | |
652 param = nparam ? nparam + 1 : NULL; | |
653 } | |
654 return NULL; | |
655 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
656 |
18799 | 657 /* |
658 * schedules a field for transmission | |
659 */ | |
660 | |
661 void rtsp_schedule_field(rtsp_t *s, const char *string) { | |
662 | |
663 int i=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
664 |
18799 | 665 if (!string) return; |
666 | |
667 while(s->scheduled[i]) { | |
668 i++; | |
669 } | |
670 s->scheduled[i]=strdup(string); | |
671 } | |
672 | |
673 /* | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
674 * removes the first scheduled field which prefix matches string. |
18799 | 675 */ |
676 | |
677 void rtsp_unschedule_field(rtsp_t *s, const char *string) { | |
678 | |
679 char **ptr=s->scheduled; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
680 |
18799 | 681 if (!string) return; |
682 | |
683 while(*ptr) { | |
684 if (!strncmp(*ptr, string, strlen(string))) | |
685 break; | |
686 else | |
687 ptr++; | |
688 } | |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
31500
diff
changeset
|
689 free(*ptr); |
18799 | 690 ptr++; |
691 do { | |
692 *(ptr-1)=*ptr; | |
693 } while(*ptr); | |
694 } | |
695 | |
696 /* | |
697 * unschedule all fields | |
698 */ | |
699 | |
700 void rtsp_unschedule_all(rtsp_t *s) { | |
701 | |
702 char **ptr; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
703 |
18799 | 704 if (!s->scheduled) return; |
705 ptr=s->scheduled; | |
706 | |
707 while (*ptr) { | |
708 free(*ptr); | |
709 *ptr=NULL; | |
710 ptr++; | |
711 } | |
712 } | |
713 /* | |
714 * free answers | |
715 */ | |
716 | |
717 void rtsp_free_answers(rtsp_t *s) { | |
718 | |
719 char **answer; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
720 |
18799 | 721 if (!s->answers) return; |
722 answer=s->answers; | |
723 | |
724 while (*answer) { | |
725 free(*answer); | |
726 *answer=NULL; | |
727 answer++; | |
728 } | |
729 } |