Metadata-Version: 2.4
Name: PyTCP
Version: 3.0.6
Summary: Pure-Python, zero-dependency TCP/IP stack — Ethernet through RFC 9293 TCP — running in user space on a TAP/TUN interface, with a Berkeley-sockets API.
Author-email: Sebastian Majewski <ccie18643@gmail.com>
License-Expression: GPL-3.0-or-later
Project-URL: Homepage, https://github.com/ccie18643/PyTCP
Project-URL: Bug Tracker, https://github.com/ccie18643/PyTCP/issues
Keywords: pytcp,stack,networking,tcp,ip,ipv4,ipv6,arp,ethernet,icmp
Classifier: Programming Language :: Python :: 3.14
Classifier: Development Status :: 3 - Alpha
Classifier: Operating System :: POSIX :: Linux
Classifier: Natural Language :: English
Classifier: Environment :: Console
Classifier: Topic :: System :: Networking
Classifier: Typing :: Typed
Requires-Python: >=3.14
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PyTCP-net_addr==3.0.6
Requires-Dist: PyTCP-net_proto==3.0.6
Dynamic: license-file

# PyTCP

Pure-Python, zero-dependency TCP/IP stack — Ethernet through
RFC 9293 TCP — running in user space on a TAP/TUN interface, with
a Berkeley-sockets API.

```python
from pytcp import socket, stack
```

## What it is

A full, RFC-grounded TCP/IP stack implemented entirely in Python:
Ethernet II / 802.3 (LLC/SNAP), ARP, IPv4 / IPv6 (with Hop-by-Hop /
Destination-Options / Routing / Fragment extension headers),
ICMPv4 / ICMPv6 (incl. Neighbor Discovery, MLDv2 with MLDv1 fallback,
and IGMP IPv4 multicast group membership), DHCPv4 and DHCPv6 clients,
UDP, and a RFC 9293 TCP with a real FSM, congestion control
(Reno / NewReno / CUBIC), SACK / timestamps / window-scaling, and a
BSD-sockets facade. It runs on a TAP/TUN interface in user space — no
kernel module, no privileged data path.

The project's north star is **feature-equivalence with the Linux
host network stack**: where an RFC is unambiguous PyTCP follows it,
and where it is silent or offers a menu PyTCP picks the Linux
choice. Per-RFC adherence is audited under
[`docs/rfc/`](../../docs/rfc/).

## The three distributions

PyTCP is strictly layered into three independently-published dists
(one invariant: project folder == import name):

| Distribution | Import | Role |
|---|---|---|
| [`PyTCP-net_addr`](https://pypi.org/project/PyTCP-net_addr/) | `net_addr` | Address value types (IPv4/IPv6/MAC, networks, masks, wildcards, interface-addresses). |
| [`PyTCP-net_proto`](https://pypi.org/project/PyTCP-net_proto/) | `net_proto` | Protocol packet parse / assemble / validate. |
| **`PyTCP`** | `pytcp` | The running stack: subsystems/threads, sockets, FIB, ARP/ND caches, RX/TX rings. |

Installing `PyTCP` pulls the other two automatically (lockstep
version pin).

## Runtime architecture

```
TAP/TUN fd ─> RxRing ─> PacketHandler (per protocol, RX) ─> Socket queues / ARP+ND caches / fragment store
           <─ TxRing <─ PacketHandler (per protocol, TX) <─ Socket send / ND / DHCP / ACD
```

- **`Subsystem` base** — every background service (RX/TX rings,
  neighbor caches, timer, DHCPv4 / DHCPv6 clients, link-local / ACD)
  extends `Subsystem` and runs its own thread with an event-driven
  loop.
- **Packet handlers** — RX and TX paths are composed from
  per-protocol sub-handlers (`packet_handler__<proto>__<rx|tx>.py`).
  Every branch bumps a per-protocol stat counter for observability.
- **Event-driven timer** — a heap-based deadline scheduler (no
  polling tick); subsystems register deadlines and are woken on the
  nearest one.
- **Per-interface model** — a `PacketHandler` *is* an interface. A
  multi-homed host runs one handler per interface; global tables
  (routing FIB, socket table, neighbor caches) are shared and
  lock-guarded.

### Free-threaded (no-GIL) safety

Per-interface state is partitioned (single-writer TX ring hand-off);
the shared global tables (`RouteTable`, `SocketTable`,
`InterfaceTable`) guard their compound (check-then-act) operations
with a small `threading.Lock` and hand readers consistent snapshots.
Single built-in dict/list ops are left lock-free (individually
atomic).

## Control-plane APIs (the Phase-3 kernel/userspace boundary)

Consumers talk to the stack only through sanctioned surfaces — never
by reaching into runtime internals — mirroring how a Linux process
talks to its kernel:

| API | Linux equivalent |
|---|---|
| `pytcp.socket` — BSD `socket()` factory + methods (TCP / UDP / raw / `AF_PACKET`) | `socket(2)` |
| `pytcp.stack.sysctl` — runtime-tunable policy registry | `/proc/sys/net/` |
| `pytcp.stack.link` — per-interface MAC / MTU / state / counters | `ip link` / `RTM_*LINK` |
| `pytcp.stack.address` — assign / remove IPv4 / IPv6 host addresses | `ip addr` / `RTM_*ADDR` |
| `pytcp.stack.route` — add / remove / list routes (FIB); `Route` / `RouteProtocol` / `RouteScope` | `ip route` / `RTM_*ROUTE` |
| `pytcp.stack.neighbor` — static ARP / ND entries, cache flush | `ip neighbor` / `RTM_*NEIGH` |
| read-only snapshots (route table, neighbor cache, socket list, counters) | `/proc/net/*`, `ss` |

### Lifecycle

`stack.init(...)` builds the singletons, `stack.add_interface(...)` /
`stack.remove_interface(...)` attach / detach interfaces at runtime
(RTNETLINK `RTM_NEWLINK` / `RTM_DELLINK` semantics, including the
address / route / neighbor / session teardown cascade), `stack.start()`
spawns the subsystem threads, and `stack.stop()` winds them down.
A stack can `init()` with zero interfaces and gain them later — the
daemon / multi-homed shape.

### Sockets

`pytcp.socket` mirrors the stdlib `socket` module: a `socket(...)`
factory returns `TcpSocket` / `UdpSocket` / `RawSocket` /
`PacketSocket`, with `bind` / `listen` / `accept` / `connect` /
`send` / `recv` / `close`, `fileno()` + eventfd for `selectors`
integration, blocking & non-blocking modes, errno-mapped `OSError`,
`getaddrinfo`, common `setsockopt` options, IPv4/IPv6 multicast group
membership and source-filter options (`IP_ADD_MEMBERSHIP`,
`IP_ADD_SOURCE_MEMBERSHIP`, `IPV6_JOIN_GROUP`, …), and an
`IP_RECVERR` / `MSG_ERRQUEUE` error queue. Stdlib-parity constants
(`AF_INET`, `SOCK_STREAM`, `IP_*`, `SO_*`, `MSG_*`) are exposed as
bare module names backed by `IntEnum`s.

## Install

```bash
pip install PyTCP
```

Brings in `PyTCP-net_proto` and `PyTCP-net_addr` — no other
runtime dependencies (the whole stack is stdlib-only).
Fully typed (ships `py.typed`, PEP 561); strict-mypy clean.

## Running the stack

Running needs a TAP/TUN interface (root for interface / bridge
setup):

```bash
make tap7        # create the tap7 interface (sudo)
make bridge      # set up the bridge (sudo)
make run         # run the stack on tap7
make run_multi   # multi-interface demo
```

PyTCP is consumed as a library through the `stack` lifecycle API and
the `pytcp.socket` BSD-sockets API. See
[`examples/`](../../examples/) — `examples/stack.py` is the complete
runnable reference (TAP/TUN open, `stack.init(...)`, multi-interface
bind, runtime interface removal on SIGUSR1).

## Requirements

Python **3.14+**, Linux (TAP/TUN), POSIX.

## Current state (3.0.6)

- ~175 source modules; the pytcp suite runs ~4,000 unit + integration
  tests (the full repo suite, across all three packages + examples, is
  ~12,400). Lint clean (codespell + isort + black + flake8 + mypy
  strict + pylint).
- Host-stack feature-complete (North Star Phase 1). Phase-2
  router/forwarding sits behind the `forward_or_deliver` seam as a
  stub. Authoring contracts in
  [`.claude/rules/pytcp.md`](../../.claude/rules/pytcp.md); per-RFC
  adherence in [`docs/rfc/`](../../docs/rfc/).

## License

GPL-3.0-or-later. PyTCP by Sebastian Majewski.
