Microsoft incorpora Bitcoin

Y es que aún cuando se veía venir a lo lejos, la noticia sorprende un poquito. No está demasiado claro nisiquiera para mi el por qué sorprende si con solo buscar Microsoft y Bitcoin en Google uno se encuentra con resultados como los de la imagen al pie de este post. 

imagePero sí, ahora Microsoft incorpora Bitcoin entre sus opciones de pago para los Estados Unidos quizás deba transcurrir algo de tiempo hasta que se extienda a otras regiones pero lo importante es que luego de Dell, PayPal,  la adopción por parte de Microsoft no debería sorprender y se posiciona entre los primeros gigantes del mundo en dar el gran paso.

Chau Google, chauuuuu

Mientras Google y Apple siguen intentando crear sus propios mecanismos de pago mediante sus iniciativas de monedas propietarias, Microsoft se decide y toma la delantera y creo que va a dejar en posición adelantada a toda la industria que ahora va a tener que repensar y rediseñar sus estrategias o quedarán muy retrasadas.

 

Movida temeraria?

En lo absoluto, el gigante de Redmon no ha tomado una decisión apresurada en lo absoluto, el equipo de Microsoft Research  ha venido investigando las criptomonedas en los últimos años y de hecho habían propuesto Permacoin (pdf), un fork de bitcoin con propósito de servir de almacenamiento de datos permanente.

 

Bill, el creyente

Pero no solo esto es de resaltar sino que Bill Gates hace un par de años que desde su fundación viene ayudando a distintas ONGs de todo el mundo, y en particular de Kenia donde el sistema MPESA tiene un éxito increible, mediante distintos sistemas de transferencia de valor por medios digitales y ha visto en primera persona las potencialidades de estas tecnologias y lo ha manifestado en reiteradas entrevistas que se pueden encontrar en la web. Una de esas entrevistas la pueden ver abajo en un video.

Bill es un creyente de Bitcoin no solo porque, más allá de su estatus de hombre de negocios utra exitoso, sigue siendo un hacker sino porque está en contacto con distintos sistemas emergentes de intercambio y él mismo ha vivenciado el impacto que éstos pueden tener. En este caso me refiero a las poblaciones más desfavorecidas del mundo en el que la inmensa mayoría de los habitantes no tienen acceso al sistema bancario y que aún teniéndolo no pueden costear los costos ni los tiempos que requieren las transacciones bancarias transnacionales.

 

Es solo por la XBox?

 

De la experiencia de Dell y Expedia podemos saber que Microsoft no va a experimentar un salto de ventas de XBoxes por incluir Bitcoin como medio de pago pero sí podemos estar seguros de algunas cosas:

  • Microsoft le da credibilidad a las monedas digitales y,
  • Google y Apple van a tener que reaccionar de alguna manera

Así que tal parece que no es para vender más ni para ahorrarse una comisión bancaria (ni ahorrársela a los clientes) sino que más bien parece una estrategia en varios sentidos. Por un lado Microsoft necesita volver a hacer punta y esta es “La” gran oportunidad, esto también le permite el uno de los primeros no solo en aceptar la moneda sino en darle aplicación real. Además, si viste mi video sobre el por qué Bitcoin es importante, entenderás que es sumamente ventajoso el incursionar en el desarrollo de software que manipulan monedas digitales (a esto le llamo la industria de la Alta Tecnología Financiera).

Así que Microsoft no es la empresa conservadora que todos muchas veces creimos que era…. Esto es gigante! Bien Microsoft, Bien!

BlockchainParser–Para descubrir la historia de Bitcoin

Introducción

Son muchos los sitios webs en donde podemos encontrar gráficas sobre distintos aspectos de bitcoin. blochain.info, por ejeimagemplo, nos provee de un rico conjunto de gráficas como las que podemos ver en la imagen de la derecha, entre muchas otras.

También existen blogs en donde se muestran análisis muy interesantes sobre tendencias, investigaciones, evidencias de ataques DDOS, introducción de contenido indeseado en la blockchain, potenciales nuevos usos del protocolo bitcoin y mucho más.

Por último, también podemos acceder a algunos papers sobre investigaciones respecto al anonimato (o falta de) de bitcoin, cómo seguir la traza del dinero, validar hipótesis como la del pago de sicarios mediante bitcoins que habría realizado el fundador de SkillRoad o, la competencia (o falta de) entre los distintos pooles de minning, entre muchas otras cosas.

 

Blockchain

Todo lo anterior es posible gracias a que todo lo que uno desee saber de bitcoin lo puede encontrar en la blockchain, allí está toda la historia desde el primer día. No obstante no existen, al menos hasta el momento en escribo estas lineas, herramientas que permitan realizar estos análisis con la flexibilidad necesaria. Es más, cada uno de estos blogs o papers comienzan explicando la creación de algun componente de software capaz de extraer la información deseada de la blockchain.

 

BlockchainParser

Mientras que cada uno crea la herramienta que necesita para cumplir con un objetivo particular, existe un componente en común que es no es necesario reescribir con cada nuevo proyecto y este es el Parser.

Por esta razón he publicado en Github un nuevo proyecto BlockchainParser en cual es capaz de recorrer la blockchain y retornar los bloques de información (bloques, transacciones, entradas y salidas) para su procesamiento posterior.

 

BlockchainToSql

Cómo ejemplo de eso de este componente he publicado también una aplicación (muy pequeña y sucia) que extrae toda la info de la blockchain y la introduce en una base de datos SQL para así poder analizar los datos con mayor flexibilidad. Así, mediante consultas SQL, es posible responder preguntas como las que siguen:  

  • ¿Cuales son las direcciones con más bitcoins? ¿Cual es el top 100 de direcciones que más reciben?
  • ¿Cómo es la tendencia en la dificultad de minado?
  • ¿Que poder de cómputo tenía Satoshi Nakamoto? ¿Cuantos bitcoins tiene? ¿Cuando gastó por última vez?
  • ¿Cuantos bitcoins tiene el FBI? ¿Cuando los vendió?
  • ¿Cuando se introdujeron las cadenas de virus en la blockchain? ¿cuanto costó hacerlo?
  • ¿Cómo se distribuyen los bitcoins entre sus tenedores?
  • ¿Cómo le va a Dell con BTC?
  • ¿Que porcentaje de Bitcoins se usan en la especulación y cuantos se mantienen sin gastarse?
  • ¿Qué porcentaje de Bitcoins se han perdido?

image

Otros usos

Existen muchos usos de este parser y entre ellos uno que me resulta muy interesante es la posibilidad de crear watchers para vigilar ciertas condiciones. Por ejemplo:

  • Vigilar las direcciones de Satoshi ya que un movimiento en cualquiera (o todas) estas direcciones puede significar un movimiento grande en el mercado.
  • Vigilar direcciones del grande jugadores como pooles, exchangers, FBI, Satoshi, BitPay.
  • Vigilar que la dificultad no baje de un umbral X. Esto podría significar que se ha perdido poder de cómputo en la red.
  • Vigilar número de micro transacciones. Esto puede significar un ataque a la red (y su consecuente impacto en la prensa, mercado, etc)
  • Vigilar el contenido de las nuevas direcciones y scripts. Esto puede significar un mal uso del protocolo o un uso novedoso.
  • Vigilar nuestras propias direcciones. Si se han gastado y no hemos sido nosotros significa que no somos tan inteligentes como creíamos.

Saludos

 

del.icio.us Tags: ,,

Open.NAT 2.0 Released

Acabo de liberar Open.NAT 2.0.6. Solo un par de ejemplos de uso:

 

Descubrir el router (Upnp o Pmp) y obtener su IP pública:

image

Descubrir router que soporte Upnp (por no más de 10 segundos) y crear un mapping TCP port: 1600 –> port: 1700

image

Este puede utilizarse ya sea del su código fuente como desde su paquete NuGet desde el administrador de paquetes:

Screenshot_1

Espero les sea de utilidad.

[CoffeeScript] Mi primer proyecto

Sobre la elección del lenguaje

En todo proyecto de desarrollo de software los arquitectos deben, tarde o temprano, tomar ciertas decisiones o enfrentarse a elecciones que pueden despertar polémicas; decisiones referentes a aspectos tales como la tecnología de persistencia de datos, los middlewares, los frameworks (léase aquí: librerías), tecnología de la capa de delivery,  granularidad de los servicios, estrategias de despliegue y un larguísimo listado de etcéteras.  Pero de entre todas las elecciones, la que quizás resulte más arriesgada es la elección del lenguaje de programación, y no me refiero a elecciones del tipo Java vs C#, de hecho difícilmente alguien pueda dudar de estos lenguajes. Tampoco resultaría extraña la utilización de PHP, ni de Python o Ruby, ni de Javascript con NodeJs aunque otros, como Scala o Lua, podrían requerir cierta justificación en algunos entornos.

Cuando digo que no generarían demasiado ruido me refiero a que son muy buenos lenguajes, bien conocidos, bien documentados, con una enorme comunidad y miles y miles de sistemas han sido desarrollados con ellos. Pero, ¿qué sucede si decidimos que el mejor lenguaje para el proyecto que le vamos a desarrollar a nuestro cliente es, por ejemplo, GorillaScript, Sugar o Fun? Es muy probable que la resistencia sea lo suficientemente fuerte, tanto desde dentro como  desde fuera del equipo, como para desistir y volver a PHP, Java o C#. Es más, en algunos casos extremos, como el del cliente para el que estamos desarrollando algunas aplicaciones actualmente, el temor a un nuevo lenguaje de programación ha sido históricamente tan grande que desarrollaron todo su sitio web en COBOL! (Pero eso será motivo de otro post)

 

Coffeescript

imageLa elección de CS no es algo que podamos considerar arriesgado ya que no es más que un dialecto de Javascritpt y compila a Javascript. No obstante, en un entorno corporativo, a diferencia de lo que puede suceder en un proyecto Open Source o en nuestro Pet Project, apostar por este lenguaje requiere de coraje. En parte porque si el proyecto fracasa (por las razones que sean) una de las primera preguntas a las que el arquitecto puede ser sometido es la siguiente: “Coffeescript?! Pero en qué diablos estabas pensando!? ”. Por otra parte, todos los que eventualmente se hubiesen opuesto, ya sea por temor al cambio, o simplemente por preferencia personal,  podrían sacar leña del árbol caído; a veces sucede.

Por cierto, una eventual justificación acerca de por qué encarar un nuevo desarrollo con este lenguaje se vuelve algo complicado puesto que, aún hasta el día de hoy, existe toda una controversia a su alrededor. Controversia en la que prominentes personalidades del mundo Javascript no terminan de ponerse de acuerdo. 

 

Coffeescript en el mundo real

Después de meditar por meses sobre los pros y contras, y sobre cómo podría solucionar algunos problemas que tuvimos en los desarrollos anteriores con javascript, me puse a buscar sobre experiencias en el mundo real y lo único que encontré fueron Trello y Dropbox, y obviamente un millar de librerías y aplicaciones open source, algunas muy buenas por cierto.

Eso me pareció suficiente puesto que, por cada aplicación mundialmente reconocida en internet, existen miles de otras aplicaciones bien hechas y brindando soluciones reales solamente que no son tan conocidas. Así que me decidí: “¡Vamos con Coffeescript!”

 

Pero ¿por qué?

En muchos proyectos web veo que se repite lo mismo una y otra vez: programadores para los que javascript no es su principal lenguaje y que no saben javascript o, en el peor de los casos, programadores que no saben que no saben javascript. Lo que sucede en estos casos es que mientras que el código del servidor es decente, el del cliente suele ser una colección de cientos o miles de snippets de jquery traídos desde StackOverflow.com y una librería javascript por cada problema que se les presenta. 

La solución es evidente: deben aprender javascript. ¿Pero cómo? ¿con una capacitación? ¿con un libro? ¿con guías de desarrollo? ¿con JLint? No. Definitivamente no. Incluso muchos patrones javascript requieren un entendimiento profundo de la naturaleza prototipal del lenguaje, los temas relacionados al scope de las variables en las funciones y closures requiere también atención extra, aprender las diferencias de uso de los operadores y las funciones de alto orden también suelen resultar dificultosas. Es simplemente demasiado.

CS soluciona estas y muchas (pero realmente muchas, muchas) cosa más, permite escribir un código más claro, conciso, con menos defectos, más mantenible, en menor tiempo (al menos una vez que ya nos hemos familiarizado con él), incorporando patrones comunes y bien conocidos de manera gratuita, generando código javascript que funciona en prácticamente todos los browsers, etc. La idea no es enumerar las bondades aquí.

Pero una imagen vale más que mil palabras, asi que, ¿alguien me explica como se pueden mantener 13.000 LoC como las que siguen? Advertencia: es código real.

image

Primer proyecto con Coffeescript

imageYa a punto de terminar con el desarrollo de la aplicación y viendo hacia atrás creo que la elección no sólo ha sido correcta sino que ha superado mis expectativas. Me explico, la aplicación es una SPA desarrollada con Knockoutjs, JQuery y CS; Knockoutjs posibilita (o fuerza) la utilización del patrón MVVM por lo que tenemos Views, ViewModels y Models por separado, obviamente los últimos 2 son 100% CS y al ser una SPA requiere de todos los conceptos que típicamente implementamos con otros lenguajes: OOP (sí, encapsulamiento, herencia y polimorfismo) y AOP, tracing, exception handling,  organización mediante namespaces y módulos, unit tests, además de una lógica de negocios harto compleja (con una interfaz de usuario que la acompaña).

Esto es algo distinto al desarrollo de una aplicación web tradicional con ASP.NET MVC en el que nuestro lenguaje es C# y en donde las vistas utilizan Razor, aquí nuestro lenguaje es javascript, y la lógica de la interfaz de usuario está en el cliente.

En este escenario no valen los snippets jquery ni que todo sea global (obviamente esto no vale en ningún desarrollo, pero es muy común), aquí necesitamos código Javascript de alta calidad, bien limpio, que incorpore las mejores prácticas utilizadas con este lenguaje, que sea orientado a objetos, que permita la inyección de dependencias, que sea sencillo de leer y modificar,  que sea modular.

Hay quienes podrían argumentar que todo esto se puede lograr igualmente con javascript ya que ninguna de las consideraciones anteriores tiene relación directa con CS. Eso es tecnológicamente cierto pero técnica y humanamente falso, me explico:

  • Tecnológicamente hablando, todo lo que se puede hacer con C# 5.0 ya se podía hacer con C# 4.0 y este, no introduce nada que no se pudiera hacer con C# 3.0 y así podemos llegar a la conclusión de que todo lo que se puede hacer con C# 5.0 ya podía hacerse con C# 1.0. Y aunque esto es cierto, no deja de resultar ridículo ya que no es lo mismo programar una operación sobre colecciones genéricas con Linq que programar bucles anidados para operar sobre colecciones de objects.

    O como decían los programadores de assembler: “Todo lo que se puede hacer con C, se puede lograr igualmente con ensamblador y por lo tanto, C no trae nada nuevo”. Este es el argumento que más resuena en la red y, aunque cierto, es absolutamente estúpido.

  • Técnica y humanamente hablando, no es lo mismo escribir y mantener 6.500 LoC que 10.000 LoC y esto se vuelve aún más evidente a medida que este número crece, es decir que no es lo mismo mantener 650.000 LoC que 1.000.000 LoC. Pero es incluso mucho más fácil mantener 65.000 LoC en un claro CS que 1.000.000 LoC de un ruidoso JS.

 

Pero mejor una imagen de código real de nuestro proyecto:

image

¿De cuál lado prefieres trabajar? ¿Cúal te gustaría mantener? Personalmente prefiero trabajar sobre las 19 líneas de código CS de la izquierda (muy claras y sencillas de modificar) que con las 74 líneas de JS de la derecha. Y si bien es cierto que yo no escribiría el código de la derecha del mismo modo que lo hace el compilador de CS, también es cierto que luego de algún esfuerzo y un buen refactoring, el código JS escrito a mano seguiría siendo todavía más ‘verboso’, ruidoso y duro de mantener que su equivalente CS del lado izquierdo. ¿Puede apreciarse ese ruido?

 

El equipo

Nuestro equipo se conforma de un desarrollador .NET, un Líder Técnico puede dedicar aproximadamente un 50% de su asignación a la programación de la aplicación y soporte (o incluso menos) y yo, que puedo dedicar entre un 10% y un 30% como mucho a soporte y programación. Testing y diseño web se requieren en momentos puntuales del ciclo de vida y, aunque no es así como trabajamos habitualmente, por restricciones de contrato y presupuesto no nos quedó otra alternativa.

Este equipo debía desarrollar la aplicación en 2 meses, y si no fuera porque el alcance fue ampliándose, esta semana estaríamos terminándolo. El punto aquí es que solo yo contaba con alguna experiencia previa con CS así que debíamos aprenderlo sobre la marcha y muy, pero muy rápido.     

 

Aprendiendo Coffeescript y algunos problemas

CS se aprendió sobre la marcha y aún estamos aprendiendo nuevas cosas todos los días porque el lenguaje tiene muchas más features y caminos que los que se describen brevemente en el sitio CoffeeScript.org. Pero cada vez que aprendemos algo nuevo inmediatamente cambiamos el código en aquellos lugares en donde hicimos algo “casero” y que CS resuelve de manera más conveniente.

Pero esto no fue feliz al comienzo. Al principio del proyecto hubo cierta resistencia por parte del TL y del desarrollador en cuanto al lenguaje,  y es lógico que eso sucediera puesto que es frustrante pasar 8hs tratando de realizar una tarea trivial y no lograrlo por no conocer el lenguaje. Y no sólo el lenguaje, KOJS era también nuevo para los dos, era realmente esperable. Encima, los desarrolladores se sienten presionados por mostrar resultado rápidamente y el no poder desempeñarse como quisieran por culpa de un cóctel de tecnologías nuevas genera un desagradable estrés.

Fue necesario acompañar el proceso de aprendizaje, asistirlos y aclararles lo evidente: nadie espera que aprendan todo esto en unas semanas. Y aunque eso no reduce la frustración, al menos queda claro donde están las responsabilidades y cuáles son las expectativas que se tiene ellos. Otro punto importante es que el desarrollador hacía lo correcto y luego lo hacía correctamente, eso también ayuda.

Por último, y no de menor importancia, es el hecho de que revisando y depurando el código generado, el equipo todo ha aprendido mucho más sobre javascript y algunos patrones comúnmente utilizados de lo que tal vez lo hubiera hecho programando directamente con javascript.

 

Lecciones aprendidas

Solo algunas:

  • Mantener los archivos .coffee pequeños hace más sencilla la tarea de depuración y correlacionar nuestro código con el javascript generado.
  • No hacer demasiadas cosas en una sola línea. Aún cuando CS posibilita (y avaces parece que alentara) la escritura de sentencias larguísimas, éstas se vuelven difíciles de leer y mantener, ni que hablar de comparar y mergear. Simplemente hay que pensar que el código debe ser legible no sólo para nosotros y listo.
  • Usar una herramienta que permita ver el JS generado mientras se escribe CS o al menos revisar el código generado con frecuencia. De esta manera se evitan varios dolores de cabeza puesto que a veces el código generado no es lo que esperábamos simplemente por un typo en nuestro código CS o un espacio/tab mal puesto. De paso se familiariza uno con el código ‘real’ que se ejecutará.
  • Configurar el editor (en nuestro caso Visual Studio) para que muestre los espacios en blanco y tabulaciones. Esto es importante porque muchas veces, sin quererlo, se mezclan espacios y tabs y uno debe saber donde es que están. Lo mismo sucede cuando el editor está configurado para hacer “word wrapping”, uno no sabe si es una línea nueva o si simplemente es la continuación de la línea anterior.
  • Los UTs no son opcionales. A medida que se escriben más y más líneas de código, el refactoring se vuelve mucho más riesgoso y uno termina rompiendo funcionalidades inesperadas que luego solo pueden detectarse en tiempo de ejecución.
  • Integrar los UTs con el entorno de desarrollo y correlos a cada rato, luego de una modificación en cualquier parte correrlos a todos. Luego de actualizar la copia local del repositorio correlos a todos, antes de subir algo correlos a todos. Escribir UTs en CS (o JS) es infinitamente más sencillo y rápido de hacer que en C# o Java así que, a menos que hagas TDD (no es nuestro caso), escribí tantos casos como puedas. No te vas a arrepentir.
  • Dedicar parte del día a leer algo sobre CS. Siempre vas a encontrar una manera mejor de hacer algo que hiciste.

Herramientas

Desarrollamos con Visual Studio así que utilizamos las siguientes extensiones para trabajar con CoffeeScript:

Mindscape Web Workbech

Esta extensión brinda el coloreado de la sintaxis CS y genera compila (genera el equivalente JS) cada vez que se guarda un archivo. Solo es cuestión de escribir algunas líneas y hacer Ctrl+S para ver cómo queda nuestro código.  Esta extensión es una buena alternativa y no hemos tenido problema alguno con ella.

image

Chutzpah Test Adapter for Test Explorer

Esta extensión permite que Visual Studio detecte la existencia de tests escritos en CS y permite correrlos desde Visual Studio de la manera habitual, haciendo fácil es escribir algo de código y correr los test, todo en el ambiente integrado de VS. Para esto, compila y corre nuestros tests con PhantomJS utilizando la librería que queramos (Jasmine, Mocha o QUnit). Chutzpah hace lo que promete, y lo hace muy bien, pero por desgracia cuando falla un test uno no puede simplemente poner un breakpoint para ver qué pasa, ni crea un code map para saber al menos en qué línea CS está fallando.  

Por esta razón yo hubiese preferido correrlos desde el browser pero bueno, aún así la herramienta vale la pena y nos está dando buenos resultados.

image

Aquí puede verse un test sencillo:

image

Y aquí puede verse la suite corrida:

image

 

Conclusión

  • CS es un lenguaje que llegó para quedarse porque los beneficios que trae consigo son reales y evidentes para todos los que se quitan las anteojeras ideológicas de javascript y lo evalúan desde una posición de neutralidad.
  • La incorporación de CS puede generar alguna frustración y penalidad de productividad en las primeras semanas si no se lo conoce de antemano.
  • CS puede ser aprendido, en un nivel suficiente para realizar un desarrollo, en un período de tiempo muy corto. Si se conoce bien javascript, el pasaje es sencillo; de lo contrario se van aprendiendo algunos conceptos y patrones javascript observando y depurando el código generado (pero primero JS y luego CS, lo opuesto no es válido).
  • Las extensiones para Visual Studio funcionan bien y permiten el desarrollo completo de una aplicación sin tener que cambiar de editor de texto para codificar ni cambiar de entorno para correr las pruebas unitarias.
  • CS es simplemente JS.
  • No pieso volver a escribir javascript nunca más en mi vida.

Documentacion XML a Markdown

Necesitaba documentar Open.NAT y colgarlo en la wiki del proyecto en GitHub pero no encontré nada, así que escribí un transformador XML—> Markdown que me sirviera. La verdad es que el código, si bien son solo 100 LoC, está bastante sucio pero si a alguien le sirve aquí se los dejo.

Y este es el resultado:

image

 

Con esto lo invoco:

  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         var xml = File.ReadAllText(args[0]);
  6.         var doc = XDocument.Parse(xml);
  7.         var md = doc.Root.ToMarkDown();
  8.         Console.WriteLine(md);
  9.     }
  10. }

Aquí está el código:

  1. static class XmlToMarkdown
  2. {
  3.     static IEnumerable<string> DocToMarkDown(XNode e)
  4.     {
  5.         var el = (XElement) e;
  6.         var members = el.Element(“members”).Elements(“member”);
  7.         return new[]
  8.             {
  9.                 el.Element(“assembly”).Element(“name”).Value,
  10.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“F:”)).ToMarkDown()),
  11.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“M:”)).ToMarkDown()),
  12.                 string.Join(“”, members.Where(x => x.Attribute(“name”).Value.StartsWith(“E:”)).ToMarkDown())
  13.             };
  14.     }
  15.  
  16.     internal static string ToMarkDown(this XNode e)
  17.     {
  18.         var templates = new Dictionary<string, string>
  19.             {
  20.                 {“doc”, “## {0} ##nn## Fieldsnn{1}nn## Methodsnn{2}nn## Eventsnn{3}nn”},
  21.                 {“field”, “### {0}nn{1}nn”},
  22.                 {“method”, “### {0}nn{1}nn”},
  23.                 {“event”, “### {0}nn{1}nn”},
  24.                 {“summary”, “{0}nn”},
  25.                 {“remarks”, “**remarks**nn{0}nn”},
  26.                 {“example”, “**example**nn{0}nn”},
  27.                 {“see”, “[{1}]({0})”},
  28.                 {“param”, “_{0}_: {1}” },
  29.                 {“exception”, “_{0}_: {1}nn” },
  30.                 {“returns”, “Returns: {0}nn”},
  31.                 {“none”, “”}
  32.             };
  33.         var d = new Func<string, XElement, string[]>((att, node) => new[]
  34.             {
  35.                 node.Attribute(att).Value,
  36.                 node.Nodes().ToMarkDown()
  37.             });
  38.         var methods = new Dictionary<string, Func<XElement, IEnumerable<string>>>
  39.             {
  40.                 {“doc”, DocToMarkDown},
  41.                 {“field”, x=> d(“name”, x)},
  42.                 {“method”,x=>d(“name”, x)},
  43.                 {“event”, x=>d(“name”, x)},
  44.                 {“summary”, x=> new[]{ x.Nodes().ToMarkDown() }},
  45.                 {“remarks”, x => new[]{x.Nodes().ToMarkDown()}},
  46.                 {“example”, x => new[]{x.Value.ToCodeBlock()}},
  47.                 {“see”, x=>d(“cref”,x)},
  48.                 {“param”, x => d(“name”, x) },
  49.                 {“exception”, x => d(“cref”, x) },
  50.                 {“returns”, x => new[]{x.Nodes().ToMarkDown()}},
  51.                 {“none”, x => new string[0]}
  52.             };
  53.  
  54.         string name;
  55.         if(e.NodeType== XmlNodeType.Element)
  56.         {
  57.             var el = (XElement) e;
  58.             name = el.Name.LocalName;
  59.             if (name == “member”)
  60.             {
  61.                 switch (el.Attribute(“name”).Value[0])
  62.                 {
  63.                     case ‘F’: name = “field”break;
  64.                     case ‘E’: name = “event”break;
  65.                     case ‘M’: name = “method”; break;
  66.                     default:  name = “none”;   break;
  67.                 }
  68.             }
  69.             var vals = methods[name](el).ToArray();
  70.             string str=“”;
  71.             switch (vals.Length)
  72.             {
  73.                 case 1: str= string.Format(templates[name], vals[0]);break;
  74.                 case 2: str= string.Format(templates[name], vals[0],vals[1]);break;
  75.                 case 3: str= string.Format(templates[name], vals[0],vals[1],vals[2]);break;
  76.                 case 4: str= string.Format(templates[name], vals[0], vals[1], vals[2], vals[3]);break;
  77.             }
  78.  
  79.             return str;
  80.         }
  81.  
  82.         if(e.NodeType==XmlNodeType.Text)
  83.             return Regex.Replace( ((XText)e).Value.Replace(‘n’, ‘ ‘), @”s+”, ” “);
  84.  
  85.         return “”;
  86.     }
  87.  
  88.     internal static string ToMarkDown(this IEnumerable<XNode> es)
  89.     {
  90.         return es.Aggregate(“”, (current, x) => current + x.ToMarkDown());
  91.     }
  92.  
  93.     static string ToCodeBlock(this string s)
  94.     {
  95.         var lines = s.Split(new char[] {‘n’}, StringSplitOptions.RemoveEmptyEntries);
  96.         var blank = lines[0].TakeWhile(x => x == ‘ ‘).Count() – 4;
  97.         return string.Join(“n”,lines.Select(x => new string(x.SkipWhile((y, i) => i < blank).ToArray())));
  98.     }
  99. }

Open.NAT–Bandwidth

64

Open.NAT heredó la implementación del mecanismo de discovery de Mono.Nat el cual buscaba por todos los servicios UPnp. El protocolo SSDP se basa en UDP el cual no es confiable, por lo que especifica que deben enviarse 3 packets UDP a la IP de broadcasting. Todas las computadoras en la LAN responden con 3 packets por cada una de las peticiones originales y por cada uno de los servicios disponibles por lo que en una LAN de pequeña, 5 computadoras por ejemplo, la que corren 5 servicios cada una, tenemos que Mono.Nat procesa 3*3*5*5 = 225 respuestas (datagramas).

Open.NAT por su parte solo consulta por aquellos servicios que pueden utilizarse para mapear puertos y solo envia 2 packets por lo que solo recibe respuestas de los routers y/o modems ADSL, y solo dos packets. Esto reduce notablemente el tráfico, que si bien en una LAN de 5 computadoras no es nada, en una de 100 no solo que sí es importante sino que el procesar todas esas respuestas consume muchos ciclos de CPU en el cliente.

Open.NAT solo necesita 1.3 segundos para completar el proceso de discovery en la LAN WIFI de mi casa, nada mal!

Esta es la salida por consola que podemos obtener al correr

Your IP: 181.110.171.21
Added mapping: 181.110.171.21:1700 -> 127.0.0.1:1600
+------+-------------------------------+--------------------------------+----------------------------------+
| PROT | PUBLIC (Reacheable)           | PRIVATE (Your computer)        | Descriptopn                      |
+------+----------------------+--------+-----------------------+--------+----------------------------------+
|      | IP Address           | Port   | IP Address            | Port   |                                  |
+------+----------------------+--------+-----------------------+--------+----------------------------------+
|  TCP | 181.110.171.21       |  21807 | 10.0.0.5              |  32400 | Plex Media Server                |
|  UDP | 181.110.171.21       |  25911 | 10.0.0.6              |  25911 | Skype UDP at 10.0.0.6:25911 (2693)|
|  TCP | 181.110.171.21       |  25911 | 10.0.0.6              |  25911 | Skype TCP at 10.0.0.6:25911 (2693)|
|  TCP | 181.110.171.21       |   1700 | 10.0.0.6              |   1600 | Open.Nat Testing                 |
+------+----------------------+--------+-----------------------+--------+----------------------------------+
[Removing TCP mapping] 181.110.171.21:1700 -> 127.0.0.1:1600
[Done]
[SUCCESS]: Test mapping effectively removed ;)
Press any kay to exit...

Open.NAT – Tracing

Una de las deudas que suelen tener las apliaciones es que no cuentan con la capacidad de saber qué es lo que está sucediendo internamente en tiempo de ejecución y esto hace que muchas veces sean una caja negra de comportamiento misterioso. Entonces, cuando se encuentra algún problema en producción, estamos bien pero bien jodidos.

Open.NAT incorpora la capacidad de vigilar su comportamiento interno para detectar posibles problemas simplemente utilizando las capacidades propias de tracing de .NET y como verán abajo, no está nada mal. ¡A seguir trabajando! 

image

Open.WinKeyboardHook 1.0.7 RELEASED

NuGet version

Acabo de liberar Open.WinKeyboardHook, una librería que permite engancharse a los eventos del teclado a bajo nivel y capturar las techas que se presionan a nivel global en todas las aplicaciones.

Existen muchas aplicaciones para esta librería, de hecho KeyPadawan utiliza este código. He escrito acerca de KeyPadawan  aquí.

Hace tiempo que desarrollé estó pero ahora lo he publicado en NuGet.org para que pueda consumirse desde el administrador de paquetes de Visual Studio. También puede descargarse el código fuente y compilarlo.

Screenshot_3

Espero les sea de utilidad.