Thanks to Anton Kovalenko.
0))))
#+win32
-(defmethod non-blocking-mode ((socket socket)) 0)
+(defmethod non-blocking-mode ((socket socket))
+ (slot-value socket 'non-blocking-p))
(defgeneric (setf non-blocking-mode) (non-blocking-p socket)
(:documentation "Put SOCKET in non-blocking mode - or not, according to NON-BLOCKING-P"))
non-blocking-p))
#+win32
-(defmethod (setf non-blocking-mode) (non-blocking-p (socket socket)) 0)
-;; (sb-alien:with-alien ((mode (unsigned 32)))
-;; (if non-blocking-p (setf mode 1))
-;; (ioctlsocket socket FIONBIO mode)))
-
+(defmethod (setf non-blocking-mode)
+ (non-blocking-p (socket socket))
+ (declare (optimize (speed 3)))
+ (setf (slot-value socket 'non-blocking-p)
+ (when non-blocking-p t))
+ (let ((fd (socket-file-descriptor socket)))
+ (when (= (the (signed-byte 32) -1)
+ (the (signed-byte 32)
+ (sockint::ioctl fd sockint::FIONBIO (if non-blocking-p 1 0))))
+ (socket-error "ioctl(FIONBIO)"))
+ (when non-blocking-p t)))
(let ((*name-service-errno* (get-name-service-errno errno)))
;; Comment next to NETDB_INTERNAL in netdb.h says "See errno.".
;; This special case treatment hasn't actually been tested yet.
- #-win32
- (if (= *name-service-errno* sockint::NETDB-INTERNAL)
+ (if (and #-win32 (= *name-service-errno* sockint::NETDB-INTERNAL))
(socket-error where)
(let ((condition
(condition-for-name-service-errno *name-service-errno*)))
(type :initarg :type
:reader socket-type
:documentation "Type of the socket: :STREAM or :DATAGRAM.")
+ #+win32
+ (non-blocking-p :type (member t nil) :initform nil)
(stream))
(:documentation "Common base class of all sockets, not meant to be
directly instantiated.")))
:external-format external-format
:timeout timeout
:auto-close auto-close
- :serve-events serve-events))
+ :serve-events (and serve-events #+win32 nil)))
(setf (slot-value socket 'stream) stream))
(sb-ext:cancel-finalization socket)
stream))
(socket-error-syscall c)
(or (socket-error-symbol c) (socket-error-errno c))
#+cmu (sb-unix:get-unix-error-msg num)
- #+sbcl (sb-int:strerror num)))))
+ #+sbcl
+ #+win32 (sb-win32::get-last-error-message num)
+ #-win32 (sb-int:strerror num)))))
(:documentation "Common base class of socket related conditions."))
;;; watch out for slightly hacky symbol punning: we use both the value
(if (= -1 (sockint::getsockopt (socket-file-descriptor socket)
,find-level ,number
(sb-alien:addr buffer)
- (sb-alien:addr size)))
+ #+win32 size
+ #-win32 (sb-alien:addr size)))
(socket-error "getsockopt")
(,mangle-return buffer size)))
`(error 'unsupported-operator
(and (> (socket-file-descriptor s) 1) t))
t)
-(deftest* (make-inet-socket-wrong :fails-on :win32)
+(deftest* (make-inet-socket-wrong)
;; fail to make a socket: check correct error return. There's no nice
;; way to check the condition stuff on its own, which is a shame
(handler-case
(:no-error nil))
t)
-(deftest* (make-inet-socket-keyword-wrong :fails-on :win32)
+(deftest* (make-inet-socket-keyword-wrong)
;; same again with keywords
(handler-case
(make-instance 'inet-socket :type :stream :protocol :udp)
t)
-(deftest* (non-block-socket :fails-on :win32)
+(deftest* (non-block-socket)
(let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)))
(setf (non-blocking-mode s) t)
(non-blocking-mode s))
(address-in-use-error () t)))
t)
-(deftest* (simple-sockopt-test :fails-on :win32)
+(deftest* (simple-sockopt-test)
;; test we can set SO_REUSEADDR on a socket and retrieve it, and in
;; the process that all the weird macros in sockopt happened right.
(let ((s (make-instance 'inet-socket :type :stream :protocol (get-protocol-by-name "tcp"))))
(:integer ENETUNREACH "WSAENETUNREACH")
(:integer ENOTCONN "WSAENOTCONN")
(:integer inaddr-any "INADDR_ANY")
+ (:integer FIONBIO "FIONBIO")
;; for socket-receive