static PRFileDesc *PushNewLayers(PRFileDesc *stack) { PRDescIdentity tmp_identity; PRFileDesc *layer; PRStatus rv; /* push a dummy layer */ tmp_identity = PR_GetUniqueIdentity("Dummy 1"); layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods()); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); /* push a data procesing layer */ layer = PR_CreateIOLayerStub(identity, &myMethods); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); /* push another dummy layer */ tmp_identity = PR_GetUniqueIdentity("Dummy 2"); layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods()); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); return stack; } /* PushLayer */
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(); if (NewTCPSocketPair(fd)) { mReadFD = fd[0]; mWriteFD = fd[1]; // 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); } }
// static nsresult ClosingService::AttachIOLayer(PRFileDesc *aFd) { if (!sTcpUdpPRCloseLayerMethodsPtr) { return NS_OK; } PRFileDesc * layer; PRStatus status; layer = PR_CreateIOLayerStub(sTcpUdpPRCloseLayerId, sTcpUdpPRCloseLayerMethodsPtr); if (!layer) { return NS_OK; } ClosingLayerSecret *secret = new ClosingLayerSecret(sInstance); layer->secret = reinterpret_cast<PRFilePrivate *>(secret); status = PR_PushIOLayer(aFd, PR_NSPR_IO_LAYER, layer); if (status == PR_FAILURE) { delete secret; PR_DELETE(layer); } return NS_OK; }
static PRFileDesc *PushLayer(PRFileDesc *stack) { PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods); PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); return stack; } /* PushLayer */
static inline PRFileDesc *filter_alloc_filter_iolayer(Session *sn, const Filter *filter) { // Get a cached PRFileDesc or allocate a new one PRFileDesc *iolayer = (PRFileDesc *)session_get_thread_data(sn, _filter_prfiledesc_slot); if (iolayer) { session_set_thread_data(sn, _filter_prfiledesc_slot, iolayer->lower); iolayer->identity = _filter_identity; iolayer->methods = &filter->priomethods; } else { iolayer = PR_CreateIOLayerStub(_filter_identity, &filter->priomethods); } return iolayer; }
PRFileDesc* PR_OpenUDPTransportSocket(PRIntn af, const char* host, PRInt32 port) { _check_init(); PRFileDesc* socks[2] = {0}; UDTSOCKET udt_socket = UDT::INVALID_SOCK; PRUdtSocketDesc* p_desc = NULL; if (UDT::INVALID_SOCK == (udt_socket = UDT::socket(af, SOCK_STREAM, 0))) goto cleanup; if (PR_SUCCESS != PR_NewTCPSocketPair(socks)) goto cleanup; PRFileDesc* udpt_fd = PR_CreateIOLayerStub(_udpt_desc_identity, &udptMethods); p_desc = (PRUdtSocketDesc*)PR_Malloc(sizeof(PRUdtSocketDesc)); if (UDT::bind_events(udt_socket, UDT_EPOLL_IN, _udp_event_cb, p_desc) < 0) goto cleanup; if ((NULL != udpt_fd) && (NULL != p_desc)) { PRFileDesc * sockpair_fd = socks[0]; memset(p_desc, 0, sizeof(PRUdtSocketDesc)); p_desc->sock_pair0 = socks[0]; p_desc->sock_pair1 = socks[1]; p_desc->dtor = udpt_fd->dtor; p_desc->udtfd = udt_socket; udpt_fd->secret = (PRFilePrivate*)p_desc; udpt_fd->lower = sockpair_fd; sockpair_fd->higher = udpt_fd; udpt_fd->dtor = _udtp_detor; return udpt_fd; } cleanup: if (NULL != socks[0]) PR_Close(socks[0]); if (NULL != socks[1]) PR_Close(socks[1]); if (UDT::INVALID_SOCK == udt_socket) UDT::close(udt_socket); if (NULL != p_desc) PR_Free(p_desc); if (NULL != udpt_fd) PR_Close(udpt_fd); return NULL; }
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; }
PRFileDesc *memio_CreateIOLayer(int readbufsize, int writebufsize) { PRFileDesc *fd; struct PRFilePrivate *secret; static PRCallOnceType once; PR_CallOnce(&once, memio_InitializeLayerName); fd = PR_CreateIOLayerStub(memio_identity, &memio_layer_methods); secret = malloc(sizeof(struct PRFilePrivate)); memset(secret, 0, sizeof(*secret)); memio_buffer_new(&secret->readbuf, readbufsize); memio_buffer_new(&secret->writebuf, writebufsize); fd->secret = secret; return fd; }
PRFileDesc* PR_OpenUDPTransportSocket(PRIntn af, const char* host, PRInt32 port) { _check_init(); PRFileDesc* socks[2] = {0}; UDTSOCKET u_socket = UDT_UDT_SNDBUF; PRUdtSocketDesc* p_desc = NULL; u_socket = udt_socket(af, SOCK_STREAM, 0); PRStatus status_pr = PR_NewTCPSocketPair(socks); PRFileDesc* udpt_fd = PR_CreateIOLayerStub(_udpt_desc_identity, &udptMethods); p_desc = (PRUdtSocketDesc*)PR_Malloc(sizeof(PRUdtSocketDesc)); int status_udt = udt_bind_events(u_socket, UDT_UDT_EPOLL_IN, (void*)_udp_event_cb, p_desc); if ((NULL != udpt_fd) && (NULL != p_desc) && (status_udt >= 0) && (status_pr == PR_SUCCESS)) { PRFileDesc * sockpair_fd = socks[0]; memset(p_desc, 0, sizeof(PRUdtSocketDesc)); p_desc->sock_pair0 = socks[0]; p_desc->sock_pair1 = socks[1]; p_desc->dtor = udpt_fd->dtor; p_desc->udtfd = u_socket; udpt_fd->secret = (PRFilePrivate*)p_desc; udpt_fd->lower = sockpair_fd; sockpair_fd->higher = udpt_fd; udpt_fd->dtor = _udtp_detor; return udpt_fd; } if (NULL != socks[0]) PR_Close(socks[0]); if (NULL != socks[1]) PR_Close(socks[1]); if (UDT_INVALID_SOCK != u_socket) udt_close(u_socket); if (NULL != p_desc) PR_Free(p_desc); if (NULL != udpt_fd) PR_Close(udpt_fd); return NULL; }
PRFileDesc* CreateNamedPipeLayer() { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); Initialize(); PRFileDesc* layer = PR_CreateIOLayerStub(nsNamedPipeLayerIdentity, &nsNamedPipeLayerMethods); if (NS_WARN_IF(!layer)) { LOG_NPIO_ERROR("CreateNamedPipeLayer() failed."); return nullptr; } RefPtr<NamedPipeInfo> info = new NamedPipeInfo(); layer->secret = reinterpret_cast<PRFilePrivate*>(info.forget().take()); return layer; }
struct tls_connection * tls_connection_init(void *tls_ctx) { struct tls_connection *conn; conn = os_zalloc(sizeof (*conn)); if (conn == NULL) return NULL; conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); if (conn->fd == NULL) { os_free(conn); return NULL; } conn->fd->secret = (void *) conn; conn->fd = SSL_ImportFD(NULL, conn->fd); if (conn->fd == NULL) { os_free(conn); return NULL; } if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: Failed to set options"); PR_Close(conn->fd); os_free(conn); return NULL; } SSL_ResetHandshake(conn->fd, PR_FALSE); return conn; }
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; }
// TODO: make sure this is called from STS. Otherwise // we have thread safety issues bool TransportLayerDtls::Setup() { CheckThread(); SECStatus rv; if (!downward_) { MOZ_MTLOG(ML_ERROR, "DTLS layer with nothing below. This is useless"); return false; } nspr_io_adapter_ = new TransportLayerNSPRAdapter(downward_); if (!identity_) { MOZ_MTLOG(ML_ERROR, "Can't start DTLS without an identity"); return false; } if (verification_mode_ == VERIFY_UNSET) { MOZ_MTLOG(ML_ERROR, "Can't start DTLS without specifying a verification mode"); return false; } if (transport_layer_identity == PR_INVALID_IO_LAYER) { transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter"); } ScopedPRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity, &TransportLayerMethods)); MOZ_ASSERT(pr_fd != nullptr); if (!pr_fd) return false; pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get()); ScopedPRFileDesc ssl_fd(DTLS_ImportFD(nullptr, pr_fd)); MOZ_ASSERT(ssl_fd != nullptr); // This should never happen if (!ssl_fd) { return false; } pr_fd.forget(); // ownership transfered to ssl_fd; if (role_ == CLIENT) { MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as client"); rv = SSL_GetClientAuthDataHook(ssl_fd, GetClientAuthDataHook, this); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't set identity"); return false; } } else { MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as server"); // Server side rv = SSL_ConfigSecureServer(ssl_fd, identity_->cert(), identity_->privkey(), kt_rsa); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't set identity"); return false; } // Insist on a certificate from the client rv = SSL_OptionSet(ssl_fd, SSL_REQUEST_CERTIFICATE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't request certificate"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_REQUIRE_CERTIFICATE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't require certificate"); return false; } } // Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS // 1.0 for stream modes. SSLVersionRange version_range = { SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_2 }; rv = SSL_VersionRangeSet(ssl_fd, &version_range); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable session tickets"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable session caching"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_DEFLATE, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable deflate"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable renegotiation"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable false start"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_NO_LOCKS, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable locks"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't disable ECDHE key reuse"); return false; } if (!SetupCipherSuites(ssl_fd)) { return false; } // Certificate validation rv = SSL_AuthCertificateHook(ssl_fd, AuthCertificateHook, reinterpret_cast<void *>(this)); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't set certificate validation hook"); return false; } // Now start the handshake rv = SSL_ResetHandshake(ssl_fd, role_ == SERVER ? PR_TRUE : PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't reset handshake"); return false; } ssl_fd_ = ssl_fd.forget(); // Finally, get ready to receive data downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange); downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived); if (downward_->state() == TS_OPEN) { Handshake(); } return true; }
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); } }