how to listen on a specific IP using the network library

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

how to listen on a specific IP using the network library

Jeremy Shaw-3
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:


And then use it in acceptLite here:


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

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: how to listen on a specific IP using the network library

Alexander Solla-2

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.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe