chiark / gitweb /
infra: Clean up project setup
[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 /*----- 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
59 typedef 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
69  *
70  * Returns:     Pointer to created transport block.
71  *
72  * Use:         Creates a socket transport.
73  */
74
75 txport *txsock_create(const char *file)
76 {
77   txsock *tx;
78   int fd;
79   struct sockaddr_un *sun;
80   size_t len, sunsz;
81
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));
95     goto fail_0;
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));
103     goto fail_1;
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
115 fail_1:
116   close(fd);
117 fail_0:
118   xfree(sun);
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
133 ssize_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
149 void *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
197 void 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 -------------------------------------------------*/