NS_IMETHODIMP
nsSOCKSSocketProvider::NewSocket(PRInt32 family,
                                 const char *host, 
                                 PRInt32 port,
                                 const char *proxyHost,
                                 PRInt32 proxyPort,
                                 PRUint32 flags,
                                 PRFileDesc **result, 
                                 nsISupports **socksInfo)
{
    PRFileDesc *sock;
    
    sock = PR_OpenTCPSocket(family);
    if (!sock)
        return NS_ERROR_OUT_OF_MEMORY;

    nsresult rv = nsSOCKSIOLayerAddToSocket(family,
                                            host, 
                                            port,
                                            proxyHost,
                                            proxyPort,
                                            mVersion,
                                            flags,
                                            sock, 
                                            socksInfo);
    if (NS_SUCCEEDED(rv)) {
        *result = sock;
        return NS_OK;
    }

    return NS_ERROR_SOCKET_CREATE_FAILED;
}
예제 #2
0
void
nsSOCKSSocketInfo::FixupAddressFamily(PRFileDesc *fd, PRNetAddr *proxy)
{
    int32_t proxyFamily = PR_NetAddrFamily(&mInternalProxyAddr);
    // Do nothing if the address family is already matched
    if (proxyFamily == mDestinationFamily) {
        return;
    }
    // If the system does not support IPv6 and the proxy address is IPv6,
    // We can do nothing here.
    if (proxyFamily == PR_AF_INET6 && !ipv6Supported) {
        return;
    }
    // If the system does not support IPv6 and the destination address is
    // IPv6, convert IPv4 address to IPv4-mapped IPv6 address to satisfy
    // the emulation layer
    if (mDestinationFamily == PR_AF_INET6 && !ipv6Supported) {
        proxy->ipv6.family = PR_AF_INET6;
        proxy->ipv6.port = mInternalProxyAddr.inet.port;
        uint8_t *proxyp = proxy->ipv6.ip.pr_s6_addr;
        memset(proxyp, 0, 10);
        memset(proxyp + 10, 0xff, 2);
        memcpy(proxyp + 12,(char *) &mInternalProxyAddr.inet.ip, 4);
        // mDestinationFamily should not be updated
        return;
    }
    // Get an OS native handle from a specified FileDesc
    PROsfd osfd = PR_FileDesc2NativeHandle(fd);
    if (osfd == -1) {
        return;
    }
    // Create a new FileDesc with a specified family
    PRFileDesc *tmpfd = PR_OpenTCPSocket(proxyFamily);
    if (!tmpfd) {
        return;
    }
    PROsfd newsd = PR_FileDesc2NativeHandle(tmpfd);
    if (newsd == -1) {
        PR_Close(tmpfd);
        return;
    }
    // Must succeed because PR_FileDesc2NativeHandle succeeded
    fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER);
    MOZ_ASSERT(fd);
    // Swap OS native handles
    PR_ChangeFileDescNativeHandle(fd, newsd);
    PR_ChangeFileDescNativeHandle(tmpfd, osfd);
    // Close temporary FileDesc which is now associated with
    // old OS native handle
    PR_Close(tmpfd);
    mDestinationFamily = proxyFamily;
}
예제 #3
0
nsresult
TryConnect(PRFileDesc **result)
{
    PRFileDesc *fd;
    PRNetAddr addr;
    PRSocketOptionData opt;
    nsresult rv = NS_ERROR_FAILURE;

    fd = PR_OpenTCPSocket(PR_AF_LOCAL);
    if (!fd)
        goto end;

    addr.local.family = PR_AF_LOCAL;
    IPC_GetDefaultSocketPath(addr.local.path, sizeof(addr.local.path));

    // blocking connect... will fail if no one is listening.
    if (PR_Connect(fd, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE)
        goto end;

#ifdef VBOX
    if (PR_GetEnv("TESTBOX_UUID"))
        fprintf(stderr, "IPC socket path: %s\n", addr.local.path);
    LogRel(("IPC socket path: %s\n", addr.local.path));
#endif

    // make socket non-blocking
    opt.option = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_TRUE;
    PR_SetSocketOption(fd, &opt);

    // do some security checks on connection socket...
    if (DoSecurityCheck(fd, addr.local.path) != PR_SUCCESS)
        goto end;

    *result = fd;
    return NS_OK;

end:
    if (fd)
        PR_Close(fd);

    return rv;
}
int main(int argc, char **argv)
{
    PRFileDesc *listenSock;
    PRNetAddr addr;
    PRUint16 port;

    listenSock = PR_OpenTCPSocket(PR_AF_INET6);
    if (NULL == listenSock) {
        fprintf(stderr, "PR_OpenTCPSocket failed\n");
        exit(1);
    }
    memset(&addr, 0, sizeof(addr));
    if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
        fprintf(stderr, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_Bind(listenSock, &addr) == PR_FAILURE) {
        fprintf(stderr, "PR_Bind failed\n");
        exit(1);
    }
    if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) {
        fprintf(stderr, "PR_GetSockName failed\n");
        exit(1);
    }
    port = PR_ntohs(addr.ipv6.port);
    if (PR_Listen(listenSock, 5) == PR_FAILURE) {
        fprintf(stderr, "PR_Listen failed\n");
        exit(1);
    }

    fprintf(stderr, "Running the test with local threads\n");
    RunTest(PR_LOCAL_THREAD, listenSock, port);
    fprintf(stderr, "Running the test with global threads\n");
    RunTest(PR_GLOBAL_THREAD, listenSock, port);

    if (PR_Close(listenSock) == PR_FAILURE) {
        fprintf(stderr, "PR_Close failed\n");
        exit(1);
    }
    printf("PASS\n");
    return 0;
}
예제 #5
0
/** Create socket. If ssl is >0, socket is ssl enabled.
  @param ssl Enable ssl (Client, SSL2+3, no TLS, compatible hello) if PR_TRUE, otherwise no.
  @param ipv6 New socket will be IPv4 if this value is 0, otherwise it will be ipv6
  @return NULL on error, otherwise socket.
*/
static PRFileDesc *create_socket(int ssl,int ipv6) {
  PRFileDesc *res_socket;

  res_socket=PR_OpenTCPSocket((ipv6?PR_AF_INET6:PR_AF_INET));
  if (res_socket==NULL) {
    print_nspr_error();

    return NULL;
  }

  if (!ssl) return res_socket;

  if (!(res_socket=SSL_ImportFD(NULL,res_socket))) {
    print_nspr_error();

    return NULL;
  }

  if ((SSL_OptionSet(res_socket,SSL_SECURITY,ssl)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_HANDSHAKE_AS_SERVER,PR_FALSE)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_HANDSHAKE_AS_CLIENT,PR_TRUE)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_ENABLE_SSL2,ssl)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_ENABLE_SSL3,ssl)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_ENABLE_TLS,PR_FALSE)!=SECSuccess) ||
      (SSL_OptionSet(res_socket,SSL_V2_COMPATIBLE_HELLO,ssl)!=SECSuccess) ||
      (SSL_SetPKCS11PinArg(res_socket,NULL)==-1) ||
      (SSL_AuthCertificateHook(res_socket,SSL_AuthCertificate,CERT_GetDefaultCertDB())!=SECSuccess) ||
      (SSL_BadCertHook(res_socket,nss_bad_cert_hook,NULL)!=SECSuccess)) {
    print_nspr_error();

    if (PR_Close(res_socket)!=PR_SUCCESS) {
      print_nspr_error();
    }

    return NULL;
  }

  return res_socket;
}
void
nsSocketTransportService::ProbeMaxCount()
{
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");

    if (mProbedMaxCount)
        return;
    mProbedMaxCount = true;

    // Allocate and test a PR_Poll up to the gMaxCount number of unconnected
    // sockets. See bug 692260 - windows should be able to handle 1000 sockets
    // in select() without a problem, but LSPs have been known to balk at lower
    // numbers. (64 in the bug).

    // Allocate
    struct PRPollDesc pfd[SOCKET_LIMIT_TARGET];
    uint32_t numAllocated = 0;

    for (uint32_t index = 0 ; index < gMaxCount; ++index) {
        pfd[index].in_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT;
        pfd[index].out_flags = 0;
        pfd[index].fd =  PR_OpenTCPSocket(PR_AF_INET);
        if (!pfd[index].fd) {
            SOCKET_LOG(("Socket Limit Test index %d failed\n", index));
            if (index < SOCKET_LIMIT_MIN)
                gMaxCount = SOCKET_LIMIT_MIN;
            else
                gMaxCount = index;
            break;
        }
        ++numAllocated;
    }

    // Test
    PR_STATIC_ASSERT(SOCKET_LIMIT_MIN >= 32U);
    while (gMaxCount <= numAllocated) {
        int32_t rv = PR_Poll(pfd, gMaxCount, PR_MillisecondsToInterval(0));
        
        SOCKET_LOG(("Socket Limit Test poll() size=%d rv=%d\n",
                    gMaxCount, rv));

        if (rv >= 0)
            break;

        SOCKET_LOG(("Socket Limit Test poll confirmationSize=%d rv=%d error=%d\n",
                    gMaxCount, rv, PR_GetError()));

        gMaxCount -= 32;
        if (gMaxCount <= SOCKET_LIMIT_MIN) {
            gMaxCount = SOCKET_LIMIT_MIN;
            break;
        }
    }

    // Free
    for (uint32_t index = 0 ; index < numAllocated; ++index)
        if (pfd[index].fd)
            PR_Close(pfd[index].fd);

    Telemetry::Accumulate(Telemetry::NETWORK_PROBE_MAXCOUNT, gMaxCount);
    SOCKET_LOG(("Socket Limit Test max was confirmed at %d\n", gMaxCount));
}
예제 #7
0
static bool NewTCPSocketPair(PRFileDesc *fd[])
{
  // this is a replacement for PR_NewTCPSocketPair that manually
  // sets the recv buffer to 64K. A windows bug (1248358)
  // can result in using an incompatible rwin and window
  // scale option on localhost pipes if not set before connect.

  PRFileDesc *listener = nullptr;
  PRFileDesc *writer = nullptr;
  PRFileDesc *reader = nullptr;
  PRSocketOptionData recvBufferOpt;
  recvBufferOpt.option = PR_SockOpt_RecvBufferSize;
  recvBufferOpt.value.recv_buffer_size = 65535;

  PRSocketOptionData nodelayOpt;
  nodelayOpt.option = PR_SockOpt_NoDelay;
  nodelayOpt.value.no_delay = true;

  PRSocketOptionData noblockOpt;
  noblockOpt.option = PR_SockOpt_Nonblocking;
  noblockOpt.value.non_blocking = true;

  listener = PR_OpenTCPSocket(PR_AF_INET);
  if (!listener) {
    goto failed;
  }
  PR_SetSocketOption(listener, &recvBufferOpt);
  PR_SetSocketOption(listener, &nodelayOpt);

  PRNetAddr listenAddr;
  memset(&listenAddr, 0, sizeof(listenAddr));
  if ((PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &listenAddr) == PR_FAILURE) ||
      (PR_Bind(listener, &listenAddr) == PR_FAILURE) ||
      (PR_GetSockName(listener, &listenAddr) == PR_FAILURE) || // learn the dynamic port
      (PR_Listen(listener, 5) == PR_FAILURE)) {
    goto failed;
  }

  writer = PR_OpenTCPSocket(PR_AF_INET);
  if (!writer) {
    goto failed;
  }
  PR_SetSocketOption(writer, &recvBufferOpt);
  PR_SetSocketOption(writer, &nodelayOpt);
  PR_SetSocketOption(writer, &noblockOpt);
  PRNetAddr writerAddr;
  if (PR_InitializeNetAddr(PR_IpAddrLoopback, ntohs(listenAddr.inet.port), &writerAddr) == PR_FAILURE) {
    goto failed;
  }

  if (PR_Connect(writer, &writerAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
    if ((PR_GetError() != PR_IN_PROGRESS_ERROR) ||
        (PR_ConnectContinue(writer, PR_POLL_WRITE) == PR_FAILURE)) {
      goto failed;
    }
  }

  reader = PR_Accept(listener, &listenAddr, PR_INTERVAL_NO_TIMEOUT);
  if (!reader) {
    goto failed;
  }
  PR_SetSocketOption(reader, &recvBufferOpt);
  PR_SetSocketOption(reader, &nodelayOpt);
  PR_SetSocketOption(reader, &noblockOpt);
  PR_Close(listener);

  fd[0] = reader;
  fd[1] = writer;
  return true;

failed:
  if (listener) {
    PR_Close(listener);
  }
  if (reader) {
    PR_Close(reader);
  }
  if (writer) {
    PR_Close(writer);
  }
  return false;
}
예제 #8
0
// 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;
}
예제 #9
0
NS_IMETHODIMP
nsServerSocket::InitWithAddress(const PRNetAddr *aAddr, int32_t aBackLog)
{
  NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
  nsresult rv;

  //
  // configure listening socket...
  //

  mFD = PR_OpenTCPSocket(aAddr->raw.family);
  if (!mFD)
  {
    NS_WARNING("unable to create server socket");
    return ErrorAccordingToNSPR(PR_GetError());
  }

  PRSocketOptionData opt;

  opt.option = PR_SockOpt_Reuseaddr;
  opt.value.reuse_addr = true;
  PR_SetSocketOption(mFD, &opt);

  opt.option = PR_SockOpt_Nonblocking;
  opt.value.non_blocking = true;
  PR_SetSocketOption(mFD, &opt);

  if (PR_Bind(mFD, aAddr) != PR_SUCCESS)
  {
    NS_WARNING("failed to bind socket");
    goto fail;
  }

  if (aBackLog < 0)
    aBackLog = 5; // seems like a reasonable default

  if (PR_Listen(mFD, aBackLog) != PR_SUCCESS)
  {
    NS_WARNING("cannot listen on socket");
    goto fail;
  }

  // get the resulting socket address, which may be different than what
  // we passed to bind.
  if (PR_GetSockName(mFD, &mAddr) != PR_SUCCESS)
  {
    NS_WARNING("cannot get socket name");
    goto fail;
  }

  // Set any additional socket defaults needed by child classes
  rv = SetSocketDefaults();
  if (NS_WARN_IF(NS_FAILED(rv))) {
    goto fail;
  }

  // wait until AsyncListen is called before polling the socket for
  // client connections.
  return NS_OK;

fail:
  rv = ErrorAccordingToNSPR(PR_GetError());
  Close();
  return rv;
}
예제 #10
0
NS_IMETHODIMP
nsServerSocket::InitWithAddress(const PRNetAddr *aAddr, PRInt32 aBackLog)
{
  NS_ENSURE_TRUE(mFD == nsnull, NS_ERROR_ALREADY_INITIALIZED);

  if (!mLock)
  {
    mLock = PR_NewLock();
    if (!mLock)
      return NS_ERROR_OUT_OF_MEMORY;
  }

  //
  // configure listening socket...
  //

  mFD = PR_OpenTCPSocket(aAddr->raw.family);
  if (!mFD)
  {
    NS_WARNING("unable to create server socket");
    return NS_ERROR_FAILURE;
  }

  PRSocketOptionData opt;

  opt.option = PR_SockOpt_Reuseaddr;
  opt.value.reuse_addr = PR_TRUE;
  PR_SetSocketOption(mFD, &opt);

  opt.option = PR_SockOpt_Nonblocking;
  opt.value.non_blocking = PR_TRUE;
  PR_SetSocketOption(mFD, &opt);

  if (PR_Bind(mFD, aAddr) != PR_SUCCESS)
  {
    NS_WARNING("failed to bind socket");
    goto fail;
  }

  if (aBackLog < 0)
    aBackLog = 5; // seems like a reasonable default

  if (PR_Listen(mFD, aBackLog) != PR_SUCCESS)
  {
    NS_WARNING("cannot listen on socket");
    goto fail;
  }

  // get the resulting socket address, which may be different than what
  // we passed to bind.
  if (PR_GetSockName(mFD, &mAddr) != PR_SUCCESS)
  {
    NS_WARNING("cannot get socket name");
    goto fail;
  }

  // wait until AsyncListen is called before polling the socket for
  // client connections.
  return NS_OK;

fail:
  Close();
  return NS_ERROR_FAILURE;
}
/* Non-blocking I/O */
static void ClientNB(void *arg)
{
    PRFileDesc *sock;
    PRSocketOptionData opt;
    PRUint16 port = (PRUint16) arg;
    PRNetAddr addr;
    char buf[BUFFER_SIZE];
    PRPollDesc pd;
    PRInt32 npds;
    PRInt32 nbytes;
    int i;
    int j;

    sock = PR_OpenTCPSocket(PR_AF_INET6);
    if (NULL == sock) {
        fprintf(stderr, "PR_OpenTCPSocket failed\n");
        exit(1);
    }
    opt.option = PR_SockOpt_Nonblocking;
    opt.value.non_blocking = PR_TRUE;
    if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) {
        fprintf(stderr, "PR_SetSocketOption failed\n");
        exit(1);
    }
    memset(&addr, 0, sizeof(addr));
    if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr)
            == PR_FAILURE) {
        fprintf(stderr, "PR_SetNetAddr failed\n");
        exit(1);
    }
    if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
        if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
            fprintf(stderr, "PR_Connect failed\n");
            exit(1);
        }
        pd.fd = sock;
        pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
        npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == npds) {
            fprintf(stderr, "PR_Poll failed\n");
            exit(1);
        }
        if (1 != npds) {
            fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
            exit(1);
        }
        if (PR_GetConnectStatus(&pd) == PR_FAILURE) {
            fprintf(stderr, "PR_GetConnectStatus failed\n");
            exit(1);
        }
    }

    for (i = 0; i < iterations; i++) {
        PR_Sleep(PR_SecondsToInterval(1));
        memset(buf, 2*i, send_amount[i]);
        while ((nbytes = PR_Send(sock, buf, send_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT)) == -1) {
            if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
                fprintf(stderr, "PR_Send failed\n");
                exit(1);
            }
            pd.fd = sock;
            pd.in_flags = PR_POLL_WRITE;
            npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
            if (-1 == npds) {
                fprintf(stderr, "PR_Poll failed\n");
                exit(1);
            }
            if (1 != npds) {
                fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
                exit(1);
            }
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes);
            exit(1);
        }

        memset(buf, 0, sizeof(buf));
        while ((nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) {
            if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
                fprintf(stderr, "PR_Recv failed\n");
                exit(1);
            }
            pd.fd = sock;
            pd.in_flags = PR_POLL_READ;
            npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
            if (-1 == npds) {
                fprintf(stderr, "PR_Poll failed\n");
                exit(1);
            }
            if (1 != npds) {
                fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds);
                exit(1);
            }
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: peeked expected data\n");

        memset(buf, 0, sizeof(buf));
        nbytes = PR_Recv(sock, buf, recv_amount[i],
                0, PR_INTERVAL_NO_TIMEOUT);
        if (-1 == nbytes) {
            fprintf(stderr, "PR_Recv failed\n");
            exit(1);
        }
        if (send_amount[i] != nbytes) {
            fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes);
            exit(1);
        }
        for (j = 0; j < nbytes; j++) {
            if (buf[j] != 2*i+1) {
                fprintf(stderr, "byte %d should be %d but is %d\n",
                        j, 2*i+1, buf[j]);
                exit(1);
            }
        }
        fprintf(stderr, "client: received expected data\n");
    }
    if (PR_Close(sock) == PR_FAILURE) {
        fprintf(stderr, "PR_Close failed\n");
        exit(1);
    }
}
예제 #12
0
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;

}
/*
 * TCP_Client
 *    Client job
 *    Connect to the server at the address specified in the argument.
 *    Fill in a buffer, write data to server, read it back and check
 *    for data corruption.
 *    Close the socket for server connection
 */
static void PR_CALLBACK
TCP_Client(void *arg)
{
    Client_Param *cp = (Client_Param *) arg;
    PRFileDesc *sockfd;
    buffer *in_buf, *out_buf;
    union PRNetAddr netaddr;
    PRInt32 bytes, i, j;


    DPRINTF(("TCP client started\n"));
    bytes = cp->datalen;
    out_buf = PR_NEW(buffer);
    if (out_buf == NULL) {
        fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
        failed_already=1;
        return;
    }
    in_buf = PR_NEW(buffer);
    if (in_buf == NULL) {
        fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
        failed_already=1;
        return;
    }
    netaddr.inet.family = cp->server_addr.inet.family;
    netaddr.inet.port = cp->server_addr.inet.port;
    netaddr.inet.ip = cp->server_addr.inet.ip;

    for (i = 0; i < num_tcp_connections_per_client; i++) {
        if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
            fprintf(stderr,"%s: PR_OpenTCPSocket failed\n", program_name);
            failed_already=1;
            return;
        }

        DPRINTF(("TCP client connecting to server:%d\n", server_port));
        if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
        	fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
            		PR_GetError(), PR_GetOSError());
            failed_already=1;
            return;
        }
        for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
            /*
             * fill in random data
             */
            memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
            /*
             * write to server
             */
            if (writen(sockfd, out_buf->data, bytes) < bytes) {
                fprintf(stderr,"%s: ERROR - TCP_Client:writen\n", program_name);
                failed_already=1;
                return;
            }
			/*
            DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
                PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
			*/
            if (readn(sockfd, in_buf->data, bytes) < bytes) {
                fprintf(stderr,"%s: ERROR - TCP_Client:readn\n", program_name);
                failed_already=1;
                return;
            }
            /*
             * verify the data read
             */
            if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
                fprintf(stderr,"%s: ERROR - data corruption\n", program_name);
                failed_already=1;
                return;
            }
        }
        /*
         * shutdown reads and writes
         */
        if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
            fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
            failed_already=1;
        }
        PR_Close(sockfd);
    }

    PR_DELETE(out_buf);
    PR_DELETE(in_buf);

    /*
     * Decrement exit_counter and notify parent thread
     */

    PR_EnterMonitor(cp->exit_mon);
    --(*cp->exit_counter);
    PR_Notify(cp->exit_mon);
    PR_ExitMonitor(cp->exit_mon);
    DPRINTF(("TCP_Client exiting\n"));
}