dependencies
| (this space intentionally left almost blank) | ||||||||||||
(ns sockets.datagram.packet (:refer-clojure :exclude [bound? send]) (:import (java.net DatagramPacket))) | |||||||||||||
Constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
(def DEFAULT_PACKET_SIZE 512) | |||||||||||||
Protocol ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
(defprotocol Packet
(address [this]
"Returns the IP address of the machine to which this datagram is being sent
or from which the datagram was received.")
(data [this]
"Returns the data buffer.")
(default-length [this]
"A Clojure method only available to the Clojure wrapper, returning the
default length a packet is created with when no length is given.")
(length [this]
"Returns the length of the data to be sent or the length of the data
received.")
(offset [this]
"Returns the offset of the data to be sent or the offset of the data
received.")
(port [this]
"Returns the port number on the remote host to which this datagram is being
sent or from which the datagram was received.")
(socket-address [this]
"Gets the SocketAddress (usually IP address + port number) of the remote
host that this packet is being sent to or is coming from.")
(address! [this addr]
"Sets the IP address of the machine to which this datagram is being sent.")
(data! [this bytes] [this bytes offset len]
"Set the data buffer for this packet.")
(length! [this len]
"Set the length for this packet.")
(port! [this port]
"Sets the port number on the remote host to which this datagram is being
sent.")
(socket-address! [this]
"Sets the `SocketAddress` (usually IP address + port number) of the remote
host to which this datagram is being sent.")
(update-address [this addr]
"Updates the IP address of the machine to which this datagram is being
sent, returning the updated packet. This is provided as a convenience for
use in Clojure threading macros.")
(update-data [this bytes] [this bytes offset len]
"Updates the data buffer for this packet, returning the updated packet.
This is provided as a convenience for use in Clojure threading macros.")
(update-length [this len]
"Set the length for this packet, returning the updated packet. This is
provided as a convenience for use in Clojure threading macros.")
(update-port [this port]
"Sets the port number on the remote host to which this datagram is being
sent, returning the updated packet. This is provided as a convenience for
use in Clojure threading macros.")
(update-socket-address [this]
"Sets the `SocketAddress` (usually IP address + port number) of the remote
host to which this datagram is being sent, returning the updated packet.
This is provided as a convenience for use in Clojure threading macros.")) | |||||||||||||
Implementation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
(def behaviour
{:address (fn [this] (.getAddress this))
:data (fn [this] (.getData this))
:default-length (constantly DEFAULT_PACKET_SIZE)
:length (fn [this] (.getLength this))
:offset (fn [this] (.getOffset this))
:port (fn [this] (.getPort this))
:socket-address (fn [this] (.getSocketAddress this))
:address! (fn [this addr] (.setAddress this addr))
:data! (fn ([this bytes]
(.setData this bytes))
([this bytes offset len]
(.setData this bytes offset len)))
:length! (fn [this len] (.setLength this len))
:port! (fn [this port] (.setPort this port))
:socket-address! (fn [this addr] (.setSocketAddress this addr) this)
:update-address (fn [this addr] (.setAddress this addr) this)
:update-data (fn ([this bytes]
(.setData this bytes)
this)
([this bytes offset len]
(.setData this bytes offset len)
this))
:update-length (fn [this len] (.setLength this len) this)
:update-port (fn [this port] (.setPort this port) this)
:update-socket-address (fn [this addr]
(.setSocketAddress this addr)
this)}) | |||||||||||||
(extend DatagramPacket Packet behaviour) | |||||||||||||
Constructors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
A constructor for datagram packets. This function may take 0, 1, 2, 3, 4, or 5 args.
| (defn create
([]
(new DatagramPacket (byte-array DEFAULT_PACKET_SIZE) DEFAULT_PACKET_SIZE))
([len]
(new DatagramPacket (byte-array len) len))
([buf len]
(new DatagramPacket buf len))
([buf arg2 arg3]
(new DatagramPacket buf arg2 arg3))
([buf arg2 arg3 arg4]
(new DatagramPacket buf arg2 arg3 arg4))
([buf offset len addr port]
(new DatagramPacket buf offset len addr port))) | ||||||||||||
(ns sockets.datagram.socket
(:require
[sockets.datagram.packet :as packet])
(:refer-clojure :exclude [bound? send])
(:import
(java.net DatagramPacket
DatagramSocket))) | |||||||||||||
Protocol ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
(defprotocol Socket
(bind [this addr]
"Binds this `DatagramSocket` to a specific address and port.")
(close [this]
"Closes this datagram socket.")
(connect [this addr] [this addr port]
"For the 1-arity function, connects this socket to a remote socket address
(IP address + port number; must be an instance or subclass of
`SocketAddress`). For the 2-arity function, connects the socket to a remote
address amd port for this socket (the address must be an instance or
subclass of `InetAddress`).")
(disconnect [this]
"Disconnects the socket.")
(broadcast? [this]
"Tests if `SO_BROADCAST` is enabled.")
(channel [this]
"Returns the unique `DatagramChannel` object associated with this datagram
socket, if any.")
(inet-address [this]
"Returns the address to which this socket is connected.")
(local-address [this]
"Gets the local address to which the socket is bound.")
(local-port [this]
"Returns the port number on the local host to which this socket is bound.")
(local-socket-address [this]
"Returns the address of the endpoint this socket is bound to.")
(port [this]
"Returns the port number to which this socket is connected.")
(receive-buffer-size [this]
"Get value of the `SO_RCVBUF option for this `DatagramSocket`, that is the
buffer size used by the platform for input on this `DatagramSocket`.")
(remote-socket-address [this]
"Returns the address of the endpoint this socket is connected to, or null
if it is unconnected.")
(reuse-address [this]
"Tests if `SO_REUSEADDR` is enabled.")
(send-buffer-size [this]
"Get value of the `SO_SNDBUF` option for this `DatagramSocket`, that is the
buffer size used by the platform for output on this `DatagramSocket`.")
(so-timeout [this]
"Retrieve setting for `SO_TIMEOUT`.")
(traffic-class [this]
"Gets traffic class or type-of-service in the IP datagram header for
packets sent from this `DatagramSocket`.")
(bound? [this]
"Returns the binding state of the socket.")
(closed? [this]
"Returns whether the socket is closed or not.")
(connected? [this]
"Returns the connection state of the socket.")
(receive [this] [this packet]
"Receives a datagram packet from this socket. Additionally, the Clojure
wrapper allows you to pass the packet size instead of the packet itself. If
this option is exercised, a packet of the indicated size will be created and
returned. Another Clojure wrapper convenience, the 1-arity version of this
function, will use the default packet size `DEFAULT_PACKET_SIZE` and create
a packet under the covers with that size.")
(send [this packet]
"Sends a datagram packet from this socket.")
(broadcast! [this bool]
"Enable/disable `SO_BROADCAST`.")
(receive-buffer-size! [this size]
"Sets the `SO_RCVBUF` option to the specified value for this
`DatagramSocket`.")
(reuse-address! [this bool]
"Enable/disable the `SO_REUSEADDR` socket option.")
(send-buffer-size! [this size]
"Sets the `SO_SNDBUF` option to the specified value for this
`DatagramSocket`.")
(so-timeout! [this timeout]
"Enable/disable `SO_TIMEOUT` with the specified timeout, in milliseconds.")
(traffic-class! [this class-int]
"Sets traffic class or type-of-service octet in the IP datagram header for
datagrams sent from this `DatagramSocket`.")) | |||||||||||||
Implementation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
(defmulti -receive
(fn ([arg1 & [arg2]]
(mapv type [arg1 arg2])))) | |||||||||||||
(defmethod -receive [DatagramSocket DatagramPacket] [this pkt] (.receive this pkt)) | |||||||||||||
(defmethod -receive [DatagramSocket Number]
[this len]
(let [pkt (packet/create len)]
(-receive this pkt)
pkt)) | |||||||||||||
(defmethod -receive [DatagramSocket] [this] (-receive this packet/DEFAULT_PACKET_SIZE)) | |||||||||||||
(def behaviour
{:bind (fn [this addr] (.bind this addr))
:close (fn [this] (.close this))
:connect (fn ([this addr]
(.connect this addr))
([this addr port]
(.connect this addr port)))
:disconnect (fn [this] (.disconnect this))
:broadcast? (fn [this] (.getBroadcast this))
:channel (fn [this] (.getChannel this))
:inet-address (fn [this] (.getInetAddress this))
:local-address (fn [this] (.getLocalAddress this))
:local-port (fn [this] (.getLocalPort this))
:local-socket-address (fn [this] (.getLocalSocketAddress this))
:port (fn [this] (.getPort this))
:receive-buffer-size (fn [this] (.getReceiveBufferSize this))
:remote-socket-address (fn [this] (.getRemoteSocketAddress this))
:reuse-address (fn [this] (.getReuseAddress this))
:send-buffer-size (fn [this] (.getSendBufferSize this))
:so-timeout (fn [this] (.getSoTimeout this))
:traffic-class (fn [this] (.getTrafficClass this))
:bound? (fn [this] (.isBound this))
:closed? (fn [this] (.isClosed this))
:connected? (fn [this] (.isConnected this))
:receive -receive
:send (fn [this packet] (.send this packet))
:broadcast! (fn [this bool] (.setBroadcast this bool))
:receive-buffer-size! (fn [this size] (.setReceiveBufferSize this size))
:reuse-address! (fn [this bool] (.setReuseAddress this bool))
:send-buffer-size! (fn [this size] (.setSendBufferSize this size))
:so-timeout! (fn [this timeout] (.setSoTimeout this timeout))
:traffic-class! (fn [this class-int] (.setTrafficClass this class-int))}) | |||||||||||||
(extend DatagramSocket Socket behaviour) | |||||||||||||
Constructors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||||||||||||
A constructor for datagram sockets. This function my take 0, 1, or two args.
| (defn create
([]
(new DatagramSocket))
([arg]
(new DatagramSocket arg))
([port local-addr]
(new DatagramSocket port local-addr))) | ||||||||||||