164 lines
6 KiB
C++
164 lines
6 KiB
C++
/* 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_INLINE_DECL_STATIC_IID(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;
|
|
};
|
|
|
|
} // namespace mozilla::net
|
|
|
|
inline nsISupports* ToSupports(mozilla::net::TLSTransportLayer* aTransport) {
|
|
return static_cast<nsISocketTransport*>(aTransport);
|
|
}
|
|
|
|
#endif
|