Configurare un HotSpot con Mikrotik

wifi-hotspotmikrotik

Era da molto tempo che avevo in mente di configurare un Hotspot gratuito. La scelta e’ ricaduta su Mikrotik RouterOS grazie alle innumerevoli features che mette a disposizione (QOS avanzato, Advertisement, Traffic Shaping…)

Lo scopo dell’HotSpot era quello di non chiedere le credenziali di accesso per ogni utente collegato, ma utilizzare sempre lo stesso account

 

1 Set-Up Interfacce

La prima cosa da fare e’ quello si dividere togliere dal bridge locale l’interfaccia dove avremo il nostro HotSpot (interfaccia Wi-Fi nel mio caso).

Bridge -> Ports -> disabilitiamo l’interfaccia wlan1

Disabilitazione WiFi dal Bridge
Disabilitazione WiFi dal Bridge

 

A questo punto avremo due segmenti di rete differenti:

  • bridge-local -> su cui ci sono le le interfacce ethernet
  • wifi1 -> L’interfaccia Wi-Fi su cui avremo l’HotSpot.

 

Ora andiamo a configurare gli indirizzi IP per ognuna delle interfacce

IP -> Addresses

Interfacce e loro IP
Interfacce e loro IP

 

Nel mio ho ho la seguente configurazione:

  • wlan1 -> subnet 10.5.10.1/24   (Interfaccia HotSpot)
  • ether1-gateway -> 192.168.1.55/24  (Interfaccia WAN/gateway)
  • bridge-local -> 192.168.88.1/24 (Interfacce ethernet)

 

2) Set-Ip HotSpot

Ora non ci resta altro che effettuare la configurazione dell’HotSpot.

Mikrotik RuoterOS ci mette a disposizione una procedura

IP -> Hotspot -> HotSpot setup

La prima cosa che ci chiederà sarà l’interfaccia su cui girerà l’HotSpot

Selezioniamo l'interfaccia dell'HotSpot
Selezioniamo l’interfaccia dell’HotSpot

IP Address di tale interfaccia (stesso IP impostato nella parte di Set-Up dell’interfaccia)

La Subnet dell'Hotspot
La Subnet dell’Hotspot

Il pool di indirizzi che avranno i client dell’HotSpot

Il pool di indirizzi dell'HotSpot
Il pool di indirizzi dell’HotSpot
Non importiamo certificati
Non importiamo certificati

 

Indirizzo del server SMPT
Indirizzo del server SMPT

 

Server DNS locale
Server DNS locale

 

Alla fine avremo il riepilogo dell’HotSpot appena creato

 

Riepilogo HotSpot
Riepilogo HotSpot

Ora selezioniamo Server Profiles

Profilo dell'HotSpot
Profilo dell’HotSpot

In questo caso ho impostato un limiti in Upload e Download ed una cartella dei files HTML che verranno utilizzati per il Login (vedremo in seguito)

 

Passiamo alla sezione User Profiles

User Profiles
User Profiles

Nel mio caso ho usato due profili utente:

  • BarBelvedereFull -> nessuna restrizione in termini di banda
  • BarBelvedereLimit -> con restrizioni in termini di Download e Upload

 

Passiamo alla sezione Users

Users
Users

Dove ho l’utente:

  • freeuser -> associato al profile Limit (limiti download/upload)
  • admin -> senza limiti

 

Il passo successivo à impostare la pagina index.html di Login all’hostpost pre-impostando l’user “freeuser”

Screen Shot 2015-04-19 at 16.29.06

 

Parser Python per pagine HTML

Python Parser HTML
Python Parser HTML in azione

Dopo (tanti) anni di studio ed un lavoro (precario) credo sia arrivata finalmente l’ora di iscrivermi all’albo degli Ingegneri, ma prima di farlo ho cercato di fare una piccola statistica su quanti ingegneri c’erano nella mia provincia (Potenza) e a quale tipo di specializzazione appartenessero.

Purtroppo lo strumento di ricerca del sito ( http://www.ordingpz.it/albo/Albolist.asp ) mette a disposizione dell’utente poche opzioni di ricerca, per tale motivo ho rispolverato la cara e vecchia libreria python Beautiful Soup per scrivere un piccolo script python il quale mi aiutasse ad effettuare il parsing di più pagine HTML e tirasse fuori i dati che mi interessavano.

Il sito in questione (http://www.ordingpz.it) ha una pagina web per ogni ingegnere iscritto all’albo. Tale pagina contiene i vari dettagli dell’ utente, compreso il campi che a me interessavano: “Settore” e “Specializzazione“.

Al seguente link è possibile avere un esempio reale del dettaglio dell’utente (l’ingegnere non è stato scelto a casa, ma è un mio amico con cui ha avuto il piacere di lavorare assieme).

http://www.ordingpz.it/albo/Alboview.asp?N__ISCR_=2714

Dalla sintassi dell’URL si capisce che ad ogni account è associato un ID (N__ISCR_) numerico univoco.

Per tale motivo il primo passo è stato quello di capire come estrapolare questi ID per poi andare a processare ogni singola pagina.

La prima parte dello script serve proprio a questo, a tirare fuori tutti gli ID dal sito.

Get ID

import urllib2
from bs4 import BeautifulSoup
import sys

f = open(‘IngPZAll.txt’, ‘w’)

url = “http://www.ordingpz.it/albo/Albolist.asp?pageno=1&t=Albo&RecPerPage=3000”
print url

try:
data = urllib2.urlopen(url).read()
except:
print url

soup = BeautifulSoup(data)

n = soup.findAll(“td”,{“width”:”100″})

#print n
numIscr = []

for i in n:
numIscr.append(i.div.string)

A questo punto la lista numIscr contiene tutti gli ID dell’albo degli Ingegneri di Potenza, adesso non ci resta che accedere alle singole pagine degli user e memorizzare tutte le informazioni che ci servono.

Il ciclo for può esterno non va altro che prendere tutti gli ID contenuti in numIscr , accedere alla pagina dell’utente ad esso associato e tramite BeautifulSoup effettuare il parsing della pagina HTML per tirare fuori le informazioni.

Parse HTML

[sourcecode language=”python”]
for i in range(len(numIscr)):
url = “http://www.ordingpz.it/albo/Alboview.asp?N__ISCR_=”+str(numIscr[i])
f.write(url+”\n”)
print “Parsing “+ str(i) + ” of ” + str(len(numIscr))
print url

try:
data = urllib2.urlopen(url).read()
except:
print url

soup = BeautifulSoup(data)
#print soup.prettify()
n = soup.findAll(“td” , “ewTableHeader”)

fields = []

for i in n:
fields.append(i.string.encode(‘ascii’,’ignore’))

n = soup.findAll(“div”)

values = [];

#print n
count = 0;

for i in n:
count=count+1;
#print count
if(i.string != None and count > 19):
#print i.string
values.append(i.string.encode(‘ascii’,’ignore’))

for i in range(len(values)):
try:
f.write(str(fields[i]+ “: “+values[i]).encode(‘utf-8’)+”\n”)
except:
print fields[i]+ “: “+values[i]

f.write(“\n”)

f.close()
[/sourcecode]

Nella lista fields saranno elencati tutti i campo della tabella (Ex. Nome, Cognome, Specializzazione ecc) ed in quella values tutti i valori dei campi prima citati. Lo step successivo è quello di scrivere tutte queste informazioni in un unico file per poi poter fare tutte le nostre statistiche in maniera semplice ed immediata.

Il file IngPZAll.txt è output dello script, ed avrà al suo interno il dettaglio di tutti gli ingegneri iscritti all’albo.

Output Example

[sourcecode language=”text”]
..
..
..
http://www.ordingpz.it/albo/Alboview.asp?N__ISCR_=2714
N Iscrizione: 2714
Cognome: MONACO
Nome: Pierpaolo
Luogo di Nascita: Potenza
Data di Nascita:
C.F.:
Indirizzo:
CAP:
Citt:
Provincia: PZ
Sezione: A
Settore: Civile ed Ambientale, Industriale, Dell’Informazione
N Iscrizione: 2714
Data Iscrizione: 04/01/2012
Specializzazione: Informatica
Sede Laurea: Roma
Data Laurea: 21/03/2011
Sede Abilitazione: Roma
Anno Abilitazione: 2011
Ordine di Provenienza: Potenza
Data Prima Iscrizione: 04/01/2012
..
..
[/sourcecode]

Ora con una semplice comando bash posso facilmente capire ciò che volevo…

[sourcecode language=”bash”]
unicondor@iMac:> grep -c “Specializzazione: Informatica” IngPZAll.txt
19
[/sourcecode]

Ecco l’informazione che cercavo, su 2506 iscritti all’albo solo 19 hanno come specializzazione Informatica 😀

Attach:

alboIngPzParser.py

IngPZAll.txt

GitHub Project:

https://github.com/flaviopace/SimplePythonHTMLParser

P.s. tutti i dati che trovate in questo articolo solo liberamente disponibili sul sito dell’albo degli Ingegneri di Potenza

WiFi HotSpot e Captiva Portal tramite pfsense

caffedelcorso

Dovrei studiare per l’esame di stato ma, ogni giorno, trovo sempre qualcosa di piu’ interessante da fare.

Era da un po’ di tempo che avevo in mente l’idea di creare degli HotSpot WiFi Free per l’accesso gratuito ad Internet per i clienti di:  Caffe del Corso e Bar Belvedere (permettetemi un po’ di pubblicita’ 😛 ).

Dopo aver girovagato un po’ su internet sulle varie soluzioni da poter utilizzare, alla fine il suggerimento migliore (come sempre accade) e’ stato quello del mio mentore Franco 😀

Utilizzare pfsense come Captive Portal e’ davvero semplice ed intuitivo. Ci ho perso solo 2 gg 😛 , ma questo mi ha permesso di avere degli accessi controllati sia in termini di banda (download/upload) sia in termini di tempo (minuti per ogni connessione).

Ho usato una macchina virtuale tramite Virtualbox per far girare pfsense (Attenzione, quando create la macchina virtuale scegliete BSD e non Linux altrimenti non vi vede le interfacce di rete ). Di seguito vi mostro i passi da seguire per un corretto settaggio delle interfacce di rete e del Captive Portal.

Per l’installazione di pfsense su macchine virtuali trovate un sacco di tutorial su google, io ho scaricato direttamente la .iso image del LiveCD montata all’avvio e poi ho provvedo alla sua installazione sull’hard disk virtuale.

Premetto che da buon utilizzare di Slackware, ho utilizzato l’interfaccia testuale e non quella grafica. Il risultato finale è lo stesso, una volta capito cosa fare potete impostare i miei stessi parametri utilizzando la comoda interfaccia web che pfsense ci mette a disposizione.

Appena finita l’installazione di pfsense, ho settato la prima interfaccia virtuale in bridge mode con la mia interfaccia fisica WAN, e la seconda interfaccia virtuale in bridge mode con la mia ethernet che fungera’ da LAN interna per l’HotSpot.

ether_em0
Wan Interface
ether_em1
LAN Interface

1) Riepilogo Interfacce e Creazione VLANs

Al primo avvio di pfsense avremo il riepilogo delle interfacce che abbiamo a disposizione, rispettivamente: em0 ed em1 (quelle settate nelle figure precedenti), e la richiesta di creare delle interfacce vortuali all’interno di pfsense. Per ora scriviamo “n”, possiamo abilitare le interfacce viartuali in un secondo momento.

Leggi tutto “WiFi HotSpot e Captiva Portal tramite pfsense”

Facebook Hacker Cup 2 Round: my Card Game Solution

FacebookHackerCup 2 Round

This is my solution to the problem of Card Game, work fine for small input… but when the value of k grows (k>500 ) my code spent a lot of time.

The bottleneck it’s about the iteration to find the max in the array…

So i hope you can optimize it 😀

[sourcecode language=”python”]

import sys
import math
from collections import Counter
import re
import itertools

in_file = open(sys.argv[1],"r")
exp = in_file.read()
in_file.close()

inputFile= exp.split("\n")

index=[]
values=[]

def findsubsets(S,m):
return set(itertools.combinations(S, m))
a=[]
flavio=1
for i in range(1, len(inputFile)-1) :
values=[]
allsub=[]
if(i%2) :
# index.append(inputFile[i])
n,k=map(int,inputFile[i].split())
else :

values= map(int,inputFile[i].split())

# Optimization , not call a function
allsub=itertools.combinations(values,k)

my_sum=0

for f in allsub:

my_max=max(f)
my_sum += (my_max)

if(my_sum>=1000000007):
my_sum = my_sum -1000000007

print "Case #"+str(flavio)+": "+str(my_sum)

flavio +=1

[/sourcecode]

GitHub

https://github.com/flaviopace/FacebookHackerCup2_CardGameSolution

Python: UnicodeEncodeError: ‘ascii’ codec can’t encode character u’\u20ac’

Chiunque abbia fatto un minimo di parsing HTML tramite Python, ha incontrato almeno una volta questo fatidico errore (almeno lo spero, altrimenti sono l’unico pseudo smanettone ad averlo avuto 😛 ), soprattutto se il parsing e’ stato effettuato su pagine web in cui la valuta e’ l’Euro, dato che \u20ac rappresenta il simbolo “” (dannato Euro, anche nel mondo dell’informatica ci da’ problemi).

Il problema deriva avviene quando Python cerca di codificare il simbolo  € con un carattere ASCII.

Codifica?? Uhm?? se sei confuso come me… continua a leggere 😀

Prima di continuare facciamo un piccolo ricapitolazione di “Fondamento di Informatica”…la cosa piu’ importante da sapere e’ che: l’oggetto str in Python memorizza il suo valore come bytes, cioe’ con una sequenza di 8-bit, a.k.a string. Per questo motivo ogni carattere ASCII viene codificato in 8-bit, questo vuol dire che abbiamo a disposizione 0-255 rappresentazioni diverse… ma questo non e’ sufficiente per rappresentare i caratteri Russi, Arabi, Giapponessi… ed il nostro famoso simbolo dell’euro.

Per superare questa limitazione, Python usa unicode che memorizza il carattere con 16-bit o 32-bit dandoci la possibilita’ di rappresentare qualsiasi simbolo in qualsiasi linguaggio.

Voi direste.. Evviva! basta usare l’unicode e risolvo il problema, giusto? NO, non puoi…. ci mancherebbe che il mondo dell’informatica sia cosi’ logico e “clean” 😀

In particolare, non si puo scrivere su un file usando l’unicode, perche’ il file vuole una stringa che sia rappresentata da 8-bit. Dato che Python e’ molto “smart” cerchera’ in automatico di codificare/uniformare il carattere in unicode per la scrittura su file (o qualsiasi altro stream, come la shell), ma ahime’ c’e’ un problema… vediamo meglio con un esempio.

[sourcecode language=”python”]
>>> price_info = u’the price is \u20ac 5′
>>> type(price_info)
<type ‘unicode’>
>>> f = open(‘priceinfo.txt’,’wb’)
>>> f.write(price_info)
Traceback (most recent call last):
File "", line 1, in ?
UnicodeEncodeError: ‘ascii’ codec can’t encode character u’\u20ac’ in position 9: ordinal not in range(128)
>>>
[/sourcecode]

What happened?? Quando Python cerca di scrivere nel file “the price is € 5”, egli cerca di trasformare il valore unicode ‘\u20ac‘ in un carattere ASCII ad 8-bit… ma prima abbiamo detto che ASCII non contiene il carattere in questione… per cui… mi stai seguendo?? 😀

La soluzione e’ semplice (dopo che ho passato almeno una nottata su stackoverflow 😛 ):

[sourcecode language=”python”]
>>> price_info_enc = price_info.encode(‘utf-8’) # >> price_info_enc
‘it costs \xe2\x82\xac 5’
>>> type(price_info_enc)
<type ‘str’>
>>> f.write(price_info_enc)
>>> f.close()
[/sourcecode]

Semplice!! abbiamo codificato l’unicode tramite ‘utf-8’, il quale usa una sequenza di 3 caratteri ‘\xe2\x82\xac‘ per rappresentare il simbolo dell’Euro , in questo modo possiamo passare facilmente da ‘utf-8′ ad ASCII.

Ovviamente nel caso volessimo leggere il simbolo al contrario ( cioe’ vedere sullo schermo il simbolo dell’euro) dovremmo procedere con la decodifica dei tre caratteri in ‘utf-8′ e poi effettuare il print 😉

Ma c’e’ davvero gente che legge i miei post??? Mmmm ne dubito… ma come sempre, questo post mi servira’ da qui ad una settimana, visto che la mia memoria e’ scarsa e mi capitera’ di nuovo di imbattermi in questo problema… spero almeno di ricordarmi di aver scritto qualcosa sull’argomento 😛

Quanta banda richiede la visualizzazione di un video su YouTube?

E’ la classica domanda che si pone chi:

1) Ha una tariffazione a KB per navigare con il proprio cellulare

2) Sfigati che come me fanno parte dell’ Anti Digital Divide (ADSL a 640 Kbps), e si chiedono il perche’ non riescono a vedere un video a 360p su YouTube senza aspettare la bufferrizzazione dei pacchetti, che tradotto sarebbe il caricamento del video 😀 .

Partiamo andando a leggere le specifiche che ci mette direttamente a disposizione Google

Risoluzione:

YouTube usa un aspect ratio standard a 16:9, con le principali risoluzione video a:

  • 1080p: 1920×1080
  • 720p: 1280×720
  • 480p: 854×480
  • 360p: 640×360
  • 240p: 426×240
Con un fps ( frame per second) pari a 24/30, dove fps rappresenta il numero di frame (immagini) per secondo
Comparison of YouTube media encoding options
Default container FLV MP4
Video Encoding Sorenson H.263 MPEG-4 AVC (H.264)
Profile Main Baseline High
Resolution progressive 240p 270p 360p 480p 360p 720p 1080p 3072p
Resolution VGA WQVGA HVGA nHD FWVGA nHD WXGA WUXGA HXGA
Max width (pixels) 400 480 640 854 640 1280 1920 4096
Max height (pixels) 240 270 360 480 360 720 1080 3072
Bitrate[2] (Mbit/s) 0.25 0.8 0.5 0.8–1 0.5 2–2.9 3–4.3 3.5–5
Audio Encoding MP3 AAC
Channels 1–2 2 (stereo)
Sampling rate (Hz) 22050 44100
Bitrate[2] (kbit/s) 64 128 96 152 128

Questa tabella presa da Wikipedia riassume le varie risoluzioni e i relativi dettagli per ogni configurazione ( compresa la banda che a noi interessa), vediamo assieme come interpretare i numeri  per la risoluzione a 360p.

Video:

Encoding: MPEG-4 AVC (H.264) è il codec usato per la compressione del video ( vedremo più avanti a cosa serve)

Resolution: 360p è la risoluzione del video

Max width (pixel): 640 sono i pixel in larghezza del video

Max height(pixel): 360 sono i pixel in altezza del video

Bitrate (Mbit/s): 0.5 è il parametro che mi interessava, in poche parole dice che per visualizzare correttamente ( senza bufferrizzare ) il video abbiamo bisogno di almeno di una banda pari a 500 Kbps ( la mia ADSL è di poco superiore)

Audio:

Encoding: AAC è il codec audio usato

Channels: 2(stereo)  abbiamo la registrazione a due canali (stereo)

Sampling rate (Hz): 44100 è il rate usato per il campionamento dell’audio

Bitrate (kbit/s): 128 è la banda utilizzata dalla sola traccia audio.

Calcolo Bitrate (Datarate)

Con il termine Bitrate si intende il numero di kilobits per secondi (kbps) che dobbiamo trasferire/ricevere per vedere un video. Più il valore è alto, più la qualità del video migliora.

La formula per il calcolo del Bitrate è molto semplice:

Total Bitrate (bps) = altezza del frame (pixel)  x  profondità del frame (pixel)  x  frame rate (fps)  x  numero di bit per rappresentare un pixel

Nel nostro caso avremo

Bitrate(360p)= 360 x 640 x 24 x 4 = 22118400 (bps)   che sarebbero all’incirca 22 Mbps

Ma non avevamo detto che il Bitrate per la 360p era di appena 0.5 Mbps ??

Ed ecco che entra in gioco il codec che abbiamo citato prima: MPEG-4 AVC (H.264), il numero che è uscito fuori dalla formula precedente si riferisce al video “un-compressed”.

Tramite il codec MPEG-4 ( tra i migliori in circolazione) abbiamo un Compression Ratio 50:1, significa che il fattore di compressione farà si che il Bitrate uncompressed venga diviso per 50.

Per tale motivo il Bitrate del video compresso sarà uguale a:

BitRate Video Compressed = Bitrate Uncompressed / Compression Ratio MPEG-4   —>  Bitrate Compressed = 22 Mbps / 50 = 0.44 Mbps

Perfetto! ora ci troviamo con il valore in tabella 😉

Spero di aver fatto un pò di chiarezza su come calcolare il Bitrate di una sorgente Video e di come leggere correttamente i dato che ci mettono a disposizione i vari siti di Hosting Video.

Sperando che presto… anche i nostri piccoli comuni vengano raggiunti da una connessione semi-decente 🙁

Riferimenti:

http://en.wikipedia.org/wiki/YouTube

http://adterrasperaspera.com/blog/2010/05/24/approximate-youtube-bitrates

http://blog.jimmyr.com/High_Quality_on_Youtube_11_2008.php

http://neuron2.net/LVG/ratesandsizes.html

http://support.google.com/richmedia/bin/answer.py?hl=en&answer=2462489

http://www.kanecomputing.co.uk/pdfs/compression_ratio_rules_of_thumb.pdf

Personalizzare Asterisk Web Manager con i Log Custom di Asterisk

Dopo aver visto come automatizzare il logratate dei file di log di Asterisk, passiamo alla visualizzazione dei file di Log ( cdr-custom)  Custom,  che Asterisk ci mette a disposizione, tramite l’interfaccia web di Asterisk WEB/PHP Management Interface.

Step I

Per prima cosa dobbiamo abilitare il Mappings del custom config file editando il seguente file: /etc/asterisk/cdr_custom.conf

il quale creera’ il file /var/log/asterisk/cdr-custom/Master.cvs con i campi che a noi interessano.

cdr_custom.conf

[sourcecode language=”bash”]

unicondor@server:~$ cat /etc/asterisk/cdr_custom.conf
;
; Mappings for custom config file
;
; To get your CSV output in a format tailored to your liking, uncomment the
; following lines and look for the output in the cdr-custom directory (usually
; in /var/log/asterisk). Depending on which mapping you uncomment, you may see
; Master.csv, Simple.csv, or both.
;
[mappings]
Master.csv =>${CSV_QUOTE(${CDR(src)})},${CSV_QUOTE(${CDR(dst)})},${CSV_QUOTE(${CDR(duration)})},${CSV_QUOTE(${CDR(disposition)})},${CDR(sequence)},${CVS_QUOTE(${CDR(start)})}

[/sourcecode]

La modifica del file riporato il alto servirà a creare un file di log customizzato per le nostre neccessità. Il path ( installazione di default di Asterisk ) dove potete trovare il file è il seguente:

/var/log/asterisk/cdr-custom/Master.csv

Al seguente indirizzo potete trovare le info riguardanti i campi che ho usato per creare il mio file di Log Custom
Ora non ci resta altro che effettuare un bel reload dalla console di Asterisk per fargli vedere le modifiche

[sourcecode language=”bash”]

server*CLI> realod

[/sourcecode]

Step II

Fatto questo, andiamo a modificare il file logs.php che si trova nella directory web del WEB/PHP Management Interface, aggiungendo la voce che riguarda il file di log appena creato

[sourcecode language=”php”]
[rot@server asterisk]# cat /var/www/html/asterisk/logs.php
<?php <br ?>
if (isset($_POST[‘radio’])) {
if ($_POST[‘radio’] == "cdrformat") {
if (isset($_POST[‘pattern’])) $pattern = $_POST[‘pattern’];
header("Location: cdr.php?pattern=$pattern");
// header("Location: http://$_SERVER/asterisk/cdr.php?pattern=$pattern");
}
}

if (isset($_POST[‘radio’])) {
if ($_POST[‘radio’] == "cdrformat_custom") {
if (isset($_POST[‘pattern’])) $pattern = $_POST[‘pattern’];
header("Location: cdr_custom.php?pattern=$pattern");
// header("Location: http://$_SERVER/asterisk/cdr.php?pattern=$pattern");
}
}

include(‘header.php’);
include(‘files.php’);
include(‘functions.php’);

if (isset($_POST[‘submit’])) {
$submit = $_POST[‘submit’];
if (isset($_POST[‘loglines’])) $loglines = $_POST[‘loglines’];
else $loglines = 0;
if (isset($_POST[‘pattern’])) $pattern = $_POST[‘pattern’];
else $pattern = "";
if (isset($_POST[‘radio’])) $radio = $_POST[‘radio’];
if ($submit =="SUBMIT") {
if ($pattern != "") $cmd = "/bin/grep $pattern ";
else {
if ($loglines == 0) $cmd = "/bin/cat ";
else $cmd = "/usr/bin/tail -$loglines ";
}
if ($radio == "syslog") $cmd .= $SYSTEMMESSAGES;
if ($radio == "cdr") $cmd .= $CDRMASTER;
if ($radio == "events") $cmd .= $ASTEVENTLOG;
if ($radio == "messages") $cmd .= $ASTMESSAGESLOG;
if ($radio == "queue") $cmd .= $ASTQUEUELOG;
echo "
";
mysystem($cmd);
echo "
";
echo "
";
echo $cmd;
echo "
";
echo "Done !";
}
}
else
{
?></pre>
<div align="center"><form action="<?php echo $_SERVER[‘PHP_SELF’]; ?><br />" method="post">
<table>
<tbody>
<tr>
<td>Search String <input type="text" name="pattern" /></td>
<td>
Lines to List [0=All] <input type="text" name="loglines" value="50" /></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td><input type="radio" name="radio" value="events" /> Asterisk Event Log</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="messages" /> Asterisk Message Log</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="queue" /> Asterisk Queue Log</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="cdr" /> Asterisk CDR Log</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="cdrformat" /> Asterisk CDR Log [Table Formatted]</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="cdrformat_custom" checked="checked" /> Asterisk CDR ***Custom*** Log [Table Formatted]</td>
<td> </td>
</tr>
<tr>
<td><input type="radio" name="radio" value="syslog" /> System Log [SYSLOG]</td>
<td> </td>
</tr>
</tbody>
</table>
<input type="submit" name="submit" value="SUBMIT" />

<input type="reset" name="reset" value="RESET" /></form></div>
<pre>
<?php } ?>

[/sourcecode]

Ora non ci resta altro che andare a creare la pagina php cdr_custom.php , responsabile della lettura del file log custom di Asterisk e la sua stampa in una tabella html

[sourcecode language=”php”]

[unicondor@server asterisk]$ cat /var/www/html/asterisk/cdr_custom.php
<?PHP <br ?>/* Modified by Flavio Pace
*/
include("header.php");
include("files.php");

//Fields of the CDR in Asterisk
//—————————–
//
// 1. accountcode: What account number to use, (string, 20 characters)
// 2. src: Caller*ID number (string, 80 characters)
// 3. dst: Destination extension (string, 80 characters)
// 4. dcontext: Destination context (string, 80 characters)
// 5. clid: Caller*ID with text (80 characters)
// 6. channel: Channel used (80 characters)
// 7. dstchannel: Destination channel if appropriate (80 characters)
// 8. lastapp: Last application if appropriate (80 characters)
// 9. lastdata: Last application data (arguments) (80 characters)
// 10. start: Start of call (date/time)
// 11. answer: Answer of call (date/time)
// 12. end: End of call (date/time)
// 13. duration: Total time in system, in seconds (integer), from dial to hangup
// 14. billsec: Total time call is up, in seconds (integer), from answer to hangup
// 15. disposition: What happened to the call: ANSWERED, NO ANSWER, BUSY
// 16. amaflags: What flags to use: DOCUMENTATION, BILL, IGNORE etc,
// specified on a per channel basis like accountcode.
// 17. user field: A user-defined field, maximum 255 characters

if (isset($_GET[‘pattern’])) $pattern = $_GET[‘pattern’];
else $pattern = "";

$fname = $CDRCUSTOM;
$fd = fopen ($fname, "r");
if (!$fd) {
echo "Error opening $fname";
exit(0);
}
echo "</pre>
<table border="1" align="center">";echo "
<tbody>
<tr>";echo "
<th>Src</th>
";echo "
<th>Dst</th>
";echo "
<th>Duration</th>
";echo "
<th>Disposition</th>
";echo "
<th>User Field</th>
";echo "
<th>Start</th>
";echo "</tr>
";$limit = 0;$d = 0;while (!feof ($fd)) { $buffer = fgets($fd, 4096); $l = trim($buffer); if ($pattern != "") { if (!strstr($l,$pattern)) continue; } $badcommapat = ‘/\"[^\"]+,[^\",]+\"/’; if (preg_match($badcommapat,$l,$matches)) { $fixcomma = str_replace(",","-",$matches[0]); $l = str_replace($matches[0],$fixcomma,$l); } $e = explode(",",$l); $len = sizeof($e); echo "
<tr>"; for ($c=0;$c echo "
<td nowrap="nowrap">";
$e[$c] = trim($e[$c],"\r\n \"");
if ($c == 4) $e[$c] = str_replace ("\"", "", $e[$c]);
if ($e[$c] == "") echo " ";
else echo htmlspecialchars($e[$c]);
echo "</td>
"; }while ($c < 6) { echo "
<td> </td>
"; ++$c; } echo "</tr>
\n"; flush(); ++$d; if ($limit != 0) { if ($d >= $limit) break; }}echo "</tbody>
</table>
<pre>
";
fclose ($fd);
?>

[/sourcecode]

Alcuni Screenshot dell’interfaccia grafica customizzata

Google File System – Come funziona e la sua Architettura

Google Data Centers - File System Distributed

Ultimamente mi sono interessato ai File System Distribuiti, usati da una miriade di Sistemi di Calcoto Distribuiti ( HPC, Cluster, Sistemi GRID ), grazie alla peculiarita’ di poter immagazzinare enormi quantita’ di dati che altrimenti non potrebbero essere immagazzinate su un singolo disco rigido.

Immaginate un Sistema come quello di Google, con migliaia di cluster e centinaia di Terabyte di dati da gestire. Un Sistema in grado di visualizzare in pochi secondi e da qualsiasi parte del mondo tutte le vostre mail, tutti i vostri documenti, tutte le vostre immagini. Un Sistema che non ammette Failure o perdita di dati alcuna ( Spero almeno che i Crawlers di Google dopo questa premessa aumentino il SiteRank del blog 😛 ).

Google File System ( GFS o GoogleFS ) è il lavoro di anni di ricerca ed implementazione da parte del settore ricerca e sviluppo di Google, l’idea alla base dell’architettura deriva direttamente dai due fondatori di Google: Larry Page e Sergey Brin quando ancora studiavano a Stanford e pensavano ad un File System che soddisfacesse tale definizione:

“store data reliably even in the presence of unreliable machines”

che tradotto significa: “Immagazzinare dati in maniera affidabile anche in presenza di macchine inaffidabili”. Infatti la maggior parte dei computer utilizzati da Google sono formati da componenti economiche che molto spesso crashano o si rompono, per tale motovo il File System da usare doveva avere un alto grado di tollerenza ai guasti.

Leggi tutto “Google File System — Come funziona e la sua Architettura”

TopHost: Redistribuire Spazio tra i servizi Web MySql Mail

E’ già da qualche mese che il blog è online ( esattamente dal 24/10/2010 ) e deve dire che di solito mi “scoccio” abbastanza presto dei capricci che spesso mi vengono in mente, questa volta devo dire che la cosa mi appassiona e mi spiace per te, malcapitato lettore, ma dovrai sopportami per un bel pò 😛

Ritornando al titolo del post, senza divagare ulteriormente, ho fatto accesso al Pannello di Amministrazione di TopHost ( devo ammettere un servizio low-cost impeccabile fino ad ora ) per controllare lo stato dei servizi e la distribuzione dei 500 MB messi a disposizione dal provider ed ho notato che lo spazio del database MySql era in esaurimento

Guardando la linea rossa lampaggiante in basso alla schermata mi sono subito preoccupato credendo di aver esaurito lo spazio totale del mio Database. Infine facendo una piccolisissima ricerca sul web mi sono accorto che il provider permette la re-distribuzione dello spazio dei servizi ( di default lo spazio Mysql è 5000 KB pari a 5 MB ) e per tale motivo basta solo aumentare lo spazio dedicato al database, ovviamente rispettando sempre il limite totale dei 500 MB messi a disposizione per ogni host.

Leggi tutto “TopHost: Redistribuire Spazio tra i servizi Web MySql Mail”