mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
rtp: fix 'size mismatch' on BSD style operating systems
On FreeBSD (and probably other BSDs as well), the FIONREAD ioctl on UDP sockets does not return the size of the next datagram (like it does on Linux), but returns the size of the output buffer: this count contain multiple datagrams and also contains the headers. We fixed this by taking the result of the FIONREAD as lower bound for the size, adding an upper bound and then removing the check that the sizes should be exactly the same. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/718>
This commit is contained in:
parent
d7a633df89
commit
9f32b7d7ee
2 changed files with 30 additions and 10 deletions
|
|
@ -200,7 +200,6 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
|
|||
uint32_t ssrc;
|
||||
uint8_t payload;
|
||||
unsigned cc;
|
||||
ssize_t r;
|
||||
uint8_t aux[1024];
|
||||
bool found_tstamp = false;
|
||||
|
||||
|
|
@ -209,6 +208,15 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
|
|||
|
||||
pa_memchunk_reset(chunk);
|
||||
|
||||
/* FIONREAD works on both BSD and Linux, but they do something different:
|
||||
* - on Linux it returns the amount of bytes in the next datagram
|
||||
* - on BSDs it returns the total amount of bytes in the output buffer; this can be
|
||||
* more than one datagram and includes headers
|
||||
*
|
||||
* So the result will be a lower bound of how many bytes are needed, but might not be
|
||||
* the exact size of the buffer size needed.
|
||||
*/
|
||||
|
||||
if (ioctl(c->fd, FIONREAD, &size) < 0) {
|
||||
pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
|
|
@ -238,6 +246,9 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
|
|||
size = 1;
|
||||
}
|
||||
|
||||
/* Since size is a lower bound, also constrain it to an upper bound */
|
||||
size = PA_MIN(size, 1<<16);
|
||||
|
||||
if (c->recv_buf_size < (size_t) size) {
|
||||
do
|
||||
c->recv_buf_size *= 2;
|
||||
|
|
@ -259,12 +270,11 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
|
|||
m.msg_controllen = sizeof(aux);
|
||||
m.msg_flags = 0;
|
||||
|
||||
r = recvmsg(c->fd, &m, 0);
|
||||
|
||||
if (r != size) {
|
||||
if (r < 0 && errno != EAGAIN && errno != EINTR)
|
||||
pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
size = recvmsg(c->fd, &m, 0);
|
||||
|
||||
if (size < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR)
|
||||
pa_log_warn("recvmsg() failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,15 +146,25 @@ int pa_sap_recv(pa_sap_context *c, bool *goodbye) {
|
|||
char *buf = NULL, *e;
|
||||
uint32_t header;
|
||||
unsigned six, ac, k;
|
||||
ssize_t r;
|
||||
|
||||
|
||||
pa_assert(c);
|
||||
pa_assert(goodbye);
|
||||
|
||||
/* FIONREAD works on both BSD and Linux, but they do something different:
|
||||
* - on Linux it returns the amount of bytes in the next datagram
|
||||
* - on BSDs it returns the total amount of bytes in the output buffer; this can be
|
||||
* more than one datagram and includes headers
|
||||
*
|
||||
* So the result will be a lower bound of how many bytes are needed, but might not be
|
||||
* the exact size of the buffer size needed.
|
||||
*/
|
||||
|
||||
if (ioctl(c->fd, FIONREAD, &size) < 0) {
|
||||
pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
/* Since size is a lower bound, also constrain it to an upper bound */
|
||||
size = PA_MIN(size, 1<<16);
|
||||
|
||||
buf = pa_xnew(char, (unsigned) size+1);
|
||||
buf[size] = 0;
|
||||
|
|
@ -170,8 +180,8 @@ int pa_sap_recv(pa_sap_context *c, bool *goodbye) {
|
|||
m.msg_controllen = 0;
|
||||
m.msg_flags = 0;
|
||||
|
||||
if ((r = recvmsg(c->fd, &m, 0)) != size) {
|
||||
pa_log_warn("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
|
||||
if ((size = recvmsg(c->fd, &m, 0)) < 0) {
|
||||
pa_log_warn("recvmsg() failed: %s", pa_cstrerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue