SOCKS5-palvelin kirjoittaa neljä tavua erikseen, ja asiakas toimii vasta kun nämä kirjoitukset on yhdistetty. Yhdistäminen voi muuttaa ajoitusta, mutta TCP ei edelleenkään lupaa yhtä lukua kirjoitusta kohden.

Asiakas tarvitsee vastauksen jäsentimen. Menetelmän valinnan ja mahdollisen todennuksen jälkeen SOCKS5-komennon vastaus alkaa neljällä tavulla: versio, tulos, varattu tavu ja osoitetyyppi. Jäljellä oleva pituus riippuu tästä osoitetyypistä.

.NET 7+ -jäsennin, jonka tarvitsee kuluttaa vain onnistunut CONNECT-vastaus, voi käyttää:

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);
}

Kaksi viimeistä tavua ovat sidottu portti. IPv4 tarvitsee neljä tavua; IPv6 tarvitsee kuusitoista; verkkotunnusosoite kantaa pituustavun ennen nimeä.

Anna peruutustunnus aiottuun neuvottelumääräaikaan. ReadExactlyAsync käsittelee lyhyempiä yksittäisiä lukuja ja heittää poikkeuksen, kun virta päättyy ennen pyydettyä pituutta. Epäonnistuessa hylkää epäonnistunut yhteys sen omistajan siivouspolun kautta.

Onnistuessa pysähdy vastauksen rajalle. Sen jälkeiset tavut kuuluvat kohdeprotokollalle. Suuremman spekulatiivisen luvun on säilytettävä ylimääräiset tavut sen sijaan, että sovellusvirran alku heitettäisiin pois.

Aiheeseen liittyvät artikkelit