summaryrefslogtreecommitdiffabout
path: root/libetpan/src/data-types/mailstream.c
Unidiff
Diffstat (limited to 'libetpan/src/data-types/mailstream.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/data-types/mailstream.c399
1 files changed, 399 insertions, 0 deletions
diff --git a/libetpan/src/data-types/mailstream.c b/libetpan/src/data-types/mailstream.c
new file mode 100644
index 0000000..ceb0ced
--- a/dev/null
+++ b/libetpan/src/data-types/mailstream.c
@@ -0,0 +1,399 @@
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.h"
37#include "maillock.h"
38#include <string.h>
39#include <stdlib.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42
43#define DEFAULT_NETWORK_TIMEOUT 300
44
45#if 0
46#ifdef LIBETPAN_MAILSTREAM_DEBUG
47
48#define STREAM_DEBUG
49
50#include <stdio.h>
51
52#define LOG_FILE "libetpan-stream-debug.log"
53
54int mailstream_debug = 0;
55
56#define STREAM_LOG_BUF(buf, size) \
57 if (mailstream_debug) { \
58 FILE * f; \
59 mode_t old_mask; \
60 \
61 old_mask = umask(0077); \
62 f = fopen(LOG_FILE, "a"); \
63 umask(old_mask); \
64 if (f != NULL) { \
65 maillock_write_lock(LOG_FILE, fileno(f)); \
66 fwrite((buf), 1, (size), f); \
67 maillock_write_unlock(LOG_FILE, fileno(f)); \
68 fclose(f); \
69 } \
70 }
71
72#define STREAM_LOG(str) \
73 if (mailstream_debug) { \
74 FILE * f; \
75 mode_t old_mask; \
76 \
77 old_mask = umask(0077); \
78 f = fopen(LOG_FILE, "a"); \
79 umask(old_mask); \
80 if (f != NULL) { \
81 maillock_write_lock(LOG_FILE, fileno(f)); \
82 fputs((str), f); \
83 maillock_write_unlock(LOG_FILE, fileno(f)); \
84 fclose(f); \
85 } \
86 }
87
88#else
89
90#define STREAM_LOG_BUF(buf, size) do { } while (0)
91#define STREAM_LOG(buf) do { } while (0)
92
93#endif
94#endif
95
96#define STREAM_LOG_BUF(buf, size) do { } while (0)
97#define STREAM_LOG(buf) do { } while (0)
98
99
100mailstream * mailstream_new(mailstream_low * low, size_t buffer_size)
101{
102 mailstream * s;
103
104 s = malloc(sizeof(* s));
105 if (s == NULL)
106 goto err;
107
108 s->read_buffer = malloc(buffer_size);
109 if (s->read_buffer == NULL)
110 goto free_s;
111 s->read_buffer_len = 0;
112
113 s->write_buffer = malloc(buffer_size);
114 if (s->write_buffer == NULL)
115 goto free_read_buffer;
116 s->write_buffer_len = 0;
117
118 s->buffer_max_size = buffer_size;
119 s->low = low;
120
121 return s;
122
123 free_read_buffer:
124 free(s->read_buffer);
125 free_s:
126 free(s);
127 err:
128 return NULL;
129}
130
131static size_t write_to_internal_buffer(mailstream * s,
132 const void * buf, size_t count)
133{
134 memcpy(s->write_buffer + s->write_buffer_len, buf, count);
135 s->write_buffer_len += count;
136
137 return count;
138}
139
140static size_t write_direct(mailstream * s, const void * buf, size_t count)
141{
142 size_t left;
143 const char * cur_buf;
144 ssize_t written;
145
146 cur_buf = buf;
147 left = count;
148 while (left > 0) {
149 written = mailstream_low_write(s->low, cur_buf, left);
150
151 if (written == -1) {
152 if (count == left)
153 return -1;
154 else
155 return count - left;
156 }
157
158 cur_buf += written;
159 left -= written;
160 }
161
162 return count;
163}
164
165ssize_t mailstream_write(mailstream * s, const void * buf, size_t count)
166{
167 int r;
168
169 if (s == NULL)
170 return -1;
171
172 if (count + s->write_buffer_len > s->buffer_max_size) {
173 r = mailstream_flush(s);
174 if (r == -1)
175 return -1;
176
177 if (count > s->buffer_max_size)
178 return write_direct(s, buf, count);
179 }
180
181#ifdef STREAM_DEBUG
182 STREAM_LOG(">>>>>>> send >>>>>>\n");
183 STREAM_LOG_BUF(buf, count);
184 STREAM_LOG("\n");
185 STREAM_LOG(">>>>>>> end send >>>>>>\n");
186#endif
187
188 return write_to_internal_buffer(s, buf, count);
189}
190
191int mailstream_flush(mailstream * s)
192{
193 char * cur_buf;
194 size_t left;
195 ssize_t written;
196
197 if (s == NULL)
198 return -1;
199
200 cur_buf = s->write_buffer;
201 left = s->write_buffer_len;
202 while (left > 0) {
203 written = mailstream_low_write(s->low, cur_buf, left);
204
205 if (written == -1)
206 goto move_buffer;
207 cur_buf += written;
208 left -= written;
209 }
210
211 s->write_buffer_len = 0;
212
213 return 0;
214
215 move_buffer:
216 memmove(s->write_buffer, cur_buf, left);
217 s->write_buffer_len = left;
218 return -1;
219}
220
221static ssize_t read_from_internal_buffer(mailstream * s,
222 void * buf, size_t count)
223{
224 if (count >= s->read_buffer_len)
225 count = s->read_buffer_len;
226 if (count != 0)
227 memcpy(buf, s->read_buffer, count);
228
229 s->read_buffer_len -= count;
230 if (s->read_buffer_len != 0)
231 memmove(s->read_buffer, s->read_buffer + count,
232 s->read_buffer_len);
233
234 return count;
235}
236
237static ssize_t read_through_buffer(mailstream * s, void * buf, size_t count)
238{
239 size_t left;
240 char * cur_buf;
241 ssize_t bytes_read;
242
243 cur_buf = buf;
244 left = count;
245
246 while (left > 0) {
247 bytes_read = mailstream_low_read(s->low, cur_buf, left);
248
249 if (bytes_read == -1) {
250 if (count == left)
251 return -1;
252 else
253 return count - left;
254 }
255 else if (bytes_read == 0)
256 return count - left;
257
258 cur_buf += bytes_read;
259 left -= bytes_read;
260 }
261
262 return count;
263}
264
265ssize_t mailstream_read(mailstream * s, void * buf, size_t count)
266{
267 ssize_t read_bytes;
268 char * cur_buf;
269 size_t left;
270
271 if (s == NULL)
272 return -1;
273
274 left = count;
275 cur_buf = buf;
276 read_bytes = read_from_internal_buffer(s, cur_buf, left);
277 cur_buf += read_bytes;
278 left -= read_bytes;
279
280 if (left == 0) {
281#ifdef STREAM_DEBUG
282 STREAM_LOG("<<<<<<< read <<<<<<\n");
283 STREAM_LOG_BUF(buf, read_bytes);
284 STREAM_LOG("\n");
285 STREAM_LOG("<<<<<<< end read <<<<<<\n");
286#endif
287
288 return read_bytes;
289 }
290
291 if (left > s->buffer_max_size) {
292 read_bytes = read_through_buffer(s, cur_buf, left);
293 if (read_bytes == -1) {
294 if (count == left)
295 return -1;
296 else {
297
298#ifdef STREAM_DEBUG
299 STREAM_LOG("<<<<<<< read <<<<<<\n");
300 STREAM_LOG_BUF(buf, count - left);
301 STREAM_LOG("\n");
302 STREAM_LOG("<<<<<<< end read <<<<<<\n");
303#endif
304
305 return count - left;
306 }
307 }
308
309 cur_buf += read_bytes;
310 left -= read_bytes;
311
312#ifdef STREAM_DEBUG
313 STREAM_LOG("<<<<<<< read <<<<<<\n");
314 STREAM_LOG_BUF(buf, count - left);
315 STREAM_LOG("\n");
316 STREAM_LOG("<<<<<<< end read <<<<<<\n");
317#endif
318
319 return count - left;
320 }
321
322 read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size);
323 if (read_bytes == -1) {
324 if (left == count)
325 return -1;
326 else {
327#ifdef STREAM_DEBUG
328 STREAM_LOG("<<<<<<< read <<<<<<\n");
329 STREAM_LOG_BUF(buf, count - left);
330 STREAM_LOG("\n");
331 STREAM_LOG("<<<<<<< end read <<<<<<\n");
332#endif
333
334 return count - left;
335 }
336 }
337 else
338 s->read_buffer_len += read_bytes;
339
340 read_bytes = read_from_internal_buffer(s, cur_buf, left);
341 cur_buf += read_bytes;
342 left -= read_bytes;
343
344#ifdef STREAM_DEBUG
345 STREAM_LOG("<<<<<<< read <<<<<<\n");
346 STREAM_LOG_BUF(buf, count - left);
347 STREAM_LOG("\n");
348 STREAM_LOG("<<<<<<< end read <<<<<<\n");
349#endif
350
351 return count - left;
352}
353
354mailstream_low * mailstream_get_low(mailstream * s)
355{
356 return s->low;
357}
358
359void mailstream_set_low(mailstream * s, mailstream_low * low)
360{
361 s->low = low;
362}
363
364int mailstream_close(mailstream * s)
365{
366 mailstream_low_close(s->low);
367 mailstream_low_free(s->low);
368
369 free(s->read_buffer);
370 free(s->write_buffer);
371
372 free(s);
373
374 return 0;
375}
376
377
378
379ssize_t mailstream_feed_read_buffer(mailstream * s)
380{
381 ssize_t read_bytes;
382
383 if (s == NULL)
384 return -1;
385
386 if (s->read_buffer_len == 0) {
387 read_bytes = mailstream_low_read(s->low, s->read_buffer,
388 s->buffer_max_size);
389 if (read_bytes == -1)
390 return -1;
391 s->read_buffer_len += read_bytes;
392 }
393
394 return s->read_buffer_len;
395}
396
397struct timeval mailstream_network_delay =
398 { .tv_sec = DEFAULT_NETWORK_TIMEOUT, .tv_usec = 0 };
399