-(defun elpher-get-selector (address renderer &optional force-ipv4)
- "Retrieve selector specified by ADDRESS, then render it using RENDERER.
-If FORCE-IPV4 is non-nil, explicitly look up and use IPv4 address corresponding
-to ADDRESS."
- (when (equal (elpher-address-protocol address) "gophers")
- (if (gnutls-available-p)
- (when (not elpher-use-tls)
- (setq elpher-use-tls t)
- (message "Engaging TLS gopher mode."))
- (error "Cannot retrieve TLS gopher selector: GnuTLS not available")))
- (unless (< (elpher-address-port address) 65536)
- (error "Cannot retrieve gopher selector: port number > 65536"))
- (condition-case nil
- (let* ((kill-buffer-query-functions nil)
- (gnutls-verify-error nil) ; We use the NSM for verification
- (port (elpher-address-port address))
- (host (elpher-address-host address))
- (selector-string-parts nil)
- (bytes-received 0)
- (hkbytes-received 0)
- (proc (open-network-stream "elpher-process"
- nil
- (if force-ipv4 (dns-query host) host)
- (if (> port 0) port 70)
- :type (if elpher-use-tls 'tls 'plain)
- :nowait t))
- (timer (run-at-time elpher-connection-timeout
- nil
- (lambda ()
- (pcase (process-status proc)
- ('failed
- (if (and (not (equal (elpher-address-protocol address)
- "gophers"))
- elpher-use-tls
- (or elpher-auto-disengage-TLS
- (yes-or-no-p "Could not establish encrypted connection. Disable TLS mode?")))
- (progn
- (message "Disabling TLS mode.")
- (setq elpher-use-tls nil)
- (elpher-get-selector address renderer))
- (elpher-network-error address "Could not establish encrypted connection")))
- ('connect
- (elpher-process-cleanup)
- (unless force-ipv4
- (message "Connection timed out. Retrying with IPv4 address.")
- (elpher-get-selector address renderer t))))))))
- (setq elpher-network-timer timer)
- (set-process-coding-system proc 'binary)
- (set-process-filter proc
- (lambda (_proc string)
- (when timer
- (cancel-timer timer)
- (setq timer nil))
- (setq bytes-received (+ bytes-received (length string)))
- (let ((new-hkbytes-received (/ bytes-received 102400)))
- (when (> new-hkbytes-received hkbytes-received)
- (setq hkbytes-received new-hkbytes-received)
- (with-current-buffer "*elpher*"
- (let ((inhibit-read-only t))
- (goto-char (point-min))
- (beginning-of-line 2)
- (delete-region (point) (point-max))
- (insert "("
- (number-to-string (/ hkbytes-received 10.0))
- " MB read)")))))
- (setq selector-string-parts
- (cons string selector-string-parts))))
- (set-process-sentinel proc
- (lambda (_proc event)
- (condition-case the-error
- (cond
- ((string-prefix-p "deleted" event))
- ((string-prefix-p "open" event)
- (let ((inhibit-eol-conversion t))
- (process-send-string
- proc
- (concat (elpher-gopher-address-selector address)
- "\r\n"))))
- (t
- (when timer
- (cancel-timer timer)
- (setq timer nil))
- (funcall renderer (apply #'concat
- (reverse selector-string-parts)))
- (elpher-restore-pos)))
- (error
- (elpher-network-error address the-error))))))
- (error
- (error "Error initiating connection to server"))))