source: roaraudio/libroar/vio_pipe.c @ 1470:9ada8abbf75d

Last change on this file since 1470:9ada8abbf75d was 1470:9ada8abbf75d, checked in by phi, 15 years ago

replaced shutdown() by ROAR_SHUTDOWN() to make it optional

File size: 7.5 KB
Line 
1//vio_pipe.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_vio_open_pipe (struct roar_vio_calls * s0, struct roar_vio_calls * s1, int type, int flags) {
38#ifndef ROAR_WITHOUT_VIO_PIPE
39 struct roar_vio_pipe * self;
40 int                    rw = flags & (O_RDONLY|O_WRONLY|O_RDWR);
41
42 if ( s0 == NULL || s1 == NULL )
43  return -1;
44
45 if ( (self = malloc(sizeof(struct roar_vio_pipe))) == NULL )
46  return -1;
47
48 memset(self, 0, sizeof(struct roar_vio_pipe));
49
50 self->refcount = 2;
51 self->flags    = flags;
52
53 if ( type == ROAR_VIO_PIPE_TYPE_AUTO ) {
54#ifdef ROAR_TARGET_WIN32
55  type = ROAR_VIO_PIPE_TYPE_BUFFER;
56#else
57  type = ROAR_VIO_PIPE_TYPE_SOCKET;
58#endif
59 }
60
61 self->type     = type;
62
63 switch (type) {
64  case ROAR_VIO_PIPE_TYPE_BUFFER:
65    // no buffers need to be set up here,
66    // we handle the NULL pointer in the reader and writer func
67    free(self);
68    return -1;
69   break;
70  case ROAR_VIO_PIPE_TYPE_PIPE:
71    self->b.p[0] = self->b.p[1] = self->b.p[2] = self->b.p[3] = -1;
72
73    if ( rw == O_RDWR || rw == O_RDONLY )
74     if ( pipe(self->b.p) == -1 ) {
75      free(self);
76      return -1;
77     }
78    if ( rw == O_RDWR || rw == O_WRONLY )
79     if ( pipe((self->b.p) + 2) == -1 ) {
80      close(self->b.p[0]);
81      close(self->b.p[1]);
82      free(self);
83      return -1;
84     }
85   break;
86  case ROAR_VIO_PIPE_TYPE_SOCKET:
87    if ( socketpair(AF_UNIX, SOCK_STREAM, 0, self->b.p) == -1 ) {
88     free(self);
89     return -1;
90    }
91
92    if ( rw == O_RDONLY ) {
93     ROAR_SHUTDOWN(self->b.p[0], SHUT_WR);
94     ROAR_SHUTDOWN(self->b.p[1], SHUT_RD);
95    } else if ( rw == O_WRONLY ) {
96     ROAR_SHUTDOWN(self->b.p[0], SHUT_RD);
97     ROAR_SHUTDOWN(self->b.p[1], SHUT_WR);
98    }
99   break;
100  default:
101    free(self);
102    return -1;
103 }
104
105 roar_vio_pipe_init(s0, self, flags);
106 roar_vio_pipe_init(s1, self, flags);
107
108 self->s0 = s0;
109
110 return 0;
111#else
112 return -1;
113#endif
114}
115
116#ifndef ROAR_WITHOUT_VIO_PIPE
117int roar_vio_pipe_init (struct roar_vio_calls * s,  struct roar_vio_pipe * self, int flags) {
118 if ( s == NULL || self == NULL )
119  return -1;
120
121 memset(s, 0, sizeof(struct roar_vio_calls));
122
123 s->close    = roar_vio_pipe_close;
124 s->read     = roar_vio_pipe_read;
125 s->write    = roar_vio_pipe_write;
126 s->nonblock = roar_vio_pipe_nonblock;
127 s->sync     = roar_vio_pipe_sync;
128
129 s->inst = (void*) self;
130
131 if ( flags & O_NONBLOCK ) {
132  roar_vio_pipe_nonblock(s, ROAR_SOCKET_NONBLOCK);
133 }
134
135 return 0;
136}
137
138int     roar_vio_pipe_close   (struct roar_vio_calls * vio) {
139 struct roar_vio_pipe * self;
140 int                    idx;
141
142 if ( vio == NULL )
143  return -1;
144
145 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
146  return -1;
147
148 self->refcount--;
149
150 switch (self->type) {
151  case ROAR_VIO_PIPE_TYPE_BUFFER:
152    // this will be a bit more complex as we need to change the flags, too.
153   break;
154  case ROAR_VIO_PIPE_TYPE_PIPE:
155   switch (ROAR_VIO_PIPE_S(self, vio)) {
156    case 0:
157      close(self->b.p[0]);
158      close(self->b.p[3]);
159      self->b.p[0] = -1;
160      self->b.p[3] = -1;
161     break;
162    case 1:
163      close(self->b.p[1]);
164      close(self->b.p[2]);
165      self->b.p[1] = -1;
166      self->b.p[2] = -1;
167     break;
168   }
169   break;
170  case ROAR_VIO_PIPE_TYPE_SOCKET:
171    close(self->b.p[idx = ROAR_VIO_PIPE_S(self, vio)]);
172    self->b.p[idx] = -1;
173   break;
174 }
175
176 if ( ! self->refcount ) {
177  free(self);
178 }
179
180 vio->inst = NULL;
181 return 0;
182}
183
184int     roar_vio_pipe_nonblock(struct roar_vio_calls * vio, int state) {
185 struct roar_vio_pipe * self;
186
187 if ( vio == NULL )
188  return -1;
189
190 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
191  return -1;
192
193 switch (self->type) {
194  case ROAR_VIO_PIPE_TYPE_PIPE:
195    if ( roar_socket_nonblock(self->b.p[ROAR_VIO_PIPE_S(self,vio)*2], state) == -1 )
196     return -1;
197    return roar_socket_nonblock(self->b.p[(ROAR_VIO_PIPE_SR(self,vio)*2)+1], state);
198   break;
199  case ROAR_VIO_PIPE_TYPE_SOCKET:
200    return roar_socket_nonblock(self->b.p[ROAR_VIO_PIPE_S(self,vio)], state);
201   break;
202 }
203
204 return -1;
205}
206
207int     roar_vio_pipe_sync    (struct roar_vio_calls * vio) {
208 // we may add fdatasync() calls here depending on the type
209 // but in general they should not be needed on pipes.
210 return 0;
211}
212
213ssize_t roar_vio_pipe_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
214 struct roar_vio_pipe * self;
215 int                    idx;
216
217 if ( vio == NULL )
218  return -1;
219
220 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
221  return -1;
222
223 switch (self->type) {
224  case ROAR_VIO_PIPE_TYPE_BUFFER:
225    idx = ROAR_VIO_PIPE_S(self,vio);
226
227    if ( (idx == 0 ? O_WRONLY : O_RDONLY) == (self->flags & (O_RDONLY|O_WRONLY|O_RDWR)) ) {
228     raise(SIGPIPE);
229     return -1;
230    }
231
232    if ( self->b.b[idx] == NULL )
233     return 0;
234
235    if ( roar_buffer_shift_out(&(self->b.b[idx]), buf, &count) == -1 )
236     return -1;
237
238    return count;
239   break;
240  case ROAR_VIO_PIPE_TYPE_PIPE:
241    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)*2], buf, count);
242   break;
243  case ROAR_VIO_PIPE_TYPE_SOCKET:
244    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
245   break;
246 }
247
248 return -1;
249}
250
251ssize_t roar_vio_pipe_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
252 struct roar_vio_pipe * self;
253 struct roar_buffer   * next;
254 void                 * data;
255 int                    idx;
256
257 if ( vio == NULL )
258  return -1;
259
260 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
261  return -1;
262
263 switch (self->type) {
264  case ROAR_VIO_PIPE_TYPE_BUFFER:
265    if ( self->refcount < 2 ) {
266     raise(SIGPIPE);
267     return -1;
268    }
269
270    idx = ROAR_VIO_PIPE_SR(self,vio);
271
272    if ( (idx == 0 ? O_WRONLY : O_RDONLY) == (self->flags & (O_RDONLY|O_WRONLY|O_RDWR)) ) {
273     raise(SIGPIPE);
274     return -1;
275    }
276
277    if ( roar_buffer_new(&next, count) == -1 )
278     return -1;
279
280    if ( roar_buffer_get_data(next, &data) == -1 ) {
281     roar_buffer_free(next);
282     return -1;
283    }
284
285    memcpy(data, buf, count);
286
287    if ( self->b.b[idx] == NULL ) {
288     self->b.b[idx] = next;
289    } else {
290     if ( roar_buffer_add(self->b.b[idx], next) == -1 ) {
291      roar_buffer_free(next);
292      return -1;
293     }
294    }
295
296    return count;
297   break;
298  case ROAR_VIO_PIPE_TYPE_PIPE:
299    return write(self->b.p[(ROAR_VIO_PIPE_SR(self,vio)*2)+1], buf, count);
300   break;
301  case ROAR_VIO_PIPE_TYPE_SOCKET:
302    return write(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
303   break;
304 }
305
306 return -1;
307}
308#endif
309
310//ll
Note: See TracBrowser for help on using the repository browser.