@@ -4,10 +4,11 @@ #include #include #include #include #include +#include #include #include #include #include #include @@ -43,12 +44,18 @@ char path_b[1010]; char tmpbuf[1010]; /** HTTP Request information **/ char *path; /*** Path being requested ***/ - off_t offset; /*** Range start ***/ - ssize_t length; /*** Range length ***/ + + struct { + struct { + int present; + off_t offset; /*** Range start ***/ + ssize_t length; /*** Range length ***/ + } range; + } headers; }; /* Global variables */ struct filed_fileinfo *filed_fileinfo_fdcache; unsigned int filed_fileinfo_fdcache_size = CACHE_SIZE; @@ -74,10 +81,12 @@ filed_fileinfo_fdcache[idx].path = strdup(""); filed_fileinfo_fdcache[idx].fd = -1; filed_fileinfo_fdcache[idx].lastmod = ""; filed_fileinfo_fdcache[idx].type = ""; } + + signal(SIGPIPE, SIG_IGN); return(0); } /* Listen on a particular address/port */ @@ -219,11 +228,11 @@ cache->fd = fd; cache->len = len; cache->path = strdup(path); /* XXX:TODO: Determine */ - cache->type = "application/octet-stream"; + cache->type = "video/mp4"; cache->lastmod = filed_format_time(cache->lastmod_b, sizeof(cache->lastmod_b), time(NULL) - 30); } else { filed_log_msg_debug("Cache hit for idx: %lu: PATH \"%s\"", (unsigned long) cache_idx, path); } @@ -254,14 +263,16 @@ char *method, *path; char *buffer, *tmpbuffer, *workbuffer, *workbuffer_next; size_t buffer_len, tmpbuffer_len; off_t range_start, range_end; ssize_t range_length; + int range_request; int i; range_start = 0; range_end = 0; + range_request = 0; range_length = -1; buffer = buffer_st->path_b; buffer_len = sizeof(buffer_st->path_b); @@ -303,19 +314,21 @@ workbuffer = tmpbuffer + 7; if (strncasecmp(workbuffer, "bytes=", 6) == 0) { workbuffer += 6; - range_start = strtoul(workbuffer, &workbuffer_next, 10); + range_request = 1; + + range_start = strtoull(workbuffer, &workbuffer_next, 10); workbuffer = workbuffer_next; if (*workbuffer == '-') { workbuffer++; if (*workbuffer != '\r' && *workbuffer != '\n') { - range_end = strtoul(workbuffer, &workbuffer_next, 10); + range_end = strtoull(workbuffer, &workbuffer_next, 10); } } } } @@ -340,12 +353,13 @@ range_length = range_end - range_start; } /* Fill up structure to return */ buffer_st->path = path; - buffer_st->offset = range_start; - buffer_st->length = range_length; + buffer_st->headers.range.present = range_request; + buffer_st->headers.range.offset = range_start; + buffer_st->headers.range.length = range_length; return(buffer_st); } /* Return an error page */ @@ -383,10 +397,12 @@ return; } request = filed_get_http_request(fp, request); + + fflush(fp); path = request->path; filed_log_msg("PROCESS_REPLY_START FD=... PATH=... RANGE_START=... RANGE_LENGTH=..."); @@ -406,47 +422,58 @@ if (fileinfo == NULL) { filed_error_page(fp, date_current, 404); filed_log_msg("PROCESS_REPLY_COMPLETE FD=... ERROR=404"); } else { - if (request->offset != 0 || request->length >= 0) { - if ((size_t) request->offset >= fileinfo->len) { + if (request->headers.range.offset != 0 || request->headers.range.length >= 0) { + if ((size_t) request->headers.range.offset >= fileinfo->len) { filed_log_msg("PROCESS_REPLY_COMPLETE FD=... ERROR=416"); filed_error_page(fp, date_current, 416); - } - - if (request->length < 0) { - request->length = fileinfo->len - request->offset; - } - - filed_log_msg_debug("Partial request, starting at: %lu and running for %lu bytes", (unsigned long) request->offset, (unsigned long) request->length); - - http_code = 216; + } else { + if (request->headers.range.length < 0) { + request->headers.range.length = fileinfo->len - request->headers.range.offset; + } + + 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); + + http_code = 206; + } } else { - http_code = 200; - request->offset = 0; - request->length = fileinfo->len; + if (request->headers.range.present) { + http_code = 206; + } else { + http_code = 200; + } + request->headers.range.offset = 0; + request->headers.range.length = fileinfo->len; } if (http_code > 0) { - 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", + 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", http_code, date_current, fileinfo->lastmod, - (unsigned long long) request->length, - (unsigned long long) request->offset, (unsigned long long) (request->offset + request->length - 1), (unsigned long long) fileinfo->len, + (unsigned long long) request->headers.range.length, fileinfo->type ); + if (http_code == 206) { + fprintf(fp, "Content-Range: %llu-%llu/%llu\r\n", + (unsigned long long) request->headers.range.offset, + (unsigned long long) (request->headers.range.offset + request->headers.range.length - 1), + (unsigned long long) fileinfo->len + ); + } + fprintf(fp, "\r\n"); fflush(fp); - filed_log_msg("PROCESS_REPLY_COMPLETE FD=... STATUS=200"); + filed_log_msg("PROCESS_REPLY_COMPLETE FD=... STATUS=20X"); filed_log_msg("SEND_START IFD=... OFD=... BYTES=..."); - sendfile_offset = request->offset; - sendfile_len = request->length; + sendfile_offset = request->headers.range.offset; + sendfile_len = request->headers.range.length; while (1) { sendfile_ret = sendfile(fd, fileinfo->fd, &sendfile_offset, sendfile_len); if (sendfile_ret <= 0) { break; }