;;;; -*- Mode: Lisp -*- ;;;; Foreign functions defined by ECL's DFFI, used for #+ecl-bytecmp only. ;;;; See LICENSE for licensing information. (in-package :usocket) #+(and ecl-bytecmp windows) (eval-when (:load-toplevel :execute) (ffi:load-foreign-library "ws2_32.dll" :module "ws2_32")) #+(and ecl-bytecmp windows) (progn (ffi:def-function ("gethostname" c-gethostname) ((name (* :unsigned-char)) (len :int)) :returning :int :module "ws2_32") (defun get-host-name () "Returns the hostname" (ffi:with-foreign-object (name '(:array :unsigned-char 256)) (when (zerop (c-gethostname (ffi:char-array-to-pointer name) 256)) (ffi:convert-from-foreign-string name)))) (ffi:def-foreign-type ws-socket :unsigned-int) (ffi:def-foreign-type ws-dword :unsigned-long) (ffi:def-foreign-type ws-event :unsigned-int) (ffi:def-struct wsa-network-events (network-events :long) (error-code (:array :int 10))) (ffi:def-function ("WSACreateEvent" wsa-event-create) () :returning ws-event :module "ws2_32") (ffi:def-function ("WSACloseEvent" c-wsa-event-close) ((event-object ws-event)) :returning :int :module "ws2_32") (defun wsa-event-close (ws-event) (not (zerop (c-wsa-event-close ws-event)))) (ffi:def-function ("WSAEnumNetworkEvents" wsa-enum-network-events) ((socket ws-socket) (event-object ws-event) (network-events (* wsa-network-events))) :returning :int :module "ws2_32") (ffi:def-function ("WSAEventSelect" wsa-event-select) ((socket ws-socket) (event-object ws-event) (network-events :long)) :returning :int :module "ws2_32") (ffi:def-function ("WSAWaitForMultipleEvents" c-wsa-wait-for-multiple-events) ((number-of-events ws-dword) (events (* ws-event)) (wait-all-p :int) (timeout ws-dword) (alertable-p :int)) :returning ws-dword :module "ws2_32") (defun wsa-wait-for-multiple-events (number-of-events events wait-all-p timeout alertable-p) (c-wsa-wait-for-multiple-events number-of-events events (if wait-all-p -1 0) timeout (if alertable-p -1 0))) (ffi:def-function ("ioctlsocket" wsa-ioctlsocket) ((socket ws-socket) (cmd :long) (argp (* :unsigned-long))) :returning :int :module "ws2_32") (ffi:def-function ("WSAGetLastError" wsa-get-last-error) () :returning :int :module "ws2_32") (defun maybe-wsa-error (rv &optional socket) (unless (zerop rv) (raise-usock-err (wsa-get-last-error) socket))) (defun bytes-available-for-read (socket) (ffi:with-foreign-object (int-ptr :unsigned-long) (maybe-wsa-error (wsa-ioctlsocket (socket-handle socket) fionread int-ptr) socket) (let ((int (ffi:deref-pointer int-ptr :unsigned-long))) (prog1 int (when (plusp int) (setf (state socket) :read)))))) (defun map-network-events (func network-events) (let ((event-map (ffi:get-slot-value network-events 'wsa-network-events 'network-events)) (error-array (ffi:get-slot-pointer network-events 'wsa-network-events 'error-code))) (unless (zerop event-map) (dotimes (i fd-max-events) (unless (zerop (ldb (byte 1 i) event-map)) (funcall func (ffi:deref-array error-array '(:array :int 10) i))))))) (defun update-ready-and-state-slots (sockets) (dolist (socket sockets) (if (%ready-p socket) (progn (setf (state socket) :READ)) (ffi:with-foreign-object (network-events 'wsa-network-events) (let ((rv (wsa-enum-network-events (socket-handle socket) 0 network-events))) (if (zerop rv) (map-network-events #'(lambda (err-code) (if (zerop err-code) (progn (setf (state socket) :READ) (when (stream-server-usocket-p socket) (setf (%ready-p socket) t))) (raise-usock-err err-code socket))) network-events) (maybe-wsa-error rv socket))))))) (defun os-wait-list-%wait (wait-list) (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event)) (defun (setf os-wait-list-%wait) (value wait-list) (setf (ffi:deref-pointer (wait-list-%wait wait-list) 'ws-event) value)) (defun free-wait-list (wl) (when (wait-list-p wl) (unless (null (wait-list-%wait wl)) (wsa-event-close (os-wait-list-%wait wl)) (ffi:free-foreign-object (wait-list-%wait wl)) (setf (wait-list-%wait wl) nil)))) (defun %setup-wait-list (wait-list) (setf (wait-list-%wait wait-list) (ffi:allocate-foreign-object 'ws-event)) (setf (os-wait-list-%wait wait-list) (wsa-event-create)) (ext:set-finalizer wait-list #'free-wait-list)) (defun os-socket-handle (usocket) (socket-handle usocket)) ) ; #+(and ecl-bytecmp windows)