Mercurial > mplayer.hg
annotate stream/librtsp/rtsp.c @ 31523:7ab5787e625c
configure: Fix detection of SDL backend for vo_gl on OS X
SDL overrides main, and provides a prototype for SDL_main
which uses argc and argv. Since the prototype didn't match
the main() in the test program, it failed to compile, making
the test fail when it should have worked.
author | astrange |
---|---|
date | Wed, 30 Jun 2010 09:27:03 +0000 |
parents | b01f807eb183 |
children | 8fa2f43cb760 |
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); |
18799 | 294 if (s->server) free(s->server); |
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 | |
615 if (s->session) free(s->session); | |
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 } | |
689 if (*ptr) free(*ptr); | |
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 } |