packages feed

sockets-0.4.0.0: sockets.cabal

cabal-version: 2.2
name: sockets
version: 0.4.0.0
synopsis: High-level network sockets
description:
  This library provides a high-level abstraction for network sockets. It uses
  Haskell2010 (along with GADTs) without typeclasses to ensure that
  consumers of the API can only call appropriate functions on a socket.
  .
  Exceptions are tracked in the types of functions and returned to the caller
  with `Either`. The caller is free to handle these gracefully or to throw
  them. This library has another class of exceptions described as _unrecoverable_.
  This library only throws exceptions in three situations:
  .
  * The library detects that it has misused the operating system's
    sockets API. This includes getting a `sockaddr` with an unexpected
    socket family. It also includes getting an error code that should not
    be possible. For example, the abstractions provided for both datagram
    sockets and stream sockets mean that `send` system calls in either
    context should never return the error code `ENOTCONN`. Consequently,
    this error is treated as unrecoverable.
  .
  * The caller asks for a negatively-sized slice of a buffer
    (such exceptions indicate a mistake in the code consuming this API).
  .
  * A system call fails with `ENOBUFS` or `ENOMEM`. These indicate that
    the operating system is out of memory. If this happens, the
    Out Of Memory (OOM) manager is likely killing processes to
    reclaim memory, so the process that received this message may
    be killed soon. Making things even worse is that the GHC runtime
    requests pages of memory from the operating system at times that
    are effectively unpredictable to Haskell developers. (Most
    memory-managed languages have this behavior). Any attempt
    to recover from `ENOBUFS` or `ENOMEM` might cause the runtime to
    allocate memory from the operating system. According to the
    documentation for the <http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Exception-Base.html#t:AsyncException HeapOverflow>
    exception, an allocation failure at this point in time (likely given
    the recent `ENOBUFS`/`ENOMEM`) would result in immidiate
    termination of the program. So, although it is technically possible
    to recover from `ENOBUFS`/`ENOMEM`, the OOM killer and the
    GHC runtime make it impossible to do so reliably.  Consequently,
    these error codes are treated as fatal.

homepage: https://github.com/andrewthad/sockets
bug-reports: https://github.com/andrewthad/sockets/issues
license: BSD-3-Clause
license-file: LICENSE
author: Andrew Martin
maintainer: andrew.thaddeus@gmail.com
copyright: 2019 Andrew Martin
category: Network
extra-source-files: CHANGELOG.md

flag mmsg
  manual: True
  description: Use sendmmsg and recvmmsg 
  default: False

flag verbose-errors
  manual: True
  description: More informative messages from internal errors
  default: False

flag debug
  manual: True
  description: Print debug output 
  default: False

flag checked
  manual: True
  description: Add bounds-checking to primitive array operations
  default: False

flag example
  manual: True
  description: Build example executables
  default: False

library sockets-internal
  build-depends:
    , base >= 4.11.1.0 && <5
    , ip >= 1.4.1
    , posix-api >=0.3 && <0.4
    , primitive-offset >= 0.2 && <0.3
    , primitive-unlifted >= 0.1 && <0.2
    , primitive-addr >= 0.1 && <0.2
    , stm >= 2.4
    , text >= 1.2
    , byteslice >=0.1.1 && <0.2
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  exposed-modules:
    Socket
    Socket.AddrLength
    Socket.Datagram
    Socket.Debug
    Socket.Error
    Socket.EventManager
    Socket.IPv4
    Socket.Stream
    Socket.Bytes
    Socket.Destined.IPv4.MutableBytes
    Socket.Destined.IPv4.Bytes
    Socket.Discard
    Socket.Connected.MutableBytes
    Socket.Connected.Bytes
    Socket.MutableBytes
    Socket.MutableBytes.Peerless
    Socket.MutableBytes.SocketAddressInternet
    Socket.Interruptible
    Socket.Uninterruptible
    Hybrid.Send.MutableBytes.AddrLength
  if flag(debug)
    hs-source-dirs: src-debug
  else
    hs-source-dirs: src-production
  if flag(debug) || flag(verbose-errors)
    hs-source-dirs: src-err
  else
    hs-source-dirs: src-noerr
  hs-source-dirs: src-internal
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-interrupt
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , stm >= 2.4
    , sockets-internal
  signatures: Socket.Interrupt
  hs-source-dirs: src-interrupt
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-buffer
  build-depends: base >= 4.11.1.0 && <5
  signatures: Socket.Buffer
  hs-source-dirs: src-buffer
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-datagram-send
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , posix-api >=0.3 && <0.4
    , stm >= 2.4
    , sockets-internal
    , sockets-buffer
    , sockets-interrupt
  exposed-modules:
    Datagram.Send.Indefinite
  signatures:
    Datagram.Send
  hs-source-dirs: src-datagram-send
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-datagram-receive
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , stm >= 2.4
    , posix-api >=0.3 && <0.4
    , primitive-offset >= 0.2 && <0.3
    , sockets-internal
    , sockets-buffer
    , sockets-interrupt
  exposed-modules:
    Datagram.Receive.Indefinite
  signatures:
    Datagram.Receive
  hs-source-dirs: src-datagram-receive
  default-language: Haskell2010
  ghc-options: -O2 -Wall

-- This is only used as a shim for when the platform does not
-- support recvmmsg. It lets us share code for the interruptible
-- and uninterruptible variants.
library sockets-datagram-receive-many
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , stm >= 2.4
    , posix-api >=0.3 && <0.4
    , primitive-unlifted >= 0.1 && <0.2
    , byteslice >= 0.1.1
    , sockets-datagram-receive
    , sockets-internal
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  exposed-modules:
    Datagram.Receive.Many.Indefinite
  hs-source-dirs: src-datagram-receive-many
  mixins:
    sockets-datagram-receive
      (Datagram.Receive.Indefinite as Socket.Datagram.Instantiate)
      requires
      (Socket.Buffer as Socket.MutableBytes)
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-stream-send
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , posix-api >=0.3 && <0.4
    , stm >= 2.4
    , sockets-internal
    , sockets-buffer
    , sockets-interrupt
  exposed-modules:
    Stream.Send.Indefinite
  signatures:
    Stream.Send
  hs-source-dirs: src-stream-send
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-stream-receive
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , posix-api >=0.3 && <0.4
    , stm >= 2.4
    , sockets-internal
    , sockets-buffer
    , sockets-interrupt
  exposed-modules:
    Stream.Receive.Indefinite
  signatures:
    Stream.Receive
  hs-source-dirs: src-stream-receive
  default-language: Haskell2010
  ghc-options: -O2 -Wall

library sockets-stream-send-two
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , posix-api >=0.3 && <0.4
    , stm >= 2.4
    , sockets-internal
    , sockets-interrupt
    , sockets-stream-send
  exposed-modules:
    Stream.Send.Two.Indefinite
  signatures:
    Stream.Send.Two
    Stream.Send.B
    Stream.Send.Buffer.A
    Stream.Send.Buffer.B
  mixins:
    sockets-stream-send
      (Stream.Send.Indefinite)
      requires
      (Socket.Buffer as Stream.Send.Buffer.B,
       Stream.Send as Stream.Send.B)
  hs-source-dirs: src-stream-send-two
  default-language: Haskell2010
  ghc-options: -O2 -Wall

-- Here, we partially apply the indefinite packages for
-- stream send and stream receive. The avoids duplication
-- in the public library.
library sockets-stream-bidirectional
  build-depends:
    , base >= 4.11.1.0 && <5
    , error-codes >= 0.1.0.1 && < 0.2
    , stm >= 2.4
    , sockets-internal
    , sockets-stream-send
    , sockets-stream-receive
  reexported-modules:
    , Stream.Send.Indefinite
    , Stream.Receive.Indefinite
  mixins:
      sockets-stream-send (Stream.Send.Indefinite)
    , sockets-stream-receive (Stream.Receive.Indefinite)
  default-language: Haskell2010

library
  exposed-modules:
    Socket.Address
    Socket.Datagram.IPv4.Unconnected
    Socket.Datagram.IPv4.Connected
    Socket.Stream.IPv4
    Socket.Datagram.Interruptible.Bytes
    Socket.Datagram.Interruptible.MutableBytes
    Socket.Datagram.Slab
    Socket.Datagram.Uninterruptible.Bytes
    Socket.Datagram.Uninterruptible.MutableBytes
    Socket.Stream.Interruptible.Addr
    Socket.Stream.Interruptible.ByteString
    Socket.Stream.Interruptible.Bytes
    Socket.Stream.Interruptible.MutableBytes
    Socket.Stream.Interruptible.Hybrid
    Socket.Stream.Uninterruptible.Addr
    Socket.Stream.Uninterruptible.ByteString
    Socket.Stream.Uninterruptible.Bytes
    Socket.Stream.Uninterruptible.MutableBytes
    Socket.Stream.Uninterruptible.Hybrid
  other-modules:
    Socket.Datagram.Interruptible.MutableBytes.Many
    Socket.Datagram.Uninterruptible.MutableBytes.Many
  mixins:
    sockets-datagram-receive-many
      (Datagram.Receive.Many.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Receive.Many.Unit)
      requires
      (Datagram.Receive as Socket.MutableBytes.Peerless,
       Socket.Interrupt as Socket.Uninterruptible),
    sockets-datagram-receive-many
      (Datagram.Receive.Many.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Receive.Many.IPv4)
      requires
      (Datagram.Receive as Socket.MutableBytes.SocketAddressInternet,
       Socket.Interrupt as Socket.Uninterruptible),
    sockets-datagram-receive-many
      (Datagram.Receive.Many.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Receive.Many.Unit)
      requires
      (Datagram.Receive as Socket.MutableBytes.Peerless,
       Socket.Interrupt as Socket.Interruptible),
    sockets-datagram-receive-many
      (Datagram.Receive.Many.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Receive.Many.IPv4)
      requires
      (Datagram.Receive as Socket.MutableBytes.SocketAddressInternet,
       Socket.Interrupt as Socket.Interruptible),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Send.IPv4)
      requires
      (Datagram.Send as Socket.Destined.IPv4.MutableBytes,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Uninterruptible.Bytes.Send.Connected)
      requires
      (Datagram.Send as Socket.Connected.Bytes,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.Bytes),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Uninterruptible.Bytes.Send.IPv4)
      requires
      (Datagram.Send as Socket.Destined.IPv4.Bytes,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.Bytes),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Send.IPv4)
      requires
      (Datagram.Send as Socket.Destined.IPv4.MutableBytes,
       Socket.Interrupt as Socket.Interruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Send.Connected)
      requires
      (Datagram.Send as Socket.Connected.MutableBytes,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-send
      (Datagram.Send.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Send.Connected)
      requires
      (Datagram.Send as Socket.Connected.MutableBytes,
       Socket.Interrupt as Socket.Interruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-receive
      (Datagram.Receive.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Receive.IPv4)
      requires
      (Datagram.Receive as Socket.MutableBytes.SocketAddressInternet,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-receive
      (Datagram.Receive.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Receive.IPv4)
      requires
      (Datagram.Receive as Socket.MutableBytes.SocketAddressInternet,
       Socket.Interrupt as Socket.Interruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-receive
      (Datagram.Receive.Indefinite as Socket.Datagram.Uninterruptible.MutableBytes.Receive.Connected)
      requires
      (Datagram.Receive as Socket.MutableBytes.Peerless,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-datagram-receive
      (Datagram.Receive.Indefinite as Socket.Datagram.Interruptible.MutableBytes.Receive.Connected)
      requires
      (Datagram.Receive as Socket.MutableBytes.Peerless,
       Socket.Interrupt as Socket.Interruptible,
       Socket.Buffer as Socket.MutableBytes),
    sockets-stream-send
      (Stream.Send.Indefinite as Socket.Stream.Interruptible.Bytes.Send)
      requires
      (Stream.Send as Socket.Bytes,
       Socket.Interrupt as Socket.Interruptible,
       Socket.Buffer as Socket.Bytes),
    sockets-stream-send
      (Stream.Send.Indefinite as Socket.Stream.Uninterruptible.Bytes.Send)
      requires
      (Stream.Send as Socket.Bytes,
       Socket.Interrupt as Socket.Uninterruptible,
       Socket.Buffer as Socket.Bytes),
    sockets-stream-bidirectional
      (Stream.Send.Indefinite as Socket.Stream.Interruptible.MutableBytes.Send,
       Stream.Receive.Indefinite as Socket.Stream.Interruptible.MutableBytes.Receive)
      requires
      (Stream.Send as Socket.MutableBytes,
       Stream.Receive as Socket.MutableBytes,
       Socket.Buffer as Socket.MutableBytes,
       Socket.Interrupt as Socket.Interruptible),
    sockets-stream-bidirectional
      (Stream.Send.Indefinite as Socket.Stream.Uninterruptible.MutableBytes.Send,
       Stream.Receive.Indefinite as Socket.Stream.Uninterruptible.MutableBytes.Receive)
      requires
      (Stream.Send as Socket.MutableBytes,
       Stream.Receive as Socket.MutableBytes,
       Socket.Buffer as Socket.MutableBytes,
       Socket.Interrupt as Socket.Uninterruptible),
    sockets-stream-bidirectional
      (Stream.Send.Indefinite as Socket.Stream.Interruptible.Addr.Send,
       Stream.Receive.Indefinite as Socket.Stream.Interruptible.Addr.Receive)
      requires
      (Stream.Send as Socket.AddrLength,
       Stream.Receive as Socket.AddrLength,
       Socket.Buffer as Socket.AddrLength,
       Socket.Interrupt as Socket.Interruptible),
    sockets-stream-bidirectional
      (Stream.Send.Indefinite as Socket.Stream.Uninterruptible.Addr.Send,
       Stream.Receive.Indefinite as Socket.Stream.Uninterruptible.Addr.Receive)
      requires
      (Stream.Send as Socket.AddrLength,
       Stream.Receive as Socket.AddrLength,
       Socket.Buffer as Socket.AddrLength,
       Socket.Interrupt as Socket.Uninterruptible),
    sockets-stream-send-two
      (Stream.Send.Two.Indefinite as Socket.Stream.Interruptible.MutableBytes.Addr.Send)
      requires
      (Stream.Send.B as Socket.AddrLength,
       Stream.Send.Buffer.A as Socket.MutableBytes,
       Stream.Send.Buffer.B as Socket.AddrLength,
       Stream.Send.Two as Hybrid.Send.MutableBytes.AddrLength,
       Socket.Interrupt as Socket.Interruptible),
    sockets-stream-send-two
      (Stream.Send.Two.Indefinite as Socket.Stream.Uninterruptible.MutableBytes.Addr.Send)
      requires
      (Stream.Send.B as Socket.AddrLength,
       Stream.Send.Buffer.A as Socket.MutableBytes,
       Stream.Send.Buffer.B as Socket.AddrLength,
       Stream.Send.Two as Hybrid.Send.MutableBytes.AddrLength,
       Socket.Interrupt as Socket.Uninterruptible),
  build-depends:
    , base >= 4.11.1.0 && <5
    , byteslice >=0.1.1 && <0.2
    , bytestring >=0.10 && <0.11
    , error-codes >=0.1.0.1 && <0.2
    , ip >=1.4.1
    , posix-api >=0.3 && <0.4
    , primitive-addr >= 0.1 && <0.2
    , primitive-offset >= 0.2 && <0.3
    , primitive-unlifted >= 0.1 && <0.2
    , sockets-datagram-receive
    , sockets-datagram-receive-many
    , sockets-datagram-send
    , sockets-internal
    , sockets-stream-bidirectional
    , sockets-stream-send
    , sockets-stream-send-two
    , stm >=2.4
    , text >=1.2
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  hs-source-dirs: src
  if flag(mmsg)
    hs-source-dirs: src-mmsg
  else
    hs-source-dirs: src-no-mmsg
  default-language: Haskell2010
  ghc-options: -O2 -Wall

test-suite test
  type: exitcode-stdio-1.0
  hs-source-dirs: test
  main-is: Main.hs
  build-depends:
    , base >= 4.11.1.0 && < 5
    , sockets
    , tasty
    , tasty-hunit
    , ip >= 1.4.1
    , async
    , bytestring
    , byteslice >= 0.1.1
    , primitive-unlifted
    , primitive-addr
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  ghc-options: -Wall -O2 -threaded
  default-language: Haskell2010

benchmark macro
  type: exitcode-stdio-1.0
  build-depends:
    , base >= 4.11.1.0 && < 5
    , sockets
    , ip >= 1.4.1
    , bytestring >= 0.10.8.2
    , entropy >= 0.4.1.4
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  ghc-options: -Wall -O2 -threaded -rtsopts
  default-language: Haskell2010
  hs-source-dirs: bench
  main-is: Macro.hs

benchmark http
  type: exitcode-stdio-1.0
  build-depends:
    , base >= 4.11.1.0 && < 5
    , sockets
    , ip >= 1.4.1
    , bytestring >= 0.10.8.2
    , byteslice >= 0.1.1
  if flag(checked)
    build-depends: primitive-checked >= 0.7 && <0.8
  else
    build-depends: primitive >= 0.7 && <0.8
  ghc-options: -Wall -O2 -threaded -rtsopts
  default-language: Haskell2010
  hs-source-dirs: bench
  main-is: Http.hs

executable sockets-example
  if flag(example)
    build-depends:
      , base >= 4.11.1.0 && < 5
      , byteslice >= 0.1.1 && < 0.2
      , bytestring >= 0.10.8.2
      , fast-logger >= 2.4.13
      , ip >= 1.4.1
      , sockets
    if flag(checked)
      build-depends: primitive-checked >= 0.7 && <0.8
    else
      build-depends: primitive >= 0.7 && <0.8
  else
    buildable: False
  hs-source-dirs: example
  main-is: Main.hs
  ghc-options: -Wall -O2 -threaded
  default-language: Haskell2010