JuanCri.com

RSS: RSS
Shared Items: RSS
Add to Google

viernes 27 de enero, 2012 a las 00:19

Perdón si el título es malo, pero quiero mostrarles una manera elegante de poder enrutar las conexiones de cualquier dispositivo para que pueda conectarse a Internet como si estuviera en otro lugar, ya sea a Internet o una VPN.

Desktop

Mi problema original era poder utilizar Netflix como si estuviera en Estados Unidos, ya que el contenido es distinto. En OSX la solución es bastante simple: basta con conectarse por SSH a un servidor en Estados Unidos abriendo un proxy SOCKS (parámetro -Dpuerto) y luego configurar el navegador para que utilice ese proxy.

Por ejemplo, supongamos que tenemos un servidor llamado servidor (¡qué original!). Podemos ejecutar la siguiente línea en el terminal:

ssh usuario@servidor -D1080

Este comando se conectará a servidor y abrirá un puerto en el ambiente local (1080) el cual funciona como proxy SOCKS. Luego, en Firefox u otro navegador, podemos configurar el proxy SOCKS localhost puerto 1080.

Esta solución me funcionó bastante bien hasta que quise utilizar el dispositivo Apple TV. En este caso, como su conexión era por WiFi, y no tiene opción de configurar una VPN, necesité encontrar una solución más rebuscada.

Dispositivos

En el caso de dispositivos como Apple TV o similares, la única opción es enrutar el tráfico transparentemente, es decir, que el dispositivo no se de cuenta de que se está desviando el tráfico. Esto podría ser simple si su router estuviera conectado a una VPN, ya que podría enrutar ciertas conexiones (o todas) a través de esta VPN, sin embargo, el escenario cambia al usar SSH.

Tenía dos desafíos:

  1. Conectar el dispositivo a Internet a través de un PC
  2. Enrutar el tráfico a través de la conexión SSH

1.- Conectar el dispositivo a Internet a través de un PC

Supongamos que tenemos este esquema original:

Para poder controlar el tráfico entre el dispositivo e Internet, podemos intervenir el router o agregar un nuevo eslabón en la cadena. Opté por lo segundo y el diagrama queda así:

Para esto, en mi caso, utilicé un cable ethernet entre el Dispositivo y el PC. Para la conexión entre el PC y el Router ISP, utilicé Wi-Fi. Este escenario es muy común. Para permitir que el PC sea capaz de enrutar el tráfico, se utiliza NAT (network address translation). En Linux, se utiliza iptables para esta tarea.

NAT funciona modificando cada paquete. Cuando un paquete de datos va desde el Dispositivo a Internet, se modifica la dirección de origen reemplazándola por la dirección del PC. Cuando el paquete llega al PC desde Internet, se cambia la dirección de destino para que apunte al Dispositivo y luego se reenvía al dispositivo. De esta forma, el Router ISP sólo sabe que está recibiendo y enviando paquetes desde y hacia el PC. Todo el trabajo de conversión se lo lloeva el PC, en este caso.

Supongamos que el PC tiene las siguientes interfaces de red:

  • eth0 hacia el Router ISP
  • eth1 hacia el Dispositivo

Para configurar NAT, debemos ejecutar los siguientes comandos (como root):

# Habilitar el reenvío de paquetes en el sistema
echo 1 > /proc/sys/net/ipv4/ip_forward
# Enmascarar el tráfico hacia Internet
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Permitir que los paquetes que vienen desde Internet y que pertenecen a una conexión ya establecida,
# puedan pasar hacia el dispositivo

iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Permitir el tráfico desde el Dispositivo hacia Internet
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

Una vez hecho esto, sólo basta configurar manualmente las interfaces tanto en el PC como en el dispositivo. También es posible habilitar DHCP en la interfaz eth1, lo que evitaría tener que configurar la dirección IP manualmente en el Dispositivo. Pueden Googlearlo :)
 
Un punto importante a  tener claro es que las direcciones de red en eth0 y eth1 deben ser distintas. Por ejemplo, si el router ISP nos entrega una dirección IP de la red 192.168.0.0/24 (la máscara 24 significa que la red es 192.168.0.X), la dirección en eth1 debe pertenecer a otra red (por ejemplo, 192.168.1.0/24).
 
En este punto, ya deberíamos poder utilizar el PC como puente para el Dispositivo, aunque todavía falta enrutar el tráfico hacia el servidor SSH.

2.- Enrutar el tráfico a través de la conexión SSH

Si bien, muchas veces he configurado un puente con NAT, el enrutamiento hacia un servidor SSH era lo novedoso para mí :) Para esto, la forma más simple que encontré es utilizando la conexión SOCKS que provee SSH; la misma que utilicé en el ambiente de escritorio, pero esta vez sin configurar el proxy en el Dispositivo, sino en el puente.
 
Para lograrlo, podemos crear una tercera interfaz de red en el PC, pero esta vez, esta interfaz es virtual y envía todo el tráfico hacia un servidor SOCKS. Este proceso es muy simple utilizando tun2socks, disponible aquí.
 
tun2socks se encarga de subir una interfaz virtual y enrutar todo el tráfico que recibe a través de un servidor SOCKS. Para poder utilizarlo, antes debemos tener nuestra conexión SSH abierta, de la misma forma que lo hice en el ambiente de escritorio:
 
ssh usuario@servidor -D1080
 
Ahora, podemos ejecutar tun2socks:
 
./badvpn-tun2socks --tundev tun0 \
        --netif-ipaddr 192.168.100.2 \
        --netif-netmask 255.255.255.0 \
        --socks-server-addr 127.0.0.1:1080
 
Los parámetros utilizados aquí son:
 
  • --netif-ipaddr 192.168.100.2: Configura la dirección IP del gateway virtual que tendremos en la interfaz. Es decir, esta no es la dirección que tendrá nuestro PC en esta interfaz virtual, sino el gateway o router [también virtual] que deberemos utilizar en esa interfaz.
  • --netif-netmask 255.255.255.0: La máscara de la interfaz. Generalmente 255.255.255.0 (24 bits) está bien.
  • --socks-server-addr 127.0.0.1:1080: Dirección y puerto donde está corriendo el servidor SOCKS. Ya que utilizamos -D1080 en el comando SSH, ése es el puerto que definimos aquí.

Una vez ejecutado este comando, ya se habrá creado una nueva Interfaz, sin embargo, aún tenemos que configurar la interfaz en el PC y las rutas para que el tráfico a ciertas -o todas- las direcciones vaya a través de esta interfaz virtual.

Para configurar la interfaz en el PC local, debemos ejecutar:

ifconfig tun0 192.168.100.1 netmask 255.255.255.0

Pueden notar que la dirección local en la interfaz virtual (192.168.100.1) está en la misma red que la dirección del router virtual (192.168.100.2). Esto es imprescindible.

Éste debería ser el estado actual:

En este paso debemos tener mucho cuidado. Ya que esta interfaz virtual depende de nuestra conexión SSH, debemos asegurarnos de que el tráfico hacia el servidor SSH siga saliendo directamente por el Router ISP. También debemos tener claro que SOCKS sólo soporta conexiones TCP (y no UDP, ICMP o cualquier otro tipo). Esto previene que usemos la configuración actual para enrutar las consultas al DNS, ya que el protocolo DNS utiliza principalmente UDP. A fin de cuentas, necesitamos mantener tanto el tráfico al servidor SSH como al DNS a través del router ISP. Para esto, ejecutamos los siguientes comandos:

# Agregamos el servidor SSH (en este ejemplo 1.2.3.4)
# hacia 192.168.0.1 suponiendo que es la dirección del Router ISP.
# Utilizamos la métrica 5 para que tenga prioridad sobre otras reglas
route add 1.2.3.4 gw 192.168.0.1 metric 5
# Agregamos el servidor DNS (en este caso, un servidor de Google)
route add 8.8.8.8 gw 192.168.0.1 metric 5

En este momento, ya podemos eliminar la ruta por defecto actual, que utiliza el Router ISP, y cambiarla por una ruta hacia nuestro router virtual en la interfaz virtual tun0:

route del default
route add default gw 192.168.100.2 metric 6
 
Este comando toma todo el tráfico (excepto hacia nuestro servidor SSH, hacia el DNS o hacia redes locales) y los envía a través del router virtual. Para comprobar que el tráfico esté saliendo por la interfaz virtual, podemos visitar http://www.whatismyip.com/. La dirección en pantalla debería ser la dirección del servidor SSH.
 
El último paso consiste en habilitar las reglas de iptables que permitan utilizar NAT, pero ahora hacia la interfaz virtual:
 
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
 
¡Ya está! Ya podemos utilizar el Dispositivo como si estuviéramos utilizando el servidor SSH :) Suficiente, me voy a ver una película. ¡Suerte!
 
Por favor, avísenme si hay dudas o errores :) @juancriolivares
lunes 9 de enero, 2012 a las 01:01

NOTA: Recomiendo leer antes la primera parte.

Estuve pensando bastante en esto e, inspirado en el bit de paridad de los RAID, hice lo mismo con operaciones XOR. Por ejemplo, sin variable auxiliar en varias expresiones:

a = a ^ b;
b = a ^ b;
a = a ^ b;

Y, ahora, sin variable auxiliar en una sola expresión:

a = (b ^= (a ^= b)) ^ a;

Una de las características interesantes de la operación XOR es que es conmutativa, lo que permite acortar la expresión.

Se reciben sugerencias :)

martes 3 de enero, 2012 a las 11:18

Éste es probablemente uno de los ejercicios más comunes en un curso de introducción a la programación. Tenemos dos variables y necesitamos intercambiar sus valores. Hay dos approaches que conocía:

1.- Variable auxiliar

var a = 1; // Primera variable
var b = 2; // Segunda variable
var c = 3; // Variable auxiliar
c = a;
a = b;
b = c;

2.- Sin variable auxiliar

var a = 1; // Primera variable
var b = 2; // Segunda variable
a = a + b;
b = a - b;
a = a - b;

Hoy estaba pensando en cómo hacer esta operación en una sola expresión y llegué a esto:

var a = 1; // Primera variable
var b = 2; // Segunda variable
a = ((b = (a = a + b) - b) - a) * -1;

¿Habrá alguna otra más simple?

ACTUALIZACIÓN: Hasta ahora, logré simplificarla de esta forma:

a = -((b = (a += b) - b) - a);

ACTUALIZACIÓN 2: Pueden leer la segunda parte aquí.

domingo 18 de diciembre, 2011 a las 23:27

Mi obsesión por el correcto uso del lenguaje -o, a lo menos, el conocimiento de cómo usarlo correctamente- me ha llevado a crear un nuevo blog donde estoy publicando algunos de los errores que escucho más a menudo. Los invito a suscribirse :)

http://vosnolodigai.blogspot.com

domingo 14 de agosto, 2011 a las 12:09

Para nadie es sorpresa que yo sea fan de .Net como plataforma. C#, su lenguaje principal, es una elegante evolución de Java y C++, mientras que su máquina virtual que incluye generics de verdad desde hace 6 años, value types, enums y un sin fin de otros azúcares, es muy atractiva. Nada de esto compensa la frustración que he sentido durante la última semana gracias a los requerimientos de un querido cliente. Acá una lista de ellas:

  • Visual studio depende fuertemente de IIS para lanzar sitios web, debiendo cambiar la configuración de la aplicación desarrollada para poder utilizar alternativas como un servidor liviano de desarrollo. Además, si llegamos a tener algún problema de configuración del debugging, Visual Studio no es capaz siquiera de entregar el detalle del error. En vez de esto, la web de MSDN publica una lista con 4 recetas distintas de cómo solucionar el DI'S problema.
  • A pesar de que ASP.NET MVC 3 es software libre (bajo licencia MS-PL), depende de componentes cerrados que no son parte del runtime estándar .Net, lo que en la práctica se traduce en una plataforma casi inutilizable en entornos de software libre (como Linux + Mono + MonoDevelop).
  • Bibliotecas como Unity y otros componentes liberados por el grupo de trabajo pattern and practices no tienen descarga directa de bibliotecas, sino que se amarran a la vieja y mala práctica de tener instaladores para componentes que deberían ser simples bibliotecas. Mi cariño por el stack Spring.Net/log4net/NUnit se reafirma.

¿Alguna otra queja?

lunes 20 de junio, 2011 a las 19:47

¿Te apasiona la programación? ¿Te gusta PHP? ¡Postula ahora! info@cxsoftware.com.

lunes 20 de junio, 2011 a las 19:13

Misión: Comprar Visual Studio

  • Voy al sitio de microsoft, intento comprar en línea. Al finalizar, la compra parece estar restringida a Estados Unidos.
  • Intento ir a microsoft.cl, pero en contacto aparecen números telefónicos de España.
  • Busco en la guía telefónica y llamo al número 800, pero éste parece ser sólo de activaciones

Y ahora, ¿quién podrá defenderme?

domingo 3 de abril, 2011 a las 16:20

Hoy leí este artículo y decidí hacer una versión en C#. Éste fue el resultado:

var valido = 
	("0123456789K" [11 - (rut.ToCharArray ().Take (rut.Length - 2).Reverse ()
	.Select ((a, b) => ((b % 6) + 2) * int.Parse (a.ToString ())).Sum () % 11)]) == rut [rut.Length - 1];

Tal vez no es tan eficiente, pero parece funcionar. Acepto comentarios :)

martes 7 de diciembre, 2010 a las 22:49

El webshow Hak5 ha iniciado un ciclo de programas sobre telefonía y telecomunicaciones. Hasta ahora hay dos episodios:

Como bonus track, pueden seguir a otros shows interesantes de Revision3 como HD Nation, Scam School o Scientific Tuesdays.

miércoles 20 de octubre, 2010 a las 00:50

Contraro a lo que muchos creen, JavaScript (o ECMAScript para ser más neutros), es un lenguaje muy poderoso y es el responsable de que tengamos aplicaciones web como GMail, Google Reader, Facebook, etc.

Como ya conté antes, JavaScript es uno de los pilares de la nueva arquitectura de aplicaciones web que estamos desarrollando en CxSoftware. Al utilizar JavaScript a diario, he encontrado algunos tips que creo pueden ser útiles para todo quien quiera ser un ninja JavaScript:

jQuery

Para comenzar, debes elegir un framework para desarrollar. Podrías no hacerlo, pero eso te traería muchos dolores de cabeza en el futuro. Recomiendo jQuery por su simplicidad, estabilidad y gran cantidad de plugins. Puedes ver más sobre jQuery en su sitio oficial. También recomeindo ver el podcast yayQuery.

linq.js

LINQ es originalmente una tecnología utilizada desde .NET 3.5 en adelante que permite utilizar programación funcional, pero además es capaz de traducir expresiones y utilizarlas en distintos contextos como SQL, XML y objetos. linq.js es una implementación de LINQ para objetos y permite realizar tareas comunes de manera simple, especialmente al tratar con listas y condiciones. Existen dos versiones: una standalone y otra que funciona como plugin de jQuery.

alert

¿Cuántas veces has utilizado alert("Hola"); en tus scripts? Bueno, window.alert es en realidad una variable que apunta a una función que muestra el message box en pantalla, pero puede ser reescrito. Puedes escribir, por ejemplo window.alert = function (texto) {}; para deshabilitar todas las llamadas a alert desde la página. Esto puede servir para otras cosas, como mostrar las notificaciones con algún sistema como ui notify.

jQueryControls

Ya hablé de esto antes y vuelvo a recomendárselo. jquerycontrols.com.

lunes 9 de agosto, 2010 a las 02:13

Como ya les conté antes, estamos en búsqueda de una arquitectura para desarrollo web que incluye ASP.NET MVC, JSON, jQuery y otros.

Dentro de ese proceso, se presenta el siguiente problema. Dede JavaScript se llama a servicios JSON (o AJAX). Una vez recibida la respuesta, se deben agregar elementos HTML a una lista. Un caso práctico sería, por ejemplo, un sistema que muestra una lista dinámica de personas, incluyendo datos personales de cada una.

La manera simple de hacerlo es recorriendo la lista y agregando elementos a una lista (elementos <li> dentro de una lista <ul>). El problema se produce cuando estos elementos son complejos e incluyen elementos como fotografía, tablas, enlaces, botones, etc.

Si la generación estuviera en el lado del servidor, utilizando el modelo clásico ASP.NET (Web forms), se crearían controles de usuario (user controls), los cuales se definen en HTML, se asocian los datos y, finalmente, se agregan a un conteedor. En el caso de JavaScript, utilizando jQuery, el código sería así:

$.each (lista, function (item, i)
{
    var divItem = $("<div>")
        .append ($("<table>")
            .append ($("<tr>")
                .append ("<td>Nombre:</td>")
                .append ($("<td>")
                    .text (item.nombre)))
            .append ($("<tr>")
                .append ("<td>Apellido:</td>")
                .append ($("<td>")
                    .text (item.apellido)))
            .append ($("<tr>")
                .append ("<td>Foto:</td>")
                .append ($("<td>")
                    .append ($("<img>")
                        .attr ("src", item.urlfoto)))));

    divLista.append (divItem);
});

Existen varios problemas con este código, incluyendo mantenibilidad, separación inexistente del código con el layout (HTML + JavaScript), etc. Para solucionar esto, decidimos crear una pequeña aplicación que transforma código HTML a objetos jQuery. Así, tenemos este código de origen:

<div id="principal">
    <table>
        <tr>
            <td>Nombre:</td>
            <td id="celdaNombre" />
        </tr>
        <tr>
            <td>Apellido:</td>
            <td id="celdaApellido" />
        </tr>
        <tr>
            <td>Foto:</td>
            <td><img id="foto" /></td>
        </tr>
    </table>
</div>

Utilizando el generador, esta estructura HTML es transformada en este código JavaScript:

var controlTest = function ()
{
	principal = $('<div>')
		.append ($('<table>')
			.append ($('<tr>')
				.append ($('<td>')
					.append ($('').text ('Nombre:')))
				.append (celdaNombre = $('<td>')))
			.append ($('<tr>')
				.append ($('<td>')
					.append ($('<span>').text ('Apellido:')))
				.append (celdaApellido = $('<td>')))
			.append ($('<tr>')
				.append ($('<td>')
					.append ($('<span>').text ('Foto:')))
				.append ($('<td>')
					.append (foto = $('<img>')))));
	
	this.principal = principal;
	this.celdaNombre = celdaNombre;
	this.celdaApellido = celdaApellido;
	this.foto = foto;
};

Finalmente, podemos utilizarlo de esta manera:

$.each (lista, function (item, i)
{
    var ct = new controlTest ();
    ct.celdaNombre.text (item.nombre);
    ct.celdaApellido.text (item.apellido);
    ct.foto.attr ('src', item.urlfoto);
    divLista.append (ct.principal);
}

Tenemos intenciones de distribuir este generador con una licencia libre. Tendremos noticias pronto.

lunes 26 de julio, 2010 a las 23:57

xmlstarlet se autodefine como un toolkit XML para línea de comando.

He usado esta herramienta desde hace varios años, generalmente para validar un xml, ya sea que esté bien formado como también contra un esquema (XSD) o DTD. Para lo primero, basta con:

xmlstarlet val test.xml

Hoy, sin embargo, estaba buscando una forma rápida de obtener un valor desde un archivo XML. Tomemos como ejemplo este archivo:


	
		
			textoelemento
		
	

Si queremos, por ejemplo, seleccionar el texto de elemento, podemos ejecutar:

xmlstarlet sel --text -t -v /root/hijo/elemento test.xml

Si queremos encontrar el valor del atributo, ejecutamos:

xmlstarlet sel --text -t -v /root/hijo/elemento/@atributo test.xml

Para seleccionar elementos se utiliza la sintaxis XPath. Más info aquí.

miércoles 12 de mayo, 2010 a las 06:22

Niños: NUNCA HAGAN ESTO:

Sitio web:

Código fuente:

lunes 3 de mayo, 2010 a las 20:28

Hoy lanzo oficialmente mi nuevo blog: magnetoscopio.net

En él, pretendo publicar todos mis posts referentes a TV, video e Internet. Tal vez verán algunos posts que ya han visto aquí, pero hay mucha información interesante que comenzaré a publicar. ¡Suscríbete! ¡Cuéntale a tus amigos! :)

martes 16 de marzo, 2010 a las 00:25

Me gusta el tema de las transmisiones de video online. No por nada, hemos estado más de un año trabajando para desarrollar IPTV Adventista (que, de paso, lanzó su versión 2.0 hace algunos días).

Desde hace un tiempo (semanas al parecer), CNN Chile está transmitiendo su señal online para clientes VTR (CNN Chile es un proyecto de CNN y VTR).

Si desean acceder directamente al stream, puede usar VLC, así:
vlc rtsp://200.83.4.17/broadcast/cnn

La transmisión funciona bien, pero podría ser mejor. Aquí va una lista de problemas y sugerencias:

  • Se desperdicia en transmitir el audio en estéreo
  • La transmisión utiliza 30 cuadros por segundos, pero el encoder parece emitir menos
  • La imagen tirita, evidenciando la utilización de sistemas analógicos con interferencia de estática
  • El bitrate es de 700Kbps aprox, pero la calidad no corresponde a ese uso de ancho de banda

ACTUALIZACION: CNN Chile cambió su sistema de streaming por RTMP (Flash) y sólo está disponible desde conexiones VTR.

ACTUALIZACIÓN 2: Sé que muchas personas ingresan a esta página buscando la transmisión de CNN Chile. Clientes VTR (y algunos otros, según he visto), pueden ingresar a http://www.tv-chile.com/cnnchile/.

martes 2 de marzo, 2010 a las 13:15

Se están reuniendo esfuerzos en el grupo Digitales Por Chile de profesionales y empresas relacionadas con tecnología. Dos personas de CxNet estaremos a partir de esta tarde colaborando.

domingo 28 de febrero, 2010 a las 20:26

El terremoto ya pasó, pero queda mucho por hacer. Yo y mi familia estamos muy bien gracias a Dios.

Aquí hay una lista de sitios que pueden visitar para colaborar:

miércoles 17 de febrero, 2010 a las 16:08

  • Lo que busco
  • Quiénes son mis contactos
  • Lo que escribo y leo (Gmail)
  • Dónde estoy (Latitude)
  • Lo que me gusta leer (Reader)
  • Adónde voy (Maps / Navigator)
  • Dónde y qué compro (Checkout)
  • A quién llamo (Android)
  • Los sitios web que visito (Chrome)
  • Mi agenda diaria (Calendar)
  • Los proyectos que tengo (Docs)
  • Mis tareas pendientes (Tasks)

Sólo eso. ¿Se les ocurren más?

miércoles 17 de febrero, 2010 a las 05:36

Hace algunas semanas, comenzamos un experimento para definir la arquitectura básica de las aplicaciones web que desarrollaremos en CxNet de aquí en adelante.

Aunque uno de los lenguajes que más utilizado es PHP (principalmente entre 2001 y 2004), no me siento cómo desarrollando "web". Comparado a la satisfacción de programar software sin interfaz de usuario, que sólo debe cumplir con los protocolos de los sistemas a los cuales se conecta, la web tiene un sin fin de complejidades.

Ésta es mi historia:

  • HTML: Aprendí gracias a Mosaic y algunas páginas de muestra que venían en el CD de mi primer módem. Luego, cuando por fin pude usarlo para conectarme a internet, seguí experimentando y creé algunas páginas, pero nada de lo que me sienta muy orgulloso.
  • Perl: Hace unos 11 años, alguien me pidió investigar una forma de listar información sobre empresas en un sitio web. Hice pruebas con Perl, el lenguaje más utilizado para desarrollar CGI en la época, y logré buenos resultados. Perl se convertiría en mi segundo lenguaje de programación (después de BASIC... aunque pasando por alto algunas pruebas con JavaScript).
  • PHP: Ya el 2001, cuando comencé a trabajar (semi) formalmente, PHP resonaba como la maravilla del desarrollo web. Me tomé algunos días y, utilizando unas mil hojas tamaño carta y varios cartuchos recargables de tinta, imprimí la documentación de la, entonces nueva, versión 4 de PHP. Éste sería uno de los lenguajes que utilizaría por más tiempo. Si bien no habían frameworks en la época, y todas las variables se importaban mágicamente (nada de $_POST o similares), hace algunos años comencé a buscar alternativas como PRADO Framework.
  • ASP.NET:
  • Durante la búsqueda de un lenguaje y plataforma más poderosos que me permitieran desarrollar para web y para escritorio, y luego de probar Java y Delphi, encontré el proyecto Mono (allá por la versión 0.16). De inmediato me sentí muy atraido por el lenguaje principal, C#. Luego, descubriría ASP.NET y su revolucionaria arquitectura de controles y estados. Ha sido mi principal plataforma de desarrollo web desde 2003 hasta 2009.
  • Java Struts: Este conocido motor MVC para Java me fue impuesto por el cruel mercado. Nunca me sentí cómodo con él y, después de menos de seis meses de práctica, renuncié a mi trabajo y decidí enfocarme en .NET/Mono, lo que incluía ASP.NET.

Si bien el modelo de ASP.NET, también ocupado en JSF, PRADO Framework y otros, es cómodo y ordenado, uno de los problemas que tiene es el uso de servicios Ajax o JSON y la interacción con JavaScript, nada de natural. Hay varios intentos de amalgamar estas tecnologías que parecen haber sido diseñadas para lo mismo pero que, sin embargo, tienen arquitecturas totalmente opuestas. Un intento es ASP.NET Ajax, el cual incluye un "update panel", en el cual se pueden insertar otros controles que utilizar AJAX por debajo. Otro intento, muy bueno, es Gaia Ajax Widgets. En este caso, sus desarrolladores crearon toda una gama de controles "ajaxosos", extendiendo la funcionalidad de los controles originales. Incluso llegué a comprar una licencia durante una oferta. El viewstate se seguía ocupando, pero no todo era color de rosas. Hay que saber muchos detalles de cómo funcionan estos sistemas, a bajo nivel, para poder resolver problemas que seguramente ocurrirán tarde o temprano, síntomas de una relación ilícita entre dos mundos que se niegan a convivir.

Como todo cambia, especialmente en este mundillo de la computación, siempre hay que replantearse las cosas. En el caso de las plataformas web, esto me ha ocurrido varias veces.

Hay dos criterios muy importantes que deben ser tomados en cuenta cuando se elige una plataforma: el usuario y el desarrollador. GMail es tal vez el gran ejemplo de AJAX. La primera aplicación masiva donde no había que esperar por un refresh o postback y donde el usuario es complacido con una interfaz intuitiva y simple. En el caso del desarrollador, hay un gran problema en el típico framework web mezclado con AJAX (o JSON, etc). Cierto contenido es rendereado en el servidor mientras otro contenido es generado dinámicamente al cargarse datos a través de un request AJAX.

Luego de la popularidad alcanzada por JQuery y la facilidad de uso de JSON en ASP.NET MVC, decidí probar esta combinación. En los próximos posts, les contaré cómo.

jueves 11 de febrero, 2010 a las 23:00

Cuando se llevan estructuras de árbol a una base de datos, es común utilizar un esquema como este:

CREATE TABLE nodos
(
    id int primary key,
    idpadre integer REFERENCES nodos (id),
    nombre varchar
);

Una vez hecho esto, podemos insertar algunos datos para crear la estructura:

INSERT INTO nodos (id, nombre) VALUES (1, 'Raíz');
INSERT INTO nodos (id, nombre, idpadre) VALUES (2, 'Nodo 1', 1);
INSERT INTO nodos (id, nombre, idpadre) VALUES (3, 'Nodo 2', 1);
INSERT INTO nodos (id, nombre, idpadre) VALUES (4, 'Nodo 3', 2);
INSERT INTO nodos (id, nombre, idpadre) VALUES (5, 'Nodo 4', 4);

Con estos datos, tendremos una estructura como esta:

Raíz (1)
 |-- Nodo 1 (2)
 |    |-- Nodo 3 (4)
 |         |-- Nodo 4 (5)
 |-- Nodo 2 (3)

Supongamos que queremos saber todos los nodos padres del "Nodo 4" (ID: 5). Para esto, PostgreSQL provee consultas recursivas. Acá un ejemplo de cómo podemos realizar la consulta para este nodo:

WITH RECURSIVE arbol (idpadre, idnodo) AS (
    SELECT
	n.idpadre,
	n.id
    FROM
	nodos n
    WHERE
	n.id = 5
  UNION ALL
    SELECT n2.idpadre, n2.id
    FROM arbol a INNER JOIN nodos n2
      ON (n2.id = a.idpadre)
  )
SELECT * FROM arbol

Esta simple consulta, retornará:

 idpadre | idnodo 
---------+--------
       4 |      5
       2 |      4
       1 |      2
         |      1

Espero que les sirva ;)

Creative Commons License
Blog JuanCri.com por Juan Cristóbal Olivares licenciado bajo la Creative Commons Attribution 2.0 Chile License.
Mono PostgreSQL

JuanCri.com