Ein SOCKS5-tenar skriv fire byte kvar for seg, og klienten verkar først når desse skrivingane er slått saman. Samanslåing kan endre tidspunktet, men TCP lovar framleis ikkje éi lesing per skriving.

Klienten treng ein svarparser. Etter metodeval og eventuell påkravd autentisering byrjar eit SOCKS5-kommandosvar med fire byte: versjon, resultat, reservert byte og adressetype. Den resterande lengda er avhengig av den adressetypen.

Ein .NET 7+-parser som berre treng å bruke eit vellukka CONNECT-svar, kan nytte:

static async Task ReadConnectReply(Stream stream, CancellationToken ct)
{
    byte[] prefix = new byte[4];
    await stream.ReadExactlyAsync(prefix, ct);
    if (prefix[0] != 5 || prefix[2] != 0)
        throw new IOException("Invalid SOCKS5 reply");
    if (prefix[1] != 0)
        throw new IOException($"SOCKS5 request failed: {prefix[1]}");

    int remaining;
    switch (prefix[3])
    {
        case 1: remaining = 4 + 2; break;
        case 4: remaining = 16 + 2; break;
        case 3:
            byte[] length = new byte[1];
            await stream.ReadExactlyAsync(length, ct);
            remaining = length[0] + 2;
            break;
        default:
            throw new IOException("Unknown SOCKS5 address type");
    }
    await stream.ReadExactlyAsync(new byte[remaining], ct);
}

Dei to siste byta er den bundne porten. IPv4 treng fire byte; IPv6 treng seksten; ei domeneadresse ber ein lengdebyte før namnet.

Oppgi eit avbrytingstoken med den planlagde forhandlingsfristen. ReadExactlyAsync handterer kortare einskildlesingar og kastar eit unntak når straumen sluttar før den etterspurde lengda. Ved feil, kast den mislukka tilkoplinga via oppryddingsvegen til eigaren.

Ved suksess, stopp ved svargrensa. Byta etter ho høyrer til målprotokollen. Ei større spekulativ lesing må ta vare på overskotsbyta i staden for å kaste byrjinga av applikasjonsstraumen.

Relaterte artiklar