From: Stephen D. <sd...@us...> - 2005-07-06 00:47:50
|
Update of /cvsroot/naviserver/naviserver/nsd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19226/nsd Modified Files: fastpath.c Log Message: Add back preliminary support for HTTP range requests. Index: fastpath.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/fastpath.c,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** fastpath.c 5 Jul 2005 23:36:06 -0000 1.11 --- fastpath.c 6 Jul 2005 00:47:36 -0000 1.12 *************** *** 39,42 **** --- 39,44 ---- NS_RCSID("@(#) $Header$"); + #define MAX_RANGES 10 + /* * The following structure defines the contents of a file *************** *** 61,65 **** static int FastReturn(NsServer *servPtr, Ns_Conn *conn, int status, char *type, char *file, struct stat *stPtr); ! /* --- 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); /* *************** *** 472,479 **** char *type, char *file, struct stat *stPtr) { ! int result = NS_ERROR, fd, new, nread; ! File *filePtr; char *key; Ns_Entry *entPtr; FileMap fmap; --- 475,484 ---- char *type, char *file, struct stat *stPtr) { ! int fd, new, nread; ! unsigned long size, offsets[MAX_RANGES*2]; ! int result = NS_ERROR, ranges = 0; char *key; Ns_Entry *entPtr; + File *filePtr; FileMap fmap; *************** *** 510,515 **** } if (servPtr->fastpath.cache == NULL ! || stPtr->st_size > servPtr->fastpath.cachemaxentry) { /* --- 515,546 ---- } + /* + * Check if this is a Range: request, if so return requested + * portion of the file. Range requests are not cached. + */ + + 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; + } + if (servPtr->fastpath.cache == NULL ! || stPtr->st_size > servPtr->fastpath.cachemaxentry ! || ranges == 1) { /* *************** *** 522,526 **** if (servPtr->fastpath.mmap && NsMemMap(file, stPtr->st_size, NS_MMAP_READ, &fmap) == NS_OK) { ! result = Ns_ConnReturnData(conn,status, fmap.addr,fmap.size, type); NsMemUmap(&fmap); } else { --- 553,561 ---- if (servPtr->fastpath.mmap && 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,status, maddr, size, type); NsMemUmap(&fmap); } else { *************** *** 531,535 **** goto notfound; } ! result = Ns_ConnReturnOpenFd(conn, status,type, fd,stPtr->st_size); close(fd); } --- 566,573 ---- goto notfound; } ! if (ranges > 0) { ! lseek(fd, offsets[0], SEEK_SET); ! } ! result = Ns_ConnReturnOpenFd(conn, status, type, fd, size); close(fd); } *************** *** 643,644 **** --- 681,780 ---- return status; } + + + /* + *---------------------------------------------------------------------- + * + * ParseRange -- + * + * Checks for presence of Range: header, parses it and returns + * the requested offsets + * + * Results: + * -1 on error, number of byte ranges parsed + * + * Side effects: + * First range specification is honored only + * + *---------------------------------------------------------------------- + */ + + 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(range,"bytes=")) == NULL) { + return 0; + } + range += 6; + memset(offsets,0,sizeof(unsigned long)*offsets_size); + + while(*range && count < offsets_size-1) { + 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; + } + |