DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (fddffdeab170)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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_TCPSocket_h
#define mozilla_dom_TCPSocket_h

#include "mozilla/dom/TCPSocketBinding.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "nsITransport.h"
#include "nsIStreamListener.h"
#include "nsIAsyncInputStream.h"
#include "nsISupportsImpl.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsITCPSocketCallback.h"
#include "js/RootingAPI.h"

class nsISocketTransport;
class nsIInputStreamPump;
class nsIScriptableInputStream;
class nsIBinaryInputStream;
class nsIMultiplexInputStream;
class nsIAsyncStreamCopier;
class nsIInputStream;
class nsINetworkInfo;

namespace mozilla {
class ErrorResult;
namespace dom {

class DOMError;
struct ServerSocketOptions;
class TCPServerSocket;
class TCPSocketChild;
class TCPSocketParent;

// This interface is only used for legacy navigator.mozTCPSocket API compatibility.
class LegacyMozTCPSocket : public nsISupports
{
public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS(LegacyMozTCPSocket)

  explicit LegacyMozTCPSocket(nsPIDOMWindow* aWindow);

  already_AddRefed<TCPServerSocket>
  Listen(uint16_t aPort,
         const ServerSocketOptions& aOptions,
         uint16_t aBacklog,
         ErrorResult& aRv);

  already_AddRefed<TCPSocket>
  Open(const nsAString& aHost,
       uint16_t aPort,
       const SocketOptions& aOptions,
       ErrorResult& aRv);

  bool WrapObject(JSContext* aCx,
                  JS::Handle<JSObject*> aGivenProto,
                  JS::MutableHandle<JSObject*> aReflector);

private:
  virtual ~LegacyMozTCPSocket();

  nsCOMPtr<nsIGlobalObject> mGlobal;
};

class TCPSocket final : public DOMEventTargetHelper
                      , public nsIStreamListener
                      , public nsITransportEventSink
                      , public nsIInputStreamCallback
                      , public nsIObserver
                      , public nsSupportsWeakReference
                      , public nsITCPSocketCallback
{
public:
  TCPSocket(nsIGlobalObject* aGlobal, const nsAString& aHost, uint16_t aPort,
            bool aSsl, bool aUseArrayBuffers);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TCPSocket, DOMEventTargetHelper)
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER
  NS_DECL_NSITRANSPORTEVENTSINK
  NS_DECL_NSIINPUTSTREAMCALLBACK
  NS_DECL_NSIOBSERVER
  NS_DECL_NSITCPSOCKETCALLBACK

  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

  static bool ShouldTCPSocketExist(JSContext* aCx, JSObject* aGlobal);

  void GetHost(nsAString& aHost);
  uint32_t Port();
  bool Ssl();
  uint64_t BufferedAmount();
  void Suspend();
  void Resume(ErrorResult& aRv);
  void Close();
  bool Send(JSContext* aCx, const nsACString& aData, ErrorResult& aRv);
  bool Send(JSContext* aCx,
            const ArrayBuffer& aData,
            uint32_t aByteOffset,
            const Optional<uint32_t>& aByteLength,
            ErrorResult& aRv);
  TCPReadyState ReadyState();
  TCPSocketBinaryType BinaryType();
  void UpgradeToSecure(ErrorResult& aRv);

  static already_AddRefed<TCPSocket>
  Constructor(const GlobalObject& aGlobal,
              const nsAString& aHost,
              uint16_t aPort,
              const SocketOptions& aOptions,
              ErrorResult& aRv);

  // Perform a send operation that's asssociated with a sequence number. Used in
  // IPC scenarios to track the number of bytes buffered at any given time.
  void SendWithTrackingNumber(const nsACString& aData,
                              const uint32_t& aTrackingNumber,
                              ErrorResult& aRv);
  void SendWithTrackingNumber(JSContext* aCx,
                              const ArrayBuffer& aData,
                              uint32_t aByteOffset,
                              const Optional<uint32_t>& aByteLength,
                              const uint32_t& aTrackingNumber,
                              ErrorResult& aRv);
  // Create a TCPSocket object from an existing low-level socket connection.
  // Used by the TCPServerSocket implementation when a new connection is accepted.
  static already_AddRefed<TCPSocket>
  CreateAcceptedSocket(nsIGlobalObject* aGlobal, nsISocketTransport* aTransport, bool aUseArrayBuffers);
  // Create a TCPSocket object from an existing child-side IPC actor.
  // Used by the TCPServerSocketChild implementation when a new connection is accepted.
  static already_AddRefed<TCPSocket>
  CreateAcceptedSocket(nsIGlobalObject* aGlobal, TCPSocketChild* aSocketBridge, bool aUseArrayBuffers);

  // Initialize this socket's associated app and browser information.
  void SetAppIdAndBrowser(uint32_t aAppId, bool aInBrowser);
  // Initialize this socket's associated IPC actor in the parent process.
  void SetSocketBridgeParent(TCPSocketParent* aBridgeParent);

  static bool SocketEnabled();

  IMPL_EVENT_HANDLER(open);
  IMPL_EVENT_HANDLER(drain);
  IMPL_EVENT_HANDLER(data);
  IMPL_EVENT_HANDLER(error);
  IMPL_EVENT_HANDLER(close);

  nsresult Init();

  // Inform this socket that a buffered send() has completed sending.
  void NotifyCopyComplete(nsresult aStatus);

  // Initialize this socket from a low-level connection that hasn't connected yet
  // (called from RecvOpenBind() in TCPSocketParent).
  nsresult InitWithUnconnectedTransport(nsISocketTransport* aTransport);

private:
  ~TCPSocket();

  // Initialize this socket with an existing IPC actor.
  void InitWithSocketChild(TCPSocketChild* aBridge);
  // Initialize this socket from an existing low-level connection.
  nsresult InitWithTransport(nsISocketTransport* aTransport);
  // Initialize the input/output streams for this socket object.
  nsresult CreateStream();
  // Initialize the asynchronous read operation from this socket's input stream.
  nsresult CreateInputStreamPump();
  // Send the contents of the provided input stream, which is assumed to be the given length
  // for reporting and buffering purposes.
  bool Send(nsIInputStream* aStream, uint32_t aByteLength);
  // Begin an asynchronous copy operation if one is not already in progress.
  nsresult EnsureCopying();
  // Enable TLS on this socket.
  void ActivateTLS();
  // Dispatch an error event if necessary, then dispatch a "close" event.
  nsresult MaybeReportErrorAndCloseIfOpen(nsresult status);
#ifdef MOZ_WIDGET_GONK
  // Store and reset any saved network stats for this socket.
  void SaveNetworkStats(bool aEnforce);
#endif

  TCPReadyState mReadyState;
  // Whether to use strings or array buffers for the "data" event.
  bool mUseArrayBuffers;
  nsString mHost;
  uint16_t mPort;
  // Whether this socket is using a secure transport.
  bool mSsl;

  // The associated IPC actor in a child process.
  RefPtr<TCPSocketChild> mSocketBridgeChild;
  // The associated IPC actor in a parent process.
  RefPtr<TCPSocketParent> mSocketBridgeParent;

  // Raw socket streams
  nsCOMPtr<nsISocketTransport> mTransport;
  nsCOMPtr<nsIInputStream> mSocketInputStream;
  nsCOMPtr<nsIOutputStream> mSocketOutputStream;

  // Input stream machinery
  nsCOMPtr<nsIInputStreamPump> mInputStreamPump;
  nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable;
  nsCOMPtr<nsIBinaryInputStream> mInputStreamBinary;

  // Output stream machinery
  nsCOMPtr<nsIMultiplexInputStream> mMultiplexStream;
  nsCOMPtr<nsIAsyncStreamCopier> mMultiplexStreamCopier;

  // Is there an async copy operation in progress?
  bool mAsyncCopierActive;
  // True if the buffer is full and a "drain" event is expected by the client.
  bool mWaitingForDrain;

  // The id of the window that created this socket.
  uint64_t mInnerWindowID;

  // The current number of buffered bytes. Only used in content processes when IPC is enabled.
  uint64_t mBufferedAmount;

  // The number of times this socket has had `Suspend` called without a corresponding `Resume`.
  uint32_t mSuspendCount;

  // The current sequence number (ie. number of send operations) that have been processed.
  // This is used in the IPC scenario by the child process to filter out outdated notifications
  // about the amount of buffered data present in the parent process.
  uint32_t mTrackingNumber;

  // True if this socket has been upgraded to secure after the initial connection,
  // but the actual upgrade is waiting for an in-progress copy operation to complete.
  bool mWaitingForStartTLS;
  // The buffered data awaiting the TLS upgrade to finish.
  nsTArray<nsCOMPtr<nsIInputStream>> mPendingDataAfterStartTLS;

#ifdef MOZ_WIDGET_GONK
  // Number of bytes sent.
  uint32_t mTxBytes;
  // Number of bytes received.
  uint32_t mRxBytes;
  // The app that owns this socket.
  uint32_t mAppId;
  // Was this socket created inside of a mozbrowser frame?
  bool mInBrowser;
  // The name of the active network used by this socket.
  nsCOMPtr<nsINetworkInfo> mActiveNetworkInfo;
#endif
};

} // namespace dom
} // namespace mozilla

#endif // mozilla_dom_TCPSocket_h