1 /*****
2 *
3 * Copyright (C) 2001-2015 CS-SI. All Rights Reserved.
4 * Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
5 *
6 * This file is part of the Prelude library.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 *****/
23 
24 #include "config.h"
25 #include "libmissing.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <netinet/in.h>
33 #include <poll.h>
34 #include <sys/ioctl.h>
35 #include <gnutls/gnutls.h>
36 
37 #include "prelude-inttypes.h"
38 
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 
43 
44 #include "prelude-log.h"
45 #include "prelude-io.h"
46 #include "common.h"
47 
48 
49 #define PRELUDE_ERROR_SOURCE_DEFAULT PRELUDE_ERROR_SOURCE_IO
50 #include "prelude-error.h"
51 
52 
53 #define CHUNK_SIZE 1024
54 
55 #ifndef MIN
56 # define MIN(x, y) ((x) < (y) ? (x) : (y))
57 #endif
58 
59 struct prelude_io {
60 
61         int fd;
62         void *fd_ptr;
63 
64         size_t size;
65         size_t rindex;
66 
67         int (*close)(prelude_io_t *pio);
68         ssize_t (*read)(prelude_io_t *pio, void *buf, size_t count);
69         ssize_t (*write)(prelude_io_t *pio, const void *buf, size_t count);
70         ssize_t (*pending)(prelude_io_t *pio);
71 };
72 
73 
74 
75 /*
76  * Buffer IO functions.
77  */
buffer_read(prelude_io_t * pio,void * buf,size_t count)78 static ssize_t buffer_read(prelude_io_t *pio, void *buf, size_t count)
79 {
80         if ( pio->size - pio->rindex == 0 )
81                 return 0;
82 
83         count = MIN(count, pio->size - pio->rindex);
84 
85         memcpy(buf, (unsigned char *) pio->fd_ptr + pio->rindex, count);
86         pio->rindex += count;
87 
88         return count;
89 }
90 
91 
92 
buffer_write(prelude_io_t * pio,const void * buf,size_t count)93 static ssize_t buffer_write(prelude_io_t *pio, const void *buf, size_t count)
94 {
95         unsigned char *new;
96 
97         if ( pio->size + count <= pio->size )
98                 return -1;
99 
100         new = _prelude_realloc(pio->fd_ptr, pio->size + count);
101         if ( ! new )
102                 return prelude_error_from_errno(errno);
103 
104         memcpy(new + pio->size, buf, count);
105 
106         pio->fd_ptr = new;
107         pio->size += count;
108 
109         return count;
110 }
111 
112 
113 
buffer_close(prelude_io_t * pio)114 static int buffer_close(prelude_io_t *pio)
115 {
116         if ( pio->fd_ptr ) {
117                 free(pio->fd_ptr);
118                 pio->fd_ptr = NULL;
119                 pio->size = pio->rindex = 0;
120         }
121 
122         return 0;
123 }
124 
125 
126 
buffer_pending(prelude_io_t * pio)127 static ssize_t buffer_pending(prelude_io_t *pio)
128 {
129         return pio->size - pio->rindex;
130 }
131 
132 
133 
134 
135 /*
136  * System IO functions.
137  */
sys_read(prelude_io_t * pio,void * buf,size_t count)138 static ssize_t sys_read(prelude_io_t *pio, void *buf, size_t count)
139 {
140         ssize_t ret;
141 
142         do {
143                 ret = read(pio->fd, buf, count);
144         } while ( ret < 0 && errno == EINTR );
145 
146         if ( ret == 0 )
147                 return prelude_error(PRELUDE_ERROR_EOF);
148 
149         if ( ret < 0 ) {
150 #ifdef ECONNRESET
151                 if ( errno == ECONNRESET )
152                         return prelude_error(PRELUDE_ERROR_EOF);
153 #endif
154                 return prelude_error_from_errno(errno);
155         }
156 
157         return ret;
158 }
159 
160 
161 
sys_write(prelude_io_t * pio,const void * buf,size_t count)162 static ssize_t sys_write(prelude_io_t *pio, const void *buf, size_t count)
163 {
164         ssize_t ret;
165 
166         do {
167                 ret = write(pio->fd, buf, count);
168         } while ( ret < 0 && errno == EINTR );
169 
170         if ( ret < 0 )
171                 return prelude_error_from_errno(errno);
172 
173         return ret;
174 }
175 
176 
177 
sys_close(prelude_io_t * pio)178 static int sys_close(prelude_io_t *pio)
179 {
180         int ret;
181 
182         do {
183                 ret = close(pio->fd);
184         } while ( ret < 0 && errno == EINTR );
185 
186         return (ret >= 0) ? ret : prelude_error_from_errno(errno);
187 }
188 
189 
190 
sys_pending(prelude_io_t * pio)191 static ssize_t sys_pending(prelude_io_t *pio)
192 {
193         long ret = 0;
194 
195         if ( ioctl(pio->fd, FIONREAD, &ret) < 0 )
196                 return prelude_error_from_errno(errno);
197 
198         return ret;
199 }
200 
201 
202 
203 
204 /*
205  * Buffered IO functions.
206  */
file_read(prelude_io_t * pio,void * buf,size_t count)207 static ssize_t file_read(prelude_io_t *pio, void *buf, size_t count)
208 {
209         FILE *fd;
210         size_t ret;
211 
212         /*
213          * ferror / clearerror can be macro that might dereference fd_ptr.
214          */
215         fd = pio->fd_ptr;
216         prelude_return_val_if_fail(fd, prelude_error(PRELUDE_ERROR_ASSERTION));
217 
218         ret = fread(buf, count, 1, fd);
219         if ( ret <= 0 ) {
220                 ret = ferror(fd) ? prelude_error_from_errno(errno) : prelude_error(PRELUDE_ERROR_EOF);
221                 clearerr(fd);
222                 return ret;
223         }
224 
225         /*
226          * fread return the number of *item* read.
227          */
228         return count;
229 }
230 
231 
232 
file_write(prelude_io_t * pio,const void * buf,size_t count)233 static ssize_t file_write(prelude_io_t *pio, const void *buf, size_t count)
234 {
235         size_t ret;
236 
237         prelude_return_val_if_fail(pio->fd_ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
238 
239         ret = fwrite(buf, count, 1, pio->fd_ptr);
240         if ( ret <= 0 )
241                 return ret;
242 
243         /*
244          * fwrite return the number of *item* written.
245          */
246         return count;
247 }
248 
249 
250 
file_close(prelude_io_t * pio)251 static int file_close(prelude_io_t *pio)
252 {
253         prelude_return_val_if_fail(pio->fd_ptr, prelude_error(PRELUDE_ERROR_ASSERTION));
254         return fclose(pio->fd_ptr);
255 }
256 
257 
258 
file_pending(prelude_io_t * pio)259 static ssize_t file_pending(prelude_io_t *pio)
260 {
261 #ifdef ENOTSUP
262         return prelude_error_from_errno(ENOTSUP);
263 #else
264         return prelude_error(PRELUDE_ERROR_GENERIC);
265 #endif
266 }
267 
268 
269 
270 /*
271  * TLS IO functions
272  */
tls_check_error(prelude_io_t * pio,int error)273 static int tls_check_error(prelude_io_t *pio, int error)
274 {
275         int ret = 0;
276         const char *alert;
277 
278         switch(error) {
279         case GNUTLS_E_AGAIN:
280                 ret = prelude_error(PRELUDE_ERROR_EAGAIN);
281                 break;
282 
283         case GNUTLS_E_WARNING_ALERT_RECEIVED:
284                 alert = gnutls_alert_get_name(gnutls_alert_get(pio->fd_ptr));
285                 ret = prelude_error_verbose(PRELUDE_ERROR_TLS_WARNING_ALERT, "TLS warning alert from peer: %s", alert);
286                 break;
287 
288         case GNUTLS_E_FATAL_ALERT_RECEIVED:
289                 alert = gnutls_alert_get_name(gnutls_alert_get(pio->fd_ptr));
290                 ret = prelude_error_verbose(PRELUDE_ERROR_TLS_FATAL_ALERT, "TLS fatal alert from peer: %s", alert);
291                 break;
292 
293         case GNUTLS_E_PUSH_ERROR:
294         case GNUTLS_E_PULL_ERROR:
295         case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
296                 ret = prelude_error(PRELUDE_ERROR_EOF);
297                 break;
298 
299         default:
300                 ret = prelude_error_verbose(PRELUDE_ERROR_TLS, "TLS: %s", gnutls_strerror(error));
301         }
302 
303         /*
304          * If the error is fatal, deinitialize the session and revert
305          * to system IO. The caller is then expected to call prelude_io_close()
306          * again until it return 0.
307          *
308          * If it's non fatal, simply return the error. The caller is supposed
309          * to resume the prelude_io_close() call still.
310          */
311         if ( gnutls_error_is_fatal(error) ) {
312                 gnutls_deinit(pio->fd_ptr);
313                 prelude_io_set_sys_io(pio, pio->fd);
314         }
315 
316         return ret;
317 }
318 
319 
320 
tls_read(prelude_io_t * pio,void * buf,size_t count)321 static ssize_t tls_read(prelude_io_t *pio, void *buf, size_t count)
322 {
323         ssize_t ret;
324 
325         do {
326                 ret = gnutls_record_recv(pio->fd_ptr, buf, count);
327         } while ( ret < 0 && ret == GNUTLS_E_INTERRUPTED );
328 
329         if ( ret < 0 )
330                 return tls_check_error(pio, ret);
331 
332         if ( ret == 0 )
333                 return prelude_error(PRELUDE_ERROR_EOF);
334 
335         return ret;
336 }
337 
338 
339 
tls_write(prelude_io_t * pio,const void * buf,size_t count)340 static ssize_t tls_write(prelude_io_t *pio, const void *buf, size_t count)
341 {
342         ssize_t ret;
343 
344         do {
345                 ret = gnutls_record_send(pio->fd_ptr, buf, count);
346         } while ( ret < 0 && ret == GNUTLS_E_INTERRUPTED );
347 
348         if ( ret < 0 )
349                 return tls_check_error(pio, ret);
350 
351         return ret;
352 }
353 
354 
355 
tls_close(prelude_io_t * pio)356 static int tls_close(prelude_io_t *pio)
357 {
358         int ret;
359 
360         do {
361                 ret = gnutls_bye(pio->fd_ptr, GNUTLS_SHUT_RDWR);
362         } while ( ret < 0 && ret == GNUTLS_E_INTERRUPTED );
363 
364         if ( ret < 0 ) {
365                 ret = tls_check_error(pio, ret);
366                 if ( prelude_io_is_error_fatal(pio, ret) )
367                         sys_close(pio);
368 
369                 return ret;
370         }
371 
372         gnutls_deinit(pio->fd_ptr);
373 
374         /*
375          * this is not expected to fail
376          */
377         prelude_io_set_sys_io(pio, pio->fd);
378         return sys_close(pio);
379 }
380 
381 
382 
tls_pending(prelude_io_t * pio)383 static ssize_t tls_pending(prelude_io_t *pio)
384 {
385         ssize_t ret;
386 
387         ret = gnutls_record_check_pending(pio->fd_ptr);
388         if ( ret > 0 )
389                 return ret;
390 
391         ret = sys_pending(pio);
392         if ( ret > 0 )
393                 return ret;
394 
395         return 0;
396 }
397 
398 
399 
400 /*
401  * Forward data from one fd to another using copy.
402  */
copy_forward(prelude_io_t * dst,prelude_io_t * src,size_t count)403 static ssize_t copy_forward(prelude_io_t *dst, prelude_io_t *src, size_t count)
404 {
405         int ret;
406         size_t scount;
407         unsigned char buf[8192];
408 
409         scount = count;
410 
411         while ( count ) {
412 
413                 ret = (count < sizeof(buf)) ? count : sizeof(buf);
414 
415                 ret = prelude_io_read(src, buf, ret);
416                 if ( ret <= 0 )
417                         return ret;
418 
419                 count -= ret;
420 
421                 ret = prelude_io_write(dst, buf, ret);
422                 if ( ret < 0 )
423                         return ret;
424         }
425 
426         return scount;
427 }
428 
429 
430 
431 
432 
433 /**
434  * prelude_io_forward:
435  * @src: Pointer to a #prelude_io_t object.
436  * @dst: Pointer to a #prelude_io_t object.
437  * @count: Number of byte to forward from @src to @dst.
438  *
439  * prelude_io_forward() attempts to transfer up to @count bytes from
440  * the file descriptor identified by @src into the file descriptor
441  * identified by @dst.
442  *
443  * Returns: If the transfer was successful, the number of bytes written
444  * to @dst is returned.  On error, -1 is returned, and errno is set appropriately.
445  */
prelude_io_forward(prelude_io_t * dst,prelude_io_t * src,size_t count)446 ssize_t prelude_io_forward(prelude_io_t *dst, prelude_io_t *src, size_t count)
447 {
448         prelude_return_val_if_fail(dst, prelude_error(PRELUDE_ERROR_ASSERTION));
449         prelude_return_val_if_fail(src, prelude_error(PRELUDE_ERROR_ASSERTION));
450 
451         return copy_forward(dst, src, count);
452 }
453 
454 
455 
456 
457 /**
458  * prelude_io_read:
459  * @pio: Pointer to a #prelude_io_t object.
460  * @buf: Pointer to the buffer to store data into.
461  * @count: Number of bytes to read.
462  *
463  * prelude_io_read() attempts to read up to @count bytes from the
464  * file descriptor identified by @pio into the buffer starting at @buf.
465  *
466  * If @count is zero, prelude_io_read() returns zero and has no other
467  * results. If @count is greater than SSIZE_MAX, the result is unspecified.
468  *
469  * The case where the read function would be interrupted by a signal is
470  * handled internally. So you don't have to check for EINTR.
471  *
472  * Returns: On success, the number of bytes read is returned (zero
473  * indicates end of file). It is not an error if this number is smaller
474  * than the number of bytes requested; this may happen for example because
475  * fewer bytes are actually available right now or because read() was
476  * interrupted by a signal.
477  *
478  * On error, a negative value is returned. In this case it is left unspecified
479  * whether the file position (if any) changes.
480  */
prelude_io_read(prelude_io_t * pio,void * buf,size_t count)481 ssize_t prelude_io_read(prelude_io_t *pio, void *buf, size_t count)
482 {
483         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
484         prelude_return_val_if_fail(pio->read, prelude_error(PRELUDE_ERROR_ASSERTION));
485         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
486 
487         return pio->read(pio, buf, count);
488 }
489 
490 
491 
492 
493 /**
494  * prelude_io_read_wait:
495  * @pio: Pointer to a #prelude_io_t object.
496  * @buf: Pointer to the buffer to store data into.
497  * @count: Number of bytes to read.
498  *
499  * prelude_io_read_wait() attempts to read up to @count bytes from the
500  * file descriptor identified by @pio into the buffer starting at @buf.
501  *
502  * If @count is zero, prelude_io_read() returns zero and has no other
503  * results. If @count is greater than SSIZE_MAX, the result is unspecified.
504  *
505  * The case where the read function would be interrupted by a signal is
506  * handled internally. So you don't have to check for EINTR.
507  *
508  * prelude_io_read_wait() always return the number of bytes requested.
509  * Be carefull that this function is blocking.
510  *
511  * Returns: On success, the number of bytes read is returned (zero
512  * indicates end of file).
513  *
514  * On error, -1 is returned, and errno is set appropriately. In this
515  * case it is left unspecified whether the file position (if any) changes.
516  */
prelude_io_read_wait(prelude_io_t * pio,void * buf,size_t count)517 ssize_t prelude_io_read_wait(prelude_io_t *pio, void *buf, size_t count)
518 {
519         ssize_t ret;
520         size_t n = 0;
521         struct pollfd pfd;
522         unsigned char *in = buf;
523 
524         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
525         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
526 
527         pfd.fd = prelude_io_get_fd(pio);
528         pfd.events = POLLIN;
529 
530         do {
531                 ret = poll(&pfd, 1, -1);
532                 if ( ret < 0 )
533                         return prelude_error_from_errno(errno);
534 
535                 if ( ! (pfd.revents & POLLIN) )
536                         return prelude_error_verbose(PRELUDE_ERROR_GENERIC, "expected POLLIN event");
537 
538                 ret = prelude_io_read(pio, &in[n], count - n);
539                 if ( ret < 0 )
540                         return ret;
541 
542                 n += (size_t) ret;
543 
544         } while ( n != count );
545 
546         return (ssize_t) n;
547 }
548 
549 
550 
551 /**
552  * prelude_io_read_delimited:
553  * @pio: Pointer to a #prelude_io_t object.
554  * @buf: Pointer to the address of a buffer to store address of data into.
555  *
556  * prelude_io_read_delimited() read message written by prelude_write_delimited().
557  * Theses messages are sents along with the len of the message.
558  *
559  * Uppon return the @buf argument is updated to point on a newly allocated
560  * buffer containing the data read. The @count argument is set to the number of
561  * bytes the message was containing.
562  *
563  * The case where the read function would be interrupted by a signal is
564  * handled internally. So you don't have to check for EINTR.
565  *
566  * Returns: On success, the number of bytes read is returned (zero
567  * indicates end of file).
568  *
569  * On error, -1 is returned, and errno is set appropriately. In this
570  * case it is left unspecified whether the file position (if any) changes.
571  */
prelude_io_read_delimited(prelude_io_t * pio,unsigned char ** buf)572 ssize_t prelude_io_read_delimited(prelude_io_t *pio, unsigned char **buf)
573 {
574         ssize_t ret;
575         size_t count;
576         uint16_t msglen;
577 
578         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
579 
580         ret = prelude_io_read_wait(pio, &msglen, sizeof(msglen));
581         if ( ret <= 0 )
582                 return ret;
583 
584         count = ntohs(msglen);
585 
586         *buf = malloc(count);
587         if ( ! *buf )
588                 return prelude_error_from_errno(errno);
589 
590         ret = prelude_io_read_wait(pio, *buf, count);
591         if ( ret < 0 )
592                 return ret;
593 
594         return count;
595 }
596 
597 
598 
599 
600 /**
601  * prelude_io_write:
602  * @pio: Pointer to a #prelude_io_t object.
603  * @buf: Pointer to the buffer to write data from.
604  * @count: Number of bytes to write.
605  *
606  * prelude_io_write() writes up to @count bytes to the file descriptor
607  * identified by @pio from the buffer starting at @buf. POSIX requires
608  * that a read() which can be proved to occur after a write() has returned
609  * returns the new data. Note that not all file systems are POSIX conforming.
610  *
611  * The case where the write() function would be interrupted by a signal is
612  * handled internally. So you don't have to check for EINTR.
613  *
614  * Returns: On success, the number of bytes written are returned (zero
615  * indicates nothing was written). On error, -1 is returned, and errno
616  * is set appropriately. If @count is zero and the file descriptor refers
617  * to a regular file, 0 will be returned without causing any other effect.
618  * For a special file, the results are not portable.
619  */
prelude_io_write(prelude_io_t * pio,const void * buf,size_t count)620 ssize_t prelude_io_write(prelude_io_t *pio, const void *buf, size_t count)
621 {
622         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
623         prelude_return_val_if_fail(pio->write, prelude_error(PRELUDE_ERROR_ASSERTION));
624         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
625 
626         return pio->write(pio, buf, count);
627 }
628 
629 
630 
631 /**
632  * prelude_io_write_delimited:
633  * @pio: Pointer to a #prelude_io_t object.
634  * @buf: Pointer to the buffer to write data from.
635  * @count: Number of bytes to write.
636  *
637  * prelude_io_write_delimited() writes up to @count bytes to the file descriptor
638  * identified by @pio from the buffer starting at @buf. POSIX requires
639  * that a read() which can be proved to occur after a write() has returned
640  * returns the new data. Note that not all file systems are POSIX conforming.
641  *
642  * prelude_io_write_delimited() also write the len of the data to be sent.
643  * which allow prelude_io_read_delimited() to safely know if it got all the
644  * data a given write contain.
645  *
646  * The case where the write() function would be interrupted by a signal is
647  * handled internally. So you don't have to check for EINTR.
648  *
649  * Returns: On success, the number of bytes written are returned (zero
650  * indicates nothing was written). On error, -1 is returned, and errno
651  * is set appropriately.
652  */
prelude_io_write_delimited(prelude_io_t * pio,const void * buf,uint16_t count)653 ssize_t prelude_io_write_delimited(prelude_io_t *pio, const void *buf, uint16_t count)
654 {
655         int ret;
656         uint16_t nlen;
657 
658         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
659         prelude_return_val_if_fail(buf, prelude_error(PRELUDE_ERROR_ASSERTION));
660 
661         nlen = htons(count);
662 
663         ret = prelude_io_write(pio, &nlen, sizeof(nlen));
664         if ( ret <= 0 )
665                 return ret;
666 
667         ret = prelude_io_write(pio, buf, count);
668         if ( ret <= 0 )
669                 return ret;
670 
671         return count;
672 }
673 
674 
675 
676 
677 /**
678  * prelude_io_close:
679  * @pio: Pointer to a #prelude_io_t object.
680  *
681  * prelude_io_close() closes the file descriptor indentified by @pio,
682  *
683  * The case where the close() function would be interrupted by a signal is
684  * handled internally. So you don't have to check for EINTR.
685  *
686  * However, and especially when the underlaying layer is TLS, prelude_io_close()
687  * might return error. If this happen, you should continue calling the function
688  * until it return zero.
689  *
690  * Returns: zero on success, or -1 if an error occurred.
691  */
prelude_io_close(prelude_io_t * pio)692 int prelude_io_close(prelude_io_t *pio)
693 {
694         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
695         prelude_return_val_if_fail(pio->close, prelude_error(PRELUDE_ERROR_ASSERTION));
696 
697         return pio->close(pio);
698 }
699 
700 
701 
702 
703 /**
704  * prelude_io_new:
705  * @ret: Pointer where to store the created #prelude_io_t object.
706  *
707  * Create a new prelude IO object.
708  *
709  * Returns: 0 on success, or a negative value if an error occur.
710  */
prelude_io_new(prelude_io_t ** ret)711 int prelude_io_new(prelude_io_t **ret)
712 {
713         *ret = calloc(1, sizeof(**ret));
714         if ( ! *ret )
715                 return prelude_error_from_errno(errno);
716 
717         return 0;
718 }
719 
720 
721 
722 /**
723  * prelude_io_set_file_io:
724  * @pio: A pointer on the #prelude_io_t object.
725  * @fd: File descriptor identifying a file.
726  *
727  * Setup the @pio object to work with file I/O function.
728  * The @pio object is then associated with @fd.
729  */
prelude_io_set_file_io(prelude_io_t * pio,FILE * fdptr)730 void prelude_io_set_file_io(prelude_io_t *pio, FILE *fdptr)
731 {
732         prelude_return_if_fail(pio);
733         prelude_return_if_fail(fdptr);
734 
735         pio->fd = fileno(fdptr);
736         pio->fd_ptr = fdptr;
737         pio->read = file_read;
738         pio->write = file_write;
739         pio->close = file_close;
740         pio->pending = file_pending;
741 }
742 
743 
744 
745 
746 /**
747  * prelude_io_set_tls_io:
748  * @pio: A pointer on the #prelude_io_t object.
749  * @tls: Pointer on the TLS structure holding the TLS connection data.
750  *
751  * Setup the @pio object to work with TLS based I/O function.
752  * The @pio object is then associated with @tls.
753  */
prelude_io_set_tls_io(prelude_io_t * pio,void * tls)754 void prelude_io_set_tls_io(prelude_io_t *pio, void *tls)
755 {
756         union {
757                 void *ptr;
758                 int fd;
759         } data;
760 
761         prelude_return_if_fail(pio);
762         prelude_return_if_fail(tls);
763 
764         data.ptr = gnutls_transport_get_ptr(tls);
765         pio->fd = data.fd;
766 
767         pio->fd_ptr = tls;
768         pio->read = tls_read;
769         pio->write = tls_write;
770         pio->close = tls_close;
771         pio->pending = tls_pending;
772 }
773 
774 
775 
776 
777 /**
778  * prelude_io_set_sys_io:
779  * @pio: A pointer on the #prelude_io_t object.
780  * @fd: A file descriptor.
781  *
782  * Setup the @pio object to work with system based I/O function.
783  * The @pio object is then associated with @fd.
784  */
prelude_io_set_sys_io(prelude_io_t * pio,int fd)785 void prelude_io_set_sys_io(prelude_io_t *pio, int fd)
786 {
787         prelude_return_if_fail(pio);
788 
789         pio->fd = fd;
790         pio->fd_ptr = NULL;
791         pio->read = sys_read;
792         pio->write = sys_write;
793         pio->close = sys_close;
794         pio->pending = sys_pending;
795 }
796 
797 
798 
prelude_io_set_buffer_io(prelude_io_t * pio)799 int prelude_io_set_buffer_io(prelude_io_t *pio)
800 {
801         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
802 
803         pio->fd_ptr = NULL;
804         pio->size = pio->rindex = 0;
805 
806         pio->read = buffer_read;
807         pio->write = buffer_write;
808         pio->close = buffer_close;
809         pio->pending = buffer_pending;
810 
811         return 0;
812 }
813 
814 
815 
816 /**
817  * prelude_io_get_fd:
818  * @pio: A pointer on a #prelude_io_t object.
819  *
820  * Returns: The FD associated with this object.
821  */
prelude_io_get_fd(prelude_io_t * pio)822 int prelude_io_get_fd(prelude_io_t *pio)
823 {
824         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
825         return pio->fd;
826 }
827 
828 
829 
830 /**
831  * prelude_io_get_fdptr:
832  * @pio: A pointer on a #prelude_io_t object.
833  *
834  * Returns: Pointer associated with this object (file, tls, buffer, or NULL).
835  */
prelude_io_get_fdptr(prelude_io_t * pio)836 void *prelude_io_get_fdptr(prelude_io_t *pio)
837 {
838         prelude_return_val_if_fail(pio, NULL);
839         return pio->fd_ptr;
840 }
841 
842 
843 
844 /**
845  * prelude_io_destroy:
846  * @pio: Pointer to a #prelude_io_t object.
847  *
848  * Destroy the @pio object.
849  */
prelude_io_destroy(prelude_io_t * pio)850 void prelude_io_destroy(prelude_io_t *pio)
851 {
852         prelude_return_if_fail(pio);
853         free(pio);
854 }
855 
856 
857 
858 
859 /**
860  * prelude_io_pending:
861  * @pio: Pointer to a #prelude_io_t object.
862  *
863  * prelude_io_pending return the number of bytes waiting to
864  * be read on an TLS or socket fd.
865  *
866  * Returns: Number of byte waiting to be read on @pio, or -1
867  * if @pio is not of type TLS or socket.
868  */
prelude_io_pending(prelude_io_t * pio)869 ssize_t prelude_io_pending(prelude_io_t *pio)
870 {
871         prelude_return_val_if_fail(pio, prelude_error(PRELUDE_ERROR_ASSERTION));
872         return pio->pending(pio);
873 }
874 
875 
876 
877 
878 /**
879  * prelude_io_is_error_fatal:
880  * @pio: Pointer to a #prelude_io_t object.
881  * @error: Error returned by one of the #prelude_io_t function.
882  *
883  * Check whether the returned error is fatal, or not.
884  *
885  * Returns: TRUE if error is fatal, FALSE if it is not.
886  */
prelude_io_is_error_fatal(prelude_io_t * pio,int error)887 prelude_bool_t prelude_io_is_error_fatal(prelude_io_t *pio, int error)
888 {
889         prelude_error_code_t code;
890 
891         prelude_return_val_if_fail(pio, FALSE);
892 
893         if ( ! error )
894                 return FALSE;
895 
896         code = prelude_error_get_code(error);
897         if ( code == PRELUDE_ERROR_EAGAIN || code == PRELUDE_ERROR_EINTR || code == PRELUDE_ERROR_TLS_WARNING_ALERT )
898                 return FALSE;
899 
900         return TRUE;
901 }
902 
903 
904 
905 /**
906  * prelude_io_set_write_callback:
907  * @pio: Pointer to a #prelude_io_t object.
908  * @write: Callback function to be called on prelude_io_write().
909  *
910  * Set an user defined write callback function to be called on
911  * prelude_io_write().
912  */
prelude_io_set_write_callback(prelude_io_t * pio,ssize_t (* write)(prelude_io_t * io,const void * buf,size_t count))913 void prelude_io_set_write_callback(prelude_io_t *pio, ssize_t (*write)(prelude_io_t *io, const void *buf, size_t count))
914 {
915         pio->write = write;
916 }
917 
918 
919 /**
920  * prelude_io_set_read_callback:
921  * @pio: Pointer to a #prelude_io_t object.
922  * @read: Callback function to be called on prelude_io_read().
923  *
924  * Set an user defined read callback function to be called on
925  * prelude_io_read().
926  */
prelude_io_set_read_callback(prelude_io_t * pio,ssize_t (* read)(prelude_io_t * io,void * buf,size_t count))927 void prelude_io_set_read_callback(prelude_io_t *pio, ssize_t (*read)(prelude_io_t *io, void *buf, size_t count))
928 {
929         pio->read = read;
930 }
931 
932 
933 
934 /**
935  * prelude_io_set_pending_callback:
936  * @pio: Pointer to a #prelude_io_t object.
937  * @pending: Callback function to be called on prelude_io_pending().
938  *
939  * Set an user defined read callback function to be called on
940  * prelude_io_pending().
941  */
prelude_io_set_pending_callback(prelude_io_t * pio,ssize_t (* pending)(prelude_io_t * io))942 void prelude_io_set_pending_callback(prelude_io_t *pio, ssize_t (*pending)(prelude_io_t *io))
943 {
944         pio->pending = pending;
945 }
946 
947 
948 
949 /**
950  * prelude_io_set_fdptr:
951  * @pio: Pointer to a #prelude_io_t object.
952  * @ptr: Pointer to user defined data.
953  *
954  * Set an user defined pointer that might be retrieved using
955  * prelude_io_get_fdptr().
956  */
prelude_io_set_fdptr(prelude_io_t * pio,void * ptr)957 void prelude_io_set_fdptr(prelude_io_t *pio, void *ptr)
958 {
959         pio->fd_ptr = ptr;
960 }
961