Client Streams Internals
Collaboration diagram for Client Streams Internals:


void clientStreamInit (dlink_list *list, CSR *func, CSD *rdetach, CSS *readstatus, ClientStreamData readdata, CSCB *callback, CSD *cdetach, ClientStreamData callbackdata, StoreIOBuffer tailBuffer)
void clientStreamInsertHead (dlink_list *list, CSR *func, CSCB *callback, CSD *detach, CSS *status, ClientStreamData data)
void clientStreamRead (clientStreamNode *thisObject, ClientHttpRequest *http, StoreIOBuffer readBuffer)
void clientStreamDetach (clientStreamNode *thisObject, ClientHttpRequest *http)
void clientStreamAbort (clientStreamNode *thisObject, ClientHttpRequest *http)
clientStream_status_t clientStreamStatus (clientStreamNode *thisObject, ClientHttpRequest *http)

Detailed Description

A client Stream is a uni directional pipe, with the usual non-blocking asynchronous approach present elsewhere in squid.
Each pipe node has a data push function, and a data request function. This limits flexibility - the data flow is no longer assembled at each step.
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 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.
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.

Quick Notes

Each node including the HEAD of the clientStream has a cbdataReference held by the stream. Freeing the stream then removes that reference 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.
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.
No data member may hold a reference to it's stream node. The stream guarantees that DETACH will be called before freeing the node, allowing data members to cleanup.
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.
mycontext = thisObject->data;
thisObject->data = nullptr;
delete thisObject->head;
mycontext = nullptr;

TODO: rather than each node undeleting the next, have a clientStreamDelete that walks the list.

Function Documentation

◆ clientStreamAbort()

void clientStreamAbort ( clientStreamNode thisObject,
ClientHttpRequest http 

Abort the stream - detach every node in the pipeline.


Definition at line 235 of file

References assert, clientStreamDetach(), dlink_node::data, debugs, clientStreamNode::head, and dlink_list::tail.

Referenced by ClientHttpRequest::freeResources().

◆ clientStreamDetach()

◆ clientStreamInit()

void clientStreamInit ( dlink_list list,
CSR func,
CSD rdetach,
CSS readstatus,
ClientStreamData  readdata,
CSCB callback,
CSD cdetach,
ClientStreamData  callbackdata,
StoreIOBuffer  tailBuffer 

Initialise a client Stream. list is the stream func is the read function for the head callback is the callback for the tail tailbuf and taillen are the initial buffer and length for the tail.

Definition at line 112 of file

References cbdataReference, clientStreamInsertHead(), dlink_node::data, dlinkAdd(), clientStreamNode::head, clientStreamNode::node, clientStreamNode::readBuffer, and dlink_list::tail.

Referenced by ConnStateData::abortRequestParsing(), ConnStateData::buildFakeRequest(), Downloader::buildRequest(), clientBeginRequest(), ConnStateData::parseHttpRequest(), and Ftp::Server::parseOneRequest().

◆ clientStreamInsertHead()

void clientStreamInsertHead ( dlink_list list,
CSR func,
CSCB callback,
CSD detach,
CSS status,
ClientStreamData  data 

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.

Definition at line 131 of file

References assert, cbdataReference, dlink_node::data, debugs, dlinkAddAfter(), RefCount< C >::getRaw(), clientStreamNode::head, dlink_list::head, dlink_node::next, clientStreamNode::node, and clientStreamNode::readBuffer.

Referenced by clientStreamInit(), and clientReplyContext::processReplyAccessResult().

◆ clientStreamRead()

◆ clientStreamStatus()

clientStream_status_t clientStreamStatus ( clientStreamNode thisObject,
ClientHttpRequest http 

Call the upstream node to find it's status


Definition at line 257 of file

References assert, dlink_node::data, clientStreamNode::node, dlink_node::prev, and clientStreamNode::status.

Referenced by esiBufferRecipient(), esiStreamStatus(), Downloader::handleReply(), and Http::Stream::socketState().






Web Site Translations