/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=4 sw=2 sts=2 et cin: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first #include"HttpLog.h"
// Log on level :5, instead of default :4. #undef LOG #define LOG(args) LOG5(args) #undef LOG_ENABLED #define LOG_ENABLED() LOG5_ENABLED()
mErrorBeforeConnect = status;
mAlpnToken = mConnInfo->GetNPNToken(); if (NS_FAILED(mErrorBeforeConnect)) { // See explanation for non-strictness of this operation in // SetSecurityCallbacks.
mCallbacks = new nsMainThreadPtrHolder<nsIInterfaceRequestor>( "HttpConnectionUDP::mCallbacks", callbacks, false);
SetCloseReason(ToCloseReason(mErrorBeforeConnect)); return mErrorBeforeConnect;
}
mSocket = do_CreateInstance("@mozilla.org/network/udp-socket;1", &rv); if (NS_FAILED(rv)) { return rv;
}
// We need an address here so that we can convey the IP version of the // socket.
NetAddr local;
local.raw.family = peerAddr.raw.family;
rv = mSocket->InitWithAddress(&local, nullptr, false, 1); if (NS_FAILED(rv)) {
mSocket = nullptr; return rv;
}
ChangeConnectionState(ConnectionState::INITED); // See explanation for non-strictness of this operation in // SetSecurityCallbacks.
mCallbacks = new nsMainThreadPtrHolder<nsIInterfaceRequestor>( "HttpConnectionUDP::mCallbacks", callbacks, false);
// Call SyncListen at the end of this function. This call will actually // attach the sockte to SocketTransportService.
rv = mSocket->SyncListen(this); if (NS_FAILED(rv)) {
mSocket->Close();
mSocket = nullptr; return rv;
}
return NS_OK;
}
// called on the socket thread
nsresult HttpConnectionUDP::Activate(nsAHttpTransaction* trans, uint32_t caps,
int32_t pri) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG1(("HttpConnectionUDP::Activate [this=%p trans=%p caps=%x]\n", this, trans,
caps));
if (!mExperienced && !trans->IsNullTransaction()) {
mHasFirstHttpTransaction = true; // For QUIC we have HttpConnecitonUDP before the actual connection // has been establish so wait for TLS handshake to be finished before // we mark the connection 'experienced'. if (!mExperienced && mHttp3Session && mHttp3Session->IsConnected()) {
mExperienced = true;
} if (mBootstrappedTimingsSet) {
mBootstrappedTimingsSet = false;
nsHttpTransaction* hTrans = trans->QueryHttpTransaction(); if (hTrans) {
hTrans->BootstrapTimings(mBootstrappedTimings);
}
}
mBootstrappedTimings = TimingStruct();
}
mTransactionCaps = caps;
mPriority = pri;
NS_ENSURE_ARG_POINTER(trans);
// Connection failures are Activated() just like regular transacions. // If we don't have a confirmation of a connected socket then test it // with a write() to get relevant error code. if (NS_FAILED(mErrorBeforeConnect)) {
CloseTransaction(nullptr, mErrorBeforeConnect);
trans->Close(mErrorBeforeConnect);
gHttpHandler->ExcludeHttp3(mConnInfo); return mErrorBeforeConnect;
}
if (!mHttp3Session->AddStream(trans, pri, mCallbacks)) {
MOZ_ASSERT(false); // this cannot happen!
trans->Close(NS_ERROR_ABORT); return NS_ERROR_FAILURE;
}
bool HttpConnectionUDP::CanReuse() { if (NS_FAILED(mErrorBeforeConnect)) { returnfalse;
} if (mDontReuse) { returnfalse;
}
if (mHttp3Session) { return mHttp3Session->CanReuse();
} returnfalse;
}
bool HttpConnectionUDP::CanDirectlyActivate() { // return true if a new transaction can be addded to ths connection at any // time through Activate(). In practice this means this is a healthy SPDY // connection with room for more concurrent streams.
if (mHttp3Session) { return CanReuse();
} returnfalse;
}
// deal with 408 Server Timeouts
uint16_t responseStatus = responseHead->Status(); staticconst PRIntervalTime k1000ms = PR_MillisecondsToInterval(1000); if (responseStatus == 408) { // If this error could be due to a persistent connection reuse then // we pass an error code of NS_ERROR_NET_RESET to // trigger the transaction 'restart' mechanism. We tell it to reset its // response headers so that it will be ready to receive the new response. if (mIsReused &&
((PR_IntervalNow() - mHttp3Session->LastWriteTime()) < k1000ms)) {
Close(NS_ERROR_NET_RESET);
*reset = true; return NS_OK;
}
}
nsresult HttpConnectionUDP::MaybeForceSendIO() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread"); // due to bug 1213084 sometimes real I/O events do not get serviced when // NSPR derived I/O events are ready and this can cause a deadlock with // https over https proxying. Normally we would expect the write callback to // be invoked before this timer goes off, but set it at the old windows // tick interval (kForceDelay) as a backup for those circumstances. staticconst uint32_t kForceDelay = 17; // ms
MOZ_ASSERT(trans == mHttp3Session);
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (NS_SUCCEEDED(reason) || (reason == NS_BASE_STREAM_CLOSED)) {
MOZ_ASSERT(false); return;
}
// The connection and security errors clear out alt-svc mappings // in case any previously validated ones are now invalid if (((reason == NS_ERROR_NET_RESET) ||
(NS_ERROR_GET_MODULE(reason) == NS_ERROR_MODULE_SECURITY)) &&
mConnInfo && !(mTransactionCaps & NS_HTTP_ERROR_SOFTLY)) {
gHttpHandler->ClearHostMapping(mConnInfo);
}
mDontReuse = true; if (mHttp3Session) {
mHttp3Session->SetCleanShutdown(aIsShutdown);
mHttp3Session->Close(reason); if (!mHttp3Session->IsClosed()) { // During closing phase we still keep mHttp3Session session, // to resend CLOSE_CONNECTION frames. return;
}
}
// flag the connection as reused here for convenience sake. certainly // it might be going away instead ;-)
mIsReused = true;
}
void HttpConnectionUDP::OnQuicTimeoutExpired() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("HttpConnectionUDP::OnQuicTimeoutExpired [this=%p]\n", this)); // if the transaction was dropped... if (!mHttp3Session) {
LOG((" no transaction; ignoring event\n")); return;
}
// not called on the socket transport thread
NS_IMETHODIMP
HttpConnectionUDP::GetInterface(const nsIID& iid, void** result) { // NOTE: This function is only called on the UI thread via sync proxy from // the socket transport thread. If that weren't the case, then we'd // have to worry about the possibility of mHttp3Session going away // part-way through this function call. See CloseTransaction.
// NOTE - there is a bug here, the call to getinterface is proxied off the // nss thread, not the ui thread as the above comment says. So there is // indeed a chance of mSession going away. bug 615342
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.