From: "Ludovic Courtès" <ludo@gnu.org>
To: 56867@debbugs.gnu.org
Cc: "Ludovic Courtès" <ludo@gnu.org>, guile-devel@gnu.org
Subject: [bug#56867] [PATCH] download: Do not wrap TLS port on GnuTLS >= 3.7.7.
Date: Mon, 1 Aug 2022 11:07:49 +0200 [thread overview]
Message-ID: <20220801090749.11655-1-ludo@gnu.org> (raw)
The custom input/output port wrapping the TLS session record port would
introduce overhead, and it would also prevent its uses in a non-blocking
context--e.g., with Fibers. The port close mechanism added in GnuTLS
3.7.7 allows us to get rid of that wrapper.
* guix/build/download.scm (wrap-record-port-for-gnutls<3.7.7): New
procedure, with code formerly in 'tls-wrap'.
(tls-wrap): Check for 'set-session-record-port-close!' and use it when
available; otherwise call 'wrap-record-port-for-gnutls<3.7.7'.
---
guix/build/download.scm | 102 +++++++++++++++++++++-------------------
1 file changed, 54 insertions(+), 48 deletions(-)
Hello!
I'll land a similar change in Guile's (web client) module afterwards
if there are no objections.
Ludo'.
diff --git a/guix/build/download.scm b/guix/build/download.scm
index 41583e8143..de094890b3 100644
--- a/guix/build/download.scm
+++ b/guix/build/download.scm
@@ -245,6 +245,54 @@ (define (print-tls-certificate-error port key args default-printer)
(set-exception-printer! 'tls-certificate-error
print-tls-certificate-error)
+(define (wrap-record-port-for-gnutls<3.7.7 record port)
+ "Return a port that wraps RECORD to ensure that closing it also closes PORT,
+the actual socket port, and its file descriptor. Make sure it does not
+introduce extra buffering (custom ports are buffered by default as of Guile
+3.0.5).
+
+This wrapper is unnecessary with GnuTLS >= 3.7.7, which can automatically
+close SESSION's file descriptor when RECORD is closed."
+ (define (read! bv start count)
+ (define read
+ (catch 'gnutls-error
+ (lambda ()
+ (get-bytevector-n! record bv start count))
+ (lambda (key err proc . rest)
+ ;; When responding to "Connection: close" requests, some servers
+ ;; close the connection abruptly after sending the response body,
+ ;; without doing a proper TLS connection termination. Treat it as
+ ;; EOF. This is fixed in GnuTLS 3.7.7.
+ (if (eq? err error/premature-termination)
+ the-eof-object
+ (apply throw key err proc rest)))))
+
+ (if (eof-object? read)
+ 0
+ read))
+ (define (write! bv start count)
+ (put-bytevector record bv start count)
+ (force-output record)
+ count)
+ (define (get-position)
+ (port-position record))
+ (define (set-position! new-position)
+ (set-port-position! record new-position))
+ (define (close)
+ (unless (port-closed? port)
+ (close-port port))
+ (unless (port-closed? record)
+ (close-port record)))
+
+ (define (unbuffered port)
+ (setvbuf port 'none)
+ port)
+
+ (unbuffered
+ (make-custom-binary-input/output-port "gnutls wrapped port" read! write!
+ get-position set-position!
+ close)))
+
(define* (tls-wrap port server #:key (verify-certificate? #t))
"Return PORT wrapped in a TLS connection to SERVER. SERVER must be a DNS
host name without trailing dot."
@@ -317,55 +365,13 @@ (define (log level str)
(apply throw args))))
(let ((record (session-record-port session)))
- (define (read! bv start count)
- (define read
- (catch 'gnutls-error
- (lambda ()
- (get-bytevector-n! record bv start count))
- (lambda (key err proc . rest)
- ;; When responding to "Connection: close" requests, some
- ;; servers close the connection abruptly after sending the
- ;; response body, without doing a proper TLS connection
- ;; termination. Treat it as EOF.
- (if (eq? err error/premature-termination)
- the-eof-object
- (apply throw key err proc rest)))))
-
- (if (eof-object? read)
- 0
- read))
- (define (write! bv start count)
- (put-bytevector record bv start count)
- (force-output record)
- count)
- (define (get-position)
- (port-position record))
- (define (set-position! new-position)
- (set-port-position! record new-position))
- (define (close)
- (unless (port-closed? port)
- (close-port port))
- (unless (port-closed? record)
- (close-port record)))
-
- (define (unbuffered port)
- (setvbuf port 'none)
- port)
-
(setvbuf record 'block)
-
- ;; Return a port that wraps RECORD to ensure that closing it also
- ;; closes PORT, the actual socket port, and its file descriptor.
- ;; Make sure it does not introduce extra buffering (custom ports
- ;; are buffered by default as of Guile 3.0.5).
- ;; XXX: This wrapper would be unnecessary if GnuTLS could
- ;; automatically close SESSION's file descriptor when RECORD is
- ;; closed, but that doesn't seem to be possible currently (as of
- ;; 3.6.9).
- (unbuffered
- (make-custom-binary-input/output-port "gnutls wrapped port" read! write!
- get-position set-position!
- close)))))
+ (if (module-defined? (resolve-interface '(gnutls))
+ 'set-session-record-port-close!) ;GnuTLS >= 3.7.7
+ (let ((close-wrapped-port (lambda (_) (close-port port))))
+ (set-session-record-port-close! record close-wrapped-port)
+ record)
+ (wrap-record-port-for-gnutls<3.7.7 record port)))))
(define (ensure-uri uri-or-string) ;XXX: copied from (web http)
(cond
base-commit: ab59155c5a38dda7efaceb47c7528578fcf0def4
--
2.37.1
next reply other threads:[~2022-08-01 9:07 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-01 9:07 Ludovic Courtès [this message]
2022-08-01 9:15 ` [bug#56867] [PATCH] download: Do not wrap TLS port on GnuTLS >= 3.7.7 Ludovic Courtès
2022-08-01 9:56 ` Maxime Devos
2022-08-02 7:59 ` Ludovic Courtès
2022-08-04 19:37 ` Maxime Devos
2022-08-05 8:31 ` Ludovic Courtès
2022-08-05 10:17 ` Maxime Devos
2022-08-03 15:57 ` bug#56867: " Ludovic Courtès
2022-08-04 14:20 ` [bug#56867] " Ludovic Courtès
2022-08-04 14:46 ` bug#56005: " Thiago Jung Bauermann via Bug reports for GNU Guix
2022-08-04 16:19 ` Ludovic Courtès
2022-08-04 17:31 ` bug#56867: " Chris Vine
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220801090749.11655-1-ludo@gnu.org \
--to=ludo@gnu.org \
--cc=56867@debbugs.gnu.org \
--cc=guile-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).