SOCKS5-servilo skribas kvar bajtojn aparte, kaj la kliento funkcias nur post kiam tiuj skriboj estas kunigitaj. Kunigo povas ŝanĝi la tempigon, sed TCP ankoraŭ ne promesas unu legadon por ĉiu skribo.

La kliento bezonas respondanalizilon. Post metoda elekto kaj iu ajn postulata aŭtentikigo, SOCKS5-komanda respondo komenciĝas per kvar bajtoj: versio, rezulto, rezervita bajto kaj adresa tipo. La restanta longo dependas de tiu adresa tipo.

Analizilo por .NET 7+, kiu bezonas konsumi nur sukcesan CONNECT-respondon, povas uzi:

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

La lastaj du bajtoj estas la ligita pordo. IPv4 bezonas kvar bajtojn; IPv6 bezonas dek ses; domajna adreso portas longobajton antaŭ la nomo.

Provizu nuligtonon kun la intencita intertrakta templimo. ReadExactlyAsync traktas pli mallongajn unuopajn legadojn kaj ĵetas escepton kiam la fluo finiĝas antaŭ la postulata longo. Ĉe malsukceso, forĵetu la malsukcesan konekton per la puriga vojo de ĝia posedanto.

Ĉe sukceso, haltu ĉe la responda limo. Bajtoj post ĝi apartenas al la cella protokolo. Pli granda spekulativa legado devas konservi la troajn bajtojn anstataŭ forĵeti la komencon de la aplikaĵa fluo.

Rilataj artikoloj