hosc-0.16: Sound/OSC/Transport/FD/UDP.hs
-- | OSC over UDP implementation.
module Sound.OSC.Transport.FD.UDP where
import Control.Monad {- base -}
import qualified Network.Socket as N {- network -}
import qualified Network.Socket.ByteString as C {- network -}
import Sound.OSC.Coding.Class
import Sound.OSC.Packet
import Sound.OSC.Packet.Class
import Sound.OSC.Transport.FD
-- | The UDP transport handle data type.
data UDP = UDP {udpSocket :: N.Socket}
-- | Return the port number associated with the UDP socket.
udpPort :: Integral n => UDP -> IO n
udpPort (UDP fd) = fmap fromIntegral (N.socketPort fd)
-- | 'UDP' is an instance of 'Transport'.
instance Transport UDP where
-- C.L.send is not implemented for W32
sendOSC (UDP fd) msg = void (C.send fd (encodeOSC msg))
recvPacket (UDP fd) = liftM decodePacket (C.recv fd 8192)
close (UDP fd) = N.close fd
-- | Create and initialise UDP socket.
udp_socket :: (N.Socket -> N.SockAddr -> IO ()) -> String -> Int -> IO UDP
udp_socket f host port = do
fd <- N.socket N.AF_INET N.Datagram 0
a <- N.inet_addr host
let sa = N.SockAddrInet (fromIntegral port) a
f fd sa
return (UDP fd)
-- | Set option, ie. 'N.Broadcast' or 'N.RecvTimeOut'.
set_udp_opt :: N.SocketOption -> Int -> UDP -> IO ()
set_udp_opt k v (UDP s) = N.setSocketOption s k v
-- | Get option.
get_udp_opt :: N.SocketOption -> UDP -> IO Int
get_udp_opt k (UDP s) = N.getSocketOption s k
-- | Make a 'UDP' connection.
--
-- > let t = openUDP "127.0.0.1" 57110
-- > in withTransport t (\fd -> recvT 0.5 fd >>= print)
openUDP :: String -> Int -> IO UDP
openUDP = udp_socket N.connect
-- N.setSocketOption fd N.RecvTimeOut 1000
-- | Trivial 'UDP' server socket.
--
-- > import Control.Concurrent
--
-- > let {f fd = forever (recvMessage fd >>= print)
-- > ;t = udpServer "127.0.0.1" 57300}
-- > in void (forkIO (withTransport t f))
--
-- > let t = openUDP "127.0.0.1" 57300
-- > in withTransport t (\fd -> sendMessage fd (message "/n" []))
udpServer :: String -> Int -> IO UDP
udpServer = udp_socket N.bind
-- | Send variant to send to specified address.
sendTo :: OSC o => UDP -> o -> N.SockAddr -> IO ()
sendTo (UDP fd) o a = do
-- C.L.sendTo does not exist
void (C.sendTo fd (encodeOSC o) a)
-- | Recv variant to collect message source address.
recvFrom :: UDP -> IO (Packet, N.SockAddr)
recvFrom (UDP fd) = do
-- C.L.recvFrom does not exist
(s,a) <- C.recvFrom fd 8192
return (decodePacket s,a)