ssize_t system_writev(gnutls_transport_ptr_t ptr, const giovec_t * iovec, int iovec_cnt) { return writev(GNUTLS_POINTER_TO_INT(ptr), (struct iovec *) iovec, iovec_cnt); }
/* Wait for data to be received within a timeout period in milliseconds. * To catch a termination it will also try to receive 0 bytes from the * socket if select reports to proceed. * * Returns -1 on error, 0 on timeout, positive value if data are available for reading. */ int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms) { fd_set rfds; struct timeval tv; int ret; int fd = GNUTLS_POINTER_TO_INT(ptr); FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = 0; tv.tv_usec = ms * 1000; while(tv.tv_usec >= 1000000) { tv.tv_usec -= 1000000; tv.tv_sec++; } ret = select(fd+1, &rfds, NULL, NULL, &tv); if (ret <= 0) return ret; return ret; }
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); }
ssize_t system_writev_nosignal(gnutls_transport_ptr_t ptr, const giovec_t * iovec, int iovec_cnt) { 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, MSG_NOSIGNAL); }
/* Wait for data to be received within a timeout period in milliseconds. * If data_size > 0 it will return the specified amount of data in * peek mode. * * Returns -1 on error, 0 on timeout. */ int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms) { fd_set rfds; struct timeval tv; int ret, ret2; FD_ZERO(&rfds); FD_SET(GNUTLS_POINTER_TO_INT(ptr), &rfds); tv.tv_sec = 0; tv.tv_usec = ms * 1000; ret = select(GNUTLS_POINTER_TO_INT(ptr)+1, &rfds, NULL, NULL, &tv); if (ret <= 0) return ret; ret2 = recv(GNUTLS_POINTER_TO_INT(ptr), NULL, 0, MSG_PEEK); if (ret2 == -1) return ret2; return ret; }
/** * 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; }
void BIO_get_fd (gnutls_session_t gnutls_state, int *fd) { gnutls_transport_ptr_t tmp = gnutls_transport_get_ptr (gnutls_state); *fd = GNUTLS_POINTER_TO_INT (tmp); }
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); }
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); }
void BIO_get_fd (gnutls_session_t gnutls_state, int *fd) { *fd = GNUTLS_POINTER_TO_INT (gnutls_transport_get_ptr (gnutls_state)); }
/* This function is like write. But it does not return -1 on error. * It does return gnutls_errno instead. * * In case of E_AGAIN and E_INTERRUPTED errors, you must call gnutls_write_flush(), * until it returns ok (0). * * We need to push exactly the data in n, since we cannot send less * data. In TLS the peer must receive the whole packet in order * to decrypt and verify the integrity. * */ ssize_t _gnutls_io_write_buffered (gnutls_session_t session, const void *iptr, size_t n) { size_t left; unsigned j, x, sum = 0; ssize_t retval, i; const opaque *ptr; int ret; gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; /* to know where the procedure was interrupted. */ session->internals.direction = 1; ptr = iptr; /* In case the previous write was interrupted, check if the * iptr != NULL and we have data in the buffer. * If this is true then return an error. */ if (session->internals.record_send_buffer.length > 0 && iptr != NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* If data in the buffer exist */ if (iptr == NULL) { /* checking is handled above */ ret = _gnutls_buffer_get (&session->internals.record_send_buffer, &ptr, &n); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_write_log ("WRITE: Restoring old write. (%d bytes to send)\n", n); } _gnutls_write_log ("WRITE: Will write %d bytes to %d.\n", n, fd); i = 0; left = n; while (left > 0) { if (session->internals._gnutls_push_func == NULL) i = send (GNUTLS_POINTER_TO_INT(fd), &ptr[n - left], left, 0); else i = session->internals._gnutls_push_func (fd, &ptr[n - left], left); if (i == -1) { if (errno == EAGAIN || errno == EINTR) { session->internals.record_send_buffer_prev_size += n - left; retval = _gnutls_buffer_insert (&session->internals. record_send_buffer, &ptr[n - left], left); if (retval < 0) { gnutls_assert (); return retval; } _gnutls_write_log ("WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n", left, n - left); retval = RET (errno); return retval; } else { gnutls_assert (); return GNUTLS_E_PUSH_ERROR; } } left -= i; if (_gnutls_log_level >= 7) { char line[128]; char tmp[16]; _gnutls_write_log ("WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n", i, fd, left, n); for (x = 0; x < (unsigned) ((i) / 16) + 1; x++) { line[0] = 0; if (sum > n - left) break; sprintf (tmp, "%.4x - ", x); _gnutls_str_cat (line, sizeof (line), tmp); for (j = 0; j < 16; j++) { if (sum < n - left) { sprintf (tmp, "%.2x ", ((unsigned char *) ptr)[sum++]); _gnutls_str_cat (line, sizeof (line), tmp); } else break; } _gnutls_write_log ("%s\n", line); } } } retval = n + session->internals.record_send_buffer_prev_size; session->internals.record_send_buffer.length = 0; session->internals.record_send_buffer_prev_size = 0; return retval; }
/* This function is like read. But it does not return -1 on error. * It does return gnutls_errno instead. * * Flags are only used if the default recv() function is being used. */ static ssize_t _gnutls_read (gnutls_session_t session, void *iptr, size_t sizeOfPtr, int flags) { size_t left; ssize_t i = 0; char *ptr = iptr; unsigned j, x, sum = 0; gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; session->internals.direction = 0; left = sizeOfPtr; while (left > 0) { if (session->internals._gnutls_pull_func == NULL) i = recv (GNUTLS_POINTER_TO_INT(fd), &ptr[sizeOfPtr - left], left, flags); else i = session->internals._gnutls_pull_func (fd, &ptr[sizeOfPtr - left], left); if (i < 0) { _gnutls_read_log ("READ: %d returned from %d, errno=%d\n", i, fd, errno); if (errno == EAGAIN || errno == EINTR) { if (sizeOfPtr - left > 0) { _gnutls_read_log ("READ: returning %d bytes from %d\n", sizeOfPtr - left, fd); goto finish; } gnutls_assert (); return RET (errno); } else { gnutls_assert (); return GNUTLS_E_PULL_ERROR; } } else { _gnutls_read_log ("READ: Got %d bytes from %d\n", i, fd); if (i == 0) break; /* EOF */ } left -= i; } finish: if (_gnutls_log_level >= 7) { char line[128]; char tmp[16]; _gnutls_read_log ("READ: read %d bytes from %d\n", (sizeOfPtr - left), fd); for (x = 0; x < ((sizeOfPtr - left) / 16) + 1; x++) { line[0] = 0; sprintf (tmp, "%.4x - ", x); _gnutls_str_cat (line, sizeof (line), tmp); for (j = 0; j < 16; j++) { if (sum < (sizeOfPtr - left)) { sprintf (tmp, "%.2x ", ((unsigned char *) ptr)[sum++]); _gnutls_str_cat (line, sizeof (line), tmp); } } _gnutls_read_log ("%s\n", line); } } return (sizeOfPtr - left); }
/* This function is like write. But it does not return -1 on error. * It does return MHD_gnutls_errno instead. * * In case of E_AGAIN and E_INTERRUPTED errors, you must call MHD_gnutls_write_flush(), * until it returns ok (0). * * We need to push exactly the data in n, since we cannot send less * data. In TLS the peer must receive the whole packet in order * to decrypt and verify the integrity. * */ ssize_t MHD_gtls_io_write_buffered (MHD_gtls_session_t session, const void *iptr, size_t n) { size_t left; unsigned j, x, sum = 0; ssize_t retval, i; const opaque *ptr; int ret; MHD_gnutls_transport_ptr_t fd = session->internals.transport_send_ptr; /* to know where the procedure was interrupted. */ session->internals.direction = 1; ptr = iptr; /* In case the previous write was interrupted, check if the * iptr != NULL and we have data in the buffer. * If this is true then return an error. */ if (session->internals.record_send_buffer.length > 0 && iptr != NULL) { MHD_gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* If data in the buffer exist */ if (iptr == NULL) { /* checking is handled above */ ret = MHD__gnutls_buffer_get (&session->internals.record_send_buffer, &ptr, &n); if (ret < 0) { MHD_gnutls_assert (); return ret; } MHD__gnutls_write_log ("WRITE: Restoring old write. (%d bytes to send)\n", n); } MHD__gnutls_write_log ("WRITE: Will write %d bytes to %d.\n", n, fd); i = 0; left = n; while (left > 0) { session->internals.errnum = 0; if (session->internals.MHD__gnutls_push_func == NULL) { i = send (GNUTLS_POINTER_TO_INT (fd), &ptr[n - left], left, 0); #if HAVE_WINSOCK if (i < 0) { int tmperr = WSAGetLastError (); switch (tmperr) { case WSAEWOULDBLOCK: session->internals.errnum = EAGAIN; break; case WSAEINTR: session->internals.errnum = EINTR; break; default: session->internals.errnum = EIO; break; } WSASetLastError (tmperr); } #endif } else i = session->internals.MHD__gnutls_push_func (fd, &ptr[n - left], left); if (i == -1) { int err = session->internals.errnum ? session->internals.errnum : errno; if ( (err == EAGAIN) || (err == EINTR) ) { session->internals.record_send_buffer_prev_size += n - left; retval = MHD__gnutls_buffer_insert (&session-> internals.record_send_buffer, &ptr[n - left], left); if (retval < 0) { MHD_gnutls_assert (); return retval; } if (err == EAGAIN) return GNUTLS_E_AGAIN; return GNUTLS_E_INTERRUPTED; } else { MHD_gnutls_assert (); return GNUTLS_E_PUSH_ERROR; } } left -= i; if (MHD__gnutls_log_level >= 7) { char line[128]; char tmp[16]; MHD__gnutls_write_log ("WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n", i, fd, left, n); for (x = 0; x < (unsigned) ((i) / 16) + 1; x++) { line[0] = 0; if (sum > n - left) break; sprintf (tmp, "%.4x - ", x); MHD_gtls_str_cat (line, sizeof (line), tmp); for (j = 0; j < 16; j++) { if (sum < n - left) { sprintf (tmp, "%.2x ", ((unsigned char *) ptr)[sum++]); MHD_gtls_str_cat (line, sizeof (line), tmp); } else break; } MHD__gnutls_write_log ("%s\n", line); } } } retval = n + session->internals.record_send_buffer_prev_size; session->internals.record_send_buffer.length = 0; session->internals.record_send_buffer_prev_size = 0; return retval; }
/* This function is like read. But it does not return -1 on error. * It does return MHD_gnutls_errno instead. * * Flags are only used if the default recv() function is being used. */ static ssize_t MHD__gnutls_read (MHD_gtls_session_t session, void *iptr, size_t sizeOfPtr, int flags) { size_t left; ssize_t i = 0; char *ptr = iptr; MHD_gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; session->internals.direction = 0; left = sizeOfPtr; while (left > 0) { session->internals.errnum = 0; if (session->internals.MHD__gnutls_pull_func == NULL) { i = recv (GNUTLS_POINTER_TO_INT (fd), &ptr[sizeOfPtr - left], left, flags); #if HAVE_WINSOCK if (i < 0) { int tmperr = WSAGetLastError (); switch (tmperr) { case WSAEWOULDBLOCK: session->internals.errnum = EAGAIN; break; case WSAEINTR: session->internals.errnum = EINTR; break; default: session->internals.errnum = EIO; break; } WSASetLastError (tmperr); } #endif } else i = session->internals.MHD__gnutls_pull_func (fd, &ptr[sizeOfPtr - left], left); if (i < 0) { int err = session->internals.errnum ? session->internals.errnum : errno; if ( (err == EAGAIN) || (err == EINTR) ) { if (sizeOfPtr - left > 0) goto finish; MHD_gnutls_assert (); if (err == EAGAIN) return GNUTLS_E_AGAIN; return GNUTLS_E_INTERRUPTED; } else { MHD_gnutls_assert (); return GNUTLS_E_PULL_ERROR; } } else { if (i == 0) break; /* EOF */ } left -= i; } finish: return (sizeOfPtr - left); }
/* This function is like read. But it does not return -1 on error. * It does return gnutls_errno instead. * * Flags are only used if the default recv() function is being used. */ static ssize_t _gnutls_read (gnutls_session_t session, void *iptr, size_t sizeOfPtr, int flags) { size_t left; ssize_t i = 0; char *ptr = iptr; unsigned j, x, sum = 0; gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr; session->internals.direction = 0; left = sizeOfPtr; while (left > 0) { session->internals.errnum = 0; if (session->internals._gnutls_pull_func == NULL) { i = recv (GNUTLS_POINTER_TO_INT (fd), &ptr[sizeOfPtr - left], left, flags); #if HAVE_WINSOCK2_H if (i < 0) { int tmperr = WSAGetLastError (); switch (tmperr) { case WSAEWOULDBLOCK: session->internals.errnum = EAGAIN; break; case WSAEINTR: session->internals.errnum = EINTR; break; default: session->internals.errnum = EIO; break; } WSASetLastError (tmperr); } #endif } else i = session->internals._gnutls_pull_func (fd, &ptr[sizeOfPtr - left], left); if (i < 0) { int err = session->internals.errnum ? session->internals.errnum : errno; _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n", i, fd, errno, session->internals.errnum); if (err == EAGAIN || err == EINTR) { if (sizeOfPtr - left > 0) { _gnutls_read_log ("READ: returning %d bytes from %p\n", sizeOfPtr - left, fd); goto finish; } gnutls_assert (); if (err == EAGAIN) return GNUTLS_E_AGAIN; return GNUTLS_E_INTERRUPTED; } else { gnutls_assert (); return GNUTLS_E_PULL_ERROR; } } else { _gnutls_read_log ("READ: Got %d bytes from %p\n", i, fd); if (i == 0) break; /* EOF */ } left -= i; } finish: if (_gnutls_log_level >= 7) { char line[128]; char tmp[16]; _gnutls_read_log ("READ: read %d bytes from %p\n", (sizeOfPtr - left), fd); for (x = 0; x < ((sizeOfPtr - left) / 16) + 1; x++) { line[0] = 0; sprintf (tmp, "%.4x - ", x); _gnutls_str_cat (line, sizeof (line), tmp); for (j = 0; j < 16; j++) { if (sum < (sizeOfPtr - left)) { sprintf (tmp, "%.2x ", ((unsigned char *) ptr)[sum++]); _gnutls_str_cat (line, sizeof (line), tmp); } } _gnutls_read_log ("%s\n", line); } } return (sizeOfPtr - left); }