infra: Clean up project setup
[jog] / tx-socket.c
CommitLineData
2ec1e693 1/* -*-c-*-
2 *
9c493717 3 * $Id: tx-socket.c,v 1.2 2002/01/30 09:25:35 mdw Exp $
2ec1e693 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
2ec1e693 29/*----- Header files ------------------------------------------------------*/
30
31#ifdef HAVE_CONFIG_H
32# include "config.h"
33#endif
34
35#include <errno.h>
36#include <stddef.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41#include <sys/types.h>
42#include <unistd.h>
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <pthread.h>
46
47#include <mLib/alloc.h>
48#include <mLib/darray.h>
49#include <mLib/sub.h>
50
51#include "err.h"
52#include "txport.h"
53#include "tx-socket.h"
54
55#undef sun
56
57/*----- Data structures ---------------------------------------------------*/
58
59typedef struct txsock {
60 txport tx; /* Transport base */
61 int fd; /* File descriptor */
62} txsock;
63
64/*----- Main code ---------------------------------------------------------*/
65
66/* --- @txsock_create@ --- *
67 *
68 * Arguments: @const char *file@ = filename for socket
2ec1e693 69 *
70 * Returns: Pointer to created transport block.
71 *
72 * Use: Creates a socket transport.
73 */
74
9c493717 75txport *txsock_create(const char *file)
2ec1e693 76{
77 txsock *tx;
78 int fd;
79 struct sockaddr_un *sun;
80 size_t len, sunsz;
81
2ec1e693 82 /* --- Set up the address block --- */
83
84 len = strlen(file) + 1;
85 sunsz = offsetof(struct sockaddr_un, sun_path) + len;
86 sun = xmalloc(sunsz);
87 sun->sun_family = AF_UNIX;
88 memcpy(sun->sun_path, file, len);
89
90 /* --- Create the socket --- */
91
92 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
93 err_report(ERR_TXPORT, ERRTX_CREATE, errno,
94 "error creating socket: %s", strerror(errno));
9c493717 95 goto fail_0;
2ec1e693 96 }
97
98 /* --- Connect --- */
99
100 if (connect(fd, (struct sockaddr *)sun, sunsz)) {
101 err_report(ERR_TXPORT, ERRTX_CREATE, errno,
102 "couldn't connect to `%s': %s", file, strerror(errno));
9c493717 103 goto fail_1;
2ec1e693 104 }
105
106 /* --- Done --- */
107
108 tx = CREATE(txsock);
109 tx->fd = fd;
110 xfree(sun);
111 return (&tx->tx);
112
113 /* --- Tidy up because it all went horribly wrong --- */
114
2ec1e693 115fail_1:
9c493717 116 close(fd);
2ec1e693 117fail_0:
9c493717 118 xfree(sun);
2ec1e693 119 return (0);
120}
121
122/* --- @txsock_write@ --- *
123 *
124 * Arguments: @txport *txg@ = pointer to transport context
125 * @const void *p@ = pointer to buffer
126 * @size_t sz@ = size of the buffer
127 *
128 * Returns: Number of bytes written, or @-1@ on error.
129 *
130 * Use: Writes data to a transport.
131 */
132
133ssize_t txsock_write(txport *txg, const void *p, size_t sz)
134{
135 txsock *tx = (txsock *)txg;
136
137 return (write(tx->fd, p, sz));
138}
139
140/* --- @txsock_fetch@ --- *
141 *
142 * Arguments: @void *txv@ = pointer to transport context
143 *
144 * Returns: Nothing of interest.
145 *
146 * Use: Thread to fetch data from a socket.
147 */
148
149void *txsock_fetch(void *txv)
150{
151 txsock *tx = txv;
152 unsigned char buf[BUFSIZ];
153 ssize_t n;
154 int e;
155
156 /* --- Read data while it arrives --- */
157
158 for (;;) {
159 n = read(tx->fd, buf, sizeof(buf));
160 if (n < 0) {
161 err_report(ERR_TXPORT, ERRTX_READ, errno,
162 "error reading from socket: %s", strerror(errno));
163 break;
164 }
165 if (!n)
166 break;
167 if ((e = pthread_mutex_lock(&tx->tx.mx)) != 0) {
168 err_report(ERR_TXPORT, ERRTX_READ, e,
169 "error locking mutex: %s", strerror(e));
170 break;
171 }
172 DA_ENSURE(&tx->tx.buf, n);
173 memcpy(DA(&tx->tx.buf) + DA_LEN(&tx->tx.buf), buf, n);
174 DA_EXTEND(&tx->tx.buf, n);
175 pthread_cond_signal(&tx->tx.cv);
176 pthread_mutex_unlock(&tx->tx.mx);
177 }
178
179 /* --- Deal with crapness --- */
180
181 e = pthread_mutex_lock(&tx->tx.mx);
182 tx->tx.s = TX_CLOSE;
183 pthread_cond_signal(&tx->tx.cv);
184 pthread_mutex_unlock(&tx->tx.mx);
185 return (0);
186}
187
188/* --- @txsock_destroy@ --- *
189 *
190 * Arguments: @txport *txg@ = pointer to transport context
191 *
192 * Returns: ---
193 *
194 * Use: Destroys a socket transport.
195 */
196
197void txsock_destroy(txport *txg)
198{
199 txsock *tx = (txsock *)txg;
200
201 close(tx->fd);
202 DESTROY(tx);
203}
204
205/*----- That's all, folks -------------------------------------------------*/