miércoles, 29 de julio de 2009

LinkedIn no me funciona

Hace un tiempo que LinkedIn me hacía cosas raras, sólo me mostraba algunas páginas y se me quedaba pensando eternamente en el resto de páginas al intentar cargarlas. Agustín me dió la solución, el culpable es el router D-Link DSL-G624T de ya.com, tal y como cuentan aquí.

El problema es debido a una regla que tiene definida el router con el tamaño máximo de segmento (MSS) y la solución que dan es borrarla.

Se puede conectar al router por telnet (con el mismo usuario que se accede al interfaz web), para ver todas las reglas

iptables -L -n
....
Chain FORWARD (policy ACCEPT) target prot opt source destination
TCPMSS tcp -- 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 TCPMSS set 1360 ....
.....

Y se debe borrar la primera regla de tipo FORWARD (que define el MSS)

iptables -D FORWARD 1

Borrando esa regla me funcionaba LinkedIn, pero empezó a dar problemas con otras web, p.e. las imagenes de ebay, que no me las cargaba. Así que opté por leerme el infernal man de iptables a ver que se contaba....

Parece ser que lo habitual es definir el tamaño máximo de segmento con un tamaño 40 bytes menor a la unidad máxima de transferencia (MTU) en lugar de un tamaño fijo como está asignando el router, y eso se puede hacer automáticamente con una regla de iptables

iptables -R FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Donde el -R FORWARD 1 indica que reemplace la primera regla de tipo FORWARD (la incorrecta) por esta.

El único inconveniente es que la regla se borra cada vez que se reinicia el router y se debe asignar de nuevo

ACTUALIZACION Nov. 2009: En los comentarios Jose Luis Domingo propone otra solución más elegante, donde la modificación se aplica sólo a los paquetes de linkedIn, no a todos los paquetes. Gracias !!!


Para quien le interese un poco más, la parte del man donde lo cuenta...

tcpmss
This matches the TCP MSS (maximum segment size) field of the TCP header. You can only use this on TCP SYN or SYN/ACK packets, since the
MSS is only negotiated during the TCP handshake at connection startup time.

[!] --mss value[:value]
Match a given TCP MSS value or range.

TCPMSS
This target allows to alter the MSS value of TCP SYN packets, to control the maximum size for that connection (usually limiting it to your
outgoing interface’s MTU minus 40 for IPv4 or 60 for IPv6, respectively). Of course, it can only be used in conjunction with -p tcp. It
is only valid in the mangle table.
This target is used to overcome criminally braindead ISPs or servers which block "ICMP Fragmentation Needed" or "ICMPv6 Packet Too Big"
packets. The symptoms of this problem are that everything works fine from your Linux firewall/router, but machines behind it can never
exchange large packets:
1) Web browsers connect, then hang with no data received.
2) Small mail works fine, but large emails hang.
3) ssh works fine, but scp hangs after initial handshaking.
Workaround: activate this option and add a rule to your firewall configuration like:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu

--set-mss value
Explicitly set MSS option to specified value.

--clamp-mss-to-pmtu
Automatically clamp MSS value to (path_MTU - 40 for IPv4; -60 for IPv6).

These options are mutually exclusive.


martes, 7 de julio de 2009

Mechanize y content-type unknown

En una aplicación, tengo que integrar un informe que se no puede obtener a partir de un Web Service o REST ni nada parecido, así que la única forma es haciendo login en una web y navegando hasta bajarse un CSV. La integración se hace sin problemas con Mechanize, pero me he encontrado con que recibo estas cabeceras en la página del CSV:

Content-Type: unknown; charset=UTF-16LE
Content-Disposition: attachment; filename=report.csv


El problema está en la forma en que Mechanize parsea los datos recibidos. Decide que clase va a utilizar en función del Content Type. Para texto y html utiliza la clase WWW::Mechanize::Page, y si no sabe que utilizar, por defecto utiliza WWW::Mechanize::File.

En mi caso como no reconoce el Content-Type unknown, me devuelve un objeto de tipo WWW::Mechanize::File, a partir del cual no puedo parsear correctamente el CSV, ya que me devuelve un objeto binario sin ningún método fácil para procesarlo.

La primera solución que se me ocurrió a partir de la documentación de la clase PluggableParser es añadir unknown en la lista de Content-Type soportados por Page

agent.pluggable_parser['unknown'] = WWW::Mechanize::Page

Pero eso no vale, porque dentro de WWW::Mechanize::Page hay un chequeo adicional:

response['content-type'] =~ /^(text\/html)|(application\/xhtml\+xml)/i

Así que la solución para mi caso ha sido crearme una nueva clase que extiende a Page en la que su initialize es tan simple (y tan ñapa) como llamar a super y ignorar la excepción de content type inválido


require 'mechanize'
module WWW
class Mechanize
class Unknown < WWW::Mechanize::Page
def initialize(uri=nil, response=nil, body=nil, code=nil, mech=nil)
begin
super(uri, response, body, code)
rescue Mechanize::ContentTypeError
# Do nothing
end
end
end
end
end


Y hacer que el Content-Type unkown lo procese esta clase

agent.pluggable_parser['unknown'] = WWW::Mechanize::Unknown

Y con esto arreglado. Ya me devuelve un objeto que puedo parsear sin problema con FasterCSV.

viernes, 12 de junio de 2009

Epson DX8400 en Ubuntu

Como ya comenté en mi última entrada, lo que más guerra me dió al migrar a Ubuntu fue instalar la impresora multifunción Epson DX8400.

En la web de Epson te redirigen a Avasys para bajar los drivers. Seleccionando el modelo se pueden bajar los paquetes para la instalación. En mi caso pipslite_1.3.0-2_i386.deb para la impresora y iscan_2.19.2-1_i386.deb para el scanner

La impresora funciona perfectamente, pero lo del scanner es más divertido....

El paquete da un error de instalación ya que depende de libltdl.so.3 y en las últimas versiones de ubuntu se utiliza libltdl.so.7

Se puede arreglar simplemente con un link simbólico, como explican aquí:

sudo dpkg -i --ignore-depends=libltdl3 iscan_2.19.2-1_i386.deb
sudo ln -s /usr/lib/libltdl.so.7 /usr/lib/libltdl.so.3

El problema es que aunque con esto ya funciona el scanner, dejan de funcionar las actualizaciones automáticas de ubuntu, que dan un error de paquete roto. Y si le dices que lo arregle, desinstala iscan y te vuelves a quedar sin scanner.

Así que la solución es compilar el paquete para que utilice la librería correcta. Los fuentes se pueden bajar de la misma página donde está el paquete.

Mi primera opción fue el clásico make / configure / sudo make install.... pero como seguía sin reconocer el escáner, no tuve más remedio que hacer eso que sólo se hace en casos extremos.... leerme el README del paquete. En el README explica que se debe generar el paquete con

dpkg-buildpackage -rfakeroot

Y instalar el paquete generado

sudo dpkg -i iscan_2.19.2-1_i386.deb

Para poder compilar tuve que instalar unas cuantas librerias, que dependerán de lo que ya tengas instalado, en mi caso fueron:

sudo apt-get install gdk-imlib11-dev libsane-dev libgtk2.0-dev libgimp2.0-dev cdbs


Y esto si que funcionó y ya tengo el escáner funcionando como un campeón.

Por último unos cuantos comandos para chequear el escáner:

diego@diego-laptop:~$ lsusb |grep Epson
Bus 001 Device 022: ID 04b8:0839 Seiko Epson Corp. CX8300/CX8400/DX8400

diego@diego-laptop:~$ sane-find-scanner
found USB scanner (vendor=0x04b8, product=0x0839) at libusb:001:022

diego@diego-laptop:~$ scanimage -L
device `epkowa:usb:001:022' is a Epson Stylus CX8300/CX8400/DX8400 flatbed scanner

viernes, 29 de mayo de 2009

Adios Vista..... Hola ubuntu

Después de muchos años utilizando Windows como S.O. de trabajo, hasta hace un par de años por obligación y despues por la simplicidad de seguir utilizando lo mismo... llegó el momento de migrar a Ubuntu.

Inicialmente, la idea de este post antes de migrar era explicar los problemas que me he encontrara en la migración, que aplicaciones de Windows echaba en falta...

Pero la verdad es que después de una semana ubuntera no me he encontrado prácticamente con ningún problema, la práctica totalidad de las aplicaciones que uso en el día a día (Netbeans, Firefox, Thunderbird, Pidgin, Gimp, Thwirl, Filezilla, OpenOffice, ...) no es que funcionen igual, funcionan mejor y más rápido

Con respecto a la instalación, en Windows habría tardado 2 días en instalarlo todo, yendo de web en web para bajarme las diferentes aplicaciones (ruby, subversion, ...) y reiniciando n mil veces. En cambio en Ubuntu casi todo lo he podido instalar con Synaptic / apt-get y sin reiniciar ni una sóla vez.

Y además Spotify, que no tiene versión para linux, funciona perfectamente con wine :-)

Caso aparte el de los periféricos, la impresora multifuncion Epson DX-8400 no hubo manera de instalarla con los .deb que recomienda Epson y los tuve que compilar para que funcionaran, pero bueno, esto es tema para otro post...

lunes, 11 de mayo de 2009

Euruko 2009

Este fin de semana, junto a otros 250 desarrolladores he estado en la EuRuKo en Barcelona.

Hasta ahora mi relación con Ruby ha sido siempre en desarrollo web y asociado a Rails. Lo que más me ha gustado es ver como Ruby es mucho más que eso. Prácticamente ni se ha nombrado a Rails en toda la conferencia y hemos visto otras interesantes aplicaciones.

Con ruby se pueden hacer juegos con Gosu y Chipmunk como explico Javi en una de las conferencia más aplaudidas, se pueden procesar imágenes, hacer aplicaciones de telefonía con Adhearsion, desarrollos multiplataforma para móviles con Rhodes, hacer música de esa que yo nunca escucharía con Aarchaeopteryx, ....

Además tuvimos la keynote de Matz, una introducción a Cucumber por el padre de la criatura que me ha venido muy bien porque voy a empezar a usarlo en breve, y como broche final una impresionante y metálica introducción a D y a RuDy por Tomasz Stacheviwz , sin olvidarnos de las Lighting Talks.

En resumen, vuelvo con la sensación de que la conferencia ha valido la pena y con las pilas puestas para seguir aprendiendo y hacer las cosas un poco mejor día a día.