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.

Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
Tommy Winther 2011-10-12 12:26:45 +03:00 committed by Martin Storsjö
parent f234e8a32e
commit 1a6b9a98ce

View File

@ -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);