void nsHttpPipeline::CloseTransaction(nsAHttpTransaction *trans, nsresult reason) { LOG(("nsHttpPipeline::CloseTransaction [this=%p trans=%x reason=%x]\n", this, trans, reason)); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(NS_FAILED(reason), "expecting failure code"); // the specified transaction is to be closed with the given "reason" int32_t index; bool killPipeline = false; index = mRequestQ.IndexOf(trans); if (index >= 0) { if (index == 0 && mRequestIsPartial) { // the transaction is in the request queue. check to see if any of // its data has been written out yet. killPipeline = true; } mRequestQ.RemoveElementAt(index); } else { index = mResponseQ.IndexOf(trans); if (index >= 0) mResponseQ.RemoveElementAt(index); // while we could avoid killing the pipeline if this transaction is the // last transaction in the pipeline, there doesn't seem to be that much // value in doing so. most likely if this transaction is going away, // the others will be shortly as well. killPipeline = true; } // Marking this connection as non-reusable prevents other items from being // added to it and causes it to be torn down soon. DontReuse(); trans->Close(reason); NS_RELEASE(trans); if (killPipeline) { // reschedule anything from this pipeline onto a different connection CancelPipeline(reason); } // If all the transactions have been removed then we can close the connection // right away. if (!mRequestQ.Length() && !mResponseQ.Length() && mConnection) mConnection->CloseTransaction(this, reason); }
PRUint32 nsHttpPipeline::CancelPipeline(nsresult originalReason) { PRUint32 i, reqLen, respLen, total; nsAHttpTransaction *trans; reqLen = mRequestQ.Length(); respLen = mResponseQ.Length(); total = reqLen + respLen; // don't count the first response, if presnet if (respLen) total--; if (!total) return 0; // any pending requests can ignore this error and be restarted // unless it is during a CONNECT tunnel request for (i = 0; i < reqLen; ++i) { trans = Request(i); if (mConnection && mConnection->IsProxyConnectInProgress()) trans->Close(originalReason); else trans->Close(NS_ERROR_NET_RESET); NS_RELEASE(trans); } mRequestQ.Clear(); // any pending responses can be restarted except for the first one, // that we might want to finish on this pipeline or cancel individually. // Higher levels of callers ensure that we don't process non-idempotent // tranasction with the NS_HTTP_ALLOW_PIPELINING bit set for (i = 1; i < respLen; ++i) { trans = Response(i); trans->Close(NS_ERROR_NET_RESET); NS_RELEASE(trans); } if (respLen > 1) mResponseQ.TruncateLength(1); DontReuse(); Classify(nsAHttpTransaction::CLASS_SOLO); return total; }