LuaSocket FTP всегда истекает

Мне удалось успешно использовать средство TCP LuaSocket, но у меня проблемы с его модулем FTP. Я всегда получаю тайм-аут при попытке получить (небольшой) файл. Я могу просто загрузить файл с помощью Firefox или ftp в пассивном режиме (в Ubuntu Dapper Linux).

Я подумал, может быть, мне нужен LuaSocket для использования пассивного FTP, но потом я обнаружил, что он делает это по умолчанию. Доступ к файлу, который я пытаюсь получить через FTP, можно получить с помощью пассивного FTP через другие программы на моем компьютере, но не через активный режим. Я нашел разговор о "взломе" пассивного режима поддержка в LuaSocket, и это обсуждение подразумевает, что более поздние версии перестали использовать пассивный режим, но моя версия, похоже, все равно использует пассивный режим (я использую 2.0.1; самая новая версия 2.0.2 и, похоже, не имеет никаких изменений, относящихся к моему использованию кейс). Я немного смущен тем, как этот пост может относиться к моей ситуации, отчасти потому, что он очень старый, а исходный код LuaSocket теперь мало похож на код в этом обсуждении).

Я сократил свой код до этого:

local ftp = require "socket.ftp"
ftp.TIMEOUT = 10
print(ftp.get("ftp://ftp.us.dell.com/app/dpart.txt"))

Это дает мне тайм-аут. Я запускал его под strace в Linux (так же, как ptrace в Solaris). Вот сокращенная стенограмма:

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl64(3, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
recv(3, "230-Welcome to the Dell FTP site."..., 8192, 0) = 971
send(3, "pasv\r\n", 6, 0)               = 6
recv(3, 0x8089a58, 8192, 0)             = -1 EAGAIN (Resource temporarily unavailable)
select(4, [3], NULL, NULL, {9, 999934}) = 0 (Timeout)

Есть еще один сайт, к которому я пытался подключиться, но у него есть пароль, который я не могу опубликовать здесь, но в этом случае результаты были немного другими... Я получил трассировку, как указано выше, но с успешным завершением select() в конце, затем это:

recv(3, "227 Entering Passive Mode (123,456,789,0,12,34)\r\n", 8192, 0) = 49
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK)  = 0
connect(4, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("123.456.789.0")}, 16) = -1 EINPROGRESS (Operation now in progress)
select(5, [4], [4], NULL, {9, 999694})  = 0 (Timeout)

Сравните это с трассировкой моей программы «ftp» в пассивном режиме (которая работает нормально, хотя обратите внимание, что она не устанавливает неблокирующие сокеты, как это делает LuaSocket):

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 6
write(5, "PASV\r\n", 6)                 = 6
read(3, "227 Entering Passive Mode (123,456,789,0,12,34)\r\n", 1024) = 51
connect(6, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("123.456.789.0")}, 16) = 0

Итак, я попробовал LuaSocket на этих двух разных FTP-сайтах с разными, но похожими сбоями. Я также попробовал это с другой машины, где работает активный FTP, и там ему не повезло (предположительно, потому, что LuaSocket всегда использует пассивный режим, насколько я могу судить, прочитав источник в socket/ftp.lua).

Так может ли кто-нибудь здесь заставить работать двухстрочный LuaSocket сверху? Обратите внимание, что на моей машине активный FTP на сайт Dell не работает (я могу подключиться, но как только я это сделаю ls, он отключится), поэтому, если вы заставите LuaSocket работать, также обратите внимание, работает ли активный FTP на сайт Dell из другой программы. на вашей машине.


person John Zwinck    schedule 16.10.2008    source источник


Ответы (3)


Хм. Похоже, проблема в том, что LuaSocket использует «pasv» в нижнем регистре. Попробую найти обходной путь.


Хм. Нет, он выглядит довольно элегантно заваренным. Вероятно, проще всего скопировать этот конкретный файл в его эквивалентное место в иерархии по более раннему пути в LUA_PATH. То есть (обычно) сделать локальную копию файла, например. path/to/your/project/socket/ftp.lua.

Затем отредактируйте локальный файл:

-    self.try(self.tp:command("user", user or USER))
+    self.try(self.tp:command("USER", user or USER))
-        self.try(self.tp:command("pass", password or PASSWORD))
+        self.try(self.tp:command("PASS", password or PASSWORD))
-    self.try(self.tp:command("pasv"))
+    self.try(self.tp:command("PASV"))
-    self.try(self.tp:command("port", arg))
+    self.try(self.tp:command("PORT", arg))
-    local command = sendt.command or "stor"
+    local command = sendt.command or "STOR"
-    self.try(self.tp:command("cwd", dir))
+    self.try(self.tp:command("CWD", dir))
-    self.try(self.tp:command("type", type))
+    self.try(self.tp:command("TYPE", type))
-    self.try(self.tp:command("quit"))
+    self.try(self.tp:command("QUIT"))

Как ни странно, экспедиция navelnaut с использованием getfenv, getmetatable и т. д., похоже, того не стоила. Я считаю это серьезной проблемой с дизайном. (из LuaSocket)

Стоит отметить, что в RFC0959 используются команды, написанные заглавными буквами. (Возможно, потому что это из 7-битной эпохи ASCII.)

person Anders Eurenius    schedule 18.10.2008
comment
Это полностью работает. В дополнение к вашему списку, я также изменил retr на RETR, но это все. Отличная работа. - person John Zwinck; 20.10.2008
comment
Я также отправил это сопровождающему LuaSocket. Надеюсь в следующей версии исправят. - person John Zwinck; 20.10.2008

Обратите внимание, что сервер не соответствует спецификации FTP, в которой говорится, что команды нечувствительны к регистру. См. RFC959, раздел 5.3 «Коды команд состоят из четырех или менее буквенных символов. Алфавитные символы верхнего и нижнего регистра должны обрабатываться одинаково. Таким образом, любая из следующих команд может представлять команду извлечения: RETR Retr retr ReTr rETr»

person Community    schedule 07.11.2008

Эта проблема теперь исправлена, и вопрос и первый ответ очень помогают.

Luasocket соответствует RFC 959 (первый комментарий здесь неверен в верхнем регистре, см. RFC959, раздел 5.2)

По крайней мере, Microsoft FTP-сервер не соответствует требованиям. Могут быть и другие.

Решение состоит в том, чтобы изменить pasv на PASV, и это обходной путь для сервера, чувствительного к регистру команд. Подробности в списке рассылки Lua, где архив будет доступен через несколько дней.

(отредактируйте строку 59 файла ftp.lua)

person Community    schedule 07.11.2008