domenica 29 maggio 2011

JFK available on GitHub

I promised JFK would have been available publicly, but then I was too much busy to publish it. I did it today, so you can access JFK source tree via GitHub. Enjoy it!

Cosa si nasconde dietro la notazione dotted-quad di IPv4

E' capitato che qualche studente mi chiedesse come mai gli indirizzi IPv4 hanno "quello strano formato di quattro cifre separate da punti". Ebbene la risposta e' molto semplice, e puo' essere facilmente indagata con un po' di codice.
La notazione dotted-quad presenta quattro gruppi di cifre comprese fra 0 e 255. E' facile notare che per rappresentare 256 valori (da 0 a 255) occorre esattamente un byte, e che quattro byte corrispondono a 32 bit, valore ben "noto" in informatica. E in effetti la correlazione non e' casuale: la notazione dotted-quad nasconde ciascuno dei quattro byte che corrispondono ad un numero identificativo, l'indirizzo ip appunto.
E' possibile verificare quanto detto mediante un piccolo programma C che riporto di seguito nella versione per Linux (su BSD le librerie cambiano leggermente):

#include
#include
#include
#include
#include
#include
#include

int main( int argc, char** argv ){

  if( argc < 2 ){
    perror( "\nOccorre specificare nome host e numero di porta\n");
    exit( EXIT_FAILURE );
  }


  // estraggo parametri da linea di comando
  char *hostName  = argv[1];
  char *port      = argv[2];


 

 
  // creazione nuova struttura addressinfo
  struct addrinfo *aInfo = malloc( sizeof( struct addrinfo ) * 1);

  // mi serve un puntatore (non inizializzato) per la struttura risultante
  // dal lookup di un host
  struct addrinfo *lookupResults;

  // compilo i campi della struttura
  memset( aInfo, 0, sizeof( struct addrinfo ) );      // azzeramento struttura in memoria
  aInfo->ai_family     = AF_INET;                         // utilizzo IP
  aInfo->ai_socktype   = SOCK_STREAM;                     // utilizza TCP
  aInfo->ai_protocol   = 0;                               // protocollo specificato (tutti)
  aInfo->ai_canonname  = NULL;                            // nome simbolico host
  aInfo->ai_addr       = NULL;
  aInfo->ai_next       = NULL;


  printf("\nCreata struttura addressinfo per nome simbolico host %s e servizio %s\n",
     hostName, port );


  // eseguo lookup host
  int lookupResultCode = getaddrinfo( hostName,         // nodo
                                      argv[2],         // servizio
                                      aInfo,        // informazioni per lookup
                                      &lookupResults
                      );

  // se ho codice diverso da zero allora sono in errore
  if( lookupResultCode != 0 ){
    printf( "\nRisultato lookup [%d] = %s\n", lookupResultCode,
                                          gai_strerror(lookupResultCode) );
    exit( EXIT_FAILURE );
  }

  // se sono qui ho effettuato il lookup, devo iterare su tutti i possibili
  // risultati
  struct addrinfo *currentResult;
  for( currentResult = lookupResults; currentResult != NULL; currentResult = currentResult->ai_next ){
    printf( "\n*** Risultato di lookup ***\n" );
    printf( "\n\tNome canonico:\t%s", currentResult->ai_canonname );
    printf( "\n\tLunghezza indirizzo:\t%d", currentResult->ai_addrlen );
    // conversione a struttura socket address per internet
    struct sockaddr_in *socketAddress = currentResult->ai_addr;
    // stampa dei campi
    printf( "\n\tPorta:\t%d", socketAddress->sin_port );
    struct in_addr addressIP = socketAddress->sin_addr;
    char* buffer = malloc( 24 * sizeof(char) );
    inet_ntop( AF_INET, &addressIP, buffer, currentResult->ai_addrlen );
    printf( "\n\tIndirizzo grezzo:\t%d", addressIP.s_addr );
    printf( "\n\tIndirizzo tradotto:\t%s", buffer );

    int i = 0;
    int mask = 0xFF;
    for( i = 0; i < 4; i++ ){
      printf( "\n\tPezzo di indirizzo %d:\t%d",
          i, ( (addressIP.s_addr) >> (8*i) ) & mask);
    }


    printf( "\n-----\n" );
  }

}


Il programma, seppur abbastanza lungo per essere un esempio didattico, e' molto semplice: si vuole ricerca l'indirizzo IPv4 mediante lookup (del resolver) di un sito internet e del relativo servizio, per poi estrarre i singoli pezzi dell'indirizzo e suddividerli in byte. Per meglio comprendere si consideri la seguente invocazione:

$ ./net.exe www.kde.org 80

Creata struttura addressinfo per nome simbolico host www.kde.org e servizio 80

*** Risultato di lookup ***

        Nome canonico:  (null)
        Lunghezza indirizzo:    16
        Porta:  20480
        Indirizzo grezzo:       -94370770
        Indirizzo tradotto:     46.4.96.250
        Pezzo di indirizzo 0:   46
        Pezzo di indirizzo 1:   4
        Pezzo di indirizzo 2:   96
        Pezzo di indirizzo 3:   250
-----


La parte interessante e' l'indirizzo grezzo: il valore riportato rappresenta 32 bit di informazione che identificano l'host www.kde.org. Tale indirizzo non e' facilmente memorizzabile da un umano e comunque ha una forma "strana" (e' perfino negativo!). L'indirizzo tradotto, quello in notazione dotted-quad, viene ottenuto mediante la funzione inet_ntop(..) che converte il numero unico di 32 bit in una stringa dotted-quad. Sarebbe possibile estrarre i singoli pezzi da 1 byte con una serie di "and" logici, come fa in effetti il programma a livello didattico. Tuttavia tale metodo non e' consigliato poiche' non tiene conto dell'ordinamento dei byte che dipende dalla architettura di sistema (little-endian, big-endian).
Ad ogni modo, a livello didattico, il programma preleva ogni singolo byte dell'indirizzo IPv4 e lo mette in "and" logico con 0xFF (255) al fine di estrarre ogni singolo valore della notazione dotted-quad.
Ed ecco svelato il mistero dietro alla notazione dotted-quad.

Trovare e rinominare automaticamente gli MP3 senza tag

Una cosa estremamente seccante quando sia accende il proprio lettore MP3 e' quella di trovare dei file che non sono stati taggati correttamente con id3. Per evitare questo problema ho creato un piccolo script che tagga in automatico i file che non hanno tag id3.
Anzitutto, per trovare i file con tag e quelli senza, e' possibile eseguire il seguente comando:

find /media/FLUCAPOD/Music -iname '*.mp3' -type f -print0 | xargs -0 mp3info > ~/mp3List.txt 2>~/untaggedMp3.txt

Il comando effettua un find (ricerca di file) sul dispositivo montato sotto /media/FLUCAPOD; la ricerca prende tutti i file con estensione mp3 e li passa uno ad uno ad un programma mp3info che visualizza le informazioni del tag stesso. La lista dei file che passano il controllo di mp3info viene inserita in mp3List.txt, mentre i file privi di tag sono memorizzati nel file untaggedMp3.txt. Quindi con il comando di cui sopra e' possibile verificare se ci sono file privi di tag sul proprio dispositivo.
Per inserire automaticamente i tag si puo' usare il comando lltag, che ha la comoda opzione -G (guess) che tenta di indovinare i tag dal nome del file che processa. A tal fine ho creato un piccolo shell script wrapper per lltag:

#!/bin/bash
# mp3tag.sh

MP3_FILE=$1

mp3info "$MP3_FILE" > /dev/null 2>&1

if [ $? -ne 0 ]
then
    # file senza tag MP3
    echo -en "Auto-tag file [$MP3_FILE]..."
    lltag -G --yes "$MP3_FILE" > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo -en "OK!\n"
    else
        echo -en "FALLITO!\n"
    fi
fi



E quindi e' possibile eseguire la ricerca dei file mp3 passando i file trovati a questo wrapper che quindi in automatico verifica se sono presenti i tag e nel caso siano assenti effettua automaticamente il tagging:

find /media/FLUCAPOD/Music/ -iname "*.mp3" -exec mp3tag.sh {} \;

Giusto per dare un'ordine di grandezza dei tempi di esecuzione di questa procedura, in meno di 5 minuti il sistema ha processato 2913 file per circa 30 GB di file!

C-Shell: considerazioni sempre attuali?

Riporto i link a due articoli piuttosto vecchi, ma sicuramente interessanti sulle motivazioni per evitare la C-Shell come la peste.

http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/

http://www.grymoire.com/Unix/CshTop10.txt

Per quello che e' la mia (fortunatamente) scarsa esperienza in csh devo ammettere che molte delle problematiche di parsing presentate sono state risolte con il tempo, tuttavia capita spesso di avere errori di sintassi che fanno abortire lo script senza alcuna indicazione utile (un numero di riga ad esempio avrebbe aiutato molto).

Consideriamo invece le ragioni di essere dietro alla C-shell. La C-Shell e' una shell di vecchio stampo, si parla del tempo della Bourne Shell. Lo scopo di questa shell era quello di avere una sintassi simile alla sintassi del linguaggio C, mentre la predominante sh aveva una sintassi differente. Francamente non so come giudicare lo scopo della C-Shell, probabilmente perche' la mia formazione informatica mi ha comunque portato a conoscere, anche se solo a livello base, differenti linguaggi. Avere quindi un interprete di comandi "simile" ad un linguaggio che conosco, seppur possa sembrare utile, non mi entusiasma piu' di tanto. Cio' che conta e' l'espressivita' del linguaggio, non la sua sintassi. La sintassi si puo' anche copiare da un libro, l'importante e' che il linguaggio permetta di fare cose complesse con poche istruzioni. Cosa che la C-Shell non consente.
A questo punto quindi secondo me due opzioni dovevano essere valutate: (i) creare una shell con sintassi identica a quella del linguaggio C oppure (ii) creare una shell con sintassi differente ma stesso potere espressivo. La C-Shell si colloca a meta' fra le due opzioni, trovando un compromesso a tratti imbarazzanti, vista la goffagine dell'interprete csh.
Sicuramente un utilizzo maggiore della csh mi permettera' di collocarla adeguatamente nel panorama del software che scrivo e gestisco, ma per ora gli script piu' complessi continuano ad essere in sh/bash.

venerdì 27 maggio 2011

Xamarin, Nat e il passato che torna (?)

Miguel De Icaza, padre di Gnome e di Mono ha dato vita ad una nuova compagnia per promuovere lo sviluppo di Mono, con particolare riferimento ai dispositivi mobile. La nuova compagnia si chiama Xamarin  e il nome ricorda molto da vicino una precedente compagnia di Miguel: Ximian. Ebbene a quanto pare la somiglianza fra Xamarin e Ximian non e' solo nel nome: Miguel ha annunciato che Nat Friedman si unira' al team di Xamarin, e lo stesso Nat conferma sostenendo di essere addirittura un fondatore di Xamarin.
Il passato che ritorna?
Ad ogni modo in bocca al lupo alla nuova nata Xamarin, e speriamo che i risultati siano un po' migliori di quelli di Ximian, che a parte essere acquisita da Novell non ha poi prodotto quel tanto ambito desktop-super-integrato basato su Gnome!

GitHub & licensing

Today I signed up for GitHub , the most famous Git-based on-line repository. Being involved in a few Open Source projects I signed up for the free account, and I noted two statements in the license agreement (do you read the license agreements when you sign up for something, don't you?) that pleased me a lot:
D.2 All of your Content will be immediately deleted from the Service upon cancellation. This information can not be recovered once your account is cancelled.

In contrast with a lot of other online services (not only related to source code management), GitHub assuers me that once I click "delete" all the copies of my work will be deleted, very good!
F.1 We claim no intellectual property rights over the material you provide to the Service. Your profile and materials uploaded remain yours. However, by setting your pages to be viewed publicly, you agree to allow others to view your Content. By setting your repositories to be viewed publicly, you agree to allow others to view and fork your repositories.

So not only they will not keep "unauthorized" copies of my work, but they will not use my intellectual property as it was their property. In other words, GitHub will work as a "simple" network storage system for my code. That was what I was searching for.

SourceForge has similar terms, and in particular it does not claim any right on the intellectual property:
(from http://sourceforge.net/apps/trac/sitelegal/wiki/Terms_of_Use)
You retain your ownership rights to any and all of Your Content. Geeknet claims no ownership of any Content you submit to Geeknet. You or your third party licensor, as applicable, retain all intellectual property rights to any Content and you are responsible for protecting those rights, as appropriate.


but has a strange term for user deletion:
(from http://sourceforge.net/apps/trac/sourceforge/wiki/Removing a user account)
When an account is removed, the account name is not released back in to available name space. Under current policy, the deleted account name will not be reallocated to a new user.
Data created by the user on the site (such as forum posts, Tracker tickets, etc.) will remain intact, and will continue to be attributed to the account, even after the account has been removed.

It seems that a deleted account is simply denied to login again, but all the stuff remains there, even the account itself (otherwise there would be no reason to not push back the nickname on the available name space!).

I'm not saying that one system is better than the other, I'm just pointing your attention to a couple of things that seems interesting to me.

mercoledì 11 maggio 2011

Verso Qt 5

Ci sono grosse novita' relativamente alle librerie grafiche Qt (alla base, fra l'altro, del KDE): le Qt 5 saranno disponibili nel 2012 con una pre-release per testing a fine di quest'anno (http://labs.qt.nokia.com/2011/05/09/thoughts-about-qt-5/). Sono tante le novita', a mio avviso le piu' importanti saranno la forte spinta dietro a QML (linguaggio dichiarativo per la composizione delle UI) e la modularizzazione di QWidget, che permettera' una maggiore separazione fra codice UI e codice "di backend", consentendo quindi una maggiore integrazione fra Qt e linguaggi dinamici e di scripting.
Circa la scelta di usare accelerazione a livello di libreria sono invece un po' perplesso: si sta ormai superando la soglia del sistema operativo per accedere direttamente all'hardware grafico (errore commesso anche da HTML 5) e si rischia quindi di "iniettare" nel sistema codice potenzialmente rischioso e buggato.
Infine sono curioso circa la decisione di sviluppare Qt 5 in modo Open Source dal primo giorno, senza fare sviluppo "in casa" per poi rilasciare il prodotto finito come Open Source. Penso che questa scelta sia un'ottima spinta sia per lo sviluppo di Qt (che potra' cosi' vantare su un numero di sviluppatori virtualmente illimitato) che per gli sviluppatori, che potranno vedere con i propri occhi come si costruisce un sistema complesso e di cosi' alta qualita'.

Git: import CVS e il ramo che ancora deve nascere...

Git e' un ottimo sistema di controllo delle versioni, con una filosofia totalmente differente rispetto a CVS (si potrebbe anche affermare che Git nasce dall'odio per CVS...). Non c'e' quindi da stupirsi quando l'uso combinato di Git e CVS possa dare qualche grattacapo inaspettato. A me e' capitato un problema eseguendo un cvs import di un repository cvs "pulito":

fatal: refs/heads/origin: not a valid SHA1
fatal: master: not a valid SHA1
fatal: You are on a branch yet to be born


Ebbene dopo diversi tentativi ho trovato la soluzione: cancellare la directory $HOME/.cvsps e la directory .git e rieffettuare l'import del modulo.