# flare.tcp.listener

> A module of flare_mlake's API.

TCP listener: a socket bound and listening for incoming connections.

``TcpListener`` wraps a ``RawSocket`` in the listening state. Call
``accept()`` to receive incoming connections as ``TcpStream`` instances.

Design rules enforced here:
- ``SO_REUSEADDR`` is set before every ``bind()`` call.
- ``TCP_NODELAY`` is set on every accepted ``TcpStream``.
- ``accept()`` sets ``TCP_NODELAY`` on the client socket automatically.

## Structs

### `TcpListener`

```mojo
struct TcpListener
```

A TCP socket in the listening state.

``TcpListener`` accepts incoming TCP connections and returns each one
as a ``TcpStream``. ``SO_REUSEADDR`` is always set before ``bind()``.

The listener is closed automatically when the struct is destroyed.

Thread safety:
    Not thread-safe . Do not call ``accept()`` concurrently.

Example:
```mojo
from flare.tcp import TcpListener, TcpStream
from flare.net import SocketAddr

var listener = TcpListener.bind(SocketAddr.localhost(8080))
var stream = listener.accept() # blocks until a client connects
stream.write_all("welcome".as_bytes())
```

Implements: `Movable`

#### `__init__`

```mojo
def __init__(out self, var socket: RawSocket, local: SocketAddr)
```

Wrap an already-bound, listening ``RawSocket``.

Safety:
``socket`` must already be in the listening state (``listen(2)``
was called). The caller must not close ``socket`` after this.

Args:

- `socket`: Open, listening socket (ownership transferred).
- `local`: The address the socket was bound to.

#### `__deinit__`

```mojo
def __deinit__(deinit self)
```

#### `bind`

```mojo
def bind(addr: SocketAddr) -> Self
```

Bind a TCP listener to ``addr`` with default options.

``SO_REUSEADDR`` is set before binding. The backlog is 128.

Example:
```mojo
var l = TcpListener.bind(SocketAddr.localhost(8080))
```

Args:

- `addr`: The local address to bind (use port 0 for OS-assigned port).

Raises: AddressInUse: If the port is already in use.
NetworkError: For any other OS bind/listen error.

#### `bind_with_options`

```mojo
def bind_with_options(addr: SocketAddr, backlog: Int = Int(128), reuse_port: Bool = False) -> Self
```

Bind with explicit backlog and ``SO_REUSEPORT`` control.

Example:
```mojo
var l = TcpListener.bind_with_options(
    SocketAddr.localhost(8080), backlog=1024, reuse_port=True
)
```

Args:

- `addr`: The local address to bind.
- `backlog`: Maximum length of the pending-connections queue.
- `reuse_port`: If ``True``, set ``SO_REUSEPORT`` (useful for
            multi-process load balancing).

Raises: AddressInUse: If the port is already in use.
NetworkError: For any other OS error.

#### `accept`

```mojo
def accept(self) -> TcpStream
```

Block until an incoming connection arrives and return it.

Sets ``TCP_NODELAY`` on the accepted socket automatically.

Example:
```mojo
while True:
    var client = listener.accept()
    client.write_all("hello".as_bytes())
    client.close()
```

Raises: NetworkError: If ``accept(2)`` fails. If the peer address cannot
be decoded afterwards the accepted socket is closed before
the error propagates (it is never leaked).

#### `local_addr`

```mojo
def local_addr(self) -> SocketAddr
```

Return the local address the listener is bound to.

#### `as_raw_fd`

```mojo
def as_raw_fd(self) -> c_int
```

Return the underlying file descriptor.

Intended for the shared-listener scheduler: bind once on
the main thread, then hand the fd (a small integer) to every
worker via the per-worker context struct. Workers call
``flare.tcp.accept_fd`` directly rather than touching the
non-thread-safe ``TcpListener`` object.

The returned fd is borrowed; its lifetime is tied to ``self``.
Callers must not ``close(fd)`` themselves; let ``TcpListener``
own the close.

#### `close`

```mojo
def close(mut self)
```

Close the listening socket. Idempotent.

## Functions

### `accept_fd`

```mojo
def accept_fd(listener_fd: Int32) -> TcpStream
```

Accept one connection on a borrowed listener fd.

Functionally equivalent to ``TcpListener.accept(self)`` but takes
the listener as a raw integer fd, so the caller can share a single
listener across multiple workers without giving any one worker
ownership of the underlying ``TcpListener`` (multi-worker
scheduler path; see ``flare.runtime.scheduler``).

The returned ``TcpStream`` owns the accepted client fd and has
``TCP_NODELAY`` already set, matching ``TcpListener.accept``'s
contract. Same error semantics: raises ``NetworkError`` on
``accept(2)`` failure (including ``EAGAIN`` / ``EWOULDBLOCK``,
which the multi-worker reactor catches as a normal "no more
pending conns" signal).

Args:

- `listener_fd`: Fd of a listener socket. Caller must keep the
    socket open for the duration of this call; this function
    does NOT take ownership of the fd.

Raises: NetworkError: If ``accept(2)`` fails. The errno-bearing
variant lets the caller distinguish ``EAGAIN`` (drain the
accept loop) from a hard failure.
