| 306 | | /** Aggregate RTSP callback */ |
|---|
| 307 | | static int RtspCallback( httpd_callback_sys_t *p_args, |
|---|
| 308 | | httpd_client_t *cl, |
|---|
| 309 | | httpd_message_t *answer, |
|---|
| 310 | | const httpd_message_t *query ) |
|---|
| 311 | | { |
|---|
| 312 | | rtsp_stream_t *rtsp = (rtsp_stream_t *)p_args; |
|---|
| | 306 | /** Finds the next transport choice */ |
|---|
| | 307 | static inline const char *transport_next( const char *str ) |
|---|
| | 308 | { |
|---|
| | 309 | /* Looks for comma */ |
|---|
| | 310 | str = strchr( str, ',' ); |
|---|
| | 311 | if( str == NULL ) |
|---|
| | 312 | return NULL; /* No more transport options */ |
|---|
| | 313 | |
|---|
| | 314 | str++; /* skips comma */ |
|---|
| | 315 | while( strchr( "\r\n\t ", *str ) ) |
|---|
| | 316 | str++; |
|---|
| | 317 | |
|---|
| | 318 | return (*str) ? str : NULL; |
|---|
| | 319 | } |
|---|
| | 320 | |
|---|
| | 321 | |
|---|
| | 322 | /** Finds the next transport parameter */ |
|---|
| | 323 | static inline const char *parameter_next( const char *str ) |
|---|
| | 324 | { |
|---|
| | 325 | while( strchr( ",;", *str ) == NULL ) |
|---|
| | 326 | str++; |
|---|
| | 327 | |
|---|
| | 328 | return (*str == ';') ? (str + 1) : NULL; |
|---|
| | 329 | } |
|---|
| | 330 | |
|---|
| | 331 | |
|---|
| | 332 | /** RTSP requests handler |
|---|
| | 333 | * @param id selected track for non-aggregate URLs, |
|---|
| | 334 | * NULL for aggregate URLs |
|---|
| | 335 | */ |
|---|
| | 336 | static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, |
|---|
| | 337 | httpd_client_t *cl, |
|---|
| | 338 | httpd_message_t *answer, |
|---|
| | 339 | const httpd_message_t *query ) |
|---|
| | 340 | { |
|---|
| | 341 | sout_stream_t *p_stream = id->stream->owner; |
|---|
| | 342 | char psz_sesbuf[17]; |
|---|
| 380 | | vlc_mutex_lock( &rtsp->lock ); |
|---|
| 381 | | ses = RtspClientGet( rtsp, psz_session ); |
|---|
| 382 | | if( ses != NULL ) |
|---|
| 383 | | { |
|---|
| 384 | | for( int i = 0; i < ses->trackc; i++ ) |
|---|
| 385 | | { |
|---|
| 386 | | rtsp_strack_t *tr = ses->trackv + i; |
|---|
| 387 | | if( !tr->playing ) |
|---|
| 388 | | { |
|---|
| 389 | | tr->playing = VLC_TRUE; |
|---|
| 390 | | rtp_add_sink( tr->id, tr->access ); |
|---|
| 391 | | } |
|---|
| 392 | | } |
|---|
| 393 | | } |
|---|
| 394 | | vlc_mutex_unlock( &rtsp->lock ); |
|---|
| 395 | | |
|---|
| 396 | | if( httpd_MsgGet( query, "Scale" ) != NULL ) |
|---|
| 397 | | httpd_MsgAdd( answer, "Scale", "1." ); |
|---|
| 398 | | break; |
|---|
| 399 | | } |
|---|
| 400 | | |
|---|
| 401 | | case HTTPD_MSG_PAUSE: |
|---|
| 402 | | answer->i_status = 405; |
|---|
| 403 | | httpd_MsgAdd( answer, "Allow", |
|---|
| 404 | | "DESCRIBE, TEARDOWN, PLAY, GET_PARAMETER" ); |
|---|
| 405 | | break; |
|---|
| 406 | | |
|---|
| 407 | | case HTTPD_MSG_GETPARAMETER: |
|---|
| 408 | | if( query->i_body > 0 ) |
|---|
| 409 | | { |
|---|
| 410 | | answer->i_status = 451; |
|---|
| 411 | | break; |
|---|
| 412 | | } |
|---|
| 413 | | |
|---|
| 414 | | answer->i_status = 200; |
|---|
| 415 | | break; |
|---|
| 416 | | |
|---|
| 417 | | case HTTPD_MSG_TEARDOWN: |
|---|
| 418 | | { |
|---|
| 419 | | rtsp_session_t *ses; |
|---|
| 420 | | |
|---|
| 421 | | /* for now only multicast so easy again */ |
|---|
| 422 | | answer->i_status = 200; |
|---|
| 423 | | |
|---|
| 425 | | |
|---|
| 426 | | vlc_mutex_lock( &rtsp->lock ); |
|---|
| 427 | | ses = RtspClientGet( rtsp, psz_session ); |
|---|
| 428 | | if( ses != NULL ) |
|---|
| 429 | | RtspClientDel( rtsp, ses ); |
|---|
| 430 | | vlc_mutex_unlock( &rtsp->lock ); |
|---|
| 431 | | break; |
|---|
| 432 | | } |
|---|
| 433 | | |
|---|
| 434 | | default: |
|---|
| 435 | | return VLC_EGENERIC; |
|---|
| 436 | | } |
|---|
| 437 | | |
|---|
| 438 | | httpd_MsgAdd( answer, "Server", "%s", PACKAGE_STRING ); |
|---|
| 439 | | httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body ); |
|---|
| 440 | | |
|---|
| 441 | | psz = httpd_MsgGet( query, "Cseq" ); |
|---|
| 442 | | if( psz != NULL ) |
|---|
| 443 | | httpd_MsgAdd( answer, "Cseq", "%s", psz ); |
|---|
| 444 | | psz = httpd_MsgGet( query, "Timestamp" ); |
|---|
| 445 | | if( psz != NULL ) |
|---|
| 446 | | httpd_MsgAdd( answer, "Timestamp", "%s", psz ); |
|---|
| 447 | | |
|---|
| 448 | | httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" ); |
|---|
| 449 | | |
|---|
| 450 | | if( psz_session ) |
|---|
| 451 | | httpd_MsgAdd( answer, "Session", "%s;timeout=5", psz_session ); |
|---|
| 452 | | return VLC_SUCCESS; |
|---|
| 453 | | } |
|---|
| 454 | | |
|---|
| 455 | | |
|---|
| 456 | | /** Finds the next transport choice */ |
|---|
| 457 | | static inline const char *transport_next( const char *str ) |
|---|
| 458 | | { |
|---|
| 459 | | /* Looks for comma */ |
|---|
| 460 | | str = strchr( str, ',' ); |
|---|
| 461 | | if( str == NULL ) |
|---|
| 462 | | return NULL; /* No more transport options */ |
|---|
| 463 | | |
|---|
| 464 | | str++; /* skips comma */ |
|---|
| 465 | | while( strchr( "\r\n\t ", *str ) ) |
|---|
| 466 | | str++; |
|---|
| 467 | | |
|---|
| 468 | | return (*str) ? str : NULL; |
|---|
| 469 | | } |
|---|
| 470 | | |
|---|
| 471 | | |
|---|
| 472 | | /** Finds the next transport parameter */ |
|---|
| 473 | | static inline const char *parameter_next( const char *str ) |
|---|
| 474 | | { |
|---|
| 475 | | while( strchr( ",;", *str ) == NULL ) |
|---|
| 476 | | str++; |
|---|
| 477 | | |
|---|
| 478 | | return (*str == ';') ? (str + 1) : NULL; |
|---|
| 479 | | } |
|---|
| 480 | | |
|---|
| 481 | | |
|---|
| 482 | | /** Non-aggregate RTSP callback */ |
|---|
| 483 | | static int RtspCallbackId( httpd_callback_sys_t *p_args, |
|---|
| 484 | | httpd_client_t *cl, |
|---|
| 485 | | httpd_message_t *answer, |
|---|
| 486 | | const httpd_message_t *query ) |
|---|
| 487 | | { |
|---|
| 488 | | rtsp_stream_id_t *id = (rtsp_stream_id_t *)p_args; |
|---|
| 489 | | rtsp_stream_t *rtsp = id->stream; |
|---|
| 490 | | sout_stream_t *p_stream = id->stream->owner; |
|---|
| 491 | | char psz_sesbuf[17]; |
|---|
| 492 | | const char *psz_session, *psz; |
|---|
| 493 | | |
|---|
| 494 | | if( answer == NULL || query == NULL ) |
|---|
| 495 | | return VLC_SUCCESS; |
|---|
| 496 | | |
|---|
| 497 | | /* */ |
|---|
| 498 | | answer->i_proto = HTTPD_PROTO_RTSP; |
|---|
| 499 | | answer->i_version= query->i_version; |
|---|
| 500 | | answer->i_type = HTTPD_MSG_ANSWER; |
|---|
| 501 | | answer->i_body = 0; |
|---|
| 502 | | answer->p_body = NULL; |
|---|
| 503 | | |
|---|
| 504 | | psz_session = httpd_MsgGet( query, "Session" ); |
|---|
| 505 | | |
|---|
| 506 | | if( httpd_MsgGet( query, "Require" ) != NULL ) |
|---|
| 507 | | { |
|---|
| 508 | | answer->i_status = 551; |
|---|
| 509 | | httpd_MsgAdd( answer, "Unsupported", "%s", |
|---|
| 510 | | httpd_MsgGet( query, "Require" ) ); |
|---|
| 511 | | } |
|---|
| 512 | | else |
|---|
| 513 | | switch( query->i_type ) |
|---|
| 514 | | { |
|---|
| 515 | | case HTTPD_MSG_SETUP: |
|---|
| 516 | | { |
|---|
| | 693 | |
|---|
| | 694 | |
|---|
| | 695 | /** Aggregate RTSP callback */ |
|---|
| | 696 | static int RtspCallback( httpd_callback_sys_t *p_args, |
|---|
| | 697 | httpd_client_t *cl, |
|---|
| | 698 | httpd_message_t *answer, |
|---|
| | 699 | const httpd_message_t *query ) |
|---|
| | 700 | { |
|---|
| | 701 | return RtspHandler( (rtsp_stream_t *)p_args, NULL, cl, answer, query ); |
|---|
| | 702 | } |
|---|
| | 703 | |
|---|
| | 704 | |
|---|
| | 705 | /** Non-aggregate RTSP callback */ |
|---|
| | 706 | static int RtspCallbackId( httpd_callback_sys_t *p_args, |
|---|
| | 707 | httpd_client_t *cl, |
|---|
| | 708 | httpd_message_t *answer, |
|---|
| | 709 | const httpd_message_t *query ) |
|---|
| | 710 | { |
|---|
| | 711 | rtsp_stream_id_t *id = (rtsp_stream_id_t *)p_args; |
|---|
| | 712 | return RtspHandler( id->stream, id, cl, answer, query ); |
|---|
| | 713 | } |
|---|