/* * libEtPan! -- a mail stuff library * * Copyright (C) 2001, 2002 - DINH Viet Hoa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the libEtPan! project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * $Id$ */ #include "mailstream_socket.h" #include #include #include /* these 3 headers MUST be included before to insure compatibility with Mac OS X (this is true for 10.2) */ #include #include #include #include #include /* mailstream_low, socket */ static int mailstream_low_socket_close(mailstream_low * s); static ssize_t mailstream_low_socket_read(mailstream_low * s, void * buf, size_t count); static ssize_t mailstream_low_socket_write(mailstream_low * s, const void * buf, size_t count); static void mailstream_low_socket_free(mailstream_low * s); static int mailstream_low_socket_get_fd(mailstream_low * s); static mailstream_low_driver local_mailstream_socket_driver = { mailstream_read: mailstream_low_socket_read, mailstream_write: mailstream_low_socket_write, mailstream_close: mailstream_low_socket_close, mailstream_free: mailstream_low_socket_free, mailstream_get_fd: mailstream_low_socket_get_fd, }; mailstream_low_driver * mailstream_socket_driver = &local_mailstream_socket_driver; /* file descriptor must be given in (default) blocking-mode */ static struct mailstream_socket_data * socket_data_new(int fd) { struct mailstream_socket_data * socket_data; socket_data = malloc(sizeof(* socket_data)); if (socket_data == NULL) goto err; socket_data->fd = fd; return socket_data; err: return NULL; } static void socket_data_free(struct mailstream_socket_data * socket_data) { free(socket_data); } static void socket_data_close(struct mailstream_socket_data * socket_data) { close(socket_data->fd); socket_data->fd = -1; } mailstream_low * mailstream_low_socket_open(int fd) { mailstream_low * s; struct mailstream_socket_data * socket_data; socket_data = socket_data_new(fd); if (socket_data == NULL) goto err; s = mailstream_low_new(socket_data, mailstream_socket_driver); if (s == NULL) goto free_socket_data; return s; free_socket_data: socket_data_free(socket_data); err: return NULL; } static int mailstream_low_socket_close(mailstream_low * s) { struct mailstream_socket_data * socket_data; socket_data = (struct mailstream_socket_data *) s->data; socket_data_close(socket_data); return 0; } static void mailstream_low_socket_free(mailstream_low * s) { struct mailstream_socket_data * socket_data; socket_data = (struct mailstream_socket_data *) s->data; socket_data_free(socket_data); s->data = NULL; free(s); } static int mailstream_low_socket_get_fd(mailstream_low * s) { struct mailstream_socket_data * socket_data; socket_data = (struct mailstream_socket_data *) s->data; return socket_data->fd; } static ssize_t mailstream_low_socket_read(mailstream_low * s, void * buf, size_t count) { struct mailstream_socket_data * socket_data; socket_data = (struct mailstream_socket_data *) s->data; /* timeout */ { fd_set fds_read; fd_set fds_excp; struct timeval timeout; int r; timeout = mailstream_network_delay; FD_ZERO(&fds_read); FD_SET(socket_data->fd, &fds_read); FD_ZERO(&fds_excp); FD_SET(socket_data->fd, &fds_excp); // LUTZ for safety I insert here a max val as well if ( timeout.tv_sec > DEFAULT_NETWORK_TIMEOUT ) timeout.tv_sec = DEFAULT_NETWORK_TIMEOUT; r = select(socket_data->fd + 1, &fds_read, NULL, &fds_excp, &timeout); if (r < 1 ) return -1; if (FD_ISSET(socket_data->fd, &fds_excp)) return -1; if (!FD_ISSET(socket_data->fd, &fds_read)) return 0; } return recv(socket_data->fd,buf,count,MSG_NOSIGNAL); //return read(socket_data->fd, buf, count); } #include static ssize_t mailstream_low_socket_write(mailstream_low * s, const void * buf, size_t count) { struct mailstream_socket_data * socket_data; socket_data = (struct mailstream_socket_data *) s->data; /* timeout */ { fd_set fds_write; fd_set fds_excp; struct timeval timeout; int r; timeout = mailstream_network_delay; FD_ZERO(&fds_write); FD_SET(socket_data->fd, &fds_write); FD_ZERO(&fds_excp); FD_SET(socket_data->fd, &fds_excp); // LUTZ next line blocks sometimes if ( timeout.tv_sec > DEFAULT_NETWORK_TIMEOUT ) timeout.tv_sec = DEFAULT_NETWORK_TIMEOUT; //fprintf(stderr,"fd %d to secs %d \n", socket_data->fd, timeout.tv_sec ); r = select(socket_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout); if (r < 1) return -1; if (FD_ISSET(socket_data->fd, &fds_excp)) return -1; if (!FD_ISSET(socket_data->fd, &fds_write)) return 0; } return send(socket_data->fd,buf,count,MSG_NOSIGNAL); //return write(socket_data->fd, buf, count); } /* mailstream */ mailstream * mailstream_socket_open(int fd) { mailstream_low * low; mailstream * s; low = mailstream_low_socket_open(fd); if (low == NULL) goto err; s = mailstream_new(low, 8192); if (s == NULL) goto free_low; return s; free_low: mailstream_low_close(low); err: return NULL; }