From 5a6edd6f458ec2fde77a9ff95ff7d52628284ce3 Mon Sep 17 00:00:00 2001 From: Dave Bakker Date: Sat, 18 Mar 2023 09:39:03 +0100 Subject: [PATCH 1/2] Merge bind and listen into a single call. --- wit/tcp-create-socket.wit | 2 +- wit/tcp.wit | 66 ++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 40 deletions(-) diff --git a/wit/tcp-create-socket.wit b/wit/tcp-create-socket.wit index 04e3943..a41ca38 100644 --- a/wit/tcp-create-socket.wit +++ b/wit/tcp-create-socket.wit @@ -8,7 +8,7 @@ default interface tcp-create-socket { /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. /// /// This function does not require a network capability handle. This is considered to be safe because - /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect` + /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `listen`/`connect` /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. /// /// # Typical errors diff --git a/wit/tcp.wit b/wit/tcp.wit index 0f5f180..b47bf6e 100644 --- a/wit/tcp.wit +++ b/wit/tcp.wit @@ -20,30 +20,7 @@ default interface tcp { } - /// Bind the socket to a specific network on the provided IP address and port. - /// - /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which - /// network interface(s) to bind to. - /// If the TCP/UDP port is zero, the socket will be bound to a random free port. - /// - /// When a socket is not explicitly bound, the first invocation to a listen or connect operation will - /// implicitly bind the socket. - /// - /// # Typical errors - /// - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL) - /// - `already-bound`: The socket is already bound. (EINVAL) - /// - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) - /// - `address-in-use`: Address is already in use. (EADDRINUSE) - /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) - /// - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY) - /// - /// # References - /// - - /// - - /// - - /// - - bind: func(this: tcp-socket, network: network, local-address: ip-socket-address) -> result<_, error-code> - + /// Connect to a remote endpoint. /// /// On success: @@ -58,11 +35,10 @@ default interface tcp { /// - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) /// - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) /// - `invalid-remote-address`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) - /// - `already-attached`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. /// - `already-connected`: The socket is already in the Connection state. (EISCONN) /// - `already-listening`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows) /// - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) - /// - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: Another `connect` or `listen` operation is already in progress. (EALREADY) /// /// # References /// - @@ -71,23 +47,35 @@ default interface tcp { /// - connect: func(this: tcp-socket, network: network, remote-address: ip-socket-address) -> result, error-code> - /// Start listening for new connections. + /// Bind the socket to a specific network on the provided IP address & port and start listening for new connections. + /// + /// This is the POSIX equivalent of calling `bind` and `listen` consecutively. + /// + /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which + /// network interface(s) to bind to. + /// If the TCP/UDP port is zero, the socket will be bound to a random free port. /// /// Transitions the socket into the Listener state. /// /// # Typical errors - /// - `already-attached`: The socket is already attached to a different network. The `network` passed to `listen` must be identical to the one passed to `bind`. + /// - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL) /// - `already-connected`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD) /// - `already-listening`: The socket is already in the Listener state. - /// - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) - /// - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EINVAL on BSD) + /// - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) + /// - `address-in-use`: Address is already in use. (EADDRINUSE) + /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) + /// - `concurrency-conflict`: Another `connect` or `listen` operation is already in progress. (EALREADY, EINVAL on BSD) /// /// # References + /// - /// - + /// - /// - + /// - /// - + /// - /// - - listen: func(this: tcp-socket, network: network) -> result<_, error-code> + listen: func(this: tcp-socket, network: network, local-address: ip-socket-address) -> result<_, error-code> /// Accept a new client socket. /// @@ -120,7 +108,7 @@ default interface tcp { /// - local-address: func(this: tcp-socket) -> result - /// Get the bound remote address. + /// Get the connected remote address. /// /// # Typical errors /// - `not-connected`: The socket is not connected to a remote address. (ENOTCONN) @@ -145,7 +133,7 @@ default interface tcp { /// - `ipv6-only-operation`: (get/set) `this` socket is an IPv4 socket. /// - `already-bound`: (set) The socket is already bound. /// - `not-supported`: (set) Host does not support dual-stack sockets. (Implementations are not required to.) - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) ipv6-only: func(this: tcp-socket) -> result set-ipv6-only: func(this: tcp-socket, value: bool) -> result<_, error-code> @@ -153,20 +141,20 @@ default interface tcp { /// /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) set-listen-backlog-size: func(this: tcp-socket, value: u64) -> result<_, error-code> /// Equivalent to the SO_KEEPALIVE socket option. /// /// # Typical errors - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) keep-alive: func(this: tcp-socket) -> result set-keep-alive: func(this: tcp-socket, value: bool) -> result<_, error-code> /// Equivalent to the TCP_NODELAY socket option. /// /// # Typical errors - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) no-delay: func(this: tcp-socket) -> result set-no-delay: func(this: tcp-socket, value: bool) -> result<_, error-code> @@ -175,7 +163,7 @@ default interface tcp { /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. /// - `already-listening`: (set) The socket is already in the Listener state. - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) unicast-hop-limit: func(this: tcp-socket) -> result set-unicast-hop-limit: func(this: tcp-socket, value: u8) -> result<_, error-code> @@ -193,7 +181,7 @@ default interface tcp { /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. /// - `already-listening`: (set) The socket is already in the Listener state. - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) receive-buffer-size: func(this: tcp-socket) -> result set-receive-buffer-size: func(this: tcp-socket, value: u64) -> result<_, error-code> send-buffer-size: func(this: tcp-socket) -> result @@ -209,7 +197,7 @@ default interface tcp { /// They're planned to be removed when `future` is natively supported in Preview3. /// /// # Typical errors - /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) + /// - `concurrency-conflict`: (set) A `connect` or `listen` operation is already in progress. (EALREADY) non-blocking: func(this: tcp-socket) -> result set-non-blocking: func(this: tcp-socket, value: bool) -> result<_, error-code> From 6119993908a18389c9e3e4f80e5d32f62bab0baa Mon Sep 17 00:00:00 2001 From: Dave Bakker Date: Sat, 18 Mar 2023 10:09:21 +0100 Subject: [PATCH 2/2] Update example-world.md --- example-world.md | 73 +++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/example-world.md b/example-world.md index b9c020f..5d3f5cf 100644 --- a/example-world.md +++ b/example-world.md @@ -992,39 +992,6 @@ be used.


Functions

-

bind: func

-

Bind the socket to a specific network on the provided IP address and port.

-

If the IP address is zero (0.0.0.0 in IPv4, :: in IPv6), it is left to the implementation to decide which -network interface(s) to bind to. -If the TCP/UDP port is zero, the socket will be bound to a random free port.

-

When a socket is not explicitly bound, the first invocation to a listen or connect operation will -implicitly bind the socket.

-

Typical errors

-
    -
  • address-family-mismatch: The local-address has the wrong address family. (EINVAL)
  • -
  • already-bound: The socket is already bound. (EINVAL)
  • -
  • ephemeral-ports-exhausted: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
  • -
  • address-in-use: Address is already in use. (EADDRINUSE)
  • -
  • address-not-bindable: local-address is not an address that the network can bind to. (EADDRNOTAVAIL)
  • -
  • concurrency-conflict: Another bind, connect or listen operation is already in progress. (EALREADY)
  • -
-

References

- -
Params
- -
Return values
-

connect: func

Connect to a remote endpoint.

On success:

@@ -1041,11 +1008,10 @@ implicitly bind the socket.

  • address-family-mismatch: The remote-address has the wrong address family. (EAFNOSUPPORT)
  • invalid-remote-address: The IP address in remote-address is set to INADDR_ANY (0.0.0.0 / ::). (EADDRNOTAVAIL on Windows)
  • invalid-remote-address: The port in remote-address is set to 0. (EADDRNOTAVAIL on Windows)
  • -
  • already-attached: The socket is already attached to a different network. The network passed to connect must be identical to the one passed to bind.
  • already-connected: The socket is already in the Connection state. (EISCONN)
  • already-listening: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows)
  • ephemeral-ports-exhausted: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD)
  • -
  • concurrency-conflict: Another bind, connect or listen operation is already in progress. (EALREADY)
  • +
  • concurrency-conflict: Another connect or listen operation is already in progress. (EALREADY)
  • References

    listen: func

    -

    Start listening for new connections.

    +

    Bind the socket to a specific network on the provided IP address & port and start listening for new connections.

    +

    This is the POSIX equivalent of calling bind and listen consecutively.

    +

    If the IP address is zero (0.0.0.0 in IPv4, :: in IPv6), it is left to the implementation to decide which +network interface(s) to bind to. +If the TCP/UDP port is zero, the socket will be bound to a random free port.

    Transitions the socket into the Listener state.

    Typical errors

      -
    • already-attached: The socket is already attached to a different network. The network passed to listen must be identical to the one passed to bind.
    • +
    • address-family-mismatch: The local-address has the wrong address family. (EINVAL)
    • already-connected: The socket is already in the Connection state. (EISCONN, EINVAL on BSD)
    • already-listening: The socket is already in the Listener state.
    • -
    • ephemeral-ports-exhausted: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE)
    • -
    • concurrency-conflict: Another bind, connect or listen operation is already in progress. (EINVAL on BSD)
    • +
    • ephemeral-ports-exhausted: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows)
    • +
    • address-in-use: Address is already in use. (EADDRINUSE)
    • +
    • address-not-bindable: local-address is not an address that the network can bind to. (EADDRNOTAVAIL)
    • +
    • concurrency-conflict: Another connect or listen operation is already in progress. (EALREADY, EINVAL on BSD)

    References

    Params
    Return values

    remote-address: func

    -

    Get the bound remote address.

    +

    Get the connected remote address.

    Typical errors

    • not-connected: The socket is not connected to a remote address. (ENOTCONN)
    • @@ -1177,7 +1154,7 @@ a pair of streams that can be used to read & write to the connection.

    • ipv6-only-operation: (get/set) this socket is an IPv4 socket.
    • already-bound: (set) The socket is already bound.
    • not-supported: (set) Host does not support dual-stack sockets. (Implementations are not required to.)
    • -
    • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
    • +
    • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
    Params
      @@ -1202,7 +1179,7 @@ a pair of streams that can be used to read & write to the connection.

      Typical errors

      • already-connected: (set) The socket is already in the Connection state.
      • -
      • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
      • +
      • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
      Params
        @@ -1217,7 +1194,7 @@ a pair of streams that can be used to read & write to the connection.

        Equivalent to the SO_KEEPALIVE socket option.

        Typical errors

          -
        • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
        • +
        • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
        Params
          @@ -1241,7 +1218,7 @@ a pair of streams that can be used to read & write to the connection.

          Equivalent to the TCP_NODELAY socket option.

          Typical errors

            -
          • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
          • +
          • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
          Params
            @@ -1267,7 +1244,7 @@ a pair of streams that can be used to read & write to the connection.

            • already-connected: (set) The socket is already in the Connection state.
            • already-listening: (set) The socket is already in the Listener state.
            • -
            • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
            • +
            • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
            Params
              @@ -1299,7 +1276,7 @@ for internal metadata structures.

              • already-connected: (set) The socket is already in the Connection state.
              • already-listening: (set) The socket is already in the Listener state.
              • -
              • concurrency-conflict: (set) A bind, connect or listen operation is already in progress. (EALREADY)
              • +
              • concurrency-conflict: (set) A connect or listen operation is already in progress. (EALREADY)
              Params