Archivi tag: iOS

2000px-Cisco_logo.svg

Uno sguardo a CDP

Ho recentemente ricercato soluzioni per reperire informazioni sulla topologia di una rete e tra le varie tecnologie che ho analizzato mi sono soffermato sulle possibilità offerte dal protocollo CDP di Cisco.

CDP è un protocollo proprietario Cisco che lavora a livello 2. Ogni dispositivo di rete conforme a questo protocollo (ossia quasi tutti i dispositivi Cisco) invia a tempo (di base 60 secondi) pacchetti conformi a questo protocollo ad un indirizzo di multicast definito. Tutti gli altri apparati nel medesimo dominio di broadcast raccolgono questi pacchetto/annuncio e memorizzano le informazioni ivi contenute in una memoria cache (cdp cache).

Le informazioni indicano versione di IOS, ruolo, porte, hostname, e altro ancora, costruendo per ciascun dispositivo una conoscenza su quale altro apparato ha nelle vicinanze (neighbours).

La cache è interrogabile via comandi IOS (show cdp…) oppure remotamente via SNMP.

Per costruire una topologia della rete (che vada anche oltre l’analisi di livello 2) occorre quindi interrogare un qualche oggetto (noto) capace di CDP e da questo ricorsivamente tutti gli oggetti confinanti rilevabili (non noti a priori). In questo modo una volta rilevato un router potremo anche superare la barriera del rilevamento a livello 2 (tipico di un nmap, ad esempio). [Cfr Rif. 1 pag 4]

Per eseguire queste interrogazioni da remoto occorre disporre di un altro protocollo, lo SNMP.

In particolare per interrogare un dispositivo Cisco con CDP attivo occorre compilare i seguenti MIBs:

  1. SNMPv2-SMI
  2. SNMPv2-TC
  3. SNMPv2-CONF
  4. SNMPv2-MIB
  5. CISCO-SMI
  6. IANAifType-MIB
  7. IF-MIB
  8. CISCO-TC
  9. INET-ADDRESS-MIB
  10. SNMP-FRAMEWORK-MIB
  11. RMON-MIB
  12. CISCO-VTP-MIB
  13. RFC1155-SMI
  14. RFC-1212
  15. SNMPv2-TC-v1
  16. CISCO-CDP-MIB

Disponibili sul sito Cisco.

Nello specifico potremmo interrogare i seguenti oggetti:

  • cdpGlobal
  • cdpInterface
  • cdpCache

Pur potendo eseguire il tutto a mano (o in maniera batch) mediante il comando snmpwalk (o altro strumento di navigazione tra rami SNMP) ho cercato una soluzione integrabile in una interfaccia web.

Così ho cercato e trovato un framework in PHP molto interessante che offre una soluzione per interrogare ricorsivamente dispositivi CDP (oltre a tutta un’altra serie di capacità che meritano di essere approfondite).

Si tratta del Framework OpenSolutions/OSS_SNMP. E’ estremamente estensibile e è già compatibile con tecnologie Cisco, HP, Foundry/Brocade, Asterisk, Extreme, MRV.

Richiede PHP >5.4.

Senza entrare in dettagli vi fornisco un programma demo che utilizza tale framework (è necessario che tutti i dispositivi di rete rispondano in SNMPv2 per la stessa community) .

Fornendo a linea di comando (PHP-CLI) l’indirizzo di un dispositivi noto interrogabile (switch, router, ecc) e la community restituisce (ovvero stampa a console) un array con la topologia individuata.

#! /usr/bin/php

<?php
// This is an example script for OSS_SNMP Cisco CDP MIBs
if( count( $argv ) != 3 )
{
echo "Missing argument\n";
echo "USAGE: <hostname/IP Address> <community>\n";

exit( 1 );
}

require_once( dirname( __FILE__ ) . '/../OSS_SNMP/SNMP.php' );

$router = new \OSS_SNMP\SNMP( $argv[1], $argv[2] );

// Neighbours del route dato
print_r( $router->useCisco_CDP()->neighbours(true) );

// Interroga ricorsivamente i router periferici
print_r( $router->useCisco_CDP()->crawl() );

echo "\n\n";
exit( 0 );

 

Vedremo in un prossimo articolo come consentire ad un server Linux di diventare un oggetto di rete che si annuncia via CDP e sia pertanto visibile come oggetto confinante ai dispositivi Cisco.

 

Riferimenti

1 “Cisco Discovery Protocol Configuration Guide, Cisco IOS Release 15M&T” 2014 (cdp-15-mt-book.pdf)

core_midi_devel

Core MIDI e il tempo

Probabilmente Core Midi, parte dell’infrastruttura software Core Audio per OSX e iOS, è il software meno documentato da Apple e dal web in generale.
Volendo costruire un mini player MIDI integrato (all’interno di un programma più complesso) ho dovuto accontentarmi di un paio di esempi nella documentazione ADC (PlaySequence e PlaySoftMIDI) e i references dell’API, quasi tutta basata su strutture opache.

Costruire un modello funzionante non è stato molto difficile seguendo il prototipo PlaySenquence, apportando anche qualche modifica (ad esempio rimuovendo l’utilizzo delle classi C++ PublicUtility incluse nel progetto a favore di un paio di funzioni per la gestione del tempo di sistema).

Il problema è nato nel momento in cui ho voluto porre nell’interfaccia l’informazione del tempo corrente del brano in esecuzione con MusicPlayer (elemento dell’API).

Interrompiamo il racconto per una breve digressione sul tema temporizzazioni in ambito musicale/MIDI.

In musica il tempo si esprime tenendo presenti due parametri: la misura (ingl. bar) e la velocità.
Il tempo della misura (ingl. time signature) è un concetto più notazionale che pratico, ma che in sostanza caratterizza la collocazione reciproca delle note sull’asse tempo (e la loro durata) nel metro di riferimento adottato, ossia la misura): è un riferimento relativo capace di esprimere la struttura metrica del brano. La divisione viene indicata con una frazione che esprime quante note di quarto (ingl. quarter note; è l’unità di misura della divisione) compongono una misura (ingl. measure).

La velocità indica quanto veloci si susseguono le note. Nella notazione classica sono i riferimenti a quel “Piano”, “Pianissimo”, “Vivace”,con brio“, ecc. Con riferimento al metronomo e nella musica digitale si utilizza invece come parametro la velocità con cui si susseguono le note di quarto nel tempo, ossia quante note di quarto sono presenti in un minuto (beat per minute = BPM): è una misura assoluta e determina la velocità di esecuzione di un brano, qualsiasi metro si adotti.

Nel file MIDI (SMF = Standard Midi File) questi concetti sono espressi in vari modi. Il tempo della misura ad esempio è collocato con meta eventi nel flusso dei dati, così come la velocità di esecuzione, mentre posizione e durata delle note è espressa come differenziale tra due momenti espressi di una unità di misura estranea alla notazione tradizionale ma che funziona egregiamente come ponte tra questa e le necessità dell’informatica: lo step (o tick o, come lo definisce Core Midi, subbeat).
Lo step è una suddivisione della nota di quarto espressa a partire dal concetto di risoluzione, un concetto estraneo alla notazione classica, ma necessario a rendere la relazione tra il tempo assoluto (in milli o microsencondi, dipendentemente dal timer adottato dal software) e la nota di quarto; più propriamente uno step è la più piccola unità riconoscibile all’interno di una nota di quarto a partire da una risoluzione. Una risoluzione di 960 (quella adottata per esempio da Garage Band) indica che nella nota di quarto sono riconoscibili 960 frazioni di tempo (480 per la nota di ottavo, 240 per la nota di sedicesimo, ecc).
Quindi la risoluzione caratterizza la precisione con cui un software può esprimere le posizioni e le durate delle note (andando ben oltre la notazione tradizionale e consentendo così di esprimere quei discostamenti dalla divisione che caratterizza l’esecuzione umana di un brano). Vedi concetto di quantizzazione/umanizzazione.

E veniamo al problema in Core Midi.

Il discorso che segue fa riferimento all’API a partire da OSX 10.5 (e quindi anche iOS della stessa epoca).
L’API mette a disposizione (per la lettura di un SMF, ma anche per la generazione ex-novo) una struttura opaca MusicSequence che contiene una lista di strutture opache MusicTrack, più un accessorio di strutture e API di gestione (come il MusicEventIterator), il tutto a favore di un altro elemento opaco (MusicPlayer) capace di eseguire un brano espresso mediante un MusicSequence.
La funzione MusicSequenceFileLoad (MusicSequence References) costruisce una sequenza a partire da un SMF; nella MusicSequence le informazioni di cui abbiamo parlato in precedenza (e di cui certamente il file SMF ne ha una rappresentazione) vengono distribuite in un modo particolare e scarsamente documentato. L’unico modo di accedere alle informazioni dovrebbe essere attraverso l’API associata (strutture opache, ricordate?) ma tutto non è ben cordinato, specialmente nella documentazione.

La velocità di esecuzione del brano (ad esempio) è collocata in un dizionario leggibile mediante la funzione MusicSequenceGetInfoDictionary per la chiave “tempo”; le sue variazioni però devono essere rilevate (lo fa ovviamente anche MusicPlayer quando esegue il brano) nella “traccia tempo“, una traccia speciale in cui sono collocati (che lo siano stai nel file SMF o no) tutti i meta eventi che caratterizzazo il tempo.
La traccia tempo è ottenibile mediante la funzione MusicSequenceGetTempoTrack e iterabile mediante MusicEventIterator per leggerne e decodificarne ogni evento (se ad esempio il nostro software deve mostrare il contenuto di una MusicSequence invece di darla in pasto a MusicPlayer). Volendo usare MusicPlayer non saremo costretti a farlo.

Ma tornando al nostro problema di visualizzazione del tempo durante l’esecuzione con MusicPlayer, quello che dovremmo utilizzare è la funzione:

OSStatus MusicSequenceBeatsToBarBeatTime(
MusicSequence inSequence,
MusicTimeStamp inBeats,
UInt32 inSubbeatDivisor,
CABarBeatTime *outBarBeatTime
);

Questa dovrebbe essere intesa per mostrare il tempo (internamente espresso come numero float di note di quarto) nella canonica forma:

Misura:Battuta:Frammento di tempo

Per quanto riguarda il parametro inBeats, questo è facilmente ottenibile mediante MusicPlayerGetTime().
Per quanto riguarda la struttura CABarBeatTime del parametro di uscita outBarBeatTime non abbiamo documentazione; ma basta cercare in AudioToolbox/CoreAudioClock.h (erroneamente chiamato ancora nella documentazione AudioToolbox/CAClock.h ) per ottenere

struct CABarBeatTime {
SInt32 bar;
UInt16 beat;
UInt16 subbeat;
UInt16 subbeatDivisor;
UInt16 reserved;
};
typedef struct CABarBeatTime CABarBeatTime;

Ma per quanto riguarda il parametro inSubbeatDivisor non esiste documentazione.
Dopo varia sperimentazione intuisco che il parametro è in qualche modo associato al concetto di risoluzione. So che il file SMF pone questo valore nell’ultima parola a 16 bit del chunk THdr; ma non trovo nell’API di MusicSequence nulla che mi possa far accedere a questa informazione.
Solo una ricerca nei file AudioToolbox/CoreAudioClock.h mi conferma che il parametro subbeatDivisor è legato alla risoluzione: questo mi convince a cercare informazioni nell’API con una ricerca brutale del termine “risoluzione”.
Rinvengo una costante kSequenceTrackProperty_TimeResolution legata all’API di MusicTrack, e per la precizione alla funzione MusicTrackGetProperty e vengo a scoprire dalla documentazione che la sola traccia tempo detiene il dato di risoluzione del brano, esattamente quanto riportato in THrd.

Bingo ! Questo è il parametro necessario.

Vista la difficoltà nel reperire una informazione così vitale implemento una estensione all’API di MusicSequence (mi pare più appropriato) con il doppio fine di documentare e di semplificare l’utilizzo di questa informazione.

Ecco l’implementazione:

/**
* MusicSequenceGetResolution
*
* @author Andrea Tassotti
*
*/
OSStatus MusicSequenceGetResolution(MusicSequence inSequence, SInt16 *outResolution)
{
MusicTrack tempoTrack;

OSStatus status = MusicSequenceGetTempoTrack(inSequence, &tempoTrack);
if (status != noErr) return status;

UInt32 ioLength = sizeof(SInt16);
return MusicTrackGetProperty (
tempoTrack,
kSequenceTrackProperty_TimeResolution,
outResolution,
&ioLength
);
}

che sarà semplicemente utilizzabile nel seguente modo:

MusicTimeStamp time;
if ( MusicPlayerGetTime (player, &time) != noErr )
[NSException raise:@"getPrerollTime" format:@"Can't get time for player"];
if (time >= sequenceLength)
time = sequenceLength;

CABarBeatTime outBarBeatTime;
SInt16 resolution;

if ( MusicSequenceGetResolution(sequence, &resolution) != noErr )
resolution = 240;

if ( MusicSequenceBeatsToBarBeatTime(sequence, time, (UInt32)resolution, &outBarBeatTime) == noErr )
{
// Get the string representation of the current time (Garage Band style)
[timeTextField setStringValue: [NSString stringWithFormat:@"%04i.%2i.%2i.%03i",
outBarBeatTime.bar,
outBarBeatTime.beat,
outBarBeatTime.subbeat / (resolution/4) + 1, // 16-th
outBarBeatTime.subbeat ]];
}

Ovviamente in un caso reale (come nel mio software), la risoluzione verrà estratta una sola volta dalla traccia tempo.

Spero anche in questo caso di essere stato utile a qualcuno.

Il vice-versa, ovvero l’impostazione di una risoluzione per un file SMF si ottiene con la funzione che crea il file (questo è documentato):

OSStatus MusicSequenceFileCreate (
MusicSequence inSequence,
CFURLRef inFileRef,
MusicSequenceFileTypeID inFileType,
MusicSequenceFileFlags inFlags,
SInt inResolution);
);

Ma questa è una altra storia.

ios

iOS, Pages e WebDAV locale

Chi possiede un dispositivo mobile Apple sa che una delle politiche Apple prevede che per usare alcune funzionalità dai suoi dispositivi o applicativi occorre avere una connessione Internet attiva.

Questo impedisce l’uso offline di alcune funzioni, e questo ci può anche stare se queste sono legate strettamente alla Rete; non lo sono altrettanto se queste funzionalità (vedi l’accesso ad un servizio webDAV) possono essere rese disponibili da una rete locale wifi, isolata da internet anche e non solo per ragioni di sicurezza (come in alcune realtà imprenditoriali o istituzionali).

Continua a leggere