socks5NegotiateAuth function
Future<void>
socks5NegotiateAuth(
- Socks5HandshakeReader reader,
- void sink(), {
- String? username,
- String? password,
Negotiates the method-selection + optional RFC1929 user/pass leg
against reader, writing through sink. Public and socket-free so
the unit suite drives it with a scripted byte stream.
Implementation
Future<void> socks5NegotiateAuth(
Socks5HandshakeReader reader,
void Function(List<int> bytes) sink, {
String? username,
String? password,
}) async {
final useAuth = username != null;
sink(socks5GreetingBytes(useAuth: useAuth));
final greeting = await reader.readExactly(2);
if (greeting[0] != 0x05) {
throw const SocketException('SOCKS5 proxy sent a non-v5 greeting');
}
switch (greeting[1]) {
case 0x00:
break;
case 0x02 when useAuth:
sink(_rfc1929AuthBytes(username: username, password: password));
final verdict = await reader.readExactly(2);
if (verdict[1] != 0x00) {
throw const SocketException(
'SOCKS5 username/password authentication failed (RFC1929 status '
'non-zero) — check proxyUsername / proxyPasswordEnv',
);
}
case 0xFF:
throw const SocketException(
'SOCKS5 proxy rejected every offered auth method',
);
default:
throw SocketException(
'SOCKS5 proxy chose unsupported auth method 0x'
'${greeting[1].toRadixString(16)}',
);
}
}