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 : #include "WebSocketEventListenerChild.h"
8 : #include "WebSocketEventService.h"
9 : #include "WebSocketFrame.h"
10 :
11 : #include "mozilla/net/NeckoChild.h"
12 : #include "mozilla/StaticPtr.h"
13 : #include "nsISupportsPrimitives.h"
14 : #include "nsIObserverService.h"
15 : #include "nsXULAppAPI.h"
16 : #include "nsSocketTransportService2.h"
17 : #include "nsThreadUtils.h"
18 : #include "mozilla/Services.h"
19 :
20 : namespace mozilla {
21 : namespace net {
22 :
23 : namespace {
24 :
25 3 : StaticRefPtr<WebSocketEventService> gWebSocketEventService;
26 :
27 : bool
28 0 : IsChildProcess()
29 : {
30 0 : return XRE_GetProcessType() != GeckoProcessType_Default;
31 : }
32 :
33 : } // anonymous namespace
34 :
35 : class WebSocketBaseRunnable : public Runnable
36 : {
37 : public:
38 0 : WebSocketBaseRunnable(uint32_t aWebSocketSerialID, uint64_t aInnerWindowID)
39 0 : : Runnable("net::WebSocketBaseRunnable")
40 : , mWebSocketSerialID(aWebSocketSerialID)
41 0 : , mInnerWindowID(aInnerWindowID)
42 0 : {}
43 :
44 0 : NS_IMETHOD Run() override
45 : {
46 0 : MOZ_ASSERT(NS_IsMainThread());
47 :
48 0 : RefPtr<WebSocketEventService> service = WebSocketEventService::GetOrCreate();
49 0 : MOZ_ASSERT(service);
50 :
51 0 : WebSocketEventService::WindowListeners listeners;
52 0 : service->GetListeners(mInnerWindowID, listeners);
53 :
54 0 : for (uint32_t i = 0; i < listeners.Length(); ++i) {
55 0 : DoWork(listeners[i]);
56 : }
57 :
58 0 : return NS_OK;
59 : }
60 :
61 : protected:
62 0 : ~WebSocketBaseRunnable()
63 0 : {}
64 :
65 : virtual void DoWork(nsIWebSocketEventListener* aListener) = 0;
66 :
67 : uint32_t mWebSocketSerialID;
68 : uint64_t mInnerWindowID;
69 : };
70 :
71 0 : class WebSocketFrameRunnable final : public WebSocketBaseRunnable
72 : {
73 : public:
74 0 : WebSocketFrameRunnable(uint32_t aWebSocketSerialID,
75 : uint64_t aInnerWindowID,
76 : already_AddRefed<WebSocketFrame> aFrame,
77 : bool aFrameSent)
78 0 : : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
79 0 : , mFrame(Move(aFrame))
80 0 : , mFrameSent(aFrameSent)
81 0 : {}
82 :
83 : private:
84 0 : virtual void DoWork(nsIWebSocketEventListener* aListener) override
85 : {
86 0 : DebugOnly<nsresult> rv;
87 0 : if (mFrameSent) {
88 0 : rv = aListener->FrameSent(mWebSocketSerialID, mFrame);
89 : } else {
90 0 : rv = aListener->FrameReceived(mWebSocketSerialID, mFrame);
91 : }
92 :
93 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Frame op failed");
94 0 : }
95 :
96 : RefPtr<WebSocketFrame> mFrame;
97 : bool mFrameSent;
98 : };
99 :
100 0 : class WebSocketCreatedRunnable final : public WebSocketBaseRunnable
101 : {
102 : public:
103 0 : WebSocketCreatedRunnable(uint32_t aWebSocketSerialID,
104 : uint64_t aInnerWindowID,
105 : const nsAString& aURI,
106 : const nsACString& aProtocols)
107 0 : : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
108 : , mURI(aURI)
109 0 : , mProtocols(aProtocols)
110 0 : {}
111 :
112 : private:
113 0 : virtual void DoWork(nsIWebSocketEventListener* aListener) override
114 : {
115 : DebugOnly<nsresult> rv =
116 0 : aListener->WebSocketCreated(mWebSocketSerialID, mURI, mProtocols);
117 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketCreated failed");
118 0 : }
119 :
120 : const nsString mURI;
121 : const nsCString mProtocols;
122 : };
123 :
124 0 : class WebSocketOpenedRunnable final : public WebSocketBaseRunnable
125 : {
126 : public:
127 0 : WebSocketOpenedRunnable(uint32_t aWebSocketSerialID,
128 : uint64_t aInnerWindowID,
129 : const nsAString& aEffectiveURI,
130 : const nsACString& aProtocols,
131 : const nsACString& aExtensions)
132 0 : : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
133 : , mEffectiveURI(aEffectiveURI)
134 : , mProtocols(aProtocols)
135 0 : , mExtensions(aExtensions)
136 0 : {}
137 :
138 : private:
139 0 : virtual void DoWork(nsIWebSocketEventListener* aListener) override
140 : {
141 0 : DebugOnly<nsresult> rv = aListener->WebSocketOpened(mWebSocketSerialID,
142 : mEffectiveURI,
143 : mProtocols,
144 0 : mExtensions);
145 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketOpened failed");
146 0 : }
147 :
148 : const nsString mEffectiveURI;
149 : const nsCString mProtocols;
150 : const nsCString mExtensions;
151 : };
152 :
153 0 : class WebSocketMessageAvailableRunnable final : public WebSocketBaseRunnable
154 : {
155 : public:
156 0 : WebSocketMessageAvailableRunnable(uint32_t aWebSocketSerialID,
157 : uint64_t aInnerWindowID,
158 : const nsACString& aData,
159 : uint16_t aMessageType)
160 0 : : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
161 : , mData(aData)
162 0 : , mMessageType(aMessageType)
163 0 : {}
164 :
165 : private:
166 0 : virtual void DoWork(nsIWebSocketEventListener* aListener) override
167 : {
168 : DebugOnly<nsresult> rv =
169 0 : aListener->WebSocketMessageAvailable(mWebSocketSerialID, mData,
170 0 : mMessageType);
171 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketMessageAvailable failed");
172 0 : }
173 :
174 : const nsCString mData;
175 : uint16_t mMessageType;
176 : };
177 :
178 0 : class WebSocketClosedRunnable final : public WebSocketBaseRunnable
179 : {
180 : public:
181 0 : WebSocketClosedRunnable(uint32_t aWebSocketSerialID,
182 : uint64_t aInnerWindowID,
183 : bool aWasClean,
184 : uint16_t aCode,
185 : const nsAString& aReason)
186 0 : : WebSocketBaseRunnable(aWebSocketSerialID, aInnerWindowID)
187 : , mWasClean(aWasClean)
188 : , mCode(aCode)
189 0 : , mReason(aReason)
190 0 : {}
191 :
192 : private:
193 0 : virtual void DoWork(nsIWebSocketEventListener* aListener) override
194 : {
195 : DebugOnly<nsresult> rv =
196 0 : aListener->WebSocketClosed(mWebSocketSerialID, mWasClean, mCode, mReason);
197 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WebSocketClosed failed");
198 0 : }
199 :
200 : bool mWasClean;
201 : uint16_t mCode;
202 : const nsString mReason;
203 : };
204 :
205 : /* static */ already_AddRefed<WebSocketEventService>
206 4 : WebSocketEventService::Get()
207 : {
208 4 : MOZ_ASSERT(NS_IsMainThread());
209 8 : RefPtr<WebSocketEventService> service = gWebSocketEventService.get();
210 8 : return service.forget();
211 : }
212 :
213 : /* static */ already_AddRefed<WebSocketEventService>
214 0 : WebSocketEventService::GetOrCreate()
215 : {
216 0 : MOZ_ASSERT(NS_IsMainThread());
217 :
218 0 : if (!gWebSocketEventService) {
219 0 : gWebSocketEventService = new WebSocketEventService();
220 : }
221 :
222 0 : RefPtr<WebSocketEventService> service = gWebSocketEventService.get();
223 0 : return service.forget();
224 : }
225 :
226 0 : NS_INTERFACE_MAP_BEGIN(WebSocketEventService)
227 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebSocketEventService)
228 0 : NS_INTERFACE_MAP_ENTRY(nsIObserver)
229 0 : NS_INTERFACE_MAP_ENTRY(nsIWebSocketEventService)
230 0 : NS_INTERFACE_MAP_END
231 :
232 0 : NS_IMPL_ADDREF(WebSocketEventService)
233 0 : NS_IMPL_RELEASE(WebSocketEventService)
234 :
235 0 : WebSocketEventService::WebSocketEventService()
236 0 : : mCountListeners(0)
237 : {
238 0 : MOZ_ASSERT(NS_IsMainThread());
239 :
240 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
241 0 : if (obs) {
242 0 : obs->AddObserver(this, "xpcom-shutdown", false);
243 0 : obs->AddObserver(this, "inner-window-destroyed", false);
244 : }
245 0 : }
246 :
247 0 : WebSocketEventService::~WebSocketEventService()
248 : {
249 0 : MOZ_ASSERT(NS_IsMainThread());
250 0 : }
251 :
252 : void
253 0 : WebSocketEventService::WebSocketCreated(uint32_t aWebSocketSerialID,
254 : uint64_t aInnerWindowID,
255 : const nsAString& aURI,
256 : const nsACString& aProtocols,
257 : nsIEventTarget* aTarget)
258 : {
259 : // Let's continue only if we have some listeners.
260 0 : if (!HasListeners()) {
261 0 : return;
262 : }
263 :
264 : RefPtr<WebSocketCreatedRunnable> runnable =
265 : new WebSocketCreatedRunnable(aWebSocketSerialID, aInnerWindowID,
266 0 : aURI, aProtocols);
267 : DebugOnly<nsresult> rv = aTarget
268 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
269 0 : : NS_DispatchToMainThread(runnable);
270 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
271 : }
272 :
273 : void
274 0 : WebSocketEventService::WebSocketOpened(uint32_t aWebSocketSerialID,
275 : uint64_t aInnerWindowID,
276 : const nsAString& aEffectiveURI,
277 : const nsACString& aProtocols,
278 : const nsACString& aExtensions,
279 : nsIEventTarget* aTarget)
280 : {
281 : // Let's continue only if we have some listeners.
282 0 : if (!HasListeners()) {
283 0 : return;
284 : }
285 :
286 : RefPtr<WebSocketOpenedRunnable> runnable =
287 : new WebSocketOpenedRunnable(aWebSocketSerialID, aInnerWindowID,
288 0 : aEffectiveURI, aProtocols, aExtensions);
289 : DebugOnly<nsresult> rv = aTarget
290 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
291 0 : : NS_DispatchToMainThread(runnable);
292 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
293 : }
294 :
295 : void
296 0 : WebSocketEventService::WebSocketMessageAvailable(uint32_t aWebSocketSerialID,
297 : uint64_t aInnerWindowID,
298 : const nsACString& aData,
299 : uint16_t aMessageType,
300 : nsIEventTarget* aTarget)
301 : {
302 : // Let's continue only if we have some listeners.
303 0 : if (!HasListeners()) {
304 0 : return;
305 : }
306 :
307 : RefPtr<WebSocketMessageAvailableRunnable> runnable =
308 : new WebSocketMessageAvailableRunnable(aWebSocketSerialID, aInnerWindowID,
309 0 : aData, aMessageType);
310 : DebugOnly<nsresult> rv = aTarget
311 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
312 0 : : NS_DispatchToMainThread(runnable);
313 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
314 : }
315 :
316 : void
317 0 : WebSocketEventService::WebSocketClosed(uint32_t aWebSocketSerialID,
318 : uint64_t aInnerWindowID,
319 : bool aWasClean,
320 : uint16_t aCode,
321 : const nsAString& aReason,
322 : nsIEventTarget* aTarget)
323 : {
324 : // Let's continue only if we have some listeners.
325 0 : if (!HasListeners()) {
326 0 : return;
327 : }
328 :
329 : RefPtr<WebSocketClosedRunnable> runnable =
330 : new WebSocketClosedRunnable(aWebSocketSerialID, aInnerWindowID,
331 0 : aWasClean, aCode, aReason);
332 : DebugOnly<nsresult> rv = aTarget
333 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
334 0 : : NS_DispatchToMainThread(runnable);
335 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
336 : }
337 :
338 : void
339 0 : WebSocketEventService::FrameReceived(uint32_t aWebSocketSerialID,
340 : uint64_t aInnerWindowID,
341 : already_AddRefed<WebSocketFrame> aFrame,
342 : nsIEventTarget* aTarget)
343 : {
344 0 : RefPtr<WebSocketFrame> frame(Move(aFrame));
345 0 : MOZ_ASSERT(frame);
346 :
347 : // Let's continue only if we have some listeners.
348 0 : if (!HasListeners()) {
349 0 : return;
350 : }
351 :
352 : RefPtr<WebSocketFrameRunnable> runnable =
353 : new WebSocketFrameRunnable(aWebSocketSerialID, aInnerWindowID,
354 0 : frame.forget(), false /* frameSent */);
355 : DebugOnly<nsresult> rv = aTarget
356 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
357 0 : : NS_DispatchToMainThread(runnable);
358 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
359 : }
360 :
361 : void
362 0 : WebSocketEventService::FrameSent(uint32_t aWebSocketSerialID,
363 : uint64_t aInnerWindowID,
364 : already_AddRefed<WebSocketFrame> aFrame,
365 : nsIEventTarget* aTarget)
366 : {
367 0 : RefPtr<WebSocketFrame> frame(Move(aFrame));
368 0 : MOZ_ASSERT(frame);
369 :
370 : // Let's continue only if we have some listeners.
371 0 : if (!HasListeners()) {
372 0 : return;
373 : }
374 :
375 : RefPtr<WebSocketFrameRunnable> runnable =
376 : new WebSocketFrameRunnable(aWebSocketSerialID, aInnerWindowID,
377 0 : frame.forget(), true /* frameSent */);
378 :
379 : DebugOnly<nsresult> rv = aTarget
380 0 : ? aTarget->Dispatch(runnable, NS_DISPATCH_NORMAL)
381 0 : : NS_DispatchToMainThread(runnable);
382 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
383 : }
384 :
385 : NS_IMETHODIMP
386 0 : WebSocketEventService::AddListener(uint64_t aInnerWindowID,
387 : nsIWebSocketEventListener* aListener)
388 : {
389 0 : MOZ_ASSERT(NS_IsMainThread());
390 :
391 0 : if (!aListener) {
392 0 : return NS_ERROR_FAILURE;
393 : }
394 :
395 0 : ++mCountListeners;
396 :
397 0 : WindowListener* listener = mWindows.Get(aInnerWindowID);
398 0 : if (!listener) {
399 0 : listener = new WindowListener();
400 :
401 0 : if (IsChildProcess()) {
402 : PWebSocketEventListenerChild* actor =
403 0 : gNeckoChild->SendPWebSocketEventListenerConstructor(aInnerWindowID);
404 :
405 0 : listener->mActor = static_cast<WebSocketEventListenerChild*>(actor);
406 0 : MOZ_ASSERT(listener->mActor);
407 : }
408 :
409 0 : mWindows.Put(aInnerWindowID, listener);
410 : }
411 :
412 0 : listener->mListeners.AppendElement(aListener);
413 :
414 0 : return NS_OK;
415 : }
416 :
417 : NS_IMETHODIMP
418 0 : WebSocketEventService::RemoveListener(uint64_t aInnerWindowID,
419 : nsIWebSocketEventListener* aListener)
420 : {
421 0 : MOZ_ASSERT(NS_IsMainThread());
422 :
423 0 : if (!aListener) {
424 0 : return NS_ERROR_FAILURE;
425 : }
426 :
427 0 : WindowListener* listener = mWindows.Get(aInnerWindowID);
428 0 : if (!listener) {
429 0 : return NS_ERROR_FAILURE;
430 : }
431 :
432 0 : if (!listener->mListeners.RemoveElement(aListener)) {
433 0 : return NS_ERROR_FAILURE;
434 : }
435 :
436 : // The last listener for this window.
437 0 : if (listener->mListeners.IsEmpty()) {
438 0 : if (IsChildProcess()) {
439 0 : ShutdownActorListener(listener);
440 : }
441 :
442 0 : mWindows.Remove(aInnerWindowID);
443 : }
444 :
445 0 : MOZ_ASSERT(mCountListeners);
446 0 : --mCountListeners;
447 :
448 0 : return NS_OK;
449 : }
450 :
451 : NS_IMETHODIMP
452 0 : WebSocketEventService::HasListenerFor(uint64_t aInnerWindowID,
453 : bool* aResult)
454 : {
455 0 : MOZ_ASSERT(NS_IsMainThread());
456 :
457 0 : *aResult = mWindows.Get(aInnerWindowID);
458 :
459 0 : return NS_OK;
460 : }
461 :
462 : NS_IMETHODIMP
463 0 : WebSocketEventService::Observe(nsISupports* aSubject, const char* aTopic,
464 : const char16_t* aData)
465 : {
466 0 : MOZ_ASSERT(NS_IsMainThread());
467 :
468 0 : if (!strcmp(aTopic, "xpcom-shutdown")) {
469 0 : Shutdown();
470 0 : return NS_OK;
471 : }
472 :
473 0 : if (!strcmp(aTopic, "inner-window-destroyed") && HasListeners()) {
474 0 : nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
475 0 : NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
476 :
477 : uint64_t innerID;
478 0 : nsresult rv = wrapper->GetData(&innerID);
479 0 : NS_ENSURE_SUCCESS(rv, rv);
480 :
481 0 : WindowListener* listener = mWindows.Get(innerID);
482 0 : if (!listener) {
483 0 : return NS_OK;
484 : }
485 :
486 0 : MOZ_ASSERT(mCountListeners >= listener->mListeners.Length());
487 0 : mCountListeners -= listener->mListeners.Length();
488 :
489 0 : if (IsChildProcess()) {
490 0 : ShutdownActorListener(listener);
491 : }
492 :
493 0 : mWindows.Remove(innerID);
494 : }
495 :
496 : // This should not happen.
497 0 : return NS_ERROR_FAILURE;
498 : }
499 :
500 : void
501 0 : WebSocketEventService::Shutdown()
502 : {
503 0 : MOZ_ASSERT(NS_IsMainThread());
504 :
505 0 : if (gWebSocketEventService) {
506 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
507 0 : if (obs) {
508 0 : obs->RemoveObserver(gWebSocketEventService, "xpcom-shutdown");
509 0 : obs->RemoveObserver(gWebSocketEventService, "inner-window-destroyed");
510 : }
511 :
512 0 : mWindows.Clear();
513 0 : gWebSocketEventService = nullptr;
514 : }
515 0 : }
516 :
517 : bool
518 0 : WebSocketEventService::HasListeners() const
519 : {
520 0 : return !!mCountListeners;
521 : }
522 :
523 : void
524 0 : WebSocketEventService::GetListeners(uint64_t aInnerWindowID,
525 : WebSocketEventService::WindowListeners& aListeners) const
526 : {
527 0 : aListeners.Clear();
528 :
529 0 : WindowListener* listener = mWindows.Get(aInnerWindowID);
530 0 : if (!listener) {
531 0 : return;
532 : }
533 :
534 0 : aListeners.AppendElements(listener->mListeners);
535 : }
536 :
537 : void
538 0 : WebSocketEventService::ShutdownActorListener(WindowListener* aListener)
539 : {
540 0 : MOZ_ASSERT(aListener);
541 0 : MOZ_ASSERT(aListener->mActor);
542 0 : aListener->mActor->Close();
543 0 : aListener->mActor = nullptr;
544 0 : }
545 :
546 : already_AddRefed<WebSocketFrame>
547 0 : WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1,
548 : bool aRsvBit2, bool aRsvBit3,
549 : uint8_t aOpCode, bool aMaskBit,
550 : uint32_t aMask,
551 : const nsCString& aPayload)
552 : {
553 0 : if (!HasListeners()) {
554 0 : return nullptr;
555 : }
556 :
557 : return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
558 0 : aOpCode, aMaskBit, aMask, aPayload);
559 : }
560 :
561 : already_AddRefed<WebSocketFrame>
562 0 : WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1,
563 : bool aRsvBit2, bool aRsvBit3,
564 : uint8_t aOpCode, bool aMaskBit,
565 : uint32_t aMask, uint8_t* aPayload,
566 : uint32_t aPayloadLength)
567 : {
568 0 : if (!HasListeners()) {
569 0 : return nullptr;
570 : }
571 :
572 0 : nsAutoCString payloadStr;
573 0 : if (NS_WARN_IF(!(payloadStr.Assign((const char*) aPayload, aPayloadLength,
574 : mozilla::fallible)))) {
575 0 : return nullptr;
576 : }
577 :
578 : return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
579 0 : aOpCode, aMaskBit, aMask, payloadStr);
580 : }
581 :
582 : already_AddRefed<WebSocketFrame>
583 0 : WebSocketEventService::CreateFrameIfNeeded(bool aFinBit, bool aRsvBit1,
584 : bool aRsvBit2, bool aRsvBit3,
585 : uint8_t aOpCode, bool aMaskBit,
586 : uint32_t aMask,
587 : uint8_t* aPayloadInHdr,
588 : uint32_t aPayloadInHdrLength,
589 : uint8_t* aPayload,
590 : uint32_t aPayloadLength)
591 : {
592 0 : if (!HasListeners()) {
593 0 : return nullptr;
594 : }
595 :
596 0 : uint32_t payloadLength = aPayloadLength + aPayloadInHdrLength;
597 :
598 0 : nsAutoCString payload;
599 0 : if (NS_WARN_IF(!payload.SetLength(payloadLength, fallible))) {
600 0 : return nullptr;
601 : }
602 :
603 0 : char* payloadPtr = payload.BeginWriting();
604 0 : if (aPayloadInHdrLength) {
605 0 : memcpy(payloadPtr, aPayloadInHdr, aPayloadInHdrLength);
606 : }
607 :
608 0 : memcpy(payloadPtr + aPayloadInHdrLength, aPayload, aPayloadLength);
609 :
610 : return MakeAndAddRef<WebSocketFrame>(aFinBit, aRsvBit1, aRsvBit2, aRsvBit3,
611 0 : aOpCode, aMaskBit, aMask, payload);
612 : }
613 :
614 : } // net namespace
615 : } // mozilla namespace
|