APPENDICE A
Alcuni chiarimenti sono necessari per capire come avviene l' annuncio di sesione tramite SDR e il controllo remoto del Vic e del Vat del generico partecipante da parte del moderatore.
Abbiamo scritto dei plugin per SDR che consentono di arricchire l'annuncio di sessione con il controllore descritto in questo lavoro con nuovi attributi per Vic eVat. All'arrivo dell'annuncio SAP/SDP SDR locale legge nei vari campi il tipo di sessione, i media impiegati e gli attributi associati a questi ultimi; gli attributi non sono altro che campi particolari d'informazione inseriti nell'annuncio. Tali atributi possono essere creati a piacimento dall'utente tramite plugine informano il ricevente, se anche questo possiede lo stesso plugin ed è quindi in grado di riconoscere gli attributi stessi, con quali particolari modalità avviare i tools.
Nel nostro caso, dal momento che Concontrol comunica con Vic e Vat sul canale 1 del Conference Bus, quando arriva l'annuncio di sessione contenete il nome del nostro controllore, che si appoggia come noto a Confcontrol, dobbiamo fare in modo che SDR avvii sia Vic che Vat in modo opportuno.
I tools appena citati possono essere avviati da linea di comando con alcune opzioni; fra queste abbiamo il canale all'interno del Conference Bus sul quale scambiarsi messaggi di gestione (opzione -I) e il file sorgente contenente particolari istruzioni (opzione -u).
[alec@genni vittorio]$ ./vat -I 1 -u/home/vittorio/vitvat 239.0.0.0/1234
Vic e Vat possono venire arrichiti con procedure Tcl Tk che si trovano in questo file sorgente e l'utente stesso può scrivere nuove linee di codice per modificare il tool.
Avendo visto che Confcntlr al suo avvio genera questo tipo di file, che permette così sia a Vic che a Vat di riconoscere il formato dei messaggi di Confcntlr e comportarsi di conseguenza, abbiamo pensato di modificare il file per impostare i tools con particolari parametri; abbiamo infatti disabilitato il “grab” dell'utente (ovvero l'effetto del click del mouse dell'utente è disattivato) sul tasto di trasmissione di Vic e Vat; tramite una nuova procedura scritta appositamente da me nel file sorgente l'unico modo per attivare la trasmissione è ricevere un messaggio di “transmit” da parte di Confcntlr. In questo modo il generico partecipante all'avvio dei propri tool, che avviene cliccando il tasto di “JOIN” sull'annuncio di SDR, non può trasmettere ma non può nemmeno attivare la trasmissione attraverso il proprio Confcntlr perchè abbiamo disabilitato il grab dell'ut-ente sul pannello di comando dei tools locali. Solo il moderatore può comunicare da
remoto al Confcntlr locale il quale poi ritrasmette il messaggio a Vic e Vat facendo partire o fermando la trasmissione.
Un altro aspetto fondamentale della questione riguarda la gerarchia del controllo all'interno di un gruppo gestito da Confcntlr. Se tutti i Confcntlr fossero paritetici qualsiasi partecipante potrebbe alterare la trasmissione degli altri in quanto ogni Confcntlr potr ebbe mettersi in contatto con gli altri. Il problema è stato risolto nel seguente modo: Confcntlr possiede una lista di autorizzazione contenente i nomi di coloro che noi voglia mo autorizzare ad apportare modifiche. All'avvio del nostro controllore questi prima di lanciare Confcntlr scrive un file di configurazione per quest'ultimo nel quale per ogni partecipante l'unica persona autorizzata ad apportare modifiche ai tools tramite Confcn tlr è il moderatore. In tal maniera l'ascoltatore non può inviare dati all'interno del gruppo multicast fino a che il moderatore non gli dà la parola.
APPENDICE B
Si riportano per completezza in questa appendice i listati Tcl/Tk. Il primo si riferisce all'applicazione in modalità MODERATORE il secondo alla modalità ASCOLTATORE. I due file contenenti rispettivamente i due listati sono caricati dinamicamente a runtime dall'applicazione: se la variabile che contiene lo stato di moderatore è pari a uno si carica il file contenente il listato 1, altrimenti viene caricato il file del listato 2
Listato n.1 (moderatore)
.....................................................................
proc heartbeat {urgente} {
global Listarefresh ListaEvase Lista1 Lista2 Mioaddress giacenti timer t_min t_max\
counter2 buff OnAir
puts "$timer"
if {$giacenti == 1} {
foreach i $Listarefresh {
scan "[.members2 get $i]" "%s %s %s %s %s" count name address Ns_List stato
set question "$Lista2($i)"
Update_Tx $name $Ns_List $question $count $stato
}
set giacenti 0
set Listarefresh [lreplace $Listarefresh 0 end]
} else {
Blink_Tx 1
}
foreach i $buff {
scan "[.members2 get $i]" "%s %s %s %s %s" count name address Ns_List stato
set question "$Lista2($count)"
if {"$stato" == "ok"} {
Update_Tx $name $Ns_List $question $count $stato
} else {
set stato "EVASA!!!!"
Update_Tx $name $Ns_List $question $count $stato
}
}
set buff [lreplace $buff 0 end]
if {$counter2 > 0} {
scan "[.members2 get [expr $counter2 -1]]" "%s %s %s %s %s" count name address Ns_List stato
set question "$Lista2($count)"
puts "$stato"
Update_Tx $name $Ns_List $question $count $stato
}
if {$OnAir != -1} {
scan "[.members2 get $OnAir]" "%s %s %s %s %s" count name address Ns_List stato
Onair_Tx $name $count
}
if {$urgente == 1} {
set timer $t_min
} else {
if {$timer > $t_max} {
set timer $t_min
} else {
set timer [expr $timer + [random [ expr $timer*2]]]
}
}
after $timer {heartbeat 0}
}
#su ricezione di un messaggio di bye del listener cancella quest'ultimo dalla lista degli iscritti#
proc Bye {name} {
global Lista1 counter1 counter2
set lista_da_cance {}
for {set i 0} {$i < $counter1} {incr i 1} {
scan "[.members1 get $i]" "%s %s %s" nome address Ns_List
if {"$nome" == "$name"} {
puts "$Ns_List"
set lista_da_cance [linsert $lista_da_cance 0 $Ns_List]
}
}
for {set i 0} {$i < $counter2} {incr i 1} {
scan "[.members2 get $i ]" "%s %s %s %s" count nome address Ns_List
if {"$nome" == "$name"} {
set lista_da_cance [linsert $lista_da_cance 0 $Ns_List]
}
}
foreach i [set lista_da_cance] {
Erase $name $i
}
}
#su ricezione di una richiesta di cancellazione di una domanda elimina quest'ultima#
proc Erase {name Ns_List} {
global Lista1 counter1 counter2 ListaEvase
for {set i 0} {$i < $counter1} {incr i 1} {
scan "[.members1 get $i]" "%s %s %s" nome address num_lis1
if {("$nome" == "$name") && ("$Ns_List" =="$num_lis1")} {
Cancel .members1 "[.members1 get $i]" $i
}
}
for {set i 0} {$i < $counter2} {incr i 1} {
scan "[.members2 get $i]" "%s %s %s %s" count nome address num_lis2
if {("$nome" == "$name") && ("$Ns_List" =="$num_lis2")} {
Cancel .members2 "[.members2 get $i]" $i
}
}
}
#chiamata dal prog in modalita MODERATOR, estrae dal socket, aperto precedentemente come server, un stringa, legge la prima parte#
#che contiene il tipo di messaggio e i parametri da aggiornare e poi esegue l' operazione relativa.
proc Controlla {channel a b} {
set buff "[gets $channel]"
set position [expr [string first # "$buff"] +1]
set question "[string range "$buff" $position end]"
scan "$buff" "%s %s %s %s " Comando name ipaddress Ns_List
if {$Comando == "Record1"} {$Comando $name $ipaddress $Ns_List $question}
if {$Comando == "Bye"} {$Comando $name}
if {$Comando == "Erase"} {
scan "$buff" "%s %s %s" $Comando name Ns_List
$Comando $name $Ns_List
}
}
#chiamata dal prog in modalita MODERATOR, crea una lista di richieste in cui le chiavi di accesso sono il nome e il num di domanda Ns_List del listener#
proc Record1 {name ipaddress Ns_List question} {
global Lista1 counter1
set Lista1($name,$Ns_List) $question
incr counter1 1
update1 $name $Ns_List $ipaddress
}
#chiamata dal MODERATOR approva sposta una domanda dalla listbox giacenze a quella approvate#
proc approva {string index} {
global Lista1 Lista2 ultimapprovata Listarefresh timer counter1 counter2 buff
scan "$string" "%s %s %s" name address Ns_List
.members1 delete $index $index
set buff [linsert $buff 1 $ultimapprovata]
set Lista2($ultimapprovata) "$Lista1($name,$Ns_List)"
set stato "ok"
.members2 insert end "$ultimapprovata $name $address $Ns_List $stato"
incr ultimapprovata 1
incr counter2 1
incr counter1 -1
after cancel [after info]
after 5000 heartbeat 1
}
proc Refresh {args} {
global Listarefresh ListaEvase giacenti counter2
foreach i $args {
if {[lsearch $Listarefresh $i] < 0} {
set Listarefresh [linsert $Listarefresh 1 $i]
set giacenti 1
}
}
}
proc update1 {name Ns_List address} {
.members1 insert end " $name $address $Ns_List"
}
#nel comando successivo, utilizzato dal MODERATOR, string contiene il nome e il numero di domanda relativa al nome da cancellare#
proc Cancel { w string index} {
global Lista1 Lista2 counter1 counter2 Listarefresh giacenti ListaEvase
$w delete $index
if {"$w" == ".members1"} {
scan "$string" "%s %s %s" name address Ns_List
unset Lista1($name,$Ns_List)
incr counter1 -1
} else {scan "$string" "%s %s %s %s" count name address Ns_List
set stato "EVASA!!!!"
$w insert $index "$index $name $address $Ns_List $stato"
$w itemconfigure $index -foreground grey
if {[lsearch $Listarefresh $index] < 0} {
set Listarefresh [linsert $Listarefresh 1 $index]
set ListaEvase [linsert $ListaEvase 0 $index]
set giacenti 1
}
}
}
proc Send_On_Air {w string index} {
global OnAir code1
set OnAir $index
set code2 [catch {send {tk #2} {getParams 1 settings}}]
set code1 [catch {send {tk #2} {set rsess1(transmit) 1}}]
set code1 [catch {send {tk #2} {set rsess3(talk) 1}}]
set code1 [catch {send {tk #2} {setting_changed "transmit" 1 0}}]
set code1 [catch {send {tk #2} {setting_changed "talk" 3 0}}]
$w itemconfigure $index -background red -selectbackground red
}
proc Send_Off_Air {w string index} {
global OnAir code2
Cancel $w $string $index
$w itemconfigure $index -foreground grey
set code2 [catch {send {tk #2} {set rsess1(transmit) 0}}]
set code2 [catch {send {tk #2} {set rsess3(talk) 0}}]
set code2 [catch {send {tk #2} {setting_changed "transmit" 1 0}}]
set code2 [catch {send {tk #2} {setting_changed "talk" 3 0}}]
set OnAir -1
}
#Questa proc si incarica di leggere la riga della listbox passata in string e di visualizzare in una finestra di dialogo (proc dialog) le info#
#relative all ' utente e al suo num di domanda che compare in quella riga#
proc visualizza {string tipo} {
global Lista1
if {$tipo == 1} {
scan "$string" "%s %s %s" name address Ns_List
dialog .d {QUESTION INFORMATION} " $name $address question n. $Ns_List: \n\n$Lista1($name,$Ns_List)\n\n Do you want to approve?" \
{YES} {CANCEL} {SEE LATER}
}
if {$tipo == 2} {
scan "$string" "%s %s %s %s" count name address Ns_List
dialog .d {CURRENTLY APPROVED} "$name $address question n. $Ns_List: \n\n$Lista1($name,$Ns_List)\nALLOW SPEAKING?"\
{YES} {NO} {EVADE}
}
if {$tipo == 3} {
scan "$string" "%s %s %s %s" count name address Ns_List
dialog .d {ON AIR} "$name $address question n. $Ns_List: \n\n$Lista1($name,$Ns_List)\n STOP IT?"\
{YES} {NO}
}
}
proc dialog {w title text args} {
global Lista1 button
# crea la finestra e la divide in due parti: quella sup e quella inf
toplevel $w -class Dialog
wm title $w $title
wm iconname $w Dialog
frame $w.top -relief raised -bd 1
pack $w.top -side top -fill both
frame $w.bot -relief raised -bd 1
pack $w.bot -side bottom -fill both
#scrive sulla finestra sup il messaggio
message $w.top.msg -width 3i -text $text\
-font -Adobe-Times-Medium-R-Normal-*-180-*
pack $w.top.msg -side right -expand 1 -fill both\
-padx 3m -pady 3m
#crea la fila di bottoni in fondo alla dialog box; stabilisce il grab e il focus
set i 0
foreach but $args {
button $w.bot.button$i -text $but -command\
"set button $i"
pack $w.bot.button$i -side left -expand 1\
-padx 3m -pady 3m -ipadx 2m -ipady 1m
incr i
}
if {"$title" == "QUESTION INFORMATION"} {
bind $w.bot.button0 <Button-1> {approva [.members1 get [.members1 index active]] [.members1 index active]}
bind $w.bot.button1 <Button-1> {Cancel .members1 [.members1 get [.members1 index active]] [.members1 index active]}
}
if {"$title" == "CURRENTLY APPROVED"} {
bind $w.bot.button0 <Button-1> {Send_On_Air .members2 [.members2 get [.members2 index active]] [.members2 index active]}
bind $w.bot.button2 <Button-1> {Cancel .members2 [.members2 get [.members2 index active]] [.members2 index active]}
}
if {"$title" == "ON AIR"} {
bind $w.bot.button0 <Button-1> {Send_Off_Air .members2 [.members2 get [.members2 index active]] [.members2 index active]}
}
set oldFocus [focus]
tkwait visibility $w
grab set $w
focus $w
#aspetta la risposta , quindi ripristina il focus e ritorna il numero del bottone selezionato
tkwait variable button
destroy $w
focus $oldFocus
return $button
}
global Lista1 Lista2 mioaddress Myname Mioaddress floorholder Listarefresh counter1 counter2\
ultimapprovata timer t_min t_max canale giacenti ListaEvase buff OnAir pid1
set counter1 0
set counter2 0
set ultimapprovata 0
set buff {}
set Listarefresh {}
set ListaEvase {}
set giacenti 0
set timer 5000
set t_min 5000
set t_max 10000
set OnAir -1
makesocket
frame .titolo -relief raised -bd 2
label .titolo.gino -text "Conference :IL MODERATORE SONO IO" -background red
button .titolo.daiparola -text "START CONFCNTLR" -background LemonChiffon1
scrollbar .scroll1 -command ".members1 yview"
listbox .members1 -relief raised -borderwidth 2 \
-yscrollcommand ".scroll1 set"
scrollbar .scroll2 -command ".members2 yview"
listbox .members2 -relief raised -borderwidth 2 \
-yscrollcommand ".scroll2 set"
pack .titolo -side top -fill x
pack .titolo.gino -side left -fill x
pack .titolo.daiparola -side left -fill x
pack .members1 -side left -fill both -expand true
pack .scroll1 -side left -fill y
pack .members2 -side left -fill both -expand true
pack .scroll2 -side left -fill y
bind .members1 <Button-2> { visualizza [.members1 get [.members1 index active]] 1}
bind .members2 <Button-2> {if {([lsearch $ListaEvase [.members2 index active]]) < 0} {
if {[.members2 index active] != $OnAir} {
visualizza [.members2 get [.members2 index active]] 2
} else {visualizza [.members2 get [.members2 index active]] 3
}
}
}
bind .titolo.daiparola <Button-1> {set pid1 [exec /home/vittorio/confcntlr/confcntlr &]}
socket -server Controlla 1600
random seed 2341
heartbeat 1
.....................................................................
fine listato n.1
Listato n.2 (ascoltatore)
.....................................................................
proc lampeggia { w option value1 value2 interval} {
global contatoreBlink idBlink
if {$contatoreBlink > 0 } {
$w config $option $value1
incr contatoreBlink -1
set idBlink [after $interval [list lampeggia $w $option $value2 $value1 $interval]]
} else {
after cancel $idBlink
}
}
proc Blink { } {
global contatoreBlink
set contatoreBlink 6
set option "-background"
set value1 "blue"
set value2 "white"
lampeggia .titolo.mod $option $value1 $value2 1000
}
proc Update { args } {
global Lista1 ListaRefresh ultimapprovata Lista2 ListaRicevute timer_min Num_Retry
set num [llength $args]
set name [lrange $args 0 0]
set Ns_List [lrange $args 1 1]
set question [lrange $args 2 [expr $num - 3]]
set Ns_M [lrange $args [expr $num - 2] [expr $num - 2] ]
set stato [lrange $args end end]
set Num_Retry 0
if {($Ns_M > $ultimapprovata)} {
set ultimapprovata $Ns_M
}
if {[lsearch $ListaRicevute $Ns_M] < 0} {
set ListaRicevute [linsert $ListaRicevute 1 $Ns_M]
set Lista2($Ns_M) $question
.members2 insert $Ns_M "$Ns_M $name $Ns_List $stato"
} else {
if { "$stato" == "EVASA!!!!"} {
.members2 delete $Ns_M
.members2 insert $Ns_M "$Ns_M $name $Ns_List $stato"
}
}
UpdateRef $Ns_M
}
proc UpdateRef {Ns_M } {
global ListaRefresh ListaRicevute Marcate ultimapprovata Lista2 idRefresh
if {[lsearch $ListaRefresh $Ns_M] != -1} {
set index [lsearch $ListaRefresh $Ns_M]
set ListaRefresh [lreplace $ListaRefresh $index $index ]
}
if {[lsearch $Marcate $Ns_M] != -1} {
set index [lsearch $Marcate $Ns_M]
set Marcate [lreplace $Marcate $index $index ]
}
for {set i 0} {$i < $ultimapprovata} {incr i 1} {
if {[lsearch $ListaRicevute $i] < 0 } {
set ListaRefresh [linsert $ListaRefresh 1 $i]
}
}
if {([llength $ListaRefresh] != 0) && ($idRefresh < 0)} {
set idRefresh [after $timer_min [list Ask_Refresh]]
} else {
after cancel $idRefresh
}
}
proc Ask_Refresh { } {
global ListaRefresh Marcate Mioaddress timer_min timer_max timer Num_Retry Num_Retry_Max
Refresh_Tx $Mioaddress $ListaRefresh
set ListaRefresh [concat $Listarefresh $Marcate]
incr Num_Retry 1
if {($Num_Retry > $Num_Retry_Max)} {
if {($timer > $timer_max)} {
set timer $timer_min
} else {
set timer [expr $timer + [random [expr $timer_max - $timer_min]]]
}
after $timer [list Ask_Refresh]
puts "$timer"
}
}
proc Refresh { address args} {
global ListaRefresh Marcate idRefresh Mioaddress
if {"$address" != "$Mioaddress"} {
foreach i [lrange $args 1 end] {
if {[lsearch $ListaRefresh $i] >= 0} {
set Marcate [linsert $Marcate 1 $i]
set index [lsearch $ListaRefresh $i]
set ListaRefresh [lreplace $ListaRefresh $index $index]
}
}
if {[llength ListaRefresh] == 0} {
after cancel $idRefresh
}
}
puts "$ListaRefresh"
}
proc dialog {w title text args} {
global Lista1 button
# crea la finestra e la divide in due parti: quella sup e quella inf
toplevel $w -class Dialog
wm title $w $title
wm iconname $w Dialog
frame $w.top -relief raised -bd 1
pack $w.top -side top -fill both
frame $w.bot -relief raised -bd 1
pack $w.bot -side bottom -fill both
#scrive sulla finestra sup il messaggio
message $w.top.msg -width 3i -text $text\
-font -Adobe-Times-Medium-R-Normal-*-180-*
pack $w.top.msg -side right -expand 1 -fill both\
-padx 3m -pady 3m
#crea la fila di bottoni in fondo alla dialog box; stabilisce il grab e il focus
set i 0
foreach but $args {
button $w.bot.button$i -text $but -command\
"set button $i"
pack $w.bot.button$i -side left -expand 1\
-padx 3m -pady 3m -ipadx 2m -ipady 1m
incr i
}
if {"$title" == "QUESTION INFORMATION"} {
bind $w.bot.button0 <Button-1> {Cancel [.members1 get [.members1 index active]] [.members1 index active]}
}
set oldFocus [focus]
tkwait visibility $w
grab set $w
focus $w
#aspetta la risposta , quindi ripristina il focus e ritorna il numero del bottone selezionato
tkwait variable button
destroy $w
focus $oldFocus
return $button
}
proc Cancel {string index} {
global Lista1 Myname Mioaddress floorholder
scan "$string" "%s %s %s %s" 1 2 3 Ns_List
.members1 delete $index $index
unset Lista1($Ns_List)
set fd [socket -async $floorholder 1600]
puts $fd "Erase $Myname $Ns_List"
flush $fd
close $fd
}
proc visualizza {string tipo} {
global Lista1 Lista2
if {$tipo == 0} {
scan "$string" "%s %s %s %s" 1 2 3 Ns_List
dialog .d {QUESTION INFORMATION} "QUESTION N. $Ns_List : $Lista1($Ns_List)\n\n\n Do you want to cancel?\n"\
{YES} {NO}
}
if {$tipo == 1} {
scan "$string" "%s %s %s" Ns_M name Ns_List
dialog .e {CURRENTLY APPROVED} "$name question:\n $Lista2($Ns_M)\n\n"\
{OK}
}
}
proc Submit {} {
global floorholder Myname Mioaddress question counter1 Ns_List ok Lista1
set ok 0
button .butt1 -text "SEND"
button .butt2 -text "NOT SEND"
entry .entry -width 20 -relief sunken -bd 2 -textvariable question
pack .entry -side left -padx 1m -pady 2m
pack .butt1 -side left
pack .butt2 -side left
bind .butt1 <Button-1> {
set fd [socket -async $floorholder 1600]
puts $fd "Record1 $Myname $Mioaddress $Ns_List #$question"
if {[catch {flush $fd}] == 0} {
incr Ns_List 1
incr counter1 1
dialog .f {NOTIFICATION} "Your Request has been SUCCESFULLY DELIVERED to the moderator" {OK}
set Lista1($Ns_List) $question
.members1 insert end "My question number $Ns_List"
} else {
dialog .f {NOTIFICATION} "CANNOT CONTACT MODERATOR" {OK}
}
close $fd
set ok 1 }
bind .butt2 <Button-1> {set ok 1}
tkwait variable ok
if {$ok == 1 } {
destroy .entry .butt1 .butt2
}
}
proc Leave_conf {} {
global floorholder Myname counter1
set fd [socket -async $floorholder 1600]
puts $fd "Bye $Myname"
catch { flush $fd }
close $fd
exit
}
global Myname Mioaddress floorholder counter1 Num_Retry Num_Retry_Max ok contatoreBlink timer_min timer_max timer idRefresh \
Lista1 Lista2 ListaRicevute ListaEvase Ns_List ultimapprovata ListaRefresh Marcate pid1 code
set ListaRicevute { }
set ListaEvase { }
set ListaRefresh { }
set Marcate { }
set pid1 { }
set contatoreBlink 0
set counter1 0
set Ns_List 0
set Num_Retry 0
set Num_Retry_Max 10
set ultimapprovata 0
set timer_min 5000
set timer 5000
set timer_max 15000
set idRefresh -1
frame .titolo -relief raised -bd 2
label .titolo.gino -text "Conference : MODERATOR is $floorholder" -background red
label .titolo.mod -text "Moderator is present" -background white
button .titolo.b -text "SUBMIT" -background yellow
button .titolo.d -text "LEAVE" -background yellow
frame .mbar -relief raised -bd 2
scrollbar .scroll1 -command ".members1 yview"
listbox .members1 -relief raised -borderwidth 2 \
-yscrollcommand ".scroll1 set" -selectbackground red
scrollbar .scroll2 -command ".members2 yview"
listbox .members2 -relief raised -borderwidth 2 \
-yscrollcommand ".scroll2 set"
pack .titolo -side top -fill x
pack .titolo.b -side left
pack .titolo.gino -side left -fill x
pack .titolo.d -side right
pack .titolo.mod -side right
pack .members1 -side left -fill both -expand true
pack .scroll1 -side left -fill y
pack .members2 -side left -fill both -expand true
pack .scroll2 -side left -fill y
bind .members1 <Button-2> {visualizza [.members1 get [.members1 index active]] 0}
bind .members2 <Button-2> { visualizza [.members2 get [.members2 index active]] 1}
bind .titolo.b <Button-1> {Submit}
bind .titolo.d <Button-1> { Leave_conf }
makesocket
random seed 1458
........................................................
fine listato n.2
1) Fourozan,A.b., “ I PROTOCOLLI TCP/IP.” McGraw-Hill, via
Ripamonti 89 20139 Milano (2001)
2) Kerningan, B.W., Dennis,M.R., “THE C PROGRAMMING
LANGUAGE” Prentice Hall Inc., NJ 07632 (1988)
3) Halsall, F., “MULTIMEDIA COMMUNICATION” Addison-Wesley,
Reading 01867 Ma. (2001)
4)Network Working Group, “A TRANSPORT PROTOCOL FOR REAL
TIME APPLICATION , (rfc 1889) (Jan. 1996)
5) Network Working Group, “RTP PROFILE FOR AUDIO AND VIDEO-
CONFERENCES WITH MANUAL CONTROL”, (rfc 1890) (Jan. 1996)
6) Ousterhout, J. K., “TCL AND TK TOOLKIT”, Addison-Wesley,
Reading 01867 Ma. (1994)
7) Perry, Marcia, “CONFONTROL, A CONFERENCE CONTROLLER”,
reperibile presso il sito internet: http://www-itg.lbl.gov/mbone/confcntlr/
8) Sally Floyd, Van Jacobson, Steve Mc Canne, and Lixia Zhang, “A
RELIABLE MULTICAST FRAME WORK FOR LIGHTWEIGHT
SESSION AND APPLICATION LEVEL FRAMING”,
[draft Transaction On Networking] (December 1997)
9) Stevens, W. Richards, “UNIX NETWORKING PROGRAMMING”,
Prentice Hall Inc., NJ 07458, (1998)
10) Welch, B., “PRACTICAL PROGRAMMING IN TCL TK”, [draft
1995],reperibile presso il sito internet:
http://www.Sunlabs.com/~bwelch/book/index
SITI INTERNET
Si segnalano per completezza i siti internet di maggior interesse che hanno contribuito allo svolgimento del presente lavoro
http://www-nrg.ee.lbl.gov/vic/
http://www-nrg.ee.lbl.gov/vat/
http://www-mice.cs.ucl.ac.uk/multimedia/software/sdr/
http://www.fokus.gmd.de/research