HE:Telefonkonferenz
Aus Piratenwiki
Inhaltsverzeichnis |
Hinweise zu Telefonkonferenzen des LV Hessen
Einleitung
Der Landesverband Hessen betreibt einen eigenen Server mit der Software Asterisk für Telefonkonferenzen. Diese WIKI-Seite soll Hinweise zur Bedienung und Einblick in die Konfiguration geben
Einwahl
Die Telefonkonferenzen sind über eine Festnetznummer und mit einem SIP-Client direkt über eine SIP-URL erreichbar:
... mit einem Telefon
- Festnetz Deutschland: +49 (0) 69 175 36 743 (Sipgate)
- Festnetz Schweiz: +41 (0) 31 5110514 (PhoneStar*)
- Festnetz Österreich: +43 (0) 720 512348 (Sipcall)
- Festnetz Luxemburg: +352 203 330 004 638 (MIXvoip)
- Festnetz USA: +1 253-753-1915 (IPKall) Muss aber regelmässig genutzt werden, sonst wird der Account gelöscht
... mit einem SIP-Client
- sip:500@sip.piratenpartei-hessen.de (deutsche Ansagen)
- sip:501@sip.piratenpartei-hessen.de (englische Ansagen)
- sip:502@sip.piratenpartei-hessen.de (französische Ansagen)
- sip:503@sip.piratenpartei-hessen.de (spanische Ansagen)
- sip:504@sip.piratenpartei-hessen.de (italienische Ansagen)
- sip:505@sip.piratenpartei-hessen.de (schwedische Ansagen)
- sip:506@sip.piratenpartei-hessen.de (russische Ansagen)
- Über SIPBroker: Nach der Einwahl über eine der Nummern aus deren PSTN numbers erhält man eine Ansage, daß man nun die Zielnummer angeben soll. Hier wählt man *9846500 (bzw. statt der 500 eine der Nummern oben für eine andere Sprache). Ggf. muß man es mehrfach versuchen!
- es gibt auch einen bulgarischen Skype SIP-Gateway (von der Firma bgopen.net) der eine Verbindung zu SIPBroker hat: man ruft im Skype den Benutzer bgopen an, und sobald man eine Ansage auf Bulgarisch hört, wählt man dann, wie oben beschrieben *9846-500 an.
Achtung: Wer einen SIP-Client hinter einem Router mit NAT einsetzt muß vermutlich auch einen STUN-Server mit angeben. Ein öffentlich erreichbarer STUN-Server ist z.B. stun.sipgate.net:1000
Nach der Ansage muß man die Raumnummer gefolgt von der "#" eingeben. Administratoren können auch die Raumnummer gefolgt von der Administrator-PIN und dann der "#" verwenden. Damit können diese den Konferenzraum schließen und wieder öffnen.
Zur Kontrolle wird dann die eingegebene Raumnummer nochmals angesagt und im Erfolgsfall die Anzahl bisheriger Teilnehmer angegeben. So lange nur ein Teilnehmer in der Konferenz ist wird Musik von David Rovics gespielt: http://www.davidrovics.com Die Musik steht unter der Lizenz CC-BY-NC-SA http://creativecommons.org/licenses/by-nc-sa/3.0/
Innerhalb der Konferenz kann man mit der *-Taste ein Menü abrufen. Die Menübefehle sind im Einzelnen:
- *1 schaltet das eigenen Mikrofon stumm oder wieder aktiv
- *4444448 stellt den eigenen Lautsprecher leiser
- *6666668 stellt den eigenen Lautsprecher lauter
- *7777778 dämpft das eigene Mikrofon
- *9999998 verstärkt das eigene Mikrofon
Wenn man aktuell nicht sprechen möchte sollte man Rücksicht auf andere Konferenzteilnehmer nehmen und sich mit * 1 stumm schalten (insbesondere wenn man viele Nebengeräusche hat). Wenn man dann sprechen möchte kann man sich mit einem erneuten * 1 wieder freischalten.
Administratoren haben zusätzlich folgende Optionen:
- *2 schliesst den Konferenzraum oder öffnet ihn wieder
- *3 wirft den zuletzt eingewählen Teilnehmer aus der Konferenz
Über das Webinterface kann der Administrator einen Livestream aktivieren. Dieser ist dann abrufbar unter http://sip.piratenpartei-hessen.de:8000/raum####.ogg (#### muss durch die Raumnummer ersetzt werden)
Raumnummern
Folgende Konferenzräume sind derzeit vorgesehen:
- 1000# Vorstandssitzungen LV Hessen
- 1001# AK Basisdemokratie
- 1002# AG mypirates
- 1003# AG Web
- 1004# Hessen AGs, PGs
- 1005# Presse-AG
- 1010# Schiedsgericht LV Hessen (nur mit PIN zugänglich)
- 1510# Kreisverband Frankfurt
- 1520# Kreisverband Kassel
- 1530# Kreisverband Wetterau
- 1540# Virtueller Stammtisch Schwalm-Eder-Kreis
- 1550# KV Bergstrasse
- 1560# KV Offenbach-Land
- 1570# KV Main-Kinzig
- 1575# KV Main-Kinzig Kreistagspiraten
- 1580# KV Wiesbaden (Basis)
- 1581# KV Wiesbaden Fraktion
- 1590# KV Marburg-Biedenkopf
- 1600# KV Hochtaunus
- 1610# KV Gießen
- 1620# KV Groß-Gerau
- 1630# KV Main-Taunus-Kreis
- 2000# BW Vorstandskonferenz
- 2101# LV RLP KV Rhein-Pfalz
- 2200# LV Bayern Vorstandssitzungen
- 2201# BzV Mittelfranken
- 2202# BzV Oberbayern
- 2203# BzV Schwaben
- 2204# BzV Unterfranken
- 2205# BzV Niederbayern
- 2206# BzV Oberpfalz
- 2207# BzV Oberfranken
- 2211# KV Erlangen
- 2210# AG Werbemittel Bayern
- 2299# LV Bayern Landesvorstand
- 2300# Nordpiraten
- 2301# LV Niedersachsen
- 2302# KV Osnabrück
- 2303# KV Wilhelmshaven
- 2304# Ratsfraktion Braunschweig
- 2305# LSG Niedersachsen
- 2306# RV Hannover
- 2307# Presse LV Niedersachsen
- 2310# KV Celle
- 2400# LV Sachsen Vorstandssitzung
- 2410# KV Chemnitz
- 2411# LSG Sachsen
- 2500# LV RLP Vorstandssitzung
- 2600# LV SH Vorstandssitzung
- 2700# LV Brandenburg Vorstandssitzung
- 2800# LV Thüringen
zeitweise mit Brücke zum NRW Mumble
- 3000# JuPis
- 8000# PPI
PPI Vorstand: Jeden Dienstag 21h
Präsidium PPLU: Jeden zweiten Mittwoch beginnend 13.10.2010 um 20:00
- 8001# Court of Arbitration (nur per PIN zugänglich)
- 8002# Court of Arbitration
- 8100# Piraten ohne Grenzen
- 8200# ACTA
- 8300# PP-LU
- 8500# Piratenradio
- 9001# BundesAGs
AG Energiepolitik: Dienstags 19:00 - 24:00 Uhr
- 9002# BundesIT (Admindaten bei der IT)
Telko: Montags 21:00 - 24:00
- 9003# Koordinatorenkonferenz
- 9004# Bundes AG Wirtschaft
- 9005# Bundes AG Innenpolitik
- 9006# Bundes AG Außenpolitik
- 9007# Landes AG Einstieg
- 9008# INDECT Projektgruppe
- 9009# Flaschenpost (flaschenpost.piratenpartei.de)
- 9010# Bundes AG_Bedingungsloses_Grundeinkommen
- 9011# Bundes AG Urheberrecht
- 9012# Bundes AG Europa
- 9013# Bundes AG Bauen und Verkehr
- 9014# Bundes AG Orange Hilfe
- 9021# BundesIT
- 9022# BundesIT
- 9023# BundesIT
- 9024# BundesIT
- 9025# BundesIT
- 9324# Hochschulgruppen
- 9500# BPT Satzungskommission
- 9600# Bundesschiedsgericht
- 9610# Bundesschiedsgericht (Anhörung)
- 9990# Virtuelle BGS
- 9999# VorstandsSitzungen Bund
Datenschutzhinweise
Im Konfigurationsmenü zum Sipgate-Account sind die Anruferlisten deaktiviert. Bei Sipcall, MIXvoip und bei Phonestar lässt sich die Anrufprotokollierung leider nicht abschalten. Bei SIPBroker ist der Status derzeit nicht bekannt.
Durch Nutzung der SIP-URL umgeht man jegliche Speicherung des Anrufs bei Providern.
Der Server des Landesverbandes selbst erstellt keine Protokolldateien über die Anrufe. Im RAM werden von Asterisk jedoch folgende Daten vorgehalten und können während der Konferenz durch Administratoren abgerufen werden:
- Rufnummer des Teilnehmers, sofern diese vom Anrufer übermittelt wird
- Name des Anschlusses des Teilnehmers, sofern dieser vom Anrufer übermittelt wird (meistens ist dies gleich der Rufnummer, insbesondere bei Internettelefonie kann der Name aber ggf. abweichen)
- IP-Adresse des SIP-Clients (bei Zugang über die Sipgate-Telefonnummer ist dies die Adresse von Sipgate, bei Zugang über die SIP-URL ist dies die IP-Adresse des Anrufers)
- ob der Teilnehmer gerade spricht, ruhig ist oder stummgeschaltet ist
- die Dauer, die der Teilnehmer aktuell in der Konferenz ist
Bei Aufruf des Web-Administrationsinterfaces werden folgende Daten gespeichert:
- Datum und Uhrzeit
- aufgerufene Seite
- Status und Größe der Seite
- Referer (sofern vom Browser übermittelt)
- Browser-Identifikation (sofern vom Browser übermittelt)
Die IP-Adresse wird explizit nicht gespeichert.
Konfigurationsdateien Asterisk
Die Informationen in diesem und folgenden Abschnitten sind nur von Interesse, falls Du einen eigenen Telefonkonferenzserver betreiben willst.
asterisk.conf
[directories] astetcdir => /opt/asterisk/etc/asterisk astmoddir => /opt/asterisk/lib/asterisk/modules astvarlibdir => /opt/asterisk/var/lib/asterisk astdbdir => /opt/asterisk/var/lib/asterisk astkeydir => /opt/asterisk/var/lib/asterisk astdatadir => /opt/asterisk/var/lib/asterisk astagidir => /opt/asterisk/var/lib/asterisk/agi-bin astspooldir => /opt/asterisk/var/spool/asterisk astrundir => /opt/asterisk/var/run astlogdir => /opt/asterisk/var/log/asterisk [options] internal_timing = yes
extensions.conf
[globals]
Ortsnetz=69
Landnetz=49
[meet]
exten => _X.,1,Answer()
exten => _X.,n,Wait(1)
exten => _X.,n(anfang),Read(CONFNO,conf-getconfno)
exten => _X.,n,SayNumber(${CONFNO:0:4})
exten => _X.,n,GotoIf($[${LEN(${CONFNO})} < 4]?invalid)
exten => _X.,n,GotoIf($[${LEN(${CONFNO})} > 4]?pin)
exten => _X.,n,MeetMe(${CONFNO},cTsM,0)
exten => _X.,n,Goto(ende)
exten => _X.,n(pin),MeetMe(${CONFNO:0:4},cTsM,${CONFNO:4})
exten => _X.,n(ende),Hangup()
exten => _X.,n(invalid),Playback(conf-invalid)
exten => _X.,n,Goto(anfang)
[default]
exten => _X.,1,Set(CHANNEL(language)=de)
exten => _X.,n,Goto(intern,${EXTEN},1)
[de-in]
exten => _X.,1,Set(CHANNEL(language)=de)
exten => _X.,n,Goto(meet,${EXTEN},1)
[en-in]
exten => _X.,1,Set(CHANNEL(language)=en)
exten => _X.,n,Goto(meet,${EXTEN},1)
[intern]
exten => 500,1,Set(CHANNEL(language)=de)
exten => 500,n,Goto(meet,${EXTEN},1)
exten => 501,1,Set(CHANNEL(language)=en)
exten => 501,n,Goto(meet,${EXTEN},1)
exten => 502,1,Set(CHANNEL(language)=fr)
exten => 502,n,Goto(meet,${EXTEN},1)
exten => 503,1,Set(CHANNEL(language)=es)
exten => 503,n,Goto(meet,${EXTEN},1)
exten => 504,1,Set(CHANNEL(language)=it)
exten => 504,n,Goto(meet,${EXTEN},1)
exten => 505,1,Set(CHANNEL(language)=se)
exten => 505,n,Goto(meet,${EXTEN},1)
exten => 506,1,Set(CHANNEL(language)=ru)
exten => 506,n,Goto(meet,${EXTEN},1)
exten => _81XXXX,1,Answer()
exten => _81XXXX,n,Wait(1)
exten => _81XXXX,n,MeetMe(${EXTEN:2:4},m,0)
exten => _81XXXX,n,HangUp()
exten => 998,1,Answer()
exten => 998,n,Wait(1)
exten => 998,n,SayUnixTime()
exten => 998,n,Hangup()
exten => 999,1,Answer()
exten => 999,n,Echo()
exten => 999,n,Hangup()
meetme.conf
Die Administrator-PINs sind unkenntlich gemacht
[rooms] conf => 1000,0,*pin* conf => 1001,0,*pin* conf => 1002,0,*pin* conf => 1003,0,*pin* conf => 1004,0,*pin* conf => 1005,0,*pin* conf => 1010,*pin*,*pin* conf => 1510,0,*pin* conf => 1520,0,*pin* conf => 1530,0,*pin* conf => 1540,0,*pin* conf => 1550,0,*pin* conf => 1560,0,*pin* conf => 1570,0,*pin* conf => 2000,0,*pin* conf => 2101,0,*pin* conf => 2200,0,*pin* conf => 2201,0,*pin* conf => 2202,0,*pin* conf => 2203,0,*pin* conf => 2210,0,*pin* conf => 2300,0,*pin* conf => 2301,0,*pin* conf => 2400,0,*pin* conf => 2500,0,*pin* conf => 2600,0,*pin* conf => 3000,0,*pin* conf => 8000,0,*pin* conf => 8100,0,*pin* conf => 8200,0,*pin* conf => 8500,0,*pin* conf => 9001,0,*pin* conf => 9002,0,*pin* conf => 9003,0,*pin* conf => 9004,0,*pin* conf => 9005,0,*pin* conf => 9006,0,*pin* conf => 9007,0,*pin* conf => 9008,0,*pin* conf => 9009,0,*pin* conf => 9010,0,*pin* conf => 9011,0,*pin* conf => 9012,0,*pin* conf => 9324,0,*pin* conf => 9500,0,*pin* conf => 9600,0,*pin* conf => 9610,0,*pin* conf => 9999,0,*pin*
modules.conf
[modules] autoload = yes preload = chan_sip
musiconhold.conf
[default] mode=files directory=/opt/asterisk/var/lib/asterisk/moh random=yes
sip.conf
Username und Passwort bei Sipgate sind unkenntlich gemacht
[general] context=default srvlookup=yes allowguest=yes alwaysauthreject=no tos_sip=cs3 tos_audio=ef tos_video=af41 language=de maxexpirey=240 defaultexpirey=240 rtptimeout=900 rtpholdtimeout=1800 useragent=Useragent register => *username*:*passwort*@sipgate.de/*username* register => *username*:*passwort*@ps1.voipgateway.org/*username* register => *username*:*passwort*@free1.voipgateway.org/*username* register => *username*:*passwort*@sipregister.mixvoip.com/00352203330004638 [sipgate] type=friend qualify=yes host=sipgate.de nat=no insecure=invite,port canreinvite=yes username=*username* fromuser=*username* fromdomain=sipgate.de secret=*passwort* context=de-in [voipgateway-at] type=friend qualify=yes secret=*passwort* username=*username* host=free1.voipgateway.org nat=no insecure=invite,port canreinvite=no fromuser=*username* fromdomain=free1.voipgateway.org context=de-in [voipgateway-ch] type=friend qualify=yes secret=*passwort* username=*username* host=ps1.voipgateway.org nat=no insecure=very canreinvite=no fromuser=*username* fromdomain=ps1.voipgateway.org context=de-in [mixvoip] type=friend qualify=yes host=sipregister.mixvoip.com nat=no insecure=invite,port canreinvite=yes username=*username* fromuser=00352203330004638 fromdomain=sipregister.mixvoip.com secret=*passwort* context=en-in
Administrationsinterface
Für die Administration einer Konferenz gibt es ein kleines Web-Formular, welches mittels eines Bash CGI-Scriptes und eines Wrapper-Programmes für das CLI von Asterisk zur Verfügung gestellt wird:
meetmeadmin.cgi
#! /bin/bash
# Dieses Shell-Script stellt ein Webformular zur Administration einer
# Telefonkonferenz in Asterisk zur Verfügung. Der Aufruf des CLI von
# Asterisk erfolgt über ein Wrapper-Programm meetmeadmin, welches mittels
# Set-UID- / Set-GID-Bit den Zugriff auf die Asterisk-Konfiguration
# und den Socket zur Steuerung erhalten muss
# Author: Lothar Krauß (mailto: pirat@lkrauss.de)
# Lizenz: CC-BY
ADMINBIN=/opt/asterisk/sbin/meetmeadmin
p_loginform()
{
echo '<FORM Method="POST" Action="meetmeadmin.cgi">'
echo 'Raumnummer: <INPUT Type="TEXT" Name="raum" size=4 Value="'$RAUM'">'
echo 'PIN: <INPUT Type="PASSWORD" Name="pin" size=8 Value="'$PIN'">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Einloggen">'
echo '</FORM>'
}
p_buttons()
{
echo '<TR><TD>'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Schliessen">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Öffnen">'
echo '</TD><TD align="right">Teilnehmer:'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Stumm">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Sprechen">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Ausschliessen">'
echo '</TD></TR>'
}
p_endhtml()
{
echo '</body>'
echo '</html>'
}
DATEN=""
RAUM=""
PIN=""
AKTION=""
SAMMEL=""
CLOSE=""
STATUS=""
STREAM=""
RECORD=""
if [ "$REQUEST_METHOD" = "POST" ]
then
DATEN=`/bin/cat | /bin/sed -e 's,[^0-9a-zA-Z&=],,g' -e 's,&, ,g'`
for x in $DATEN
do
feld=${x%=*}
wert=${x#*=}
case $feld in
raum)
RAUM="$wert"
;;
pin)
PIN="$wert"
;;
close)
CLOSE="$wert"
;;
aktion)
AKTION="$wert"
;;
mark)
SAMMEL="$SAMMEL $wert"
;;
esac
done
fi
if [ "$AKTION" = "Download" -a -r /opt/asterisk/var/spool/asterisk/monitor/raum$RAUM.gsm ]
then
$ADMINBIN test $RAUM $PIN
if [ "$?" = "0" ]
then
echo "Content-type: application/octed-stream"
echo "Content-disposition: filename=raum$RAUM.ogg"
echo ""
sox /opt/asterisk/var/spool/asterisk/monitor/raum$RAUM.gsm -t ogg -
exit 0
fi
fi
/bin/cat <<ende1
Content-type: text/html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Piratenpartei Hessen - Administration Telefonkonferenz</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
</head>
<body>
ende1
if [ "$AKTION" = "Ausloggen" ]
then
RAUM=""
PIN=""
fi
if [ "$RAUM" = "" -o "$PIN" = "" ]
then
p_loginform
p_endhtml
exit 0
fi
if [ "$AKTION" = "Einloggen" ]
then
$ADMINBIN test $RAUM $PIN
if [ "$?" != "0" ]
then
sleep 5
p_loginform
echo '<h3>Fehler beim Einloggen</h3>'
p_endhtml
exit 0
fi
fi
if [ "$AKTION" = "D6ffnen" ]
then
$ADMINBIN unlock $RAUM $PIN
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim &OUml;effnen</h3>'
p_endhtml
exit 0
fi
CLOSE=0
elif [ "$AKTION" = "Schliessen" ]
then
$ADMINBIN lock $RAUM $PIN
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Schiessen</h3>'
p_endhtml
exit 0
fi
CLOSE=1
elif [ "$AKTION" = "Stream" ]
then
x=`ps -fu asterisk | grep /opt/asterisk/ices/raum$RAUM.xml`
if [ "$x" != "" ]
then
STATUS="Stream läuft bereits"
else
$ADMINBIN stream $RAUM $PIN
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Stream Starten</h3>'
p_endhtml
exit 0
fi
sleep 3
fi
elif [ "$AKTION" = "Record" ]
then
x=`$ADMINBIN list $RAUM $PIN|grep '!0!Record!Local/81'`
if [ "$x" != "" ]
then
STATUS="Aufzeichnung läuft bereits"
else
$ADMINBIN record $RAUM $PIN
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Aufzeichnung Starten</h3>'
p_endhtml
exit 0
fi
sleep 3
fi
elif [ "$AKTION" = "Delete" ]
then
$ADMINBIN delrecord $RAUM $PIN
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Löschen der Aufzeichnung</h3>'
p_endhtml
exit 0
fi
elif [ "$AKTION" = "Stumm" ]
then
if [ "$SAMMEL" = "" ]
then
STATUS="Bitte mindestens einen Teilnehmer markieren"
else
$ADMINBIN mute $RAUM $PIN $SAMMEL
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Stummschalten</h3>'
p_endhtml
exit 0
fi
fi
elif [ "$AKTION" = "Sprechen" ]
then
if [ "$SAMMEL" = "" ]
then
STATUS="Bitte mindestens einen Teilnehmer markieren"
else
$ADMINBIN unmute $RAUM $PIN $SAMMEL
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Freischalten</h3>'
p_endhtml
exit 0
fi
fi
elif [ "$AKTION" = "Ausschliessen" ]
then
if [ "$SAMMEL" = "" ]
then
STATUS="Bitte mindestens einen Teilnehmer markieren"
else
$ADMINBIN kick $RAUM $PIN $SAMMEL
if [ "$?" != "0" ]
then
p_loginform
echo '<h3>Fehler beim Ausschliessen</h3>'
p_endhtml
exit 0
fi
sleep 3
fi
fi
if [ "$STATUS" = "" ]
then
if [ "$CLOSE" = "0" ]
then
STATUS="Raum ist geöffnet"
elif [ "$CLOSE" = "1" ]
then
STATUS="Raum ist geschlossen"
else
STATUS=" "
fi
fi
echo '<FORM Method="POST" Action="meetmeadmin.cgi">'
echo '<INPUT Type="HIDDEN" Name="raum" Value='"$RAUM"'>'
echo '<INPUT Type="HIDDEN" Name="pin" Value='"$PIN"'>'
echo '<INPUT Type="HIDDEN" Name="close" Value='"$CLOSE"'>'
echo '<TABLE><TR>'
echo '<TD>Raumnummer: '$RAUM'  '
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Ausloggen">'
echo '</TD><TD align="right">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Aktualisieren">'
echo '</TD></TR>'
echo '<TR><TD colspan="2">'
echo '<hr><h3>'$STATUS'</h3><hr>'
echo '</TD></TR>'
x=`ps -fu asterisk | grep /opt/asterisk/ices/raum$RAUM.xml`
if [ "$x" = "" ]
then
STREAM=0
else
STREAM=1
fi
x=`$ADMINBIN list $RAUM $PIN|grep '!0!Record!Local/81'`
if [ "$x" = "" ]
then
if [ -r /opt/asterisk/var/spool/asterisk/monitor/raum$RAUM.gsm ]
then
RECORD=9
else
RECORD=0
fi
else
RECORD=1
fi
echo '<TR><TD colspan="2">'
if [ "$STREAM" = "0" ]
then
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Stream">'
fi
if [ "$RECORD" = "0" ]
then
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Record">'
elif [ "$RECORD" = "9" ]
then
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Download">'
echo '<INPUT Type="SUBMIT" Name="aktion" Value="Delete">'
fi
echo '</TD></TR>'
p_buttons
echo '<TR><TD colspan="2">'
echo '<TABLE border="3" cellpadding="5">'
echo '<tr><th>Lfd.</th><th>Nummer</th><th>Name</th><th>Kanal</th>'
echo '<th>Dauer</th><th>Status</th>'
echo '<td><INPUT type="CHECKBOX" name="mark" Value="all"></td></tr>'
$ADMINBIN list $RAUM $PIN|/usr/bin/awk -F '!' '{
if ($5 == "1")
{
printf("<tr bgcolor=\"#ff0000\">");
}
else
{
printf("<tr>");
}
printf("<td align=\"right\">%s</td>",$1);
printf("<td>%s</td>",$2);
printf("<td>%s</td>",$3);
printf("<td>%s</td>",$4);
printf("<td>%s</td>",$9);
if ($7 == "1") { printf("<td>stumm</td>"); }
else if ($8 == "1") { printf("<td bgcolor=\"#ff0000\">spricht</td>"); }
else if ($8 == "-1") { printf("<td>unbekannt</td>"); }
else { printf("<td bgcolor=\"#00ff00\">bereit</td>"); }
printf("<td><INPUT type=\"CHECKBOX\" name=\"mark\" Value=\"%s\"></td>",$1);
printf("</tr>\n");
}'
echo '</TABLE>'
echo '</TD></TR>'
p_buttons
echo '</TABLE>'
echo '</FORM>'
p_endhtml
exit 0
meetmeadmin.c
Dieses Programm muss mittels SUID/SGID-Bit
- Leserechte auf /opt/asterisk/etc/asterisk/meetme.conf
- Schreibrechte auf /opt/asterisk/var/run/asterisk.ctl
erhalten
/* --- Dieses Programm dient dazu, das CLI von Asterisk nur für den --- */
/* --- meete-Befehl auszuführen. Zur Authorisation wird die Admini- --- */
/* --- strator-PIN des Konferenzraumes geprüft. Dem Programm muss mittels --- */
/* --- Set-UID- / Set-GID-Bit der Zugriff auf die Asterisk-Konfiguration --- */
/* --- und den Socket zur Steuerung gewährt werden --- */
/* --- Author: Lothar Krauß (mailto: pirat@lkrauss.de) --- */
/* --- Lizenz: CC-BY --- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
/* --- Konstanten zum Auffinden der Asterisk-Dateien --- */
#define ASTBIN "/opt/asterisk/sbin/asterisk"
#define ASTMEET "/opt/asterisk/etc/asterisk/meetme.conf"
#define ASTICE "/opt/asterisk/ices"
#define ASTOUT "/opt/asterisk/var/spool/asterisk/outgoing"
#define ASTMON "/opt/asterisk/var/spool/asterisk/monitor"
#define ICEPWD "*passwort*"
/* --- Ein Buffer zum Einlesen einer Zeile --- */
char wBuf[512];
/* --- Liest eine Zeile aus f in s (max size-1 Bytes + Null-Byte) --- */
/* --- und schneidet Leerzeichen und Tabs vorne und hinten ab --- */
/* --- Ergebnis: NULL = Fehler/Dateiende, ansonsten s --- */
char *readTrim(char *s, int size, FILE *f)
{
int i1,i2,j;
if (fgets(s,size,f)==NULL) return(NULL);
for (i1=0; strchr(" \t\r\n",s[i1])!=NULL; i1++);
for (i2=strlen(s); i2>=i1 && strchr(" \t\r\n",s[i2-1])!=NULL; i2--);
if (i1==0)
j=i2;
else
for (j=0; i1<i2; j++,i1++) s[j]=s[i1];
s[j]=0;
return(s);
}
/* --- Testet, ob "pin" die korrekte Admin PIN von Raum "room" ist --- */
/* --- Ergebnis: 0 = Raum oder PIN falsch --- */
/* --- 1 = Raum und PIN passen zuammen --- */
int checkAdmin(int room, int pin)
{
FILE *f;
int i1,i2,flag_found;
int room1,pin1;
if ((f=fopen(ASTMEET,"r"))==NULL) return(0);
/* --- Suche eine Zeile "[rooms]" --- */
strcpy(wBuf,"");
flag_found=0;
for (flag_found=0; !flag_found && readTrim(wBuf,sizeof(wBuf),f)!=NULL; )
{
if (!strcmp(wBuf,"[rooms]")) flag_found=1;
}
if (!flag_found)
{
fclose(f);
return(0);
}
/* --- Suche die Raumnummer, Ende spaetestens bei naechster Sektion --- */
for (flag_found=0; !flag_found && readTrim(wBuf,sizeof(wBuf),f)!=NULL; )
{
/* --- Zeile lautet "conf => raum,pin1,pin2" --- */
if (strncmp(wBuf,"conf",4)) continue;
for (i1=4; wBuf[i1]==' ' || wBuf[i1]=='\t'; i1++);
if (strncmp(wBuf+i1,"=>",2)) continue;
for (i1+=2; wBuf[i1]==' '||wBuf[i1]=='\t'; i1++);
/* --- Lese Raumnummer --- */
for (room1=0; isdigit(wBuf[i1]); i1++) room1=10*room1+(int)(wBuf[i1]-'0');
if (room1!=room) continue;
/* --- Ueberspringe "," --- */
for (; wBuf[i1]==' '||wBuf[i1]=='\t'; i1++);
if (wBuf[i1]!=',') continue;
for (i1++ ; wBuf[i1]==' '||wBuf[i1]=='\t'; i1++);
/* --- Ueberspringe User-PIN --- */
for (; isdigit(wBuf[i1]); i1++);
/* --- Ueberspringe "," --- */
for (; wBuf[i1]==' '||wBuf[i1]=='\t'; i1++);
if (wBuf[i1]!=',') continue;
for (i1++ ; wBuf[i1]==' '||wBuf[i1]=='\t'; i1++);
/* --- Lese Admin-PIN --- */
for (pin1=0; isdigit(wBuf[i1]); i1++) pin1=10*pin1+(int)(wBuf[i1]-'0');
flag_found=1;
}
if (!flag_found)
{
fclose(f);
return(0);
}
fclose(f);
if (pin!=pin1) return(0);
return(1);
}
void showHelp()
{
printf("Aufruf: meetmeadmin Befehl Raumnr PIN [Usernr] [Usernr]...\n");
printf("Befehl: list Listet die Teilnehmer der Konferenz\n");
printf("Befehl: lock Schliesst die Konferenz\n");
printf("Befehl: unlock Oeffnet die Konferenz wieder\n");
printf("Befehl: mute Schaltet die angegebenen Teilnehmer stumm\n");
printf("Befehl: unmute Schaltet die angegebenen Teilnehmer wieder frei\n");
printf("Befehl: kick Wirft die angegebenen Teilnehmer aus der Konferenz\n");
printf("Befehl: stream Startet einen Icecast Stream\n");
printf("Befehl: test Keine Ausgabe, Testet nur Gueltigkeit von Raum und PIN\n");
printf("Returncode: 0=Erfolg, 1=Fehler\n");
}
/* --- Fuehrt einen Befehl aus (User darf NULL sein) --- */
void Cmd(char *sCmd, char *sRoom, char *sUser)
{
int i,s;
/* --- Plausi-Checks --- */
if (sCmd==NULL||sRoom==NULL) return;
i=7+strlen(sCmd)+1+strlen(sRoom)+1;
if (sUser!=NULL) i=i+1+strlen(sUser);
if (i>sizeof(wBuf)) return;
strcpy(wBuf,"meetme ");
strcat(wBuf,sCmd);
strcat(wBuf," ");
strcat(wBuf,sRoom);
if (sUser!=NULL) { strcat(wBuf," "); strcat(wBuf,sUser); }
i=fork();
if (i==-1) return;
if (i>0)
{
execl(ASTBIN,ASTBIN,"-r","-x",wBuf,NULL);
exit(0);
}
else
{
waitpid(i,&s,0);
}
}
void Stream(int iRoom)
{
FILE *f;
/* --- ices2-Konfiguration aufbauen --- */
sprintf(wBuf,"%s/raum%04i.xml",ASTICE,iRoom);
if ((f=fopen(wBuf,"w"))==NULL) return;
chmod(wBuf,S_IREAD|S_IWRITE);
fprintf(f,"<?xml version=\"1.0\"?>\n");
fprintf(f,"<ices>\n");
fprintf(f," <background>0</background>\n");
fprintf(f," <logpath>/opt/asterisk/var/log/asterisk</logpath>\n");
fprintf(f," <logfile>ices.log</logfile>\n");
fprintf(f," <loglevel>1</loglevel>\n");
fprintf(f," <consolelog>0</consolelog>\n");
fprintf(f," <stream>\n");
fprintf(f," <metadata>\n");
fprintf(f," <name>Raum %04i</name>\n",iRoom);
fprintf(f," <genre>Telefonkonferenz</genre>\n");
fprintf(f," <description>Telefonkonferenz Piratenpartei Hessen Raum %04i</description>\n",iRoom);
fprintf(f," <url>http://www.piratenpartei-hessen.de</url>\n");
fprintf(f," </metadata>\n");
fprintf(f," <input>\n");
fprintf(f," <module>stdinpcm</module>\n");
fprintf(f," <param name=\"rate\">8000</param>\n");
fprintf(f," <param name=\"channels\">1</param>\n");
fprintf(f," </input>\n");
fprintf(f," <instance>\n");
fprintf(f," <hostname>localhost</hostname>\n");
fprintf(f," <port>8000</port>\n");
fprintf(f," <password>%s</password>\n",ICEPWD);
fprintf(f," <mount>/raum%04i.ogg</mount>\n",iRoom);
fprintf(f," <yp>0</yp>\n");
fprintf(f," <encode>\n");
fprintf(f," <quality>0</quality>\n");
fprintf(f," <samplerate>8000</samplerate>\n");
fprintf(f," <channels>1</channels>\n");
fprintf(f," </encode>\n");
fprintf(f," <downmix>0</downmix>\n");
fprintf(f," </instance>\n");
fprintf(f," </stream>\n");
fprintf(f,"</ices>\n");
fclose(f);
/* --- Asterisk Call File aufbauen --- */
sprintf(wBuf,"%s/raum%04i.call",ASTOUT,iRoom);
if ((f=fopen(wBuf,"w"))==NULL) return;
fprintf(f,"Channel: LOCAL/81%04i\n",iRoom);
fprintf(f,"MaxRetries: 1\n");
fprintf(f,"RetryTime: 15\n");
fprintf(f,"WaitTime: 30\n");
fprintf(f,"Application: Ices\n");
fprintf(f,"Data: %s/raum%04i.xml\n",ASTICE,iRoom);
fprintf(f,"Callerid: Stream <0>\n");
fprintf(f,"AlwaysDelete: Yes\n");
fclose(f);
}
void DelRecord(int iRoom)
{
sprintf(wBuf,"%s/raum%04i.gsm",ASTMON,iRoom);
unlink(wBuf);
}
void Record(int iRoom)
{
FILE *f;
/* --- Asterisk Call File aufbauen --- */
sprintf(wBuf,"%s/raum%04i.call",ASTOUT,iRoom);
if ((f=fopen(wBuf,"w"))==NULL) return;
fprintf(f,"Channel: LOCAL/81%04i\n",iRoom);
fprintf(f,"MaxRetries: 1\n");
fprintf(f,"RetryTime: 15\n");
fprintf(f,"WaitTime: 30\n");
fprintf(f,"Application: Record\n");
fprintf(f,"Data: %s/raum%04i.gsm|0|18000|x\n",ASTMON,iRoom);
fprintf(f,"Callerid: Record <0>\n");
fprintf(f,"AlwaysDelete: Yes\n");
fclose(f);
}
int main(int argc, char **argv)
{
char *sCmd,*sRoom,*sPin,*sUser;
int iRoom,iPin;
int i,j;
if (argc<4) { showHelp(); exit(1); }
sCmd=argv[1];
sRoom=argv[2];
for (i=0; isdigit(sRoom[i]); i++);
if (i<1 || i>4 || sRoom[i]!=0) { exit(1); }
iRoom=atoi(sRoom);
sPin =argv[3];
for (i=0; isdigit(sPin[i]); i++);
if (i<1 || i>10 || sPin[i]!=0) { exit(1); }
iPin =atoi(sPin);
if (iRoom<1000||iRoom>9999||iPin<1) { exit(1); }
if (!checkAdmin(iRoom,iPin))
{
exit(1);
}
if (!strcmp(sCmd,"test")) exit(0);
if (!strcmp(sCmd,"lock") ||
!strcmp(sCmd,"unlock") )
{
Cmd(sCmd,sRoom,NULL);
exit(0);
}
if (!strcmp(sCmd,"list"))
{
Cmd(sCmd,sRoom,"concise");
exit(0);
}
if (!strcmp(sCmd,"mute") ||
!strcmp(sCmd,"unmute") ||
!strcmp(sCmd,"kick") )
{
for (j=4; j<argc; j++)
{
sUser=argv[j];
if (strcmp(sUser,"all"))
{
for (i=0; isdigit(sUser[i]); i++);
if (i<1 || i>4 || sUser[i]!=0) { exit(1); }
}
Cmd(sCmd,sRoom,sUser);
}
return(0);
}
if (!strcmp(sCmd,"stream"))
{
Stream(iRoom);
exit(0);
}
if (!strcmp(sCmd,"record"))
{
Record(iRoom);
exit(0);
}
if (!strcmp(sCmd,"delrecord"))
{
DelRecord(iRoom);
exit(0);
}
showHelp();
exit(1);
}
Installation Asterisk
Da die Konferenzfunktion "meetme" in Asterisk nur aktiviert wird, wenn beim Compilieren das Kernelmodul "DAHDI" und die dazugehörigen Tools installiert sind, wird das Asterisk-Paket aus der Source erstellt:
Vorbedingungen: Folgendes muß installiert sein:
- Kernel-Source
- wget
- gcc
- make
- ncurses-dev
- libssl-dev
- doxygen
DAHDI-Kernelmodul:
Quelle: http://downloads.asterisk.org/pub/telephony/dahdi-tools/dahdi-tools-current.tar.gz
make sodu make install
DAHDI-Tools:
Quelle: http://downloads.asterisk.org/pub/telephony/dahdi-tools/dahdi-tools-current.tar.gz
./configure --prefix=/opt/dahdi make sodu make install
Asterisk:
Quelle: http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-1.4-current.tar.gz
Erstellen:
./configure --prefix=/opt/asterisk --localstatedir=/opt/asterisk/var --sysconfdir=/opt/asterisk/etc --with-dahdi=/opt/dahdi make sodu make install sodu make progdocs
Deutsche Sprachprompts:
Quelle: http://www.greenable.de/downloads/core-prompts-DE-greenable.tar.gz
Der Inhalt muß auf die folgende Untererzeichnisse von /opt/asterisk/var/lib/asterisk/sound/ verteilt werden:
- de
- de/dictate
- de/digits
- de/followme
- de/letters
- de/phonetic
Weitere Sprachprompts:
Italienisch: http://www.voip.ammdomus.it/pub/asterisk-core-sounds-it-gsm-1.4.15-mm20090405.tar.gz
Schwedisch: http://www.danielnylander.se/asterisk/asterisk-prompt-se_1.045-orig.tar.gz
Russisch: http://ivrvoice.ru/downloader/download/file/7
Anschliessend sollte noch eine Group "phone" und ein User "asterisk" angelegt werden und die Rechte auf /opt/asterisk/... so angepasst werden, dass asterisk alles lesen und auf Unterverzeichnissen von /opt/asterisk/var (ausser lib) schreiben darf. Andere User sollten zumindestens auf /opt/asterisk/etc keine Leserechte haben, da dort Zugangsdaten hinterlegt sind.
Startscripte für verschiedene Systeme sind auf dem Asterisk Source-Verzeichnis unter contrib/init.d vorhanden. Es müssen darin dann noch Anpassungen vorgenommen werden um den Prozess als User:Group asterisk:phone und auf dem Verzeichnis /opt/asterisk gestartet wird.
Abschliessend sollten noch je nach persönlicher Preferenz auf /opt/asterisk/var/lib/asterisk/moh Musikdateien im WAV-Format hinterlegt werden.
