Запрос соединения SOCKS4 выполняется успешно, но приложение так и не видит начальное приветствие сервера. Одно из мест, куда стоит посмотреть, — первое чтение коннектора. Чтение шестнадцати байт слишком велико для восьмибайтного ответа SOCKS4.

Поле ответаБайты
Поле версии ответа1
Код результата1
Поле порта2
Поле адреса4

Код результата 0x5a означает, что запрос разрешён. SOCKS4a меняет то, как запрос несёт имя хоста; он не превращает ответ в шестнадцать байт.

После ответа тот же поток TCP несёт протокол назначения. Почтовый сервер может отправить приветствие сразу. Поэтому чтение, забирающее шестнадцать доступных байт, может захватить полный ответ прокси и первые восемь байт этого приветствия. Если дальше пока ничего нет, слишком большое блокирующее чтение, наоборот, добавит лишнее ожидание.

Точная длина — обязанность парсера

Однократный запрос восьми байт не доказывает, что восемь байт пришли. Чтения из потока могут вернуть меньше. Соберите ровно длину ответа в пределах срока, остановитесь на закрытом или сбойном потоке, проверьте ответ и оставьте следующие байты приложению.

Если коннектор использует большее буферизованное чтение, сохраните всё после границы и передайте следующему потребителю. Выбрасывание излишка — та же потеря данных при другом размере чтения.

SOCKS5 нужен собственный парсер. Длина адреса в его ответе может различаться в зависимости от типа адреса. Замена каждого чтения прокси фиксированным чтением восьми байт исправила бы один протокол, но сломала бы другой.

Похожие статьи