Commit 2e3f6cb3 authored by Liang-Heng Chen's avatar Liang-Heng Chen
Browse files

Bug 1288308 - Part 2: implement Named Pipe IO layer; r=bagder,mayhemer

MozReview-Commit-ID: 85MbD0QFRRq
parent 901781de
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,15 @@ static PRDescIdentity sWinSockShutdownLayerIdentity;
static PRIOMethods sWinSockShutdownLayerMethods;
static PRIOMethods sWinSockShutdownLayerMethods;
static PRIOMethods *sWinSockShutdownLayerMethodsPtr = nullptr;
static PRIOMethods *sWinSockShutdownLayerMethodsPtr = nullptr;


namespace mozilla {
namespace net {

extern PRDescIdentity nsNamedPipeLayerIdentity;

} // namespace net
} // namespace mozilla


PRStatus
PRStatus
WinSockClose(PRFileDesc *aFd)
WinSockClose(PRFileDesc *aFd)
{
{
@@ -45,6 +54,13 @@ nsresult mozilla::net::AttachShutdownLayer(PRFileDesc *aFd)
    sWinSockShutdownLayerMethodsPtr = &sWinSockShutdownLayerMethods;
    sWinSockShutdownLayerMethodsPtr = &sWinSockShutdownLayerMethods;
  }
  }


  if (mozilla::net::nsNamedPipeLayerIdentity &&
      PR_GetIdentitiesLayer(aFd, mozilla::net::nsNamedPipeLayerIdentity)) {
    // Do not attach shutdown layer on named pipe layer,
    // it is for PR_NSPR_IO_LAYER only.
    return NS_OK;
  }

  PRFileDesc * layer;
  PRFileDesc * layer;
  PRStatus     status;
  PRStatus     status;


+5 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,10 @@ XPIDL_SOURCES += [


XPIDL_MODULE = 'necko_socket'
XPIDL_MODULE = 'necko_socket'


LOCAL_INCLUDES += [
    '/netwerk/base',
]

UNIFIED_SOURCES += [
UNIFIED_SOURCES += [
    'nsSocketProviderService.cpp',
    'nsSocketProviderService.cpp',
    'nsSOCKSIOLayer.cpp',
    'nsSOCKSIOLayer.cpp',
@@ -26,6 +30,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
        'nsINamedPipeService.idl',
        'nsINamedPipeService.idl',
    ]
    ]
    UNIFIED_SOURCES += [
    UNIFIED_SOURCES += [
        'nsNamedPipeIOLayer.cpp',
        'nsNamedPipeService.cpp'
        'nsNamedPipeService.cpp'
    ]
    ]


+952 −0

File added.

Preview size limit exceeded, changes collapsed.

+23 −0
Original line number Original line Diff line number Diff line
/* -*- 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_netwerk_socket_nsNamedPipeIOLayer_h
#define mozilla_netwerk_socket_nsNamedPipeIOLayer_h

#include "nscore.h"
#include "prio.h"

namespace mozilla {
namespace net {

bool IsNamedPipePath(const nsACString& aPath);
PRFileDesc* CreateNamedPipeLayer();

extern PRDescIdentity nsNamedPipeLayerIdentity;

} // namespace net
} // namespace mozilla

#endif // mozilla_netwerk_socket_nsNamedPipeIOLayer_h
+55 −3
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
#include "nsIDNSRecord.h"
#include "nsIDNSRecord.h"
#include "nsISOCKSSocketInfo.h"
#include "nsISOCKSSocketInfo.h"
#include "nsISocketProvider.h"
#include "nsISocketProvider.h"
#include "nsNamedPipeIOLayer.h"
#include "nsSOCKSIOLayer.h"
#include "nsSOCKSIOLayer.h"
#include "nsNetCID.h"
#include "nsNetCID.h"
#include "nsIDNSListener.h"
#include "nsIDNSListener.h"
@@ -84,9 +85,14 @@ public:
    int16_t GetPollFlags() const;
    int16_t GetPollFlags() const;
    bool IsConnected() const { return mState == SOCKS_CONNECTED; }
    bool IsConnected() const { return mState == SOCKS_CONNECTED; }
    void ForgetFD() { mFD = nullptr; }
    void ForgetFD() { mFD = nullptr; }
    void SetNamedPipeFD(PRFileDesc *fd) { mFD = fd; }


private:
private:
    virtual ~nsSOCKSSocketInfo() { HandshakeFinished(); }
    virtual ~nsSOCKSSocketInfo()
    {
        ForgetFD();
        HandshakeFinished();
    }


    void HandshakeFinished(PRErrorCode err = 0);
    void HandshakeFinished(PRErrorCode err = 0);
    PRStatus StartDNS(PRFileDesc *fd);
    PRStatus StartDNS(PRFileDesc *fd);
@@ -179,6 +185,20 @@ private:
#endif
#endif
    }
    }


    bool
    SetupNamedPipeLayer(PRFileDesc *fd)
    {
#if defined(XP_WIN)
        if (IsLocalProxy()) {
            // nsSOCKSIOLayer handshaking only works under blocking mode
            // unfortunately. Remember named pipe's FD to switch between modes.
            SetNamedPipeFD(fd->lower);
            return true;
        }
#endif
        return false;
    }

private:
private:
    State     mState;
    State     mState;
    uint8_t * mData;
    uint8_t * mData;
@@ -405,6 +425,14 @@ nsSOCKSSocketInfo::HandshakeFinished(PRErrorCode err)
{
{
    if (err == 0) {
    if (err == 0) {
        mState = SOCKS_CONNECTED;
        mState = SOCKS_CONNECTED;
        // Switch back to nonblocking mode after finishing handshaking.
        if (mFD) {
            PRSocketOptionData opt_nonblock;
            opt_nonblock.option = PR_SockOpt_Nonblocking;
            opt_nonblock.value.non_blocking = PR_TRUE;
            PR_SetSocketOption(mFD, &opt_nonblock);
            mFD = nullptr;
        }
    } else {
    } else {
        mState = SOCKS_FAILED;
        mState = SOCKS_FAILED;
        PR_SetError(PR_UNKNOWN_ERROR, err);
        PR_SetError(PR_UNKNOWN_ERROR, err);
@@ -545,6 +573,14 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
        }
        }
    } while (status != PR_SUCCESS);
    } while (status != PR_SUCCESS);


    // Switch to blocking mode during handshaking
    if (mFD) {
        PRSocketOptionData opt_nonblock;
        opt_nonblock.option = PR_SockOpt_Nonblocking;
        opt_nonblock.value.non_blocking = PR_FALSE;
        PR_SetSocketOption(mFD, &opt_nonblock);
    }

    // Connected now, start SOCKS
    // Connected now, start SOCKS
    if (mVersion == 4)
    if (mVersion == 4)
        return WriteV4ConnectRequest();
        return WriteV4ConnectRequest();
@@ -577,11 +613,18 @@ nsSOCKSSocketInfo::FixupAddressFamily(PRFileDesc *fd, NetAddr *proxy)
        // mDestinationFamily should not be updated
        // mDestinationFamily should not be updated
        return;
        return;
    }
    }
    // There's no PR_NSPR_IO_LAYER required when using named pipe,
    // we simply ignore the TCP family here.
    if (SetupNamedPipeLayer(fd)) {
        return;
    }

    // Get an OS native handle from a specified FileDesc
    // Get an OS native handle from a specified FileDesc
    PROsfd osfd = PR_FileDesc2NativeHandle(fd);
    PROsfd osfd = PR_FileDesc2NativeHandle(fd);
    if (osfd == -1) {
    if (osfd == -1) {
        return;
        return;
    }
    }

    // Create a new FileDesc with a specified family
    // Create a new FileDesc with a specified family
    PRFileDesc *tmpfd = PR_OpenTCPSocket(proxyFamily);
    PRFileDesc *tmpfd = PR_OpenTCPSocket(proxyFamily);
    if (!tmpfd) {
    if (!tmpfd) {
@@ -1529,7 +1572,16 @@ nsSOCKSIOLayerAddToSocket(int32_t family,
    NS_ADDREF(infoObject);
    NS_ADDREF(infoObject);
    infoObject->Init(socksVersion, family, proxy, host, flags);
    infoObject->Init(socksVersion, family, proxy, host, flags);
    layer->secret = (PRFilePrivate*) infoObject;
    layer->secret = (PRFilePrivate*) infoObject;
    rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);

    PRDescIdentity fdIdentity = PR_GetLayersIdentity(fd);
#if defined(XP_WIN)
    if (fdIdentity == mozilla::net::nsNamedPipeLayerIdentity) {
        // remember named pipe fd on the info object so that we can switch
        // blocking and non-blocking mode on the pipe later.
        infoObject->SetNamedPipeFD(fd);
    }
#endif
    rv = PR_PushIOLayer(fd, fdIdentity, layer);


    if (rv == PR_FAILURE) {
    if (rv == PR_FAILURE) {
        LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
        LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
@@ -1549,7 +1601,7 @@ IsHostLocalTarget(const nsACString& aHost)
#if defined(XP_UNIX)
#if defined(XP_UNIX)
    return StringBeginsWith(aHost, NS_LITERAL_CSTRING("file:"));
    return StringBeginsWith(aHost, NS_LITERAL_CSTRING("file:"));
#elif defined(XP_WIN)
#elif defined(XP_WIN)
    return StringBeginsWith(aHost, NS_LITERAL_CSTRING("\\\\.\\pipe\\"));
    return IsNamedPipePath(aHost);
#else
#else
    return false;
    return false;
#endif // XP_UNIX
#endif // XP_UNIX
Loading