Anonymous avatar Anonymous committed 2628dac

Initial revision.

Comments (0)

Files changed (5)

+
+sources = Network/Socket/LocalAddress.hs
+
+objs = $(sources:.hs=.o)
+interfaces = $(sources:.hs=.hi)
+
+%.o: %.hs
+	ghc -Wall -c $<
+
+all: build hlint cabal_build
+
+build: $(objs)
+
+hlint:
+	hlint --utf8 $(sources)
+
+cabal_build:
+	cabal configure
+	cabal build
+	cabal haddock
+
+clean:
+	$(RM) $(objs) $(interfaces)
+	cabal clean
+Copyright (c)2011, Kei Hibino
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Kei Hibino nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Network/Socket/LocalAddress.hs

+-----------------------------------------------------------------------------
+-- |
+-- Module      : Network.Socket.LocalAddress
+-- Copyright   : 2011 Kei Hibino
+-- License     : BSD3
+--
+-- Maintainer  : ex8k.hibino@gmail.com
+-- Stability   : experimental
+-- Portability : portable
+--
+-- This package includes small functions to get local interface address.
+-- Following method is traditional technique to getSockName without sending packet.
+--
+-----------------------------------------------------------------------------
+
+module Network.Socket.LocalAddress (
+  localSockAddr',
+  localSockAddr,
+  localAddress,
+  localAddressString) where
+
+import Network.Socket (Socket, Family(..),
+                       SockAddr(..), SocketType(..), HostAddress,
+                       socket, connect,
+                       defaultProtocol,
+                       getSocketName,
+                       sClose,
+                       inet_addr, inet_ntoa)
+
+toIO :: a -> IO a
+toIO =  return
+
+{- | Get local address and datagram socket corresponding to remote address
+     without sending any packet. -}
+localSockAddr' :: SockAddr -> IO (SockAddr, Socket)
+localSockAddr' remote =
+  do sock <- socket (af remote) Datagram defaultProtocol
+     connect sock remote
+     addr <- getSocketName sock
+     toIO (addr, sock)
+  where af (SockAddrInet  _ _)     = AF_INET
+        af (SockAddrInet6 _ _ _ _) = AF_INET6
+        af (SockAddrUnix _)        = AF_UNIX
+
+{- | Get local address corresponding to remote address 
+     without sending any packet. -}
+localSockAddr :: SockAddr -> IO SockAddr
+localSockAddr remote = do (addr, sock) <- localSockAddr' remote
+                          sClose sock
+                          toIO $ erasePort addr
+  where erasePort (SockAddrInet _ addr)      = SockAddrInet 0 addr
+        erasePort (SockAddrInet6 _ fi ha si) = SockAddrInet6 0 fi ha si
+        erasePort sa@(SockAddrUnix _)        = sa
+
+{- | Get IPv4 local address corresponding to remote IPv4 address 
+     without sending any packet. -}
+localAddress :: HostAddress -> IO (Maybe HostAddress)
+localAddress =  fmap expect4 . localSockAddr . SockAddrInet 0
+  where expect4 (SockAddrInet _ addr) = Just addr
+        expect4  _                    = Nothing
+
+{- | Get IPv4 local address string corresponding to 
+     remote IPv4 address string without sending any packet. -}
+localAddressString :: String -> IO (Maybe String)
+localAddressString astr =
+  do remote <- inet_addr astr
+     local <- localAddress remote
+     maybe (toIO Nothing) (fmap Just . inet_ntoa) local
+import Distribution.Simple
+main = defaultMain

local-address.cabal

+Name:                local-address
+Version:             0.0.1
+Synopsis:            Functions to get local interface address
+Description:         This package includes small functions to get local interface address.
+Homepage:            http://bitbucket.org/khibino/haskell-local-address
+License:             BSD3
+License-file:        LICENSE
+Author:              Kei Hibino
+Maintainer:          ex8k.hibino@gmail.com
+Category:            Network
+Build-type:          Simple
+Cabal-version:       >=1.2
+Library
+  Exposed-modules:     Network.Socket.LocalAddress
+  Build-depends:       base >= 3 && < 5, network
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.