import sys
sys.unraisablehook = lambda unraisable: None

import asyncio
import ssl
from argparse import ArgumentParser

from aioquic.asyncio import connect
from aioquic.quic.configuration import QuicConfiguration

TLS13_CIPHERS = [
    'TLS_AES_128_GCM_SHA256',
    'TLS_AES_256_GCM_SHA384',
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_128_CCM_SHA256'
]

def get_client_supported_tls13_ciphers():
    """Gibt die vom Client unterstützten TLS 1.3 Cipher-Suiten zurück."""
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    supported = []
    for cipher in ctx.get_ciphers():
        if cipher['protocol'] == 'TLSv1.3' and cipher['name'] in TLS13_CIPHERS:
            supported.append(cipher['name'])
    return supported

async def check_cipher(host, port, cipher):
    """Versucht eine QUIC-Verbindung mit der angegebenen Cipher-Suite herzustellen."""
    config = QuicConfiguration(is_client=True)
    config.ciphers = [cipher]
    config.verify_mode = ssl.CERT_NONE
    config.alpn_protocols = ['h3']  # HTTP/3 ALPN

    try:
        async with asyncio.timeout(5):
            async with connect(host, port, configuration=config):
                return True
    except Exception:
        return False

async def main(host, port):
    client_ciphers = get_client_supported_tls13_ciphers()
    supported_ciphers = []

    for cipher in client_ciphers:
        if await check_cipher(host, port, cipher):
            supported_ciphers.append(cipher)

    for cipher in supported_ciphers:
        print(cipher)

if __name__ == "__main__":
    parser = ArgumentParser(description="Ermittelt die unterstützten TLS 1.3 Cipher-Suiten eines HTTP/3-Servers.")
    parser.add_argument("host", help="Hostname des Servers")
    parser.add_argument("-p", "--port", type=int, default=443, help="Port des Servers (Standard: 443)")
    args = parser.parse_args()

    asyncio.run(main(args.host, args.port))
