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