@@ -1,7 +1,7 @@
/* $OpenBSD: server_http.c,v 1.111 2017/01/31 12:21:27 reyk Exp $ */
/* $OpenBSD: server_http.c,v 1.112 2017/01/31 14:39:47 reyk Exp $ */
/*
* Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2006 - 2017 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -609,6 +609,101 @@ server_read_httpchunks(struct bufferevent *bev, void *arg)
server_close (clt, strerror (errno));
}
void
server_read_httprange (struct bufferevent *bev, void *arg)
{
struct client *clt = arg;
struct evbuffer *src = EVBUFFER_INPUT (bev);
size_t size;
struct media_type *media;
struct range_data *r = &clt->clt_ranges ;
struct range *range;
getmonotime (&clt->clt_tv_last );
if (r->range_toread > 0 ) {
size = EVBUFFER_LENGTH (src);
if (!size)
return ;
/* Read chunk data */
if ((off_t )size > r->range_toread ) {
size = r->range_toread ;
if (server_bufferevent_write_chunk (clt, src, size)
== -1 )
goto fail;
r->range_toread = 0 ;
} else {
if (server_bufferevent_write_buffer (clt, src) == -1 )
goto fail;
r->range_toread -= size;
}
if (r->range_toread < 1 )
r->range_toread = TOREAD_HTTP_RANGE;
DPRINTF (" %s : done, size %lu , to read %lld " , __func__,
size, r->range_toread );
}
switch (r->range_toread ) {
case TOREAD_HTTP_RANGE:
if (r->range_index >= r->range_count ) {
if (r->range_count > 1 ) {
/* Add end marker */
if (server_bufferevent_printf (clt,
" \r\n --%llu --\r\n " ,
clt->clt_boundary ) == -1 )
goto fail;
}
r->range_toread = TOREAD_HTTP_NONE;
break ;
}
range = &r->range [r->range_index ];
if (r->range_count > 1 ) {
media = r->range_media ;
if (server_bufferevent_printf (clt,
" \r\n --%llu \r\n "
" Content-Type: %s /%s \r\n "
" Content-Range: bytes %lld -%lld /%zu \r\n\r\n " ,
clt->clt_boundary ,
media->media_type , media->media_subtype ,
range->start , range->end , r->range_total ) == -1 )
goto fail;
}
r->range_toread = range->end - range->start + 1 ;
if (lseek (clt->clt_fd , range->start , SEEK_SET) == -1 )
goto fail;
/* Throw away bytes that are already in the input buffer */
evbuffer_drain (src, EVBUFFER_LENGTH (src));
/* Increment for the next part */
r->range_index ++;
break ;
case TOREAD_HTTP_NONE:
case 0 :
break ;
}
if (clt->clt_done )
goto done;
if (EVBUFFER_LENGTH (EVBUFFER_OUTPUT (clt->clt_bev )) > (size_t )
SERVER_MAX_PREFETCH * clt->clt_sndbufsiz ) {
bufferevent_disable (clt->clt_srvbev , EV_READ);
clt->clt_srvbev_throttled = 1 ;
}
return ;
done:
(*bev->errorcb )(bev, EVBUFFER_READ, bev->cbarg );
return ;
fail:
server_close (clt, strerror (errno));
}
void
server_reset_http (struct client *clt)
{