mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-03 09:01:50 -05:00
Handle pipes on platforms where they are non-existant of broken.
We do this by creating a TCP socket pair instead of a normal pipe. Since Windows isn't UNIX-y enough to support read()/write() on sockets, we also need a wrapper to handle read() vs recv() and write() vs send(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@840 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
12d4b5d952
commit
48d66cd5e8
9 changed files with 249 additions and 107 deletions
|
|
@ -202,19 +202,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
|
|||
assert(l);
|
||||
assert(io->ofd >= 0);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
r = send(io->ofd, data, l, 0);
|
||||
if (r < 0) {
|
||||
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||
errno = WSAGetLastError();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
#endif
|
||||
r = write(io->ofd, data, l);
|
||||
|
||||
r = pa_write(io->ofd, data, l);
|
||||
if (r >= 0) {
|
||||
io->writable = 0;
|
||||
enable_mainloop_sources(io);
|
||||
|
|
@ -229,20 +217,8 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
|
|||
assert(io);
|
||||
assert(data);
|
||||
assert(io->ifd >= 0);
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
r = recv(io->ifd, data, l, 0);
|
||||
if (r < 0) {
|
||||
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||
errno = WSAGetLastError();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
#endif
|
||||
r = read(io->ifd, data, l);
|
||||
|
||||
r = pa_read(io->ifd, data, l);
|
||||
if (r >= 0) {
|
||||
io->readable = 0;
|
||||
enable_mainloop_sources(io);
|
||||
|
|
|
|||
160
src/polypcore/pipe.c
Normal file
160
src/polypcore/pipe.c
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of polypaudio.
|
||||
|
||||
polypaudio is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
polypaudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with polypaudio; If not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA.
|
||||
***/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
#include "pipe.h"
|
||||
|
||||
#ifndef HAVE_PIPE
|
||||
|
||||
static int set_block(int fd, int blocking) {
|
||||
#ifdef O_NONBLOCK
|
||||
|
||||
int v;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if ((v = fcntl(fd, F_GETFL)) < 0)
|
||||
return -1;
|
||||
|
||||
if (blocking)
|
||||
v &= ~O_NONBLOCK;
|
||||
else
|
||||
v |= O_NONBLOCK;
|
||||
|
||||
if (fcntl(fd, F_SETFL, v) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(OS_IS_WIN32)
|
||||
|
||||
u_long arg;
|
||||
|
||||
arg = !blocking;
|
||||
|
||||
if (ioctlsocket(fd, FIONBIO, &arg) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
return -1;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int pipe(int filedes[2]) {
|
||||
int listener;
|
||||
struct sockaddr_in addr, peer;
|
||||
socklen_t len;
|
||||
|
||||
listener = -1;
|
||||
filedes[0] = -1;
|
||||
filedes[1] = -1;
|
||||
|
||||
listener = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (listener < 0)
|
||||
goto error;
|
||||
|
||||
filedes[0] = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (filedes[0] < 0)
|
||||
goto error;
|
||||
|
||||
filedes[1] = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (filedes[1] < 0)
|
||||
goto error;
|
||||
|
||||
/* Make non-blocking so that connect() won't block */
|
||||
if (set_block(filedes[0], 0) < 0)
|
||||
goto error;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||
goto error;
|
||||
|
||||
if (listen(listener, 1) < 0)
|
||||
goto error;
|
||||
|
||||
len = sizeof(addr);
|
||||
if (getsockname(listener, (struct sockaddr*)&addr, &len) < 0)
|
||||
goto error;
|
||||
|
||||
if (connect(filedes[0], (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
#ifdef OS_IS_WIN32
|
||||
if (WSAGetLastError() != EWOULDBLOCK)
|
||||
#else
|
||||
if (errno != EINPROGRESS)
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
|
||||
len = sizeof(peer);
|
||||
filedes[1] = accept(listener, (struct sockaddr*)&peer, &len);
|
||||
if (filedes[1] < 0)
|
||||
goto error;
|
||||
|
||||
/* Restore blocking */
|
||||
if (set_block(filedes[0], 1) < 0)
|
||||
goto error;
|
||||
|
||||
len = sizeof(addr);
|
||||
if (getsockname(filedes[0], (struct sockaddr*)&addr, &len) < 0)
|
||||
goto error;
|
||||
|
||||
/* Check that someone else didn't steal the connection */
|
||||
if ((addr.sin_port != peer.sin_port) || (addr.sin_addr.s_addr != peer.sin_addr.s_addr))
|
||||
goto error;
|
||||
|
||||
close(listener);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (listener >= 0)
|
||||
close(listener);
|
||||
if (filedes[0] >= 0)
|
||||
close(filedes[0]);
|
||||
if (filedes[1] >= 0)
|
||||
close(filedes[0]);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_PIPE */
|
||||
22
src/polypcore/pipe.h
Normal file
22
src/polypcore/pipe.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* $Id$ */
|
||||
|
||||
/***
|
||||
This file is part of polypaudio.
|
||||
|
||||
polypaudio is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
polypaudio is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with polypaudio; If not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA.
|
||||
***/
|
||||
|
||||
int pipe(int filedes[2]);
|
||||
|
|
@ -198,6 +198,47 @@ finish:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/** Platform independent read function. Necessary since not all systems
|
||||
* treat all file descriptors equal. */
|
||||
ssize_t pa_read(int fd, void *buf, size_t count) {
|
||||
ssize_t r;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
r = recv(fd, buf, count, 0);
|
||||
if (r < 0) {
|
||||
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||
errno = WSAGetLastError();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
#endif
|
||||
r = read(fd, buf, count);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Similar to pa_read(), but handles writes */
|
||||
ssize_t pa_write(int fd, void *buf, size_t count) {
|
||||
ssize_t r;
|
||||
|
||||
#ifdef OS_IS_WIN32
|
||||
r = send(fd, buf, count, 0);
|
||||
if (r < 0) {
|
||||
if (WSAGetLastError() != WSAENOTSOCK) {
|
||||
errno = WSAGetLastError();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
#endif
|
||||
r = write(fd, buf, count);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Calls read() in a loop. Makes sure that as much as 'size' bytes,
|
||||
* unless EOF is reached or an error occured */
|
||||
ssize_t pa_loop_read(int fd, void*data, size_t size) {
|
||||
|
|
@ -207,7 +248,7 @@ ssize_t pa_loop_read(int fd, void*data, size_t size) {
|
|||
while (size > 0) {
|
||||
ssize_t r;
|
||||
|
||||
if ((r = read(fd, data, size)) < 0)
|
||||
if ((r = pa_read(fd, data, size)) < 0)
|
||||
return r;
|
||||
|
||||
if (r == 0)
|
||||
|
|
@ -229,7 +270,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) {
|
|||
while (size > 0) {
|
||||
ssize_t r;
|
||||
|
||||
if ((r = write(fd, data, size)) < 0)
|
||||
if ((r = pa_write(fd, data, size)) < 0)
|
||||
return r;
|
||||
|
||||
if (r == 0)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ void pa_make_nonblock_fd(int fd);
|
|||
int pa_make_secure_dir(const char* dir);
|
||||
int pa_make_secure_parent_dir(const char *fn);
|
||||
|
||||
ssize_t pa_read(int fd, void *buf, size_t count);
|
||||
ssize_t pa_write(int fd, void *buf, size_t count);
|
||||
ssize_t pa_loop_read(int fd, void*data, size_t size);
|
||||
ssize_t pa_loop_write(int fd, const void*data, size_t size);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue