HE   Diskussion   Quelltext anzeigen   Versionen/Autoren   

HE:Telefonkonferenz

Aus Piratenwiki

Wechseln zu: Navigation, Suche

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 

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' &nbsp'
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.

Persönliche Werkzeuge
Werkzeuge