Christopher Baines <m...@cbaines.net> skribis: > As described in the GnuTLS documentation on Asynchronous operation, > GNUTLS_NONBLOCK should be passed to gnutls_init, and the Guile > equivalent is passing connection-flag/nonblock to make-session. > > Additionally, error/again or error/interrupted should lead to a retry of > the handshake, after waiting for the appropriate I/O on the port. As > record-get-direction is new in Guile-GnuTLS, specifically check if this > is defined. > > * module/web/client.scm (tls-wrap): Call make-session with > connection-flag/nonblock if the port is non-blocking, and handle waiting > for I/O when performing the handshake.
[...] > + (let ((session > + (apply > + make-session > + (cons connection-end/client > + (if (zero? (logand O_NONBLOCK (fcntl port F_GETFL))) > + '() > + ;; If the port is non-blocking, tell GnuTLS > + (list connection-flag/nonblock))))) You can avoid ‘cons’ here: (apply make-session connection-end/client (if … '() (list …))) > + (cond ((and > + (or (eq? err error/again) > + (eq? err error/interrupted)) > + (module-defined? (resolve-interface '(gnutls)) > + 'record-get-direction)) ; Guile-GnuTLS >= > 4.0.0 > + (if (= 0 (record-get-direction session)) > + ((current-read-waiter) port) > + ((current-write-waiter) port)) Should EINTR (error/interrupted) really be treated in the same way as EAGAIN? That looks fishy. Also, this only addresses handshake, but what about ‘error/again’ raise while transferring data over the session record port? Thanks, Ludo’ “better late than never”.