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