aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorspiff <spiff@xbmc.org>2012-08-04 20:03:01 +0200
committerspiff <spiff@xbmc.org>2012-08-04 20:04:54 +0200
commitb5cf00aec8feec1629b8cba992c9decc9d51a75c (patch)
tree33141439a2b1b6de198d2ef3e02449a8bb319072 /lib
parent482ff6f2c9abe01214510cadf8a7d45188fa58e4 (diff)
rtsp: Handle requests from server to client
This returns 200 OK for OPTIONS requests and 501 Not Implemented for all other requests. Even though this doesn't do much actual handling of the requests, it makes the code properly identify server requests as such, instead of interpreting it as a reply to the client's request as it did before. backports upstream 1a6b9a98ceacc3aca35ab354f9e97e3ac01b0ded
Diffstat (limited to 'lib')
-rw-r--r--lib/ffmpeg/libavformat/rtsp.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/lib/ffmpeg/libavformat/rtsp.c b/lib/ffmpeg/libavformat/rtsp.c
index c2a0d26e5e..2fccea1bea 100644
--- a/lib/ffmpeg/libavformat/rtsp.c
+++ b/lib/ffmpeg/libavformat/rtsp.c
@@ -900,9 +900,13 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
char buf[4096], buf1[1024], *q;
unsigned char ch;
const char *p;
- int ret, content_length, line_count = 0;
+ int ret, content_length, line_count = 0, request = 0;
unsigned char *content = NULL;
+start:
+ line_count = 0;
+ request = 0;
+ content = NULL;
memset(reply, 0, sizeof(*reply));
/* parse reply (XXX: use buffers) */
@@ -938,9 +942,15 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
if (line_count == 0) {
/* get reply code */
get_word(buf1, sizeof(buf1), &p);
- get_word(buf1, sizeof(buf1), &p);
- reply->status_code = atoi(buf1);
- av_strlcpy(reply->reason, p, sizeof(reply->reason));
+ if (!strncmp(buf1, "RTSP/", 5)) {
+ get_word(buf1, sizeof(buf1), &p);
+ reply->status_code = atoi(buf1);
+ av_strlcpy(reply->reason, p, sizeof(reply->reason));
+ } else {
+ av_strlcpy(reply->reason, buf1, sizeof(reply->reason)); // method
+ get_word(buf1, sizeof(buf1), &p); // object
+ request = 1;
+ }
} else {
ff_rtsp_parse_line(reply, p, rt, method);
av_strlcat(rt->last_reply, p, sizeof(rt->last_reply));
@@ -949,7 +959,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
line_count++;
}
- if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0')
+ if (rt->session_id[0] == '\0' && reply->session_id[0] != '\0' && !request)
av_strlcpy(rt->session_id, reply->session_id, sizeof(rt->session_id));
content_length = reply->content_length;
@@ -964,6 +974,44 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
else
av_free(content);
+ if (request) {
+ char buf[1024];
+ char base64buf[AV_BASE64_SIZE(sizeof(buf))];
+ const char* ptr = buf;
+
+ if (!strcmp(reply->reason, "OPTIONS")) {
+ snprintf(buf, sizeof(buf), "RTSP/1.0 200 OK\r\n");
+ if (reply->seq)
+ av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", reply->seq);
+ if (reply->session_id[0])
+ av_strlcatf(buf, sizeof(buf), "Session: %s\r\n",
+ reply->session_id);
+ } else {
+ snprintf(buf, sizeof(buf), "RTSP/1.0 501 Not Implemented\r\n");
+ }
+ av_strlcat(buf, "\r\n", sizeof(buf));
+
+ if (rt->control_transport == RTSP_MODE_TUNNEL) {
+ av_base64_encode(base64buf, sizeof(base64buf), buf, strlen(buf));
+ ptr = base64buf;
+ }
+ ffurl_write(rt->rtsp_hd_out, ptr, strlen(ptr));
+
+ rt->last_cmd_time = av_gettime();
+ /* Even if the request from the server had data, it is not the data
+ * that the caller wants or expects. The memory could also be leaked
+ * if the actual following reply has content data. */
+ if (content_ptr)
+ av_freep(content_ptr);
+ /* If method is set, this is called from ff_rtsp_send_cmd,
+ * where a reply to exactly this request is awaited. For
+ * callers from within packet reciving, we just want to
+ * return to the caller and go back to receiving packets. */
+ if (method)
+ goto start;
+ return 0;
+ }
+
if (rt->seq != reply->seq) {
av_log(s, AV_LOG_WARNING, "CSeq %d expected, %d received.\n",
rt->seq, reply->seq);