/* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */ int ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) { int rv = 0; SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes", SSL_GETPID(), ss->fd, len)); if (ss->shutdownHow & ssl_SHUTDOWN_SEND) { PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); rv = PR_FAILURE; goto done; } if (flags) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); rv = PR_FAILURE; goto done; } ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { PORT_Assert(ss->pendingBuf.len > 0); rv = ssl_SendSavedWriteData(ss); if (rv >= 0 && ss->pendingBuf.len != 0) { PORT_Assert(ss->pendingBuf.len > 0); PORT_SetError(PR_WOULD_BLOCK_ERROR); rv = SECFailure; } } ssl_ReleaseXmitBufLock(ss); if (rv < 0) { goto done; } if (len > 0) ss->writerThread = PR_GetCurrentThread(); /* If any of these is non-zero, the initial handshake is not done. */ if (!ss->firstHsDone) { PRBool falseStart = PR_FALSE; ssl_Get1stHandshakeLock(ss); if (ss->opt.enableFalseStart) { ssl_GetSSL3HandshakeLock(ss); falseStart = ss->ssl3.hs.canFalseStart; ssl_ReleaseSSL3HandshakeLock(ss); } if (!falseStart && ss->handshake) { rv = ssl_Do1stHandshake(ss); } ssl_Release1stHandshakeLock(ss); } if (rv < 0) { ss->writerThread = NULL; goto done; } /* Check for zero length writes after we do housekeeping so we make forward * progress. */ if (len == 0) { rv = 0; goto done; } PORT_Assert(buf != NULL); if (!buf) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); rv = PR_FAILURE; goto done; } if (!ss->firstHsDone) { #ifdef DEBUG ssl_GetSSL3HandshakeLock(ss); PORT_Assert(ss->ssl3.hs.canFalseStart); ssl_ReleaseSSL3HandshakeLock(ss); #endif SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start", SSL_GETPID(), ss->fd)); } ssl_GetXmitBufLock(ss); rv = ssl3_SendApplicationData(ss, buf, len, flags); ssl_ReleaseXmitBufLock(ss); ss->writerThread = NULL; done: if (rv < 0) { SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d", SSL_GETPID(), ss->fd, rv, PORT_GetError())); } else { SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count", SSL_GETPID(), ss->fd, rv)); } return rv; }
/* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */ int ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) { int rv = 0; SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes", SSL_GETPID(), ss->fd, len)); if (ss->shutdownHow & ssl_SHUTDOWN_SEND) { PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); rv = PR_FAILURE; goto done; } if (flags) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); rv = PR_FAILURE; goto done; } ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { PORT_Assert(ss->pendingBuf.len > 0); rv = ssl_SendSavedWriteData(ss); if (rv >= 0 && ss->pendingBuf.len != 0) { PORT_Assert(ss->pendingBuf.len > 0); PORT_SetError(PR_WOULD_BLOCK_ERROR); rv = SECFailure; } } ssl_ReleaseXmitBufLock(ss); if (rv < 0) { goto done; } if (len > 0) ss->writerThread = PR_GetCurrentThread(); /* Check to see if we can write even though we're not finished. * * Case 1: False start * Case 2: TLS 1.3 0-RTT */ if (!ss->firstHsDone) { PRBool falseStart = PR_FALSE; ssl_Get1stHandshakeLock(ss); if (ss->opt.enableFalseStart || (ss->opt.enable0RttData && !ss->sec.isServer)) { ssl_GetSSL3HandshakeLock(ss); /* The client can sometimes send before the handshake is fully * complete. In TLS 1.2: false start; in TLS 1.3: 0-RTT. */ falseStart = ss->ssl3.hs.canFalseStart || ss->ssl3.hs.zeroRttState == ssl_0rtt_sent || ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted; ssl_ReleaseSSL3HandshakeLock(ss); } if (!falseStart && ss->handshake) { rv = ssl_Do1stHandshake(ss); } ssl_Release1stHandshakeLock(ss); } if (rv < 0) { ss->writerThread = NULL; goto done; } /* Check for zero length writes after we do housekeeping so we make forward * progress. */ if (len == 0) { rv = 0; goto done; } PORT_Assert(buf != NULL); if (!buf) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); rv = PR_FAILURE; goto done; } if (!ss->firstHsDone) { #ifdef DEBUG ssl_GetSSL3HandshakeLock(ss); PORT_Assert(!ss->sec.isServer && (ss->ssl3.hs.canFalseStart || ss->ssl3.hs.zeroRttState == ssl_0rtt_sent || ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted)); ssl_ReleaseSSL3HandshakeLock(ss); #endif SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start", SSL_GETPID(), ss->fd)); } ssl_GetXmitBufLock(ss); rv = ssl3_SendApplicationData(ss, buf, len, flags); ssl_ReleaseXmitBufLock(ss); ss->writerThread = NULL; done: if (rv < 0) { SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d", SSL_GETPID(), ss->fd, rv, PORT_GetError())); } else { SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count", SSL_GETPID(), ss->fd, rv)); } return rv; }