On Thu, Apr 08, 2021 at 07:18:39PM +0200, Claudio Jeker wrote:
> On Thu, Apr 08, 2021 at 06:22:16PM +0200, Theo Buehler wrote:
> > On Thu, Apr 08, 2021 at 04:47:15PM +0200, Claudio Jeker wrote:
> > > This diff is a first step in tightening the code in http.c
> > > It should cleanup the poll handling and make adds some code to ensure that
> > > only expected results are returned. The goal is that http_handle() only
> > > does IO processing and http_nextstep() is used for transitions into new
> > > states.
> > 
> > I like this direction.
> > 
> > > I did shuffle the code around a bit. So that similar functions are 
> > > together.
> > > Also by shuffling the poll loop now connections are added after the all
> > > active connections have been processed.
> > 
> > This added quite a bit of noise to the diff (especially some parts
> > shuffling _write() functions are hard to read).
> > 
> > I'm ok with this, one small comment below.
> > 
> 
> Sorry about that. I committed the deck chair shuffle and some other minor
> bits. Here is the part that replaces the regular and chunked write
> functions with a single data_write one.
> 
> I made the strtoul() check look like the man page example to detect
> overflows. There is some off_t vs size_t casts required but in that case
> the size limited bufpos is casted.


> On Thu, Apr 08, 2021 at 06:22:16PM +0200, Theo Buehler wrote:
> > On Thu, Apr 08, 2021 at 04:47:15PM +0200, Claudio Jeker wrote:
> > > This diff is a first step in tightening the code in http.c
> > > It should cleanup the poll handling and make adds some code to ensure that
> > > only expected results are returned. The goal is that http_handle() only
> > > does IO processing and http_nextstep() is used for transitions into new
> > > states.
> > 
> > I like this direction.
> > 
> > > I did shuffle the code around a bit. So that similar functions are 
> > > together.
> > > Also by shuffling the poll loop now connections are added after the all
> > > active connections have been processed.
> > 
> > This added quite a bit of noise to the diff (especially some parts
> > shuffling _write() functions are hard to read).
> > 
> > I'm ok with this, one small comment below.
> > 
> 
> Sorry about that. I committed the deck chair shuffle and some other minor
> bits. Here is the part that replaces the regular and chunked write
> functions with a single data_write one.
> 
> I made the strtoul() check look like the man page example to detect
> overflows. There is some off_t vs size_t casts required but in that case
> the size limited bufpos is casted.

Thanks. Still looks good. Tiny suggestion below, but ok either way.

> 
> -- 
> :wq Claudio
> 
> Index: http.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 http.c
> --- http.c    8 Apr 2021 16:56:34 -0000       1.24
> +++ http.c    8 Apr 2021 17:12:49 -0000
> @@ -107,9 +107,7 @@ struct http_connection {
>       size_t          bufsz;
>       size_t          bufpos;
>       size_t          id;
> -     size_t          chunksz;
> -     off_t           filesize;
> -     off_t           bytes;
> +     off_t           iosz;
>       int             status;
>       int             redirect_loop;
>       int             fd;
> @@ -727,10 +725,10 @@ http_parse_header(struct http_connection
>               cp += sizeof(CONTENTLEN) - 1;
>               if ((s = strcspn(cp, " \t")) != 0)
>                       *(cp+s) = 0;
> -             conn->filesize = strtonum(cp, 0, LLONG_MAX, &errstr);
> +             conn->iosz = strtonum(cp, 0, LLONG_MAX, &errstr);
>               if (errstr != NULL) {
> -                     warnx("Improper response from %s",
> -                         http_info(conn->url));
> +                     warnx("Content-Length of %s is %s",
> +                         http_info(conn->url), errstr);
>                       return -1;
>               }
>       } else if (http_isredirect(conn) &&
> @@ -820,7 +818,7 @@ http_parse_chunked(struct http_connectio
>  {
>       char *header = buf;
>       char *end;
> -     int chunksize;
> +     unsigned long chunksize;
>  
>       /* ignore empty lines, used between chunk and next header */
>       if (*header == '\0')
> @@ -830,14 +828,14 @@ http_parse_chunked(struct http_connectio
>       header[strcspn(header, ";\r\n")] = '\0';
>       errno = 0;
>       chunksize = strtoul(header, &end, 16);
> -     if (errno != 0 || header[0] == '\0' || *end != '\0' ||
> -         chunksize > INT_MAX) {
> +     if (header[0] == '\0' || *end != '\0' || (errno == ERANGE &&
> +         chunksize == ULONG_MAX) || chunksize > INT_MAX) {
>               warnx("%s: Invalid chunk size", http_info(conn->url));
>               return -1;
>       }
> -     conn->chunksz = chunksize;
> +     conn->iosz = chunksize;
>  
> -     if (conn->chunksz == 0) {
> +     if (conn->iosz == 0) {
>               http_done(conn, HTTP_OK);
>               return 0;
>       }
> @@ -895,11 +893,11 @@ http_read(struct http_connection *conn)
>               return WANT_POLLIN;
>       case STATE_RESPONSE_DATA:
>               if (conn->bufpos == conn->bufsz ||
> -                 conn->filesize - conn->bytes <= (off_t)conn->bufpos)
> +                 conn->iosz <= (off_t)conn->bufpos)
>                       return 0;
>               return WANT_POLLIN;
>       case STATE_RESPONSE_CHUNKED:
> -             while (conn->chunksz == 0) {
> +             while (conn->iosz == 0) {
>                       buf = http_get_line(conn);
>                       if (buf == NULL)
>                               return WANT_POLLIN;
> @@ -915,7 +913,7 @@ http_read(struct http_connection *conn)
>               }
>  
>               if (conn->bufpos == conn->bufsz ||
> -                 conn->chunksz <= conn->bufpos)
> +                 conn->iosz <= (off_t)conn->bufpos)
>                       return 0;
>               return WANT_POLLIN;
>       default:
> @@ -970,53 +968,30 @@ data_write(struct http_connection *conn)
>       ssize_t s;
>       size_t bsz = conn->bufpos;
>  
> -     if (conn->filesize - conn->bytes < (off_t)bsz)
> -             bsz = conn->filesize - conn->bytes;
> +     if (conn->iosz < (off_t)bsz)
> +             bsz = conn->iosz;
>  
>       s = write(conn->outfd, conn->buf, bsz);
>       if (s == -1) {
> -             warn("%s: Data write", http_info(conn->url));
> +             warn("%s: data write", http_info(conn->url));
>               return -1;
>       }
>  
>       conn->bufpos -= s;
> -     conn->bytes += s;
> +     conn->iosz -= s;
>       memmove(conn->buf, conn->buf + s, conn->bufpos);
>  
> -     if (conn->bytes == conn->filesize) {
> +     /* check if regular file transfer is finished */
> +     if (conn->iosz == 0 && conn->chunked == 0) {

I would treat chunked as a Boolean (as is done elsewhere) and perhaps
switch the logic around (matches the comment better):

        if (!conn->chunked && conn->iosz == 0) {

>               http_done(conn, HTTP_OK);
>               return 0;
>       }
>  
> -     if (conn->bufpos == 0)
> -             return 0;
> -
> -     return WANT_POLLOUT;
> -}
> -
> -static int
> -chunk_write(struct http_connection *conn)
> -{
> -     ssize_t s;
> -     size_t bsz = conn->bufpos;
> -
> -     if (bsz > conn->chunksz)
> -             bsz = conn->chunksz;
> -
> -     s = write(conn->outfd, conn->buf, bsz);
> -     if (s == -1) {
> -             warn("%s: Chunk write", http_info(conn->url));
> -             return -1;
> -     }
> -
> -     conn->bufpos -= s;
> -     conn->chunksz -= s;
> -     conn->bytes += s;
> -     memmove(conn->buf, conn->buf + s, conn->bufpos);
> -
> -     if (conn->bufpos == 0 || conn->chunksz == 0)
> +     /* all data written, switch back to read */
> +     if (conn->bufpos == 0 || conn->iosz == 0)
>               return 0;
>  
> +     /* still more data to write in buffer */
>       return WANT_POLLOUT;
>  }
>  
> @@ -1041,10 +1016,7 @@ http_handle(struct http_connection *conn
>       case STATE_RESPONSE_CHUNKED:
>               return http_read(conn);
>       case STATE_WRITE_DATA:
> -             if (conn->chunked)
> -                     return chunk_write(conn);
> -             else
> -                     return data_write(conn);
> +             return data_write(conn);
>       case STATE_DONE:
>               return http_close(conn);
>       case STATE_FREE:

Reply via email to