X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=contrib%2Fsb-bsd-sockets%2Fsockets.lisp;h=e21228f51a7462829584013820f38ed9dd671945;hb=afa42190bccb563aa5b38d7716f1f6dbf39611ac;hp=54ac2ec900193ce206661b057005a332669d1f7b;hpb=5a0fd10d9995460c34c0cfb509b97d1cc931932b;p=sbcl.git diff --git a/contrib/sb-bsd-sockets/sockets.lisp b/contrib/sb-bsd-sockets/sockets.lisp index 54ac2ec..e21228f 100644 --- a/contrib/sb-bsd-sockets/sockets.lisp +++ b/contrib/sb-bsd-sockets/sockets.lisp @@ -20,7 +20,7 @@ protocol. Other values are used as-is.") :reader socket-type :documentation "Type of the socket: :STREAM or :DATAGRAM.") (stream)) - (:documentation "Common base class of all sockets, not ment to be + (:documentation "Common base class of all sockets, not meant to be directly instantiated."))) (defmethod print-object ((object socket) stream) @@ -96,7 +96,9 @@ values")) sockaddr (size-of-sockaddr socket)))) (cond - ((and (= fd -1) (= sockint::EAGAIN (sb-unix::get-errno))) + ((and (= fd -1) + (member (sb-unix::get-errno) + (list sockint::EAGAIN sockint::EINTR))) nil) ((= fd -1) (socket-error "accept")) (t (apply #'values @@ -154,25 +156,27 @@ values")) (defgeneric socket-receive (socket buffer length &key - oob peek waitall element-type) - (:documentation "Read LENGTH octets from SOCKET into BUFFER (or a freshly-consed buffer if -NIL), using recvfrom(2). If LENGTH is NIL, the length of BUFFER is -used, so at least one of these two arguments must be non-NIL. If -BUFFER is supplied, it had better be of an element type one octet wide. -Returns the buffer, its length, and the address of the peer -that sent it, as multiple values. On datagram sockets, sets MSG_TRUNC -so that the actual packet length is returned even if the buffer was too -small")) + oob peek waitall dontwait element-type) + (:documentation + "Read LENGTH octets from SOCKET into BUFFER (or a freshly-consed +buffer if NIL), using recvfrom(2). If LENGTH is NIL, the length of +BUFFER is used, so at least one of these two arguments must be +non-NIL. If BUFFER is supplied, it had better be of an element type +one octet wide. Returns the buffer, its length, and the address of the +peer that sent it, as multiple values. On datagram sockets, sets +MSG_TRUNC so that the actual packet length is returned even if the +buffer was too small.")) (defmethod socket-receive ((socket socket) buffer length &key - oob peek waitall + oob peek waitall dontwait (element-type 'character)) (with-sockaddr-for (socket sockaddr) (let ((flags (logior (if oob sockint::MSG-OOB 0) (if peek sockint::MSG-PEEK 0) (if waitall sockint::MSG-WAITALL 0) + (if dontwait sockint::MSG-DONTWAIT 0) #+linux sockint::MSG-NOSIGNAL ;don't send us SIGPIPE (if (eql (socket-type socket) :datagram) sockint::msg-TRUNC 0)))) @@ -200,7 +204,10 @@ small")) sockaddr (sb-alien:addr sa-len)))) (cond - ((and (= len -1) (= sockint::EAGAIN (sb-unix::get-errno))) nil) + ((and (= len -1) + (member (sb-unix::get-errno) + (list sockint::EAGAIN sockint::EINTR))) + nil) ((= len -1) (socket-error "recvfrom")) (t (loop for i from 0 below len do (setf (elt buffer i) @@ -276,7 +283,7 @@ send(2) will be called instead. Returns the number of octets written.")) (cond ((and (= len -1) (member (sb-unix::get-errno) - '(sockint::EAGAIN sockint::EINTR))) + (list sockint::EAGAIN sockint::EINTR))) nil) ((= len -1) (socket-error "sendto")) @@ -340,22 +347,45 @@ calls CLOSE on that stream instead")) nil)))))) -(defgeneric socket-make-stream (socket &rest args) +(defgeneric socket-make-stream (socket &key input output + element-type external-format + buffering + timeout) (:documentation "Find or create a STREAM that can be used for IO on -SOCKET (which must be connected). ARGS are passed onto -SB-SYS:MAKE-FD-STREAM.")) - -(defmethod socket-make-stream ((socket socket) &rest args) +SOCKET \(which must be connected\). Specify whether the stream is for +INPUT, OUTPUT, or both \(it is an error to specify neither\). ELEMENT-TYPE +and EXTERNAL-FORMAT are as per OPEN. TIMEOUT specifies a read timeout +for the stream.")) + +(defmethod socket-make-stream ((socket socket) + &key input output + (element-type 'character) + (buffering :full) + (external-format :default) + timeout) + "Default method for SOCKET objects. An ELEMENT-TYPE of :DEFAULT +will construct a bivalent stream. Acceptable values for BUFFERING +are :FULL, :LINE and :NONE. Streams will have no TIMEOUT +by default. + The stream for SOCKET will be cached, and a second invocation of this +method will return the same stream. This may lead to oddities if this +function is invoked with inconsistent arguments \(e.g., one might request +an input stream and get an output stream in response\)." (let ((stream (and (slot-boundp socket 'stream) (slot-value socket 'stream)))) (unless stream - (setf stream (apply #'sb-sys:make-fd-stream - (socket-file-descriptor socket) - :name "a constant string" - :dual-channel-p t - args)) + (setf stream (sb-sys:make-fd-stream + (socket-file-descriptor socket) + :name "a socket" + :dual-channel-p t + :input input + :output output + :element-type element-type + :buffering buffering + :external-format external-format + :timeout timeout))) (setf (slot-value socket 'stream) stream) - (sb-ext:cancel-finalization socket)) + (sb-ext:cancel-finalization socket) stream))