diff options
Diffstat (limited to '')
-rw-r--r-- | netwerk/protocol/http/TLSTransportLayer.h | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/netwerk/protocol/http/TLSTransportLayer.h b/netwerk/protocol/http/TLSTransportLayer.h new file mode 100644 index 0000000000..85489ffa40 --- /dev/null +++ b/netwerk/protocol/http/TLSTransportLayer.h @@ -0,0 +1,170 @@ +/* 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/. */ + +#ifndef TLSTransportLayer_h__ +#define TLSTransportLayer_h__ + +#include "nsSocketTransportService2.h" +#include "nsIInterfaceRequestor.h" +#include "nsISocketTransport.h" +#include "nsIAsyncInputStream.h" +#include "nsIAsyncOutputStream.h" +#include "prio.h" + +namespace mozilla::net { + +// TLSTransportLayer will provide a secondary TLS layer. It will be added as a +// layer between nsHttpConnection and nsSocketTransport. +// The mSocketTransport, mSocketIn, and mSocketOut of nsHttpConnection will be +// replaced by TLSTransportLayer. +// +// The input path of reading data from a socket is shown below. +// nsHttpConnection::OnSocketReadable +// nsHttpConnection::OnWriteSegment +// nsHttpConnection::mSocketIn->Read +// TLSTransportLayer::InputStreamWrapper::Read +// TLSTransportLayer::InputInternal +// TLSTransportLayer::InputStreamWrapper::ReadDirectly +// nsSocketInputStream::Read +// +// The output path of writing data to a socket is shown below. +// nsHttpConnection::OnSocketWritable +// nsHttpConnection::OnReadSegment +// TLSTransportLayer::OutputStreamWrapper::Write +// TLSTransportLayer::OutputInternal +// TLSTransportLayer::OutputStreamWrapper::WriteDirectly +// nsSocketOutputStream::Write + +// 9d6a3bc6-1f90-41d0-9b02-33ccd169052b +#define NS_TLSTRANSPORTLAYER_IID \ + { \ + 0x9d6a3bc6, 0x1f90, 0x41d0, { \ + 0x9b, 0x02, 0x33, 0xcc, 0xd1, 0x69, 0x05, 0x2b \ + } \ + } + +class TLSTransportLayer final : public nsISocketTransport, + public nsIInputStreamCallback, + public nsIOutputStreamCallback { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_TLSTRANSPORTLAYER_IID) + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITRANSPORT + NS_DECL_NSISOCKETTRANSPORT + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIOUTPUTSTREAMCALLBACK + + explicit TLSTransportLayer(nsISocketTransport* aTransport, + nsIAsyncInputStream* aInputStream, + nsIAsyncOutputStream* aOutputStream, + nsIInputStreamCallback* aOwner); + bool Init(const char* aTLSHost, int32_t aTLSPort); + already_AddRefed<nsIAsyncInputStream> GetInputStreamWrapper() { + nsCOMPtr<nsIAsyncInputStream> stream = &mSocketInWrapper; + return stream.forget(); + } + already_AddRefed<nsIAsyncOutputStream> GetOutputStreamWrapper() { + nsCOMPtr<nsIAsyncOutputStream> stream = &mSocketOutWrapper; + return stream.forget(); + } + + bool HasDataToRecv(); + + void ReleaseOwner() { mOwner = nullptr; } + + private: + class InputStreamWrapper : public nsIAsyncInputStream { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIINPUTSTREAM + NS_DECL_NSIASYNCINPUTSTREAM + + explicit InputStreamWrapper(nsIAsyncInputStream* aInputStream, + TLSTransportLayer* aTransport); + + nsresult ReadDirectly(char* buf, uint32_t count, uint32_t* countRead); + nsresult Status() { return mStatus; } + void SetStatus(nsresult aStatus) { mStatus = aStatus; } + + private: + friend class TLSTransportLayer; + virtual ~InputStreamWrapper() = default; + nsresult ReturnDataFromBuffer(char* buf, uint32_t count, + uint32_t* countRead); + + nsCOMPtr<nsIAsyncInputStream> mSocketIn; + + nsresult mStatus{NS_OK}; + // The lifetime of InputStreamWrapper and OutputStreamWrapper are bound to + // TLSTransportLayer, so using |mTransport| as a raw pointer should be safe. + TLSTransportLayer* MOZ_OWNING_REF mTransport; + }; + + class OutputStreamWrapper : public nsIAsyncOutputStream { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIOUTPUTSTREAM + NS_DECL_NSIASYNCOUTPUTSTREAM + + explicit OutputStreamWrapper(nsIAsyncOutputStream* aOutputStream, + TLSTransportLayer* aTransport); + + nsresult WriteDirectly(const char* buf, uint32_t count, + uint32_t* countWritten); + nsresult Status() { return mStatus; } + void SetStatus(nsresult aStatus) { mStatus = aStatus; } + + private: + friend class TLSTransportLayer; + virtual ~OutputStreamWrapper() = default; + static nsresult WriteFromSegments(nsIInputStream*, void*, const char*, + uint32_t offset, uint32_t count, + uint32_t* countRead); + + nsCOMPtr<nsIAsyncOutputStream> mSocketOut; + + nsresult mStatus{NS_OK}; + TLSTransportLayer* MOZ_OWNING_REF mTransport; + }; + + virtual ~TLSTransportLayer(); + bool DispatchRelease(); + + nsISocketTransport* Transport() { return mSocketTransport; } + + int32_t OutputInternal(const char* aBuf, int32_t aAmount); + int32_t InputInternal(char* aBuf, int32_t aAmount); + + static PRStatus GetPeerName(PRFileDesc* fd, PRNetAddr* addr); + static PRStatus GetSocketOption(PRFileDesc* fd, PRSocketOptionData* aOpt); + static PRStatus SetSocketOption(PRFileDesc* fd, + const PRSocketOptionData* data); + static int32_t Write(PRFileDesc* fd, const void* buf, int32_t amount); + static int32_t Read(PRFileDesc* fd, void* buf, int32_t amount); + static int32_t Send(PRFileDesc* fd, const void* buf, int32_t amount, + int flags, PRIntervalTime timeout); + static int32_t Recv(PRFileDesc* fd, void* buf, int32_t amount, int flags, + PRIntervalTime timeout); + static PRStatus Close(PRFileDesc* fd); + static int16_t Poll(PRFileDesc* fd, int16_t in_flags, int16_t* out_flags); + + nsCOMPtr<nsISocketTransport> mSocketTransport; + InputStreamWrapper mSocketInWrapper; + OutputStreamWrapper mSocketOutWrapper; + nsCOMPtr<nsITLSSocketControl> mTLSSocketControl; + nsCOMPtr<nsIInputStreamCallback> mInputCallback; + nsCOMPtr<nsIOutputStreamCallback> mOutputCallback; + PRFileDesc* mFD{nullptr}; + nsCOMPtr<nsIInputStreamCallback> mOwner; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(TLSTransportLayer, NS_TLSTRANSPORTLAYER_IID) + +} // namespace mozilla::net + +inline nsISupports* ToSupports(mozilla::net::TLSTransportLayer* aTransport) { + return static_cast<nsISocketTransport*>(aTransport); +} + +#endif |