[prev in list] [next in list] [prev in thread] [next in thread] 

List:       dav-cvs
Subject:    [dav-checkins] CVS: mod_dav mod_dav.c
From:       Greg Stein (CVS user) <gjscvs () nebula ! lyra ! org>
Date:       2000-05-28 10:48:42
[Download RAW message or body]

gjscvs      00/05/28 03:48:42

  Modified:    .        mod_dav.c
  Log:
  add Content-Range support in the GET handling
  
  Revision  Changes    Path
  1.116     +75 -4     mod_dav/mod_dav.c
  
  Index: mod_dav.c
  ===================================================================
  RCS file: /home/cvsroot/mod_dav/mod_dav.c,v
  retrieving revision 1.115
  retrieving revision 1.116
  diff -u -r1.115 -r1.116
  --- mod_dav.c	2000/05/27 20:32:08	1.115
  +++ mod_dav.c	2000/05/28 10:48:42	1.116
  @@ -806,6 +806,9 @@
   	dav_stream *stream;
   	dav_error *err;
   	void *buffer;
  +        const char *range;
  +        off_t range_start;
  +        off_t range_end;
   
   	/* set up the HTTP headers for the response */
   	if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
  @@ -815,14 +818,52 @@
   	    return dav_handle_err(r, err, NULL);
   	}
   
  +        /* use plain READ mode unless we see a Content-Range */
  +	mode = DAV_MODE_READ;
  +
  +        range = ap_table_get(r->headers_in, "content-range");
  +        if (range != NULL) {
  +            char *dash;
  +            char *slash;
  +
  +            range = ap_pstrdup(r->pool, range);
  +            if (strncasecmp(range, "bytes ", 6) != 0
  +                || (dash = strchr(range, '-')) == NULL
  +                || (slash = strchr(range, '/')) == NULL) {
  +                /* malformed header. ignore it (per S14.16 of RFC2616) */
  +                range = NULL;
  +            }
  +            else {
  +                *dash = *slash = '\0';
  +                range_start = atol(range + 6);
  +                range_end = atol(dash + 1);
  +                if (range_end < range_start
  +                    || (slash[1] != '*' && atol(slash + 1) <= range_end)) {
  +                    /* invalid range. ignore it (per S14.16 of RFC2616) */
  +                    range = NULL;
  +                }
  +                else {
  +                    /* we now have a valid range */
  +
  +                    /* use a read mode which is seekable */
  +                    mode = DAV_MODE_READ_SEEKABLE;
  +
  +                    /* prep the output */
  +                    r->status = HTTP_PARTIAL_CONTENT;
  +                    ap_table_setn(r->headers_out,
  +                                  "Content-Range",
  +                                  ap_psprintf(r->pool, "bytes %ld-%ld/*",
  +                                              range_start, range_end));
  +                    ap_set_content_length(r, range_end - range_start + 1);
  +                }
  +            }
  +        }
  +
           if (r->header_only) {
               ap_send_http_header(r);
               return DONE;
           }
   
  -	/* ### use DAV_MODE_READ_SEEKABLE if a Content-Range is present */
  -	mode = DAV_MODE_READ;
  -
   	if ((err = (*resource->hooks->open_stream)(resource, mode,
                                                      &stream)) != NULL) {
   	    /* ### assuming FORBIDDEN is probably not quite right... */
  @@ -834,6 +875,15 @@
   	    return dav_handle_err(r, err, NULL);
   	}
   
  +        if (range != NULL
  +            && (err = (*resource->hooks->seek_stream)(stream,
  +                                                      range_start)) != NULL) {
  +            err = dav_push_error(r->pool, err->status, 0,
  +                                 "Could not seek to beginning of the "
  +                                 "specified Content-Range.", err);
  +            return dav_handle_err(r, err, NULL);
  +        }
  +
   	/* all set. send the headers now. */
   	ap_send_http_header(r);
   
  @@ -844,7 +894,15 @@
   	while (1) {
   	    size_t amt;
   
  -	    amt = DAV_READ_BLOCKSIZE;
  +            if (range == NULL)
  +                amt = DAV_READ_BLOCKSIZE;
  +            else if ((range_end - range_start + 1) > DAV_READ_BLOCKSIZE)
  +                amt = DAV_READ_BLOCKSIZE;
  +            else {
  +                /* note: range_end - range_start is an ssize_t */
  +                amt = (size_t)(range_end - range_start + 1);
  +            }
  +
   	    if ((err = (*resource->hooks->read_stream)(stream, buffer,
                                                          &amt)) != NULL) {
   		break;
  @@ -858,6 +916,12 @@
   		break;
   	    }
   
  +            if (range != NULL) {
  +                range_start += amt;
  +                if (range_start > range_end)
  +                    break;
  +            }
  +
   	    /* reset the timeout after a successful write */
   	    ap_reset_timeout(r);
   	}
  @@ -868,6 +932,13 @@
   	if (err != NULL)
   	    return dav_handle_err(r, err, NULL);
   
  +        /*
  +        ** ### range_start should equal range_end+1. if it doesn't, then
  +        ** ### we did not send enough data to the client. the client will
  +        ** ### hang (and timeout) waiting for the data.
  +        **
  +        ** ### what to do? abort the connection?
  +        */
   	return DONE;
       }
   
  
  
  

_______________________________________________
dav-checkins maillist  -  dav-checkins@lyra.org
http://dav.lyra.org/mailman/listinfo/dav-checkins

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic