Check-in [f27754658d]
Overview
Comment:Updated to ignore SIGPIPE and made several Range handling improvements
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f27754658d52ebf923b3e5ca8ed923956b19be70
User & Date: rkeene on 2014-02-06 06:02:39
Other Links: manifest | tags
Context
2014-02-06
06:47
Updated to keep track of sent bytes check-in: 5d3ae25128 user: rkeene tags: trunk
06:02
Updated to ignore SIGPIPE and made several Range handling improvements check-in: f27754658d user: rkeene tags: trunk
04:15
Added range support check-in: 409fc328b7 user: rkeene tags: trunk
Changes

Modified filed.c from [460b9a234e] to [5e37a15236].

     2      2   #include <sys/socket.h>
     3      3   #include <sys/types.h>
     4      4   #include <arpa/inet.h>
     5      5   #include <sys/mman.h>
     6      6   #include <sys/stat.h>
     7      7   #include <pthread.h>
     8      8   #include <strings.h>
            9  +#include <signal.h>
     9     10   #include <stdlib.h>
    10     11   #include <unistd.h>
    11     12   #include <string.h>
    12     13   #include <fcntl.h>
    13     14   #include <stdio.h>
    14     15   #include <time.h>
    15     16   
................................................................................
    41     42   	/** Buffers **/
    42     43   	struct filed_fileinfo fileinfo;
    43     44   	char path_b[1010];
    44     45   	char tmpbuf[1010];
    45     46   
    46     47   	/** HTTP Request information **/
    47     48   	char *path;     /*** Path being requested ***/
    48         -	off_t offset;   /*** Range start ***/
    49         -	ssize_t length; /*** Range length ***/
           49  +
           50  +	struct {
           51  +		struct {
           52  +			int present;
           53  +			off_t offset;   /*** Range start ***/
           54  +			ssize_t length; /*** Range length ***/
           55  +		} range;
           56  +	} headers;
    50     57   };
    51     58   
    52     59   /* Global variables */
    53     60   struct filed_fileinfo *filed_fileinfo_fdcache;
    54     61   unsigned int filed_fileinfo_fdcache_size = CACHE_SIZE;
    55     62   
    56     63   /* Initialize process */
................................................................................
    72     79   		}
    73     80   
    74     81   		filed_fileinfo_fdcache[idx].path = strdup("");
    75     82   		filed_fileinfo_fdcache[idx].fd = -1;
    76     83   		filed_fileinfo_fdcache[idx].lastmod = "";
    77     84   		filed_fileinfo_fdcache[idx].type = "";
    78     85   	}
           86  +
           87  +	signal(SIGPIPE, SIG_IGN);
    79     88   
    80     89   	return(0);
    81     90   }
    82     91   
    83     92   /* Listen on a particular address/port */
    84     93   static int filed_listen(const char *address, unsigned int port) {
    85     94   	struct sockaddr_in6 addr;
................................................................................
   217    226   		lseek(fd, 0, SEEK_SET);
   218    227   
   219    228   		cache->fd = fd;
   220    229   		cache->len = len;
   221    230   		cache->path = strdup(path);
   222    231   
   223    232   		/* XXX:TODO: Determine */
   224         -		cache->type = "application/octet-stream";
          233  +		cache->type = "video/mp4";
   225    234   		cache->lastmod = filed_format_time(cache->lastmod_b, sizeof(cache->lastmod_b), time(NULL) - 30);
   226    235   	} else {
   227    236   		filed_log_msg_debug("Cache hit for idx: %lu: PATH \"%s\"", (unsigned long) cache_idx, path);
   228    237   	}
   229    238   
   230    239   	/*
   231    240   	 * We have to make a duplicate FD, because once we release the cache
................................................................................
   252    261   /* Process an HTTP request and return the path requested */
   253    262   static struct filed_http_request *filed_get_http_request(FILE *fp, struct filed_http_request *buffer_st) {
   254    263   	char *method, *path;
   255    264   	char *buffer, *tmpbuffer, *workbuffer, *workbuffer_next;
   256    265   	size_t buffer_len, tmpbuffer_len;
   257    266   	off_t range_start, range_end;
   258    267   	ssize_t range_length;
          268  +	int range_request;
   259    269   	int i;
   260    270   
   261    271   	range_start = 0;
   262    272   	range_end   = 0;
          273  +	range_request = 0;
   263    274   	range_length = -1;
   264    275   
   265    276   	buffer = buffer_st->path_b;
   266    277   	buffer_len = sizeof(buffer_st->path_b);
   267    278   
   268    279   	tmpbuffer = buffer_st->tmpbuf;
   269    280   	tmpbuffer_len = sizeof(buffer_st->tmpbuf);
................................................................................
   301    312   
   302    313   		if (strncasecmp(tmpbuffer, "Range: ", 7) == 0) {
   303    314   			workbuffer = tmpbuffer + 7;
   304    315   
   305    316   			if (strncasecmp(workbuffer, "bytes=", 6) == 0) {
   306    317   				workbuffer += 6;
   307    318   
   308         -				range_start = strtoul(workbuffer, &workbuffer_next, 10);
          319  +				range_request = 1;
          320  +
          321  +				range_start = strtoull(workbuffer, &workbuffer_next, 10);
   309    322   
   310    323   				workbuffer = workbuffer_next;
   311    324   
   312    325   				if (*workbuffer == '-') {
   313    326   					workbuffer++;
   314    327   
   315    328   					if (*workbuffer != '\r' && *workbuffer != '\n') {
   316         -						range_end = strtoul(workbuffer, &workbuffer_next, 10);
          329  +						range_end = strtoull(workbuffer, &workbuffer_next, 10);
   317    330   					}
   318    331   				}
   319    332   			}
   320    333   		}
   321    334   
   322    335   		if (memcmp(tmpbuffer, "\r\n", 2) == 0) {
   323    336   			break;
................................................................................
   338    351   		}
   339    352   
   340    353   		range_length = range_end - range_start;
   341    354   	}
   342    355   
   343    356   	/* Fill up structure to return */
   344    357   	buffer_st->path   = path;
   345         -	buffer_st->offset = range_start;
   346         -	buffer_st->length = range_length;
          358  +	buffer_st->headers.range.present = range_request;
          359  +	buffer_st->headers.range.offset  = range_start;
          360  +	buffer_st->headers.range.length  = range_length;
   347    361   
   348    362   	return(buffer_st);
   349    363   }
   350    364   
   351    365   /* Return an error page */
   352    366   static void filed_error_page(FILE *fp, const char *date_current, int error_number) {
   353    367   	char *error_string = "<html><head><title>ERROR</title></head><body>Unable to process request</body></html>";
................................................................................
   381    395   	if (fp == NULL) {
   382    396   		close(fd);
   383    397   
   384    398   		return;
   385    399   	}
   386    400   
   387    401   	request = filed_get_http_request(fp, request);
          402  +
          403  +	fflush(fp);
   388    404   
   389    405   	path = request->path;
   390    406   
   391    407   	filed_log_msg("PROCESS_REPLY_START FD=... PATH=... RANGE_START=... RANGE_LENGTH=...");
   392    408   
   393    409   	if (path == NULL) {
   394    410   		filed_error_page(fp, date_current, 500);
................................................................................
   404    420   
   405    421   	fileinfo = filed_open_file(path, &request->fileinfo);
   406    422   	if (fileinfo == NULL) {
   407    423   		filed_error_page(fp, date_current, 404);
   408    424   
   409    425   		filed_log_msg("PROCESS_REPLY_COMPLETE FD=... ERROR=404");
   410    426   	} else {
   411         -		if (request->offset != 0 || request->length >= 0) {
   412         -			if ((size_t) request->offset >= fileinfo->len) {
          427  +		if (request->headers.range.offset != 0 || request->headers.range.length >= 0) {
          428  +			if ((size_t) request->headers.range.offset >= fileinfo->len) {
   413    429   				filed_log_msg("PROCESS_REPLY_COMPLETE FD=... ERROR=416");
   414    430   
   415    431   				filed_error_page(fp, date_current, 416);
          432  +			} else {
          433  +				if (request->headers.range.length < 0) {
          434  +					request->headers.range.length = fileinfo->len - request->headers.range.offset;
          435  +				}
          436  +
          437  +				filed_log_msg_debug("Partial request, starting at: %llu and running for %llu bytes", (unsigned long long) request->headers.range.offset, (unsigned long long) request->headers.range.length);
          438  +
          439  +				http_code = 206;
   416    440   			}
   417         -
   418         -			if (request->length < 0) {
   419         -				request->length = fileinfo->len - request->offset;
   420         -			}
   421         -
   422         -			filed_log_msg_debug("Partial request, starting at: %lu and running for %lu bytes", (unsigned long) request->offset, (unsigned long) request->length);
   423         -
   424         -			http_code = 216;
   425    441   		} else {
   426         -			http_code = 200;
   427         -			request->offset = 0;
   428         -			request->length = fileinfo->len;
          442  +			if (request->headers.range.present) {
          443  +				http_code = 206;
          444  +			} else {
          445  +				http_code = 200;
          446  +			}
          447  +			request->headers.range.offset = 0;
          448  +			request->headers.range.length = fileinfo->len;
   429    449   		}
   430    450   
   431    451   		if (http_code > 0) {
   432         -			fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nContent-Range: %llu-%llu/%llu\r\nContent-Type: %s\r\nConnection: close\r\n\r\n",
          452  +			fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nAccept-Ranges: bytes\r\nContent-Type: %s\r\nConnection: close\r\n",
   433    453   				http_code,
   434    454   				date_current,
   435    455   				fileinfo->lastmod,
   436         -				(unsigned long long) request->length,
   437         -				(unsigned long long) request->offset, (unsigned long long) (request->offset + request->length - 1), (unsigned long long) fileinfo->len,
          456  +				(unsigned long long) request->headers.range.length,
   438    457   				fileinfo->type
   439    458   			);
          459  +			if (http_code == 206) {
          460  +				fprintf(fp, "Content-Range: %llu-%llu/%llu\r\n",
          461  +					(unsigned long long) request->headers.range.offset,
          462  +					(unsigned long long) (request->headers.range.offset + request->headers.range.length - 1),
          463  +					(unsigned long long) fileinfo->len
          464  +				);
          465  +			}
          466  +			fprintf(fp, "\r\n");
   440    467   			fflush(fp);
   441    468   
   442         -			filed_log_msg("PROCESS_REPLY_COMPLETE FD=... STATUS=200");
          469  +			filed_log_msg("PROCESS_REPLY_COMPLETE FD=... STATUS=20X");
   443    470   
   444    471   			filed_log_msg("SEND_START IFD=... OFD=... BYTES=...");
   445    472   
   446         -			sendfile_offset = request->offset;
   447         -			sendfile_len = request->length;
          473  +			sendfile_offset = request->headers.range.offset;
          474  +			sendfile_len = request->headers.range.length;
   448    475   			while (1) {
   449    476   				sendfile_ret = sendfile(fd, fileinfo->fd, &sendfile_offset, sendfile_len);
   450    477   				if (sendfile_ret <= 0) {
   451    478   					break;
   452    479   				}
   453    480   
   454    481   				sendfile_len -= sendfile_ret;