On Sat, Dec 29, 2007, Erik Huelsmann wrote:
> That's why I rather use
> select()/LISTEN/READ-CHAR/READ-CHAR-NO-HANG/etc. to implement time-out
> behaviour which can be used on all lisps on all OSes. I hope you don't
> mind (and that you - as I do - think that the result is what counts).
I have implemented timeouts for non-LispWorks lisps. Latest usocket
trunk and working usocket:wait-for-input required.
Patch attached.
--
/\
/ Jabber ID :: [EMAIL PROTECTED]
\ \/ Unix stuff :: http://tehran.lain.pl
\/\ Yet Another RBL :: http://rbl.lain.pl
diff -urN /tmp/drakma-0.11.1/drakma.asd drakma-0.11.1/drakma.asd
--- /tmp/drakma-0.11.1/drakma.asd 2007-10-11 10:45:47.000000000 +0200
+++ drakma-0.11.1/drakma.asd 2007-12-29 14:01:24.000000000 +0100
@@ -48,9 +48,11 @@
(:file "util")
(:file "read")
(:file "cookies")
- (:file "request"))
+ (:file "request")
+ #-lispworks (:file "gray-streams"))
:depends-on (:puri
:cl-base64
:chunga
#-:lispworks :usocket
- #-(or :lispworks :allegro) :cl+ssl))
+ #-(or :lispworks :allegro) :cl+ssl
+ #-lispworks #:trivial-gray-streams))
diff -urN /tmp/drakma-0.11.1/gray-streams.lisp drakma-0.11.1/gray-streams.lisp
--- /tmp/drakma-0.11.1/gray-streams.lisp 1970-01-01 01:00:00.000000000 +0100
+++ drakma-0.11.1/gray-streams.lisp 2007-12-29 14:48:36.000000000 +0100
@@ -0,0 +1,46 @@
+(in-package #:drakma)
+
+(defclass timeout-stream (trivial-gray-stream-mixin
+ fundamental-binary-input-stream
+ fundamental-binary-output-stream)
+ ((socket :initarg :socket :accessor timeout-stream-socket)
+ (stream :initarg :stream :accessor timeout-stream-stream)
+ (timeout :initarg :timeout :accessor timeout-stream-timeout)))
+
+(defmethod stream-force-output ((stream timeout-stream))
+ (force-output (timeout-stream-stream stream)))
+
+(defmethod stream-finish-output ((stream timeout-stream))
+ (finish-output (timeout-stream-stream stream)))
+
+(defun timeout-stream-do-timeout (stream)
+ (with-slots (socket timeout stream) stream
+ (unless (or (listen stream)
+ (usocket:wait-for-input socket :timeout timeout))
+ (usocket:socket-close socket)
+ (error 'usocket:timeout-error :socket socket))))
+
+(defmethod stream-read-byte ((stream timeout-stream))
+ (timeout-stream-do-timeout stream)
+ (read-byte (timeout-stream-stream stream) nil nil))
+
+(defmethod stream-write-byte ((stream timeout-stream) integer)
+ (write-byte integer (timeout-stream-stream stream)))
+
+(defmethod stream-read-sequence ((stream timeout-stream)
+ sequence start end &key)
+ (loop
+ with s = (timeout-stream-stream stream)
+ with ret = 0
+ for i from start below end
+ do (timeout-stream-do-timeout stream)
+ do (setf (aref sequence i)
+ (or (read-byte s nil nil)
+ (return ret)))
+ do (incf i)
+ finally (return ret)))
+
+(defmethod stream-write-sequence ((stream timeout-stream)
+ sequence start end &key)
+ (write-sequence sequence (timeout-stream-stream stream)
+ :start start :end end))
diff -urN /tmp/drakma-0.11.1/request.lisp drakma-0.11.1/request.lisp
--- /tmp/drakma-0.11.1/request.lisp 2007-10-11 10:45:47.000000000 +0200
+++ drakma-0.11.1/request.lisp 2007-12-29 14:12:34.000000000 +0100
@@ -194,7 +194,7 @@
want-stream
stream
#+:lispworks (connection-timeout 20)
- #+:lispworks (read-timeout 20)
+ (read-timeout 20)
#+:lispworks5.0 (write-timeout 20))
"Sends an HTTP request to a web server and returns its reply. URI
is where the request is sent to, and it is either a string denoting a
@@ -428,9 +428,17 @@
:write-timeout write-timeout
:errorp t)
#-:lispworks
- (usocket:socket-stream
- (usocket:socket-connect host port
- :element-type 'octet)))))
+ (if (null read-timeout)
+ (usocket:socket-stream
+ (usocket:socket-connect host port
+ :element-type 'octet))
+ (let* ((socket (usocket:socket-connect host port
+ :element-type 'octet))
+ (stream (usocket:socket-stream socket)))
+ (make-instance 'timeout-stream
+ :socket socket
+ :stream stream
+ :timeout read-timeout))))))
(when (and (or force-ssl
(eq (uri-scheme uri) :https))
;; don't attach SSL to existing streams
_______________________________________________
drakma-devel mailing list
[email protected]
http://common-lisp.net/cgi-bin/mailman/listinfo/drakma-devel