1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
3 ;;; base-sockets.lisp --- Base socket classes.
5 ;;; Copyright (C) 2006-2008, Stelian Ionescu <sionescu@common-lisp.net>
7 ;;; This code is free software; you can redistribute it and/or
8 ;;; modify it under the terms of the version 2.1 of
9 ;;; the GNU Lesser General Public License as published by
10 ;;; the Free Software Foundation, as clarified by the
11 ;;; preamble found here:
12 ;;; http://opensource.franz.com/preamble.html
14 ;;; This program is distributed in the hope that it will be useful,
15 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;;; GNU General Public License for more details.
19 ;;; You should have received a copy of the GNU Lesser General
20 ;;; Public License along with this library; if not, write to the
21 ;;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 ;;; Boston, MA 02110-1301, USA
24 (in-package :net.sockets
)
28 (defclass socket
(dual-channel-single-fd-mixin)
29 ((family :initarg
:family
:accessor socket-family
)
30 (protocol :initarg
:protocol
:accessor socket-protocol
)
31 (bound :initform nil
:reader socket-bound-p
:type boolean
)))
33 (defgeneric socket-os-fd
(socket)
34 (:documentation
"Returns the OS file descriptor of `SOCKET'."))
36 (defgeneric socket-type
(socket)
37 (:documentation
"Returns the socket type of `SOCKET' - one of :STREAM or :DATAGRAM."))
39 (defgeneric socket-open-p
(socket)
40 (:documentation
"Returns a boolean indicating whether or not the file descriptor of `SOCKET' is open."))
42 (defgeneric local-name
(socket)
43 (:documentation
"For INTERNET sockets, returns two values: the local host and the local port.
44 For LOCAL sockets, returns the local filename."))
46 (defgeneric local-host
(socket)
47 (:documentation
"Returns the local host of `SOCKET'.
48 Works only on INTERNET sockets."))
50 (defgeneric local-port
(socket)
51 (:documentation
"Returns the local port of `SOCKET' - an (unsigned-byte 16).
52 Works only on INTERNET sockets."))
54 (defgeneric local-filename
(socket)
55 (:documentation
"Returns the local filename of `SOCKET'.
56 Works only on LOCAL sockets."))
58 (defgeneric remote-name
(socket)
59 (:documentation
"For INTERNET sockets, returns two values: the remote host and the remote port.
60 For REMOTE sockets, returns the remote filename."))
62 (defgeneric remote-host
(socket)
63 (:documentation
"Returns the remote host of `SOCKET'.
64 Works only on INTERNET sockets."))
66 (defgeneric remote-port
(socket)
67 (:documentation
"Returns the remote port of `SOCKET' - an (unsigned-byte 16).
68 Works only on INTERNET sockets."))
70 (defgeneric remote-filename
(socket)
71 (:documentation
"Returns the remote filename of `SOCKET'.
72 Works only on LOCAL sockets."))
74 (defgeneric socket-option
(socket option-name
)
75 (:documentation
"Returns the value(s) of OS options on `SOCKET'.
76 For a complete list of supported options see net.sockets/socket-options.lisp ."))
78 (defclass stream-socket
(socket) ()
79 (:default-initargs
:type
:stream
))
81 (defclass datagram-socket
(socket) ()
82 (:default-initargs
:type
:datagram
))
84 (defgeneric disconnect
(socket)
85 (:documentation
"Disassociates `SOCKET' from any remote address.
86 Works only on DATAGRAM sockets."))
88 (define-symbol-macro +default-inet-family
+
89 (if *ipv6
* :ipv6
:ipv4
))
91 (defclass internet-socket
(socket) ()
92 (:default-initargs
:family
+default-inet-family
+))
94 (defclass local-socket
(socket) ()
95 (:default-initargs
:family
:local
))
97 (defun socket-read-fn (fd buffer nbytes
)
98 (%recvfrom fd buffer nbytes
0 (null-pointer) (null-pointer)))
100 (defun socket-write-fn (fd buffer nbytes
)
101 (%sendto fd buffer nbytes
0 (null-pointer) 0))
103 (defclass active-socket
(socket dual-channel-gray-stream
) ()
104 (:default-initargs
:read-fn
'socket-read-fn
105 :write-fn
'socket-write-fn
))
107 (defgeneric connect
(socket address
&key
&allow-other-keys
)
108 (:documentation
"Connects `SOCKET' to `ADDRESS'. For INTERNET sockets you can specify
109 the port to connect to using keyword argument `PORT'. The default value of `PORT' is 0,
110 which usually means letting the OS choose a random port to connect to."))
112 (defgeneric socket-connected-p
(socket)
113 (:documentation
"Returns a boolean specifying whether or not `SOCKET' is connected."))
115 (defgeneric shutdown
(socket &key read write
)
116 (:documentation
"Shut down all or part of a connection. If `READ' it non-NIL, further receptions are
117 disallowed; if `WRITE' is non-NIL, further transmissions are disallowed. CLOSE must still be called on
118 `SOCKET' in order to release OS resources."))
120 (defgeneric receive-from
(socket &rest args
&key
&allow-other-keys
)
121 (:documentation
"Receives data from `SOCKET'. If `BUFFER' is specified - which must be either a
122 string or a (simple-array (unsigned-byte 8) *) - then `START' and `END' are used as bounding index,
123 otherwise a buffer of size `SIZE' will be allocated.
125 Some flags can also be passed to recvfrom(2):
126 * `OUT-OF-BAND' for receiving out-of-band data - only for stream sockets
127 * `PEEK' for keeping the returned data in the kernel buffers
128 * `WAIT-ALL' for waiting until the entire buffer can be filled
129 * `DONT-WAIT' for making only the current call non-blocking
131 The first two values returned are the buffer and the number of elements that have been copied into the buffer.
132 For INTERNET DATAGRAM sockets, two additional values are returned: the host and port of the remote peer
133 from which the data was received.
134 For LOCAL DATAGRAM sockets, one additional values is returned: the filename of the remote peer
135 from which the data was received."))
137 (defgeneric send-to
(socket buffer
&rest args
&key
&allow-other-keys
)
138 (:documentation
"Send the contents of `BUFFER' to `SOCKET'.
139 `BUFFER' must be either a string or a vector that can be coerced to a (simple-array (unsigned-byte 8) *).
140 `START' and `END' are used a bounding index on `BUFFER'.
141 For disconnected datagram sockets, `REMOTE-HOST' and `REMOTE-PORT' or `REMOTE-FILENAME' are used
142 as destination for the data.
144 Some flags can also be passed to sendto(2):
145 * `OUT-OF-BAND' for receiving out-of-band data - only for stream sockets
146 * `DONT-WAIT' for making only the current call non-blocking
147 * `DONT-ROUTE' for sending only to hosts on directly connected networks, not using gateways
148 * `CONFIRM' for signalling progress on the link layer - only available on Linux and only with DATAGRAM sockets
149 * `MORE' for telling the kernel that there is more data to send - only available on Linux
151 Returns the number of bytes sent."))
153 (defclass passive-socket
(socket)
154 ((listening :initform nil
:reader socket-listening-p
:type boolean
)
155 (external-format :initarg
:external-format
:reader external-format-of
)
156 (active-class :initarg
:active-class
:reader active-class
157 :type symbol
:allocation
:class
))
158 (:default-initargs
:external-format
:default
))
160 (defgeneric bind-address
(socket address
&key
&allow-other-keys
)
161 (:documentation
"Sets the local address of `SOCKET' to `ADDRESS'(and `PORT' for INTERNET sockets).
162 `REUSE-ADDRESS' sets the SO_REUSEADDR socket option on `SOCKET'."))
164 (defgeneric listen-on
(socket &key
&allow-other-keys
)
165 (:documentation
"Start allowing incoming connections on `SOCKET'.
166 `BACKLOG' specifies the maximum length of the queue of pending connections."))
168 (defgeneric accept-connection
(passive-socket &key
&allow-other-keys
)
169 (:documentation
"Returns one connection from the queue of pending connections on `SOCKET'.
170 `EXTERNAL-FORMAT' optionally specifies the external format of the new socket - the default being
171 that of `SOCKET'. Buffer sizes for the new socket can also be specified using `INPUT-BUFFER-SIZE'
172 and `OUTPUT-BUFFER-SIZE'."))
174 (defclass socket-stream-internet-active
175 (active-socket stream-socket internet-socket
)
178 (defclass socket-stream-internet-passive
179 (passive-socket stream-socket internet-socket
)
181 (:default-initargs
:active-class
'socket-stream-internet-active
))
183 (defclass socket-stream-local-active
(active-socket stream-socket local-socket
)
186 (defclass socket-stream-local-passive
187 (passive-socket stream-socket local-socket
)
189 (:default-initargs
:active-class
'socket-stream-local-active
))
191 (defclass socket-datagram-local-active
192 (active-socket datagram-socket local-socket
)
195 (defclass socket-datagram-internet-active
196 (active-socket datagram-socket internet-socket
)