NSAPI_PUBLIC int INTnet_buffer_input(SYS_NETFD sd, int sz)
{
    NetLayer *nl = _netlayer_find(sd);
    if (nl) {
        if (sz > nl->maxsize) {
            void *inbuf = PERM_REALLOC(nl->inbuf, sz);
            if (!inbuf)
                return -1;

            nl->inbuf = (char *) inbuf;
        }

        nl->maxsize = sz;

        return 0;
    }

    nl = (NetLayer *) PERM_MALLOC(sizeof(NetLayer));
    if (!nl)
        return -1;

    nl->pos = 0;
    nl->cursize = 0;
    nl->maxsize = sz;
    nl->inbuf = (char *) PERM_MALLOC(sz);
    if (!nl->inbuf) {
        PERM_FREE(nl);
        return -1;
    }

    PRFileDesc *layer = PR_CreateIOLayerStub(_netlayer_identity, &_netlayer_methods);
    if (!layer) {
        PERM_FREE(nl->inbuf);
        PERM_FREE(nl);
        return -1;
    }

    layer->secret = (PRFilePrivate *) nl;

    PRStatus rv = PR_PushIOLayer(sd, PR_NSPR_IO_LAYER, layer);
    if (rv != PR_SUCCESS) {
        PR_Close(layer);
        return -1;
    }

    return 0;
}
static PRInt32 PR_CALLBACK pl_DefAcceptread (
    PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf,
    PRInt32 amount, PRIntervalTime t)
{
    PRInt32 nbytes;
    PRStatus rv;
    PRFileDesc *newstack;
    PRFileDesc *layer = sd;
    PRBool newstyle_stack = PR_FALSE;

    PR_ASSERT(sd != NULL);
    PR_ASSERT(sd->lower != NULL);

    /* test for new style stack */
    while (NULL != layer->higher)
        layer = layer->higher;
    newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
    newstack = PR_NEW(PRFileDesc);
    if (NULL == newstack)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return -1;
    }
    *newstack = *sd;  /* make a copy of the accepting layer */

    nbytes = sd->lower->methods->acceptread(
                 sd->lower, nd, raddr, buf, amount, t);
    if (-1 == nbytes)
    {
        PR_DELETE(newstack);
        return nbytes;
    }
    if (newstyle_stack) {
        newstack->lower = *nd;
        (*nd)->higher = newstack;
        *nd = newstack;
        return nbytes;
    } else {
        /* this PR_PushIOLayer call cannot fail */
        rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
        PR_ASSERT(PR_SUCCESS == rv);
        return nbytes;
    }
}
Exemple #3
0
static PRFileDesc * PR_CALLBACK MyAccept(
    PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
{
    PRStatus rv;
    PRFileDesc *newfd, *layer = fd;
    PRFileDesc *newstack;
    PRFilePrivate *newsecret;

    PR_ASSERT(fd != NULL);
    PR_ASSERT(fd->lower != NULL);

    newstack = PR_NEW(PRFileDesc);
    if (NULL == newstack)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }
    newsecret = PR_NEW(PRFilePrivate);
    if (NULL == newsecret)
    {
        PR_DELETE(newstack);
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }
    *newstack = *fd;  /* make a copy of the accepting layer */
    *newsecret = *fd->secret;
    newstack->secret = newsecret;

    newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
    if (NULL == newfd)
    {
        PR_DELETE(newsecret);
        PR_DELETE(newstack);
        return NULL;
    }

    /* this PR_PushIOLayer call cannot fail */
    rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
    PR_ASSERT(PR_SUCCESS == rv);
    return newfd;  /* that's it */
}
static PRFileDesc* PR_CALLBACK pl_TopAccept (
    PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
{
    PRStatus rv;
    PRFileDesc *newfd, *layer = fd;
    PRFileDesc *newstack;
    PRBool newstyle_stack = PR_FALSE;

    PR_ASSERT(fd != NULL);
    PR_ASSERT(fd->lower != NULL);

    /* test for new style stack */
    while (NULL != layer->higher)
        layer = layer->higher;
    newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE;
    newstack = PR_NEW(PRFileDesc);
    if (NULL == newstack)
    {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return NULL;
    }
    *newstack = *fd;  /* make a copy of the accepting layer */

    newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout);
    if (NULL == newfd)
    {
        PR_DELETE(newstack);
        return NULL;
    }

    if (newstyle_stack) {
        newstack->lower = newfd;
        newfd->higher = newstack;
        return newstack;
    } else {
        /* this PR_PushIOLayer call cannot fail */
        rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
        PR_ASSERT(PR_SUCCESS == rv);
        return newfd;  /* that's it */
    }
}
static void AcceptingThread(void *arg)
{
    PRStatus rv;
    PRInt32 bytes;
    PRSize buf_size = BUF_SIZE;
    PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32];
    PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg;
    PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket();
    PRFileDesc *layer;
    PRSocketOptionData sock_opt;

    if (NULL == listen_sock)
    {
        PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed");
        PR_ProcessExit(1);        
    }
    layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods);
    if (NULL == layer)
    {
        PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed");
        PR_ProcessExit(1);        
    }
    if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE)
    {
        PL_FPrintError(err_out, "PR_PushIOLayer (server) failed");
        PR_ProcessExit(1);        
    }
    sock_opt.option = PR_SockOpt_Reuseaddr;
    sock_opt.value.reuse_addr = PR_TRUE;
    rv = PR_SetSocketOption(listen_sock, &sock_opt);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_SetSocketOption (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Bind(listen_sock, listen_addr);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Bind (server) failed");
        PR_ProcessExit(1);        
    }
    rv = PR_Listen(listen_sock, 10);
    if (PR_FAILURE == rv)
    {
        PL_FPrintError(err_out, "PR_Listen (server) failed");
        PR_ProcessExit(1);        
    }
    bytes = PR_AcceptRead(
        listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout);

    if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed");
    else
    {
        PrintAddress(accept_addr);
        PR_fprintf(
            std_out, "(Server) read [0x%p..0x%p) %s\n",
            buf, &buf[BUF_SIZE], buf);
        bytes = PR_Write(accept_sock, buf, bytes);
        rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Shutdown (server) failed");
    }

    if (-1 != bytes)
    {
        rv = PR_Close(accept_sock);
        if (PR_FAILURE == rv)
            PL_FPrintError(err_out, "PR_Close (server) failed");
    }

    rv = PR_Close(listen_sock);
    if (PR_FAILURE == rv)
        PL_FPrintError(err_out, "PR_Close (server) failed");
}  /* AcceptingThread */
// add SOCKS IO layer to an existing socket
nsresult
nsSOCKSIOLayerAddToSocket(int32_t family,
                          const char *host, 
                          int32_t port,
                          const char *proxyHost,
                          int32_t proxyPort,
                          int32_t socksVersion,
                          uint32_t flags,
                          PRFileDesc *fd, 
                          nsISupports** info)
{
    NS_ENSURE_TRUE((socksVersion == 4) || (socksVersion == 5), NS_ERROR_NOT_INITIALIZED);


    if (firstTime)
    {
        //XXX hack until NSPR provides an official way to detect system IPv6
        // support (bug 388519)
        PRFileDesc *tmpfd = PR_OpenTCPSocket(PR_AF_INET6);
        if (!tmpfd) {
            ipv6Supported = false;
        } else {
            // If the system does not support IPv6, NSPR will push
            // IPv6-to-IPv4 emulation layer onto the native layer
            ipv6Supported = PR_GetIdentitiesLayer(tmpfd, PR_NSPR_IO_LAYER) == tmpfd;
            PR_Close(tmpfd);
        }

        nsSOCKSIOLayerIdentity		= PR_GetUniqueIdentity("SOCKS layer");
        nsSOCKSIOLayerMethods		= *PR_GetDefaultIOMethods();

        nsSOCKSIOLayerMethods.connect	= nsSOCKSIOLayerConnect;
        nsSOCKSIOLayerMethods.connectcontinue	= nsSOCKSIOLayerConnectContinue;
        nsSOCKSIOLayerMethods.poll	= nsSOCKSIOLayerPoll;
        nsSOCKSIOLayerMethods.bind	= nsSOCKSIOLayerBind;
        nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
        nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
        nsSOCKSIOLayerMethods.getpeername = nsSOCKSIOLayerGetPeerName;
        nsSOCKSIOLayerMethods.accept	= nsSOCKSIOLayerAccept;
        nsSOCKSIOLayerMethods.listen	= nsSOCKSIOLayerListen;
        nsSOCKSIOLayerMethods.close	= nsSOCKSIOLayerClose;

        firstTime			= false;

#if defined(PR_LOGGING)
        gSOCKSLog = PR_NewLogModule("SOCKS");
#endif

    }

    LOGDEBUG(("Entering nsSOCKSIOLayerAddToSocket()."));

    PRFileDesc *	layer;
    PRStatus	rv;

    layer = PR_CreateIOLayerStub(nsSOCKSIOLayerIdentity, &nsSOCKSIOLayerMethods);
    if (! layer)
    {
        LOGERROR(("PR_CreateIOLayerStub() failed."));
        return NS_ERROR_FAILURE;
    }

    nsSOCKSSocketInfo * infoObject = new nsSOCKSSocketInfo();
    if (!infoObject)
    {
        // clean up IOLayerStub
        LOGERROR(("Failed to create nsSOCKSSocketInfo()."));
        PR_DELETE(layer);
        return NS_ERROR_FAILURE;
    }

    NS_ADDREF(infoObject);
    infoObject->Init(socksVersion, family, proxyHost, proxyPort, host, flags);
    layer->secret = (PRFilePrivate*) infoObject;
    rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);

    if (rv == PR_FAILURE) {
        LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
        NS_RELEASE(infoObject);
        PR_DELETE(layer);
        return NS_ERROR_FAILURE;
    }

    *info = static_cast<nsISOCKSSocketInfo*>(infoObject);
    NS_ADDREF(*info);
    return NS_OK;
}
NS_IMETHODIMP
nsWINCESSLSocketProvider::NewSocket(PRInt32 family,
                                    const char *host, 
                                    PRInt32 port,
                                    const char *proxyHost,
                                    PRInt32 proxyPort,
                                    PRUint32 flags,
                                    PRFileDesc **result, 
                                    nsISupports **socksInfo)
{
  static PRBool firstTime = PR_TRUE;
  if (firstTime)  {
    
    nsWINCESSLIOLayerIdentity		     = PR_GetUniqueIdentity("WINCESSL layer");
    nsWINCESSLIOLayerMethods		     = *PR_GetDefaultIOMethods();
    
    nsWINCESSLIOLayerMethods.connect   = nsWINCESSLIOLayerConnect;
    nsWINCESSLIOLayerMethods.close     = nsWINCESSLIOLayerClose;
    nsWINCESSLIOLayerMethods.available = nsWINCESSLIOLayerAvailable;
    nsWINCESSLIOLayerMethods.write     = nsWINCESSLIOLayerWrite;
    nsWINCESSLIOLayerMethods.read      = nsWINCESSLIOLayerRead;
    nsWINCESSLIOLayerMethods.poll      = nsWINCESSLIOLayerPoll;

    firstTime = PR_FALSE;
  }
  
  PRFileDesc *fd = PR_OpenTCPSocket(family);
  if (!fd)
    return NS_ERROR_OUT_OF_MEMORY;
  
  PRFileDesc *	layer;
  PRStatus	rv;
  
  layer = PR_CreateIOLayerStub(nsWINCESSLIOLayerIdentity, &nsWINCESSLIOLayerMethods);
  if (! layer)
    return NS_ERROR_UNEXPECTED;
  
  nsWINCESSLSocketInfo * infoObject = new nsWINCESSLSocketInfo();
  if (!infoObject)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(infoObject);

  layer->secret = (PRFilePrivate*) infoObject;
  rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
  if (NS_FAILED(rv))
    return NS_ERROR_UNEXPECTED;
  
  
  nsresult initrv = infoObject->Init(host, proxyHost, proxyPort);
  if (NS_FAILED(initrv))
  {
    MessageBox(0, "Can not create ssl socket.", "Can not create ssl socket.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
    return NS_ERROR_FAILURE;
  }

  *result    = fd;
  *socksInfo = (nsISupports*) (nsITransportSecurityInfo*) infoObject;
  return NS_OK;

}
PollableEvent::PollableEvent()
  : mWriteFD(nullptr)
  , mReadFD(nullptr)
  , mSignaled(false)
{
  MOZ_COUNT_CTOR(PollableEvent);
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
  // create pair of prfiledesc that can be used as a poll()ble
  // signal. on windows use a localhost socket pair, and on
  // unix use a pipe.
#ifdef USEPIPE
  SOCKET_LOG(("PollableEvent() using pipe\n"));
  if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) {
    // make the pipe non blocking. NSPR asserts at
    // trying to use SockOpt here
    PROsfd fd = PR_FileDesc2NativeHandle(mReadFD);
    int flags = fcntl(fd, F_GETFL, 0);
    (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    fd = PR_FileDesc2NativeHandle(mWriteFD);
    flags = fcntl(fd, F_GETFL, 0);
    (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  } else {
    mReadFD = nullptr;
    mWriteFD = nullptr;
    SOCKET_LOG(("PollableEvent() pipe failed\n"));
  }
#else
  SOCKET_LOG(("PollableEvent() using socket pair\n"));
  PRFileDesc *fd[2];
  LazyInitSocket();

  // Try with a increased recv buffer first (bug 1248358).
  if (NewTCPSocketPair(fd, true)) {
    mReadFD = fd[0];
    mWriteFD = fd[1];
  // If the previous fails try without recv buffer increase (bug 1305436).
  } else if (NewTCPSocketPair(fd, false)) {
    mReadFD = fd[0];
    mWriteFD = fd[1];
  // If both fail, try the old version.
  } else if (PR_NewTCPSocketPair(fd) == PR_SUCCESS) {
    mReadFD = fd[0];
    mWriteFD = fd[1];

    PRSocketOptionData socket_opt;
    DebugOnly<PRStatus> status;
    socket_opt.option = PR_SockOpt_NoDelay;
    socket_opt.value.no_delay = true;
    PR_SetSocketOption(mWriteFD, &socket_opt);
    PR_SetSocketOption(mReadFD, &socket_opt);
    socket_opt.option = PR_SockOpt_Nonblocking;
    socket_opt.value.non_blocking = true;
    status = PR_SetSocketOption(mWriteFD, &socket_opt);
    MOZ_ASSERT(status == PR_SUCCESS);
    status = PR_SetSocketOption(mReadFD, &socket_opt);
    MOZ_ASSERT(status == PR_SUCCESS);
  }

  if (mReadFD && mWriteFD) {
    // compatibility with LSPs such as McAfee that assume a NSPR
    // layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop.
    PRFileDesc *topLayer =
      PR_CreateIOLayerStub(sPollableEventLayerIdentity,
                           sPollableEventLayerMethodsPtr);
    if (topLayer) {
      if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) {
        topLayer->dtor(topLayer);
      } else {
        SOCKET_LOG(("PollableEvent() nspr layer ok\n"));
        mReadFD = topLayer;
      }
    }

  } else {
    SOCKET_LOG(("PollableEvent() socketpair failed\n"));
  }
#endif

  if (mReadFD && mWriteFD) {
    // prime the system to deal with races invovled in [dc]tor cycle
    SOCKET_LOG(("PollableEvent() ctor ok\n"));
    mSignaled = true;
    PR_Write(mWriteFD, "I", 1);
  }
}