jueves, 25 de febrero de 2016

Enfoque nativo en el desarrollo de aplicaciones móviles

Alternativamente podríamos titular esta entrada como hacer aplicaciones móviles multiplataforma y no morir en el intento.

Introducción


A la hora de hacer aplicaciones, el 90% de los dispositivos Android usan solo Java, y la mayoría de iOS usa Objective-C/Swift frente al uso de código C++ en ambas. Este sistema puede servir para muchos casos, pero implica en tener que codificar en 2 plataformas distintas. Por otro lado, si se separa el diseño en un SDK en C++ que contenga la lógica, y se usa un modelo vista – controlador, delegando el aspecto y la interacción a la parte móvil, conseguimos programar la lógica solo una vez, en C++, y tener separadas las interfaces en en cada plataforma. Se puede dar una vuelta de rosca más, y usar una web o framework que genere la misma interfaz para Android e iOS, aunque por el momento no hay una herramienta lo suficientemente potente o consolidada que ofrezca unos resultados de calidad.

Este enfoque no llama nada la atención si alguna vez has utilizado QT para hacer la interfaz de tu librería, en lugar de usar directamente ventanas de OpenGL o interfaces a tu S.O de escritorio. Incluso, puede usarse QT para hacer aplicaciones Android e iOS, pero aun no veo maduro el tema. Y por supuesto este diseño sirve para estos casos tradicionales en escritorio, hay muchas formas de afrontar esta problemática, pero voy a centrarme más en el caso concreto de los sistemas móviles.

Dropbox por ejemplo, utiliza este sistema porque creen que tiene muchas ventajas, puedes leer más sobre como hacen sus diseños en esta entrada.

Diseño


El diseño separa 2 grandes partes:
  • Por un lado, a nivel de aplicación, la interfaz o capa de presentación y el front-end, encargado de la comunicación al usuario con la librería encargada de la lógica.
  • Por otro lado, a nivel de motor, el back-end que procesa la entrada desde front-end para recibir y enviar todos los datos necesarios para el correcto funcionamiento a la capa de aplicación. 

Como se puede ver en la ilustración, la App Android y la App de iOS pueden diferir en lógica y elementos. Al ser 2 S.O distintos cada uno tiene sus peculiaridades, aunque ya he dicho antes que hay frameworks que pueden facilitar este desarrollo y podría ser delegada esta tarea en ellos.

Los front-end serán las capas encargadas de “traducir” el lenguaje de aplicación al nativo. En el caso de Android consistirá en una interfaz JNI que cambie funciones y valores de Java a C++ y viceversa, haciendo un uso correcto del back-end. En el caso de iOS la interfaz será entre Objective-C/Swift y C++. Aunque tengan diferente sintaxis o diferentes patrones de diseño, es deseable que sean calcados, para tener un conocimiento homogeneo del funcionamiento para todas las plataformas.

Añadir que en la parte de front-end, además de hacer llamadas a nativo, es deseable poder recibirlas. De esta forma se pueden hacer callbacks o llamadas asíncronas que notifiquen eventos en la capa de presentación. La forma más sencilla de hacer esto es proveer al inicio de la aplicación de un puntero a función, o callback que sea llamado de forma asíncrona y la aplicación pueda procesar esas peticiones usando threads o hilos coordinados.

Habitualmente uso la siguiente terminología:
  • Front-end de Android, InterfaceFromCJNI para llamadas de C++ a Java, e InterfaceToCJNI para las llamadas de Java a C++
  • Front-end de iOS, InterfaceFromONI para llamadas de C++ a Objective-C e InterfaceToCONI para el otro sentido. Usando un singleton y delegates tan comunes en iOS, se pueden unir en una sola clase.
  • Back-end, es conjunto, en C++ y lo suelo colocar como un Facade con llamadas estáticas por su versatilidad y flexibilidad si se rediseña el SDK.
  • Core o lógica serán todas las llamadas encargadas de la gestión lógica de la aplicación deseada. Algunas directamente llamadas desde la fachada, pero no tienen porque estar todas. De esta forma puedes hacer distintas fachadas en función de las configuraciones al exterior.

Diferencias


Pros:

  • Ahorras el programar la lógica en distintos lenguajes 2 veces.
  • Más fácil reciclar el código para usar también en escritorio y otros S.O
  • Separación lógica de diferentes comportamientos.
  • Con algo de código extra puedes adaptar un mismo core para aprovecharlo en distintos proyectos.
  • Permite la gestión externa de errores mediante logs y variables.

Contras:

  • Back-end vs core puede ser redundante.
  • Toda la lógica tiene que tener un puente hasta el core, muchas veces código repetitivo.
  • No es común el perfil de programador


Logs a bajo y alto nivel

 

Aunque hoy en día cualquier programa se puede debugear con muchas herramientas, gdb, eclipse, Visual Studio, Xcode... No hay que subestimar el uso de logs estratégicamente colocados en nuestro código. Por varias razones:
  • Dan información util.
  • Ayudan a aislar errores de forma rápida.
  • Son rápidos, no necesitas parar la ejecución.
  • En Release también funcionan.
Por ejemplo, podemos conseguir que los logs de warnings comenten que esperaban algún dato o estado y que se ha seguido ejecutando a pesar de ello. Se puede informar errores producidos en la ejecución, y se puede terminar o no con ella. O simplemente se puede informar de que se pasan por diversos Checkpoints o zonas, para saber que partes se han ejecutado y que otras partes no.

Los logs toman una especial importancia en plataformas móviles, porque son más dificiles de debuguear que los ejecutables normales, cuesta más tiempo hacerlo, y a veces es un verdadero quebradero de cabeza.

Por supuesto esta información no sustituye el uso de debuggers, pero es complementaria y muy útil si son colocados de forma estratégica. Además, si usas alguna macro, se pueden mostrar o dejar de mostrar según interese con el cambio de alguna definición. Una de mis headers favoritos para logs es este.


Peculiaridades de Android

 

Android es una de las plataformas móviles más extendida actualmente. Por desgracia, el ecosistema Android cambia constantemente y las herramientas de desarrollo se han ido adaptando a lo largo del tiempo. Además, hay una gran fragmentación de dispositivos, no es algo intrínsicamente malo, pero seo hace que haya que testear muchos dispositivos diferentes y el diseño de interfaz tiene ciertas peculiaridades. Por cierto, aunque lioso al principio, una vez comprendido es fácil de usar y potente, en el caso de iOS no es así, porque al principio contaban solo con 1 tipo de dispositivo, y el número ha ido creciendo a lo largo del tiempo, y los parches para adaptarse a todos ellos con el diseño de una interfaz son un desastre.

Cosas que debes saber antes de desarrollar en Android
  • Normalmente necesitas saber Java, usar C++ es complicado y engorroso al principio.
  • Para manejar una librería C++ necesitas usar JNI, es decir, traducir llamadas y variables de java a C++
  • En Java tienes que cargar la librería dinámica (*.so) de C++, Ejemplo 
  • Para realizar llamadas de C++ a Java puedes usar un puntero a función y recoger mensajes, como podeis ver aquí.
  • El verdadero reto es crear las llamadas desde C++ usando JNI
  • Una buena estrategia puede ser usar todo librerías estáticas, y crear una librería dinámica forzando al compilador que meta todo el código para evitar problemas con factorias. Para GNU en Cmake deberías TARGET_LINK_LIBRARIES(cmakeproject -Wl,--whole-archive yourcpplibrary -Wl,--no-whole-archive)
Para sabes más sobre JNI mira la documentación oficial, o busca tutoriales.


Peculiaridades de iOS

 
iOS es otra de las plataformas más extendidas. Es más dificil publicar aplicaciones en la store que en Android, debido a sus multiples restricciones en los procesos de validación. Normalmente los dispositivos son más caros, y sus usuarios están más dispuestos a pagar. Hace unos años era más fácil hacer interfaces, porque no había variedad de tamaños, pero ultimamente han salido diversos modelos, y se han sacado de la manga los constrains y auto-layouts para lidiar con diversos dispositivos. Habiendo usado los de Android e iOS, me quedo sin duda con Android. El sistema de APPLE no está nada pulido, da muchos comportamientos imprevistos, y la teoría no se corresponde para nada con la práctica. En Android no es tan complicado.

Cosas que debes saber antes de desarrollar en iOS.
  • Objective-C es una variante de C/C++, su integración es sencilla y no necesitas un JNI.
  • El standard de ficheros de *.m, pero si lo renombras a *.mm aceptará código C.
  • Solo se puede linkar librerías estáticas, por temas de seguridad (según ellos)
  • El ejecutable final debe tener por tanto todas las librerias, y su configuración es totalmente manual.
  • Es recomensable usar variables user-defined en el proyecto, combinadas con $(SRCROOT) y paths relativos puede tener proyectos multiusuario sin tener que cambiar la configuración de forma manual entre ordenadores.
Con toda esta información espero que os podais hacer una idea de como hacer unos diseños eficientes. Para cualquier sugerencia o retoque, aportación de información y bibliografía, poneos en contacto conmigo.

viernes, 19 de febrero de 2016

Conexión SSH con vuestro NAS Synology

Introducción: 

Para realizar una conexión por SSH a vuestro NAS synology, hay una serie de aspectos que debereis tener en cuenta y que describo a continuación.

Como habilitar el servicio:

Para activar el servicio SSH solo teneis que ir a:
  • Control panel > Terminal & SNMP > Enable SSH at port 22
No te recomiendo usar telnet, ya que la conexión no está protegida como el caso de ssh.

Como utilizar servicio:

Para utilizar el servicio, teneis que conectaros obligatoriamente con el usuario admin. Este usuario tendrá la contraseña del usuario administrador del NAS. Aunque no te podrás conectar con este.

Comando
ssh admin@IPtoNAS
Ejemplo usando un DDNS habilitado
ssh admin@vgonisanz.synology.me
Alternativamente puedes usar un cliente como putty o fireSSH

¿Por que no cambiar el puerto 22 por defecto?

Muchas personas, están tentadas de cambiar el puerto por defecto para "despistar" a atacantes que llaman a ips al azar y tratan de loguearse con contraseñas por defecto. Yo lo intenté cuando el NAS me avisaba de la cantidad de IPS que bloquea que intentan entrar. ¿Es efectivo? En realidad no.

La razón es que aunque el puerto por defecto sea el 22, los atacantes probaran con varios puertos, no solo con 1. Así que aunque no todos, seguirán llegando. No se pueden abrir puertos por debajo del 1024. La razón es que estos están reservados solo a conexiones de administradores de sistemas.Es decir, usando el puerto 22, solo se podrá abrir el puerto con acceso root, si está en el puerto 9999, se podrá abrir sin serlo. En este caso, con un simple script que imite ssh escuchando el puerto 9999, se podría robar tus contraseñas.

Si quieres sabes más del tema te recomiendo consultar este post.

¿Cómo proteger para evitar ataques?

Por defecto, synology viene configurado para bloquear N intentos fallidos en un periodo de tiempo T. Lo encontraras en:
  •  Control Panel > Security > Auto-block
Además, puedes poner IPs que no se bloqueen, por si a veces olvidas la contraseña y no tienes acceso físico al NAS. Es efectiva, fácil de activar (de hecho viene por defecto), y dificilmente entrarán en el sistema con unos pocos intentos a menos que hayas puesto tu admin con un password del tipo "1234", "qwer", "password".... No deberías usar ninguna de este articulo. Puedes hacerlo de forma "casera" como recomiendo la fundación Mozilla, o puedes usar un gestor de contraseñas.
Menu de auto bloqueo

Una solución algo peor, de la que hablo en el punto anterior, es cambiar el puerto, por ejemplo, al 9999. Aunque disminuyen, porque no todos prueban varios puertos, el sistema persistirá.

Una solución más elegante, es el bloqueo de regiones. Normalmente no te vas a teletransportar, ni viajar a paises como China, o Zimbabwe. Puedes hacer reglas en el firewall de forma sencilla que permitan solo acceder de tu pais, o denegar de ciertos paises.

  • Control Panel > Security > Firewall > Create...
Ahora no se podrá acceder desde China, a menos que usen proxys
 Y bueno, la solución más compleja es utilizar Port Knocking, descrito en este tutorial. Básicamente se configuran las tablas de sistema para aceptar solo conexiones que sigan un patrón. Dista de ser un método trivial, pero si te animas a implementarlo aquí tienes un tutorial que lo explica paso a paso.

Espero que todo esto te sirva para manejar como un profesional tu NAS a distancia.

lunes, 15 de febrero de 2016

Ajustando las mirillas del CSGO

Introducción:

En este tutorial de juegos vamos a enseñaros a como personalizar a vuestro gusto las mirillas en el CSGO usando comandos de consola. Es importante tener configurada una mirilla con la que nos sintamos cómodos y nos ayude a jugar mejor. Existen varios parámetros ajustables, tamaño, grosor, estática, que varíe… ¡Comenzamos!

Creador de parámetros de mirillas ONLINE:

En esta web podrás ajustar los parámetros de tu mirilla de manera automática, y podemos ver el resultado en la pantalla. Tiene una imagen con distintos contrastes para que podamos valorar como se va a ver nuestra mirilla en zonas brillantes, oscuras, y encima de los distintos modelos de CT y T del CSGO. Es muy útil para que puedas buscar la que más se adapta a tus necesidades.
Una vez creada tu mirilla, basta con que copies el comando de la zona inferior a la derecha en la consola. Recuerda que para usar la consola tiene que activarla en las opciones, y pulsar la tecla º para mostrarla. Si no consigues verla, añade el parámetro -console a las opciones de lanzamiento del CSGO.

Ejemplos:
  • Para una mirilla únicamente un punto:
cl_crosshairsize “0”;cl_crosshairdot “1”;cl_crosshairthickness “0.7”
  • Mirilla minimalista (Tipo Half Life):
cl_crosshairalpha “209”;cl_crosshaircolor “5”;cl_crosshaircolor_b “125”;cl_crosshaircolor_r “124”;cl_crosshaircolor_g “255”;cl_crosshairdot “0”;cl_crosshairgap “-1”;cl_crosshairsize “1”;cl_crosshairstyle “4”;cl_crosshairusealpha “1”;cl_crosshairthickness “0.5”;cl_fixedcrosshairgap “-1”;cl_crosshair_outlinethickness “0”;cl_crosshair_drawoutline “0”;
  • Mirilla variable y grande:
cl_crosshairalpha “164”;cl_crosshaircolor “5”;cl_crosshaircolor_b “50”;cl_crosshaircolor_r “50”;cl_crosshaircolor_g “207”;cl_crosshairdot “1”;cl_crosshairgap “0”;cl_crosshairsize “4”;cl_crosshairstyle “3”;cl_crosshairusealpha “1”;cl_crosshairthickness “1”;cl_fixedcrosshairgap “0”;cl_crosshair_outlinethickness “0”;cl_crosshair_drawoutline “0”;
  • Mirilla alto contraste no dinámica:
cl_crosshairalpha “201”;cl_crosshaircolor “5”;cl_crosshaircolor_b “182”;cl_crosshaircolor_r “153”;cl_crosshaircolor_g “74”;cl_crosshairdot “0”;cl_crosshairgap “-2”;cl_crosshairsize “2”;cl_crosshairstyle “4”;cl_crosshairusealpha “1”;cl_crosshairthickness “0.5”;cl_fixedcrosshairgap “-2”;cl_crosshair_outlinethickness “0”;cl_crosshair_drawoutline “0”;
  • Versión dinámica:
cl_crosshairalpha “201”;cl_crosshaircolor “5”;cl_crosshaircolor_b “182”;cl_crosshaircolor_r “153”;cl_crosshaircolor_g “74”;cl_crosshairdot “1”;cl_crosshairgap “-2”;cl_crosshairsize “1”;cl_crosshairstyle “3”;cl_crosshairusealpha “1”;cl_crosshairthickness “1”;cl_fixedcrosshairgap “-2”;cl_crosshair_outlinethickness “0”;cl_crosshair_drawoutline “0”;

Y mi favorita:

cl_crosshairstyle "4";

cl_crosshairdot "0";

cl_crosshairgap "-2";

cl_crosshairsize "1.5";

cl_crosshairthickness "0.25";

cl_crosshairalpha "255";

cl_crosshairusealpha "1";

cl_crosshaircolor "5";

cl_crosshaircolor_r "255";

cl_crosshaircolor_g "255";

cl_crosshaircolor_b "255";

cl_crosshair_drawoutline "1";

cl_crosshair_outlinethickness "0.25"
Espero que les haya resultado útil este tutorial. Un saludo.

Licenciando tu código

Usar licencias en nuestro código nos ayuda en muchos aspectos. Impide que otro se apropie de tu trabajo indebidamente, y nos da crédito, de cara a buscar un trabajo o poder desarrollar un rol como diseñador/programador en el futuro. Por eso, es importante colocar en las cabeceras, que tipo de licencia rige el código fuente, para que los demás puedan utilizarlo y respetarlo al mismo tiempo (si es permisiva claro).

Hay muchos tipos de licencia, me inclino especialmente por las de código abierto, ya que respetan las 4 libertades de los usuarios definidas por Richard Stallman. Es más,la página de GNU ofrece un completo listado e información útil sobre licencias, clasificandolas compatibles, incompatibles con GPL, y licencias no libres. Si tienes dudas, mira sus recomendaciones.

Libertades del software libre
Tipos de licencia más comunes actualmente (2016):
A chart illustrating compatibility relationships between different free software licenses.  For details, see the FSF's license list page.
Evolución

 En la parte final de los enlaces, tienes un ejemplo de que lineas poner en los headers para asignar a tu código la licencia, por ejemplo, apache:

/**
* Copyright [2016] [vgoni]
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
**/

Que puedo hacer y que no cuando uso software libre:

En función de tus dependencias, podrás licenciar tu código de una u otra manera, como este suele ser un tema lioso, trato de resumirlo con un sencillo ejemplo. Supongamos que crear un proyecto A, que no sabes como licenciar, y tiene una dependencia B+ΔB con otra licencia, siendo ΔB los cambios que hayas realizado en la dependencia (pueden ser nulos).

  • Si B tiene una licencia GPL, entonces A y ΔB debe ser GPL obligatoriamente.
  • Si B tiene una licencia LGPL, entonces tu A puede ser cualquier otra, incluso software privativo, y ΔB debe ser liberado como LGPL.
  • Si B tiene una licencia MIT o Apache, entonces tu A y tu ΔB puede ser cualquier otra, incluso software privativo.

Espero que todas estas indicaciones te ayuden a elegir sabiamente la licencia que más se adecue a tu código. Todas tienen pros y contras, si quieres que algo se expanda si y solo si como software libre, derivados incluidos, GPL, si quieres lo contrario, MIT/Apache, intermedio, LGPL. Elige bien pequeño padawan.