diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-25 15:47:19 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-27 08:58:53 +0200 |
commit | e971d6aded5af7b2d47107717b04a5d9bf521a29 (patch) | |
tree | d41447118e8cc99395081ae70817692c08394a5f /lib/system/sockets.c | |
parent | ef861381871a77719aac292d7ac3ee6a961b53cc (diff) | |
download | gnutls-e971d6aded5af7b2d47107717b04a5d9bf521a29.tar.gz |
split system.c to various files under system/
Diffstat (limited to 'lib/system/sockets.c')
-rw-r--r-- | lib/system/sockets.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/lib/system/sockets.c b/lib/system/sockets.c new file mode 100644 index 0000000000..f399fc93a9 --- /dev/null +++ b/lib/system/sockets.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2010-2016 Free Software Foundation, Inc. + * Copyright (C) 2015-2016 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#include <config.h> +#include <system.h> +#include "gnutls_int.h" +#include "errors.h" + +#include <sys/socket.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <c-ctype.h> + +#ifdef _WIN32 +# include <windows.h> +#else /* !_WIN32 */ +# include <poll.h> +#endif + +/* System specific socket function wrappers. + */ + +#ifdef _WIN32 +/* Do not use the gnulib functions for sending and receiving data. + * Using them makes gnutls only working with gnulib applications. + */ +#undef send +#undef recv +#undef select + +int system_errno(gnutls_transport_ptr p) +{ + int tmperr = WSAGetLastError(); + int ret = 0; + switch (tmperr) { + case WSAEWOULDBLOCK: + ret = EAGAIN; + break; + case NO_ERROR: + ret = 0; + break; + case WSAEINTR: + ret = EINTR; + break; + case WSAEMSGSIZE: + ret = EMSGSIZE; + break; + default: + ret = EIO; + break; + } + WSASetLastError(tmperr); + + return ret; +} + +ssize_t +system_write(gnutls_transport_ptr ptr, const void *data, size_t data_size) +{ + return send(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0); +} +#else /* POSIX */ +int system_errno(gnutls_transport_ptr_t ptr) +{ +#if defined(_AIX) || defined(AIX) + if (errno == 0) + errno = EAGAIN; +#endif + + return errno; +} + +static ssize_t +_system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec, + int iovec_cnt, int flags) +{ + struct msghdr hdr; + + memset(&hdr, 0, sizeof(hdr)); + hdr.msg_iov = (struct iovec *)iovec; + hdr.msg_iovlen = iovec_cnt; + + return sendmsg(GNUTLS_POINTER_TO_INT(ptr), &hdr, flags); +} + +#ifdef MSG_NOSIGNAL +ssize_t +system_writev_nosignal(gnutls_transport_ptr_t ptr, const giovec_t * iovec, + int iovec_cnt) +{ + return _system_writev(ptr, iovec, iovec_cnt, MSG_NOSIGNAL); +} + +#endif + +ssize_t +system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec, + int iovec_cnt) +{ + return _system_writev(ptr, iovec, iovec_cnt, 0); +} + +#endif + + +ssize_t +system_read(gnutls_transport_ptr_t ptr, void *data, size_t data_size) +{ + return recv(GNUTLS_POINTER_TO_INT(ptr), data, data_size, 0); +} + +/** + * gnutls_system_recv_timeout: + * @ptr: A gnutls_transport_ptr_t pointer + * @ms: The number of milliseconds to wait. + * + * Wait for data to be received from the provided socket (@ptr) within a + * timeout period in milliseconds, using select() on the provided @ptr. + * + * This function is provided as a helper for constructing custom + * callbacks for gnutls_transport_set_pull_timeout_function(), + * which can be used if you rely on socket file descriptors. + * + * Returns -1 on error, 0 on timeout, positive value if data are available for reading. + * + * Since: 3.4.0 + **/ +int gnutls_system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms) +{ + int ret; + int fd = GNUTLS_POINTER_TO_INT(ptr); +#ifndef _WIN32 + int timeo; + struct pollfd pfd; + + pfd.fd = fd; + pfd.events = POLLIN; + pfd.revents = 0; + + if (ms == GNUTLS_INDEFINITE_TIMEOUT) + timeo = -1; + else + timeo = ms; + do { + ret = poll(&pfd, 1, timeo); + } while(ret == -1 && errno == EINTR); +#else + fd_set rfds; + struct timeval _tv, *tv = NULL; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + if (ms != GNUTLS_INDEFINITE_TIMEOUT) { + _tv.tv_sec = ms/1000; + _tv.tv_usec = (ms % 1000) * 1000; + tv = &_tv; + } + + ret = select(fd + 1, &rfds, NULL, NULL, tv); +#endif + if (ret <= 0) + return ret; + + return ret; +} + |