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