LCOV - code coverage report
Current view: top level - dom/network - TCPSocketParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 199 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          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 file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "TCPSocketParent.h"
       8             : #include "jsapi.h"
       9             : #include "jsfriendapi.h"
      10             : #include "nsJSUtils.h"
      11             : #include "mozilla/Unused.h"
      12             : #include "mozilla/net/NeckoCommon.h"
      13             : #include "mozilla/net/PNeckoParent.h"
      14             : #include "mozilla/dom/ContentParent.h"
      15             : #include "mozilla/dom/ScriptSettings.h"
      16             : #include "mozilla/dom/TabParent.h"
      17             : #include "mozilla/HoldDropJSObjects.h"
      18             : #include "nsISocketTransportService.h"
      19             : #include "nsISocketTransport.h"
      20             : #include "nsIScriptSecurityManager.h"
      21             : #include "nsNetUtil.h"
      22             : 
      23             : namespace IPC {
      24             : 
      25             : //Defined in TCPSocketChild.cpp
      26             : extern bool
      27             : DeserializeArrayBuffer(JSContext* aCx,
      28             :                        const InfallibleTArray<uint8_t>& aBuffer,
      29             :                        JS::MutableHandle<JS::Value> aVal);
      30             : 
      31             : } // namespace IPC
      32             : 
      33             : namespace mozilla {
      34             : 
      35             : namespace net {
      36             : //
      37             : // set MOZ_LOG=TCPSocket:5
      38             : //
      39             : extern LazyLogModule gTCPSocketLog;
      40             : #define TCPSOCKET_LOG(args)     MOZ_LOG(gTCPSocketLog, LogLevel::Debug, args)
      41             : #define TCPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gTCPSocketLog, LogLevel::Debug)
      42             : } // namespace net
      43             : 
      44             : namespace dom {
      45             : 
      46             : static void
      47           0 : FireInteralError(mozilla::net::PTCPSocketParent* aActor, uint32_t aLineNo)
      48             : {
      49             :   mozilla::Unused <<
      50           0 :       aActor->SendCallback(NS_LITERAL_STRING("onerror"),
      51           0 :                            TCPError(NS_LITERAL_STRING("InvalidStateError"), NS_LITERAL_STRING("Internal error")),
      52             :                            static_cast<uint32_t>(TCPReadyState::Connecting));
      53           0 : }
      54             : 
      55           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketParentBase)
      56           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      57           0 : NS_INTERFACE_MAP_END
      58             : 
      59           0 : NS_IMPL_CYCLE_COLLECTION(TCPSocketParentBase, mSocket)
      60           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketParentBase)
      61           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketParentBase)
      62             : 
      63           0 : TCPSocketParentBase::TCPSocketParentBase()
      64           0 : : mIPCOpen(false)
      65             : {
      66           0 : }
      67             : 
      68           0 : TCPSocketParentBase::~TCPSocketParentBase()
      69             : {
      70           0 : }
      71             : 
      72             : uint32_t
      73           0 : TCPSocketParent::GetAppId()
      74             : {
      75           0 :   return nsIScriptSecurityManager::UNKNOWN_APP_ID;
      76             : };
      77             : 
      78             : bool
      79           0 : TCPSocketParent::GetInIsolatedMozBrowser()
      80             : {
      81           0 :   const PContentParent *content = Manager()->Manager();
      82           0 :   if (PBrowserParent* browser = SingleManagedOrNull(content->ManagedPBrowserParent())) {
      83           0 :     TabParent *tab = TabParent::GetFrom(browser);
      84           0 :     return tab->IsIsolatedMozBrowserElement();
      85             :   } else {
      86           0 :     return false;
      87             :   }
      88             : }
      89             : 
      90             : void
      91           0 : TCPSocketParentBase::ReleaseIPDLReference()
      92             : {
      93           0 :   MOZ_ASSERT(mIPCOpen);
      94           0 :   mIPCOpen = false;
      95           0 :   this->Release();
      96           0 : }
      97             : 
      98             : void
      99           0 : TCPSocketParentBase::AddIPDLReference()
     100             : {
     101           0 :   MOZ_ASSERT(!mIPCOpen);
     102           0 :   mIPCOpen = true;
     103           0 :   this->AddRef();
     104           0 : }
     105             : 
     106           0 : NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketParent::Release(void)
     107             : {
     108           0 :   nsrefcnt refcnt = TCPSocketParentBase::Release();
     109           0 :   if (refcnt == 1 && mIPCOpen) {
     110           0 :     mozilla::Unused << PTCPSocketParent::SendRequestDelete();
     111           0 :     return 1;
     112             :   }
     113           0 :   return refcnt;
     114             : }
     115             : 
     116             : mozilla::ipc::IPCResult
     117           0 : TCPSocketParent::RecvOpen(const nsString& aHost, const uint16_t& aPort, const bool& aUseSSL,
     118             :                           const bool& aUseArrayBuffers)
     119             : {
     120             :   // Obtain App ID
     121           0 :   uint32_t appId = GetAppId();
     122           0 :   bool     inIsolatedMozBrowser = GetInIsolatedMozBrowser();
     123             : 
     124           0 :   mSocket = new TCPSocket(nullptr, aHost, aPort, aUseSSL, aUseArrayBuffers);
     125           0 :   mSocket->SetAppIdAndBrowser(appId, inIsolatedMozBrowser);
     126           0 :   mSocket->SetSocketBridgeParent(this);
     127           0 :   NS_ENSURE_SUCCESS(mSocket->Init(), IPC_OK());
     128           0 :   return IPC_OK();
     129             : }
     130             : 
     131             : mozilla::ipc::IPCResult
     132           0 : TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
     133             :                               const uint16_t& aRemotePort,
     134             :                               const nsCString& aLocalAddr,
     135             :                               const uint16_t& aLocalPort,
     136             :                               const bool&     aUseSSL,
     137             :                               const bool&     aReuseAddrPort,
     138             :                               const bool&     aUseArrayBuffers,
     139             :                               const nsCString& aFilter)
     140             : {
     141             :   nsresult rv;
     142             :   nsCOMPtr<nsISocketTransportService> sts =
     143           0 :     do_GetService("@mozilla.org/network/socket-transport-service;1", &rv);
     144           0 :   if (NS_FAILED(rv)) {
     145           0 :     FireInteralError(this, __LINE__);
     146           0 :     return IPC_OK();
     147             :   }
     148             : 
     149           0 :   nsCOMPtr<nsISocketTransport> socketTransport;
     150           0 :   if (aUseSSL) {
     151             :     const char* socketTypes[1];
     152           0 :     socketTypes[0] = "ssl";
     153           0 :     rv = sts->CreateTransport(socketTypes, 1,
     154           0 :                               aRemoteHost, aRemotePort,
     155           0 :                               nullptr, getter_AddRefs(socketTransport));
     156             :   } else {
     157           0 :     rv = sts->CreateTransport(nullptr, 0,
     158           0 :                               aRemoteHost, aRemotePort,
     159           0 :                               nullptr, getter_AddRefs(socketTransport));
     160             :   }
     161             : 
     162           0 :   if (NS_FAILED(rv)) {
     163           0 :     FireInteralError(this, __LINE__);
     164           0 :     return IPC_OK();
     165             :   }
     166             : 
     167             :   // in most cases aReuseAddrPort is false, but ICE TCP needs
     168             :   // sockets options set that allow addr/port reuse
     169           0 :   socketTransport->SetReuseAddrPort(aReuseAddrPort);
     170             : 
     171             :   PRNetAddr prAddr;
     172           0 :   if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) {
     173           0 :     FireInteralError(this, __LINE__);
     174           0 :     return IPC_OK();
     175             :   }
     176           0 :   if (PR_SUCCESS != PR_StringToNetAddr(aLocalAddr.BeginReading(), &prAddr)) {
     177           0 :     FireInteralError(this, __LINE__);
     178           0 :     return IPC_OK();
     179             :   }
     180             : 
     181             :   mozilla::net::NetAddr addr;
     182           0 :   PRNetAddrToNetAddr(&prAddr, &addr);
     183           0 :   rv = socketTransport->Bind(&addr);
     184           0 :   if (NS_FAILED(rv)) {
     185           0 :     FireInteralError(this, __LINE__);
     186           0 :     return IPC_OK();
     187             :   }
     188             : 
     189           0 :   if (!aFilter.IsEmpty()) {
     190           0 :     nsAutoCString contractId(NS_NETWORK_TCP_SOCKET_FILTER_HANDLER_PREFIX);
     191           0 :     contractId.Append(aFilter);
     192             :     nsCOMPtr<nsISocketFilterHandler> filterHandler =
     193           0 :       do_GetService(contractId.get());
     194           0 :     if (!filterHandler) {
     195           0 :       NS_ERROR("Content doesn't have a valid filter");
     196           0 :       FireInteralError(this, __LINE__);
     197           0 :       return IPC_OK();
     198             :     }
     199           0 :     rv = filterHandler->NewFilter(getter_AddRefs(mFilter));
     200           0 :     if (NS_FAILED(rv)) {
     201           0 :       NS_ERROR("Cannot create filter that content specified");
     202           0 :       FireInteralError(this, __LINE__);
     203           0 :       return IPC_OK();
     204             :     }
     205             :   }
     206             : 
     207           0 :   bool     inIsolatedMozBrowser = false;
     208           0 :   const PContentParent *content = Manager()->Manager();
     209           0 :   if (PBrowserParent* browser = SingleManagedOrNull(content->ManagedPBrowserParent())) {
     210           0 :     TabParent *tab = TabParent::GetFrom(browser);
     211           0 :     inIsolatedMozBrowser = tab->IsIsolatedMozBrowserElement();
     212             :   }
     213             : 
     214           0 :   mSocket = new TCPSocket(nullptr, NS_ConvertUTF8toUTF16(aRemoteHost), aRemotePort, aUseSSL, aUseArrayBuffers);
     215           0 :   mSocket->SetAppIdAndBrowser(nsIScriptSecurityManager::NO_APP_ID, inIsolatedMozBrowser);
     216           0 :   mSocket->SetSocketBridgeParent(this);
     217           0 :   rv = mSocket->InitWithUnconnectedTransport(socketTransport);
     218           0 :   NS_ENSURE_SUCCESS(rv, IPC_OK());
     219           0 :   return IPC_OK();
     220             : }
     221             : 
     222             : mozilla::ipc::IPCResult
     223           0 : TCPSocketParent::RecvStartTLS()
     224             : {
     225           0 :   NS_ENSURE_TRUE(mSocket, IPC_OK());
     226           0 :   ErrorResult rv;
     227           0 :   mSocket->UpgradeToSecure(rv);
     228           0 :   if (NS_WARN_IF(rv.Failed())) {
     229           0 :     rv.SuppressException();
     230             :   }
     231             : 
     232           0 :   return IPC_OK();
     233             : }
     234             : 
     235             : mozilla::ipc::IPCResult
     236           0 : TCPSocketParent::RecvSuspend()
     237             : {
     238           0 :   NS_ENSURE_TRUE(mSocket, IPC_OK());
     239           0 :   mSocket->Suspend();
     240           0 :   return IPC_OK();
     241             : }
     242             : 
     243             : mozilla::ipc::IPCResult
     244           0 : TCPSocketParent::RecvResume()
     245             : {
     246           0 :   NS_ENSURE_TRUE(mSocket, IPC_OK());
     247           0 :   ErrorResult rv;
     248           0 :   mSocket->Resume(rv);
     249           0 :   if (NS_WARN_IF(rv.Failed())) {
     250           0 :     rv.SuppressException();
     251             :   }
     252             : 
     253           0 :   return IPC_OK();
     254             : }
     255             : 
     256             : mozilla::ipc::IPCResult
     257           0 : TCPSocketParent::RecvData(const SendableData& aData,
     258             :                           const uint32_t& aTrackingNumber)
     259             : {
     260           0 :   ErrorResult rv;
     261             : 
     262           0 :   if (mFilter) {
     263             :     mozilla::net::NetAddr addr; // dummy value
     264             :     bool allowed;
     265           0 :     MOZ_ASSERT(aData.type() == SendableData::TArrayOfuint8_t,
     266             :                "Unsupported data type for filtering");
     267           0 :     const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t());
     268           0 :     nsresult nsrv = mFilter->FilterPacket(&addr, data.Elements(),
     269           0 :                                           data.Length(),
     270             :                                           nsISocketFilter::SF_OUTGOING,
     271           0 :                                           &allowed);
     272             : 
     273             :     // Reject sending of unallowed data
     274           0 :     if (NS_WARN_IF(NS_FAILED(nsrv)) || !allowed) {
     275           0 :       TCPSOCKET_LOG(("%s: Dropping outgoing TCP packet", __FUNCTION__));
     276           0 :       return IPC_FAIL_NO_REASON(this);
     277             :     }
     278             :   }
     279             : 
     280           0 :   switch (aData.type()) {
     281             :     case SendableData::TArrayOfuint8_t: {
     282           0 :       AutoSafeJSContext autoCx;
     283           0 :       JS::Rooted<JS::Value> val(autoCx);
     284           0 :       const nsTArray<uint8_t>& buffer = aData.get_ArrayOfuint8_t();
     285           0 :       bool ok = IPC::DeserializeArrayBuffer(autoCx, buffer, &val);
     286           0 :       NS_ENSURE_TRUE(ok, IPC_OK());
     287           0 :       RootedTypedArray<ArrayBuffer> data(autoCx);
     288           0 :       data.Init(&val.toObject());
     289           0 :       Optional<uint32_t> byteLength(buffer.Length());
     290           0 :       mSocket->SendWithTrackingNumber(autoCx, data, 0, byteLength, aTrackingNumber, rv);
     291           0 :       break;
     292             :     }
     293             : 
     294             :     case SendableData::TnsCString: {
     295           0 :       const nsCString& strData = aData.get_nsCString();
     296           0 :       mSocket->SendWithTrackingNumber(strData, aTrackingNumber, rv);
     297           0 :       break;
     298             :     }
     299             : 
     300             :     default:
     301           0 :       MOZ_CRASH("unexpected SendableData type");
     302             :   }
     303           0 :   NS_ENSURE_SUCCESS(rv.StealNSResult(), IPC_OK());
     304           0 :   return IPC_OK();
     305             : }
     306             : 
     307             : mozilla::ipc::IPCResult
     308           0 : TCPSocketParent::RecvClose()
     309             : {
     310           0 :   NS_ENSURE_TRUE(mSocket, IPC_OK());
     311           0 :   mSocket->Close();
     312           0 :   return IPC_OK();
     313             : }
     314             : 
     315             : void
     316           0 : TCPSocketParent::FireErrorEvent(const nsAString& aName, const nsAString& aType, TCPReadyState aReadyState)
     317             : {
     318           0 :   SendEvent(NS_LITERAL_STRING("error"), TCPError(nsString(aName), nsString(aType)), aReadyState);
     319           0 : }
     320             : 
     321             : void
     322           0 : TCPSocketParent::FireEvent(const nsAString& aType, TCPReadyState aReadyState)
     323             : {
     324           0 :   return SendEvent(aType, mozilla::void_t(), aReadyState);
     325             : }
     326             : 
     327             : void
     328           0 : TCPSocketParent::FireArrayBufferDataEvent(nsTArray<uint8_t>& aBuffer, TCPReadyState aReadyState)
     329             : {
     330           0 :   InfallibleTArray<uint8_t> arr;
     331           0 :   arr.SwapElements(aBuffer);
     332             : 
     333           0 :   if (mFilter) {
     334             :     bool allowed;
     335             :     mozilla::net::NetAddr addr;
     336           0 :     nsresult nsrv = mFilter->FilterPacket(&addr, arr.Elements(), arr.Length(),
     337             :                                           nsISocketFilter::SF_INCOMING,
     338           0 :                                           &allowed);
     339             :     // receiving unallowed data, drop it.
     340           0 :     if (NS_WARN_IF(NS_FAILED(nsrv)) || !allowed) {
     341           0 :       TCPSOCKET_LOG(("%s: Dropping incoming TCP packet", __FUNCTION__));
     342           0 :       return;
     343             :     }
     344             :   }
     345             : 
     346           0 :   SendableData data(arr);
     347           0 :   SendEvent(NS_LITERAL_STRING("data"), data, aReadyState);
     348             : }
     349             : 
     350             : void
     351           0 : TCPSocketParent::FireStringDataEvent(const nsACString& aData, TCPReadyState aReadyState)
     352             : {
     353           0 :   SendableData data((nsCString(aData)));
     354             : 
     355           0 :   MOZ_ASSERT(!mFilter, "Socket filtering doesn't support nsCString");
     356             : 
     357           0 :   SendEvent(NS_LITERAL_STRING("data"), data, aReadyState);
     358           0 : }
     359             : 
     360             : void
     361           0 : TCPSocketParent::SendEvent(const nsAString& aType, CallbackData aData, TCPReadyState aReadyState)
     362             : {
     363           0 :   if (mIPCOpen) {
     364           0 :     mozilla::Unused << PTCPSocketParent::SendCallback(nsString(aType),
     365             :                                                       aData,
     366           0 :                                                       static_cast<uint32_t>(aReadyState));
     367             :   }
     368           0 : }
     369             : 
     370             : void
     371           0 : TCPSocketParent::SetSocket(TCPSocket *socket)
     372             : {
     373           0 :   mSocket = socket;
     374           0 : }
     375             : 
     376             : nsresult
     377           0 : TCPSocketParent::GetHost(nsAString& aHost)
     378             : {
     379           0 :   if (!mSocket) {
     380           0 :     NS_ERROR("No internal socket instance mSocket!");
     381           0 :     return NS_ERROR_FAILURE;
     382             :   }
     383           0 :   mSocket->GetHost(aHost);
     384           0 :   return NS_OK;
     385             : }
     386             : 
     387             : nsresult
     388           0 : TCPSocketParent::GetPort(uint16_t* aPort)
     389             : {
     390           0 :   if (!mSocket) {
     391           0 :     NS_ERROR("No internal socket instance mSocket!");
     392           0 :     return NS_ERROR_FAILURE;
     393             :   }
     394           0 :   *aPort = mSocket->Port();
     395           0 :   return NS_OK;
     396             : }
     397             : 
     398             : void
     399           0 : TCPSocketParent::ActorDestroy(ActorDestroyReason why)
     400             : {
     401           0 :   if (mSocket) {
     402           0 :     mSocket->Close();
     403             :   }
     404           0 :   mSocket = nullptr;
     405           0 : }
     406             : 
     407             : mozilla::ipc::IPCResult
     408           0 : TCPSocketParent::RecvRequestDelete()
     409             : {
     410           0 :   mozilla::Unused << Send__delete__(this);
     411           0 :   return IPC_OK();
     412             : }
     413             : 
     414             : } // namespace dom
     415             : } // namespace mozilla

Generated by: LCOV version 1.13