]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/clientStream.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / clientStream.cc
index b8969cbc425d2d37f373369826332231a20cc84b..17ad74d6a65b36caaa1d0528fa311293c19ba141 100644 (file)
-
 /*
- * $Id: clientStream.cc,v 1.11 2004/12/20 16:30:35 robertc Exp $
- *
- * DEBUG: section 87    Client-side Stream routines.
- * AUTHOR: Robert Collins
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *  
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *  
- *  You should have received a copy of the GNU General Public License
- *  along with thisObject program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
-/*
+/* DEBUG: section 87    Client-side Stream routines. */
+
+#include "squid.h"
+#include "client_side_request.h"
+#include "clientStream.h"
+#include "http/Stream.h"
+#include "HttpReply.h"
+#include "HttpRequest.h"
+
+/**
+ \defgroup ClientStreamInternal Client Streams Internals
+ \ingroup ClientStreamAPI
+ \par
  * A client Stream is a uni directional pipe, with the usual non-blocking
  * asynchronous approach present elsewhere in squid.
  *
+ \par
  * Each pipe node has a data push function, and a data request function.
  * This limits flexability - the data flow is no longer assembled at each
- * step. 
+ * step.
  *
+ \par
  * An alternative approach is to pass each node in the pipe the call-
- * back to use on each IO call. This allows the callbacks to be changed 
- * very easily by a participating node, but requires more maintenance 
- * in each node (store the call  back to the msot recent IO request in 
- * the nodes context.) Such an approach also prevents dynamically 
+ * back to use on each IO call. This allows the callbacks to be changed
+ * very easily by a participating node, but requires more maintenance
+ * in each node (store the callback to the most recent IO request in
+ * the nodes context.) Such an approach also prevents dynamically
  * changing the pipeline from outside without an additional interface
  * method to extract the callback and context from the next node.
  *
+ \par
  * One important characteristic of the stream is that the readfunc
  * on the terminating node, and the callback on the first node
  * will be NULL, and never used.
- */
-
-#include "squid.h"
-#include "clientStream.h"
-#include "HttpReply.h"
-#include "HttpRequest.h"
-#include "client_side_request.h"
-
-CBDATA_TYPE(clientStreamNode);
-
-/*
- * TODO: rather than each node undeleting the next, have a clientStreamDelete
- * that walks the list
- */
-
-/*
- * clientStream quick notes:
  *
+ \section QuickNotes Quick Notes
+ \par
  * Each node including the HEAD of the clientStream has a cbdataReference
  * held by the stream. Freeing the stream then removes that reference
- * and cbdataFrees every node.
- * Any node with other References, and all nodes downstream will only 
+ * and delete's every node.
+ * Any node with other References, and all nodes downstream will only
  * free when those references are released.
- * Stream nodes MAY hold references to the data member of the node. 
+ * Stream nodes MAY hold references to the data member of the node.
  *
- * Specifically - on creation no reference is made. 
+ \par
+ * Specifically - on creation no reference is made.
  * If you pass a data variable to a node, give it an initial reference.
  * If the data member is non-null on FREE, cbdataFree WILL be called.
  * This you must never call cbdataFree on your own context without
  * explicitly setting the stream node data member to NULL and
  * cbdataReferenceDone'ing it.
  *
+ \par
  * No data member may hold a reference to it's stream node.
  * The stream guarantees that DETACH will be called before
  * freeing the node, alowing data members to cleanup.
- * 
+ *
+ \par
  * If a node's data holds a reference to something that needs to
  * free the stream a circular reference list will occur.
  * This results no data being freed until that reference is removed.
  * One way to accomplish thisObject is to explicitly remove the
  * data from your own node before freeing the stream.
  *
- * (i.e. 
- * mycontext = thisObject->data;
- * thisObject->data = NULL;
- * clientStreamFree (thisObject->head);
- * mycontext = NULL;
- * return;
+ \code
+   mycontext = thisObject->data;
+   thisObject->data = NULL;
+   delete thisObject->head;
+   mycontext = NULL;
+   return;
+ \endcode
+ *
+ \todo rather than each node undeleting the next, have a clientStreamDelete that walks the list.
  */
 
-/* Local functions */
-static FREE clientStreamFree;
+CBDATA_CLASS_INIT(clientStreamNode);
 
-clientStreamNode *
-clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status,
-                ClientStreamData data)
+clientStreamNode::clientStreamNode(CSR * aReadfunc, CSCB * aCallback, CSD * aDetach, CSS * aStatus, ClientStreamData aData) :
+    head(NULL),
+    readfunc(aReadfunc),
+    callback(aCallback),
+    detach(aDetach),
+    status(aStatus),
+    data(aData)
+{}
+
+clientStreamNode::~clientStreamNode()
 {
-    clientStreamNode *temp;
-    CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree);
-    temp = cbdataAlloc(clientStreamNode);
-    temp->readfunc = readfunc;
-    temp->callback = callback;
-    temp->detach = detach;
-    temp->status = status;
-    temp->data = data;
-    return temp;
+    debugs(87, 3, "Freeing clientStreamNode " << this);
+
+    removeFromStream();
+    data = NULL;
 }
 
-/*
+/**
+ \ingroup ClientStreamInternal
  * Initialise a client Stream.
  * list is the stream
  * func is the read function for the head
@@ -132,8 +113,7 @@ clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus,
                  ClientStreamData readdata, CSCB * callback, CSD * cdetach, ClientStreamData callbackdata,
                  StoreIOBuffer tailBuffer)
 {
-    clientStreamNode *temp = clientStreamNew(func, NULL, rdetach, readstatus,
-                             readdata);
+    clientStreamNode *temp = new clientStreamNode(func, NULL, rdetach, readstatus, readdata);
     dlinkAdd(cbdataReference(temp), &temp->node, list);
     temp->head = list;
     clientStreamInsertHead(list, NULL, callback, cdetach, NULL, callbackdata);
@@ -141,7 +121,8 @@ clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus,
     temp->readBuffer = tailBuffer;
 }
 
-/*
+/**
+ \ingroup ClientStreamInternal
  * Doesn't actually insert at head. Instead it inserts one *after*
  * head. This is because HEAD is a special node, as is tail
  * This function is not suitable for inserting the real HEAD.
@@ -150,15 +131,13 @@ void
 clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback,
                        CSD * detach, CSS * status, ClientStreamData data)
 {
-
     /* test preconditions */
     assert(list != NULL);
     assert(list->head);
-    clientStreamNode *temp = clientStreamNew(func, callback, detach, status, data);
+    clientStreamNode *temp = new clientStreamNode(func, callback, detach, status, data);
     temp->head = list;
-    debug(87, 3)
-    ("clientStreamInsertHead: Inserted node %p with data %p after head\n",
-     temp, data.getRaw());
+    debugs(87, 3, "clientStreamInsertHead: Inserted node " << temp <<
+           " with data " << data.getRaw() << " after head");
 
     if (list->head->next)
         temp->readBuffer = ((clientStreamNode *)list->head->next->data)->readBuffer;
@@ -166,28 +145,30 @@ clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback,
     dlinkAddAfter(cbdataReference(temp), &temp->node, list->head, list);
 }
 
-/*
- * Callback the next node the in chain with it's requested data
- */
+// API
 void
-clientStreamCallback(clientStreamNode * thisObject, clientHttpRequest * http,
+clientStreamCallback(clientStreamNode * thisObject, ClientHttpRequest * http,
                      HttpReply * rep, StoreIOBuffer replyBuffer)
 {
     clientStreamNode *next;
     assert(thisObject && http && thisObject->node.next);
     next = thisObject->next();
 
-    debug(87,
-          3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n",
-              next->callback, next->data.getRaw(), thisObject);
+    debugs(87, 3, "clientStreamCallback: Calling " << next->callback << " with cbdata " <<
+           next->data.getRaw() << " from node " << thisObject);
     next->callback(next, http, rep, replyBuffer);
 }
 
-/*
+/**
+ \ingroup ClientStreamInternal
  * Call the previous node in the chain to read some data
+ *
+ \param thisObject  ??
+ \param http        ??
+ \param readBuffer  ??
  */
 void
-clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http,
+clientStreamRead(clientStreamNode * thisObject, ClientHttpRequest * http,
                  StoreIOBuffer readBuffer)
 {
     /* place the parameters on the 'stack' */
@@ -195,22 +176,26 @@ clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http,
     assert(thisObject && http && thisObject->prev());
     prev = thisObject->prev();
 
-    debug(87, 3) ("clientStreamRead: Calling %p with cbdata %p from node %p\n",
-                  prev->readfunc, prev->data.getRaw(), thisObject);
+    debugs(87, 3, "clientStreamRead: Calling " << prev->readfunc <<
+           " with cbdata " << prev->data.getRaw() << " from node " << thisObject);
     thisObject->readBuffer = readBuffer;
     prev->readfunc(prev, http);
 }
 
-/*
+/**
+ \ingroup ClientStreamInternal
  * Detach from the stream - only allowed for terminal members
+ *
+ \param thisObject  ??
+ \param http        ??
  */
 void
-clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http)
+clientStreamDetach(clientStreamNode * thisObject, ClientHttpRequest * http)
 {
     clientStreamNode *temp = thisObject;
 
     assert(thisObject->node.next == NULL);
-    debug(87, 3) ("clientStreamDetach: Detaching node %p\n", thisObject);
+    debugs(87, 3, "clientStreamDetach: Detaching node " << thisObject);
     /* And clean up thisObject node */
     /* ESI TODO: push refcount class through to head */
     clientStreamNode *prev = NULL;
@@ -222,17 +207,16 @@ clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http)
 
     cbdataReferenceDone(temp);
 
-    cbdataFree(thisObject);
+    delete thisObject;
 
-    /* and tell the prev that the detach has occured */
+    /* and tell the prev that the detach has occurred */
     /*
      * We do it in thisObject order so that the detaching node is always
      * at the end of the list
      */
 
     if (prev) {
-        debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n",
-                      prev->detach, prev->data.getRaw());
+        debugs(87, 3, "clientStreamDetach: Calling " << prev->detach << " with cbdata " << prev->data.getRaw());
 
         if (cbdataReferenceValid(prev))
             prev->detach(prev, http);
@@ -241,30 +225,37 @@ clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http)
     }
 }
 
-/*
+/**
+ \ingroup ClientStreamInternal
  * Abort the stream - detach every node in the pipeline.
+ *
+ \param thisObject  ??
+ \param http        ??
  */
 void
-clientStreamAbort(clientStreamNode * thisObject, clientHttpRequest * http)
+clientStreamAbort(clientStreamNode * thisObject, ClientHttpRequest * http)
 {
     dlink_list *list;
 
     assert(thisObject != NULL);
     assert(http != NULL);
     list = thisObject->head;
-    debug(87, 3) ("clientStreamAbort: Aborting stream with tail %p\n",
-                  list->tail);
+    debugs(87, 3, "clientStreamAbort: Aborting stream with tail " << list->tail);
 
     if (list->tail) {
         clientStreamDetach((clientStreamNode *)list->tail->data, http);
     }
 }
 
-/*
- * Call the upstream node to find it's status 
+/**
+ \ingroup ClientStreamInternal
+ * Call the upstream node to find it's status
+ *
+ \param thisObject  ??
+ \param http        ??
  */
 clientStream_status_t
-clientStreamStatus(clientStreamNode * thisObject, clientHttpRequest * http)
+clientStreamStatus(clientStreamNode * thisObject, ClientHttpRequest * http)
 {
     clientStreamNode *prev;
     assert(thisObject && http && thisObject->node.prev);
@@ -272,7 +263,6 @@ clientStreamStatus(clientStreamNode * thisObject, clientHttpRequest * http)
     return prev->status(prev, http);
 }
 
-/* Local function bodies */
 void
 clientStreamNode::removeFromStream()
 {
@@ -282,17 +272,6 @@ clientStreamNode::removeFromStream()
     head = NULL;
 }
 
-void
-clientStreamFree(void *foo)
-{
-    clientStreamNode *thisObject = (clientStreamNode *)foo;
-
-    debug(87, 3) ("Freeing clientStreamNode %p\n", thisObject);
-
-    thisObject->removeFromStream();
-    thisObject->data = NULL;
-}
-
 clientStreamNode *
 clientStreamNode::prev() const
 {
@@ -310,3 +289,4 @@ clientStreamNode::next() const
     else
         return NULL;
 }
+