summaryrefslogtreecommitdiffstats
path: root/src/polypcore
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2006-05-11 11:08:58 +0000
committerPierre Ossman <ossman@cendio.se>2006-05-11 11:08:58 +0000
commit48d66cd5e89764b00fe225db4823b3392a759942 (patch)
tree0e60a5cf549d07f6be53e60fa83b355fd77a7094 /src/polypcore
parent12d4b5d952c7a284fd081966a02d34d94dd6be10 (diff)
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
Diffstat (limited to 'src/polypcore')
-rw-r--r--src/polypcore/iochannel.c28
-rw-r--r--src/polypcore/pipe.c160
-rw-r--r--src/polypcore/pipe.h22
-rw-r--r--src/polypcore/util.c45
-rw-r--r--src/polypcore/util.h2
5 files changed, 229 insertions, 28 deletions
diff --git a/src/polypcore/iochannel.c b/src/polypcore/iochannel.c
index 5da7a9a9..623925ac 100644
--- a/src/polypcore/iochannel.c
+++ b/src/polypcore/iochannel.c
@@ -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);
diff --git a/src/polypcore/pipe.c b/src/polypcore/pipe.c
new file mode 100644
index 00000000..eef6d533
--- /dev/null
+++ b/src/polypcore/pipe.c
@@ -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 */
diff --git a/src/polypcore/pipe.h b/src/polypcore/pipe.h
new file mode 100644
index 00000000..a9b088b5
--- /dev/null
+++ b/src/polypcore/pipe.h
@@ -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]);
diff --git a/src/polypcore/util.c b/src/polypcore/util.c
index 191fa809..beb93f45 100644
--- a/src/polypcore/util.c
+++ b/src/polypcore/util.c
@@ -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)
diff --git a/src/polypcore/util.h b/src/polypcore/util.h
index ca81b229..a7c65381 100644
--- a/src/polypcore/util.h
+++ b/src/polypcore/util.h
@@ -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);