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))) | ||||||||||||