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