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