Claudio Jeker(cje...@diehard.n-r-g.com) on 2022.09.02 19:55:28 +0200:
> We want to be able to abort RRDP syncs. Now the problem is that depending
> on the state the abort request is more or less complex. What needs to be
> avoided is that a message received after the corresponding RRDP session
> was removed. This is mainly the RRDP_FILE and RRDP_HTTP_FIN messages that
> cause this.
> 
> So once a RRDP_HTTP_INI message was received the abort code goes through
> most states, it just aborts the internal XML parser and closes the input
> fd.

ok.

> -- 
> :wq Claudio
> 
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.151
> diff -u -p -r1.151 extern.h
> --- extern.h  30 Aug 2022 18:56:49 -0000      1.151
> +++ extern.h  2 Sep 2022 17:41:07 -0000
> @@ -408,6 +408,7 @@ enum rrdp_msg {
>       RRDP_HTTP_REQ,
>       RRDP_HTTP_INI,
>       RRDP_HTTP_FIN,
> +     RRDP_ABORT,
>  };
>  
>  /*
> Index: rrdp.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rrdp.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 rrdp.c
> --- rrdp.c    15 May 2022 16:43:35 -0000      1.24
> +++ rrdp.c    2 Sep 2022 17:54:58 -0000
> @@ -57,6 +57,7 @@ struct rrdp {
>       struct pollfd           *pfd;
>       int                      infd;
>       int                      state;
> +     int                      aborted;
>       unsigned int             file_pending;
>       unsigned int             file_failed;
>       enum http_result         res;
> @@ -73,7 +74,7 @@ struct rrdp {
>       struct delta_xml        *dxml;
>  };
>  
> -TAILQ_HEAD(, rrdp)   states = TAILQ_HEAD_INITIALIZER(states);
> +static TAILQ_HEAD(, rrdp)    states = TAILQ_HEAD_INITIALIZER(states);
>  
>  char *
>  xstrdup(const char *s)
> @@ -256,7 +257,7 @@ rrdp_failed(struct rrdp *s)
>       /* reset file state before retrying */
>       s->file_failed = 0;
>  
> -     if (s->task == DELTA) {
> +     if (s->task == DELTA && !s->aborted) {
>               /* fallback to a snapshot as per RFC8182 */
>               free_delta_xml(s->dxml);
>               s->dxml = NULL;
> @@ -289,7 +290,7 @@ rrdp_finished(struct rrdp *s)
>       if (s->file_pending > 0)
>               return;
>  
> -     if (s->state & RRDP_STATE_PARSE_ERROR) {
> +     if (s->state & RRDP_STATE_PARSE_ERROR || s->aborted) {
>               rrdp_failed(s);
>               return;
>       }
> @@ -372,6 +373,34 @@ rrdp_finished(struct rrdp *s)
>  }
>  
>  static void
> +rrdp_abort_req(struct rrdp *s)
> +{
> +     unsigned int id = s->id;
> +
> +     s->aborted = 1;
> +     if (s->state == RRDP_STATE_REQ) {
> +             /* nothing is pending, just abort */
> +             rrdp_free(s);
> +             rrdp_done(id, 1);
> +             return;
> +     }
> +     if (s->state == RRDP_STATE_WAIT)
> +             /* wait for HTTP_INI which will progress the state */
> +             return;
> +
> +     /*
> +      * RRDP_STATE_PARSE or later, close infd, abort parser but
> +      * wait for HTTP_FIN and file_pending to drop to 0.
> +      */
> +     if (s->infd != -1) {
> +             close(s->infd);
> +             s->infd = -1;
> +             s->state |= RRDP_STATE_PARSE_DONE | RRDP_STATE_PARSE_ERROR;
> +     }
> +     rrdp_finished(s);
> +}
> +
> +static void
>  rrdp_input_handler(int fd)
>  {
>       static struct ibuf *inbuf;
> @@ -408,12 +437,15 @@ rrdp_input_handler(int fd)
>                       errx(1, "expected fd not received");
>               s = rrdp_get(id);
>               if (s == NULL)
> -                     errx(1, "rrdp session %u does not exist", id);
> +                     errx(1, "http ini, rrdp session %u does not exist", id);
>               if (s->state != RRDP_STATE_WAIT)
>                       errx(1, "%s: bad internal state", s->local);
> -
>               s->infd = b->fd;
>               s->state = RRDP_STATE_PARSE;
> +             if (s->aborted) {
> +                     rrdp_abort_req(s);
> +                     break;
> +             }
>               break;
>       case RRDP_HTTP_FIN:
>               io_read_buf(b, &res, sizeof(res));
> @@ -423,20 +455,19 @@ rrdp_input_handler(int fd)
>  
>               s = rrdp_get(id);
>               if (s == NULL)
> -                     errx(1, "rrdp session %u does not exist", id);
> +                     errx(1, "http fin, rrdp session %u does not exist", id);
>               if (!(s->state & RRDP_STATE_PARSE))
>                       errx(1, "%s: bad internal state", s->local);
> -
> +             s->state |= RRDP_STATE_HTTP_DONE;
>               s->res = res;
>               free(s->last_mod);
>               s->last_mod = last_mod;
> -             s->state |= RRDP_STATE_HTTP_DONE;
>               rrdp_finished(s);
>               break;
>       case RRDP_FILE:
>               s = rrdp_get(id);
>               if (s == NULL)
> -                     errx(1, "rrdp session %u does not exist", id);
> +                     errx(1, "file, rrdp session %u does not exist", id);;
>               if (b->fd != -1)
>                       errx(1, "received unexpected fd");
>               io_read_buf(b, &ok, sizeof(ok));
> @@ -445,6 +476,13 @@ rrdp_input_handler(int fd)
>               s->file_pending--;
>               if (s->file_pending == 0)
>                       rrdp_finished(s);
> +             break;
> +     case RRDP_ABORT:
> +             if (b->fd != -1)
> +                     errx(1, "received unexpected fd");
> +             s = rrdp_get(id);
> +             if (s != NULL)
> +                     rrdp_abort_req(s);
>               break;
>       default:
>               errx(1, "unexpected message %d", type);
> 

Reply via email to