1 ;;;; win32 socket operations
\r
2 ;;;; these have all been done by hand since I can't seem
\r
3 ;;;; to get my head around the sb-grovel stuff
\r
5 ;;;; Winsock requires us to convert HANDLES to/from
\r
6 ;;;; file descriptors, so I've added an additional
\r
7 ;;;; package for the actual winsock alien defs, and then
\r
8 ;;;; in the sockint package, we implement wrappers that
\r
9 ;;;; handle the conversion.
\r
11 ;;; these are all of the basic structure alien defs
\r
12 (in-package :sockint)
\r
14 (sb-alien:load-shared-object "ws2_32.dll")
\r
15 (sb-alien:load-shared-object "msvcrt.dll")
\r
17 (sb-alien:define-alien-type nil
\r
19 (wVersion (unsigned 16))
\r
20 (wHighVersion (unsigned 16))
\r
21 (szDescription (array char 257))
\r
22 (szSystemStatus (array char 129))
\r
23 (iMaxSockets (unsigned 16))
\r
24 (iMaxUdpDg (unsigned 16))
\r
25 (lpVendorInfo sb-alien:c-string)))
\r
27 (sb-alien:define-alien-type nil
\r
32 (s_b4 (unsigned 8))))
\r
34 (sb-alien:define-alien-type nil
\r
36 (s_w1 (unsigned 16))
\r
37 (s_w2 (unsigned 16))))
\r
39 (sb-alien:define-alien-type nil
\r
41 (s_un_b (struct s_un_byte))
\r
42 (s_un_w (struct s_un_wide))
\r
43 (s_addr (unsigned 32))))
\r
45 (sb-alien:define-alien-type nil
\r
47 (s_union (union s_union))))
\r
49 (sb-alien:define-alien-type nil
\r
51 (sin_family (signed 16))
\r
52 (sin_port (array (unsigned 8) 2))
\r
53 (sin_addr (array (unsigned 8) 4))
\r
54 (sin_zero (array char 8))))
\r
56 (defconstant size-of-sockaddr-in 16)
\r
58 (defconstant size-of-sockaddr-un 16)
\r
60 (sb-alien:define-alien-type nil
\r
62 (sa_family (unsigned 16))
\r
63 (sa_data (array char 14))))
\r
65 (sb-alien:define-alien-type nil
\r
67 (h_name sb-alien:c-string)
\r
68 (h_aliases (* sb-alien:c-string))
\r
69 (h_addrtype sb-alien:short)
\r
70 (h_length sb-alien:short)
\r
71 (h_addr_list (* (* (unsigned 8))))))
\r
73 (sb-alien:define-alien-type nil
\r
75 (pname sb-alien:c-string)
\r
76 (p_aliases (* sb-alien:c-string))
\r
77 (p_proto (signed 16))))
\r
79 (sb-alien:define-alien-type socklen-t
\r
83 ;;; these are all non-HANDLE using, so are safe to have here
\r
84 (sb-alien:define-alien-routine "gethostbyaddr" (struct hostent)
\r
85 (addr sb-alien:c-string)
\r
89 (sb-alien:define-alien-routine "gethostbyname" (struct hostent)
\r
90 (addr sb-alien:c-string))
\r
92 (sb-alien:define-alien-routine "getservbyport" (struct servent)
\r
94 (proto sb-alien:c-string))
\r
96 (sb-alien:define-alien-routine "getservbyname" (struct servent)
\r
97 (name sb-alien:c-string)
\r
98 (proto sb-alien:c-string))
\r
100 (sb-alien:define-alien-routine "getprotobynumber" (struct protoent)
\r
103 (sb-alien:define-alien-routine "getprotobyname" (struct protoent)
\r
104 (name sb-alien:c-string))
\r
106 ;;; these are the alien references to the
\r
109 (in-package :win32sockint)
\r
111 (sb-alien:define-alien-routine "socket" int
\r
116 (sb-alien:define-alien-routine ("WSASocketA" wsa-socket) int
\r
120 (lpProtocolInfo (* t))
\r
124 (sb-alien:define-alien-routine "bind" int
\r
126 (name (* (struct sockint::sockaddr_in)))
\r
129 (sb-alien:define-alien-routine "getsockname" int
\r
131 (name (* (struct sockint::sockaddr_in)))
\r
132 (namelen int :in-out))
\r
134 (sb-alien:define-alien-routine "listen" int
\r
138 (sb-alien:define-alien-routine "accept" int
\r
140 (addr (* (struct sockint::sockaddr_in)))
\r
141 (addrlen int :in-out))
\r
143 (sb-alien:define-alien-routine "recv" int
\r
149 (sb-alien:define-alien-routine "recvfrom" int
\r
154 (from (* (struct sockint::sockaddr_in)))
\r
155 (fromlen (* sockint::socklen-t)))
\r
157 (sb-alien:define-alien-routine ("closesocket" close) int
\r
160 (sb-alien:define-alien-routine "connect" int
\r
162 (name (* (struct sockint::sockaddr_in)))
\r
165 (sb-alien:define-alien-routine "getpeername" int
\r
167 (name (* (struct sockint::sockaddr_in)))
\r
168 (namelen int :in-out))
\r
170 (sb-alien:define-alien-routine "getsockopt" int
\r
174 (optval sb-alien:c-string)
\r
175 (optlen int :in-out))
\r
177 (sb-alien:define-alien-routine ("ioctlsocket" ioctl) int
\r
180 (argp (unsigned 32) :in-out))
\r
182 (sb-alien:define-alien-routine "setsockopt" int
\r
190 ;;;; we are now going back to the normal sockint
\r
191 ;;;; package where we will redefine all of the above
\r
192 ;;;; functions, converting between HANDLES and fds
\r
194 (in-package :sockint)
\r
196 (sb-alien:define-alien-routine ("_get_osfhandle" fd->handle) sb-alien:long
\r
199 (sb-alien:define-alien-routine ("_open_osfhandle" handle->fd) int
\r
203 (defun socket (af type proto)
\r
204 (let* ((handle (win32sockint::wsa-socket af type proto nil 0 0))
\r
205 (fd (handle->fd handle 0)))
\r
208 (defun bind (fd &rest options)
\r
209 (let ((handle (fd->handle fd)))
\r
210 (apply #'win32sockint::bind handle options)))
\r
212 (defun getsockname (fd &rest options)
\r
213 (apply #'win32sockint::getsockname (fd->handle fd) options))
\r
215 (defun listen (fd &rest options)
\r
216 (apply #'win32sockint::listen (fd->handle fd) options))
\r
218 (defun accept (fd &rest options)
\r
220 (apply #'win32sockint::accept (fd->handle fd) options)
\r
223 (defun recv (fd &rest options)
\r
224 (apply #'win32sockint::recv (fd->handle fd) options))
\r
226 (defun recvfrom (fd &rest options)
\r
227 (apply #'win32sockint::recvfrom (fd->handle fd) options))
\r
229 (defun close (fd &rest options)
\r
230 (apply #'win32sockint::close (fd->handle fd) options))
\r
232 (defun connect (fd &rest options)
\r
233 (apply #'win32sockint::connect (fd->handle fd) options))
\r
235 (defun getpeername (fd &rest options)
\r
236 (apply #'win32sockint::getpeername (fd->handle fd) options))
\r
238 (defun getsockopt (fd &rest options)
\r
239 (apply #'win32sockint::getsockopt (fd->handle fd) options))
\r
241 (defun ioctl (fd &rest options)
\r
242 (apply #'win32sockint::ioctl (fd->handle fd) options))
\r
244 (defun setsockopt (fd &rest options)
\r
245 (apply #'win32sockint::setsockopt (fd->handle fd) options))
\r
247 (defmacro with-in-addr (name init &rest body)
\r
248 (declare (ignore init))
\r
249 `(with-alien ((,name (struct in_addr)))
\r
252 (defun in-addr-addr (addr)
\r
253 (sb-alien:slot (sb-alien:slot addr 's_union) 's_addr))
\r
255 (defmacro sockaddr-in-addr (addr)
\r
256 `(sb-alien:slot ,addr 'sin_addr))
\r
258 (defmacro sockaddr-in-family (addr)
\r
259 `(sb-alien:slot ,addr 'sin_family))
\r
261 (defmacro sockaddr-in-port (addr)
\r
262 `(sb-alien:slot ,addr 'sin_port))
\r
264 (defun allocate-sockaddr-in ()
\r
265 (sb-alien:make-alien (struct sockaddr_in)))
\r
267 (defun free-sockaddr-in (addr)
\r
268 (sb-alien:free-alien addr))
\r
270 (defmacro protoent-proto (ent)
\r
271 `(sb-alien:slot ,ent 'p_proto))
\r
273 (defmacro hostent-addresses (ent)
\r
274 `(sb-alien:slot ,ent 'h_addr_list))
\r
276 (defmacro hostent-aliases (ent)
\r
277 `(sb-alien:slot ,ent 'h_aliases))
\r
279 (defmacro hostent-length (ent)
\r
280 `(sb-alien:slot ,ent 'h_length))
\r
282 (defmacro hostent-name (ent)
\r
283 `(sb-alien:slot ,ent 'h_name))
\r
285 (defmacro hostent-type (ent)
\r
286 `(sb-alien:slot ,ent 'h_addrtype))
\r
288 (sb-alien:define-alien-routine ("WSAStartup" wsa-startup) int
\r
289 (wVersionRequested (unsigned 16))
\r
290 (lpWSAData (struct WSADATA) :out))
\r
292 (sb-alien:define-alien-routine ("WSAGetLastError" wsa-get-last-error) int)
\r
294 (defun make-wsa-version (major minor)
\r
295 (dpb minor (byte 8 8) major))
\r
297 (defun make-sockaddr (family)
\r
298 (let ((sa (make-alien (struct sockaddr))))
\r
299 (setf (slot sa 'sa_family) family)
\r
301 (setf (deref (slot sa 'sa_data) n) 0))
\r
307 ;; un-addr not implemented on win32
\r
308 (defun (setf sockaddr-un-family) (addr family) ())
\r
309 (defun (setf sockaddr-un-path) (addr family) ())
\r
310 (defun sockaddr-un-path (addr) ())
\r
311 (defun free-sockaddr-un (addr) ())
\r
312 (defun allocate-sockaddr-un () ())
\r