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