Conditionally compile Netlink helpers and classes only on Linux
[iolib.git] / src / sockets / base-sockets.lisp
blobc9fe54f522d087d6976b4163de7c6d4b3765210e
1 ;;;; -*- Mode: Lisp; indent-tabs-mode: nil -*-
2 ;;;
3 ;;; --- Base socket classes.
4 ;;;
6 (in-package :iolib.sockets)
8 ;;;; Sockets
10 (defclass socket (dual-channel-fd-mixin)
11 ((address-family :initarg :address-family :accessor socket-address-family)
12 (protocol :initarg :protocol :accessor socket-protocol)
13 (bound :initform nil :reader socket-bound-p :type boolean))
14 (:documentation "Base class for sockets."))
15 (unset-method-docstring #'socket-address-family () '(socket))
16 (set-function-docstring 'socket-address-family "Return the address family of a socket.")
17 (unset-method-docstring #'socket-protocol () '(socket))
18 (set-function-docstring 'socket-protocol "Return the protocol of a socket.")
20 (defgeneric make-socket (&key address-family type connect ipv6 external-format
21 &allow-other-keys)
22 (:documentation "Create an instance of a subclass of SOCKET. ADDRESS-FAMILY, TYPE, CONNECT and IPV6
23 are used to specify the kind of socket to create.
25 * ADDRESS-FAMILY - :INTERNET, :LOCAL (or :FILE as synonim), or :NETLINK(on Linux)
26 * TYPE - :STREAM, :DATAGRAM or :RAW
27 * CONNECT - :ACTIVE or :PASSIVE
28 * IPV6 - if NIL, create an IPv4 socket, otherwise an IPv6 socket.
30 To initialize the socket, the following keyword arguments can be used depending on ADDRESS-FAMILY, TYPE and CONNECT:
31 * :local-host - a hostname designator or NIL. If non-null the socket will be bound to this address
32 * :local-port - a port designator or NIL. If LOCAL-HOST is non-null, bind the socket to this port. If NIL, choose a random port
33 * :remote-host - a hostname designator or NIL. If non-null the socket will be connected to this address
34 * :remote-port - a port designator. If REMOTE-HOST is non-null, connect the socket to this port
35 * :local-filename - a string or NIL. If non-null the socket will be bound to this file
36 * :remote-filename - a string or NIL. If non-null the socket will be connected to this file
37 * :backlog - a positive integer or NIL. Specifies the length of the incomming connection queue and can't be larger than +MAX-BACKLOG-SIZE+. If NIL, default is *DEFAULT-BACKLOG-SIZE*
38 * :reuse-address: a boolean(default T). set option SO_REUSEADDR if LOCAL-HOST is non-null
39 * :keepalive - a boolean. set option SO_KEEPALIVE
40 * :nodelay - a boolean. set option SO_NODELAY
41 * :interface - a string. set option SO_BINDTODEVICE to this interface
42 * :input-buffer-size - a positive integer. Create the stream input buffer of this size
43 * :output-buffer-size - a positive integer. Create the stream output buffer of this size
44 * :multicast-groups - a non-negative integer. Accept messages sent to those multicast groups
46 Glossary:
47 * hostname designator: an instance of INET-ADDRESS or any object accepted by LOOKUP-HOST. IPV6 is passed to LOOKUP-HOST as is
48 * port designator: any object accepted by LOOKUP-SERVICE
50 :address-family :INTERNET :type :STREAM :connect :ACTIVE
51 * Valid keyword args: :LOCAL-HOST, :LOCAL-PORT, :REMOTE-HOST, :REMOTE-PORT, :REUSE-ADDRESS, :KEEPALIVE, :NODELAY, :INPUT-BUFFER-SIZE and :OUTPUT-BUFFER-SIZE
53 :address-family :INTERNET :type :STREAM :connect :PASSIVE
54 * Valid keyword args: :LOCAL-HOST, :LOCAL-PORT, :BACKLOG, :REUSE-ADDRESS, :INTERFACE and :NODELAY
56 :address-family :INTERNET :type :STREAM :connect :ACTIVE
57 * Valid keyword args: :LOCAL-FILENAME, :REMOTE-FILENAME, :INPUT-BUFFER-SIZE and :OUTPUT-BUFFER-SIZE
59 :address-family :INTERNET :type :STREAM :connect :PASSIVE
60 * Valid keyword args: :LOCAL-FILENAME, :REMOTE-FILENAME, :BACKLOG and :REUSE-ADDRESS
62 :address-family :INTERNET :type :DATAGRAM
63 * Valid keyword args: :LOCAL-HOST, :LOCAL-PORT, :REMOTE-HOST, :REMOTE-PORT, :REUSE-ADDRESS, :INTERFACE and :BROADCAST
65 :address-family :LOCAL :type :DATAGRAM
66 * Valid keyword args: :LOCAL-FILENAME and :REMOTE-FILENAME
68 :address-family :INTERNET :type :RAW
69 * Valid keyword args: :INCLUDE-HEADERS
71 :address-family :NETLINK :type :RAW
72 * Valid keyword args: :LOCAL-PORT and :MULTICAST-GROUPS"))
74 (defgeneric make-socket-from-fd (fd &key dup connect external-format
75 input-buffer-size output-buffer-size)
76 (:documentation "Create a socket instance of the appropriate subclass of SOCKET using FD.
77 The connection type of the socket must be specified - :ACTIVE or :PASSIVE.
78 The address family and type of the socket are automatically discovered using OS functions. Buffer sizes
79 for the new socket can also be specified using INPUT-BUFFER-SIZE and OUTPUT-BUFFER-SIZE."))
81 (defgeneric make-socket-pair (&key type protocol external-format
82 input-buffer-size output-buffer-size)
83 (:documentation "Create a pair of sockets connected to each other.
84 The socket type must be either :STREAM or :DATAGRAM. Currently OSes can only create :LOCAL sockets this way.
85 Buffer sizes for the new sockets can also be specified using INPUT-BUFFER-SIZE and OUTPUT-BUFFER-SIZE."))
87 (defgeneric socket-os-fd (socket)
88 (:documentation "Returns the OS file descriptor of SOCKET."))
90 (defgeneric socket-type (socket)
91 (:documentation "Returns the socket type of SOCKET - :STREAM or :DATAGRAM."))
93 (defgeneric socket-open-p (socket)
94 (:documentation "Returns a boolean indicating whether or not the file descriptor of SOCKET is open."))
96 (defgeneric local-name (socket)
97 (:documentation "For INTERNET sockets, returns two values: the local host and the local port.
98 For LOCAL sockets, returns the local filename."))
100 (defgeneric local-host (socket)
101 (:documentation "Returns the local host of SOCKET.
102 Works only on INTERNET sockets."))
104 (defgeneric local-port (socket)
105 (:documentation "Returns the local port of SOCKET - an (UNSIGNED-BYTE 16).
106 Works only on INTERNET sockets."))
108 (defgeneric local-filename (socket)
109 (:documentation "Returns the local filename of SOCKET.
110 Works only on LOCAL sockets."))
112 (defgeneric remote-name (socket)
113 (:documentation "For INTERNET sockets, returns two values: the remote host and the remote port.
114 For REMOTE sockets, returns the remote filename."))
116 (defgeneric remote-host (socket)
117 (:documentation "Returns the remote host of SOCKET.
118 Works only on INTERNET sockets."))
120 (defgeneric remote-port (socket)
121 (:documentation "Returns the remote port of SOCKET - an (UNSIGNED-BYTE 16).
122 Works only on INTERNET sockets."))
124 (defgeneric remote-filename (socket)
125 (:documentation "Returns the remote filename of SOCKET.
126 Works only on LOCAL sockets."))
128 (defgeneric socket-option (socket option-name)
129 (:documentation "Returns the value(s) of OS option OPTION-NAME on SOCKET.
130 For a complete list of supported options see src/sockets/socket-options.lisp."))
132 (defclass stream-socket (socket) ()
133 (:default-initargs :type :stream)
134 (:documentation "Mixin for sockets of type SOCK_STREAM."))
136 (defclass datagram-socket (socket) ()
137 (:default-initargs :type :datagram)
138 (:documentation "Mixin for sockets of type SOCK_DGRAM."))
140 (defclass raw-socket (socket) ()
141 (:default-initargs :type :raw)
142 (:documentation "Mixin for sockets of type SOCK_RAW."))
144 (defgeneric disconnect (socket)
145 (:documentation "Disassociates SOCKET from any remote address.
146 Works only on DATAGRAM sockets."))
148 (define-symbol-macro +default-inet-address-family+
149 (if *ipv6* :ipv6 :ipv4))
151 (defclass internet-socket (socket) ()
152 (:default-initargs :address-family +default-inet-address-family+)
153 (:documentation "Mixin for sockets of domain AF_INET or AF_INET6."))
155 (defclass local-socket (socket) ()
156 (:default-initargs :address-family :local)
157 (:documentation "Mixin for sockets of domain AF_LOCAL."))
159 #+linux
160 (defclass netlink-socket (socket) ()
161 (:default-initargs :address-family :netlink)
162 (:documentation "Mixin for sockets of domain AF_NETLINK."))
164 (defgeneric send-file-descriptor (socket file-descriptor)
165 (:documentation "Send FILE-DESCRIPTOR through SOCKET.
166 The receiving process must use RECEIVE-FILE-DESCRIPTOR to receive the
167 file descriptor in order for it to be valid in the receiving process."))
169 (defgeneric receive-file-descriptor (socket)
170 (:documentation "Receive a file descriptor as ancillary data through SOCKET."))
172 (defun socket-read-fn (fd buffer nbytes)
173 (debug-only
174 (assert buffer)
175 (assert fd))
176 (%recvfrom fd buffer nbytes 0 (null-pointer) (null-pointer)))
178 (defun socket-write-fn (fd buffer nbytes)
179 (debug-only
180 (assert buffer)
181 (assert fd))
182 (%sendto fd buffer nbytes 0 (null-pointer) 0))
184 (defclass active-socket (socket dual-channel-gray-stream) ()
185 (:default-initargs :read-fn #'socket-read-fn
186 :write-fn #'socket-write-fn)
187 (:documentation "Mixin class for active(client) sockets."))
189 (defgeneric connect (socket address &key &allow-other-keys)
190 (:documentation "Connects SOCKET to ADDRESS. For INTERNET sockets you can specify
191 the port to connect to using keyword argument PORT. The default value of PORT is 0,
192 which usually means letting the OS choose a random port to connect to.
193 WAIT specifies how long to wait for a connection: NIL means \"return immediately\", a non-negative real
194 specifies a timeout in seconds and T means \"wait forever\"."))
196 (defgeneric socket-connected-p (socket)
197 (:documentation "Returns a boolean specifying whether or not SOCKET is connected."))
199 (defgeneric shutdown (socket &key read write)
200 (:documentation "Shut down all or part of a connection. If READ it non-NIL, further receptions are
201 disallowed; if WRITE is non-NIL, further transmissions are disallowed. CLOSE must still be called on
202 SOCKET in order to release OS resources."))
204 (defgeneric receive-from (socket &rest args &key &allow-other-keys)
205 (:documentation "Receives data from SOCKET. If BUFFER is specified
206 START and END are used as bounding index. In that case BUFFER must be
207 an array and its ARRAY-ELEMENT-TYPE be either (UNSIGNED-BYTE 8) or T.
208 If BUFFER is not specified an (UNSIGNED-BYTE 8) buffer of size SIZE
209 will be allocated.
211 Some flags can also be passed to recvfrom(2):
212 * :OUT-OF-BAND for receiving out-of-band data - only for STREAM sockets
213 * :PEEK for keeping the returned data in the kernel buffers
214 * :WAIT-ALL for waiting until the entire buffer can be filled
215 * :DONT-WAIT for making only the current call non-blocking
217 The first two values returned are the buffer and the number of elements that have been copied into the buffer.
218 For INTERNET DATAGRAM sockets, two additional values are returned: the host and port of the remote peer
219 from which the data was received.
220 For LOCAL DATAGRAM sockets, one additional values is returned: the filename of the remote peer
221 from which the data was received."))
223 (defgeneric send-to (socket buffer &rest args &key &allow-other-keys)
224 (:documentation "Send the contents of BUFFER to SOCKET.
225 BUFFER must be a vector that can be coerced to a (SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*)).
226 START and END are used a bounding index on BUFFER.
227 For disconnected datagram sockets, REMOTE-HOST and REMOTE-PORT or REMOTE-FILENAME are used
228 as destination for the data.
230 Some flags can also be passed to sendto(2):
231 * :OUT-OF-BAND for receiving out-of-band data - only for stream sockets
232 * :DONT-WAIT for making only the current call non-blocking
233 * :DONT-ROUTE for sending only to hosts on directly connected networks, not using gateways
234 * :CONFIRM for signalling progress on the link layer - only available on Linux and only with DATAGRAM sockets
235 * :MORE for telling the kernel that there is more data to send - only available on Linux
237 Returns the number of bytes sent."))
239 (defclass passive-socket (socket)
240 ((listening :initform nil :reader socket-listening-p :type boolean)
241 (external-format :initarg :external-format :reader external-format-of)
242 (active-class :initarg :active-class :reader active-class
243 :type symbol :allocation :class))
244 (:default-initargs :external-format :default)
245 (:documentation "Mixin class for PASSIVE(server) sockets."))
247 (defgeneric bind-address (socket address &key &allow-other-keys)
248 (:documentation "Sets the local address of SOCKET to ADDRESS(and PORT for INTERNET sockets).
249 REUSE-ADDRESS sets the SO_REUSEADDR socket option on SOCKET."))
251 (defgeneric listen-on (socket &key &allow-other-keys)
252 (:documentation "Start allowing incoming connections on SOCKET.
253 BACKLOG specifies the maximum length of the queue of pending connections."))
255 (defgeneric accept-connection (passive-socket &key &allow-other-keys)
256 (:documentation "Extracts the first connection from the queue of pending connections on SOCKET.
257 WAIT specifies how long to wait for a connection: NIL means \"return immediately\", a non-negative real
258 specifies a timeout in seconds and T means \"wait forever\".
259 EXTERNAL-FORMAT optionally specifies the external format of the new socket - the default being
260 that of SOCKET. Buffer sizes for the new socket can also be specified using INPUT-BUFFER-SIZE
261 and OUTPUT-BUFFER-SIZE.
262 If a connection is received, returns two or three values: the newly created socket, the remote peer
263 address and the remote port if applicable."))
265 (defclass socket-stream-internet-active
266 (active-socket stream-socket internet-socket) ()
267 (:documentation "Class representing active sockets of type SOCK_STREAM and domain AF_INET or AF_INET6."))
269 (defclass socket-stream-internet-passive
270 (passive-socket stream-socket internet-socket) ()
271 (:default-initargs :active-class 'socket-stream-internet-active)
272 (:documentation "Class representing passive sockets of type SOCK_STREAM and domain AF_INET or AF_INET6."))
274 (defclass socket-stream-local-active
275 (active-socket stream-socket local-socket) ()
276 (:documentation "Class representing active sockets of type SOCK_STREAM and domain AF_LOCAL."))
278 (defclass socket-stream-local-passive
279 (passive-socket stream-socket local-socket) ()
280 (:default-initargs :active-class 'socket-stream-local-active)
281 (:documentation "Class representing passive sockets of type SOCK_STREAM and domain AF_LOCAL."))
283 (defclass socket-datagram-internet
284 (datagram-socket internet-socket) ()
285 (:documentation "Class representing active sockets of type SOCK_DGRAM and domain AF_INET or AF_INET6."))
287 (defclass socket-datagram-local
288 (datagram-socket local-socket) ()
289 (:documentation "Class representing active sockets of type SOCK_DGRAM and domain AF_LOCAL."))
291 (defclass socket-raw-internet
292 (internet-socket raw-socket) ()
293 (:default-initargs :type :raw)
294 (:documentation "Class representing active sockets of type SOCK_RAW and domain AF_LOCAL."))
296 #+linux
297 (defclass socket-raw-netlink
298 (netlink-socket raw-socket) ()
299 (:default-initargs :type :raw)
300 (:documentation "Class representing active sockets of type SOCK_RAW and domain AF_NETLINK."))