New audio subsystem.
[jog] / tx-socket.c
1 /* -*-c-*-
2 *
3 * $Id: tx-socket.c,v 1.2 2002/01/30 09:25:35 mdw Exp $
4 *
5 * Socket transport
6 *
7 * (c) 2001 Mark Wooding
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Jog: Programming for a jogging machine.
13 *
14 * Jog is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * Jog is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Jog; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Revision history --------------------------------------------------*
30 *
31 * $Log: tx-socket.c,v $
32 * Revision 1.2 2002/01/30 09:25:35 mdw
33 * Minor modifications for the transport configuration change.
34 *
35 * Revision 1.1 2002/01/25 19:34:45 mdw
36 * Initial revision
37 *
38 */
39
40 /*----- Header files ------------------------------------------------------*/
41
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <errno.h>
47 #include <stddef.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 #include <sys/types.h>
53 #include <unistd.h>
54 #include <sys/socket.h>
55 #include <sys/un.h>
56 #include <pthread.h>
57
58 #include <mLib/alloc.h>
59 #include <mLib/darray.h>
60 #include <mLib/sub.h>
61
62 #include "err.h"
63 #include "txport.h"
64 #include "tx-socket.h"
65
66 #undef sun
67
68 /*----- Data structures ---------------------------------------------------*/
69
70 typedef struct txsock {
71 txport tx; /* Transport base */
72 int fd; /* File descriptor */
73 } txsock;
74
75 /*----- Main code ---------------------------------------------------------*/
76
77 /* --- @txsock_create@ --- *
78 *
79 * Arguments: @const char *file@ = filename for socket
80 *
81 * Returns: Pointer to created transport block.
82 *
83 * Use: Creates a socket transport.
84 */
85
86 txport *txsock_create(const char *file)
87 {
88 txsock *tx;
89 int fd;
90 struct sockaddr_un *sun;
91 size_t len, sunsz;
92
93 /* --- Set up the address block --- */
94
95 len = strlen(file) + 1;
96 sunsz = offsetof(struct sockaddr_un, sun_path) + len;
97 sun = xmalloc(sunsz);
98 sun->sun_family = AF_UNIX;
99 memcpy(sun->sun_path, file, len);
100
101 /* --- Create the socket --- */
102
103 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
104 err_report(ERR_TXPORT, ERRTX_CREATE, errno,
105 "error creating socket: %s", strerror(errno));
106 goto fail_0;
107 }
108
109 /* --- Connect --- */
110
111 if (connect(fd, (struct sockaddr *)sun, sunsz)) {
112 err_report(ERR_TXPORT, ERRTX_CREATE, errno,
113 "couldn't connect to `%s': %s", file, strerror(errno));
114 goto fail_1;
115 }
116
117 /* --- Done --- */
118
119 tx = CREATE(txsock);
120 tx->fd = fd;
121 xfree(sun);
122 return (&tx->tx);
123
124 /* --- Tidy up because it all went horribly wrong --- */
125
126 fail_1:
127 close(fd);
128 fail_0:
129 xfree(sun);
130 return (0);
131 }
132
133 /* --- @txsock_write@ --- *
134 *
135 * Arguments: @txport *txg@ = pointer to transport context
136 * @const void *p@ = pointer to buffer
137 * @size_t sz@ = size of the buffer
138 *
139 * Returns: Number of bytes written, or @-1@ on error.
140 *
141 * Use: Writes data to a transport.
142 */
143
144 ssize_t txsock_write(txport *txg, const void *p, size_t sz)
145 {
146 txsock *tx = (txsock *)txg;
147
148 return (write(tx->fd, p, sz));
149 }
150
151 /* --- @txsock_fetch@ --- *
152 *
153 * Arguments: @void *txv@ = pointer to transport context
154 *
155 * Returns: Nothing of interest.
156 *
157 * Use: Thread to fetch data from a socket.
158 */
159
160 void *txsock_fetch(void *txv)
161 {
162 txsock *tx = txv;
163 unsigned char buf[BUFSIZ];
164 ssize_t n;
165 int e;
166
167 /* --- Read data while it arrives --- */
168
169 for (;;) {
170 n = read(tx->fd, buf, sizeof(buf));
171 if (n < 0) {
172 err_report(ERR_TXPORT, ERRTX_READ, errno,
173 "error reading from socket: %s", strerror(errno));
174 break;
175 }
176 if (!n)
177 break;
178 if ((e = pthread_mutex_lock(&tx->tx.mx)) != 0) {
179 err_report(ERR_TXPORT, ERRTX_READ, e,
180 "error locking mutex: %s", strerror(e));
181 break;
182 }
183 DA_ENSURE(&tx->tx.buf, n);
184 memcpy(DA(&tx->tx.buf) + DA_LEN(&tx->tx.buf), buf, n);
185 DA_EXTEND(&tx->tx.buf, n);
186 pthread_cond_signal(&tx->tx.cv);
187 pthread_mutex_unlock(&tx->tx.mx);
188 }
189
190 /* --- Deal with crapness --- */
191
192 e = pthread_mutex_lock(&tx->tx.mx);
193 tx->tx.s = TX_CLOSE;
194 pthread_cond_signal(&tx->tx.cv);
195 pthread_mutex_unlock(&tx->tx.mx);
196 return (0);
197 }
198
199 /* --- @txsock_destroy@ --- *
200 *
201 * Arguments: @txport *txg@ = pointer to transport context
202 *
203 * Returns: ---
204 *
205 * Use: Destroys a socket transport.
206 */
207
208 void txsock_destroy(txport *txg)
209 {
210 txsock *tx = (txsock *)txg;
211
212 close(tx->fd);
213 DESTROY(tx);
214 }
215
216 /*----- That's all, folks -------------------------------------------------*/