From: David Woodhouse Date: Fri, 4 Jan 2019 12:24:04 +0000 (+0000) Subject: Split out cancellable recv/send/gets functions from proxy code X-Git-Tag: v8.00~9 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=c2eb86f5c7d10bcfbb028ebe9cbc41e335e6639e;p=users%2Fdwmw2%2Fopenconnect.git Split out cancellable recv/send/gets functions from proxy code Signed-off-by: David Woodhouse --- diff --git a/http.c b/http.c index d1941247..fa3279b1 100644 --- a/http.c +++ b/http.c @@ -1005,101 +1005,17 @@ char *openconnect_create_useragent(const char *base) static int proxy_gets(struct openconnect_info *vpninfo, char *buf, size_t len) { - int i = 0; - int ret; - - if (len < 2) - return -EINVAL; - - while ((ret = proxy_read(vpninfo, (void *)(buf + i), 1)) == 1) { - if (buf[i] == '\n') { - buf[i] = 0; - if (i && buf[i-1] == '\r') { - buf[i-1] = 0; - i--; - } - return i; - } - i++; - - if (i >= len - 1) { - buf[i] = 0; - return i; - } - } - buf[i] = 0; - return i ?: ret; + return cancellable_gets(vpninfo, vpninfo->proxy_fd, buf, len); } static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len) { - size_t count; - int fd = vpninfo->proxy_fd; - - if (fd == -1) - return -EINVAL; - - for (count = 0; count < len; ) { - fd_set rd_set, wr_set; - int maxfd = fd; - int i; - - FD_ZERO(&wr_set); - FD_ZERO(&rd_set); - FD_SET(fd, &wr_set); - cmd_fd_set(vpninfo, &rd_set, &maxfd); - - select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); - if (is_cancel_pending(vpninfo, &rd_set)) - return -EINTR; - - /* Not that this should ever be able to happen... */ - if (!FD_ISSET(fd, &wr_set)) - continue; - - i = send(fd, (void *)&buf[count], len - count, 0); - if (i < 0) - return -errno; - - count += i; - } - return count; + return cancellable_send(vpninfo, vpninfo->proxy_fd, buf, len); } static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len) { - size_t count; - int fd = vpninfo->proxy_fd; - - if (fd == -1) - return -EINVAL; - - for (count = 0; count < len; ) { - fd_set rd_set; - int maxfd = fd; - int i; - - FD_ZERO(&rd_set); - FD_SET(fd, &rd_set); - cmd_fd_set(vpninfo, &rd_set, &maxfd); - - select(maxfd + 1, &rd_set, NULL, NULL, NULL); - if (is_cancel_pending(vpninfo, &rd_set)) - return -EINTR; - - /* Not that this should ever be able to happen... */ - if (!FD_ISSET(fd, &rd_set)) - continue; - - i = recv(fd, (void *)&buf[count], len - count, 0); - if (i < 0) - return -errno; - else if (i == 0) - return -ECONNRESET; - - count += i; - } - return count; + return cancellable_recv(vpninfo, vpninfo->proxy_fd, buf, len); } static const char *socks_errors[] = { diff --git a/openconnect-internal.h b/openconnect-internal.h index e823cd5a..43bbeea0 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -908,7 +908,13 @@ int udp_sockaddr(struct openconnect_info *vpninfo, int port); int udp_connect(struct openconnect_info *vpninfo); int ssl_reconnect(struct openconnect_info *vpninfo); void openconnect_clear_cookies(struct openconnect_info *vpninfo); +int cancellable_gets(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len); +int cancellable_send(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len); +int cancellable_recv(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len); /* openssl-pkcs11.c */ int load_pkcs11_key(struct openconnect_info *vpninfo); int load_pkcs11_certificate(struct openconnect_info *vpninfo); diff --git a/ssl.c b/ssl.c index c3a9a775..6bcb5e0a 100644 --- a/ssl.c +++ b/ssl.c @@ -1038,3 +1038,104 @@ int ssl_reconnect(struct openconnect_info *vpninfo) return 0; } + +int cancellable_gets(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len) +{ + int i = 0; + int ret; + + if (len < 2) + return -EINVAL; + + while ((ret = cancellable_recv(vpninfo, fd, (void *)(buf + i), 1)) == 1) { + if (buf[i] == '\n') { + buf[i] = 0; + if (i && buf[i-1] == '\r') { + buf[i-1] = 0; + i--; + } + return i; + } + i++; + + if (i >= len - 1) { + buf[i] = 0; + return i; + } + } + buf[i] = 0; + return i ?: ret; +} + +int cancellable_send(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len) +{ + size_t count; + + if (fd == -1) + return -EINVAL; + + for (count = 0; count < len; ) { + fd_set rd_set, wr_set; + int maxfd = fd; + int i; + + FD_ZERO(&wr_set); + FD_ZERO(&rd_set); + FD_SET(fd, &wr_set); + cmd_fd_set(vpninfo, &rd_set, &maxfd); + + select(maxfd + 1, &rd_set, &wr_set, NULL, NULL); + if (is_cancel_pending(vpninfo, &rd_set)) + return -EINTR; + + /* Not that this should ever be able to happen... */ + if (!FD_ISSET(fd, &wr_set)) + continue; + + i = send(fd, (void *)&buf[count], len - count, 0); + if (i < 0) + return -errno; + + count += i; + } + return count; +} + + +int cancellable_recv(struct openconnect_info *vpninfo, int fd, + char *buf, size_t len) +{ + size_t count; + + if (fd == -1) + return -EINVAL; + + for (count = 0; count < len; ) { + fd_set rd_set; + int maxfd = fd; + int i; + + FD_ZERO(&rd_set); + FD_SET(fd, &rd_set); + cmd_fd_set(vpninfo, &rd_set, &maxfd); + + select(maxfd + 1, &rd_set, NULL, NULL, NULL); + if (is_cancel_pending(vpninfo, &rd_set)) + return -EINTR; + + /* Not that this should ever be able to happen... */ + if (!FD_ISSET(fd, &rd_set)) + continue; + + i = recv(fd, (void *)&buf[count], len - count, 0); + if (i < 0) + return -errno; + else if (i == 0) + return -ECONNRESET; + + count += i; + } + return count; +}