diff --git a/lib/rtsp.c b/lib/rtsp.c index b8965ff15b..3eebd5ace2 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -119,6 +119,7 @@ const struct Curl_handler Curl_handler_rtsp = { PROTOPT_NONE /* flags */ }; +#define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */ static CURLcode rtsp_setup_connection(struct Curl_easy *data, struct connectdata *conn) @@ -130,6 +131,7 @@ static CURLcode rtsp_setup_connection(struct Curl_easy *data, if(!rtsp) return CURLE_OUT_OF_MEMORY; + Curl_dyn_init(&conn->proto.rtspc.buf, MAX_RTP_BUFFERSIZE); return CURLE_OK; } @@ -176,7 +178,7 @@ static CURLcode rtsp_disconnect(struct Curl_easy *data, { (void) dead; (void) data; - Curl_safefree(conn->proto.rtspc.rtp_buf); + Curl_dyn_free(&conn->proto.rtspc.buf); return CURLE_OK; } @@ -204,7 +206,7 @@ static CURLcode rtsp_done(struct Curl_easy *data, return CURLE_RTSP_CSEQ_ERROR; } if(data->set.rtspreq == RTSPREQ_RECEIVE && - (data->conn->proto.rtspc.rtp_channel == -1)) { + (data->conn->proto.rtspc.rtp_channel == -1)) { infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv); } } @@ -598,25 +600,16 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, char *rtp; /* moving pointer to rtp data */ ssize_t rtp_dataleft; /* how much data left to parse in this round */ - char *scratch; CURLcode result; bool interleaved = false; size_t skip_size = 0; - if(rtspc->rtp_buf) { - /* There was some leftover data the last time. Merge buffers */ - char *newptr = Curl_saferealloc(rtspc->rtp_buf, - rtspc->rtp_bufsize + *nread); - if(!newptr) { - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; + if(Curl_dyn_len(&rtspc->buf)) { + /* There was some leftover data the last time. Append new buffers */ + if(Curl_dyn_addn(&rtspc->buf, k->str, *nread)) return CURLE_OUT_OF_MEMORY; - } - rtspc->rtp_buf = newptr; - memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread); - rtspc->rtp_bufsize += *nread; - rtp = rtspc->rtp_buf; - rtp_dataleft = rtspc->rtp_bufsize; + rtp = Curl_dyn_ptr(&rtspc->buf); + rtp_dataleft = Curl_dyn_len(&rtspc->buf); } else { /* Just parse the request buffer directly */ @@ -667,9 +660,6 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, result = rtp_client_write(data, &rtp[0], rtp_length + 4); if(result) { *readmore = FALSE; - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; return result; } @@ -716,20 +706,18 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, if(rtp_dataleft && rtp[0] == '$') { DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft, - *readmore ? "(READMORE)" : "")); + *readmore ? "(READMORE)" : "")); /* Store the incomplete RTP packet for a "rewind" */ - scratch = malloc(rtp_dataleft); - if(!scratch) { - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; - return CURLE_OUT_OF_MEMORY; + if(!Curl_dyn_len(&rtspc->buf)) { + /* nothing was stored, add this data */ + if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft)) + return CURLE_OUT_OF_MEMORY; + } + else { + /* keep the remainder */ + Curl_dyn_tail(&rtspc->buf, rtp_dataleft); } - memcpy(scratch, rtp, rtp_dataleft); - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = scratch; - rtspc->rtp_bufsize = rtp_dataleft; /* As far as the transfer is concerned, this data is consumed */ *nread = 0; @@ -738,20 +726,10 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, /* 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]); - - DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */ - *nread = rtp_dataleft; /* If we get here, we have finished with the leftover/merge buffer */ - Curl_safefree(rtspc->rtp_buf); - rtspc->rtp_buf = NULL; - rtspc->rtp_bufsize = 0; + Curl_dyn_free(&rtspc->buf); return CURLE_OK; } diff --git a/lib/rtsp.h b/lib/rtsp.h index 6e55616b38..111bac2a61 100644 --- a/lib/rtsp.h +++ b/lib/rtsp.h @@ -45,8 +45,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header); * Currently, only used for tracking incomplete RTP data reads */ struct rtsp_conn { - char *rtp_buf; - ssize_t rtp_bufsize; + struct dynbuf buf; int rtp_channel; };