sb-bsd-sockets: Implement NON-BLOCKING-MODE on Windows
[sbcl.git] / contrib / sb-bsd-sockets / misc.lisp
1 (in-package :sb-bsd-sockets)
2
3 ;;; Miscellaneous things, placed here until I can find a logically more
4 ;;; coherent place to put them
5
6 ;;; I don't want to provide a complete interface to unix file
7 ;;; operations, for example, but being about to set O_NONBLOCK on a
8 ;;; socket is a necessary operation.
9
10 ;;; XXX bad (sizeof (int) ==4 ) assumptions
11
12 (defgeneric non-blocking-mode (socket)
13   (:documentation "Is SOCKET in non-blocking mode?"))
14
15 #-win32
16 (defmethod non-blocking-mode ((socket socket))
17   (let ((fd (socket-file-descriptor socket)))
18     (sb-alien:with-alien ((arg integer))
19                          (> (logand
20                              (sockint::fcntl fd sockint::f-getfl arg)
21                              sockint::o-nonblock)
22                             0))))
23
24 #+win32
25 (defmethod non-blocking-mode ((socket socket))
26   (slot-value socket 'non-blocking-p))
27
28 (defgeneric (setf non-blocking-mode) (non-blocking-p socket)
29   (:documentation "Put SOCKET in non-blocking mode - or not, according to NON-BLOCKING-P"))
30
31 #-win32
32 (defmethod (setf non-blocking-mode) (non-blocking-p (socket socket))
33   (declare (optimize (speed 3)))
34   (let* ((fd (socket-file-descriptor socket))
35          (arg1 (the (signed-byte 32) (sockint::fcntl fd sockint::f-getfl 0)))
36          (arg2
37           (if non-blocking-p
38               (logior arg1 sockint::o-nonblock)
39             (logand (lognot sockint::o-nonblock) arg1))))
40     (when (= (the (signed-byte 32) -1)
41              (the (signed-byte 32)
42                (sockint::fcntl fd sockint::f-setfl arg2)))
43       (socket-error "fcntl"))
44     non-blocking-p))
45
46 #+win32
47 (defmethod (setf non-blocking-mode)
48     (non-blocking-p (socket socket))
49   (declare (optimize (speed 3)))
50   (setf (slot-value socket 'non-blocking-p)
51         (when non-blocking-p t))
52   (let ((fd (socket-file-descriptor socket)))
53     (when (= (the (signed-byte 32) -1)
54              (the (signed-byte 32)
55                (sockint::ioctl fd sockint::FIONBIO (if non-blocking-p 1 0))))
56       (socket-error "ioctl(FIONBIO)"))
57     (when non-blocking-p t)))