1
0
Fork 0

- [gemini] wrapped non gemini files download's thread.

Also added a few of useful slotslike temporary file path and number of
  bytes downloaded so far.
This commit is contained in:
cage 2020-08-28 17:20:44 +02:00
parent 8ae83a2323
commit 0bb4406be7
2 changed files with 153 additions and 85 deletions

View File

@ -81,6 +81,14 @@
:initform nil :initform nil
:initarg :download-socket :initarg :download-socket
:accessor download-socket) :accessor download-socket)
(support-file
:initform (fs:temporary-file)
:initarg :support-file
:accessor support-file)
(octect-count
:initform 0
:initarg :octect-count
:accessor octect-count)
(thread (thread
:initform nil :initform nil
:initarg :thread :initarg :thread
@ -123,12 +131,42 @@
(defclass gemini-file-stream (gemini-stream) ()) (defclass gemini-file-stream (gemini-stream) ())
(defclass gemini-others-data-stream (gemini-stream) ())
(defmacro with-open-support-file ((stream file &optional (element-type '(unsigned-byte 8)))
&body body)
`(with-open-file (,stream ,file
:element-type ',element-type
:direction :output
:element-type 'character
:if-exists :supersede
:if-does-not-exist :create)
,@body))
(defgeneric increment-bytes-count (object data &key &allow-other-keys))
(defmethod increment-bytes-count ((object gemini-stream) data
&key (convert-to-octects nil))
(with-accessors ((octect-count octect-count)) object
(if convert-to-octects
(incf octect-count (babel:string-size-in-octets data
:errorp nil))
(incf octect-count (length data)))))
(defmethod increment-bytes-count ((object gemini-stream) (data number)
&key &allow-other-keys)
(with-accessors ((octect-count octect-count)) object
(incf octect-count data)))
(defun request-stream-gemini-document-thread (wrapper-object host (defun request-stream-gemini-document-thread (wrapper-object host
port path query port path query
status-code status-code-description meta) status-code status-code-description meta)
(with-accessors ((download-socket download-socket) (with-accessors ((download-socket download-socket)
(download-stream download-stream)) wrapper-object (download-stream download-stream)
(octect-count octect-count)
(support-file support-file)) wrapper-object
(lambda () (lambda ()
(with-open-support-file (file-stream support-file character)
(let* ((url (gemini-parser:make-gemini-uri host path query port)) (let* ((url (gemini-parser:make-gemini-uri host path query port))
(parsed-url (gemini-parser:parse-gemini-file (format nil "-> ~a~%" url))) (parsed-url (gemini-parser:parse-gemini-file (format nil "-> ~a~%" url)))
(url-response (gemini-client:make-gemini-file-response nil (url-response (gemini-client:make-gemini-file-response nil
@ -161,6 +199,8 @@
(event (make-instance 'program-events:gemini-got-line-event (event (make-instance 'program-events:gemini-got-line-event
:wrapper-object wrapper-object :wrapper-object wrapper-object
:payload response))) :payload response)))
(write-sequence line file-stream)
(increment-bytes-count wrapper-object line :convert-to-octects t)
(program-events:push-event event)) (program-events:push-event event))
(progn (progn
(return-from download-loop nil)))) (return-from download-loop nil))))
@ -168,21 +208,40 @@
(ui:notify (_ "Gemini document downloading aborted")) (ui:notify (_ "Gemini document downloading aborted"))
(ui:notify (_ "Gemini document downloading completed"))) (ui:notify (_ "Gemini document downloading completed")))
(allow-downloading wrapper-object) (allow-downloading wrapper-object)
(gemini-client:close-ssl-socket download-socket))))) (gemini-client:close-ssl-socket download-socket)))
(fs:delete-file-if-exists support-file))))
(defun request-stream-other-document-thread (socket stream host (defun request-stream-other-document-thread (wrapper-object
port path query socket
host
port
path
query
status-code status-code-description meta) status-code status-code-description meta)
(declare (ignorable host (declare (ignorable host
port path query port path query
status-code status-code-description meta)) status-code status-code-description meta))
(with-accessors ((download-socket download-socket)
(download-stream download-stream)
(octect-count octect-count)
(support-file support-file)) wrapper-object
(lambda () (lambda ()
(fs:with-anaphoric-temp-file (out-stream) (with-open-support-file (file-stream support-file)
(let* ((buffer (misc:read-all stream))) (labels ((%fill-buffer ()
(multiple-value-bind (buffer read-so-far)
(read-array download-stream 1024)
(increment-bytes-count wrapper-object read-so-far)
(if (< read-so-far (length buffer))
(progn
(write-sequence buffer file-stream :start 0 :end read-so-far)
(force-output file-stream)
(gemini-client:close-ssl-socket socket) (gemini-client:close-ssl-socket socket)
(write-sequence buffer out-stream) (os-utils:xdg-open support-file))
(force-output out-stream) (progn
(os-utils:xdg-open fs:temp-file))))) (write-sequence buffer file-stream)
(%fill-buffer))))))
(%fill-buffer))))))
(defun request (url) (defun request (url)
(let ((parsed-uri (quri:uri url))) (let ((parsed-uri (quri:uri url)))
@ -238,7 +297,6 @@
((gemini-client:response-sensitive-input-p status) ((gemini-client:response-sensitive-input-p status)
(get-user-input t host meta)) (get-user-input t host meta))
((streamp response) ((streamp response)
(let ((stream response))
(if (gemini-client:mime-gemini-p meta) (if (gemini-client:mime-gemini-p meta)
(let* ((gemini-stream (make-instance 'gemini-file-stream (let* ((gemini-stream (make-instance 'gemini-file-stream
:download-stream response :download-stream response
@ -258,15 +316,25 @@
port port
path path
query)) query))
(bt:make-thread (request-stream-other-document-thread socket (let* ((gemini-stream (make-instance 'gemini-others-data-stream
stream :download-stream response
:download-socket socket))
(thread-fn
(request-stream-other-document-thread gemini-stream
socket
host host
port port
path path
query query
status status
code-description code-description
meta)))))))) meta)))
(downloading-start-thread gemini-stream
thread-fn
host
port
path
query)))))))
(gemini-client:gemini-tofu-error (e) (gemini-client:gemini-tofu-error (e)
(let ((host (gemini-client:host e))) (let ((host (gemini-client:host e)))
(flet ((on-input-complete (maybe-accepted) (flet ((on-input-complete (maybe-accepted)

View File

@ -453,9 +453,9 @@ Name from Emacs Lisp."
(defun read-array (stream size &key (offset nil)) (defun read-array (stream size &key (offset nil))
(when offset (when offset
(file-position stream offset)) (file-position stream offset))
(let* ((bytes (misc-utils:make-array-frame size 0 '(unsigned-byte 8) t))) (let* ((bytes (misc-utils:make-array-frame size 0 '(unsigned-byte 8) t))
(read-sequence bytes stream) (read-so-far (read-sequence bytes stream)))
bytes)) (values bytes read-so-far)))
(defun read-all (stream) (defun read-all (stream)
"Read all the octent from stream ad returns them as array" "Read all the octent from stream ad returns them as array"