From: Vlad S. <ser...@us...> - 2005-06-28 20:15:53
|
Update of /cvsroot/naviserver/naviserver/nsd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3191/nsd Modified Files: fastpath.c return.c Log Message: Added Ns_ConnVSetHeaders function to add headers to the output in printf-style way Added support for Range: header for returning partial content Index: fastpath.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/fastpath.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** fastpath.c 11 Jun 2005 18:40:31 -0000 1.5 --- fastpath.c 28 Jun 2005 20:15:44 -0000 1.6 *************** *** 61,65 **** static int FastReturn(NsServer *servPtr, Ns_Conn *conn, int status, char *type, char *file, struct stat *stPtr); ! /* --- 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); /* *************** *** 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; --- 473,482 ---- char *type, char *file, struct stat *stPtr) { ! int fd, new, nread; ! unsigned long size, offset1, offset2; ! int result = NS_ERROR, range = NS_ERROR; char *key; Ns_Entry *entPtr; + File *filePtr; FileMap fmap; *************** *** 510,515 **** } if (servPtr->fastpath.cache == NULL ! || stPtr->st_size > servPtr->fastpath.cachemaxentry) { /* --- 513,544 ---- } + /* + * 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) { + range = ParseRange(conn, stPtr->st_size, &offset1, &offset2); + } + if (range != NS_ERROR) { + if (offset1 > offset2) { + /* 416 Requested Range Not Satisfiable */ + Ns_ConnVSetHeaders(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_ConnVSetHeaders(conn, "Content-Range", "bytes %lu-%lu/%lu", + offset1, offset2, stPtr->st_size); + size = (offset2 - offset1) + 1; + /* 206 Partial Content */ + status = 206; + } + if (servPtr->fastpath.cache == NULL ! || stPtr->st_size > servPtr->fastpath.cachemaxentry ! || range == NS_OK) { /* *************** *** 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 { --- 551,559 ---- if (servPtr->fastpath.mmap && 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); NsMemUmap(&fmap); } else { *************** *** 531,535 **** goto notfound; } ! result = Ns_ConnReturnOpenFd(conn, status,type, fd,stPtr->st_size); close(fd); } --- 564,571 ---- goto notfound; } ! if (range == NS_OK) { ! lseek(fd, offset1, SEEK_SET); ! } ! result = Ns_ConnReturnOpenFd(conn, status, type, fd, size); close(fd); } *************** *** 643,644 **** --- 679,737 ---- return status; } + + + /* + *---------------------------------------------------------------------- + * + * ParseRange -- + * + * Checks for presence of Range: header, parses it and returns + * the requested offsets + * + * Results: + * NS_OK or NS_ERROR + * + * Side effects: + * First range specification is honored only + * + *---------------------------------------------------------------------- + */ + + 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 = strchr(range,'=')) != NULL) { + range++; + if (isdigit(*range)) { + *offset1 = atol(range); + while (isdigit(*range)) range++; + if (*range == '-') { + range++; + *offset2 = atol(range); + if (*offset2 == 0 || *offset2 >= size) { + *offset2 = size - 1; + } + } + } else if (*range == '-') { + range++; + *offset2 = atol(range); + if (*offset2 > size) { + *offset2 = size; + } + /* Size from the end requested, convert into offset */ + *offset1 = size - *offset2; + *offset2 = *offset1 + *offset2 - 1; + } + } + if (*offset2 == 0) { + return NS_ERROR; + } + return NS_OK; + } + Index: return.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/return.c,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** return.c 27 Jun 2005 17:48:57 -0000 1.7 --- return.c 28 Jun 2005 20:15:44 -0000 1.8 *************** *** 368,371 **** --- 368,401 ---- } + /* + *---------------------------------------------------------------------- + * + * Ns_ConnVSetHeaders -- + * + * Add a printf-style string as an output header. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + + void + Ns_ConnVSetHeaders(Ns_Conn *conn, char *field, char *fmt,...) + { + Ns_DString ds; + va_list ap; + + Ns_DStringInit(&ds); + va_start(ap, fmt); + Ns_DStringVPrintf(&ds, fmt, ap); + va_end(ap); + Ns_SetPut(conn->outputheaders, field, ds.string); + Ns_DStringFree(&ds); + } + /* |