Sending UDP datagram with Haskell

503 views Asked by At

I'm trying to send an MSEARCH datagram packet to discover my Roku device on my LAN. I have this implemented in Java already, and it works fine, however I'm trying to learn Haskell. While I'm not getting any compilation errors, the code is hanging during a call to recv.

Here's my work in progress, shamelessly mostly plagiarized from the Network.Socket.ByteString documentation page.

import Network.Socket hiding (recv)
import Network.Socket.ByteString (recv, sendAll)
import qualified Data.ByteString.Char8 as C
msearch = "M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\nST: roku:ecp\r\n\r\n"

main :: IO ()
main = withSocketsDo $
    do addrinfos <- getAddrInfo Nothing (Just "239.255.255.250") (Just "1900")
       let serveraddr = head addrinfos
       sock <- socket (addrFamily serveraddr) Datagram defaultProtocol
       connect sock (addrAddress serveraddr)
       putStrLn "Sending: "
       putStrLn msearch
       sendAll sock $ C.pack msearch
       msg <- recv sock 1024
       close sock
       putStr "Got response: "
       C.putStrLn msg

In Java:

import java.net.*;
public class Msearch {
    public static void main(String[] args) {
        try {
            // MSEARCH query
            String MSEARCH = "M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nMan: \"ssdp:discover\"\r\nST: roku:ecp\r\n\r\n";
            byte[] sendData = MSEARCH.getBytes();

            // Send a datagram packet
            System.out.println("Sending:\n" + MSEARCH);
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.250"), 1900);
            DatagramSocket clientSocket = new DatagramSocket();
            clientSocket.send(sendPacket);

            // Wait for response & close
            byte[] receiveData = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            clientSocket.receive(receivePacket);
            clientSocket.close();

            // Print the response
            String response = new String(receivePacket.getData());
            System.out.println("Got response:\n" + response);
        } catch (Exception e) {
            // ...
        }
    }
}

The Java version works perfectly, yielding:

Sending:
M-SEARCH * HTTP/1.1
Host: 239.255.255.250:1900
Man: "ssdp:discover"
ST: roku:ecp


Got response:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
ST: roku:ecp
USN: uuid:roku:ecp:2N00G7750045
Ext: 
Server: Roku UPnP/1.0 MiniUPnPd/1.4
LOCATION: http://192.168.1.169:8060/

The Haskell version hangs on the call to recv. I'm still learning Haskell and I'm not sure what I'm doing differently that may be causing this. I would be grateful for any insights!

0

There are 0 answers