summaryrefslogtreecommitdiffabout
path: root/libetpan/src/data-types/mailstream_socket.c
Unidiff
Diffstat (limited to 'libetpan/src/data-types/mailstream_socket.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/data-types/mailstream_socket.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/libetpan/src/data-types/mailstream_socket.c b/libetpan/src/data-types/mailstream_socket.c
new file mode 100644
index 0000000..bd58571
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream_socket.c
@@ -0,0 +1,238 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailstream_socket.h"
37#include <unistd.h>
38#include <stdlib.h>
39#include <fcntl.h>
40#include <sys/socket.h>
41
42/*
43 these 3 headers MUST be included before <sys/select.h>
44 to insure compatibility with Mac OS X (this is true for 10.2)
45*/
46#include <sys/time.h>
47#include <sys/types.h>
48#include <unistd.h>
49#include <sys/select.h>
50
51/* mailstream_low, socket */
52
53static int mailstream_low_socket_close(mailstream_low * s);
54static ssize_t mailstream_low_socket_read(mailstream_low * s,
55 void * buf, size_t count);
56static ssize_t mailstream_low_socket_write(mailstream_low * s,
57 const void * buf, size_t count);
58static void mailstream_low_socket_free(mailstream_low * s);
59static int mailstream_low_socket_get_fd(mailstream_low * s);
60
61static mailstream_low_driver local_mailstream_socket_driver = {
62 mailstream_read: mailstream_low_socket_read,
63 mailstream_write: mailstream_low_socket_write,
64 mailstream_close: mailstream_low_socket_close,
65 mailstream_free: mailstream_low_socket_free,
66 mailstream_get_fd: mailstream_low_socket_get_fd,
67};
68
69mailstream_low_driver * mailstream_socket_driver =
70&local_mailstream_socket_driver;
71
72/* file descriptor must be given in (default) blocking-mode */
73
74static struct mailstream_socket_data * socket_data_new(int fd)
75{
76 struct mailstream_socket_data * socket_data;
77
78 socket_data = malloc(sizeof(* socket_data));
79 if (socket_data == NULL)
80 goto err;
81
82 socket_data->fd = fd;
83
84 return socket_data;
85
86 err:
87 return NULL;
88}
89
90static void socket_data_free(struct mailstream_socket_data * socket_data)
91{
92 free(socket_data);
93}
94
95static void socket_data_close(struct mailstream_socket_data * socket_data)
96{
97 close(socket_data->fd);
98 socket_data->fd = -1;
99}
100
101mailstream_low * mailstream_low_socket_open(int fd)
102{
103 mailstream_low * s;
104 struct mailstream_socket_data * socket_data;
105
106 socket_data = socket_data_new(fd);
107 if (socket_data == NULL)
108 goto err;
109
110 s = mailstream_low_new(socket_data, mailstream_socket_driver);
111 if (s == NULL)
112 goto free_socket_data;
113
114 return s;
115
116 free_socket_data:
117 socket_data_free(socket_data);
118 err:
119 return NULL;
120}
121
122static int mailstream_low_socket_close(mailstream_low * s)
123{
124 struct mailstream_socket_data * socket_data;
125
126 socket_data = (struct mailstream_socket_data *) s->data;
127 socket_data_close(socket_data);
128
129 return 0;
130}
131
132static void mailstream_low_socket_free(mailstream_low * s)
133{
134 struct mailstream_socket_data * socket_data;
135
136 socket_data = (struct mailstream_socket_data *) s->data;
137 socket_data_free(socket_data);
138 s->data = NULL;
139
140 free(s);
141}
142
143static int mailstream_low_socket_get_fd(mailstream_low * s)
144{
145 struct mailstream_socket_data * socket_data;
146
147 socket_data = (struct mailstream_socket_data *) s->data;
148 return socket_data->fd;
149}
150
151
152static ssize_t mailstream_low_socket_read(mailstream_low * s,
153 void * buf, size_t count)
154{
155 struct mailstream_socket_data * socket_data;
156
157 socket_data = (struct mailstream_socket_data *) s->data;
158
159 /* timeout */
160 {
161 fd_set fds_read;
162 fd_set fds_excp;
163 struct timeval timeout;
164 int r;
165
166 timeout = mailstream_network_delay;
167
168 FD_ZERO(&fds_read);
169 FD_SET(socket_data->fd, &fds_read);
170 FD_ZERO(&fds_excp);
171 FD_SET(socket_data->fd, &fds_excp);
172 r = select(socket_data->fd + 1, &fds_read, NULL, &fds_excp, &timeout);
173 if (r == 0)
174 return -1;
175 if (FD_ISSET(socket_data->fd, &fds_excp))
176 return -1;
177 if (!FD_ISSET(socket_data->fd, &fds_read))
178 return 0;
179 }
180
181 return read(socket_data->fd, buf, count);
182}
183
184static ssize_t mailstream_low_socket_write(mailstream_low * s,
185 const void * buf, size_t count)
186{
187 struct mailstream_socket_data * socket_data;
188
189 socket_data = (struct mailstream_socket_data *) s->data;
190 /* timeout */
191 {
192 fd_set fds_write;
193 fd_set fds_excp;
194 struct timeval timeout;
195 int r;
196
197 timeout = mailstream_network_delay;
198
199 FD_ZERO(&fds_write);
200 FD_SET(socket_data->fd, &fds_write);
201 FD_ZERO(&fds_excp);
202 FD_SET(socket_data->fd, &fds_excp);
203 r = select(socket_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout);
204 if (r == 0)
205 return -1;
206 if (FD_ISSET(socket_data->fd, &fds_excp))
207 return -1;
208 if (!FD_ISSET(socket_data->fd, &fds_write))
209 return 0;
210 }
211
212 return write(socket_data->fd, buf, count);
213}
214
215
216/* mailstream */
217
218mailstream * mailstream_socket_open(int fd)
219{
220 mailstream_low * low;
221 mailstream * s;
222
223 low = mailstream_low_socket_open(fd);
224 if (low == NULL)
225 goto err;
226
227 s = mailstream_new(low, 8192);
228 if (s == NULL)
229 goto free_low;
230
231 return s;
232
233 free_low:
234 mailstream_low_close(low);
235 err:
236 return NULL;
237}
238