summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-08-21 20:05:46 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-08-21 20:05:46 +0300
commit5ac3e04ec5ad33e1bbc6ac2334f5990ef12f2bd3 (patch)
tree9e3eb63a6b82e74e2bacb3c975e7ee0d724d5398
parent12c4d5dc022dea90299659fcc0541f8e9c317d56 (diff)
downloadmailutils-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.c48
-rw-r--r--imap4d/imap4d.c2
-rw-r--r--imap4d/imap4d.h1
-rw-r--r--imap4d/io.c100
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);

Return to:

Send suggestions and report system problems to the System administrator.