source: roaraudio/libroar/vio_pipe.c @ 1312:4c0160c484c9

Last change on this file since 1312:4c0160c484c9 was 1312:4c0160c484c9, checked in by phi, 15 years ago

you can not write if any handle got closed

File size: 7.4 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 struct roar_vio_pipe * self;
39 int                    rw = flags & (O_RDONLY|O_WRONLY|O_RDWR);
40
41 if ( s0 == NULL || s1 == NULL )
42  return -1;
43
44 if ( (self = malloc(sizeof(struct roar_vio_pipe))) == NULL )
45  return -1;
46
47 memset(self, 0, sizeof(struct roar_vio_pipe));
48
49 self->refcount = 2;
50 self->flags    = flags;
51
52 if ( type == ROAR_VIO_PIPE_TYPE_AUTO ) {
53#ifdef ROAR_TARGET_WIN32
54  type = ROAR_VIO_PIPE_TYPE_BUFFER;
55#else
56  type = ROAR_VIO_PIPE_TYPE_SOCKET;
57#endif
58 }
59
60 self->type     = type;
61
62 switch (type) {
63  case ROAR_VIO_PIPE_TYPE_BUFFER:
64    // no buffers need to be set up here,
65    // we handle the NULL pointer in the reader and writer func
66    free(self);
67    return -1;
68   break;
69  case ROAR_VIO_PIPE_TYPE_PIPE:
70    self->b.p[0] = self->b.p[1] = self->b.p[2] = self->b.p[3] = -1;
71
72    if ( rw == O_RDWR || rw == O_RDONLY )
73     if ( pipe(self->b.p) == -1 ) {
74      free(self);
75      return -1;
76     }
77    if ( rw == O_RDWR || rw == O_WRONLY )
78     if ( pipe((self->b.p) + 2) == -1 ) {
79      close(self->b.p[0]);
80      close(self->b.p[1]);
81      free(self);
82      return -1;
83     }
84   break;
85  case ROAR_VIO_PIPE_TYPE_SOCKET:
86    if ( socketpair(AF_UNIX, SOCK_STREAM, 0, self->b.p) == -1 ) {
87     free(self);
88     return -1;
89    }
90
91    if ( rw == O_RDONLY ) {
92     shutdown(self->b.p[0], SHUT_WR);
93     shutdown(self->b.p[1], SHUT_RD);
94    } else if ( rw == O_WRONLY ) {
95     shutdown(self->b.p[0], SHUT_RD);
96     shutdown(self->b.p[1], SHUT_WR);
97    }
98   break;
99  default:
100    free(self);
101    return -1;
102 }
103
104 roar_vio_pipe_init(s0, self, flags);
105 roar_vio_pipe_init(s1, self, flags);
106
107 self->s0 = s0;
108
109 return 0;
110}
111
112int roar_vio_pipe_init (struct roar_vio_calls * s,  struct roar_vio_pipe * self, int flags) {
113 if ( s == NULL || self == NULL )
114  return -1;
115
116 memset(s, 0, sizeof(struct roar_vio_calls));
117
118 s->close    = roar_vio_pipe_close;
119 s->read     = roar_vio_pipe_read;
120 s->write    = roar_vio_pipe_write;
121 s->nonblock = roar_vio_pipe_nonblock;
122 s->sync     = roar_vio_pipe_sync;
123
124 s->inst = (void*) self;
125
126 if ( flags & O_NONBLOCK ) {
127  roar_vio_pipe_nonblock(s, ROAR_SOCKET_NONBLOCK);
128 }
129
130 return 0;
131}
132
133int     roar_vio_pipe_close   (struct roar_vio_calls * vio) {
134 struct roar_vio_pipe * self;
135 int                    idx;
136
137 if ( vio == NULL )
138  return -1;
139
140 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
141  return -1;
142
143 self->refcount--;
144
145 switch (self->type) {
146  case ROAR_VIO_PIPE_TYPE_BUFFER:
147    // this will be a bit more complex as we need to change the flags, too.
148   break;
149  case ROAR_VIO_PIPE_TYPE_PIPE:
150   switch (ROAR_VIO_PIPE_S(self, vio)) {
151    case 0:
152      close(self->b.p[0]);
153      close(self->b.p[3]);
154      self->b.p[0] = -1;
155      self->b.p[3] = -1;
156     break;
157    case 1:
158      close(self->b.p[1]);
159      close(self->b.p[2]);
160      self->b.p[1] = -1;
161      self->b.p[2] = -1;
162     break;
163   }
164   break;
165  case ROAR_VIO_PIPE_TYPE_SOCKET:
166    close(self->b.p[idx = ROAR_VIO_PIPE_S(self, vio)]);
167    self->b.p[idx] = -1;
168   break;
169 }
170
171 if ( ! self->refcount ) {
172  free(self);
173 }
174
175 vio->inst = NULL;
176 return 0;
177}
178
179int     roar_vio_pipe_nonblock(struct roar_vio_calls * vio, int state) {
180 struct roar_vio_pipe * self;
181
182 if ( vio == NULL )
183  return -1;
184
185 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
186  return -1;
187
188 switch (self->type) {
189  case ROAR_VIO_PIPE_TYPE_PIPE:
190    if ( roar_socket_nonblock(self->b.p[ROAR_VIO_PIPE_S(self,vio)*2], state) == -1 )
191     return -1;
192    return roar_socket_nonblock(self->b.p[(ROAR_VIO_PIPE_SR(self,vio)*2)+1], state);
193   break;
194  case ROAR_VIO_PIPE_TYPE_SOCKET:
195    return roar_socket_nonblock(self->b.p[ROAR_VIO_PIPE_S(self,vio)], state);
196   break;
197 }
198
199 return -1;
200}
201
202int     roar_vio_pipe_sync    (struct roar_vio_calls * vio) {
203 // we may add fdatasync() calls here depending on the type
204 // but in general they should not be needed on pipes.
205 return 0;
206}
207
208ssize_t roar_vio_pipe_read    (struct roar_vio_calls * vio, void *buf, size_t count) {
209 struct roar_vio_pipe * self;
210 int                    idx;
211
212 if ( vio == NULL )
213  return -1;
214
215 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
216  return -1;
217
218 switch (self->type) {
219  case ROAR_VIO_PIPE_TYPE_BUFFER:
220    idx = ROAR_VIO_PIPE_S(self,vio);
221
222    if ( (idx == 0 ? O_WRONLY : O_RDONLY) == (self->flags & (O_RDONLY|O_WRONLY|O_RDWR)) ) {
223     raise(SIGPIPE);
224     return -1;
225    }
226
227    if ( self->b.b[idx] == NULL )
228     return 0;
229
230    if ( roar_buffer_shift_out(&(self->b.b[idx]), buf, &count) == -1 )
231     return -1;
232
233    return count;
234   break;
235  case ROAR_VIO_PIPE_TYPE_PIPE:
236    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)*2], buf, count);
237   break;
238  case ROAR_VIO_PIPE_TYPE_SOCKET:
239    return read(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
240   break;
241 }
242
243 return -1;
244}
245
246ssize_t roar_vio_pipe_write   (struct roar_vio_calls * vio, void *buf, size_t count) {
247 struct roar_vio_pipe * self;
248 struct roar_buffer   * next;
249 void                 * data;
250 int                    idx;
251
252 if ( vio == NULL )
253  return -1;
254
255 if ( (self = (struct roar_vio_pipe *)vio->inst) == NULL )
256  return -1;
257
258 switch (self->type) {
259  case ROAR_VIO_PIPE_TYPE_BUFFER:
260    if ( self->refcount < 2 ) {
261     raise(SIGPIPE);
262     return -1;
263    }
264
265    idx = ROAR_VIO_PIPE_SR(self,vio);
266
267    if ( (idx == 0 ? O_WRONLY : O_RDONLY) == (self->flags & (O_RDONLY|O_WRONLY|O_RDWR)) ) {
268     raise(SIGPIPE);
269     return -1;
270    }
271
272    if ( roar_buffer_new(&next, count) == -1 )
273     return -1;
274
275    if ( roar_buffer_get_data(next, &data) == -1 ) {
276     roar_buffer_free(next);
277     return -1;
278    }
279
280    memcpy(data, buf, count);
281
282    if ( self->b.b[idx] == NULL ) {
283     self->b.b[idx] = next;
284    } else {
285     if ( roar_buffer_add(self->b.b[idx], next) == -1 ) {
286      roar_buffer_free(next);
287      return -1;
288     }
289    }
290
291    return count;
292   break;
293  case ROAR_VIO_PIPE_TYPE_PIPE:
294    return write(self->b.p[(ROAR_VIO_PIPE_SR(self,vio)*2)+1], buf, count);
295   break;
296  case ROAR_VIO_PIPE_TYPE_SOCKET:
297    return write(self->b.p[ROAR_VIO_PIPE_S(self,vio)], buf, count);
298   break;
299 }
300
301 return -1;
302}
303
304//ll
Note: See TracBrowser for help on using the repository browser.