diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-08-21 20:05:46 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-08-21 20:05:46 +0300 |
commit | 5ac3e04ec5ad33e1bbc6ac2334f5990ef12f2bd3 (patch) | |
tree | 9e3eb63a6b82e74e2bacb3c975e7ee0d724d5398 | |
parent | 12c4d5dc022dea90299659fcc0541f8e9c317d56 (diff) | |
download | mailutils-5ac3e04ec5ad33e1bbc6ac2334f5990ef12f2bd3.tar.gz mailutils-5ac3e04ec5ad33e1bbc6ac2334f5990ef12f2bd3.tar.bz2 |
imap4d: switch to timed stream I/O
* imap4d/idle.c (imap4d_idle): Use mu_stream_timed_getline.
* imap4d/imap4d.c (imap4d_mainloop): Remove use of io_wait_input.
* imap4d/imap4d.h (io_wait_input): Remove.
* imap4d/io.c (io_wait_input): Remove.
(io_getline): Rewrite using mu_stream_timed_getline.
(imap4d_tokbuf_getline): Likewise.
(check_input_err): Handle MU_ERR_TIMEOUT.
-rw-r--r-- | imap4d/idle.c | 48 | ||||
-rw-r--r-- | imap4d/imap4d.c | 2 | ||||
-rw-r--r-- | imap4d/imap4d.h | 1 | ||||
-rw-r--r-- | imap4d/io.c | 100 |
4 files changed, 102 insertions, 49 deletions
diff --git a/imap4d/idle.c b/imap4d/idle.c index 30d937977..69514004c 100644 --- a/imap4d/idle.c +++ b/imap4d/idle.c @@ -20,30 +20,60 @@ int imap4d_idle (struct imap4d_session *session, struct imap4d_command *command, imap4d_tokbuf_t tok) { - time_t start; + struct timeval stop_time, tv, *to; char *token_str = NULL; size_t token_size = 0, token_len; if (imap4d_tokbuf_argc (tok) != 2) return io_completion_response (command, RESP_BAD, "Invalid arguments"); - if (io_wait_input (0) == -1) + if (mu_stream_ioctl (iostream, MU_IOCTL_TIMEOUT, MU_IOCTL_OP_GET, &tv)) return io_completion_response (command, RESP_NO, "Cannot idle"); io_sendf ("+ idling\n"); io_flush (); - start = time (NULL); + if (idle_timeout) + { + gettimeofday (&stop_time, NULL); + stop_time.tv_sec += idle_timeout; + to = &tv; + } + else + to = NULL; + while (1) { - if (io_wait_input (5)) + int rc; + + if (to) + { + struct timeval d; + + gettimeofday (&d, NULL); + if (mu_timeval_cmp (&d, &stop_time) >= 0) + { + imap4d_bye (ERR_TIMEOUT); + } + *to = mu_timeval_sub (&stop_time, &d); + } + + rc = mu_stream_timed_getline (iostream, &token_str, &token_size, + to, &token_len); + if (rc == MU_ERR_TIMEOUT) + { + imap4d_bye (ERR_TIMEOUT); + } + else if (rc) { - io_getline (&token_str, &token_size, &token_len); - if (token_len == 4 && mu_c_strcasecmp (token_str, "done") == 0) - break; + mu_error (_("read error: %s"), mu_strerror (rc)); + imap4d_bye (ERR_NO_IFILE); } - else if (time (NULL) - start > idle_timeout) - imap4d_bye (ERR_TIMEOUT); + + token_len = mu_rtrim_class (token_str, MU_CTYPE_ENDLN); + + if (token_len == 4 && mu_c_strcasecmp (token_str, "done") == 0) + break; imap4d_sync (); io_flush (); diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c index 1d9b15c58..7fbdf4a19 100644 --- a/imap4d/imap4d.c +++ b/imap4d/imap4d.c @@ -810,8 +810,6 @@ imap4d_mainloop (int ifd, int ofd, struct imap4d_srv_config *cfg) tokp = imap4d_tokbuf_init (); while (1) { - if (idle_timeout && io_wait_input (idle_timeout) != 1) - imap4d_bye (ERR_TIMEOUT); imap4d_readline (tokp); /* check for updates */ imap4d_sync (); diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h index b61fa09bb..9dcbfe175 100644 --- a/imap4d/imap4d.h +++ b/imap4d/imap4d.h @@ -249,7 +249,6 @@ extern int io_stream_completion_response (mu_stream_t str, void io_getline (char **pbuf, size_t *psize, size_t *pnbytes); void io_setio (int, int, struct mu_tls_config *); void io_flush (void); -int io_wait_input (int); void io_enable_crlf (int); imap4d_tokbuf_t imap4d_tokbuf_init (void); diff --git a/imap4d/io.c b/imap4d/io.c index 04c1702c6..83375540c 100644 --- a/imap4d/io.c +++ b/imap4d/io.c @@ -16,6 +16,7 @@ #include "imap4d.h" #include <mailutils/property.h> +#include <mailutils/datetime.h> mu_stream_t iostream; @@ -374,29 +375,6 @@ io_stream_completion_response (mu_stream_t str, return status; } -/* Wait TIMEOUT seconds for data on the input stream. - Returns 0 if no data available - 1 if some data is available - -1 an error occurred */ -int -io_wait_input (int timeout) -{ - int wflags = MU_STREAM_READY_RD; - struct timeval tv; - int status; - - tv.tv_sec = timeout; - tv.tv_usec = 0; - status = mu_stream_wait (iostream, &wflags, &tv); - if (status) - { - mu_diag_output (MU_DIAG_ERROR, _("cannot poll input stream: %s"), - mu_strerror(status)); - return -1; - } - return wflags & MU_STREAM_READY_RD; -} - void io_flush () { @@ -407,7 +385,19 @@ void io_getline (char **pbuf, size_t *psize, size_t *pnbytes) { size_t len; - int rc = mu_stream_getline (iostream, pbuf, psize, &len); + int rc; + struct timeval tv, *to; + + if (idle_timeout) + { + tv.tv_sec = idle_timeout; + tv.tv_usec = 0; + to = &tv; + } + else + to = NULL; + + rc = mu_stream_timed_getline (iostream, pbuf, psize, to, &len); if (rc == 0) { char *s = *pbuf; @@ -421,6 +411,8 @@ io_getline (char **pbuf, size_t *psize, size_t *pnbytes) if (pnbytes) *pnbytes = len; } + else if (rc == MU_ERR_TIMEOUT) + imap4d_bye (ERR_TIMEOUT); else { mu_error (_("read error: %s"), mu_strerror (rc)); @@ -625,20 +617,30 @@ imap4d_tokbuf_tokenize (struct imap4d_tokbuf *tok, size_t off) static void check_input_err (int rc, size_t sz) { - if (rc) + switch (rc) { - const char *p = mu_stream_strerror (iostream, rc); - if (!p) - p = mu_strerror (rc); + case 0: + if (sz == 0) + { + mu_diag_output (MU_DIAG_INFO, _("unexpected eof on input")); + imap4d_bye (ERR_NO_IFILE); + } + break; - mu_diag_output (MU_DIAG_INFO, - _("error reading from input file: %s"), p); - imap4d_bye (ERR_NO_IFILE); - } - else if (sz == 0) - { - mu_diag_output (MU_DIAG_INFO, _("unexpected eof on input")); - imap4d_bye (ERR_NO_IFILE); + case MU_ERR_TIMEOUT: + imap4d_bye (ERR_TIMEOUT); + break; + + default: + { + const char *p = mu_stream_strerror (iostream, rc); + if (!p) + p = mu_strerror (rc); + + mu_diag_output (MU_DIAG_INFO, + _("error reading from input file: %s"), p); + imap4d_bye (ERR_NO_IFILE); + } } } @@ -647,13 +649,37 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok) { char buffer[512]; size_t level = tok->level; + struct timeval tv, *to, stop_time; + + if (idle_timeout) + { + gettimeofday (&stop_time, NULL); + stop_time.tv_sec += idle_timeout; + to = &tv; + } + else + to = NULL; do { size_t len; int rc; + + if (to) + { + struct timeval d; + + gettimeofday (&d, NULL); + if (mu_timeval_cmp (&d, &stop_time) >= 0) + { + rc = MU_ERR_TIMEOUT; + break; + } + *to = mu_timeval_sub (&stop_time, &d); + } - rc = mu_stream_readline (iostream, buffer, sizeof (buffer), &len); + rc = mu_stream_timed_readline (iostream, buffer, sizeof (buffer), + to, &len); check_input_err (rc, len); imap4d_tokbuf_expand (tok, len); |