Прочитайте восемь байт, затем передайте туннель SOCKS4
Не глотайте приветствие назначения и не ждите несуществующих байт — разбирайте фиксированную границу ответа SOCKS4.
Запрос соединения SOCKS4 выполняется успешно, но приложение так и не видит начальное приветствие сервера. Одно из мест, куда стоит посмотреть, — первое чтение коннектора. Чтение шестнадцати байт слишком велико для восьмибайтного ответа SOCKS4.
| Поле ответа | Байты |
|---|---|
| Поле версии ответа | 1 |
| Код результата | 1 |
| Поле порта | 2 |
| Поле адреса | 4 |
Код результата 0x5a означает, что запрос разрешён. SOCKS4a меняет то, как запрос несёт имя хоста; он не превращает ответ в шестнадцать байт.
После ответа тот же поток TCP несёт протокол назначения. Почтовый сервер может отправить приветствие сразу. Поэтому чтение, забирающее шестнадцать доступных байт, может захватить полный ответ прокси и первые восемь байт этого приветствия. Если дальше пока ничего нет, слишком большое блокирующее чтение, наоборот, добавит лишнее ожидание.
Точная длина — обязанность парсера
Однократный запрос восьми байт не доказывает, что восемь байт пришли. Чтения из потока могут вернуть меньше. Соберите ровно длину ответа в пределах срока, остановитесь на закрытом или сбойном потоке, проверьте ответ и оставьте следующие байты приложению.
Если коннектор использует большее буферизованное чтение, сохраните всё после границы и передайте следующему потребителю. Выбрасывание излишка — та же потеря данных при другом размере чтения.
SOCKS5 нужен собственный парсер. Длина адреса в его ответе может различаться в зависимости от типа адреса. Замена каждого чтения прокси фиксированным чтением восьми байт исправила бы один протокол, но сломала бы другой.