X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=contrib%2Fsb-bsd-sockets%2Flocal.lisp;h=1c9e9ae81a1fffda9336fc90029a4a3dfe4427b6;hb=905df5c4bcb138a4d0423fca82eefd19efe952e7;hp=d77fee74364ce84bfd5d2e72b555cc86a3b3e3a7;hpb=8a3c76ab9725a199aa06a0abc018e096271a0f75;p=sbcl.git diff --git a/contrib/sb-bsd-sockets/local.lisp b/contrib/sb-bsd-sockets/local.lisp index d77fee7..1c9e9ae 100644 --- a/contrib/sb-bsd-sockets/local.lisp +++ b/contrib/sb-bsd-sockets/local.lisp @@ -5,8 +5,14 @@ (:documentation "Class representing local domain (AF_LOCAL) sockets, also known as unix-domain sockets.")) +(defmethod socket-namestring ((socket local-socket)) + (ignore-errors (socket-name socket))) + +(defmethod socket-peerstring ((socket local-socket)) + (ignore-errors (socket-peername socket))) + (defmethod make-sockaddr-for ((socket local-socket) - &optional sockaddr &rest address &aux (filename (first address))) + &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 @@ -24,3 +30,70 @@ also known as unix-domain sockets.")) (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))))