summaryrefslogtreecommitdiff
path: root/dom/flyweb/HttpServer.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/flyweb/HttpServer.h')
-rw-r--r--dom/flyweb/HttpServer.h193
1 files changed, 193 insertions, 0 deletions
diff --git a/dom/flyweb/HttpServer.h b/dom/flyweb/HttpServer.h
new file mode 100644
index 0000000000..dab601c247
--- /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