/*
- * $Id: StoreIOBuffer.h,v 1.3 2003/02/21 22:50:06 robertc Exp $
+ * $Id: StoreIOBuffer.h,v 1.4 2003/08/10 03:59:19 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
+ * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
*/
-#ifndef SQUID_STOREIORESULT_H
-#define SQUID_STOREIORESULT_H
+#ifndef SQUID_STOREIOBUFFER_H
+#define SQUID_STOREIOBUFFER_H
+
+/* TODO: move this and the range() method into a .cci */
+#include "Range.h"
class StoreIOBuffer
{
flags.error = 0;
}
+ Range<size_t> range() const
+ {
+ return Range<size_t>(offset, offset + length);
+ }
+
struct
{
char *data;
};
-#endif /* SQUID_STOREIORESULT_H */
+#endif /* SQUID_STOREIOBUFFER_H */
/*
- * $Id: client_side.cc,v 1.652 2003/08/04 22:14:41 robertc Exp $
+ * $Id: client_side.cc,v 1.653 2003/08/10 03:59:19 robertc Exp $
*
* DEBUG: section 33 Client-side Routines
* AUTHOR: Duane Wessels
}
size_t
-ClientSocketContext::lengthToSend(size_t maximum)
+ClientSocketContext::lengthToSend(Range<size_t> const &available)
{
+ size_t maximum = available.size();
+
if (!http->request->range)
return maximum;
assert (http->range_iter.debt() > 0);
+ /* TODO this + the last line could be a range intersection calculation */
+ if ((ssize_t)available.start < http->range_iter.currentSpec()->offset)
+ return 0;
+
return XMIN(http->range_iter.debt(), (ssize_t)maximum);
}
assert(rep == NULL);
if (!multipartRangeRequest()) {
- size_t length = lengthToSend(bodyData.length);
+ size_t length = lengthToSend(bodyData.range());
noteSentBodyBytes (length);
comm_write(fd(), bodyData.data, length,
clientWriteBodyComplete, this);
MemBuf mb;
memBufDefInit(&mb);
- char const *t = bodyData.data;
- packRange(&t, bodyData.length, &mb);
- /* write */
- comm_old_write_mbuf(fd(), mb, clientWriteComplete, this);
- return;
+ packRange(bodyData, &mb);
+
+ if (mb.size)
+ /* write */
+ comm_old_write_mbuf(fd(), mb, clientWriteComplete, this);
+ else
+ writeComplete(fd(), NULL, 0, COMM_OK);
}
/* put terminating boundary for multiparts */
* all offsets and such.
*/
void
-ClientSocketContext::packRange(const char **buf,
- size_t size,
- MemBuf * mb)
+ClientSocketContext::packRange(StoreIOBuffer const &source, MemBuf * mb)
{
HttpHdrRangeIter * i = &http->range_iter;
- size_t available = size;
+ Range<size_t> available (source.range());
+ char const *buf (source.data);
- while (i->currentSpec() && available) {
+ while (i->currentSpec() && available.size()) {
const size_t copy_sz = lengthToSend(available);
- /*
- * intersection of "have" and "need" ranges must not be empty
- */
- assert(http->out.offset < i->currentSpec()->offset + i->currentSpec()->length);
- assert(http->out.offset + available > (size_t)i->currentSpec()->offset);
- /*
- * put boundary and headers at the beginning of a range in a
- * multi-range
- */
+ if (copy_sz) {
+ /*
+ * intersection of "have" and "need" ranges must not be empty
+ */
+ assert(http->out.offset < i->currentSpec()->offset + i->currentSpec()->length);
+ assert(http->out.offset + available.size() > (size_t)i->currentSpec()->offset);
- if (http->multipartRangeRequest() && i->debt() == i->currentSpec()->length) {
- assert(http->memObject());
- clientPackRangeHdr(
- http->memObject()->getReply(), /* original reply */
- i->currentSpec(), /* current range */
- i->boundary, /* boundary, the same for all */
- mb);
- }
+ /*
+ * put boundary and headers at the beginning of a range in a
+ * multi-range
+ */
- /*
- * append content
- */
- debug(33, 3) ("clientPackRange: appending %ld bytes\n", (long int) copy_sz);
+ if (http->multipartRangeRequest() && i->debt() == i->currentSpec()->length) {
+ assert(http->memObject());
+ clientPackRangeHdr(
+ http->memObject()->getReply(), /* original reply */
+ i->currentSpec(), /* current range */
+ i->boundary, /* boundary, the same for all */
+ mb);
+ }
- noteSentBodyBytes (copy_sz);
+ /*
+ * append content
+ */
+ debug(33, 3) ("clientPackRange: appending %ld bytes\n", (long int) copy_sz);
- memBufAppend(mb, *buf, copy_sz);
+ noteSentBodyBytes (copy_sz);
- /*
- * update offsets
- */
- available -= copy_sz;
+ memBufAppend(mb, buf, copy_sz);
+
+ /*
+ * update offsets
+ */
+ available.start += copy_sz;
+
+ buf += copy_sz;
- //body_off += copy_sz;
- *buf += copy_sz;
+ }
/*
* paranoid check
*/
- assert(available >= 0 && i->debt() >= 0 || i->debt() == -1);
+ assert(available.size() >= 0 && i->debt() >= 0 || i->debt() == -1);
if (!canPackMoreRanges()) {
debug(33, 3) ("clientPackRange: Returning because !canPackMoreRanges.\n");
size_t skip = next - http->out.offset;
- if (available <= skip)
+ /* adjust for not to be transmitted bytes */
+ http->out.offset = next;
+
+ if (available.size() <= skip)
return;
- available -= skip;
+ available.start += skip;
- *buf += skip;
+ buf += skip;
+
+ if (copy_sz == 0)
+ return;
}
}
/* Content-Length is not required in multipart responses
* but it is always nice to have one */
actual_clen = http->mRangeCLen();
+ /* http->out needs to start where we want data at */
+ http->out.offset = http->range_iter.currentSpec()->offset;
}
/* replace Content-Length header */
if (bodyData.data && bodyData.length) {
if (!multipartRangeRequest()) {
- size_t length = lengthToSend(bodyData.length);
+ size_t length = lengthToSend(bodyData.range());
noteSentBodyBytes (length);
memBufAppend(&mb, bodyData.data, length);
} else {
- char const *t = bodyData.data;
- packRange(&t,
- bodyData.length,
- &mb);
+ packRange(bodyData, &mb);
}
}
return start;
}
-#if 0
-
- } else if (http->request->range->specs.count > 1) {
- /* put terminating boundary for multiparts */
- clientPackTermBound(i->boundary, mb);
-#endif
-
}
return http->out.offset;
/*
- * $Id: client_side.h,v 1.6 2003/08/04 22:14:41 robertc Exp $
+ * $Id: client_side.h,v 1.7 2003/08/10 03:59:19 robertc Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
class clientStreamNode;
+template <class T>
+
+class Range;
+
class ClientSocketContext : public RefCountable
{
clientStream_status_t socketState();
void sendBody(HttpReply * rep, StoreIOBuffer bodyData);
void sendStartOfMessage(HttpReply * rep, StoreIOBuffer bodyData);
- size_t lengthToSend(size_t maximum);
+ size_t lengthToSend(Range<size_t> const &available);
void noteSentBodyBytes(size_t);
void buildRangeHeader(HttpReply * rep);
int fd() const;
void removeFromConnectionList(RefCount<ConnStateData> conn);
void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer recievedData);
bool multipartRangeRequest() const;
- void packRange(const char **buf,
- size_t size,
- MemBuf * mb);
void registerWithConn();
private:
CBDATA_CLASS(ClientSocketContext);
void prepareReply(HttpReply * rep);
+ void packRange(StoreIOBuffer const &, MemBuf * mb);
void deRegisterWithConn();
bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */
bool connRegistered_;