LuaSocket FTP siempre agota el tiempo
passive-mode (3)
He tenido éxito con la instalación TCP de LuaSocket , pero estoy teniendo problemas con su módulo FTP. Siempre obtengo un tiempo de espera cuando trato de recuperar un archivo (pequeño). Puedo descargar el archivo muy bien utilizando Firefox o ftp en modo pasivo (en Ubuntu Dapper Linux).
Pensé que podría ser que necesite LuaSocket para usar FTP pasivo, pero luego descubrí que parece hacerlo por defecto. El archivo que estoy tratando de recuperar a través de FTP se puede acceder con FTP pasivo a través de otros programas en mi máquina, pero no a través del modo activo. Encontré algunas conversaciones sobre "piratear" el soporte del modo pasivo en LuaSocket, y esa discusión implica que las versiones posteriores dejaron de usar el modo pasivo, pero mi versión parece usar pasiva de todos modos (estoy usando 2.0.1; la más reciente es 2.0.2 y no parece tener ningún cambio relevante para mi caso de uso). Estoy un poco confundido acerca de cómo esa publicación se puede relacionar con mi situación, en parte porque es muy antigua y la fuente de LuaSocket ahora tiene poco parecido con el código en esa discusión).
He reducido mi código a esto:
local ftp = require "socket.ftp"
ftp.TIMEOUT = 10
print(ftp.get("ftp://ftp.us.dell.com/app/dpart.txt"))
Esto me da un tiempo de espera. Lo ejecuté bajo Linux en strace
(igual que ptrace
en Solaris). Aquí hay una transcripción abreviada:
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)
Hay otro sitio al que traté de conectarme, pero tiene una contraseña que no puedo publicar aquí, pero en ese caso los resultados fueron ligeramente diferentes ... Obtuve el rastro como el anterior pero con select()
teniendo éxito al final, luego esta:
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)
Compare esto con el rastro de mi programa "ftp" en modo pasivo (que funciona bien, aunque tenga en cuenta que no establece los sockets en no bloqueo como lo hace 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
Así que he probado LuaSocket contra estos dos sitios FTP diferentes con fallas diferentes pero similares. También lo probé desde otra máquina donde funciona el FTP activo, y no tuvo mejor suerte allí (presumiblemente porque LuaSocket siempre usa el modo pasivo, por lo que puedo ver al leer la fuente en socket/ftp.lua
).
Entonces, ¿alguien puede hacer que el LuaSocket de dos líneas en la parte superior funcione? Tenga en cuenta que en mi máquina, el FTP activo en el sitio de Dell no funciona (puedo conectar, pero en cuanto lo hago, se desconecta), así que si consigue que LuaSocket funcione, también tenga en cuenta si funciona el FTP activo del sitio de Dell desde otro programa. en tu máquina.
Hm. Parece que el problema es que LuaSocket usa "pasv" en minúsculas. Voy a tratar de encontrar una solución.
Hm. No, parece muy elegantemente soldado. Lo más fácil es probablemente copiar ese archivo en particular a su lugar equivalente en una jerarquía en una ruta anterior en LUA_PATH. Es decir, (por lo general) hacer una copia local del archivo, por ejemplo, path/to/your/project/socket/ftp.lua
.
Luego edite el archivo local:
- 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"))
Perversamente, una expedición de navelnaut usando getfenv, getmetatable, etc. no parecía valer la pena. Lo considero un problema serio con el diseño. (de LuaSocket)
Vale la pena señalar que RFC0959 usa comandos de mayúsculas. (Probablemente porque es de la era ASCII de 7 bits).
Este problema ahora está solucionado, con la pregunta y la primera respuesta de gran ayuda.
Luasocket es correcto para RFC 959 (el primer comentario aquí no es correcto sobre mayúsculas, ver RFC959 sección 5.2)
Al menos el servidor FTP de Microsoft no es compatible. Puede haber otros.
La solución es cambiar a PASV y es una solución alternativa para un servidor sensible a mayúsculas y minúsculas. Los detalles se encuentran en la lista de correos electrónicos de Lua, donde el archivo estará disponible para la web en unos pocos días.
(Editar la línea 59 de ftp.lua)
Tenga en cuenta que el servidor no sigue la especificación de FTP, que indica que los comandos no distinguen entre mayúsculas y minúsculas. Consulte RFC959, sección 5.3 "Los códigos de comando son cuatro o menos caracteres alfabéticos. Los caracteres alfabéticos superior e inferior deben tratarse de manera idéntica. Por lo tanto, cualquiera de los siguientes puede representar el comando de recuperación: RETR Retr retr ReTr rETr"