how to listen on a specific IP using the network library

Hello, I would really like to modify happstack so that you can specific what IP address to listen on. So I think I want a function like: listenOnAddr :: SockAddr -> IO Socket The problem is that the user might want to specify IPv4 or IPv6 address. But support for IPv6 is only conditionally compiled into the network library. I can not figure out how to write my code so that it will compile regardless of whether network was compiled with ipv6 enabled. I got this far: -------------------------------- import qualified Control.Exception as Exception import Network.BSD (getProtocolNumber) import Network.Socket listenOnAddr :: Family -> SocketType -> SockAddr -> IO Socket listenOnAddr fam typ sockAddr = do proto <- getProtocolNumber "tcp" Exception.bracketOnError (socket fam typ proto) (sClose) (\sock -> do setSocketOption sock ReuseAddr 1 bindSocket sock sockAddr listen sock maxListenQueue return sock ) --------------------------------------- But I am not sure how to modify it to calculate 'fam' and 'typ' from 'sockAddr' with out making my code depend on IPv6 being enabled. If I was adding this function directly to the network package, there would be no problem. I could just use: #if defined(IPV6_SOCKET_SUPPORT) #endif But in a 3rd party library IPV6_SOCKET_SUPPORT is not defined. I could copy the autoconf code into my library -- but there is no guarantee that my library and the network library were compiled with the same value for IPV6_SOCKET_SUPPORT. In happstack we use a really horrible trick involving template haskell where we see if the SockAddrInet6 constructor exists at compile time and conditionally compile different versions of the code that way. But it is really ugly. We defined supportsIPv6 here: http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happsta... And then use it in acceptLite here: http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happsta... It wouldn't be that bad if we could actually use the [| |] mechanism. But we can't because it won't compile when ipv6 support is not enabled due to '(S.SockAddrInet6 _ _ ha _) -> showHostAddress6 ha'. Any suggestions? At this point I am thinking that the best solution is to add a new function to network, since it is not trivial to do it anywhere else in a portable way, and it seems like a fairly useful and common operation? - jeremy

On Mar 15, 2010, at 12:09 PM, Jeremy Shaw wrote:
In happstack we use a really horrible trick involving template haskell where we see if the SockAddrInet6 constructor exists at compile time and conditionally compile different versions of the code that way. But it is really ugly.
Maybe a simpler code generator would be a better fit, since this task isn't really parametrized over types? I'm not familiar with cabal really -- can you drop down to bash? Can you run an arbitrary program? Or at least one in the cwd? Or at the very least, one you just built? If so, a simple bash script (or Haskell program) can emit valid Haskell to compile. It can (potentially) be as simple as concatenating your IPv6 instances/data to the end of the "default" IPv4 code.
participants (2)
-
Alexander Solla
-
Jeremy Shaw