X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=inline;f=contrib%2Fsb-bsd-sockets%2Flocal.lisp;h=1c9e9ae81a1fffda9336fc90029a4a3dfe4427b6;hb=a71c8bac4722c4bb28758f27c41362a8c961831c;hp=ccc220b08d1e68089284cce941f3ec31a1bdbba3;hpb=d4c7ab04ed10729a2cfa3321f4382d8a218ad958;p=sbcl.git
diff --git a/contrib/sb-bsd-sockets/local.lisp b/contrib/sb-bsd-sockets/local.lisp
index ccc220b..1c9e9ae 100644
--- a/contrib/sb-bsd-sockets/local.lisp
+++ b/contrib/sb-bsd-sockets/local.lisp
@@ -1,21 +1,18 @@
(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))
+ (: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)))
-(defclass local-socket (socket)
- ((family :initform sockint::af-local)))
+(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)))
+(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
@@ -33,3 +30,70 @@ a network.
(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))))