Revision: 14399
Author: adrian.chadd
Date: Thu Feb 11 08:12:47 2010
Log: Migrate more of the client-side range request handling code out.


http://code.google.com/p/lusca-cache/source/detail?r=14399

Modified:
 /branches/LUSCA_HEAD/src/client_side.c
 /branches/LUSCA_HEAD/src/client_side_ranges.c
 /branches/LUSCA_HEAD/src/client_side_ranges.h

=======================================
--- /branches/LUSCA_HEAD/src/client_side.c      Thu Feb 11 02:08:09 2010
+++ /branches/LUSCA_HEAD/src/client_side.c      Thu Feb 11 08:12:47 2010
@@ -1208,152 +1208,6 @@
        return 1;
     return 0;
 }
-
-/*
- * returns true if If-Range specs match reply, false otherwise
- */
-static int
-clientIfRangeMatch(clientHttpRequest * http, HttpReply * rep)
-{
- const TimeOrTag spec = httpHeaderGetTimeOrTag(&http->request->header, HDR_IF_RANGE);
-    /* check for parsing falure */
-    if (!spec.valid)
-       return 0;
-    /* got an ETag? */
-    if (spec.tag) {
-       const char *rep_tag = httpHeaderGetStr(&rep->header, HDR_ETAG);
-       debug(33, 3) ("clientIfRangeMatch: ETags: %s and %s\n",
-           spec.tag, rep_tag ? rep_tag : "<none>");
-       if (!rep_tag)
-           return 0;           /* entity has no etag to compare with! */
-       if (spec.tag[0] == 'W' || rep_tag[0] == 'W') {
- debug(33, 1) ("clientIfRangeMatch: Weak ETags are not allowed in If-Range: %s ? %s\n",
-               spec.tag, rep_tag);
-           return 0;           /* must use strong validator for sub-range 
requests */
-       }
-       return strcmp(rep_tag, spec.tag) == 0;
-    }
-    /* got modification time? */
-    else if (spec.time >= 0) {
-       return http->entry->lastmod == spec.time;
-    }
-    assert(0);                 /* should not happen */
-    return 0;
-}
-
-/* returns expected content length for multi-range replies
- * note: assumes that httpHdrRangeCanonize has already been called
- * warning: assumes that HTTP headers for individual ranges at the
- *          time of the actuall assembly will be exactly the same as
- *          the headers when clientMRangeCLen() is called */
-static squid_off_t
-clientMRangeCLen(clientHttpRequest * http)
-{
-    squid_off_t clen = 0;
-    HttpHdrRangePos pos = HttpHdrRangeInitPos;
-    const HttpHdrRangeSpec *spec;
-    MemBuf mb;
-
-    assert(http->entry->mem_obj);
-
-    memBufDefInit(&mb);
-    while ((spec = httpHdrRangeGetSpec(http->request->range, &pos))) {
-
-       /* account for headers for this range */
-       memBufReset(&mb);
-       clientPackRangeHdr(http->entry->mem_obj->reply,
-           spec, http->range_iter.boundary, &mb);
-       clen += mb.size;
-
-       /* account for range content */
-       clen += spec->length;
-
- debug(33, 6) ("clientMRangeCLen: (clen += %ld + %" PRINTF_OFF_T ") == %" PRINTF_OFF_T "\n",
-           (long int) mb.size, spec->length, clen);
-    }
-    /* account for the terminating boundary */
-    memBufReset(&mb);
-    clientPackTermBound(http->range_iter.boundary, &mb);
-    clen += mb.size;
-
-    memBufClean(&mb);
-    return clen;
-}
-
-/* adds appropriate Range headers if needed */
-static void
-clientBuildRangeHeader(clientHttpRequest * http, HttpReply * rep)
-{
-    HttpHeader *hdr = rep ? &rep->header : 0;
-    const char *range_err = NULL;
-    request_t *request = http->request;
-    assert(request->range);
-    /* check if we still want to do ranges */
-    if (!rep)
-       range_err = "no [parse-able] reply";
-    else if (rep->sline.status != HTTP_OK)
-       range_err = "wrong status code";
-    else if (httpHeaderHas(hdr, HDR_CONTENT_RANGE))
-       range_err = "origin server does ranges";
-    else if (rep->content_length < 0)
-       range_err = "unknown length";
- else if (rep->content_length != http->entry->mem_obj->reply->content_length)
-       range_err = "INCONSISTENT length";    /* a bug? */
- else if (httpHeaderHas(&http->request->header, HDR_IF_RANGE) && !clientIfRangeMatch(http, rep))
-       range_err = "If-Range match failed";
- else if (!httpHdrRangeCanonize(http->request->range, rep->content_length))
-       range_err = "canonization failed";
-    else if (httpHdrRangeIsComplex(http->request->range))
-       range_err = "too complex range header";
-    else if (!request->flags.cachable)      /* from we_do_ranges in http.c */
-       range_err = "non-cachable request";
- else if (!http->flags.hit && httpHdrRangeOffsetLimit(http->request->range))
-       range_err = "range outside range_offset_limit";
-    /* get rid of our range specs on error */
-    if (range_err) {
- debug(33, 3) ("clientBuildRangeHeader: will not do ranges: %s.\n", range_err);
-       httpHdrRangeDestroy(http->request->range);
-       http->request->range = NULL;
-    } else {
-       const int spec_count = http->request->range->specs.count;
-       squid_off_t actual_clen = -1;
-
- debug(33, 3) ("clientBuildRangeHeader: range spec count: %d virgin clen: %" PRINTF_OFF_T "\n",
-           spec_count, rep->content_length);
-       assert(spec_count > 0);
-       /* append appropriate header(s) */
-       if (spec_count == 1) {
-           HttpHdrRangePos pos = HttpHdrRangeInitPos;
- const HttpHdrRangeSpec *spec = httpHdrRangeGetSpec(http->request->range, &pos);
-           assert(spec);
-           /* append Content-Range */
-           httpHeaderAddContRange(hdr, *spec, rep->content_length);
-           /* set new Content-Length to the actual number of bytes
-            * transmitted in the message-body */
-           actual_clen = spec->length;
-       } else {
-           /* multipart! */
-           /* generate boundary string */
-           http->range_iter.boundary = httpHdrRangeBoundaryStr(http);
-           /* delete old Content-Type, add ours */
-           httpHeaderDelById(hdr, HDR_CONTENT_TYPE);
-           httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE,
-               "multipart/byteranges; boundary=\"%.*s\"",
-               strLen2(http->range_iter.boundary),
-               strBuf2(http->range_iter.boundary));
-           /* Content-Length is not required in multipart responses
-            * but it is always nice to have one */
-           actual_clen = clientMRangeCLen(http);
-       }
-
-       /* replace Content-Length header */
-       assert(actual_clen >= 0);
-       httpHeaderDelById(hdr, HDR_CONTENT_LENGTH);
-       httpHeaderPutSize(hdr, HDR_CONTENT_LENGTH, actual_clen);
-       rep->content_length = actual_clen;
- debug(33, 3) ("clientBuildRangeHeader: actual content length: %" PRINTF_OFF_T "\n", actual_clen);
-    }
-}

 /*
  * filters out unwanted entries from original reply header
=======================================
--- /branches/LUSCA_HEAD/src/client_side_ranges.c       Wed Feb 10 23:10:44 2010
+++ /branches/LUSCA_HEAD/src/client_side_ranges.c       Thu Feb 11 08:12:47 2010
@@ -168,3 +168,150 @@
     http->out.offset = body_off + i->prefix_size;        /* sync */
     return i->debt_size > 0;
 }
+
+/* returns expected content length for multi-range replies
+ * note: assumes that httpHdrRangeCanonize has already been called
+ * warning: assumes that HTTP headers for individual ranges at the
+ *          time of the actuall assembly will be exactly the same as
+ *          the headers when clientMRangeCLen() is called */
+static squid_off_t
+clientMRangeCLen(clientHttpRequest * http)
+{
+    squid_off_t clen = 0;
+    HttpHdrRangePos pos = HttpHdrRangeInitPos;
+    const HttpHdrRangeSpec *spec;
+    MemBuf mb;
+
+    assert(http->entry->mem_obj);
+
+    memBufDefInit(&mb);
+    while ((spec = httpHdrRangeGetSpec(http->request->range, &pos))) {
+
+        /* account for headers for this range */
+        memBufReset(&mb);
+        clientPackRangeHdr(http->entry->mem_obj->reply,
+            spec, http->range_iter.boundary, &mb);
+        clen += mb.size;
+
+        /* account for range content */
+        clen += spec->length;
+
+ debug(33, 6) ("clientMRangeCLen: (clen += %ld + %" PRINTF_OFF_T ") == %" PRINTF_OFF_T "\n",
+            (long int) mb.size, spec->length, clen);
+    }
+    /* account for the terminating boundary */
+    memBufReset(&mb);
+    clientPackTermBound(http->range_iter.boundary, &mb);
+    clen += mb.size;
+
+    memBufClean(&mb);
+    return clen;
+}
+
+/*
+ * returns true if If-Range specs match reply, false otherwise
+ */
+static int
+clientIfRangeMatch(clientHttpRequest * http, HttpReply * rep)
+{
+ const TimeOrTag spec = httpHeaderGetTimeOrTag(&http->request->header, HDR_IF_RANGE);
+    /* check for parsing falure */
+    if (!spec.valid)
+        return 0;
+    /* got an ETag? */
+    if (spec.tag) {
+        const char *rep_tag = httpHeaderGetStr(&rep->header, HDR_ETAG);
+        debug(33, 3) ("clientIfRangeMatch: ETags: %s and %s\n",
+            spec.tag, rep_tag ? rep_tag : "<none>");
+        if (!rep_tag)
+            return 0;           /* entity has no etag to compare with! */
+        if (spec.tag[0] == 'W' || rep_tag[0] == 'W') {
+ debug(33, 1) ("clientIfRangeMatch: Weak ETags are not allowed in If-Range: %s ? %s\n",
+                spec.tag, rep_tag);
+ return 0; /* must use strong validator for sub-range requests */
+        }
+        return strcmp(rep_tag, spec.tag) == 0;
+    }
+    /* got modification time? */
+    else if (spec.time >= 0) {
+        return http->entry->lastmod == spec.time;
+    }
+    assert(0);                  /* should not happen */
+    return 0;
+}
+
+/* adds appropriate Range headers if needed */
+void
+clientBuildRangeHeader(clientHttpRequest * http, HttpReply * rep)
+{
+    HttpHeader *hdr = rep ? &rep->header : 0;
+    const char *range_err = NULL;
+    request_t *request = http->request;
+    assert(request->range);
+    /* check if we still want to do ranges */
+    if (!rep)
+        range_err = "no [parse-able] reply";
+    else if (rep->sline.status != HTTP_OK)
+        range_err = "wrong status code";
+    else if (httpHeaderHas(hdr, HDR_CONTENT_RANGE))
+        range_err = "origin server does ranges";
+    else if (rep->content_length < 0)
+        range_err = "unknown length";
+ else if (rep->content_length != http->entry->mem_obj->reply->content_length)
+        range_err = "INCONSISTENT length";      /* a bug? */
+ else if (httpHeaderHas(&http->request->header, HDR_IF_RANGE) && !clientIfRangeMatch(http, rep))
+        range_err = "If-Range match failed";
+ else if (!httpHdrRangeCanonize(http->request->range, rep->content_length))
+        range_err = "canonization failed";
+    else if (httpHdrRangeIsComplex(http->request->range))
+        range_err = "too complex range header";
+    else if (!request->flags.cachable)  /* from we_do_ranges in http.c */
+        range_err = "non-cachable request";
+ else if (!http->flags.hit && httpHdrRangeOffsetLimit(http->request->range))
+        range_err = "range outside range_offset_limit";
+    /* get rid of our range specs on error */
+    if (range_err) {
+ debug(33, 3) ("clientBuildRangeHeader: will not do ranges: %s.\n", range_err);
+        httpHdrRangeDestroy(http->request->range);
+        http->request->range = NULL;
+    } else {
+        const int spec_count = http->request->range->specs.count;
+        squid_off_t actual_clen = -1;
+
+ debug(33, 3) ("clientBuildRangeHeader: range spec count: %d virgin clen: %" PRINTF_OFF_T "\n",
+            spec_count, rep->content_length);
+        assert(spec_count > 0);
+        /* append appropriate header(s) */
+        if (spec_count == 1) {
+            HttpHdrRangePos pos = HttpHdrRangeInitPos;
+ const HttpHdrRangeSpec *spec = httpHdrRangeGetSpec(http->request->range, &pos);
+            assert(spec);
+            /* append Content-Range */
+            httpHeaderAddContRange(hdr, *spec, rep->content_length);
+            /* set new Content-Length to the actual number of bytes
+             * transmitted in the message-body */
+            actual_clen = spec->length;
+        } else {
+            /* multipart! */
+            /* generate boundary string */
+            http->range_iter.boundary = httpHdrRangeBoundaryStr(http);
+            /* delete old Content-Type, add ours */
+            httpHeaderDelById(hdr, HDR_CONTENT_TYPE);
+            httpHeaderPutStrf(hdr, HDR_CONTENT_TYPE,
+                "multipart/byteranges; boundary=\"%.*s\"",
+                strLen2(http->range_iter.boundary),
+                strBuf2(http->range_iter.boundary));
+            /* Content-Length is not required in multipart responses
+             * but it is always nice to have one */
+            actual_clen = clientMRangeCLen(http);
+        }
+
+        /* replace Content-Length header */
+        assert(actual_clen >= 0);
+        httpHeaderDelById(hdr, HDR_CONTENT_LENGTH);
+        httpHeaderPutSize(hdr, HDR_CONTENT_LENGTH, actual_clen);
+        rep->content_length = actual_clen;
+ debug(33, 3) ("clientBuildRangeHeader: actual content length: %" PRINTF_OFF_T "\n", actual_clen);
+    }
+}
+
=======================================
--- /branches/LUSCA_HEAD/src/client_side_ranges.h       Wed Feb 10 23:10:44 2010
+++ /branches/LUSCA_HEAD/src/client_side_ranges.h       Thu Feb 11 08:12:47 2010
@@ -7,5 +7,6 @@
     MemBuf * mb);
extern int clientCanPackMoreRanges(const clientHttpRequest * http, HttpHdrRangeIter * i, size_t size); extern int clientPackMoreRanges(clientHttpRequest * http, const char *buf, size_t size, MemBuf * mb); +extern void clientBuildRangeHeader(clientHttpRequest * http, HttpReply * rep);

 #endif

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to