1 (in-package :bsd-sockets
)
3 #||
<h2
>INET-domain sockets
</h2
>
5 <p
>The TCP and UDP sockets that you know and love. Some representation issues
:
7 <li
>These functions do not accept hostnames directly
: see
<a href
="#name-service">name resolution
</a
>
8 <li
>Internet
<b
>addresses
</b
> are represented by vectors of
<tt
>(unsigned-byte 8)</tt
> - viz.
<tt
>#(127 0 0 1)</tt
>.
<b
>Ports
</b
> are just integers
: <tt
>6010</tt
>. No conversion between network- and host-order data is needed from the user of this package.
9 <li
><b
><i
>socket addresses
</i
></b
> are represented by the two values for
<b
>address
</b
> and
<b
>port
</b
>, so for example
, <tt
>(<a href
="#SOCKET-CONNECT">socket-connect
</a
> s
#(192.168
.1.1) 80)</tt
>
14 ;;; Our class and constructor
16 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
17 (defclass inet-socket
(socket)
18 ((family :initform sockint
::AF-INET
))))
20 ;;; XXX should we *...* this?
21 (defparameter inet-address-any
(vector 0 0 0 0))
23 ;;; binding a socket to an address and port. Doubt that anyone's
24 ;;; actually using this much, to be honest.
26 (defun make-inet-address (dotted-quads)
27 "Return a vector of octets given a string DOTTED-QUADS in the format
30 (mapcar #'parse-integer
31 (split dotted-quads nil
'(#\.
)))
34 ;;; getprotobyname only works in the internet domain, which is why this
36 (defun get-protocol-by-name (name) ;exported
37 "Returns the network protocol number associated with the string NAME,
38 using getprotobyname(2) which typically looks in NIS or /etc/protocols"
39 ;; for extra brownie points, could return canonical protocol name
40 ;; and aliases as extra values
41 (let ((ent (sockint::foreign-vector
(sockint::getprotobyname name
) 1
42 sockint
::size-of-protoent
)))
43 (sockint::protoent-proto ent
)))
47 ;;; (1) sockaddrs are represented as the semi-foreign array-of-octets
49 ;;; (2) a protocol provides make-sockaddr-for, size-of-sockaddr,
52 (defmethod make-sockaddr-for ((socket inet-socket
) &optional sockaddr
&rest address
&aux
(host (first address
)) (port (second address
)))
53 (let ((sockaddr (or sockaddr
(sockint::allocate-sockaddr-in
))))
55 ;; port and host are represented in C as "network-endian" unsigned
56 ;; integers of various lengths. This is stupid. The value of the
57 ;; integer doesn't matter (and will change depending on your
58 ;; machine's endianness); what the bind(2) call is interested in
59 ;; is the pattern of bytes within that integer.
61 ;; We have no truck with such dreadful type punning. Octets to
62 ;; octets, dust to dust.
64 (setf (sockint::sockaddr-in-family sockaddr
) sockint
::af-inet
)
65 (setf (sockint::sockaddr-in-port sockaddr
0) (ldb (byte 8 8) port
))
66 (setf (sockint::sockaddr-in-port sockaddr
1) (ldb (byte 8 0) port
))
68 (setf (sockint::sockaddr-in-addr sockaddr
0) (elt host
0))
69 (setf (sockint::sockaddr-in-addr sockaddr
1) (elt host
1))
70 (setf (sockint::sockaddr-in-addr sockaddr
2) (elt host
2))
71 (setf (sockint::sockaddr-in-addr sockaddr
3) (elt host
3)))
74 (defmethod size-of-sockaddr ((socket inet-socket
))
75 sockint
::size-of-sockaddr-in
)
77 (defmethod bits-of-sockaddr ((socket inet-socket
) sockaddr
)
78 "Returns address and port of SOCKADDR as multiple values"
81 (sockint::sockaddr-in-addr sockaddr
0)
82 (sockint::sockaddr-in-addr sockaddr
1)
83 (sockint::sockaddr-in-addr sockaddr
2)
84 (sockint::sockaddr-in-addr sockaddr
3))
85 (+ (* 256 (sockint::sockaddr-in-port sockaddr
0))
86 (sockint::sockaddr-in-port sockaddr
1))))
89 (defun make-inet-socket (type protocol
)
90 "Make an INET socket. Deprecated in favour of make-instance"
91 (make-instance 'inet-socket
:type type
:protocol protocol
))