}
} else if (IS_SSL_ERROR(err)) {   nsHandleSSLError(socketInfo, err); } } else if (IS_SSL_ERROR(err)) {   nsHandleSSLError(socketInfo, err);
nsSSLIOLayerWrite(PRFileDesc* fd, const void* buf, PRInt32 amount){  if (!fd || !fd->lower)    return PR_FAILURE;    #ifdef DEBUG_SSL_VERBOSE  DEBUG_DUMP_BUFFER((unsigned char*)buf, amount);#endif  nsNSSSocketInfo *socketInfo = nsnull;  PRBool firstWrite;  socketInfo = (nsNSSSocketInfo*)fd->secret;  NS_ASSERTION(socketInfo,"nsNSSSocketInfo was null for an fd");  socketInfo->GetFirstWrite(&firstWrite);  PRBool oldBlockVal;  PRBool oldBlockReset = PR_FALSE;  PRSocketOptionData sockopt;  if (firstWrite) {    // We only want the first write to be blocking so that we    // can trap the case of the TLS intolerant server.    sockopt.option = PR_SockOpt_Nonblocking;    PR_GetSocketOption(fd, &sockopt);    oldBlockVal = sockopt.value.non_blocking;    sockopt.value.non_blocking = PR_FALSE;    PR_SetSocketOption(fd, &sockopt);  }  PRInt32 bytesWritten = fd->lower->methods->write(fd->lower, buf, amount);#ifdef DEBUG_SSL_VERBOSE  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] wrote %d bytes\n", (void*)fd, bytesWritten));#endif  // This is where we work around all of those SSL servers that don't   // conform to the SSL spec and shutdown a connection when we request  // SSL v3.1 (aka TLS).  The spec says the client says what version  // of the protocol we're willing to perform, in our case SSL v3.1  // In its response, the server says which version it wants to perform.  // Many servers out there only know how to do v3.0.  Next, we're supposed  // to send back the version of the protocol we requested (ie v3.1).  At  // this point many servers's implementations are broken and they shut  // down the connection when they don't see the version they sent back.  // This is supposed to prevent a man in the middle from forcing one  // side to dumb down to a lower level of the protocol.  Unfortunately,  // there are enough broken servers out there that such a gross work-around  // is necessary.  :(    if (bytesWritten == -1) {    if (firstWrite) {      PRBool tlsOn;      SSL_OptionGet(fd->lower, SSL_ENABLE_TLS, &tlsOn);      if (tlsOn) {        // The write may have failed because we're talking to a server        // that doesn't correctly implement TLS.  So let's turn TLS off and        // try again.        SSL_InvalidateSession(fd->lower);        nsXPIDLCString host;        nsXPIDLCString proxyHost;        PRInt32 port, proxyPort;        PRBool forTLSStepUp;        nsCOMPtr<nsISupports> newInfo;        socketInfo->GetHostName(getter_Copies(host));        socketInfo->GetProxyHost(getter_Copies(proxyHost));        socketInfo->GetPort(&port);        socketInfo->GetProxyPort(&proxyPort);        socketInfo->GetForTLSStepUp(&forTLSStepUp);        // In order to make this work, we've got to replace the SSL layer        // with a new socket.  So let's create one here.        //        // XXX We should be calling PR_PopIOLayer and PR_PushIOLayer here,        //     but doing so will confuse necko because the top most layer fd's        //     will change.  So we re-wire the layers manually to get things        //     running.  NOTE: This only works iff NSS/PSM/necko all use the        //     same allocators for their file descriptors.        PRFileDesc *newSocket = PR_OpenTCPSocket(PR_AF_INET6);        PRFileDesc *newSSLSocket = nsSSLIOLayerImportFD(newSocket,                                                         socketInfo, host);        if (newSSLSocket) {          nsSSLIOLayerSetOptions(newSSLSocket, forTLSStepUp, proxyHost,                                 host, port, socketInfo);          PRNetAddr addr;          fd->lower->higher = nsnull;          PR_Close(fd->lower);           fd->lower = newSSLSocket;          newSSLSocket->higher = fd;          //Make sure TLS is off when we try to re-connect.          SSL_OptionSet(newSSLSocket, SSL_ENABLE_TLS, PR_FALSE);          // This connect must be blocking.          socketInfo->GetNetAddr(&addr);          PRStatus prv = PR_Connect(fd, &addr, PR_INTERVAL_NO_TIMEOUT);          // We no longer need this socket to block, so make it non-blocking.          sockopt.option = PR_SockOpt_Nonblocking;          sockopt.value.non_blocking = oldBlockVal;          PR_SetSocketOption(fd, &sockopt);          oldBlockReset = PR_TRUE;          if (prv == PR_SUCCESS)            bytesWritten = fd->lower->methods->write(fd->lower, buf, amount);        } else {          PR_Close(newSocket);        }      }     }  }  // TLS intolerant servers only cause the first write to fail, so let's   // set the fristWrite attribute to false so that we don't try the logic  // above again in a subsequent write.  if (firstWrite) {    socketInfo->SetFirstWrite(PR_FALSE);    if (!oldBlockReset) {      sockopt.option = PR_SockOpt_Nonblocking;      sockopt.value.non_blocking = oldBlockVal;      PR_SetSocketOption(fd, &sockopt);    }  }  return bytesWritten;}