Check-in [268b7a0965]
Overview
Comment:Cache read/write wants from BIO_read/BIO_write and include in watch mask
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tls-1.8
Files: files | file ages | folders
SHA3-256: 268b7a0965b1a3a6b496d124dc605a4cdfb748d4ecf40dd6b4de5dba111dbeb3
User & Date: bohagan on 2024-06-08 20:49:50
Other Links: branch diff | manifest | tags
Context
2024-06-15
21:49
Removed obsolete locking code and added support for checking system OpenSSL config file for crypto policies. check-in: 449470132e user: bohagan tags: tls-1.8
2024-06-08
20:49
Cache read/write wants from BIO_read/BIO_write and include in watch mask check-in: 268b7a0965 user: bohagan tags: tls-1.8
01:51
Added more info to comments check-in: fdb58ae458 user: bohagan tags: tls-1.8
Changes
174
175
176
177
178
179
180
181

182






183
184
185
186
187
188
189
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195







-
+

+
+
+
+
+
+







	if (rc != SSL_ERROR_NONE) {
	    dprintf("Got error: %i (rc = %i)", err, rc);
	    dprintf("Got error: %s", ERR_reason_error_string(backingError));
	}

	bioShouldRetry = 0;
	if (err <= 0) {
	    if (rc == SSL_ERROR_WANT_CONNECT || rc == SSL_ERROR_WANT_ACCEPT || rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
	    if (rc == SSL_ERROR_WANT_CONNECT || rc == SSL_ERROR_WANT_ACCEPT) {
		bioShouldRetry = 1;
	    } else if (rc == SSL_ERROR_WANT_READ) {
		bioShouldRetry = 1;
		statePtr->want = TCL_READABLE;
	    } else if (rc == SSL_ERROR_WANT_WRITE) {
		bioShouldRetry = 1;
		statePtr->want = TCL_WRITABLE;
	    } else if (BIO_should_retry(statePtr->bio)) {
		bioShouldRetry = 1;
	    } else if (rc == SSL_ERROR_SYSCALL && Tcl_GetErrno() == EAGAIN) {
		bioShouldRetry = 1;
	    }
	} else {
	    if (!SSL_is_init_finished(statePtr->ssl)) {
417
418
419
420
421
422
423

424
425

426
427
428
429
430
431

432
433

434
435
436
437
438
439
440
423
424
425
426
427
428
429
430
431

432
433
434
435
436
437
438
439
440

441
442
443
444
445
446
447
448







+

-
+






+

-
+







	    }
#endif
	    break;

	case SSL_ERROR_WANT_READ:
	    /* Op did not complete due to not enough data was available. Retry later. */
	    dprintf("Got SSL_ERROR_WANT_READ, mapping this to EAGAIN");
	    *errorCodePtr = EAGAIN;
	    bytesRead = -1;
	    *errorCodePtr = EAGAIN;
	    statePtr->want = TCL_READABLE;
	    Tls_Error(statePtr, "SSL_ERROR_WANT_READ");
	    break;

	case SSL_ERROR_WANT_WRITE:
	    /* Op did not complete due to unable to sent all data to the BIO. Retry later. */
	    dprintf("Got SSL_ERROR_WANT_WRITE, mapping this to EAGAIN");
	    *errorCodePtr = EAGAIN;
	    bytesRead = -1;
	    *errorCodePtr = EAGAIN;
	    statePtr->want = TCL_WRITABLE;
	    Tls_Error(statePtr, "SSL_ERROR_WANT_WRITE");
	    break;

	case SSL_ERROR_WANT_X509_LOOKUP:
	    /* Op didn't complete since callback set by SSL_CTX_set_client_cert_cb() asked to be called again */
	    dprintf("Got SSL_ERROR_WANT_X509_LOOKUP, mapping it to EAGAIN");
	    *errorCodePtr = EAGAIN;
636
637
638
639
640
641
642

643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667







+








+







	    break;

	case SSL_ERROR_WANT_READ:
	    /* Op did not complete due to not enough data was available. Retry later. */
	    dprintf("Got SSL_ERROR_WANT_READ, mapping it to EAGAIN");
	    *errorCodePtr = EAGAIN;
	    written = -1;
	    statePtr->want = TCL_READABLE;
	    Tls_Error(statePtr, "SSL_ERROR_WANT_READ");
	    break;

	case SSL_ERROR_WANT_WRITE:
	    /* Op did not complete due to unable to sent all data to the BIO. Retry later. */
	    dprintf("Got SSL_ERROR_WANT_WRITE, mapping it to EAGAIN");
	    *errorCodePtr = EAGAIN;
	    written = -1;
	    statePtr->want = TCL_WRITABLE;
	    Tls_Error(statePtr, "SSL_ERROR_WANT_WRITE");
	    break;

	case SSL_ERROR_WANT_X509_LOOKUP:
	    /* Op didn't complete since callback set by SSL_CTX_set_client_cert_cb() asked to be called again */
	    dprintf("Got SSL_ERROR_WANT_X509_LOOKUP, mapping it to EAGAIN");
	    *errorCodePtr = EAGAIN;
831
832
833
834
835
836
837
838

839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857

858
859
860
861
862
863
864
841
842
843
844
845
846
847

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875







-
+



















+







 *    Result:
 *        None.
 *
 *------------------------------------------------------*
 */
static void TlsChannelHandlerTimer(ClientData clientData) {
    State *statePtr = (State *) clientData;
    int mask = 0;
    int mask = statePtr->want; /* Init to SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE */

    dprintf("Called");

    statePtr->timer = (Tcl_TimerToken) NULL;

    if (BIO_wpending(statePtr->bio)) {
	dprintf("[chan=%p] BIO writable", statePtr->self);

	mask |= TCL_WRITABLE;
    }

    if (BIO_pending(statePtr->bio)) {
	dprintf("[chan=%p] BIO readable", statePtr->self);

	mask |= TCL_READABLE;
    }

    dprintf("Notifying ourselves");
    Tcl_NotifyChannel(statePtr->self, mask);
    statePtr->want = 0;

    dprintf("Returning");

    return;
}

/*
928
929
930
931
932
933
934
935
936


937
938
939
940
941
942
943
939
940
941
942
943
944
945


946
947
948
949
950
951
952
953
954







-
-
+
+







     */
    if (statePtr->timer != (Tcl_TimerToken) NULL) {
	dprintf("A timer was found, deleting it");
	Tcl_DeleteTimerHandler(statePtr->timer);
	statePtr->timer = (Tcl_TimerToken) NULL;
    }

    if ((mask & TCL_READABLE) &&
	((Tcl_InputBuffered(statePtr->self) > 0) || (BIO_ctrl_pending(statePtr->bio) > 0))) {
    if (statePtr->want || ((mask & TCL_READABLE) &&
	((Tcl_InputBuffered(statePtr->self) > 0) || (BIO_ctrl_pending(statePtr->bio) > 0)))) {
	/*
	 * There is interest in readable events and we actually have
	 * data waiting, so generate a timer to flush that.
	 */
	dprintf("Creating a new timer since data appears to be waiting");
	statePtr->timer = Tcl_CreateTimerHandler(TLS_TCL_DELAY, TlsChannelHandlerTimer, (ClientData) statePtr);
    }
171
172
173
174
175
176
177

178
179
180
181
182
183
184
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185







+







 */
typedef struct State {
	Tcl_Channel self;	/* this socket channel */
	Tcl_TimerToken timer;

	int flags;		/* see State.flags above  */
	int watchMask;		/* current WatchProc mask */
	int want;		/* pending wants from OpenSSL */
	int mode;		/* current mode of parent channel */

	Tcl_Interp *interp;	/* interpreter in which this resides */
	Tcl_Obj *callback;	/* script called for tracing, info, and errors */
	Tcl_Obj *password;	/* script called for certificate password */
	Tcl_Obj *vcmd;		/* script called to verify or validate protocol config */