8 #include "inputstream.h"
9 #include "outputstream.h"
10 #include "protocol-simple.h"
14 struct protocol_simple
*protocol
;
16 struct input_stream
*istream
;
17 struct output_stream
*ostream
;
18 struct client
*client
;
21 struct protocol_simple
{
23 struct socket_server
*server
;
24 struct idxset
*connections
;
25 enum protocol_simple_mode mode
;
28 #define BUFSIZE PIPE_BUF
30 static void free_connection(void *data
, void *userdata
) {
31 struct connection
*c
= data
;
35 input_stream_free(c
->istream
);
37 output_stream_free(c
->ostream
);
39 client_free(c
->client
);
41 iochannel_free(c
->io
);
45 static void io_callback(struct iochannel
*io
, void *userdata
) {
46 struct connection
*c
= userdata
;
49 if (c
->istream
&& iochannel_is_readable(io
)) {
50 struct memchunk chunk
;
53 chunk
.memblock
= memblock_new(BUFSIZE
);
54 assert(chunk
.memblock
);
56 if ((r
= iochannel_read(io
, chunk
.memblock
->data
, BUFSIZE
)) <= 0) {
57 fprintf(stderr
, "read(): %s\n", r
== 0 ? "EOF" : strerror(errno
));
58 memblock_unref(chunk
.memblock
);
62 chunk
.memblock
->length
= r
;
66 memblockq_push(c
->istream
->memblockq
, &chunk
, 0);
67 input_stream_notify(c
->istream
);
68 memblock_unref(chunk
.memblock
);
71 if (c
->ostream
&& iochannel_is_writable(io
)) {
72 struct memchunk chunk
;
75 memblockq_peek(c
->ostream
->memblockq
, &chunk
);
76 assert(chunk
.memblock
&& chunk
.length
);
78 if ((r
= iochannel_write(io
, chunk
.memblock
->data
+chunk
.index
, chunk
.length
)) < 0) {
79 fprintf(stderr
, "write(): %s\n", strerror(errno
));
80 memblock_unref(chunk
.memblock
);
84 memblockq_drop(c
->ostream
->memblockq
, r
);
85 memblock_unref(chunk
.memblock
);
91 idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
);
92 free_connection(c
, NULL
);
95 static void on_connection(struct socket_server
*s
, struct iochannel
*io
, void *userdata
) {
96 struct protocol_simple
*p
= userdata
;
97 struct connection
*c
= NULL
;
100 c
= malloc(sizeof(struct connection
));
107 c
->client
= client_new(p
->core
, "SIMPLE", "Client");
110 if (p
->mode
& PROTOCOL_SIMPLE_RECORD
) {
111 struct source
*source
;
113 if (!(source
= core_get_default_source(p
->core
))) {
114 fprintf(stderr
, "Failed to get default source.\n");
118 c
->ostream
= output_stream_new(source
, &DEFAULT_SAMPLE_SPEC
, c
->client
->name
);
122 if (p
->mode
& PROTOCOL_SIMPLE_PLAYBACK
) {
125 if (!(sink
= core_get_default_sink(p
->core
))) {
126 fprintf(stderr
, "Failed to get default sink.\n");
130 c
->istream
= input_stream_new(sink
, &DEFAULT_SAMPLE_SPEC
, c
->client
->name
);
135 iochannel_set_callback(c
->io
, io_callback
, c
);
136 idxset_put(p
->connections
, c
, NULL
);
142 client_free(c
->client
);
144 input_stream_free(c
->istream
);
146 output_stream_free(c
->ostream
);
148 iochannel_free(c
->io
);
153 struct protocol_simple
* protocol_simple_new(struct core
*core
, struct socket_server
*server
, enum protocol_simple_mode mode
) {
154 struct protocol_simple
* p
;
155 assert(core
&& server
&& mode
<= PROTOCOL_SIMPLE_DUPLEX
&& mode
> 0);
157 p
= malloc(sizeof(struct protocol_simple
));
161 p
->connections
= idxset_new(NULL
, NULL
);
164 socket_server_set_callback(p
->server
, on_connection
, p
);
170 void protocol_simple_free(struct protocol_simple
*p
) {
173 idxset_free(p
->connections
, free_connection
, NULL
);
174 socket_server_free(p
->server
);