1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
3 ;;; --- Various helpers for bsd-sockets.
6 (in-package :net.sockets
)
10 (deftype ipv4-array
() '(ub8-sarray 4))
11 (deftype ipv6-array
() '(ub16-sarray 8))
13 ;;;; Byte-swap functions
17 (logior (ash (logand (the ub16 short
) #x00FF
) 8)
18 (ash (logand (the ub16 short
) #xFF00
) -
8))
26 (logior (ash (logand (the ub32 long
) #x000000FF
) 24)
27 (ash (logand (the ub32 long
) #x0000FF00
) 8)
28 (ash (logand (the ub32 long
) #x00FF0000
) -
8)
29 (ash (logand (the ub32 long
) #xFF000000
) -
24))
35 ;;;; Conversion between address formats
37 (defun copy-simple-array-ub16-to-alien-vector (lisp-vec alien-vec
)
38 (declare (type ipv6-array lisp-vec
))
40 (setf (mem-aref alien-vec
:uint16 i
)
41 (htons (aref lisp-vec i
)))))
43 (defun map-ipv4-vector-to-ipv6 (addr)
44 (declare (type ipv4-array addr
))
45 (let ((ipv6addr (make-array 8 :element-type
'ub16
47 ;; setting the IPv4 marker
48 (setf (aref ipv6addr
5) #xFFFF
)
49 ;; setting the first two bytes
50 (setf (aref ipv6addr
6) (+ (ash (aref addr
0) 8)
52 ;; setting the last two bytes
53 (setf (aref ipv6addr
7) (+ (ash (aref addr
2) 8)
57 (defun map-ipv6-vector-to-ipv4 (addr)
58 (declare (type ipv6-array addr
))
59 (let ((ipv4addr (make-array 4 :element-type
'ub8
61 (setf (aref ipv4addr
0) (ldb (byte 8 8) (aref addr
6)))
62 (setf (aref ipv4addr
1) (ldb (byte 8 0) (aref addr
6)))
63 (setf (aref ipv4addr
2) (ldb (byte 8 8) (aref addr
7)))
64 (setf (aref ipv4addr
3) (ldb (byte 8 0) (aref addr
7)))
67 ;;; From CLOCC's PORT library.
68 (defun vector-to-integer (vector)
69 "Convert a vector to a 32-bit unsigned integer."
70 (coercef vector
'ipv4-array
)
71 (+ (ash (aref vector
0) 24)
72 (ash (aref vector
1) 16)
73 (ash (aref vector
2) 8)
76 (defun integer-to-vector (ipaddr)
77 "Convert a 32-bit unsigned integer to a vector."
78 (check-type ipaddr ub32
"an '(unsigned-byte 32)")
79 (let ((vector (make-array 4 :element-type
'ub8
)))
80 (setf (aref vector
0) (ldb (byte 8 24) ipaddr
)
81 (aref vector
1) (ldb (byte 8 16) ipaddr
)
82 (aref vector
2) (ldb (byte 8 8) ipaddr
)
83 (aref vector
3) (ldb (byte 8 0) ipaddr
))
86 (defun in6-addr-to-ipv6-array (in6-addr)
87 (let ((vector (make-array 8 :element-type
'ub16
)))
90 (ntohs (mem-aref in6-addr
:uint16 i
))))
93 ;;;; Constructors for SOCKADDR_* structs
95 (defun make-sockaddr-in (sin ub8-vector
&optional
(portno 0))
96 (declare (type ipv4-array ub8-vector
) (type ub16 portno
))
97 (bzero sin size-of-sockaddr-in
)
98 (with-foreign-slots ((family addr port
) sin sockaddr-in
)
100 (setf addr
(htonl (vector-to-integer ub8-vector
)))
101 (setf port
(htons portno
)))
104 (defmacro with-sockaddr-in
((var address
&optional
(port 0)) &body body
)
105 `(with-foreign-object (,var
'sockaddr-in
)
106 (make-sockaddr-in ,var
,address
,port
)
109 (defun make-sockaddr-in6 (sin6 ub16-vector
&optional
(portno 0))
110 (declare (type ipv6-array ub16-vector
) (type ub16 portno
))
111 (bzero sin6 size-of-sockaddr-in6
)
112 (with-foreign-slots ((family addr port
) sin6 sockaddr-in6
)
113 (setf family af-inet6
)
114 (copy-simple-array-ub16-to-alien-vector ub16-vector addr
)
115 (setf port
(htons portno
)))
118 (defmacro with-sockaddr-in6
((var address
&optional port
) &body body
)
119 `(with-foreign-object (,var
'sockaddr-in6
)
120 (make-sockaddr-in6 ,var
,address
,port
)
123 (defun make-sockaddr-un (sun string
)
124 (declare (type string string
))
125 (bzero sun size-of-sockaddr-un
)
126 (with-foreign-slots ((family path
) sun sockaddr-un
)
127 (setf family af-local
)
128 (with-foreign-string (c-string string
)
129 (loop :for off
:below
(1- unix-path-max
)
130 :do
(setf (mem-aref path
:uint8 off
)
131 (mem-aref c-string
:uint8 off
)))))
134 (defmacro with-sockaddr-un
((var address
) &body body
)
135 `(with-foreign-object (,var
'sockaddr-un
)
136 (make-sockaddr-un ,var
,address
)
139 (defmacro with-sockaddr-storage
((var) &body body
)
140 `(with-foreign-object (,var
'sockaddr-storage
)
141 (bzero ,var size-of-sockaddr-storage
)
144 (defmacro with-socklen
((var value
) &body body
)
145 `(with-foreign-object (,var
'socklen
)
146 (setf (mem-aref ,var
'socklen
) ,value
)
149 (defmacro with-sockaddr-storage-and-socklen
((ss-var size-var
) &body body
)
150 `(with-sockaddr-storage (,ss-var
)
151 (with-socklen (,size-var size-of-sockaddr-storage
)
156 (defun %to-octets
(buff ef start end
)
157 (babel:string-to-octets buff
:start start
:end end
158 :encoding
(babel:external-format-encoding ef
)))
160 (defun ensure-number (value &key
(start 0) end
(radix 10) (type t
) (errorp t
))
164 (ignore-errors (parse-integer value
:start start
:end end
165 :radix radix
:junk-allowed nil
)))
168 ((typep parsed type
) parsed
)
169 (errorp (error 'parse-error
)))))
171 (defun ensure-string-or-unsigned-byte (thing &key
(type t
) (radix 10) (errorp t
))
172 (or (and (symbolp thing
) (string-downcase thing
))
173 (ensure-number thing
:type type
:radix radix
:errorp nil
)
174 (and (stringp thing
) thing
)
175 (if errorp
(error 'parse-error
) nil
)))
177 (defun lisp->c-bool
(val)
180 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
181 (defun compute-flags (flags args
)
182 (loop :with flag-combination
:= 0
183 :for cons
:on args
:by
#'cddr
184 :for flag
:= (car cons
)
185 :for val
:= (cadr cons
)
186 :for const
:= (cdr (assoc flag flags
))
188 (when (not (constantp val
)) (return* nil
))
189 (setf flag-combination
(logior flag-combination const
))
190 :finally
(return flag-combination
))))
192 (defun set-function-docstring (function docstring
)
193 (setf (documentation function
'function
) docstring
))
195 (defun unset-method-docstring (gf qualifiers specializers
)
196 (setf (documentation (find-method gf qualifiers
(mapcar #'find-class specializers
)) t
) nil
))