int
tls_handshake_close(tls_handshake_t filter)
{
	int      err = errSSLSuccess;

    assert(filter);

    err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertCloseNotify, filter);

    SSLChangeHdskState(filter, SSL_HdskStateGracefulClose);

    return err;
}
OSStatus
SSLFatalSessionAlert(AlertDescription desc, SSLContext *ctx)
{   OSStatus          err1, err2;

    if(desc != SSL_AlertCloseNotify) {
    	sslHdskMsgDebug("SSLFatalSessionAlert: desc %d\n", desc);
    }
    SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);

	if(ctx->negProtocolVersion < TLS_Version_1_0) {
		/* translate to SSL3 if necessary */
		switch(desc) {
			//case SSL_AlertDecryptionFail_RESERVED:
			case SSL_AlertRecordOverflow:
			case SSL_AlertAccessDenied:
			case SSL_AlertDecodeError:
			case SSL_AlertDecryptError:
			//case SSL_AlertExportRestriction_RESERVED:
			case SSL_AlertProtocolVersion:
			case SSL_AlertInsufficientSecurity:
			case SSL_AlertUserCancelled:
			case SSL_AlertNoRenegotiation:
				desc = SSL_AlertHandshakeFail;
				break;
			case SSL_AlertUnknownCA:
				desc = SSL_AlertUnsupportedCert;
				break;
			case SSL_AlertInternalError:
				desc = SSL_AlertCloseNotify;
				break;
			default:
				/* send as is */
				break;
		}
	}
    /* Make session unresumable; I'm not stopping if I get an error,
        because I'd like to attempt to send the alert anyway */
    err1 = SSLDeleteSessionData(ctx);

    /* Second, send the alert */
    err2 = SSLSendAlert(SSL_AlertLevelFatal, desc, ctx);

	ctx->sentFatalAlert = true;

    /* If they both returned errors, arbitrarily return the first */
    return err1 != 0 ? err1 : err2;
}