(:documentation "Deallocate a Socket Address object that was
created for SOCKET."))
-(defmacro with-sockaddr-for ((socket sockaddr sockaddr-args) &body body)
+(defmacro with-sockaddr-for ((socket sockaddr &optional sockaddr-args) &body body)
`(let ((,sockaddr (apply #'make-sockaddr-for ,socket nil ,sockaddr-args)))
(unwind-protect (progn ,@body)
(free-sockaddr-for ,socket ,sockaddr))))
values"))
(defmethod socket-accept ((socket socket))
- (with-sockaddr-for (socket sockaddr nil)
+ (with-sockaddr-for (socket sockaddr)
(let ((fd (sockint::accept (socket-file-descriptor socket)
sockaddr
(size-of-sockaddr socket))))
- (apply #'values
- (if (= fd -1)
- (socket-error "accept")
- (let ((s (make-instance (class-of socket)
- :type (socket-type socket)
- :protocol (socket-protocol socket)
- :descriptor fd)))
- (sb-ext:finalize s (lambda () (sockint::close fd)))))
- (multiple-value-list (bits-of-sockaddr socket sockaddr))))))
+ (cond
+ ((and (= fd -1) (= sockint::EAGAIN (sb-unix::get-errno)))
+ nil)
+ ((= fd -1) (socket-error "accept"))
+ (t (apply #'values
+ (let ((s (make-instance (class-of socket)
+ :type (socket-type socket)
+ :protocol (socket-protocol socket)
+ :descriptor fd)))
+ (sb-ext:finalize s (lambda () (sockint::close fd))))
+ (multiple-value-list (bits-of-sockaddr socket sockaddr))))))))
(defgeneric socket-connect (socket &rest address)
(:documentation "Perform the connect(2) call to connect SOCKET to a
family this may return multiple values"))
(defmethod socket-peername ((socket socket))
- (with-sockaddr-for (socket sockaddr address)
+ (with-sockaddr-for (socket sockaddr)
(when (= (sockint::getpeername (socket-file-descriptor socket)
sockaddr
(size-of-sockaddr socket))
that the socket is bound to, as multiple values."))
(defmethod socket-name ((socket socket))
- (with-sockaddr-for (socket sockaddr nil)
+ (with-sockaddr-for (socket sockaddr)
(when (= (sockint::getsockname (socket-file-descriptor socket)
sockaddr
(size-of-sockaddr socket))
&key
oob peek waitall
(element-type 'character))
- (with-sockaddr-for (socket sockaddr nil)
+ (with-sockaddr-for (socket sockaddr)
(let ((flags
(logior (if oob sockint::MSG-OOB 0)
(if peek sockint::MSG-PEEK 0)
flags
sockaddr
(sb-alien:cast sa-len (* integer)))))
- (when (= len -1) (socket-error "recvfrom"))
- (loop for i from 0 below len
- do (setf (elt buffer i) (sb-alien:deref copy-buffer i)))
- (apply #'values buffer len (multiple-value-list
- (bits-of-sockaddr socket sockaddr)))))
+ (cond
+ ((and (= len -1) (= sockint::EAGAIN (sb-unix::get-errno))) nil)
+ ((= len -1) (socket-error "recvfrom"))
+ (t (loop for i from 0 below len
+ do (setf (elt buffer i) (sb-alien:deref copy-buffer i)))
+ (apply #'values buffer len (multiple-value-list
+ (bits-of-sockaddr socket sockaddr)))))))
(sb-alien:free-alien copy-buffer))))))
`(progn
(define-condition ,name (socket-error)
((symbol :reader socket-error-symbol :initform (quote ,symbol))))
+ (export ',name)
(push (cons ,symbol (quote ,name)) *conditions-for-errno*)))
(defparameter *conditions-for-errno* nil)
;;; this needs the rest of the list adding to it, really. They also
-;;; need
-;;; - conditions to be exported in the DEFPACKAGE form
-;;; - symbols to be added to constants.ccon
+;;; need symbols to be added to constants.ccon
;;; I haven't yet thought of a non-kludgey way of keeping all this in
;;; the same place
(define-socket-condition sockint::EADDRINUSE address-in-use-error)
(define-socket-condition sockint::EAGAIN interrupted-error)
(define-socket-condition sockint::EBADF bad-file-descriptor-error)
(define-socket-condition sockint::ECONNREFUSED connection-refused-error)
+(define-socket-condition sockint::ETIMEDOUT operation-timeout-error)
(define-socket-condition sockint::EINTR interrupted-error)
(define-socket-condition sockint::EINVAL invalid-argument-error)
(define-socket-condition sockint::ENOBUFS no-buffers-error)