(:structure sockaddr-un ("struct sockaddr_un"
(integer family "sa_family_t" "sun_family")
(c-string path "char" "sun_path")))
+ (:structure sockaddr-un-abstract ("struct sockaddr_un"
+ (integer family "sa_family_t" "sun_family")
+ ((array (unsigned 8)) path "char" "sun_path")))
(:structure hostent ("struct hostent"
(c-string-pointer name "char *" "h_name")
((* c-string) aliases "char **" "h_aliases")
(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))))