Hello,<div><br></div><div>I would really like to modify happstack so that you can specific what IP address to listen on.</div><div><br></div><div>So I think I want a function like:</div><div><br></div><div>listenOnAddr :: SockAddr -&gt; IO Socket</div>
<div><br></div><div>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.</div><div><br></div><div>I can not figure out how to write my code so that it will compile regardless of whether network was compiled with ipv6 enabled.</div>
<div><br></div><div>I got this far:</div><div><br></div><div><br></div><div>--------------------------------</div><div><div>import qualified Control.Exception as Exception</div><div>import Network.BSD    (getProtocolNumber)</div>
<div>import Network.Socket</div><div><br></div><div>listenOnAddr :: Family -&gt; SocketType -&gt; SockAddr -&gt; IO Socket</div><div>listenOnAddr fam typ sockAddr =</div><div>  do proto &lt;- getProtocolNumber &quot;tcp&quot;</div>
<div>     Exception.bracketOnError</div><div>      (socket fam typ proto)</div><div>      (sClose)</div><div>      (\sock -&gt; do</div><div>          setSocketOption sock ReuseAddr 1</div><div>          bindSocket sock sockAddr</div>
<div>          listen sock maxListenQueue</div><div>          return sock</div><div>        )</div><div>---------------------------------------</div><div><br></div><div>But I am not sure how to modify it to calculate &#39;fam&#39; and &#39;typ&#39; from &#39;sockAddr&#39; with out making my code depend on IPv6 being enabled.</div>
<div><br></div><div>If I was adding this function directly to the network package, there would be no problem. I could just use:</div><div><br></div><div>#if defined(IPV6_SOCKET_SUPPORT)</div><div>#endif </div><div><br></div>
<div>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.</div>
<div><br></div><div>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:</div>
<div><br></div><div><a href="http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happstack-server/src/Happstack/Server/HTTP/SocketTH.hs">http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happstack-server/src/Happstack/Server/HTTP/SocketTH.hs</a></div>
<div><br></div><div>And then use it in acceptLite here:</div><div><br></div><div><div><a href="http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happstack-server/src/Happstack/Server/HTTP/Socket.hs">http://patch-tag.com/r/mae/happstack/snapshot/current/content/pretty/happstack-server/src/Happstack/Server/HTTP/Socket.hs</a></div>
<div><br></div><div>It wouldn&#39;t be that bad if we could actually use the [| |] mechanism. But we can&#39;t because it won&#39;t compile when ipv6 support is not enabled due to &#39;(S.SockAddrInet6 _ _ ha _) -&gt; showHostAddress6 ha&#39;. </div>
<div><br></div><div>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?</div>
<div><br></div><div>- jeremy</div></div></div>