I was building range code to support streaming from VLC player and it does wirk. Also i have this code running on out public site and i see
many range requests coming with asking partial contents so it is working in real life. The implementation is not complete but i've never seen in the logs multiple ranges. So for fastpath it looks working forme even in this form.
The funny thins that VLc does not handle range replies tself so this code did not help me with streaming.
Of course we can remove it but i think this is too conservative, without having it in the code there is notway to check how it works and have experience with it to complete it. Having this code in separate patches is not going to work, i use only CVS now and have no desire to have separate copies of the code. If this is just for release why it would harm it? It does no harm and handle subset of range requests pretty well.
It needs improvements i agree.
i am on vaca!
tion this week so you all decide without waiting for me.
-------- Original Message --------
To: naviserver-devel@lists.sourceforge.net
From: Stephen Deasey
Subject: [naviserver-devel] Range requests
It doesn't make sense for the client to ask for a certain byte range
unless it already has the other bytes. It needs to make sure that
it's not asking for the tail of a file which has changed in the
server.
The code doesn't handle If-Range. If-Modified-Since is handled in the
existing code and returns early before the range code runs. I don't
see how this range implementation could work in the real world.
There's no tests for any of this.
Maybe a better way to handle multiple ranges is by using an iovec
struct. We can pass the result directly to Ns_ConnSend() or something
similar.
The range code only handles fastpath requests, bu!
t it should probably
also handle stuff like ns_returnfp/ns_respond. I don't see any reason
why it shouldn't also handle the fastpath cache.
The handling of response codes looks a little hairy. How about if
ParseRange just returned the correct response code? All error
checking should be moved inside that function. At the moment
ParseRange handles some errors, the calling code others, which is
tricky to follow. Also, it's extremely difficult to figure out what
the parsing code is doing.
AOLserver 4.5 has support for chunked responses. We should probably
check to see how that might impact things.
I'm wondering if the best way forward is to back out the range code,
make a quick release, then add it back for the next one along with the
TclVFS stuff, file upload improvements, and hopefully my mythical
caching changes, all of which are pretty in!
vasive and potentially
destabilizing. What does everyone think?
On 6/29/05, Vlad Seryakov wrote:
> Update of /cvsroot/naviserver/naviserver/nsd
> In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4535/nsd
>
> Modified Files:
> fastpath.c
> Log Message:
> see ChangeLog
>
>
> Index: fastpath.c
> ===================================================================
> RCS file: /cvsroot/naviserver/naviserver/nsd/fastpath.c,v
> retrieving revision 1.9
> retrieving revision 1.10
> diff -C2 -d -r1.9 -r1.10
> *** fastpath.c 29 Jun 2005 23:27:50 -0000 1.9
> --- fastpath.c 30 Jun 2005 01:14:02 -0000 1.10
> ***************
> *** 39,42 ****
> --- 39,44 ----
> NS_RCSID("@(#) $Header$");
>
> + #define MA!
X_RANGES 10
> +
> /*
> * The following structure defines the contents of a file
> ***************
> *** 61,66 ****
> static int FastReturn(NsServer *servPtr, Ns_Conn *conn, int status,
> char *type, char *file, struct stat *stPtr);
> ! static int ParseRange(Ns_Conn *conn, unsigned long size,
> ! unsigned long *offset1, unsigned long *offset2);
>
> /*
> --- 63,68 ----
> static int FastReturn(NsServer *servPtr, Ns_Conn *conn, int status,
> char *type, char *file, struct stat *stPtr);
> ! static int ParseRange(Ns_Conn *conn, unsigned long size, unsigned long
*offsets,
> ! int offsets_size);
>
> /*
> ***************
> *** 474,479 ****
> {
> int fd, new, nread; > ! unsigned long size, offset1, offset2;
> ! int result = NS_ERROR, range = NS_ERROR;
> char *key;
> Ns_Entry *entPtr;
> --- 476,481 ----
> {
> int fd, new, nread;
> ! unsigned long size, offsets[MAX_RANGES*2];
> ! int result = NS_ERROR, ranges = 0;
> char *key;
> Ns_Entry *entPtr;
> ***************
> *** 520,537 ****
> size = stPtr->st_size;
> if (status == 200) {
> ! range = ParseRange(conn, stPtr->st_size, &offset1,
> }
> ! if (range != NS_ERROR) {
> ! if (offset1 > offset2) {
> ! /* 416 Requested Range Not Satisfiable */
> ! Ns_ConnPrintfHeaders(conn, "Content-Range", "bytes */%lu",
> ! stPtr->st_size);!
> ! Ns_ConnSetRequiredHeaders(conn, type, (int) stPtr->st_size);
> ! return Ns_ConnFlushHeaders(conn, 416);
> ! }
> /* Continue with returning a portion of the file */
> Ns_ConnPrintfHeaders(conn, "Content-Range", "bytes %lu-%lu/%lu",
> ! offset1, offset2, stPtr->st_size);
> ! size = (offset2 - offset1) + 1;
> /* 206 Partial Content */
> status = 206;
> --- 522,539 ----
> size = stPtr->st_size;
> if (status == 200) {
> ! ranges = ParseRange(conn, stPtr->st_size, offsets, MAX_RANGES*2);
> }
> ! if (ranges == -1) {
> ! /* 416 Requested Range Not Satisfiable */
> ! Ns_ConnPrintfHeaders(conn, "Content-Range", "bytes */%lu",!
> ! stPtr->st_size);
> ! Ns_ConnSetRequiredHeaders(conn, type, (int) stPtr->st_size);
> ! return Ns_ConnFlushHeaders(conn, 416);
> ! }
> ! if (ranges == 1) {
> /* Continue with returning a portion of the file */
> Ns_ConnPrintfHeaders(conn, "Content-Range", "bytes %lu-%lu/%lu",
> ! offsets[0], offsets[1], stPtr->st_size);
> ! size = (offsets[1] - offsets[0]) + 1;
> /* 206 Partial Content */
> status = 206;
> ***************
> *** 540,544 ****
> if (servPtr->fastpath.cache == NULL
> || stPtr->st_size > servPtr->fastpath.cachemaxentry
> ! || range == NS_OK) {
>
> /*
> --- 542,546 ----
> if (s!
ervPtr->fastpath.cache == NULL
> || stPtr->st_size > servPtr->fastpath.cachemaxentry
> ! || ranges == 1) {
>
> /*
> ***************
> *** 552,557 ****
> && NsMemMap(file, stPtr->st_size, NS_MMAP_READ, &fmap) == NS_OK)
{
> char *maddr = fmap.addr;
> ! if (range == NS_OK) {
> ! maddr += offset1;
> }
> result = Ns_ConnReturnData(conn,status, maddr, size, type);
> --- 554,559 ----
> && NsMemMap(file, stPtr->st_size, NS_MMAP_READ, &fmap) == NS_OK)
{
> char *maddr = fmap.addr;
> ! if (ranges > 0) {
> ! maddr += offsets[0];
> }
> result = Ns_ConnReturnData(conn,stat!
us, maddr, size, type);
> ***************
> *** 564,569 ****
> goto notfound;
> }
> ! if (range == NS_OK) {
> ! lseek(fd, offset1, SEEK_SET);
> }
> result = Ns_ConnReturnOpenFd(conn, status, type, fd, size);
> --- 566,571 ----
> goto notfound;
> }
> ! if (ranges > 0) {
> ! lseek(fd, offsets[0], SEEK_SET);
> }
> result = Ns_ConnReturnOpenFd(conn, status, type, fd, size);
> ***************
> *** 690,694 ****
> *
> * Results:
> ! * NS_OK or NS_ERROR
> *
> * Side effects:
> --- 692,696 ----
> *
> * Results:
> ! * -1 on error, number of byte ran!
ges parsed
> *
> * Side effects:
> ***************
> *** 699,755 ****
>
> static int
> ! ParseRange(Ns_Conn *conn, unsigned long size,
> ! unsigned long *offset1, unsigned long *offset2)
> {
> char *range;
>
> ! *offset1 = *offset2 = 0;
>
> ! if ((range = Ns_SetIGet(conn->headers, "Range")) != NULL
> ! && (range = strstr(range,"bytes=")) != NULL) {
> ! range += 6;
> ! /* Multiple ranges are not supported yet */
> ! if (strchr(range,',') != NULL) {
> ! return NS_ERROR;
> ! }
> if (isdigit(*range)) {
> ! *offset1 = atol(range);
> while (isdigit(*range)) range++;
> if (*range == '-') {
> !
range++;
> if (!isdigit(*range)) {
> ! if (*range != '\0') {
> ! return NS_ERROR;
> ! }
> ! *offset2 = size - 1;
> } else {
> ! *offset2 = atol(range);
> ! if (*offset1 > *offset2) {
> ! return NS_ERROR;
> }
> ! if (*offset2 >= size) {
> ! *offset2 = size - 1;
> }
> }
> ! return NS_OK;
> ! } else {
> ! return NS_ERROR;
> }
> } else if (*range == '-') {
> range++;
> if (!isdigit(*range)) !
{
> ! return NS_ERROR;
> }
> ! *offset2 = atol(range);
> ! if (*offset2 > size) {
> ! *offset2 = size;
> }
> /* Size from the end requested, convert into offset */
> ! *offset1 = size - *offset2;
> ! *offset2 = *offset1 + *offset2 - 1;
> ! return NS_OK;
> }
> }
> ! return NS_ERROR;
> }
>
> --- 701,780 ----
>
> static int
> ! ParseRange(Ns_Conn *conn, unsigned long size, unsigned long *offsets,
> ! int offsets_size)
> {
> + int count = 0;
> char *range;
>
> ! if ((range = Ns_SetIGet(conn->headers, "Range")) == NULL
> ! || (range = strstr(ran!
ge,"bytes=")) == NULL) {
> ! return 0;
> ! }
> ! range += 6;
> ! memset(offsets,0,sizeof(unsigned long)*offsets_size);
>
> ! while(*range && count if (isdigit(*range)) {
> ! offsets[count] = atol(range);
> while (isdigit(*range)) range++;
> if (*range == '-') {
> range++;
> if (!isdigit(*range)) {
> ! offsets[count+1] = size - 1;
> } else {
> ! offsets[count+1] = atol(range);
> ! if (offsets[count] > offsets[count+1]) {
> ! return 0;
> }
> ! if (offsets[count+1] >= size) {
> ! offsets[count+1] = size - 1;
> }
> + while (isdigit(*range)) range++;
> }
> ! switch (*range) {
> ! case ',':
> ! range++;
> ! case '\0':
> ! break;
> ! default:
> ! return 0;
> ! }
> ! if (offsets[count] > offsets[count+1]) {
> ! return -1;
> ! }
> ! count += 2;
> ! continue;
> }
> } else if (*range == '-') {
> range++;
> if (!isdigit(*range)) {
> ! return 0;
> }
> ! offsets[count+1] = atol(range);
> ! !
if (offsets[count+1] > size) {
> ! offsets[count+1] = size;
> }
> /* Size from the end requested, convert into offset */
> ! offsets[count] = size - offsets[count+1];
> ! offsets[count+1] = offsets[count] + offsets[count+1] - 1;
> ! while (isdigit(*range)) range++;
> ! switch (*range) {
> ! case ',':
> ! range++;
> ! case '\0':
> ! break;
> ! default:
> ! return 0;
> ! }
> ! if (offsets[count] > offsets[count+1]) {
> ! return -1;
> ! }
> ! count += 2;
> ! continue;
> }
> + /* Invalid syntax */
> + !
return 0;
> }
> ! return count/2;
> }
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_idt77&alloc_id492&opÌk
_______________________________________________
naviserver-devel mailing list
naviserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/naviserver-devel