Mercurial > mplayer.hg
annotate stream/librtsp/rtsp.c @ 30017:7119354805e7
Use on-stack subtitle struct for temporary storage for passing subtitles on
for rendering by libass.
This avoids mangling the static subtitle struct that is supposed to contain
the subtitles that will actually be displayed and it also minimally reduces
memory usage by freeing the subtitle lines again as early as possible.
author | reimar |
---|---|
date | Fri, 18 Dec 2009 19:29:33 +0000 |
parents | 0f1b5b68af32 |
children | b01f807eb183 |
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" | |
54 | |
55 /* | |
56 #define LOG | |
57 */ | |
58 | |
59 /* | |
60 * network utilities | |
61 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
62 |
18799 | 63 static int write_stream(int s, const char *buf, int len) { |
64 int total, timeout; | |
65 | |
66 total = 0; timeout = 30; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
67 while (total < len){ |
18799 | 68 int n; |
69 | |
70 n = send (s, &buf[total], len - total, 0); | |
71 | |
72 if (n > 0) | |
73 total += n; | |
74 else if (n < 0) { | |
28402 | 75 #if !HAVE_WINSOCK2_H |
18799 | 76 if ((timeout>0) && ((errno == EAGAIN) || (errno == EINPROGRESS))) { |
77 #else | |
78 if ((timeout>0) && ((errno == EAGAIN) || (WSAGetLastError() == WSAEINPROGRESS))) { | |
79 #endif | |
80 usec_sleep (1000000); timeout--; | |
81 } else | |
82 return -1; | |
83 } | |
84 } | |
85 | |
86 return total; | |
87 } | |
88 | |
89 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
|
90 |
18799 | 91 ssize_t ret, total; |
92 | |
93 total = 0; | |
94 | |
95 while (total < count) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
96 |
18799 | 97 ret=recv (fd, ((uint8_t*)buf)+total, count-total, 0); |
98 | |
99 if (ret<0) { | |
100 if(errno == EAGAIN) { | |
101 fd_set rset; | |
102 struct timeval timeout; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
103 |
18799 | 104 FD_ZERO (&rset); |
105 FD_SET (fd, &rset); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
106 |
18799 | 107 timeout.tv_sec = 30; |
108 timeout.tv_usec = 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
109 |
18799 | 110 if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) { |
111 return -1; | |
112 } | |
113 continue; | |
114 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
115 |
18799 | 116 mp_msg(MSGT_OPEN, MSGL_ERR, "rtsp: read error.\n"); |
117 return ret; | |
118 } else | |
119 total += ret; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
120 |
18799 | 121 /* end of stream */ |
122 if (!ret) break; | |
123 } | |
124 | |
125 return total; | |
126 } | |
127 | |
128 /* | |
129 * rtsp_get gets a line from stream | |
130 * and returns a null terminated string. | |
131 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
132 |
18799 | 133 static char *rtsp_get(rtsp_t *s) { |
134 | |
135 int n=1; | |
136 char *buffer = malloc(BUF_SIZE); | |
137 char *string = NULL; | |
138 | |
139 read_stream(s->s, buffer, 1); | |
140 while (n<BUF_SIZE) { | |
141 read_stream(s->s, &(buffer[n]), 1); | |
142 if ((buffer[n-1]==0x0d)&&(buffer[n]==0x0a)) break; | |
143 n++; | |
144 } | |
145 | |
146 if (n>=BUF_SIZE) { | |
147 mp_msg(MSGT_OPEN, MSGL_FATAL, "librtsp: buffer overflow in rtsp_get\n"); | |
148 exit(1); | |
149 } | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
150 string=malloc(n); |
18799 | 151 memcpy(string,buffer,n-1); |
152 string[n-1]=0; | |
153 | |
154 #ifdef LOG | |
155 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << '%s'\n", string); | |
156 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
157 |
18799 | 158 |
159 free(buffer); | |
160 return string; | |
161 } | |
162 | |
163 /* | |
164 * rtsp_put puts a line on stream | |
165 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
166 |
18799 | 167 static void rtsp_put(rtsp_t *s, const char *string) { |
168 | |
169 int len=strlen(string); | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
170 char *buf=malloc(len+2); |
18799 | 171 |
172 #ifdef LOG | |
173 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: >> '%s'", string); | |
174 #endif | |
175 | |
176 memcpy(buf,string,len); | |
177 buf[len]=0x0d; | |
178 buf[len+1]=0x0a; | |
179 | |
180 write_stream(s->s, buf, len+2); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
181 |
18799 | 182 #ifdef LOG |
183 mp_msg(MSGT_OPEN, MSGL_INFO, " done.\n"); | |
184 #endif | |
185 | |
186 free(buf); | |
187 } | |
188 | |
189 /* | |
190 * extract server status code | |
191 */ | |
192 | |
193 static int rtsp_get_code(const char *string) { | |
194 | |
195 char buf[4]; | |
196 int code=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
197 |
18799 | 198 if (!strncmp(string, RTSP_PROTOCOL_VERSION, strlen(RTSP_PROTOCOL_VERSION))) |
199 { | |
200 memcpy(buf, string+strlen(RTSP_PROTOCOL_VERSION)+1, 3); | |
201 buf[3]=0; | |
202 code=atoi(buf); | |
203 } else if (!strncmp(string, RTSP_METHOD_SET_PARAMETER,8)) | |
204 { | |
205 return RTSP_STATUS_SET_PARAMETER; | |
206 } | |
207 | |
208 if(code != RTSP_STATUS_OK) mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: server responds: '%s'\n",string); | |
209 | |
210 return code; | |
211 } | |
212 | |
213 /* | |
214 * send a request | |
215 */ | |
216 | |
217 static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) { | |
218 | |
219 char **payload=s->scheduled; | |
220 char *buf; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
221 |
18799 | 222 buf = malloc(strlen(type)+strlen(what)+strlen(RTSP_PROTOCOL_VERSION)+3); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
223 |
18799 | 224 sprintf(buf,"%s %s %s",type, what, RTSP_PROTOCOL_VERSION); |
225 rtsp_put(s,buf); | |
226 free(buf); | |
227 if (payload) | |
228 while (*payload) { | |
229 rtsp_put(s,*payload); | |
230 payload++; | |
231 } | |
232 rtsp_put(s,""); | |
233 rtsp_unschedule_all(s); | |
234 } | |
235 | |
236 /* | |
237 * schedule standard fields | |
238 */ | |
239 | |
240 static void rtsp_schedule_standard(rtsp_t *s) { | |
241 | |
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
|
242 char tmp[17]; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
243 |
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
|
244 snprintf(tmp, 17, "CSeq: %u", s->cseq); |
18799 | 245 rtsp_schedule_field(s, tmp); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
246 |
18799 | 247 if (s->session) { |
248 char *buf; | |
249 buf = malloc(strlen(s->session)+15); | |
250 sprintf(buf, "Session: %s", s->session); | |
251 rtsp_schedule_field(s, buf); | |
252 free(buf); | |
253 } | |
254 } | |
255 /* | |
256 * get the answers, if server responses with something != 200, return NULL | |
257 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
258 |
18799 | 259 static int rtsp_get_answers(rtsp_t *s) { |
260 | |
261 char *answer=NULL; | |
262 unsigned int answer_seq; | |
263 char **answer_ptr=s->answers; | |
264 int code; | |
265 int ans_count = 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
266 |
18799 | 267 answer=rtsp_get(s); |
268 if (!answer) | |
269 return 0; | |
270 code=rtsp_get_code(answer); | |
271 free(answer); | |
272 | |
273 rtsp_free_answers(s); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
274 |
18799 | 275 do { /* while we get answer lines */ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
276 |
18799 | 277 answer=rtsp_get(s); |
278 if (!answer) | |
279 return 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
280 |
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
|
281 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
|
282 sscanf(answer,"%*s %u",&answer_seq); |
18799 | 283 if (s->cseq != answer_seq) { |
284 #ifdef LOG | |
285 mp_msg(MSGT_OPEN, MSGL_WARN, "librtsp: warning: CSeq mismatch. got %u, assumed %u", answer_seq, s->cseq); | |
286 #endif | |
287 s->cseq=answer_seq; | |
288 } | |
289 } | |
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
|
290 if (!strncasecmp(answer,"Server:",7)) { |
18799 | 291 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
|
292 sscanf(answer,"%*s %s",buf); |
18799 | 293 if (s->server) free(s->server); |
294 s->server=strdup(buf); | |
295 free(buf); | |
296 } | |
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
|
297 if (!strncasecmp(answer,"Session:",8)) { |
18799 | 298 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
|
299 sscanf(answer,"%*s %s",buf); |
18799 | 300 if (s->session) { |
301 if (strcmp(buf, s->session)) { | |
302 mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: setting NEW session: %s\n", buf); | |
303 free(s->session); | |
304 s->session=strdup(buf); | |
305 } | |
306 } else | |
307 { | |
308 #ifdef LOG | |
309 mp_msg(MSGT_OPEN, MSGL_INFO, "rtsp: setting session id to: %s\n", buf); | |
310 #endif | |
311 s->session=strdup(buf); | |
312 } | |
313 free(buf); | |
314 } | |
315 *answer_ptr=answer; | |
316 answer_ptr++; | |
317 } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS)); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
318 |
18799 | 319 s->cseq++; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
320 |
18799 | 321 *answer_ptr=NULL; |
322 rtsp_schedule_standard(s); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
323 |
18799 | 324 return code; |
325 } | |
326 | |
327 /* | |
328 * send an ok message | |
329 */ | |
330 | |
331 int rtsp_send_ok(rtsp_t *s) { | |
332 char cseq[16]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
333 |
18799 | 334 rtsp_put(s, "RTSP/1.0 200 OK"); |
335 sprintf(cseq,"CSeq: %u", s->cseq); | |
336 rtsp_put(s, cseq); | |
337 rtsp_put(s, ""); | |
338 return 0; | |
339 } | |
340 | |
341 /* | |
342 * implementation of must-have rtsp requests; functions return | |
343 * server status code. | |
344 */ | |
345 | |
346 int rtsp_request_options(rtsp_t *s, const char *what) { | |
347 | |
348 char *buf; | |
349 | |
350 if (what) { | |
351 buf=strdup(what); | |
352 } else | |
353 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
354 buf=malloc(strlen(s->host)+16); |
18799 | 355 sprintf(buf,"rtsp://%s:%i", s->host, s->port); |
356 } | |
357 rtsp_send_request(s,RTSP_METHOD_OPTIONS,buf); | |
358 free(buf); | |
359 | |
360 return rtsp_get_answers(s); | |
361 } | |
362 | |
363 int rtsp_request_describe(rtsp_t *s, const char *what) { | |
364 | |
365 char *buf; | |
366 | |
367 if (what) { | |
368 buf=strdup(what); | |
369 } else | |
370 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
371 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 372 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
373 } | |
374 rtsp_send_request(s,RTSP_METHOD_DESCRIBE,buf); | |
375 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
376 |
18799 | 377 return rtsp_get_answers(s); |
378 } | |
379 | |
380 int rtsp_request_setup(rtsp_t *s, const char *what, char *control) { | |
381 | |
382 char *buf = NULL; | |
383 | |
384 if (what) | |
385 buf = strdup (what); | |
386 else | |
387 { | |
388 int len = strlen (s->host) + strlen (s->path) + 16; | |
389 if (control) | |
390 len += strlen (control) + 1; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
391 |
18799 | 392 buf = malloc (len); |
393 sprintf (buf, "rtsp://%s:%i/%s%s%s", s->host, s->port, s->path, | |
394 control ? "/" : "", control ? control : ""); | |
395 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
396 |
18799 | 397 rtsp_send_request (s, RTSP_METHOD_SETUP, buf); |
398 free (buf); | |
399 return rtsp_get_answers (s); | |
400 } | |
401 | |
402 int rtsp_request_setparameter(rtsp_t *s, const char *what) { | |
403 | |
404 char *buf; | |
405 | |
406 if (what) { | |
407 buf=strdup(what); | |
408 } else | |
409 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
410 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 411 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
412 } | |
413 rtsp_send_request(s,RTSP_METHOD_SET_PARAMETER,buf); | |
414 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
415 |
18799 | 416 return rtsp_get_answers(s); |
417 } | |
418 | |
419 int rtsp_request_play(rtsp_t *s, const char *what) { | |
420 | |
421 char *buf; | |
422 int ret; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
423 |
18799 | 424 if (what) { |
425 buf=strdup(what); | |
426 } else | |
427 { | |
18854
a973acb2e572
cosmetic patch to remove useless sizeof(char) statements
ben
parents:
18853
diff
changeset
|
428 buf=malloc(strlen(s->host)+strlen(s->path)+16); |
18799 | 429 sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); |
430 } | |
431 rtsp_send_request(s,RTSP_METHOD_PLAY,buf); | |
432 free(buf); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
433 |
18799 | 434 ret = rtsp_get_answers (s); |
435 if (ret == RTSP_STATUS_OK) | |
436 s->server_state = RTSP_PLAYING; | |
437 | |
438 return ret; | |
439 } | |
440 | |
441 int rtsp_request_teardown(rtsp_t *s, const char *what) { | |
442 | |
443 char *buf; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
444 |
18799 | 445 if (what) |
446 buf = strdup (what); | |
447 else | |
448 { | |
449 buf = | |
450 malloc (strlen (s->host) + strlen (s->path) + 16); | |
451 sprintf (buf, "rtsp://%s:%i/%s", s->host, s->port, s->path); | |
452 } | |
453 rtsp_send_request (s, RTSP_METHOD_TEARDOWN, buf); | |
454 free (buf); | |
18801 | 455 |
456 /* after teardown we're done with RTSP streaming, no need to get answer as | |
457 reading more will only result to garbage and buffer overflow */ | |
458 return RTSP_STATUS_OK; | |
18799 | 459 } |
460 | |
461 /* | |
462 * read opaque data from stream | |
463 */ | |
464 | |
465 int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) { | |
466 | |
467 int i,seq; | |
468 | |
469 if (size>=4) { | |
470 i=read_stream(s->s, buffer, 4); | |
471 if (i<4) return i; | |
472 if (((buffer[0]=='S')&&(buffer[1]=='E')&&(buffer[2]=='T')&&(buffer[3]=='_')) || | |
473 ((buffer[0]=='O')&&(buffer[1]=='P')&&(buffer[2]=='T')&&(buffer[3]=='I'))) // OPTIONS | |
474 { | |
475 char *rest=rtsp_get(s); | |
476 if (!rest) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
477 return -1; |
18799 | 478 |
479 seq=-1; | |
480 do { | |
481 free(rest); | |
482 rest=rtsp_get(s); | |
483 if (!rest) | |
484 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
|
485 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
|
486 sscanf(rest,"%*s %u",&seq); |
18799 | 487 } while (strlen(rest)!=0); |
488 free(rest); | |
489 if (seq<0) { | |
490 #ifdef LOG | |
491 mp_msg(MSGT_OPEN, MSGL_WARN, "rtsp: warning: CSeq not recognized!\n"); | |
492 #endif | |
493 seq=1; | |
494 } | |
495 /* let's make the server happy */ | |
496 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
|
497 rest=malloc(17); |
18799 | 498 sprintf(rest,"CSeq: %u", seq); |
499 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
|
500 free(rest); |
18799 | 501 rtsp_put(s, ""); |
502 i=read_stream(s->s, buffer, size); | |
503 } else | |
504 { | |
505 i=read_stream(s->s, buffer+4, size-4); | |
506 i+=4; | |
507 } | |
508 } else | |
509 i=read_stream(s->s, buffer, size); | |
510 #ifdef LOG | |
511 mp_msg(MSGT_OPEN, MSGL_INFO, "librtsp: << %d of %d bytes\n", i, size); | |
512 #endif | |
513 | |
514 return i; | |
515 } | |
516 | |
517 /* | |
518 * connect to a rtsp server | |
519 */ | |
520 | |
521 //rtsp_t *rtsp_connect(const char *mrl, const char *user_agent) { | |
522 rtsp_t *rtsp_connect(int fd, char* mrl, char *path, char *host, int port, char *user_agent) { | |
523 | |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
524 rtsp_t *s; |
18799 | 525 int i; |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
526 |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
527 if (fd < 0) { |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
528 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
|
529 return NULL; |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
530 } |
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 s = malloc(sizeof(rtsp_t)); |
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
533 |
18799 | 534 for (i=0; i<MAX_FIELDS; i++) { |
535 s->answers[i]=NULL; | |
536 s->scheduled[i]=NULL; | |
537 } | |
538 | |
27103
a3f6dc43b585
Move rtsp_close away by simplification - avoids symbol clash with libnemesi
lu_zero
parents:
19271
diff
changeset
|
539 s->s = fd; |
18799 | 540 s->server=NULL; |
541 s->server_state=0; | |
542 s->server_caps=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
543 |
18799 | 544 s->cseq=0; |
545 s->session=NULL; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
546 |
18799 | 547 if (user_agent) |
548 s->user_agent=strdup(user_agent); | |
549 else | |
550 s->user_agent=strdup("User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)"); | |
551 | |
552 s->mrl = strdup(mrl); | |
553 s->host = strdup(host); | |
554 s->port = port; | |
555 s->path = strdup(path); | |
556 while (*path == '/') | |
557 path++; | |
558 if ((s->param = strchr(s->path, '?')) != NULL) | |
559 s->param++; | |
560 //mp_msg(MSGT_OPEN, MSGL_INFO, "path=%s\n", s->path); | |
561 //mp_msg(MSGT_OPEN, MSGL_INFO, "param=%s\n", s->param ? s->param : "NULL"); | |
562 | |
563 s->server_state=RTSP_CONNECTED; | |
564 | |
565 /* now let's send an options request. */ | |
566 rtsp_schedule_field(s, "CSeq: 1"); | |
567 rtsp_schedule_field(s, s->user_agent); | |
568 rtsp_schedule_field(s, "ClientChallenge: 9e26d33f2984236010ef6253fb1887f7"); | |
569 rtsp_schedule_field(s, "PlayerStarttime: [28/03/2003:22:50:23 00:00]"); | |
570 rtsp_schedule_field(s, "CompanyID: KnKV4M4I/B2FjJ1TToLycw=="); | |
571 rtsp_schedule_field(s, "GUID: 00000000-0000-0000-0000-000000000000"); | |
572 rtsp_schedule_field(s, "RegionData: 0"); | |
573 rtsp_schedule_field(s, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); | |
574 /*rtsp_schedule_field(s, "Pragma: initiate-session");*/ | |
575 rtsp_request_options(s, NULL); | |
576 | |
577 return s; | |
578 } | |
579 | |
580 | |
581 /* | |
582 * search in answers for tags. returns a pointer to the content | |
583 * after the first matched tag. returns NULL if no match found. | |
584 */ | |
585 | |
586 char *rtsp_search_answers(rtsp_t *s, const char *tag) { | |
587 | |
588 char **answer; | |
589 char *ptr; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
590 |
18799 | 591 if (!s->answers) return NULL; |
592 answer=s->answers; | |
593 | |
594 while (*answer) { | |
595 if (!strncasecmp(*answer,tag,strlen(tag))) { | |
596 ptr=strchr(*answer,':'); | |
597 if (!ptr) return NULL; | |
598 ptr++; | |
599 while(*ptr==' ') ptr++; | |
600 return ptr; | |
601 } | |
602 answer++; | |
603 } | |
604 | |
605 return NULL; | |
606 } | |
607 | |
608 /* | |
609 * session id management | |
610 */ | |
611 | |
612 void rtsp_set_session(rtsp_t *s, const char *id) { | |
613 | |
614 if (s->session) free(s->session); | |
615 | |
616 s->session=strdup(id); | |
617 | |
618 } | |
619 | |
620 char *rtsp_get_session(rtsp_t *s) { | |
621 | |
622 return s->session; | |
623 | |
624 } | |
625 | |
626 char *rtsp_get_mrl(rtsp_t *s) { | |
627 | |
628 return s->mrl; | |
629 | |
630 } | |
631 | |
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
|
632 char *rtsp_get_param(rtsp_t *s, const char *p) { |
18799 | 633 int len; |
634 char *param; | |
635 if (!s->param) | |
636 return NULL; | |
637 if (!p) | |
638 return strdup(s->param); | |
639 len = strlen(p); | |
640 param = s->param; | |
641 while (param && *param) { | |
642 char *nparam = strchr(param, '&'); | |
643 if (strncmp(param, p, len) == 0 && param[len] == '=') { | |
644 param += len + 1; | |
645 len = nparam ? nparam - param : strlen(param); | |
646 nparam = malloc(len + 1); | |
647 memcpy(nparam, param, len); | |
648 nparam[len] = 0; | |
649 return nparam; | |
650 } | |
651 param = nparam ? nparam + 1 : NULL; | |
652 } | |
653 return NULL; | |
654 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
655 |
18799 | 656 /* |
657 * schedules a field for transmission | |
658 */ | |
659 | |
660 void rtsp_schedule_field(rtsp_t *s, const char *string) { | |
661 | |
662 int i=0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
663 |
18799 | 664 if (!string) return; |
665 | |
666 while(s->scheduled[i]) { | |
667 i++; | |
668 } | |
669 s->scheduled[i]=strdup(string); | |
670 } | |
671 | |
672 /* | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
673 * removes the first scheduled field which prefix matches string. |
18799 | 674 */ |
675 | |
676 void rtsp_unschedule_field(rtsp_t *s, const char *string) { | |
677 | |
678 char **ptr=s->scheduled; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
679 |
18799 | 680 if (!string) return; |
681 | |
682 while(*ptr) { | |
683 if (!strncmp(*ptr, string, strlen(string))) | |
684 break; | |
685 else | |
686 ptr++; | |
687 } | |
688 if (*ptr) free(*ptr); | |
689 ptr++; | |
690 do { | |
691 *(ptr-1)=*ptr; | |
692 } while(*ptr); | |
693 } | |
694 | |
695 /* | |
696 * unschedule all fields | |
697 */ | |
698 | |
699 void rtsp_unschedule_all(rtsp_t *s) { | |
700 | |
701 char **ptr; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
702 |
18799 | 703 if (!s->scheduled) return; |
704 ptr=s->scheduled; | |
705 | |
706 while (*ptr) { | |
707 free(*ptr); | |
708 *ptr=NULL; | |
709 ptr++; | |
710 } | |
711 } | |
712 /* | |
713 * free answers | |
714 */ | |
715 | |
716 void rtsp_free_answers(rtsp_t *s) { | |
717 | |
718 char **answer; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28402
diff
changeset
|
719 |
18799 | 720 if (!s->answers) return; |
721 answer=s->answers; | |
722 | |
723 while (*answer) { | |
724 free(*answer); | |
725 *answer=NULL; | |
726 answer++; | |
727 } | |
728 } |