Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_dom_HttpServer_h
8 : #define mozilla_dom_HttpServer_h
9 :
10 : #include "nsISupportsImpl.h"
11 : #include "mozilla/DOMEventTargetHelper.h"
12 : #include "nsITLSServerSocket.h"
13 : #include "nsIAsyncInputStream.h"
14 : #include "nsIAsyncOutputStream.h"
15 : #include "mozilla/Variant.h"
16 : #include "nsIRequestObserver.h"
17 : #include "mozilla/MozPromise.h"
18 : #include "nsITransportProvider.h"
19 : #include "nsILocalCertService.h"
20 :
21 : class nsIX509Cert;
22 :
23 : class nsISerialEventTarget;
24 :
25 : namespace mozilla {
26 : namespace dom {
27 :
28 : extern bool
29 : ContainsToken(const nsCString& aList, const nsCString& aToken);
30 :
31 : class InternalRequest;
32 : class InternalResponse;
33 :
34 0 : class HttpServerListener
35 : {
36 : public:
37 : NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
38 :
39 : virtual void OnServerStarted(nsresult aStatus) = 0;
40 : virtual void OnRequest(InternalRequest* aRequest) = 0;
41 : virtual void OnWebSocket(InternalRequest* aConnectRequest) = 0;
42 : virtual void OnServerClose() = 0;
43 : };
44 :
45 : class HttpServer final : public nsIServerSocketListener,
46 : public nsILocalCertGetCallback
47 : {
48 : public:
49 : explicit HttpServer(nsISerialEventTarget* aEventTarget);
50 :
51 : NS_DECL_ISUPPORTS
52 : NS_DECL_NSISERVERSOCKETLISTENER
53 : NS_DECL_NSILOCALCERTGETCALLBACK
54 :
55 : void Init(int32_t aPort, bool aHttps, HttpServerListener* aListener);
56 :
57 : void SendResponse(InternalRequest* aRequest, InternalResponse* aResponse);
58 : already_AddRefed<nsITransportProvider>
59 : AcceptWebSocket(InternalRequest* aConnectRequest,
60 : const Optional<nsAString>& aProtocol,
61 : ErrorResult& aRv);
62 : void SendWebSocketResponse(InternalRequest* aConnectRequest,
63 : InternalResponse* aResponse);
64 :
65 : void Close();
66 :
67 : void GetCertKey(nsACString& aKey);
68 :
69 0 : int32_t GetPort()
70 : {
71 0 : return mPort;
72 : }
73 :
74 : private:
75 : ~HttpServer();
76 :
77 : nsresult StartServerSocket(nsIX509Cert* aCert);
78 : void NotifyStarted(nsresult aStatus);
79 :
80 0 : class TransportProvider final : public nsITransportProvider
81 : {
82 : public:
83 : NS_DECL_ISUPPORTS
84 : NS_DECL_NSITRANSPORTPROVIDER
85 :
86 : void SetTransport(nsISocketTransport* aTransport,
87 : nsIAsyncInputStream* aInput,
88 : nsIAsyncOutputStream* aOutput);
89 :
90 : private:
91 : virtual ~TransportProvider();
92 : void MaybeNotify();
93 :
94 : nsCOMPtr<nsIHttpUpgradeListener> mListener;
95 : nsCOMPtr<nsISocketTransport> mTransport;
96 : nsCOMPtr<nsIAsyncInputStream> mInput;
97 : nsCOMPtr<nsIAsyncOutputStream> mOutput;
98 : };
99 :
100 : class Connection final : public nsIInputStreamCallback
101 : , public nsIOutputStreamCallback
102 : , public nsITLSServerSecurityObserver
103 : {
104 : public:
105 : Connection(nsISocketTransport* aTransport,
106 : HttpServer* aServer,
107 : nsresult& rv);
108 :
109 : NS_DECL_ISUPPORTS
110 : NS_DECL_NSIINPUTSTREAMCALLBACK
111 : NS_DECL_NSIOUTPUTSTREAMCALLBACK
112 : NS_DECL_NSITLSSERVERSECURITYOBSERVER
113 :
114 : bool TryHandleResponse(InternalRequest* aRequest,
115 : InternalResponse* aResponse);
116 : already_AddRefed<nsITransportProvider>
117 : HandleAcceptWebSocket(const Optional<nsAString>& aProtocol,
118 : ErrorResult& aRv);
119 : void HandleWebSocketResponse(InternalResponse* aResponse);
120 0 : bool HasPendingWebSocketRequest(InternalRequest* aRequest)
121 : {
122 0 : return aRequest == mPendingWebSocketRequest;
123 : }
124 :
125 : void Close();
126 :
127 : private:
128 : ~Connection();
129 :
130 : void SetSecurityObserver(bool aListen);
131 :
132 : static nsresult ReadSegmentsFunc(nsIInputStream* aIn,
133 : void* aClosure,
134 : const char* aBuffer,
135 : uint32_t aToOffset,
136 : uint32_t aCount,
137 : uint32_t* aWriteCount);
138 : nsresult ConsumeInput(const char*& aBuffer,
139 : const char* aEnd);
140 : nsresult ConsumeLine(const char* aBuffer,
141 : size_t aLength);
142 : void MaybeAddPendingHeader();
143 :
144 : void QueueResponse(InternalResponse* aResponse);
145 :
146 : RefPtr<HttpServer> mServer;
147 : nsCOMPtr<nsISocketTransport> mTransport;
148 : nsCOMPtr<nsIAsyncInputStream> mInput;
149 : nsCOMPtr<nsIAsyncOutputStream> mOutput;
150 :
151 : enum { eRequestLine, eHeaders, eBody, ePause } mState;
152 : RefPtr<InternalRequest> mPendingReq;
153 : uint32_t mPendingReqVersion;
154 : nsCString mInputBuffer;
155 : nsCString mPendingHeaderName;
156 : nsCString mPendingHeaderValue;
157 : uint32_t mRemainingBodySize;
158 : nsCOMPtr<nsIAsyncOutputStream> mCurrentRequestBody;
159 : bool mCloseAfterRequest;
160 :
161 : typedef Pair<RefPtr<InternalRequest>,
162 : RefPtr<InternalResponse>> PendingRequest;
163 : nsTArray<PendingRequest> mPendingRequests;
164 : RefPtr<MozPromise<nsresult, bool, false>> mOutputCopy;
165 :
166 : RefPtr<InternalRequest> mPendingWebSocketRequest;
167 : RefPtr<TransportProvider> mWebSocketTransportProvider;
168 :
169 0 : struct OutputBuffer {
170 : nsCString mString;
171 : nsCOMPtr<nsIInputStream> mStream;
172 : bool mChunked;
173 : };
174 :
175 : nsTArray<OutputBuffer> mOutputBuffers;
176 : };
177 :
178 : friend class Connection;
179 :
180 : RefPtr<HttpServerListener> mListener;
181 : nsCOMPtr<nsIServerSocket> mServerSocket;
182 : nsCOMPtr<nsIX509Cert> mCert;
183 :
184 : nsTArray<RefPtr<Connection>> mConnections;
185 :
186 : int32_t mPort;
187 : bool mHttps;
188 :
189 : const nsCOMPtr<nsISerialEventTarget> mEventTarget;
190 : };
191 :
192 : } // namespace dom
193 : } // namespace mozilla
194 :
195 : #endif // mozilla_dom_HttpServer_h
|