Un web server con Commodore-64 e cartuccia 64NIC+

Introduzione

In questo articolo vedremo come poter configurare un web server su un C64 non espanso, con il solo ausilio di una unità disco (reale o emulata con SD2IEC/Pi1541), di una cartuccia/interfaccia ethernet, e di un BASIC extender molto interessante.

L’interfaccia ethernet viene fornita dalla cartuccia 64NIC+, che mette a disposizione del C64 una connettività a 10Mbit/s emulando diversi standard: RR-NET, TFE, NET64. Ha anche altre caratteristiche interessanti, come ad esempio quella di poter ospitare una ROM/EPROM da caricare al boot ma di queste, per il momento, non ci occuperemo

Lo stack TCP/IP viene gestito e programmato appunto da un BASIC extender chiamato BASIC ON BAILS. Scritto da Jonno Downes nel 2010-11 e basato su netboot65, insieme a KIPPER BASIC forma una suite con la quale è possibile scrivere programmi per il networking, in semplice BASIC. A tale scopo vedremo che sono stati aggiunti diversi comandi. BASIC ON BAILS è dedicato allo sviluppo di applicazioni lato server, KIPPER BASIC è più dedicato allo sviluppo di applicazioni lato client.

Dato che il nostro intento è sviluppare un piccolo web server, utilizzeremo BASIC ON BAILS.

BASIC ON BAILS (BoB, da qui in avanti) viene distribuito liberamente e va caricato sul nostro C64 come un semplice programma PRG. È lungo 39 blocchi, che equivalgono all’incirca a 10kByte, e lascia dunque memoria sufficiente per realizzare qualcosa di carino, unico e… vostro.

Test di connettività e comandi

Appena caricato, BoB… dà errore! Ma non c’è da preoccuparsi.

Alla prima esecuzione esso è predisposto per cercare sull’unità disco corrente il programma chiamato INDEX.BAS. Non trovandolo darà errore, ma BoB sarà ancora in memoria e pronto per essere utilizzato.

Potremo usare questa feature quando saremo soddisfatti del sito web che avremo creato: potremo salvarlo con il nome INDEX.BAS in modo che venga caricato automaticamente all’avvio di BoB. Una bella comodità.

Focalizziamoci ora sui comandi aggiunti da BoB al classico BASIC V2 e vediamo dapprima quelli dedicati alla configurazione dei parametri di rete. La tabella è presa dal sito in bibliografia ed è stata da me tradotta:

Comando

Descrizione

Parametri

Esempio

IPCFG Mostra la configurazione IP corrente nessuno IPCFG
MAC Setta gli ultimi 3 byte del MAC Address. I primi tre bytes saranno sempre “00:80:10”.
Questo comando resetta inoltre l’intero stack IP, bisognerà pertanto assegnare un indirizzo IP (tramite MYIP o DHCP) dopo ogni esecuzione di questo comando.
stringa di 3 byte MAC “FOO” – Il MAC Address diventerà 00:80:10:46:4F:4F (nel PETSCII, $46 è una ‘F’ e $4F è una ‘O’)
DHCP Usa il DHCP per assegnare indirizzo IP, netmask, default gateway e DNS server nessuno DHCP
MYIP Assegna un nuovo indirizzo IP indirizzo IP (stringa) MYIP”10.1.1.2″
NETMASK Assegna una nuova maschera di rete netmask (stringa) NETMASK”255.255.255.0″
GATEWAY Assegna un nuovo default gateway (router a cui mandare il traffico non locale) indirizzo IP del gateway (stringa) GATEWAY”10.1.1.1″
DNS Specifica il DNS da usare per la risoluzione degli hostname indirizzo IP del DNS server (stringa) DNS”10.1.1.1″
PING Manda un certo numero di richieste ICMP ad un host. Per ogni pacchetto inviato viene visualizzato un “.” per ogni pacchetto ricevuto. Se si verifica un errore (incluso il timeout) viene visualizzato un “!”. hostname o indirizzo IP (stringa)

[opzionale] numero di richieste ping da mandare (1..255) – il default è 3

PING”JAMTRONIX.COM”

PING”10.1.1.1″,10

I nuovi comandi sono dunque molto intuitivi e permettono di impostare la connettività IP in poche righe.

Facciamo un primo test dando in sequenza i comandi DHCP, IPCFG e PING come in questa immagine:

Dato che la vostra configurazione di rete potrebbe differire dalla mia: fate il PING sull’indirizzo IP del default gateway che vedrete visualizzato dal comando IPCFG.

Se l’output del comando PING sarà composto da 3 puntini (…) significherà che esso è andato a buon fine, diversamente compariranno tre punti esclamativi (!!!). In questo momento non cercate di pingare il C64 da un altro host della vostra rete domestica.

In questa implementazione dello stack TCP/IP infatti, in assenza di servizi in ascolto su qualsivoglia porta TCP, il C64 non risponde alle richieste ARP (Address Resolution Protocol: associano indirizzo IP a MAC Address dell’interfaccia di rete) provenienti da altri host, facendo dunque fallire tutti i PING.

Se vedete i tre puntini siete già a metà dell’opera: la configurazione IP è fatta.

Vediamo ora quali altre istruzioni possiamo usare per la configurazione TCP e a livello applicativo:

HTTPD Inizia l’ascolto TCP su una determinata porta. Quando viene ricevuta una richiesta HTTP salta al numero di riga corrispondente, a meno che la richiesta non sia per un path già gestito dal comando HOOK. numero di porta (1..65535),

numero di linea (1..65535)

HTTPD80,100 – ascolterà sulla porta 80 ed effettuerà un salto alla linea 100 non appena verrà ricevuta una richiesta HTTP
HOOK Associa uno specifico path della URL ad uno specifico numero di linea. Effettua il salto alla linea indicata non appena riceve la richiesta al path specificato path (stringa) – deve iniziare con “/”,

numero di linea (1..65535)

HOOK”/HELLO”,200 – verrà eseguirà la linea 200 non appena verrà ricevuta la richiesta per “/HELLO”
TYPE cambia il campo HTTP Content Type nell’header HTTP dal default “text/html” a qualunque valore indicato. Attenzione alle minuscole/maiuscole, il client si aspetta ASCII e non PETSCII! Per funzionare, questo comando va dato PRIMA di inviare qualunque contenuto con I comandi “!” e XSEND mime type (stringa) TYPE”application/octet-stream”
STATUS cambia l’HTTP status line dal default “200 OK”. Attenzione ad includere il codice di 3 cifre (come stringa ASCII) seguito da uno spazio e poi da una descrizione dello stato (ASCII, non PETSCII). Per funzionare, questo comando va dato PRIMA di inviare qualunque contenuto con I comandi “!” e XSEND HTTP status line (stringa) STATUS”404 File Not Found”
! Trasmette la stringa indicata. Se non è stato ancora mandato ancora nessun header HTTP, esso verrà trasmesso. stringa da trasmettere !”<H1>HELLO WORLD</H1>”
XSEND Manda un file leggendolo dal drive di default. Se non esiste, verrà mandato un messaggio di errore al browser remoto. Se non è stato ancora mandato ancora nessun header HTTP, esso verrà trasmesso. filename (stringa) XSEND”FAVICON.ICO”
YIELD Termina l’elaborazione della richiesta e torna in attesa di un’altra richiesta HTTP nessuno YIELD

Anche qui troviamo istruzioni semplici e intuitive.

Hello, World!

Proviamo ora a digitare il seguente programma:

Le prime quattro righe servono per impostare la connettività IP in maniera statica, ossia senza l’uso di un DHCP server. Se vogliamo infatti che il nostro C64 sia accessibile anche dalla big internet dovremo prima o poi configurare delle regole di port forwarding / mapping. Per non essere costretti a rivederle ad ogni cambio di IP del C64 per mano del DHCP, è buona norma assegnare subito un indirizzo statico. Notate che gli indirizzamenti proposti funzionano sulla mia rete domestica: adattateli alla vostra, se necessario.

Le righe 50 e 60 sono il vero cuore pulsante del nostro programma: la riga 50 sostanzialmente recita: “per qualunque richiesta arrivi al path ‘/’ prosegui l’esecuzione del programma dalla riga 100 in avanti”. Quindi: se un browser richiede l’indirizzo http://192.168.1.64/ sarà proprio questa istruzione HOOK che si prenderà cura della richiesta, facendo saltare (proprio come un’istruzione GOTO) l’esecuzione alla linea 100.

Se desideriamo gestire più pagine esse andranno definite da altre istruzioni HOOK, come ad esempio HOOK”/INDEX2.HTML”,1000 o HOOK “/IMMAGINI”,2000

Alla fine di tutte le istruzioni HOOK desiderate bisogna avviare il servizio HTTPD. Nel nostro piccolo esempio la linea 60 si occupa proprio di questo. La sintassi HTTPD80,100 significa: “mettiti in ascolto sulla porta TCP numero 80 (ossia quella usata comunemente dai server web), e se arrivano richieste HTTP che non sono già state gestite dalle istruzioni HOOK precedenti, continua l’esecuzione dalla riga 100 in avanti”. Questa istruzione quindi comanda sia l’attivazione servizio vera e propria che una sorta di fallback per eventuali pagine non gestite in precedenza.

Proseguendo con l’analisi del programma, alla linea 100 troviamo il carattere ‘!’ seguito da una stringa tra doppi apici. In BoB il carattere ‘!’ è l’equivalente del ‘?’ (PRINT) in BASIC, con la differenza che la stringa verrà trasmessa sulla connessione logica http corrente. Notate che l’argomento dell’istruzione è sempre una stringa: se si desidera trasmettere dei valori numerici, ad esempio il contenuto di una variabile, sarà sempre necessario convertirlo in stringa con la nota istruzione STR$().

Al termine della trasmissione dei contenuti, effettuata alla riga 100, il programma DEVE rimettersi in ascolto sul socket TCP per eventuali altre richieste. Per fare ciò si usa l’istruzione YIELD. Tale istruzione chiude la fase di elaborazione e trasmissione del contenuto e forza il programma a tornare in ascolto. Immaginate per comodità che l’esecuzione a questo punto diventi un loop infinito tra tutte le istruzioni HOOK e la HTTPD. Tale loop durerà fino a che non arriverà una richiesta HTTP che verrà gestita da HOOK o HTTPD. Notate che nel programma non ci sono istruzioni di separazione END o GOTO tra la parte di HOOK/HTTPD e la parte di gestione delle pagine vere e proprie: è tutto automatico.

Eseguendo il programma noterete che quasi immediatamente compare sullo schermo la scritta LISTENING seguita dal socket (IP:PORTA) dove il web server è in ascolto. Se a questo punto, da un browser di un computer nella stessa rete digitate l’indirizzo IP del C64, dovrebbe comparire quanto segue:

Contestualmente, sullo schermo del C64, compariranno informazioni riguardanti le richieste provenienti dal browser remoto Esse sono identificabili dalle righe CONNECTION FROM IP:PORTA dove: IP è l’indirizzo IP del computer che sta richiedendo la pagina e PORTA è la source port scelta dal browser stesso per quella specifica transazione.

Se provate a ricaricare la pagina col tasto F5 o con il pulsante RELOAD del browser vedrete nuove righe CONNECTION FROM comparire sullo schermo.

Se tutto ha funzionato: COMPLIMENTI! Avete appena attivato un server web su un computer che mai se lo sarebbe sognato!

Nei link in bibliografia ci sono interessanti esempi, un po’ più complessi, che vi dimostreranno quanto è facile e didattico programmare siti con un minimo di interattività.

Programmabilità

Il fatto di poter gestire tutti i TAG HTML (non usati in questo semplice esempio) come semplici stringhe dà a BoB una grande flessibilità: è possibile gestire sfondi, colori, font, perfino form e tabelle. Gli unici vincoli sono la memoria disponibile e l’accesso al disco.

Giocando con le istruzioni XSEND e TYPE è possibile infatti inviare contenuti (immagini, per esempio) anche di “grandi” dimensioni. L’unico problema, in questo caso, è la velocità di trasferimento dati del drive 1541 che (nella versione non modificata) è inadeguata e rischia di scatenare dei timeout sul browser del richiedente. Per questa ragione suggerisco di limitare l’accesso al disco al minimo indispensabile, a meno che non sia stato adeguatamente velocizzato o virtualizzato. Per l’utilizzo delle variabili ‘speciali’ rifatevi alla documentazione in bibliografia.

Notate che per via delle note difformità tra ASCII e PETSCII, tutte le scritte delle vostre pagine web saranno maiuscole.

Precisazioni

Il web server di BoB è rigorosamente single task, quindi può servire soltanto una pagina per volta a chi l’ha richiesta per primo. Durante la preparazione e l’invio dei contenuti il server rimane irraggiungibile a terzi. Se state già pensando di fare il porting di Star Trek o Lunar Lander per Apple-1 o di o di qualche altra avventura testuale, per giocarci quando siete in metropolitana, tenete presente che nativamente il server è stateless.

Il fatto che quindi non abbia memoria delle transazioni precedenti potrebbe rivelarsi fastidioso. Pensate per esempio se, mentre meditate su quanta potenza dare ai retrorazzi prima di arrivare sulla superficie lunare, altro client si connettesse al vostro server e cliccasse su ‘nuovo gioco’…

Emulatori

Le ultime versioni di VICE, sia per Linux che per Windows, virtualizzano pienamente le varie cartucce ethernet, è sufficiente attivarle dal menu corrispondente. Se BoB rileva una cartuccia RR-NET il caricamento andrà a buon fine, diversamente verrà visualizzato un messaggio di errore. Sarà dunque possibile testare gli esempi di questo articolo, e quelli proposti dagli autori di Bob, senza scomodarsi troppo e senza spendere un centesimo.

È necessario assegnare al C64 un indirizzo IP diverso da quello della macchina ospitante, appartenente ovviamente alla stessa subnet.

Se VICE gira su una macchina Linux è necessario assicurarsi che l’IP forwarding sia abilitato. Verificatene l’attivazione, da utente root con:

sysctl net.ipv4.ip_forward

Se la risposta a tale comando è 0 sarà necessario abilitarlo, almeno temporaneamente, con:

echo 1 > /proc/sys/net/ipv4/ip_forward

Deciderete poi se abilitarlo in maniera definitiva con le necessarie operazioni.

Per le macchine Windows potrebbe essere necessario installare le librerie WinPCAP.

Visibilità da Internet

Se lo desiderate, nulla vi impedisce di rendere visibile il vostro C64 dalla big internet: basta effettuare un port mapping/forwarding di una porta a vostra scelta da internet verso indirizzo IP e porta che avete impostato all’interno del programma. Dovrete ovviamente disporre di un Internet Service Provider che vi fornisca un indirizzo IP pubblico, anche temporaneo. Potrete poi crearvi un nome di dominio (statico o dinamico) che vi aiuti a ricordare l’indirizzo: sta tutto alla vostra iniziativa. Niente di più e niente di meno, insomma, che quello che fareste per esporre su internet un qualunque altro server locale, perché di fatto il C64 è ora un server vero e proprio.

Sono confidente che in caso di un attacco informatico di tipo DDoS il C64 ne uscirebbe indenne, per via del fatto che gestisce una sola richiesta per volta; tuttavia non posso escludere che esistano degli exploit più o meno noti che permettano RCE (Remote Code Execution) tramite chiamate particolari al web server. Questo potrebbe non essere un vero problema nel caso di un vero C64 (chi mai inietterebbe ed eseguirebbe codice malevolo per il 6510?); potrebbe però diventarlo in caso di un C64 virtualizzato con VICE o simili. All’estremo potrebbe perfino portare all’esecuzione di codice arbitrario sulla macchina ospitante o all’esposizione di aree di memoria. Ignoro come sia gestita la faccenda in VICE, e non mi aspetto nulla di più di un crash del programma in caso di attacco, tuttavia è bene tenere sempre l’occhio il traffico da/per il C64, vero o virtualizzato che sia.

Conclusioni

A mio personale giudizio BASIC ON BAILS, e la sua controparte KIPPER BASIC, sono degli ottimi BASIC extender. Sono molto stabili, e sono sufficientemente leggeri e completi per fare cose interessanti e didattiche, al di là dell’aspetto puramente ludico/sperimentale. La possibilità di usare un emulatore consente di scrivere (e testare) codice in maniera più comoda, veloce ed efficiente rispetto a una programmazione sulla piattaforma originale.

Tuttavia, il fascino e la soddisfazione di vedere girare il proprio mini-sito su un C64 originale sono inarrivabili, provare per credere.

Per tale ragione consiglio vivamente quanti faranno qualche prova al volo con VICE, di provare anche con un C64 vero: non resterete delusi. A tal proposito… se avete in programma di lasciarlo acceso qualche giorno fate PRIMA un bel controllo dell’alimentatore; se volete lasciarlo acceso SEMPRE prevedete anche una adeguata ventilazione di tutto.

Questo è tutto! Enjoy!

Fonti

 

1 comment

  1. Pingback: Perché dovresti provare Linux (seconda parte del pippone) - TristeMietitore

Have your say