comparison rtsp.c @ 4877:940946a4569b libavformat

Send dummy requests over the TCP connection (WMS wants GET_PARAMETER, Real wants OPTIONS) while the connection is idle, otherwise it will be aborted after a short period (usually a minute). See the thread "[PATCH] rtsp.c: keep-alive" on the mailinglist.
author rbultje
date Wed, 15 Apr 2009 13:04:34 +0000
parents 13a2a1a475d5
children 609322be76a6
comparison
equal deleted inserted replaced
4876:3a1ffb822e81 4877:940946a4569b
680 const char *p; 680 const char *p;
681 681
682 /* NOTE: we do case independent match for broken servers */ 682 /* NOTE: we do case independent match for broken servers */
683 p = buf; 683 p = buf;
684 if (av_stristart(p, "Session:", &p)) { 684 if (av_stristart(p, "Session:", &p)) {
685 int t;
685 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p); 686 get_word_sep(reply->session_id, sizeof(reply->session_id), ";", &p);
687 if (av_stristart(p, ";timeout=", &p) &&
688 (t = strtol(p, NULL, 10)) > 0) {
689 reply->timeout = t;
690 }
686 } else if (av_stristart(p, "Content-Length:", &p)) { 691 } else if (av_stristart(p, "Content-Length:", &p)) {
687 reply->content_length = strtol(p, NULL, 10); 692 reply->content_length = strtol(p, NULL, 10);
688 } else if (av_stristart(p, "Transport:", &p)) { 693 } else if (av_stristart(p, "Transport:", &p)) {
689 rtsp_parse_transport(reply, p); 694 rtsp_parse_transport(reply, p);
690 } else if (av_stristart(p, "CSeq:", &p)) { 695 } else if (av_stristart(p, "CSeq:", &p)) {
835 av_free(content); 840 av_free(content);
836 841
837 return 0; 842 return 0;
838 } 843 }
839 844
840 static void rtsp_send_cmd(AVFormatContext *s, 845 static void rtsp_send_cmd_async (AVFormatContext *s,
841 const char *cmd, RTSPMessageHeader *reply, 846 const char *cmd, RTSPMessageHeader *reply,
842 unsigned char **content_ptr) 847 unsigned char **content_ptr)
843 { 848 {
844 RTSPState *rt = s->priv_data; 849 RTSPState *rt = s->priv_data;
845 char buf[4096], buf1[1024]; 850 char buf[4096], buf1[1024];
855 av_strlcat(buf, "\r\n", sizeof(buf)); 860 av_strlcat(buf, "\r\n", sizeof(buf));
856 #ifdef DEBUG 861 #ifdef DEBUG
857 printf("Sending:\n%s--\n", buf); 862 printf("Sending:\n%s--\n", buf);
858 #endif 863 #endif
859 url_write(rt->rtsp_hd, buf, strlen(buf)); 864 url_write(rt->rtsp_hd, buf, strlen(buf));
865 rt->last_cmd_time = av_gettime();
866 }
867
868 static void rtsp_send_cmd (AVFormatContext *s,
869 const char *cmd, RTSPMessageHeader *reply,
870 unsigned char **content_ptr)
871 {
872 rtsp_send_cmd_async(s, cmd, reply, content_ptr);
860 873
861 rtsp_read_reply(s, reply, content_ptr, 0); 874 rtsp_read_reply(s, reply, content_ptr, 0);
862 } 875 }
863 876
864 877
940 953
941 if (rt->transport == RTSP_TRANSPORT_RDT) 954 if (rt->transport == RTSP_TRANSPORT_RDT)
942 trans_pref = "x-pn-tng"; 955 trans_pref = "x-pn-tng";
943 else 956 else
944 trans_pref = "RTP/AVP"; 957 trans_pref = "RTP/AVP";
958
959 /* default timeout: 1 minute */
960 rt->timeout = 60;
945 961
946 /* for each stream, make the setup request */ 962 /* for each stream, make the setup request */
947 /* XXX: we assume the same server is used for the control of each 963 /* XXX: we assume the same server is used for the control of each
948 RTSP stream */ 964 RTSP stream */
949 965
1120 } 1136 }
1121 1137
1122 if ((err = rtsp_open_transport_ctx(s, rtsp_st))) 1138 if ((err = rtsp_open_transport_ctx(s, rtsp_st)))
1123 goto fail; 1139 goto fail;
1124 } 1140 }
1141
1142 if (reply->timeout > 0)
1143 rt->timeout = reply->timeout;
1125 1144
1126 if (rt->server_type == RTSP_SERVER_REAL) 1145 if (rt->server_type == RTSP_SERVER_REAL)
1127 rt->need_subscription = 1; 1146 rt->need_subscription = 1;
1128 1147
1129 return 0; 1148 return 0;
1401 { 1420 {
1402 RTSPState *rt = s->priv_data; 1421 RTSPState *rt = s->priv_data;
1403 RTSPStream *rtsp_st; 1422 RTSPStream *rtsp_st;
1404 int ret, len; 1423 int ret, len;
1405 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH]; 1424 uint8_t buf[10 * RTP_MAX_PACKET_LENGTH];
1425 RTSPMessageHeader reply1, *reply = &reply1;
1426 char cmd[1024];
1406 1427
1407 if (rt->server_type == RTSP_SERVER_REAL) { 1428 if (rt->server_type == RTSP_SERVER_REAL) {
1408 int i; 1429 int i;
1409 RTSPMessageHeader reply1, *reply = &reply1;
1410 enum AVDiscard cache[MAX_STREAMS]; 1430 enum AVDiscard cache[MAX_STREAMS];
1411 char cmd[1024];
1412 1431
1413 for (i = 0; i < s->nb_streams; i++) 1432 for (i = 0; i < s->nb_streams; i++)
1414 cache[i] = s->streams[i]->discard; 1433 cache[i] = s->streams[i]->discard;
1415 1434
1416 if (!rt->need_subscription) { 1435 if (!rt->need_subscription) {
1506 goto redo; 1525 goto redo;
1507 if (ret == 1) { 1526 if (ret == 1) {
1508 /* more packets may follow, so we save the RTP context */ 1527 /* more packets may follow, so we save the RTP context */
1509 rt->cur_transport_priv = rtsp_st->transport_priv; 1528 rt->cur_transport_priv = rtsp_st->transport_priv;
1510 } 1529 }
1530
1531 /* send dummy request to keep TCP connection alive */
1532 if ((rt->server_type == RTSP_SERVER_WMS ||
1533 rt->server_type == RTSP_SERVER_REAL) &&
1534 (av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
1535 if (rt->server_type == RTSP_SERVER_WMS) {
1536 snprintf(cmd, sizeof(cmd) - 1,
1537 "GET_PARAMETER %s RTSP/1.0\r\n",
1538 s->filename);
1539 rtsp_send_cmd_async(s, cmd, reply, NULL);
1540 } else {
1541 rtsp_send_cmd_async(s, "OPTIONS * RTSP/1.0\r\n",
1542 reply, NULL);
1543 }
1544 }
1545
1511 return 0; 1546 return 0;
1512 } 1547 }
1513 1548
1514 static int rtsp_read_play(AVFormatContext *s) 1549 static int rtsp_read_play(AVFormatContext *s)
1515 { 1550 {