diff options
Diffstat (limited to 'dom/flyweb/HttpServer.h')
-rw-r--r-- | dom/flyweb/HttpServer.h | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/dom/flyweb/HttpServer.h b/dom/flyweb/HttpServer.h new file mode 100644 index 000000000..dab601c24 --- /dev/null +++ b/dom/flyweb/HttpServer.h @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_dom_HttpServer_h +#define mozilla_dom_HttpServer_h + +#include "nsISupportsImpl.h" +#include "mozilla/DOMEventTargetHelper.h" +#include "nsITLSServerSocket.h" +#include "nsIAsyncInputStream.h" +#include "nsIAsyncOutputStream.h" +#include "mozilla/Variant.h" +#include "nsIRequestObserver.h" +#include "mozilla/MozPromise.h" +#include "nsITransportProvider.h" +#include "nsILocalCertService.h" + +class nsIX509Cert; + +namespace mozilla { +namespace dom { + +extern bool +ContainsToken(const nsCString& aList, const nsCString& aToken); + +class InternalRequest; +class InternalResponse; + +class HttpServerListener +{ +public: + // switch to NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING when that lands + NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; + NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; + + virtual void OnServerStarted(nsresult aStatus) = 0; + virtual void OnRequest(InternalRequest* aRequest) = 0; + virtual void OnWebSocket(InternalRequest* aConnectRequest) = 0; + virtual void OnServerClose() = 0; +}; + +class HttpServer final : public nsIServerSocketListener, + public nsILocalCertGetCallback +{ +public: + HttpServer(); + + NS_DECL_ISUPPORTS + NS_DECL_NSISERVERSOCKETLISTENER + NS_DECL_NSILOCALCERTGETCALLBACK + + void Init(int32_t aPort, bool aHttps, HttpServerListener* aListener); + + void SendResponse(InternalRequest* aRequest, InternalResponse* aResponse); + already_AddRefed<nsITransportProvider> + AcceptWebSocket(InternalRequest* aConnectRequest, + const Optional<nsAString>& aProtocol, + ErrorResult& aRv); + void SendWebSocketResponse(InternalRequest* aConnectRequest, + InternalResponse* aResponse); + + void Close(); + + void GetCertKey(nsACString& aKey); + + int32_t GetPort() + { + return mPort; + } + +private: + ~HttpServer(); + + nsresult StartServerSocket(nsIX509Cert* aCert); + void NotifyStarted(nsresult aStatus); + + class TransportProvider final : public nsITransportProvider + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSITRANSPORTPROVIDER + + void SetTransport(nsISocketTransport* aTransport, + nsIAsyncInputStream* aInput, + nsIAsyncOutputStream* aOutput); + + private: + virtual ~TransportProvider(); + void MaybeNotify(); + + nsCOMPtr<nsIHttpUpgradeListener> mListener; + nsCOMPtr<nsISocketTransport> mTransport; + nsCOMPtr<nsIAsyncInputStream> mInput; + nsCOMPtr<nsIAsyncOutputStream> mOutput; + }; + + class Connection final : public nsIInputStreamCallback + , public nsIOutputStreamCallback + , public nsITLSServerSecurityObserver + { + public: + Connection(nsISocketTransport* aTransport, + HttpServer* aServer, + nsresult& rv); + + NS_DECL_ISUPPORTS + NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSIOUTPUTSTREAMCALLBACK + NS_DECL_NSITLSSERVERSECURITYOBSERVER + + bool TryHandleResponse(InternalRequest* aRequest, + InternalResponse* aResponse); + already_AddRefed<nsITransportProvider> + HandleAcceptWebSocket(const Optional<nsAString>& aProtocol, + ErrorResult& aRv); + void HandleWebSocketResponse(InternalResponse* aResponse); + bool HasPendingWebSocketRequest(InternalRequest* aRequest) + { + return aRequest == mPendingWebSocketRequest; + } + + void Close(); + + private: + ~Connection(); + + void SetSecurityObserver(bool aListen); + + static nsresult ReadSegmentsFunc(nsIInputStream* aIn, + void* aClosure, + const char* aBuffer, + uint32_t aToOffset, + uint32_t aCount, + uint32_t* aWriteCount); + nsresult ConsumeInput(const char*& aBuffer, + const char* aEnd); + nsresult ConsumeLine(const char* aBuffer, + size_t aLength); + void MaybeAddPendingHeader(); + + void QueueResponse(InternalResponse* aResponse); + + RefPtr<HttpServer> mServer; + nsCOMPtr<nsISocketTransport> mTransport; + nsCOMPtr<nsIAsyncInputStream> mInput; + nsCOMPtr<nsIAsyncOutputStream> mOutput; + + enum { eRequestLine, eHeaders, eBody, ePause } mState; + RefPtr<InternalRequest> mPendingReq; + uint32_t mPendingReqVersion; + nsCString mInputBuffer; + nsCString mPendingHeaderName; + nsCString mPendingHeaderValue; + uint32_t mRemainingBodySize; + nsCOMPtr<nsIAsyncOutputStream> mCurrentRequestBody; + bool mCloseAfterRequest; + + typedef Pair<RefPtr<InternalRequest>, + RefPtr<InternalResponse>> PendingRequest; + nsTArray<PendingRequest> mPendingRequests; + RefPtr<MozPromise<nsresult, bool, false>> mOutputCopy; + + RefPtr<InternalRequest> mPendingWebSocketRequest; + RefPtr<TransportProvider> mWebSocketTransportProvider; + + struct OutputBuffer { + nsCString mString; + nsCOMPtr<nsIInputStream> mStream; + bool mChunked; + }; + + nsTArray<OutputBuffer> mOutputBuffers; + }; + + friend class Connection; + + RefPtr<HttpServerListener> mListener; + nsCOMPtr<nsIServerSocket> mServerSocket; + nsCOMPtr<nsIX509Cert> mCert; + + nsTArray<RefPtr<Connection>> mConnections; + + int32_t mPort; + bool mHttps; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_HttpServer_h |