int mailstream_wait_idle(mailstream * s, int max_idle_delay) { int fd; int idle_fd; int cancel_fd; int maxfd; fd_set readfds; struct timeval delay; int r; if (s->low->driver == mailstream_cfstream_driver) { return mailstream_cfstream_wait_idle(s, max_idle_delay); } fd = mailstream_low_get_fd(mailstream_get_low(s)); idle_fd = mailstream_cancel_get_fd(s->idle); cancel_fd = mailstream_cancel_get_fd(mailstream_low_get_cancel(mailstream_get_low(s))); FD_ZERO(&readfds); FD_SET(fd, &readfds); FD_SET(idle_fd, &readfds); FD_SET(cancel_fd, &readfds); maxfd = fd; if (idle_fd > maxfd) { maxfd = idle_fd; } if (cancel_fd > maxfd) { maxfd = cancel_fd; } delay.tv_sec = max_idle_delay; delay.tv_usec = 0; r = select(maxfd + 1, &readfds, NULL, NULL, &delay); if (r == 0) { // timeout return MAILSTREAM_IDLE_TIMEOUT; } else if (r == -1) { // do nothing return MAILSTREAM_IDLE_ERROR; } else { if (FD_ISSET(fd, &readfds)) { // has something on socket return MAILSTREAM_IDLE_HASDATA; } if (FD_ISSET(idle_fd, &readfds)) { // idle interrupted mailstream_cancel_ack(s->idle); return MAILSTREAM_IDLE_INTERRUPTED; } if (FD_ISSET(cancel_fd, &readfds)) { // idle cancelled mailstream_cancel_ack(mailstream_low_get_cancel(mailstream_get_low(s))); return MAILSTREAM_IDLE_CANCELLED; } return MAILSTREAM_IDLE_ERROR; } }
static int wait_read(mailstream_low * s) { fd_set fds_read; struct timeval timeout; int fd; struct mailstream_ssl_data * ssl_data; int max_fd; int r; int cancelled; int got_data; #ifdef WIN32 HANDLE event; #endif ssl_data = (struct mailstream_ssl_data *) s->data; timeout = mailstream_network_delay; #ifdef USE_GNUTLS if (gnutls_record_check_pending(ssl_data->session) != 0) return 0; #endif FD_ZERO(&fds_read); fd = mailstream_cancel_get_fd(ssl_data->cancel); FD_SET(fd, &fds_read); #ifdef WIN32 event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (WAIT_TIMEOUT == r) return -1; cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd); got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); #else FD_SET(ssl_data->fd, &fds_read); max_fd = ssl_data->fd; if (fd > max_fd) max_fd = fd; r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout); if (r <= 0) return -1; cancelled = (FD_ISSET(fd, &fds_read)); got_data = FD_ISSET(ssl_data->fd, &fds_read); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } return 0; }
/* mostly copied from mailstream_ssl.c removed their windows support - we only need iOS */ static int wait_write_compress(mailstream_low * s) { fd_set fds_read; fd_set fds_write; struct timeval timeout; int r; int fd; int max_fd; int cancelled; int write_enabled; // use the session timeout if set if (s->timeout) { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } else { timeout = mailstream_network_delay; } FD_ZERO(&fds_read); struct mailstream_cancel * cancel = mailstream_low_compress_get_cancel(s); fd = mailstream_cancel_get_fd(cancel); FD_SET(fd, &fds_read); FD_ZERO(&fds_write); FD_SET(mailstream_low_compress_get_fd(s), &fds_write); max_fd = mailstream_low_compress_get_fd(s); if (fd > max_fd) max_fd = fd; r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(fd, &fds_read); write_enabled = FD_ISSET(mailstream_low_compress_get_fd(s), &fds_write); if (cancelled) { /* cancelled */ mailstream_cancel_ack(cancel); return -1; } if (!write_enabled) return 0; return 1; }
static int wait_write(mailstream_low * s) { fd_set fds_read; fd_set fds_write; struct timeval timeout; int r; int fd; struct mailstream_ssl_data * ssl_data; int max_fd; int cancelled; int write_enabled; #ifdef WIN32 HANDLE event; #endif ssl_data = (struct mailstream_ssl_data *) s->data; if (mailstream_cancel_cancelled(ssl_data->cancel)) return -1; if (s->timeout == 0) { timeout = mailstream_network_delay; } else { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } FD_ZERO(&fds_read); fd = mailstream_cancel_get_fd(ssl_data->cancel); FD_SET(fd, &fds_read); FD_ZERO(&fds_write); #ifdef WIN32 event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (r < 0) { WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); return -1; } cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd) /* SEB 20070709 */; write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); #else FD_SET(ssl_data->fd, &fds_write); max_fd = ssl_data->fd; if (fd > max_fd) max_fd = fd; r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(fd, &fds_read); write_enabled = FD_ISSET(ssl_data->fd, &fds_write); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } if (!write_enabled) return 0; return 1; }
static int wait_write(mailstream_low * s) { struct timeval timeout; int r; int cancellation_fd; struct mailstream_ssl_data * ssl_data; int cancelled; int write_enabled; #if defined(WIN32) fd_set fds_read; fd_set fds_write; HANDLE event; #elif USE_POLL struct pollfd pfd[2]; #else fd_set fds_read; fd_set fds_write; int max_fd; #endif ssl_data = (struct mailstream_ssl_data *) s->data; if (mailstream_cancel_cancelled(ssl_data->cancel)) return -1; if (s->timeout == 0) { timeout = mailstream_network_delay; } else { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel); #if defined(WIN32) FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_SET(cancellation_fd, &fds_read); event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (r < 0) { WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); return -1; } cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd) /* SEB 20070709 */; write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); #elif USE_POLL pfd[0].fd = ssl_data->fd; pfd[0].events = POLLOUT; pfd[0].revents = 0; pfd[1].fd = cancellation_fd; pfd[1].events = POLLIN; pfd[1].revents = 0; r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (r <= 0) return -1; cancelled = pfd[1].revents & POLLIN; write_enabled = pfd[0].revents & POLLOUT; #else FD_ZERO(&fds_read); FD_ZERO(&fds_write); FD_SET(cancellation_fd, &fds_read); FD_SET(ssl_data->fd, &fds_write); max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd; r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(cancellation_fd, &fds_read); write_enabled = FD_ISSET(ssl_data->fd, &fds_write); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } if (!write_enabled) return 0; return 1; }
static int wait_read(mailstream_low * s) { struct timeval timeout; int cancellation_fd; struct mailstream_ssl_data * ssl_data; int r; int cancelled; #if defined(WIN32) fd_set fds_read; HANDLE event; #elif USE_POLL struct pollfd pfd[2]; #else fd_set fds_read; int max_fd; #endif ssl_data = (struct mailstream_ssl_data *) s->data; if (s->timeout == 0) { timeout = mailstream_network_delay; } else { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } #ifdef USE_GNUTLS if (gnutls_record_check_pending(ssl_data->session) != 0) return 0; #endif cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel); #if defined(WIN32) FD_ZERO(&fds_read); FD_SET(cancellation_fd, &fds_read); event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (WAIT_TIMEOUT == r) { WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); return -1; } cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd); WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); #elif USE_POLL pfd[0].fd = ssl_data->fd; pfd[0].events = POLLIN; pfd[0].revents = 0; pfd[1].fd = cancellation_fd; pfd[1].events = POLLIN; pfd[1].revents = 0; r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (r <= 0) return -1; cancelled = pfd[1].revents & POLLIN; #else FD_ZERO(&fds_read); FD_SET(cancellation_fd, &fds_read); FD_SET(ssl_data->fd, &fds_read); max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd; r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(cancellation_fd, &fds_read); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } return 0; }
int mailstream_low_wait_idle(mailstream_low * low, struct mailstream_cancel * idle, int max_idle_delay) { int fd; int idle_fd; int cancel_fd; int maxfd; fd_set readfds; struct timeval delay; int r; if (low->driver == mailstream_cfstream_driver) { return mailstream_low_cfstream_wait_idle(low, max_idle_delay); } else if (low->driver == mailstream_compress_driver) { return mailstream_low_compress_wait_idle(low, idle, max_idle_delay); } if (idle == NULL) { return MAILSTREAM_IDLE_ERROR; } if (mailstream_low_get_cancel(low) == NULL) { return MAILSTREAM_IDLE_ERROR; } fd = mailstream_low_get_fd(low); idle_fd = mailstream_cancel_get_fd(idle); cancel_fd = mailstream_cancel_get_fd(mailstream_low_get_cancel(low)); FD_ZERO(&readfds); #ifdef WIN32 HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(fd, event, FD_READ | FD_CLOSE); FD_SET(event, &readfds); FD_SET(idle_fd, &readfds); FD_SET(cancel_fd, &readfds); r = WaitForMultipleObjects(readfds.fd_count, readfds.fd_array, FALSE, max_idle_delay * 1000); WSAEventSelect(fd, event, 0); CloseHandle(event); if (r == WAIT_TIMEOUT) { return MAILSTREAM_IDLE_TIMEOUT; } else if (r == WAIT_OBJECT_0){ return MAILSTREAM_IDLE_HASDATA; } else if (r == WAIT_OBJECT_0 + 1){ return MAILSTREAM_IDLE_INTERRUPTED; } else if (r == WAIT_OBJECT_0 + 2){ return MAILSTREAM_IDLE_CANCELLED; } DWORD i = GetLastError(); return MAILSTREAM_IDLE_ERROR; #else FD_SET(fd, &readfds); FD_SET(idle_fd, &readfds); FD_SET(cancel_fd, &readfds); maxfd = fd; if (idle_fd > maxfd) { maxfd = idle_fd; } if (cancel_fd > maxfd) { maxfd = cancel_fd; } delay.tv_sec = max_idle_delay; delay.tv_usec = 0; r = select(maxfd + 1, &readfds, NULL, NULL, &delay); if (r == 0) { // timeout return MAILSTREAM_IDLE_TIMEOUT; } else if (r == -1) { // do nothing return MAILSTREAM_IDLE_ERROR; } else { if (FD_ISSET(fd, &readfds)) { // has something on socket return MAILSTREAM_IDLE_HASDATA; } if (FD_ISSET(idle_fd, &readfds)) { // idle interrupted mailstream_cancel_ack(idle); return MAILSTREAM_IDLE_INTERRUPTED; } if (FD_ISSET(cancel_fd, &readfds)) { // idle cancelled mailstream_cancel_ack(mailstream_low_get_cancel(low)); return MAILSTREAM_IDLE_CANCELLED; } return MAILSTREAM_IDLE_ERROR; } #endif }
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; if (mailstream_cancel_cancelled(socket_data->cancel)) return -1; /* timeout */ { fd_set fds_read; struct timeval timeout; int r; int fd; int cancelled; int got_data; #ifdef WIN32 HANDLE event; #else int max_fd; #endif if (s->timeout == 0) { timeout = mailstream_network_delay; } else { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } FD_ZERO(&fds_read); fd = mailstream_cancel_get_fd(socket_data->cancel); FD_SET(fd, &fds_read); #ifdef WIN32 event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(socket_data->fd, event, FD_READ | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (WAIT_TIMEOUT == r) { WSAEventSelect(socket_data->fd, event, 0); CloseHandle(event); return -1; } cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd); got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); WSAEventSelect(socket_data->fd, event, 0); CloseHandle(event); #else FD_SET(socket_data->fd, &fds_read); max_fd = socket_data->fd; if (fd > max_fd) max_fd = fd; r = select(max_fd + 1, &fds_read, NULL,/* &fds_excp*/ NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(fd, &fds_read); got_data = FD_ISSET(socket_data->fd, &fds_read); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(socket_data->cancel); return -1; } if (!got_data) return 0; } if (socket_data->use_read) { return read(socket_data->fd, buf, count); } else { return recv(socket_data->fd, buf, count, 0); } }