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