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