Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
446a22b
temp: temporty quic impl
AkMo3 Jun 10, 2025
54b3055
fix: impl quic listener
AkMo3 Jun 10, 2025
a3231af
fix: add basic tests for listener
AkMo3 Jun 12, 2025
bc2ac47
fix: add basic quic stream and associated tests
AkMo3 Jun 12, 2025
ce76641
temp: impl security modile
AkMo3 Jun 13, 2025
45c5f16
fix: update conn and transport for security
AkMo3 Jun 14, 2025
94d920f
chore: fix doc generation for quic transport
AkMo3 Jun 15, 2025
ac01cc5
fix: add echo example
AkMo3 Jun 16, 2025
a1d1a07
fix: implement missing methods
AkMo3 Jun 16, 2025
cb6fd27
fix: process packets received and send to quic
AkMo3 Jun 17, 2025
369f793
chore: add logs to debug connection
AkMo3 Jun 17, 2025
123c86c
fix: duplication connection creation for same sessions
AkMo3 Jun 17, 2025
6633eb0
fix: add QUICTLSSecurityConfig for better security config handle
AkMo3 Jun 18, 2025
e2fee14
fix: try to fix connection id updation
AkMo3 Jun 20, 2025
8263052
fix: peer verification successful
AkMo3 Jun 29, 2025
2689040
fix: handle short quic headers and compelete connection establishment
AkMo3 Jun 29, 2025
bbe632b
fix: initial connection succesfull
AkMo3 Jun 30, 2025
8f0cdc9
fix: succesfull echo
AkMo3 Jun 30, 2025
6c45862
fix: succesfull echo example completed
AkMo3 Jul 1, 2025
c15c317
fix: accept stream on server side
AkMo3 Jul 2, 2025
03bf071
chore: cleanup and near v1 quic impl
AkMo3 Jul 2, 2025
0f64bb4
chore: log cleanup
AkMo3 Jul 4, 2025
b3f0a4e
DEBUG: client certificate at server
AkMo3 Jul 7, 2025
342ac74
fix: client certificate verification done
AkMo3 Jul 9, 2025
8e6e881
fix: add support for rsa, ecdsa keys in quic
AkMo3 Jul 11, 2025
a6ff931
chore: fix linting issues
AkMo3 Jul 13, 2025
84c9ddc
chore: cleanup and doc gen fixes
AkMo3 Jul 14, 2025
f550c19
multiple streams ping, invalid certificate handling
lla-dane Aug 5, 2025
5ed3707
fix: use ASN.1 format certificate extension
AkMo3 Aug 14, 2025
6d1e53a
fix: ignore peer id derivation for quic dial
AkMo3 Aug 14, 2025
760f94b
fix: quic maddr test
AkMo3 Aug 14, 2025
933741b
fix: allow accept stream to wait indefinitely
AkMo3 Aug 15, 2025
58433f9
fix: changes to opening new stream, setting quic connection parameters
AkMo3 Aug 16, 2025
2c03ac4
fix: Peer ID verification during dial (#7)
lla-dane Aug 17, 2025
d97b860
fix: add nim libp2p echo interop
AkMo3 Aug 30, 2025
89cb8c0
fix: check forced failure for nim interop
AkMo3 Aug 30, 2025
8e74f94
update multiaddr dep
lla-dane Aug 30, 2025
e1141ee
fix: fix nim interop env setup file
AkMo3 Aug 31, 2025
1861139
chore: remove unwanted code, fix type issues and comments
AkMo3 Aug 31, 2025
9749be6
fix: refine selection of quic transport while init
AkMo3 Aug 31, 2025
eab8df8
chore: add news fragment
AkMo3 Aug 31, 2025
159d2cc
Merge remote-tracking branch 'upstream/main'
AkMo3 Sep 2, 2025
33730bd
fix: type assertion for config class
AkMo3 Sep 2, 2025
4b4214f
fix: add mistakenly removed windows CI/CD tests
AkMo3 Sep 2, 2025
d2d4c4b
fix: proper connection config setup
AkMo3 Sep 2, 2025
d0c8130
fix: quic transport mock in quic connection
AkMo3 Sep 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,48 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}

- name: Install Nim for interop testing
if: matrix.toxenv == 'interop'
run: |
echo "Installing Nim for nim-libp2p interop testing..."
curl -sSf https://nim-lang.org/choosenim/init.sh | sh -s -- -y --firstInstall
echo "$HOME/.nimble/bin" >> $GITHUB_PATH
echo "$HOME/.choosenim/toolchains/nim-stable/bin" >> $GITHUB_PATH

- name: Cache nimble packages
if: matrix.toxenv == 'interop'
uses: actions/cache@v4
with:
path: |
~/.nimble
~/.choosenim/toolchains/*/lib
key: ${{ runner.os }}-nimble-${{ hashFiles('**/nim_echo_server.nim') }}
restore-keys: |
${{ runner.os }}-nimble-

- name: Build nim interop binaries
if: matrix.toxenv == 'interop'
run: |
export PATH="$HOME/.nimble/bin:$HOME/.choosenim/toolchains/nim-stable/bin:$PATH"
cd tests/interop/nim_libp2p
./scripts/setup_nim_echo.sh

- run: |
python -m pip install --upgrade pip
python -m pip install tox
- run: |

- name: Run Tests or Generate Docs
run: |
if [[ "${{ matrix.toxenv }}" == 'docs' ]]; then
export TOXENV=docs
else
export TOXENV=py${{ matrix.python }}-${{ matrix.toxenv }}
fi
# Set PATH for nim commands during tox
if [[ "${{ matrix.toxenv }}" == 'interop' ]]; then
export PATH="$HOME/.nimble/bin:$HOME/.choosenim/toolchains/nim-stable/bin:$PATH"
fi
python -m tox run -r

windows:
Expand Down
77 changes: 77 additions & 0 deletions docs/libp2p.transport.quic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
libp2p.transport.quic package
=============================

Submodules
----------

libp2p.transport.quic.config module
-----------------------------------

.. automodule:: libp2p.transport.quic.config
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.connection module
---------------------------------------

.. automodule:: libp2p.transport.quic.connection
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.exceptions module
---------------------------------------

.. automodule:: libp2p.transport.quic.exceptions
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.listener module
-------------------------------------

.. automodule:: libp2p.transport.quic.listener
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.security module
-------------------------------------

.. automodule:: libp2p.transport.quic.security
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.stream module
-----------------------------------

.. automodule:: libp2p.transport.quic.stream
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.transport module
--------------------------------------

.. automodule:: libp2p.transport.quic.transport
:members:
:undoc-members:
:show-inheritance:

libp2p.transport.quic.utils module
----------------------------------

.. automodule:: libp2p.transport.quic.utils
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

.. automodule:: libp2p.transport.quic
:members:
:undoc-members:
:show-inheritance:
5 changes: 5 additions & 0 deletions docs/libp2p.transport.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Subpackages

libp2p.transport.tcp

.. toctree::
:maxdepth: 4

libp2p.transport.quic

Submodules
----------

Expand Down
178 changes: 178 additions & 0 deletions examples/echo/echo_quic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/usr/bin/env python3
"""
QUIC Echo Example - Fixed version with proper client/server separation

This program demonstrates a simple echo protocol using QUIC transport where a peer
listens for connections and copies back any input received on a stream.

Fixed to properly separate client and server modes - clients don't start listeners.
"""

import argparse
import logging

from multiaddr import Multiaddr
import trio

from libp2p import new_host
from libp2p.crypto.secp256k1 import create_new_key_pair
from libp2p.custom_types import TProtocol
from libp2p.network.stream.net_stream import INetStream
from libp2p.peer.peerinfo import info_from_p2p_addr

PROTOCOL_ID = TProtocol("/echo/1.0.0")


async def _echo_stream_handler(stream: INetStream) -> None:
try:
msg = await stream.read()
await stream.write(msg)
await stream.close()
except Exception as e:
print(f"Echo handler error: {e}")
try:
await stream.close()
except: # noqa: E722
pass


async def run_server(port: int, seed: int | None = None) -> None:
"""Run echo server with QUIC transport."""
listen_addr = Multiaddr(f"/ip4/0.0.0.0/udp/{port}/quic")

if seed:
import random

random.seed(seed)
secret_number = random.getrandbits(32 * 8)
secret = secret_number.to_bytes(length=32, byteorder="big")
else:
import secrets

secret = secrets.token_bytes(32)

# Create host with QUIC transport
host = new_host(
enable_quic=True,
key_pair=create_new_key_pair(secret),
)

# Server mode: start listener
async with host.run(listen_addrs=[listen_addr]):
try:
print(f"I am {host.get_id().to_string()}")
host.set_stream_handler(PROTOCOL_ID, _echo_stream_handler)

print(
"Run this from the same folder in another console:\n\n"
f"python3 ./examples/echo/echo_quic.py "
f"-d {host.get_addrs()[0]}\n"
)
print("Waiting for incoming QUIC connections...")
await trio.sleep_forever()
except KeyboardInterrupt:
print("Closing server gracefully...")
await host.close()
return


async def run_client(destination: str, seed: int | None = None) -> None:
"""Run echo client with QUIC transport."""
if seed:
import random

random.seed(seed)
secret_number = random.getrandbits(32 * 8)
secret = secret_number.to_bytes(length=32, byteorder="big")
else:
import secrets

secret = secrets.token_bytes(32)

# Create host with QUIC transport
host = new_host(
enable_quic=True,
key_pair=create_new_key_pair(secret),
)

# Client mode: NO listener, just connect
async with host.run(listen_addrs=[]): # Empty listen_addrs for client
print(f"I am {host.get_id().to_string()}")

maddr = Multiaddr(destination)
info = info_from_p2p_addr(maddr)

# Connect to server
print("STARTING CLIENT CONNECTION PROCESS")
await host.connect(info)
print("CLIENT CONNECTED TO SERVER")

# Start a stream with the destination
stream = await host.new_stream(info.peer_id, [PROTOCOL_ID])

msg = b"hi, there!\n"

await stream.write(msg)
response = await stream.read()

print(f"Sent: {msg.decode('utf-8')}")
print(f"Got: {response.decode('utf-8')}")
await stream.close()
await host.disconnect(info.peer_id)


async def run(port: int, destination: str, seed: int | None = None) -> None:
"""
Run echo server or client with QUIC transport.

Fixed version that properly separates client and server modes.
"""
if not destination: # Server mode
await run_server(port, seed)
else: # Client mode
await run_client(destination, seed)


def main() -> None:
"""Main function - help text updated for QUIC."""
description = """
This program demonstrates a simple echo protocol using QUIC
transport where a peer listens for connections and copies back
any input received on a stream.

QUIC provides built-in TLS security and stream multiplexing over UDP.

To use it, first run 'python ./echo_quic_fixed.py -p <PORT>', where <PORT> is
the UDP port number. Then, run another host with ,
'python ./echo_quic_fixed.py -d <DESTINATION>'
where <DESTINATION> is the QUIC multiaddress of the previous listener host.
"""

example_maddr = "/ip4/127.0.0.1/udp/8000/quic/p2p/QmQn4SwGkDZKkUEpBRBv"

parser = argparse.ArgumentParser(description=description)
parser.add_argument("-p", "--port", default=0, type=int, help="UDP port number")
parser.add_argument(
"-d",
"--destination",
type=str,
help=f"destination multiaddr string, e.g. {example_maddr}",
)
parser.add_argument(
"-s",
"--seed",
type=int,
help="provide a seed to the random number generator",
)
args = parser.parse_args()

try:
trio.run(run, args.port, args.destination, args.seed)
except KeyboardInterrupt:
pass


if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("aioquic").setLevel(logging.DEBUG)
main()
Loading
Loading