8 #include "socket-util.h"
12 struct pa_mainloop_api
* mainloop
;
14 void (*callback
)(struct pa_iochannel
*io
, void *userdata
);
23 void* input_source
, *output_source
;
26 static void enable_mainloop_sources(struct pa_iochannel
*io
) {
29 if (io
->input_source
== io
->output_source
) {
30 enum pa_mainloop_api_io_events e
= PA_MAINLOOP_API_IO_EVENT_NULL
;
31 assert(io
->input_source
);
34 e
|= PA_MAINLOOP_API_IO_EVENT_INPUT
;
36 e
|= PA_MAINLOOP_API_IO_EVENT_OUTPUT
;
38 io
->mainloop
->enable_io(io
->mainloop
, io
->input_source
, e
);
41 io
->mainloop
->enable_io(io
->mainloop
, io
->input_source
, io
->readable
? PA_MAINLOOP_API_IO_EVENT_NULL
: PA_MAINLOOP_API_IO_EVENT_INPUT
);
42 if (io
->output_source
)
43 io
->mainloop
->enable_io(io
->mainloop
, io
->output_source
, io
->writable
? PA_MAINLOOP_API_IO_EVENT_NULL
: PA_MAINLOOP_API_IO_EVENT_OUTPUT
);
47 static void callback(struct pa_mainloop_api
* m
, void *id
, int fd
, enum pa_mainloop_api_io_events events
, void *userdata
) {
48 struct pa_iochannel
*io
= userdata
;
50 assert(m
&& fd
>= 0 && events
&& userdata
);
52 if ((events
& PA_MAINLOOP_API_IO_EVENT_HUP
) && !io
->hungup
) {
57 if ((events
& PA_MAINLOOP_API_IO_EVENT_INPUT
) && !io
->readable
) {
60 assert(id
== io
->input_source
);
63 if ((events
& PA_MAINLOOP_API_IO_EVENT_OUTPUT
) && !io
->writable
) {
66 assert(id
== io
->output_source
);
70 enable_mainloop_sources(io
);
73 io
->callback(io
, io
->userdata
);
77 struct pa_iochannel
* pa_iochannel_new(struct pa_mainloop_api
*m
, int ifd
, int ofd
) {
78 struct pa_iochannel
*io
;
79 assert(m
&& (ifd
>= 0 || ofd
>= 0));
81 io
= malloc(sizeof(struct pa_iochannel
));
95 pa_make_nonblock_fd(io
->ifd
);
96 io
->input_source
= io
->output_source
= m
->source_io(m
, ifd
, PA_MAINLOOP_API_IO_EVENT_BOTH
, callback
, io
);
100 pa_make_nonblock_fd(io
->ifd
);
101 io
->input_source
= m
->source_io(m
, ifd
, PA_MAINLOOP_API_IO_EVENT_INPUT
, callback
, io
);
103 io
->input_source
= NULL
;
106 pa_make_nonblock_fd(io
->ofd
);
107 io
->output_source
= m
->source_io(m
, ofd
, PA_MAINLOOP_API_IO_EVENT_OUTPUT
, callback
, io
);
109 io
->output_source
= NULL
;
115 void pa_iochannel_free(struct pa_iochannel
*io
) {
121 if (io
->ofd
>= 0 && io
->ofd
!= io
->ifd
)
125 if (io
->input_source
)
126 io
->mainloop
->cancel_io(io
->mainloop
, io
->input_source
);
127 if (io
->output_source
&& (io
->output_source
!= io
->input_source
))
128 io
->mainloop
->cancel_io(io
->mainloop
, io
->output_source
);
133 int pa_iochannel_is_readable(struct pa_iochannel
*io
) {
138 int pa_iochannel_is_writable(struct pa_iochannel
*io
) {
143 int pa_iochannel_is_hungup(struct pa_iochannel
*io
) {
148 ssize_t
pa_iochannel_write(struct pa_iochannel
*io
, const void*data
, size_t l
) {
150 assert(io
&& data
&& l
&& io
->ofd
>= 0);
152 if ((r
= write(io
->ofd
, data
, l
)) >= 0) {
154 enable_mainloop_sources(io
);
160 ssize_t
pa_iochannel_read(struct pa_iochannel
*io
, void*data
, size_t l
) {
163 assert(io
&& data
&& io
->ifd
>= 0);
165 if ((r
= read(io
->ifd
, data
, l
)) >= 0) {
167 enable_mainloop_sources(io
);
173 void pa_iochannel_set_callback(struct pa_iochannel
*io
, void (*callback
)(struct pa_iochannel
*io
, void *userdata
), void *userdata
) {
175 io
->callback
= callback
;
176 io
->userdata
= userdata
;
179 void pa_iochannel_set_noclose(struct pa_iochannel
*io
, int b
) {
184 void pa_iochannel_socket_peer_to_string(struct pa_iochannel
*io
, char*s
, size_t l
) {
185 assert(io
&& s
&& l
);
186 pa_socket_peer_to_string(io
->ifd
, s
, l
);
189 int pa_iochannel_socket_set_rcvbuf(struct pa_iochannel
*io
, size_t l
) {
191 return pa_socket_set_rcvbuf(io
->ifd
, l
);
194 int pa_iochannel_socket_set_sndbuf(struct pa_iochannel
*io
, size_t l
) {
196 return pa_socket_set_sndbuf(io
->ofd
, l
);