summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/rtsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/rtsp.c')
-rw-r--r--Utilities/cmcurl/lib/rtsp.c151
1 files changed, 84 insertions, 67 deletions
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index dbd7dc6a6..55766757a 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#ifndef CURL_DISABLE_RTSP
+#if !defined(CURL_DISABLE_RTSP) && !defined(USE_HYPER)
#include "urldata.h"
#include <curl/curl.h>
@@ -48,11 +48,13 @@
((int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
-static CURLcode rtsp_do(struct connectdata *conn, bool *done);
-static CURLcode rtsp_done(struct connectdata *conn, CURLcode, bool premature);
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done);
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead);
-static int rtsp_getsock_do(struct connectdata *conn, curl_socket_t *socks);
+static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
+static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature);
+static CURLcode rtsp_connect(struct Curl_easy *data, bool *done);
+static CURLcode rtsp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead);
+static int rtsp_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn, curl_socket_t *socks);
/*
* Parse and write out any available RTP data.
@@ -66,23 +68,26 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
ssize_t *nread,
bool *readmore);
-static CURLcode rtsp_setup_connection(struct connectdata *conn);
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn);
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *check,
unsigned int checks_to_perform);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int rtsp_getsock_do(struct connectdata *conn,
+static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks)
{
/* write mode */
+ (void)data;
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
/*
@@ -106,15 +111,18 @@ const struct Curl_handler Curl_handler_rtsp = {
rtsp_conncheck, /* connection_check */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
+ CURLPROTO_RTSP, /* family */
PROTOPT_NONE /* flags */
};
-static CURLcode rtsp_setup_connection(struct connectdata *conn)
+static CURLcode rtsp_setup_connection(struct Curl_easy *data,
+ struct connectdata *conn)
{
struct RTSP *rtsp;
+ (void)conn;
- conn->data->req.protop = rtsp = calloc(1, sizeof(struct RTSP));
+ data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
if(!rtsp)
return CURLE_OUT_OF_MEMORY;
@@ -155,13 +163,15 @@ static bool rtsp_connisdead(struct connectdata *check)
/*
* Function to check on various aspects of a connection.
*/
-static unsigned int rtsp_conncheck(struct connectdata *check,
+static unsigned int rtsp_conncheck(struct Curl_easy *data,
+ struct connectdata *conn,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
+ (void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) {
- if(rtsp_connisdead(check))
+ if(rtsp_connisdead(conn))
ret_val |= CONNRESULT_DEAD;
}
@@ -169,12 +179,11 @@ static unsigned int rtsp_conncheck(struct connectdata *check,
}
-static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
+static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
{
CURLcode httpStatus;
- struct Curl_easy *data = conn->data;
- httpStatus = Curl_http_connect(conn, done);
+ httpStatus = Curl_http_connect(data, done);
/* Initialize the CSeq if not already done */
if(data->state.rtsp_next_client_CSeq == 0)
@@ -182,31 +191,32 @@ static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
if(data->state.rtsp_next_server_CSeq == 0)
data->state.rtsp_next_server_CSeq = 1;
- conn->proto.rtspc.rtp_channel = -1;
+ data->conn->proto.rtspc.rtp_channel = -1;
return httpStatus;
}
-static CURLcode rtsp_disconnect(struct connectdata *conn, bool dead)
+static CURLcode rtsp_disconnect(struct Curl_easy *data,
+ struct connectdata *conn, bool dead)
{
(void) dead;
+ (void) data;
Curl_safefree(conn->proto.rtspc.rtp_buf);
return CURLE_OK;
}
-static CURLcode rtsp_done(struct connectdata *conn,
+static CURLcode rtsp_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct Curl_easy *data = conn->data;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
CURLcode httpStatus;
/* Bypass HTTP empty-reply checks on receive */
if(data->set.rtspreq == RTSPREQ_RECEIVE)
premature = TRUE;
- httpStatus = Curl_http_done(conn, status, premature);
+ httpStatus = Curl_http_done(data, status, premature);
if(rtsp) {
/* Check the sequence numbers */
@@ -219,7 +229,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
return CURLE_RTSP_CSEQ_ERROR;
}
if(data->set.rtspreq == RTSPREQ_RECEIVE &&
- (conn->proto.rtspc.rtp_channel == -1)) {
+ (data->conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
}
}
@@ -227,12 +237,12 @@ static CURLcode rtsp_done(struct connectdata *conn,
return httpStatus;
}
-static CURLcode rtsp_do(struct connectdata *conn, bool *done)
+static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
{
- struct Curl_easy *data = conn->data;
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
struct dynbuf req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -329,7 +339,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport");
+ p_transport = Curl_checkheaders(data, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -353,11 +363,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept")?
+ p_accept = Curl_checkheaders(data, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding") &&
+ if(!Curl_checkheaders(data, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(data->state.aptr.accept_encoding);
data->state.aptr.accept_encoding =
@@ -374,17 +384,18 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) {
+ if(Curl_checkheaders(data, "User-Agent") && data->state.aptr.uagent) {
Curl_safefree(data->state.aptr.uagent);
data->state.aptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent") &&
+ else if(!Curl_checkheaders(data, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = data->state.aptr.uagent;
}
/* setup the authentication headers */
- result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE);
+ result = Curl_http_output_auth(data, conn, p_request, HTTPREQ_GET,
+ p_stream_uri, FALSE);
if(result)
return result;
@@ -393,7 +404,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
Curl_safefree(data->state.aptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
+ if(data->change.referer && !Curl_checkheaders(data, "Referer"))
data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
data->state.aptr.ref = NULL;
@@ -410,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range") && data->state.range) {
+ if(!Curl_checkheaders(data, "Range") && data->state.range) {
Curl_safefree(data->state.aptr.rangeline);
data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = data->state.aptr.rangeline;
@@ -420,11 +431,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq")) {
+ if(Curl_checkheaders(data, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session")) {
+ if(Curl_checkheaders(data, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -483,12 +494,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
- result = Curl_add_timecondition(conn, &req_buffer);
+ result = Curl_add_timecondition(data, &req_buffer);
if(result)
return result;
}
- result = Curl_add_custom_headers(conn, FALSE, &req_buffer);
+ result = Curl_add_custom_headers(data, FALSE, &req_buffer);
if(result)
return result;
@@ -511,7 +522,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length")) {
+ if(!Curl_checkheaders(data, "Content-Length")) {
result =
Curl_dyn_addf(&req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
@@ -522,7 +533,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -531,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type")) {
+ if(!Curl_checkheaders(data, "Content-Type")) {
result = Curl_dyn_addf(&req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
@@ -563,7 +574,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* issue the request */
- result = Curl_buffer_send(&req_buffer, conn,
+ result = Curl_buffer_send(&req_buffer, data,
&data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
@@ -579,7 +590,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* if a request-body has been sent off, we make sure this progress is
noted properly */
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
- if(Curl_pgrsUpdate(conn))
+ if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
}
@@ -641,7 +652,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
* Write out the header including the leading '$' */
DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
+ result = rtp_client_write(data, &rtp[0], rtp_length + 4);
if(result) {
failf(data, "Got an error writing an RTP packet");
*readmore = FALSE;
@@ -712,9 +723,8 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
}
static
-CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
{
- struct Curl_easy *data = conn->data;
size_t wrote;
curl_write_callback writeit;
void *user_ptr;
@@ -754,17 +764,15 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
return CURLE_OK;
}
-CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
- char *header)
+CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
{
- struct Curl_easy *data = conn->data;
long CSeq = 0;
if(checkprefix("CSeq:", header)) {
/* Store the received CSeq. Match is verified in rtsp_done */
int nc = sscanf(&header[4], ": %ld", &CSeq);
if(nc == 1) {
- struct RTSP *rtsp = data->req.protop;
+ struct RTSP *rtsp = data->req.p.rtsp;
rtsp->CSeq_recv = CSeq; /* mark the request */
data->state.rtsp_CSeq_recv = CSeq; /* update the handle */
}
@@ -775,6 +783,8 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
}
else if(checkprefix("Session:", header)) {
char *start;
+ char *end;
+ size_t idlen;
/* Find the first non-space letter */
start = header + 8;
@@ -783,11 +793,25 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
if(!*start) {
failf(data, "Got a blank Session ID");
+ return CURLE_RTSP_SESSION_ERROR;
}
- else if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
+ /* Find the end of Session ID
+ *
+ * Allow any non whitespace content, up to the field separator or end of
+ * line. RFC 2326 isn't 100% clear on the session ID and for example
+ * gstreamer does url-encoded session ID's not covered by the standard.
+ */
+ end = start;
+ while(*end && *end != ';' && !ISSPACE(*end))
+ end++;
+ idlen = end - start;
+
+ if(data->set.str[STRING_RTSP_SESSION_ID]) {
+
/* If the Session ID is set, then compare */
- if(strncmp(start, data->set.str[STRING_RTSP_SESSION_ID],
- strlen(data->set.str[STRING_RTSP_SESSION_ID])) != 0) {
+ if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
+ strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen) != 0) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]);
return CURLE_RTSP_SESSION_ERROR;
@@ -796,24 +820,17 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
else {
/* If the Session ID is not set, and we find it in a response, then set
* it.
- *
- * Allow any non whitespace content, up to the field separator or end of
- * line. RFC 2326 isn't 100% clear on the session ID and for example
- * gstreamer does url-encoded session ID's not covered by the standard.
*/
- char *end = start;
- while(*end && *end != ';' && !ISSPACE(*end))
- end++;
/* Copy the id substring into a new buffer */
- data->set.str[STRING_RTSP_SESSION_ID] = malloc(end - start + 1);
+ data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
if(data->set.str[STRING_RTSP_SESSION_ID] == NULL)
return CURLE_OUT_OF_MEMORY;
- memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, end - start);
- (data->set.str[STRING_RTSP_SESSION_ID])[end - start] = '\0';
+ memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
+ (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
}
}
return CURLE_OK;
}
-#endif /* CURL_DISABLE_RTSP */
+#endif /* CURL_DISABLE_RTSP or using Hyper */