X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=contrib%2Fsb-bsd-sockets%2Flocal.lisp;h=8ca769bb350202ba1ef0af2931794e36eb3b4dec;hb=b4031d85bc80194c3cd44d8dee7c51d82098c193;hp=363f0514772be8faaf34df5d60855985245f237a;hpb=3b91bf9e9daf110b35dd8d5b6ca5a88e0fb0f13b;p=sbcl.git diff --git a/contrib/sb-bsd-sockets/local.lisp b/contrib/sb-bsd-sockets/local.lisp index 363f051..8ca769b 100644 --- a/contrib/sb-bsd-sockets/local.lisp +++ b/contrib/sb-bsd-sockets/local.lisp @@ -1,40 +1,93 @@ (in-package :sb-bsd-sockets) -#||

Local (unix) domain sockets

- -Local domain (AF_LOCAL) sockets are also known as Unix-domain sockets, but were -renamed by POSIX presumably on the basis that they may be -available on other systems too. - -A local socket address is a string, which is used to create a node -in the local filesystem. This means of course that they cannot be used across -a network. - -||# - (defclass local-socket (socket) - ((family :initform sockint::af-local))) + ((family :initform sockint::af-local)) + (:documentation "Class representing local domain (AF_LOCAL) sockets, +also known as unix-domain sockets.")) -(defmethod make-sockaddr-for ((socket local-socket) &optional sockaddr &rest address &aux (filename (first address))) +(defmethod make-sockaddr-for ((socket local-socket) + &optional sockaddr &rest address &aux (filename (first address))) (let ((sockaddr (or sockaddr (sockint::allocate-sockaddr-un)))) (setf (sockint::sockaddr-un-family sockaddr) sockint::af-local) (when filename - (loop for c across filename - ;; XXX magic constant ew ew ew. should grovel this from - ;; system headers - for i from 0 to (min 107 (1- (length filename))) - do (setf (sockint::sockaddr-un-path sockaddr i) (char-code c)) - finally - (setf (sockint::sockaddr-un-path sockaddr (1+ i)) 0))) + (setf (sockint::sockaddr-un-path sockaddr) filename)) sockaddr)) +(defmethod free-sockaddr-for ((socket local-socket) sockaddr) + (sockint::free-sockaddr-un sockaddr)) + (defmethod size-of-sockaddr ((socket local-socket)) sockint::size-of-sockaddr-un) (defmethod bits-of-sockaddr ((socket local-socket) sockaddr) - "Returns filename of SOCKADDR" - (let ((name (sb-c-call::%naturalize-c-string - (sb-sys:sap+ (sockint::array-data-address sockaddr) - sockint::offset-of-sockaddr-un-path)))) + "Return the file name of the local socket address SOCKADDR." + (let ((name (sockint::sockaddr-un-path sockaddr))) (if (zerop (length name)) nil name))) +(defclass local-abstract-socket (local-socket) () + (:documentation "Class representing local domain (AF_LOCAL) sockets with +addresses in the abstract namespace.")) + +(defmethod make-sockaddr-for ((socket local-abstract-socket) + &optional sockaddr &rest address + &aux (path (first address))) + (let ((sockaddr (or sockaddr (sockint::allocate-sockaddr-un-abstract))) + (len 0)) + (setf (sockint::sockaddr-un-abstract-family sockaddr) sockint::af-local) + ;;First byte of the path is always 0. + (setf (sb-alien:deref (sockint::sockaddr-un-abstract-path sockaddr) 0) 0) + + (when path + (when (stringp path) + (setf path (sb-ext:string-to-octets path))) + (setf len (min (- sockint::size-of-sockaddr-un-abstract 3) (length path))) + ;;We fill in the rest of the path starting at index 1. + (loop for i from 0 below len + do (setf (sb-alien:deref (sockint::sockaddr-un-abstract-path + sockaddr) + (1+ i)) + (elt path i)))) + (values sockaddr (+ 3 len)))) + +(defmethod free-sockaddr-for ((socket local-abstract-socket) sockaddr) + (sockint::free-sockaddr-un-abstract sockaddr)) + +(defmethod size-of-sockaddr ((socket local-abstract-socket)) + sockint::size-of-sockaddr-un-abstract) + +(defmethod bits-of-sockaddr ((socket local-abstract-socket) sockaddr) + "Return the contents of the local socket address SOCKADDR." + (let* ((path-len (- sockint::size-of-sockaddr-un-abstract 3)) + (path (make-array `(,path-len) + :element-type '(unsigned-byte 8) + :initial-element 0))) + ;;exclude the first byte (it's always null) of the address + (loop for i from 1 to path-len + do (setf (elt path (1- i)) + (sb-alien:deref (sockint::sockaddr-un-abstract-path sockaddr) + i))) + path)) + +(defmethod socket-connect ((socket local-abstract-socket) &rest peer + &aux (path (first peer))) + (multiple-value-bind (sockaddr addr-len) + (make-sockaddr-for socket nil path) + (unwind-protect + (if (= (sockint::connect (socket-file-descriptor socket) + sockaddr + addr-len) + -1) + (socket-error "connect")) + (free-sockaddr-for socket sockaddr)))) + +(defmethod socket-bind ((socket local-abstract-socket) + &rest address &aux (path (first address))) + (multiple-value-bind (sockaddr addr-len) + (make-sockaddr-for socket nil path) + (unwind-protect + (if (= (sockint::bind (socket-file-descriptor socket) + sockaddr + addr-len) + -1) + (socket-error "bind")) + (free-sockaddr-for socket sockaddr))))