{-# LANGUAGE CPP #-}
#include "HsNetDef.h"
module Network.Socket.Name (
    getPeerName
  , getSocketName
  , socketPort
  , socketPortSafe
  ) where
import Foreign.Marshal.Utils (with)
import Network.Socket.Imports
import Network.Socket.Internal
import Network.Socket.Types
getPeerName :: SocketAddress sa => Socket -> IO sa
getPeerName s =
 withNewSocketAddress $ \ptr sz ->
   with (fromIntegral sz) $ \int_star -> withFdSocket s $ \fd -> do
     throwSocketErrorIfMinus1Retry_ "Network.Socket.getPeerName" $
       c_getpeername fd ptr int_star
     _sz <- peek int_star
     peekSocketAddress ptr
getSocketName :: SocketAddress sa => Socket -> IO sa
getSocketName s =
 withNewSocketAddress $ \ptr sz ->
   with (fromIntegral sz) $ \int_star -> withFdSocket s $ \fd -> do
     throwSocketErrorIfMinus1Retry_ "Network.Socket.getSocketName" $
       c_getsockname fd ptr int_star
     peekSocketAddress ptr
foreign import CALLCONV unsafe "getpeername"
  c_getpeername :: CInt -> Ptr sa -> Ptr CInt -> IO CInt
foreign import CALLCONV unsafe "getsockname"
  c_getsockname :: CInt -> Ptr sa -> Ptr CInt -> IO CInt
socketPort :: Socket            
           -> IO PortNumber     
socketPort s = do
    sa <- getSocketName s
    case sa of
      SockAddrInet port _      -> return port
      SockAddrInet6 port _ _ _ -> return port
      _                        -> ioError $ userError "Network.Socket.socketPort: AF_UNIX not supported."
socketPortSafe :: Socket                
               -> IO (Maybe PortNumber) 
socketPortSafe s = do
    sa <- getSocketName s
    return $ case sa of
      SockAddrInet port _      -> Just port
      SockAddrInet6 port _ _ _ -> Just port
      _                        -> Nothing