]> code.delx.au - pulseaudio/blob - src/pulsecore/pipe.c
big s/polyp/pulse/g
[pulseaudio] / src / pulsecore / pipe.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 PulseAudio is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published
8 by the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with PulseAudio; If not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include <sys/types.h>
31
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>
34 #endif
35
36 #include "winsock.h"
37
38 #include "pipe.h"
39
40 #ifndef HAVE_PIPE
41
42 static int set_block(int fd, int blocking) {
43 #ifdef O_NONBLOCK
44
45 int v;
46
47 assert(fd >= 0);
48
49 if ((v = fcntl(fd, F_GETFL)) < 0)
50 return -1;
51
52 if (blocking)
53 v &= ~O_NONBLOCK;
54 else
55 v |= O_NONBLOCK;
56
57 if (fcntl(fd, F_SETFL, v) < 0)
58 return -1;
59
60 return 0;
61
62 #elif defined(OS_IS_WIN32)
63
64 u_long arg;
65
66 arg = !blocking;
67
68 if (ioctlsocket(fd, FIONBIO, &arg) < 0)
69 return -1;
70
71 return 0;
72
73 #else
74
75 return -1;
76
77 #endif
78 }
79
80 int pipe(int filedes[2]) {
81 int listener;
82 struct sockaddr_in addr, peer;
83 socklen_t len;
84
85 listener = -1;
86 filedes[0] = -1;
87 filedes[1] = -1;
88
89 listener = socket(PF_INET, SOCK_STREAM, 0);
90 if (listener < 0)
91 goto error;
92
93 filedes[0] = socket(PF_INET, SOCK_STREAM, 0);
94 if (filedes[0] < 0)
95 goto error;
96
97 filedes[1] = socket(PF_INET, SOCK_STREAM, 0);
98 if (filedes[1] < 0)
99 goto error;
100
101 /* Make non-blocking so that connect() won't block */
102 if (set_block(filedes[0], 0) < 0)
103 goto error;
104
105 addr.sin_family = AF_INET;
106 addr.sin_port = 0;
107 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
108
109 if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
110 goto error;
111
112 if (listen(listener, 1) < 0)
113 goto error;
114
115 len = sizeof(addr);
116 if (getsockname(listener, (struct sockaddr*)&addr, &len) < 0)
117 goto error;
118
119 if (connect(filedes[0], (struct sockaddr*)&addr, sizeof(addr)) < 0) {
120 #ifdef OS_IS_WIN32
121 if (WSAGetLastError() != EWOULDBLOCK)
122 #else
123 if (errno != EINPROGRESS)
124 #endif
125 goto error;
126 }
127
128 len = sizeof(peer);
129 filedes[1] = accept(listener, (struct sockaddr*)&peer, &len);
130 if (filedes[1] < 0)
131 goto error;
132
133 /* Restore blocking */
134 if (set_block(filedes[0], 1) < 0)
135 goto error;
136
137 len = sizeof(addr);
138 if (getsockname(filedes[0], (struct sockaddr*)&addr, &len) < 0)
139 goto error;
140
141 /* Check that someone else didn't steal the connection */
142 if ((addr.sin_port != peer.sin_port) || (addr.sin_addr.s_addr != peer.sin_addr.s_addr))
143 goto error;
144
145 close(listener);
146
147 return 0;
148
149 error:
150 if (listener >= 0)
151 close(listener);
152 if (filedes[0] >= 0)
153 close(filedes[0]);
154 if (filedes[1] >= 0)
155 close(filedes[0]);
156
157 return -1;
158 }
159
160 #endif /* HAVE_PIPE */