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); >