* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, 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
* -incoming server requests
* -server CSeq counter
* -digest authentication
- * -connect thru proxy
+ * -connect through proxy
* -pipelining?
*/
static CURLcode rtsp_setup_connection(struct connectdata *conn);
+bool rtsp_connisdead(struct connectdata *check);
+static unsigned int rtsp_conncheck(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
ZERO_NULL, /* perform_getsock */
rtsp_disconnect, /* disconnect */
rtsp_rtp_readwrite, /* readwrite */
+ rtsp_conncheck, /* connection_check */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
PROTOPT_NONE /* flags */
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-bool Curl_rtsp_connisdead(struct connectdata *check)
+bool rtsp_connisdead(struct connectdata *check)
{
int sval;
bool ret_val = TRUE;
return ret_val;
}
+/*
+ * Function to check on various aspects of a connection.
+ */
+static unsigned int rtsp_conncheck(struct connectdata *check,
+ unsigned int checks_to_perform)
+{
+ unsigned int ret_val = CONNRESULT_NONE;
+
+ if(checks_to_perform & CONNCHECK_ISDEAD) {
+ if(rtsp_connisdead(check))
+ ret_val |= CONNRESULT_DEAD;
+ }
+
+ return ret_val;
+}
+
+
static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
{
CURLcode httpStatus;
CSeq_sent, CSeq_recv);
return CURLE_RTSP_CSEQ_ERROR;
}
- else if(data->set.rtspreq == RTSPREQ_RECEIVE &&
+ if(data->set.rtspreq == RTSPREQ_RECEIVE &&
(conn->proto.rtspc.rtp_channel == -1)) {
infof(data, "Got an RTP Receive with a CSeq of %ld\n", CSeq_recv);
/* TODO CPC: Server -> Client logic here */
static CURLcode rtsp_do(struct connectdata *conn, bool *done)
{
struct Curl_easy *data = conn->data;
- CURLcode result=CURLE_OK;
+ CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp = data->req.protop;
struct HTTP *http;
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport:");
+ p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept:")?
+ p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
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:") && conn->allocptr.uagent) {
+ if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
/* Referrer */
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
(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(conn, "Range") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq:")) {
+ if(Curl_checkheaders(conn, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session:")) {
+ if(Curl_checkheaders(conn, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
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(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
*readmore = TRUE;
break;
}
- else {
- /* We have the full RTP interleaved packet
- * 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);
- if(result) {
- failf(data, "Got an error writing an RTP packet");
- *readmore = FALSE;
- Curl_safefree(rtspc->rtp_buf);
- rtspc->rtp_buf = NULL;
- rtspc->rtp_bufsize = 0;
- return result;
- }
+ /* We have the full RTP interleaved packet
+ * 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);
+ if(result) {
+ failf(data, "Got an error writing an RTP packet");
+ *readmore = FALSE;
+ Curl_safefree(rtspc->rtp_buf);
+ rtspc->rtp_buf = NULL;
+ rtspc->rtp_bufsize = 0;
+ return result;
+ }
- /* Move forward in the buffer */
- rtp_dataleft -= rtp_length + 4;
- rtp += rtp_length + 4;
+ /* Move forward in the buffer */
+ rtp_dataleft -= rtp_length + 4;
+ rtp += rtp_length + 4;
- if(data->set.rtspreq == RTSPREQ_RECEIVE) {
- /* If we are in a passive receive, give control back
- * to the app as often as we can.
- */
- k->keepon &= ~KEEP_RECV;
- }
+ if(data->set.rtspreq == RTSPREQ_RECEIVE) {
+ /* If we are in a passive receive, give control back
+ * to the app as often as we can.
+ */
+ k->keepon &= ~KEEP_RECV;
}
}
else {
*nread = 0;
return CURLE_OK;
}
- else {
- /* Fix up k->str to point just after the last RTP packet */
- k->str += *nread - rtp_dataleft;
+ /* Fix up k->str to point just after the last RTP packet */
+ k->str += *nread - rtp_dataleft;
- /* either all of the data has been read or...
- * rtp now points at the next byte to parse
- */
- if(rtp_dataleft > 0)
- DEBUGASSERT(k->str[0] == rtp[0]);
+ /* either all of the data has been read or...
+ * rtp now points at the next byte to parse
+ */
+ if(rtp_dataleft > 0)
+ DEBUGASSERT(k->str[0] == rtp[0]);
- DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
+ DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */
- *nread = rtp_dataleft;
- }
+ *nread = rtp_dataleft;
/* If we get here, we have finished with the leftover/merge buffer */
Curl_safefree(rtspc->rtp_buf);
struct Curl_easy *data = conn->data;
size_t wrote;
curl_write_callback writeit;
+ void *user_ptr;
if(len == 0) {
failf(data, "Cannot write a 0 size RTP packet.");
return CURLE_WRITE_ERROR;
}
- writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
- wrote = writeit(ptr, 1, len, data->set.rtp_out);
+ /* If the user has configured CURLOPT_INTERLEAVEFUNCTION then use that
+ function and any configured CURLOPT_INTERLEAVEDATA to write out the RTP
+ data. Otherwise, use the CURLOPT_WRITEFUNCTION with the CURLOPT_WRITEDATA
+ pointer to write out the RTP data. */
+ if(data->set.fwrite_rtp) {
+ writeit = data->set.fwrite_rtp;
+ user_ptr = data->set.rtp_out;
+ }
+ else
+ {
+ writeit = data->set.fwrite_func;
+ user_ptr = data->set.out;
+ }
+
+ Curl_set_in_callback(data, true);
+ wrote = writeit(ptr, 1, len, user_ptr);
+ Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf(data, "Cannot pause RTP");
/* 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 seperator or end of
+ * 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.
*/