chiark / gitweb /
*** empty log message ***
[sympathy.git] / src / symsocket.c
1 /*
2  * symsocket.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] =
10   "$Id$";
11
12 /*
13  * $Log$
14  * Revision 1.6  2008/02/27 00:27:22  james
15  * *** empty log message ***
16  *
17  * Revision 1.5  2008/02/20 22:54:22  staffcvs
18  * *** empty log message ***
19  *
20  * Revision 1.4  2008/02/20 18:31:53  james
21  * *** empty log message ***
22  *
23  * Revision 1.3  2008/02/14 02:46:44  james
24  * *** empty log message ***
25  *
26  * Revision 1.2  2008/02/14 00:57:58  james
27  * *** empty log message ***
28  *
29  * Revision 1.1  2008/02/13 18:05:06  james
30  * *** empty log message ***
31  *
32  */
33
34 #include "project.h"
35 #include <sys/socket.h>
36 #include <sys/un.h>
37
38 #define BUF_SIZE 65536
39 #define MAX_TXN 4096
40
41 int
42 wrap_recv (int fd, void *buf, int len)
43 {
44   int red;
45
46   red = recv (fd, buf, len, 0);
47   if (!red)
48     return -1;
49
50   if ((red < 0) && (errno == EAGAIN))
51     red = 0;
52
53   return red;
54 }
55
56 int
57 wrap_send (int fd, void *buf, int len)
58 {
59   int writ;
60
61   errno = 0;
62
63   writ = send (fd, buf, len, MSG_NOSIGNAL);
64
65   if (!writ)
66     return -1;
67
68   if ((writ < 0) && (errno == EAGAIN))
69     writ = 0;
70
71   return writ;
72 }
73
74 void
75 socket_free (Socket * s)
76 {
77   if (!s)
78     return;
79   if (s->read_buf)
80     slide_free (s->read_buf);
81   if (s->write_buf)
82     slide_free (s->write_buf);
83   if (s->path_to_unlink)
84     {
85       unlink (s->path_to_unlink);
86       free (s->path_to_unlink);
87     }
88   close (s->fd);
89   free (s);
90 }
91
92 void
93 socket_free_parent (Socket * s)
94 {
95   if (!s)
96     return;
97   if (s->read_buf)
98     slide_free (s->read_buf);
99   if (s->write_buf)
100     slide_free (s->write_buf);
101   if (s->path_to_unlink)
102     free (s->path_to_unlink);
103   close (s->fd);
104
105   free (s);
106 }
107
108
109 Socket *
110 socket_listen (char *path)
111 {
112   int fd;
113   struct sockaddr_un *sun;
114   Socket *ret;
115   int n;
116
117
118   unlink (path);
119
120   fd = socket (PF_UNIX, SOCK_STREAM, 0);
121
122   if (fd < 0)
123     return NULL;
124
125   n = strlen (path) + sizeof (struct sockaddr_un);
126   sun = (struct sockaddr_un *) malloc (n);
127   memset (sun, 0, n);
128
129   sun->sun_family = AF_UNIX;
130   strcpy (sun->sun_path, path);
131
132   if (bind (fd, (struct sockaddr *) sun, SUN_LEN (sun)) < 0)
133     {
134       free (sun);
135       close (fd);
136       return NULL;
137     }
138
139   free (sun);
140
141   if (listen (fd, 5) < 0)
142     {
143       close (fd);
144       return NULL;
145     }
146
147   set_nonblocking (fd);
148
149   ret = (Socket *) malloc (sizeof (Socket));
150   memset (ret, 0, sizeof (Socket));
151   ret->read_buf = NULL;
152   ret->write_buf = NULL;
153
154   ret->fd = fd;
155   ret->path_to_unlink = strdup (path);
156
157
158   return ret;
159 }
160
161 Socket *
162 socket_accept (Socket * l)
163 {
164   Socket *ret;
165   int len;
166   int fd;
167   struct sockaddr_un sun;
168
169   len = sizeof (struct sockaddr_un);
170
171   fd = accept (l->fd, (struct sockaddr *) &sun, &len);
172
173   if (fd < 0)
174     return NULL;
175
176
177   ret = (Socket *) malloc (sizeof (Socket));
178   memset (ret, 0, sizeof (Socket));
179
180   set_nonblocking (fd);
181
182   ret->fd = fd;
183   ret->read_buf = slide_new (BUF_SIZE);
184   ret->write_buf = slide_new (BUF_SIZE);
185   ret->msg = 0;
186
187   return ret;
188 }
189
190
191 /*Blocking for now*/
192 Socket *
193 socket_connect (char *path)
194 {
195   int n;
196   int fd;
197   struct sockaddr_un *sun;
198   Socket *ret;
199
200
201   fd = socket (PF_UNIX, SOCK_STREAM, 0);
202
203   if (fd < 0)
204     return NULL;
205
206   n = strlen (path) + sizeof (struct sockaddr_un);
207   sun = (struct sockaddr_un *) malloc (n);
208   memset (sun, 0, n);
209
210   sun->sun_family = AF_UNIX;
211   strcpy (sun->sun_path, path);
212
213   if (connect (fd, (struct sockaddr *) sun, SUN_LEN (sun)))
214     {
215       free (sun);
216       close (fd);
217       return NULL;
218     }
219
220   free (sun);
221
222   set_nonblocking (fd);
223
224   ret = (Socket *) malloc (sizeof (Socket));
225   memset (ret, 0, sizeof (Socket));
226
227   ret->fd = fd;
228   ret->read_buf = slide_new (BUF_SIZE);
229   ret->write_buf = slide_new (BUF_SIZE);
230   ret->msg = 0;
231
232   return ret;
233 }
234
235 void
236 socket_consume_msg (Socket * s)
237 {
238   int n;
239
240   if (!s->msg)
241     return;
242
243   ipc_consume_message_in_slide (s->read_buf);
244   s->msg = ipc_check_for_message_in_slide (s->read_buf);
245
246 }
247
248 void
249 socket_pre_select (Socket * s, fd_set * rfds, fd_set * wfds)
250 {
251   char buf[1024];
252   int n;
253
254   /*Server socket */
255   if (SOCKET_IS_LISTENER (s))
256     {
257       FD_SET (s->fd, rfds);
258       return;
259     }
260
261   if (!SLIDE_EMPTY (s->write_buf))
262     FD_SET (s->fd, wfds);
263
264   if (!SLIDE_FULL (s->read_buf))
265     FD_SET (s->fd, rfds);
266
267 }
268
269 int
270 socket_post_select (Socket * s, fd_set * rfds, fd_set * wfds)
271 {
272   char buf[1024];
273   int n;
274   int error = 0;
275
276
277   if ((!SLIDE_EMPTY (s->write_buf)) && FD_ISSET (s->fd, wfds))
278     {
279       n =
280         (SLIDE_BYTES (s->write_buf) >
281          MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf);
282       n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n);
283       if (n > 0)
284         slide_consume (s->write_buf, n);
285       if (n < 0)
286         error = -1;
287     }
288
289   if (!SLIDE_FULL (s->read_buf) && FD_ISSET (s->fd, rfds))
290     {
291       n =
292         (SLIDE_SPACE (s->read_buf) >
293          MAX_TXN) ? MAX_TXN : SLIDE_SPACE (s->read_buf);
294       n = wrap_recv (s->fd, SLIDE_WPTR (s->read_buf), n);
295       if (n > 0)
296         slide_added (s->read_buf, n);
297       if (n < 0)
298         error = -1;
299     }
300
301   s->msg = ipc_check_for_message_in_slide (s->read_buf);
302
303   return error;
304
305 }
306
307
308 int
309 socket_write (Socket * s, void *buf, int len)
310 {
311   int n;
312
313   slide_expand (s->write_buf, len);
314   memcpy (SLIDE_WPTR (s->write_buf), buf, len);
315   slide_added (s->write_buf, len);
316
317   n =
318     (SLIDE_BYTES (s->write_buf) >
319      MAX_TXN) ? MAX_TXN : SLIDE_BYTES (s->write_buf);
320   n = wrap_send (s->fd, SLIDE_RPTR (s->write_buf), n);
321   {
322     uint8_t *c = SLIDE_RPTR (s->write_buf);
323   }
324
325   if (n > 0)
326     slide_consume (s->write_buf, n);
327
328   if (n < 0)
329     return -1;
330
331   return len;
332 }