User:Deej: Difference between revisions

From WolfWiki
Jump to navigation Jump to search
Deej (talk | contribs)
mNo edit summary
Deej (talk | contribs)
m tweaked oldschool script a bit
 
(8 intermediate revisions by the same user not shown)
Line 34: Line 34:




If you remember that an ETTV server connects at an ''unlimited rate'' to another server, you might see a problem arising when lots of people would like to see a "big match".
If you remember that an ETTV server connects at an ''unlimited rate'' to another server, and as from ETTV b9 the slaves are in fact not limited at all by the original ET netcode, you might see a problem arising when lots of people would like to see a "big match".




Line 68: Line 68:




'''How do you use this script?''' Copy / paste this script and save it as <code>hub.sh</code> or any other name you prefer. Then use <code>./hub.sh start</code> to start and <code>./hub.sh stop</code> to stop your hub.
'''How do you use this script?''' Copy / paste this script and save it as <code>hub.sh</code> or any other name you prefer. Then use <code>./hub.sh start</code> to start and <code>./hub.sh stop</code> to stop your hub. The script generates the server.cfg dynamically every time you start it. If you just want to generate server.cfg do <code>./hub.sh sim</code>.




Line 78: Line 78:
#################################################################
#################################################################
#                                                              #
#                                                              #
#               reT!reD.ettv delayed hub script                 #
#                   ettv delayed hub script                   #
#                            -                                #
#                            -                                #
#                       reT!reD.deej                          #
#                           deej.                               #
#                                                              #
#                                                              #
#################################################################
#################################################################
Line 93: Line 93:
#  This script creates a subdirectory which represents the      #
#  This script creates a subdirectory which represents the      #
#  date of the match and stores the demos in this subdir.      #
#  date of the match and stores the demos in this subdir.      #
#                                                              #
#  The script generates etmain/server.cfg dynamically.          #
#                                                              #
#                                                              #
#  The script launches the daemon in a different screen        #
#  The script launches the daemon in a different screen        #
Line 100: Line 102:
#  - Daita (pourix.net) for the original idea & script          #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - aNgel (fragland.org) for debugging Beavis' mistakes ;-)    #
#                                                              #
#                                                              #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
#                                                              #
#################################################################
#                                                              #
#                  http://www.fragland.org                    #
#                                                              #
#                                                              #
#################################################################
#################################################################
Line 123: Line 120:


# Hetzner Game Server IP
# Hetzner Game Server IP
# WServer2.ath.cx IP
# ettv4.fragland.org
# ettv4.fragland.org
HETZNER_IP="213.239.207.195"
HETZNER_IP="213.239.207.195"
Line 145: Line 141:
# account for the majority of crashes of ETTV.
# account for the majority of crashes of ETTV.
#
#
MATCH_DATE=`date +%Y%m%d` # Do NOT modify
MATCH_DATE=`date +%Y%m%d` # Do NOT modify
MATCH_HOST="et.fragland.org:27965" # Match server port & address
MATCH_HOST="et.fragland.org:27965" # Match server port & address
MATCH_ETTV_PASS="[get_pass_from_admin]" # Match server ETTV password
MATCH_ETTV_PASS="[get_pass_from_admin]" # Match server ETTV password
MATCH_PASS="[get_pass_from_admin]" # Match server password
MATCH_PASS="[get_pass_from_admin]" # Match server password
 
MATCH_HOME_TEAM="uQ" # Making our hostname more fancy ;-)
MATCH_AWAY_TEAM="Logitech"
MATCH_CUP="Warleagues"


#
#
# IPs & Ports For Your Host
# IPs & Ports For Your Host
#
#
THISHOST_IP=$PERONI_IP # Replace with your IP
HUB_IP="$PERONI_IP" # This host is Webperoni
HUB_PORT="50000" # Port of the public hub for ETTV slaves
HUB_PORT="30000" # Port of public hub for ETTV slaves


#
#
Line 163: Line 163:
#  of your server in the game server.
#  of your server in the game server.
#
#
HUB_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^7hub ^1#^71"
ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^7hub ^1#^71"
ETTV_CLIENT=$HUB_HOSTNAME
HUB_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"


#
#
Line 177: Line 177:
# Directories
# Directories
#
#
BASEPATH="/srv/et/ETTV/ettv_hub" # Path to ettv.x86. Use absolute paths!
BASEPATH="/srv/et/ETTV/ettv_hub" # Use absolute paths here!


#
#
# ETTV Net settings for ETTV b8 & up
# ETTV Net settings for ETTV b8 & up
#
#
ETTV_NETBLAST="1" # Sends all packets as one big one
ETTV_NETBLAST="1"
ETTV_TV_IPTOS="0"
ETTV_TV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_MTU="1400" # Can be increased to avoid fragmentation
ETTV_MTU="1400"


#
#
# Other relevant ETTV settings
# Other relevant ETTV settings
#
#
SHOUTCAST_DELAY="60" # Delay between live match & broadcasting hub in seconds
HUB_DELAY="1" # Delay between live match & hub in seconds
HUB_SLAVES="8" # 1 ETTV slave connects at an UNLIMITED rate to the hub!
HUB_SLAVES="8" # 1 ETTV slave connects at an UNLIMITED rate!
ALLOW_DL="0" # Allow downloading (only works for viewers on slaves)
HUB_PRIVATE_SLOTS="0"
ALLOW_WWW_DL="0" # Allow downloading over http?
 
WWW_DL_URL="http://www.yoursite.com" # Do not append a "/" at the end!
RECORD_GAME="1" # Record the game?
 
ALLOW_DL="0" # Slaves don't download from the hub
ALLOW_WWW_DL="0"
WWW_DL_URL="http://www.yoursite.com"


#  
#  
Line 205: Line 209:
# he was created on our systems by us.
# he was created on our systems by us.
#
#
# gamed can not log in. His homedir is equal to the path
# gamed cannot log in. His homedir is equal to the path where
# where all our servers are installed.
# all our servers are installed.
#
#
USER="gamed"
USER="gamed"
Line 215: Line 219:
#                                                              #
#                                                              #
#################################################################
#################################################################
#
# Make sure buffers are high enough!
#
echo "524288" > /proc/sys/net/core/rmem_max
echo "524288" > /proc/sys/net/core/wmem_max
#
#
# Assembling the Command Line
# Assembling the Command Line
#
#
HOMEPATH="$BASEPATH/$MATCH_DATE"
BINARY="ettv.x86"
BINARY="ettv.x86"
DAEMON="$BASEPATH/$BINARY"
DAEMON="$BASEPATH/$BINARY"
HOMEPATH="$BASEPATH/$MATCH_DATE"


HUB_OPTIONS="\
HUB_OPTIONS="\
+set fs_game etpro \
+set fs_game etpro \
+set dedicated 2 \
+set dedicated 2 \
+set net_ip $THISHOST_IP \
+set net_ip $HUB_IP \
+set net_port $HUB_PORT \
+set net_port $HUB_PORT \
+set fs_basepath $BASEPATH \
+set fs_basepath $BASEPATH \
+set fs_homepath $HOMEPATH \
+set fs_homepath $HOMEPATH \
+set com_hunkMegs 128 \
+set com_hunkMegs 128 \
+set g_password $HUB_PASS \
+set sv_maxclients $HUB_SLAVES \
+set rconpassword $HUB_RCON_PASS \
+exec server.cfg"
+set sv_hostname $HUB_HOSTNAME \
+set sv_maxclients $((HUB_SLAVES+2)) \
+set sv_maxRate 25000 \
+set sv_allowDownload $ALLOW_DL \
+set sv_wwwDownload $ALLOW_WWW_DL \
+set sv_wwwBaseURL "$WWW_DL_URL" \
+set sv_wwwDlDisconnected 0 \
+set g_log "hub.log" \
+set logfile 2 \
+set b_ettv_flags 3 \
+set ettv_autorecord 1 \
+set ettv_clientname $ETTV_CLIENT \
+set ettv_sv_maxslaves $HUB_SLAVES \
+set ettv_password $HUB_ETTV_PASS \
+set ettv_netblast $ETTV_NETBLAST \
+set ettv_tv_iptos $ETTV_TV_IPTOS \
+set ettv_sv_iptos $ETTV_SV_IPTOS \
+set ettv_mtu $ETTV_MTU \
+set ettv_delay $SHOUTCAST_DELAY \
+tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS"


#
#
Line 280: Line 269:


echo "ETTV slaves can now connect to your box by issuing:"
echo "ETTV slaves can now connect to your box by issuing:"
echo -e "tv connect $THISHOST_IP:$HUB_PORT $HUB_ETTV_PASS $HUB_PASS\n"
echo -e "tv connect $HUB_IP:$HUB_PORT $HUB_ETTV_PASS $HUB_PASS\n"
}
}


Line 291: Line 280:
echo -n "Shutting Down Hub: "
echo -n "Shutting Down Hub: "
sleep 1
sleep 1
if [ $HUB_PID ]
if [ -n $HUB_PID ]
then
then
kill -3 $HUB_PID
kill -SIGTERM $HUB_PID
echo -e "done."
echo -e "done."
else
else
Line 300: Line 289:


sleep 1
sleep 1
}
create_config (){
#
# Generate etmain/server.cfg
#
TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
echo "//" > $BASEPATH/etmain/server.cfg
echo "// server.cfg generated $TIMESTAMP" >> $BASEPATH/etmain/server.cfg
echo -e "//\n" >> $BASEPATH/etmain/server.cfg
echo "set sv_privateclients $HUB_PRIVATE_SLOTS" >> $BASEPATH/etmain/server.cfg
echo "set sv_maxRate 25000" >> $BASEPATH/etmain/server.cfg
echo -e "set sv_hostname \"$HUB_HOSTNAME\"\n" >> $BASEPATH/etmain/server.cfg
echo "set g_password \"$HUB_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set rconpassword \"$HUB_RCON_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set sv_privatepassword \"$HUB_PRIVATE_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set sv_allowDownload $ALLOW_DL" >> $BASEPATH/etmain/server.cfg
echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $BASEPATH/etmain/server.cfg
echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $BASEPATH/etmain/server.cfg
echo -e "set sv_wwwDlDisconnected 0\n" >> $BASEPATH/etmain/server.cfg
echo "set b_ettv_flags 3" >> $BASEPATH/etmain/server.cfg
echo "set ettv_delay $HUB_DELAY" >> $BASEPATH/etmain/server.cfg
echo "set ettv_autorecord $RECORD_GAME" >> $BASEPATH/etmain/server.cfg
echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_sv_maxslaves \"$HUB_ETTV_SLAVES\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_password \"$HUB_ETTV_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_netblast $ETTV_NETBLAST" >> $BASEPATH/etmain/server.cfg
echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $BASEPATH/etmain/server.cfg
echo "set ettv_sv_iptos $ETTV_SV_IPTOS" >> $BASEPATH/etmain/server.cfg
echo -e "set ettv_mtu $ETTV_MTU\n" >> $BASEPATH/etmain/server.cfg
echo "set b_crashlogpath \"$BASEPATH/etpro\"" >> $BASEPATH/etmain/server.cfg
echo "set g_log \"slave.log\"" >> $BASEPATH/etmain/server.cfg
echo -e "set logfile 2\n" >> $BASEPATH/etmain/server.cfg
echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $BASEPATH/etmain/server.cfg
}
}


Line 328: Line 357:
esac
esac
}
}
 
#
#
# Performing The magic :-)
# Performing The magic :-)
Line 335: Line 364:
case "$1" in
case "$1" in
start)
start)
create_config
hub_start
hub_start
;;
;;
    stop)
stop)
hub_stop
hub_stop
clean_up
clean_up
;;
sim)
create_config
echo -e "\nFollowing config was generated automatically:\n"
cat $BASEPATH/etmain/server.cfg
;;
;;
*)
*)
SCRIPT_NAME=`basename $0`
SCRIPT_NAME=`basename $0`
echo "Usage: $SCRIPT_NAME {start|stop}"
echo "Usage: $SCRIPT_NAME {start|stop|sim}"
exit 1
exit 1
;;
;;
Line 353: Line 388:
=== Slave script ===
=== Slave script ===


This script connects an undelayed slave to a hub (that hopefully delays the signal ;-)). The usage of this script is very similar to the Hub script. Copy / paste it and save it as <code>slave.sh</code> or any other name you prefer. THen issue <code>./slave.sh start</code> to start your slave and <code>./slave.sh stop</code> to stop it. Like above, it is actually better to do quit in the console instead of just killing the slave with this script.
This script connects a delayed or undelayed slave to a Hub or directly to a gameserver. The usage of this script is very similar to the Hub script. Copy / paste it and save it as <code>slave.sh</code> or any other name you prefer. Then issue <code>./slave.sh start</code> to start your slave and <code>./slave.sh stop</code> to stop it. Use <code>./slave.sh sim</code> to only create etmain/server.cfg. Like above, it is actually better to do quit in the console instead of just killing the slave with this script.




Line 360: Line 395:
#################################################################
#################################################################
#                                                              #
#                                                              #
#                 reT!reD.ettv slave script                   #
#                     ETTV slave script                         #
#                            -                                #
#                            -                                #
#                       reT!reD.deej                          #
#                           deej.                               #
#                                                              #
#                                                              #
#################################################################
#################################################################
#                                                              #
#                                                              #
#  This script can be used to start up an ETTV slave to connect #
#  This script can be used to start up an ETTV slave to connect #
#  to a HUB provided by another server.                         #
#  to an ETTV HUB or directly to a game server.                #
#                                                              #
#  The script generates etmain/server.cfg dynamically.          #
#                                                              #
#                                                              #
#  This script launches the daemon in a different screen which  #
#  This script launches the daemon in a different screen which  #
Line 375: Line 412:
#  - Daita (pourix.net) for the original idea & script          #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - aNgel (fragland.org) for debugging Beavis' mistakes ;-)    #
#                                                              #
#                                                              #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
# Questions? deej@fragland.org or go to #gamestv.org           #
#                                                              #
#################################################################
#                                                              #
#                  http://www.fragland.org                     #
#                                                              #
#                                                              #
#################################################################
#################################################################
Line 398: Line 430:


# Hetzner Game Server IP
# Hetzner Game Server IP
# WServer2.ath.cx IP
# ettv4.fragland.org
# ettv4.fragland.org
HETZNER_IP="213.239.207.195"
HETZNER_IP="213.239.207.195"
Line 419: Line 450:
# PK3 mismatches between game server and ETTV hosts
# PK3 mismatches between game server and ETTV hosts
# account for the majority of crashes of ETTV.
# account for the majority of crashes of ETTV.
#
#  
MATCH_DATE=`date +%Y%m%d` # Do NOT modify
MATCH_HOST="et.fragland.org:27965" # HUB / Match server port & address
MATCH_ETTV_PASS="[get_pass_from_admin]" # HUB / Match server ETTV password
MATCH_PASS="[get_pass_from_admin]" # HUB / Match server password


HUB_IP=$PERONI_IP # Hub runs on Webperoni
MATCH_HOME_TEAM="uQ" # Making our hostname more fancy ;-)
HUB_PORT="50000"
MATCH_AWAY_TEAM="Logitech"
HUB_ETTV_PASS="[get_pass_from_hub_admin]"
MATCH_CUP="Warleagues"
HUB_PASS="[get_pass_from_hub_admin]"
HUB_HOST="$HUB_IP:$HUB_PORT"


#
#
# Slave Info  
# Slave Info  
#
#
SLAVE_IP="$PERONI_IP" # This host is Peroni
SLAVE_PORT="27960" # port of public broadcaster


SLAVE_IP=$FRAGLAND_IP # select from list above
ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^1#^71" # shows up on the Hub
SLAVE_PORT="27960" # port of the public broadcaster
SLAVE_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"
SLAVE_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^1#^72"
 
ETTV_CLIENT=$SLAVE_HOSTNAME # Shows up on Hub


SLAVE_SLOTS="100"
SLAVE_SLOTS="100"
SLAVE_PASS="[put_your_pass_here]"
SLAVE_PASS="[put_your_pass_here]"


SLAVE_PRIVATE_SLOTS="10"
SLAVE_PRIVATE_SLOTS="20"
SLAVE_PRIVATE_PASS="[put_your_pass_here]"
SLAVE_PRIVATE_PASS="[put_your_pass_here]"


SLAVE_ETTV_SLAVES="0"
SLAVE_ETTV_SLAVES="5" # Allow chaining?
SLAVE_ETTV_PASS="[put_your_pass_here]"
SLAVE_ETTV_PASS="[put_your_pass_here]"


RCON_PASS="[put_your_pass_here]"
SLAVE_RCON_PASS="[put_your_pass_here]"
 
RECORD_GAME="1" # 1 = record game, 0 = don't
SLAVE_DELAY="60" # Time in seconds
 
REDIRECT="Server is full" # Message displayed when server is full
#REDIRECT="ET://ettv2.fragland.org:27960" # Allows redirecting to other ettv's


ALLOW_DL="1"
#
ALLOW_WWW_DL="1" # Allow downloading over http?
# Downloading
WWW_DL_URL="http://www.yoursite.com" # No "/" at the end!
#
ALLOW_DL="1" # Can clients download stuff?
ALLOW_WWW_DL="1" # Allow downloading over http?
WWW_DL_URL="http://www.yoursite.com" # No "/" at the end!


RECORD_GAME="0" # 1 = record the game, 0 = don't
#
# ETTV Net settings for ETTV b8 & up
#
ETTV_NETBLAST="1"
ETTV_TV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_MTU="1400"


#
#
# Directories
# Directories
#
#
BASEPATH="/srv/et/ETTV/ettv_slave" # Path to ettv.x86. Use absolute paths here!
BASEPATH="/srv/et/ETTV/ettv_slave" # Path to ettv.x86
# Use absolute paths here!


#  
#  
Line 478: Line 526:
#                                                              #
#                                                              #
#################################################################
#################################################################
#
# Make sure buffers are ok!
#
echo "524288" > /proc/sys/net/core/rmem_max
echo "524288" > /proc/sys/net/core/wmem_max
#
#
# Assembling the Command Line
# Assembling the Command Line
#
#
BINARY="ettv.x86"
BINARY="ettv.x86"
DAEMON="$BASEPATH/$BINARY"
DAEMON="$BASEPATH/$BINARY"
HOMEPATH="$BASEPATH"
HOMEPATH="$BASEPATH/$MATCH_DATE"


SLAVE_OPTIONS="\
SLAVE_OPTIONS="\
+set fs_game etpro \
+set fs_game etpro \
+set dedicated 2 \
+set dedicated 2 \
+set com_hunkMegs 256 \
+set net_ip $SLAVE_IP \
+set net_ip $SLAVE_IP \
+set net_port $SLAVE_PORT \
+set net_port $SLAVE_PORT \
+set fs_basepath $BASEPATH \
+set fs_basepath $BASEPATH \
+set fs_homepath $HOMEPATH \
+set fs_homepath $HOMEPATH \
+set com_hunkMegs 128 \
+set sv_maxclients $SLAVE_SLOTS \
+set sv_maxclients $SLAVE_SLOTS \
+set sv_privateclients $SLAVE_PRIVATE_SLOTS \
+exec server.cfg"
+set sv_privatepassword $SLAVE_PRIVATE_PASS \
+set sv_hostname $SLAVE_HOSTNAME \
+set ettv_delay 0 \
+set ettv_autorecord $RECORD_GAME \
+set ettv_clientname $ETTV_CLIENT \
+set g_password $SLAVE_PASS \
+set rconpassword $RCON_PASS \
+set sv_maxRate 18000 \
+set sv_allowDownload $ALLOW_DL \
+set sv_wwwDownload $ALLOW_WWW_DL \
+set sv_wwwBaseURL "$WWW_DL_URL" \
+set sv_wwwDlDisconnected 0 \
+set g_log "slave.log" \
+set logfile 2 \
+tv connect $HUB_HOST $HUB_ETTV_PASS $HUB_PASS"


#
#
Line 518: Line 556:
slave_start (){
slave_start (){
#
#
# FYI'ing the user
# FYI the user
#
echo -n "Match Date is "
echo -n "$MATCH_DATE"
echo -e ".\nDemos are stored in $HOMEPATH/etpro/demos/.\n"
 
#
# Start the slave
#
#
echo -n "Starting Slave: "
echo -n "Starting Slave: "
Line 533: Line 579:
echo -n "Slave has PID "
echo -n "Slave has PID "
echo -e "$SLAVE_PID.\n"
echo -e "$SLAVE_PID.\n"
if [ $SLAVE_ETTV_SLAVES != 0 ]
then
echo "ETTV slaves can now connect to your box by issuing:"
echo -e "tv connect $SLAVE_IP:$SLAVE_PORT $SLAVE_ETTV_PASS $SLAVE_PASS\n"
fi
}
}


Line 545: Line 597:
if [ $SLAVE_PID ]
if [ $SLAVE_PID ]
then
then
kill -3 $SLAVE_PID
kill -SIGTERM $SLAVE_PID
echo -e "done."
echo -e "done."
else
else
echo -e "failed.\nSlave wasn't active anymore.\n"
echo -e "failed.\nSlave wasn't active anymore.\n"
fi
fi
}
create_config (){
#
# Generate etmain/server.cfg
#
TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
echo "//" > $BASEPATH/etmain/server.cfg
echo "// server.cfg generated $TIMESTAMP" >> $BASEPATH/etmain/server.cfg
echo -e "//\n" >> $BASEPATH/etmain/server.cfg
echo "set sv_privateclients $SLAVE_PRIVATE_SLOTS" >> $BASEPATH/etmain/server.cfg
echo "set sv_maxRate 25000" >> $BASEPATH/etmain/server.cfg
echo -e "set sv_hostname \"$SLAVE_HOSTNAME\"\n" >> $BASEPATH/etmain/server.cfg
echo "set g_password \"$SLAVE_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set rconpassword \"$SLAVE_RCON_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set sv_privatepassword \"$SLAVE_PRIVATE_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set sv_allowDownload $ALLOW_DL" >> $BASEPATH/etmain/server.cfg
echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $BASEPATH/etmain/server.cfg
echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $BASEPATH/etmain/server.cfg
echo -e "set sv_wwwDlDisconnected 0\n" >> $BASEPATH/etmain/server.cfg
echo "set b_ettv_flags 3" >> $BASEPATH/etmain/server.cfg
echo "set ettv_delay $SLAVE_DELAY" >> $BASEPATH/etmain/server.cfg
echo "set ettv_autorecord $RECORD_GAME" >> $BASEPATH/etmain/server.cfg
echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_sv_maxslaves \"$SLAVE_ETTV_SLAVES\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_password \"$SLAVE_ETTV_PASS\"" >> $BASEPATH/etmain/server.cfg
echo "set ettv_netblast $ETTV_NETBLAST" >> $BASEPATH/etmain/server.cfg
echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $BASEPATH/etmain/server.cfg
echo "set ettv_sv_iptos $ETTV_SV_IPTOS" >> $BASEPATH/etmain/server.cfg
echo -e "set ettv_mtu $ETTV_MTU\n" >> $BASEPATH/etmain/server.cfg
echo "set b_crashlogpath \"$BASEPATH/etpro\"" >> $BASEPATH/etmain/server.cfg
echo "set g_log \"slave.log\"" >> $BASEPATH/etmain/server.cfg
echo -e "set logfile 2\n" >> $BASEPATH/etmain/server.cfg
echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $BASEPATH/etmain/server.cfg
}
clean_up (){
#
# Clean up prompt
#
echo -n "Clean up demos directory [y/n]? "
read ANSWER
case "$ANSWER" in
y)
rm -Rf $BASEPATH/$MATCH_DATE
ls -l --color=always $BASEPATH
;;
*)
echo "Following demos still exist:"
ls -l --color=always $BASEPATH/$MATCH_DATE/etpro/demos/
;;
esac
}
}


Line 558: Line 668:
case "$1" in
case "$1" in
start)
start)
create_config
slave_start
slave_start
;;
;;
stop)
stop)
slave_stop
slave_stop
clean_up
;;
;;
restart)
restart)
slave_stop
$0 stop
sleep 1
sleep 1
slave_start
$0 start
;;
;;
sim)
create_config
echo -e "\nFollowing config was generated automatically:\n"
cat $BASEPATH/etmain/server.cfg
;;
*)
*)
SCRIPT_NAME=`basename $0`
SCRIPT_NAME=`basename $0`
echo "Usage: $SCRIPT_NAME {start|stop|restart}"
echo "Usage: $SCRIPT_NAME {start|stop|restart|sim}"
exit 1
exit 1
;;
;;
Line 576: Line 693:
exit 0
exit 0
</pre>
</pre>


=== Old school record / playback script ===
=== Old school record / playback script ===
Line 609: Line 725:
#  - Daita (pourix.net) for the original idea & script          #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#  - aNgel (fragland.org) for debugging Beavis' mistakes ;-)    #
#                                                              #
#                                                              #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
Line 637: Line 752:


# Planet Hosting Game Server IP
# Planet Hosting Game Server IP
# ettv5.fragland.org
# ettv.fragland.org
PLANET_IP="85.190.1.13"
KLEIN_IP="83.243.82.88"


#################################################################
#################################################################
Line 648: Line 763:
# Parameters of the Game Server to Connect to
# Parameters of the Game Server to Connect to
#
#
# IMPORTANT: Let the admin of the game server do
# IMPORTANT: Let the admin of the game server do a
# "fdir *.pk3" in his console and give you the output!
# fdir *.pk3 in his console and give you the output!
#
#
# PK3 mismatches between game server and ETTV hosts
# PK3 mismatches between game server and ETTV hosts
# account for the majority of crashes of ETTV.
# account for the majority of crashes of ETTV.
#
#
MATCH_DATE=`date +%Y%m%d` # Today's date for creating the subdir
MATCH_DATE=`date +%Y%m%d` # Do NOT modify
MATCH_HOST="et.fragland.org:27965" # Match server port & address
MATCH_HOST="et.fragland.org:27970" # Match server port & address
MATCH_ETTV_PASS="[get_pass_from_admin]" # Match server ETTV password
MATCH_ETTV_PASS="[put_your_pass_here]" # Match server ETTV password
MATCH_PASS="[get_pass_from_admin]" # Match server password
MATCH_PASS="[put_your_pass_here]" # Match server password
 
#
# Match info for setting hostname & storing demos
#
MATCH_HOME_TEAM="NED"
MATCH_AWAY_TEAM="BEL"
MATCH_CUP="NationsCup"


#
#
# IPs & Ports For Your Host
# IPs & Ports For Your Host
#
#
THISHOST_IP=$PERONI_IP # This host is Webperoni
THISHOST_IP="$KLEIN_IP" # Select from list above
RECORDER_PORT="44999" # Port of the private recorder
RECORDER_PORT="29995" # Port of the private recorder
BROADCASTER_PORT="27960" # Port of the public broadcaster
SLAVE_PORT="27960" # Port of the public broadcaster


#
#
Line 674: Line 796:
#
#
RECORDER_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^7recorder ^1#^71"
RECORDER_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^7recorder ^1#^71"
BROADCASTER_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^1#^71"
ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^1#^71"
SLAVE_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"


ETTV_CLIENT=$BROADCASTER_HOSTNAME


#
#
# Passwords
# Passwords
#
#
RCON_PASS="[put_your_pass_here]"
RECORDER_RCON_PASS="[put_your_pass_here]"
RECORDER_PASS="[put_your_pass_here]"
RECORDER_PASS="[put_your_pass_here]"
BROADCASTER_PRIVATE_PASS="[put_your_pass_here]"
SLAVE_RCON_PASS="[put_your_pass_here]"
BROADCASTER_ETTV_PASS="[put_your_pass_here]"
SLAVE_PRIVATE_PASS="[put_your_pass_here]"
BROADCASTER_PASS="[put_your_pass_here]" # Issue /rcon g_password "" for opening it up to the crowd
SLAVE_ETTV_PASS="[put_your_pass_here]"
SLAVE_PASS="[put_your_pass_here]" # /rcon g_password "" to clear


#
#
# Directories
# Other relevant settings
#
#
BASEPATH="/srv/et/ETTV/ettv_brc" # Path to ettv.x86. Use absolute paths here!
SLAVE_DELAY="60" # Delay between live match &
# broadcaster in seconds
 
SLAVE_SLOTS="100"
SLAVE_PRIVATE_SLOTS="25"
SLAVE_ETTV_SLAVES="0" # Allow chaining?
 
REDIRECT="Server is full" # Message displayed when server is full
#REDIRECT="ET://ettv2.fragland.org:27960"


#
#
Line 701: Line 832:


#
#
# Other relevant settings
# Download settings
#
#
SHOUTCAST_DELAY="60" # Delay between live match & broadcasting hub in seconds
BROADCASTER_SLOTS="100"
BROADCASTER_PRIVATE_SLOTS="10"
BROADCASTER_ETTV_SLAVES="0"
ALLOW_DL="1"
ALLOW_DL="1"
ALLOW_WWW_DL="1" # Allow downloading over http?
ALLOW_WWW_DL="1" # Allow downloading over http?
WWW_DL_URL="http://www.yoursite.org" # No "/" at the end!
WWW_DL_URL="http://wwww.fragland.org/maps"


#
# Directories
#
BASEPATH="/srv/et/ETTV" # Use absolute paths here!
RECORDER_BASEPATH="$BASEPATH/ettv_recorder"
SLAVE_BASEPATH="$BASEPATH/ettv_slave"


#  
#  
Line 723: Line 854:
# he was created on our systems by us.
# he was created on our systems by us.
#
#
# gamed cannot log in. His homedir is equal to the path
# gamed cannot log in. His homedir is equal to the path where
# where all our servers are installed.
# all our servers are installed.
#
#
USER="gamed"
USER="gamed"
Line 733: Line 864:
#                                                              #
#                                                              #
#################################################################
#################################################################
#
# Make sure buffers are ok!
#
echo "262144" > /proc/sys/net/core/rmem_max
echo "262144" > /proc/sys/net/core/wmem_max
#
#
# Assembling the Command Line
# Assembling the Command Line
#
#
RECORDER_HOMEPATH="$BASEPATH/$MATCH_DATE/recorder"
MATCH=""$MATCH_HOME_TEAM"vs"$MATCH_AWAY_TEAM""
BROADCASTER_HOMEPATH="$BASEPATH/$MATCH_DATE/broadcaster"
HOMEPATH="$BASEPATH/$MATCH"


BINARY="ettv.x86"
BINARY="ettv.x86"
DAEMON="$BASEPATH/$BINARY"
RECORDER_DAEMON="$RECORDER_BASEPATH/$BINARY"
SLAVE_DAEMON="$SLAVE_BASEPATH/$BINARY"


RECORDER_OPTIONS="\
RECORDER_OPTIONS="\
+set fs_game etpro \
+set fs_game etpro \
+set dedicated 1 \
+set dedicated 1 \
+map oasis \
+set net_ip $THISHOST_IP \
+set net_ip $THISHOST_IP \
+set net_port $RECORDER_PORT \
+set net_port $RECORDER_PORT \
+set fs_basepath $BASEPATH \
+set fs_basepath $RECORDER_BASEPATH \
+set fs_homepath $RECORDER_HOMEPATH \
+set fs_homepath $HOMEPATH \
+set com_hunkMegs 128 \
+set com_hunkMegs 128 \
+set g_password $RECORDER_PASS \
+exec recorder.cfg"
+set rconpassword $RCON_PASS \
+set sv_hostname $RECORDER_HOSTNAME \
+set sv_maxclients 4 \
+set sv_maxRate 25000 \
+set sv_allowDownload 0 \
+set sv_wwwDownload 0 \
+set sv_wwwBaseURL "$WWW_DL_URL" \
+set sv_wwwDlDisconnected 0 \
+set g_log "recorder.log" \
+set logfile 2 \
+set b_ettv_flags 3 \
+set ettv_sv_maxslaves 2 \
+set ettv_clientname $ETTV_CLIENT \
+set ettv_password $BROADCASTER_ETTV_PASS \
+set ettv_netblast $ETTV_NETBLAST \
+set ettv_tv_iptos $ETTV_TV_IPTOS \
+set ettv_sv_iptos $ETTV_SV_IPTOS \
+set ettv_mtu $ETTV_MTU \
+set ettv_autorecord 1 \
+set ettv_delay 1 \
+tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS"


BROADCASTER_OPTIONS="\
SLAVE_OPTIONS="\
+set fs_game etpro \
+set fs_game etpro \
+set dedicated 2 \
+set dedicated 2 \
+set net_ip $THISHOST_IP \
+set net_ip $THISHOST_IP \
+set net_port $BROADCASTER_PORT \
+set net_port $SLAVE_PORT \
+set fs_basepath $BASEPATH \
+set fs_basepath $SLAVE_BASEPATH \
+set fs_homepath $BROADCASTER_HOMEPATH \
+set fs_homepath $HOMEPATH \
+set sv_maxclients $SLAVE_SLOTS \
+set com_hunkMegs 160 \
+set com_hunkMegs 160 \
+set sv_maxclients $BROADCASTER_SLOTS \
+exec slave.cfg"
+set sv_privateclients $BROADCASTER_PRIVATE_SLOTS \
 
+set sv_privatepassword $BROADCASTER_PRIVATE_PASS \
#
+set sv_hostname $BROADCASTER_HOSTNAME \
# Only add for ETTV b8 & up
+set g_password $BROADCASTER_PASS \
#
+set rconpassword $RCON_PASS \
#+set ettv_mtu $ETTV_MTU \
+set sv_maxRate 18000 \
+set sv_allowDownload $ALLOW_DL \
+set sv_wwwDownload $ALLOW_WWW_DL \
+set sv_wwwBaseURL "$WWW_DL_URL" \
+set sv_wwwDlDisconnected 0 \
+set g_log "broadcaster.log" \
+set logfile 2 \
+set ettv_autoplay 1 \
+set ettv_password $BROADCASTER_ETTV_PASS \
+set b_ettv_flags 3 \
+set ettv_sv_maxslaves $BROADCASTER_ETTV_SLAVES \
+demo demo0000"


#
#
# Functions
# Functions
#
#
broadcast_start (){
broadcast_start (){
#
#
Line 811: Line 917:
echo -n "Match Date is "
echo -n "Match Date is "
echo -n "$MATCH_DATE"
echo -n "$MATCH_DATE"
 
echo -e ".\nDemos are stored in $RECORDER_HOMEPATH/etpro/demos/.\n"
echo -e ".\nDemos are stored in $HOMEPATH/etpro/demos/.\n"


echo -n "Starting Recorder: "
echo -n "Starting Recorder: "
screen -dmS recorder su -m -c "$DAEMON $RECORDER_OPTIONS" - $USER
screen -dmS recorder su -m -c "$RECORDER_DAEMON $RECORDER_OPTIONS" - $USER
echo "done."
echo "done."


get_pids
echo "Sleeping for $SLAVE_DELAY seconds."
sleep $SLAVE_DELAY
echo -n "Recorder has PID "
echo -n $RECORDER_PID
echo -e ".\n\nSleeping for $SHOUTCAST_DELAY seconds."
sleep $SHOUTCAST_DELAY
mkdir "$BROADCASTER_HOMEPATH"
mkdir "$BROADCASTER_HOMEPATH/etpro"
ln -s "$RECORDER_HOMEPATH/etpro/demos" "$BROADCASTER_HOMEPATH/etpro"
chown -R $USER "$BROADCASTER_HOMEPATH"
chmod -R 775 "$BROADCASTER_HOMEPATH"


echo -n "Starting Broadcaster: "
echo -n "Starting Broadcaster: "
screen -dmS broadcaster su -m -c "$DAEMON $BROADCASTER_OPTIONS" - $USER
screen -dmS slave su -m -c "$SLAVE_DAEMON $SLAVE_OPTIONS" - $USER
echo -e "done.\n"
echo -e "done.\n"


Line 842: Line 937:
echo -n "Recorder has PID "
echo -n "Recorder has PID "
echo -n $RECORDER_PID
echo $RECORDER_PID
echo -e ".\n\nBroadcaster has PID "
renice -8 $RECORDER_PID
echo -e "$BROADCASTER_PID.\n"
echo -n "Broadcaster has PID "
echo -e "$SLAVE_PID\n"
renice -7 $SLAVE_PID
}
}


Line 851: Line 948:
get_pids
get_pids
echo -n "Shutting Down Broadcaster: "
echo -n "Shutting Down Slave: "
sleep 1
sleep 1
if [ $BROADCASTER_PID ]
if [ $SLAVE_PID ]
then
then
kill -3 $BROADCASTER_PID
kill -SIGTERM $SLAVE_PID
echo -e "done."
echo -e "done."
else
else
echo -e "failed.\nBroadcaster wasn't active anymore.\n"
echo -e "failed.\nSlave wasn't active anymore.\n"
fi
fi


Line 865: Line 962:
if [ $RECORDER_PID ]
if [ $RECORDER_PID ]
then
then
kill -3 $RECORDER_PID
kill -SIGTERM $RECORDER_PID
echo -e "done."
echo -e "done."
else
else
Line 872: Line 969:


sleep 1
sleep 1
clean_up
}
}


Line 883: Line 979:
case "$ANSWER" in
case "$ANSWER" in
y)
y)
rm -Rf $BASEPATH/$MATCH_DATE
rm -Rf $BASEPATH/$MATCH
ls -l --color=always $BASEPATH
ls -l $BASEPATH
;;
;;
*)
*)
echo "Following demos still exist:"
echo "Following demos still exist:"
ls -l --color=always $BASEPATH/$MATCH_DATE/etpro/demos/
ls -l $BASEPATH/$MATCH/etpro/demos/
;;
;;
esac
esac
}
}
create_recorder_config (){
#
# Generate etmain/recorder.cfg
#
TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
RECORDER_CFG="$RECORDER_BASEPATH/etmain/recorder.cfg"
echo "//" > $RECORDER_CFG
echo "// config generated $TIMESTAMP" >> $RECORDER_CFG
echo -e "//\n" >> $RECORDER_CFG
echo "set sv_maxclients 2" >> $RECORDER_CFG
echo "set sv_privateclients 0" >> $RECORDER_CFG
echo "set sv_maxRate 25000" >> $RECORDER_CFG
echo -e "set sv_hostname \"$RECORDER_HOSTNAME\"\n" >> $RECORDER_CFG
echo "set g_password \"$RECORDER_PASS\"" >> $RECORDER_CFG
echo "set rconpassword \"$RECORDER_RCON_PASS\"" >> $RECORDER_CFG
echo -e "set sv_allowDownload 0\n" >> $RECORDER_CFG
echo "set ettv_delay 1" >> $RECORDER_CFG
echo "set ettv_autorecord 1" >> $RECORDER_CFG
echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $RECORDER_CFG
echo "set ettv_sv_maxslaves 0" >> $RECORDER_CFG
echo "set ettv_netblast $ETTV_NETBLAST" >> $RECORDER_CFG
echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $RECORDER_CFG
echo -e "set ettv_sv_iptos $ETTV_SV_IPTOS\n" >> $RECORDER_CFG
echo "set b_crashlogpath \"$RECORDER_BASEPATH/etpro\"" >> $RECORDER_CFG
echo "set g_log \"recorder.log\"" >> $RECORDER_CFG
echo -e "set logfile 2\n" >> $RECORDER_CFG
echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $RECORDER_CFG
}
create_slave_config (){
#
# Generate etmain/slave.cfg
#
TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
SLAVE_CFG="$SLAVE_BASEPATH/etmain/slave.cfg"
echo "//" > $SLAVE_CFG
echo "// config generated $TIMESTAMP" >> $SLAVE_CFG
echo -e "//\n" >> $SLAVE_CFG
echo "set sv_maxclients $SLAVE_SLOTS" >> $SLAVE_CFG
echo "set sv_privateclients $SLAVE_PRIVATE_SLOTS" >> $SLAVE_CFG
echo "set sv_maxRate 25000" >> $SLAVE_CFG
echo -e "set sv_hostname \"$SLAVE_HOSTNAME\"\n" >> $SLAVE_CFG
echo "set g_password \"$SLAVE_PASS\"" >> $SLAVE_CFG
echo "set rconpassword \"$SLAVE_RCON_PASS\"" >> $SLAVE_CFG
echo "set sv_privatepassword \"$SLAVE_PRIVATE_PASS\"" >> $SLAVE_CFG
echo "set sv_allowDownload $ALLOW_DL" >> $SLAVE_CFG
echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $SLAVE_CFG
echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $SLAVE_CFG
echo -e "set sv_wwwDlDisconnected 0\n" >> $SLAVE_CFG
echo "set b_ettv_flags 3" >> $SLAVE_CFG
echo "set ettv_delay 0" >> $SLAVE_CFG
echo "set ettv_autorecord 0" >> $SLAVE_CFG
echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $SLAVE_CFG
echo "set ettv_sv_maxslaves \"$SLAVE_ETTV_SLAVES\"" >> $SLAVE_CFG
echo "set ettv_password \"$SLAVE_ETTV_PASS\"" >> $SLAVE_CFG
echo "set ettv_netblast $ETTV_NETBLAST" >> $SLAVE_CFG
echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $SLAVE_CFG
echo -e "set ettv_sv_iptos $ETTV_SV_IPTOS\n" >> $SLAVE_CFG
echo "set b_crashlogpath \"$SLAVE_BASEPATH/etpro\"" >> $SLAVE_CFG
echo "set g_log \"slave.log\"" >> $SLAVE_CFG
echo -e "set logfile 2\n" >> $SLAVE_CFG
echo "demo demo0000" >> $SLAVE_CFG
}
get_pids (){
get_pids (){
#
#
# Pulling some very ugly tricks here
# Since we want to run multiple casts in parallel we launch the same
# binary twice or more. pidof then doesn't work so we have to recreate
# the human behaviour of looking for the PID.
#
#
RECORDER_PID=`ps aux|grep "+set net_port $RECORDER_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"\|awk '{ print $1 $2 }'|tr -d "$USER"`
RECORDER_PID=`ps aux|grep "+set net_port $RECORDER_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"|grep -v grep|awk '{ print $2 }'`
BROADCASTER_PID=`ps aux|grep "+set net_port $BROADCASTER_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"|awk '{ print $1 $2 }'|tr -d "$USER"`
SLAVE_PID=`ps aux|grep "+set net_port $SLAVE_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"|grep -v grep|awk '{ print $2 }'`
 
}
}


Line 907: Line 1,082:
case "$1" in
case "$1" in
start)
start)
create_recorder_config
create_slave_config
broadcast_start
broadcast_start
;;
    ;;
stop)
stop)
broadcast_stop
broadcast_stop
clean_up
;;
sim)
create_recorder_config
create_slave_config
echo -e "\nFollowing configs were generated automatically:\n"
cat $RECORDER_CFG | more
cat $SLAVE_CFG | more
;;
;;
*)
*)
SCRIPT_NAME=`basename $0`
SCRIPT_NAME=`basename $0`
echo "Usage: $SCRIPT_NAME {start|stop}"
echo "Usage: $SCRIPT_NAME {start|stop|sim}"
exit 1
exit 1
;;
;;
Line 921: Line 1,106:
</pre>
</pre>


=== Sanitization script ===
This is a script to restore an ETTV directory to the bare minimum required to broadcast matches or be a hub. It isn't a very advanced script but it gets the job done. Copy / paste this script and save it as <code>sanitize.sh</code> or any other name you prefer. Just do <code>./sanitize.sh</code> do delete all files in etmain & etpro that are not needed anymore.
''Note'': this script deletes '''everything''' it finds in the etmain and etpro directories. If you have stuff that you do not want to delete in there, add it to the ETMAIN_FILES & ETPRO_FILES arrays.
<pre>#!/bin/bash
#################################################################
#                                                              #
#                    ettv clean-up script                      #
#                            -                                #
#                          deej.                              #
#                                                              #
#################################################################
#                                                              #
# This script is used to restore an ETTV directory to the bare  #
# minimum in terms of files.                                    #
#                                                              #
# Use it to clean up after an ETTV session so you can start the #
# next session with a minimum of PK3s.                          #
#                                                              #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
#                                                              #
#################################################################
ETMAIN_FILES=(\
"description.txt" \
"hunkusage.dat" \
"mp_bin.pk3" \
"pak0.pk3" \
"pak1.pk3" \
"pak2.pk3" \
"et_ice.pk3" \
"braundorf_b4.pk3" \
"supplydepot2.pk3" \
"sw_goldrush_te.pk3" \
"sw_oasis_b3.pk3")
ETPRO_FILES=(\
"etpro-3_2_4.pk3" \
"etpro_cheats.dat" \
"qagame.mp.i386.so" \
"tvgame.mp.i386.so")
SCRIPT_NAME=`basename $0`
case $1 in
hub)
BASEPATH="/srv/et/ETTV/ettv_hub"
;;
slave)
BASEPATH="/srv/et/ETTV/ettv_slave"
;;
*)
echo -e "\nError: $1 is not a valid installation target."
echo -e "Usage: $SCRIPT_NAME {hub|slave}\n"
exit 1
esac
#
# Test for existence of backup directories
#
if [ ! -d "$BASEPATH/etmain/bak/" ]; then
mkdir "$BASEPATH/etmain/bak"
fi
if [ ! -d "$BASEPATH/etpro/bak/" ]; then
mkdir "$BASEPATH/etpro/bak"
fi
#
# Clear etmain
#
for i in ${ETMAIN_FILES[@]}
do
mv "$BASEPATH/etmain/$i" "$BASEPATH/etmain/bak/"
done
rm $BASEPATH/etmain/*
#
# Clear etpro
#
for i in ${ETPRO_FILES[@]}
do
mv "$BASEPATH/etpro/$i" "$BASEPATH/etpro/bak/"
done
rm $BASEPATH/etpro/*
#
# Restore etmain
#
for i in ${ETMAIN_FILES[@]}
do
mv "$BASEPATH/etmain/bak/$i" "$BASEPATH/etmain/"
done
#
# Restore etpro
#
for i in ${ETPRO_FILES[@]}
do
mv "$BASEPATH/etpro/bak/$i" "$BASEPATH/etpro/"
done
#
# Clean the backup directories
#
rm -Rf $BASEPATH/etmain/bak
rm -Rf $BASEPATH/etpro/bak
</pre>
=== Switching beta's script ===
This script allows you to quickly switch between the different beta's Bani has released. Just save it as <code>switchbeta.sh</code> and adapt the directory fields to your setup. Usage example: <code>./switchbeta.sh 9 hub</code> switches the hub to beta 9. <code>./switchbeta.sh 4 all</code> switches hub & slave (or others you can define of course) back to beta 4.
<pre>#!/bin/bash
#################################################################
#                                                              #
#                  switching ettv betas script                  #
#                            -                                #
#                          deej.                              #
#                                                              #
#################################################################
#                                                              #
# This script allows you to easily switch ETTV beta versions.  #
#                                                              #
# Just put the ettv-beta[x].zip files in directory $REPODIR,    #
# adapt settings for hub & slave and start switching!          #
#                                                              #
# Questions? Contact me on deej@fragland.org or go to #r0f.et  #
#                                                              #
#################################################################
#
# Paths & files
#
REPODIR="/srv/et" # Where the ettv-betaX.zip files reside
HUB_DIR="/srv/et/ETTV/ettv_hub"
SLAVE_DIR="/srv/et/ETTV/ettv_slave"
#
# Argument check
#
SCRIPT_NAME=`basename $0`
ARGS=2
E_BADARGS=65
if [ $# -lt "$ARGS" ]
then
echo -e "\nError: missing arguments"
echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|broadcast|all}\n"
exit $E_BADARGS
fi
FILENAME="ettv-beta$1.zip"
if [ ! -e "$REPODIR/$FILENAME" ]
then
echo -e "\nError: beta version $1 is not present in $REPODIR."
echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|all}\n"
exit $E_BADARGS
fi
case $2 in
hub)
unzip -o "$REPODIR/$FILENAME" -d "$HUB_DIR" ettv.x86
chmod +x "$HUB_DIR/ettv.x86"
unzip -o "$REPODIR/$FILENAME" -d "$HUB_DIR/etpro" tvgame.mp.i386.so
;;
slave)
unzip -o "$REPODIR/$FILENAME" -d "$SLAVE_DIR" ettv.x86
chmod +x "$SLAVE_DIR/ettv.x86"
unzip -o "$REPODIR/$FILENAME" -d "$SLAVE_DIR/etpro" tvgame.mp.i386.so
;;
all)
$0 $1 hub
$0 $1 slave
;;
*)
echo -e "\nError: $2 is not a valid installation target."
echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|all}\n"
exit $E_BADARGS
esac
exit 0
</pre>


Have fun broadcasting!
Have fun broadcasting!


[[User:Deej|deej]] 00:04, 7 November 2005 (PST)
[[User:Deej|deej]] 01:46, 3 January 2006 (PST)


[[Category:ETTV:Server Configuration]]
[[Category:ETTV]]

Latest revision as of 12:31, 6 April 2006

http://www.fragland.org/deej/572.gif

Guilty for founding the Retired Old Farts which provide:
- ETPro servers
- ETTV servers
- ETPub servers
- General annoyance
- Pub requests for a competition mod

My interpretation of ETTV setups

Since I'm quite fond of toying around with new developments, I'm always one of the first to test new ETTV / ETPro releases and bug bani with questions about them. Having said that, here's my 'personal' view on a good ETTV broadcast (this is not the Bible!):


Terminology

There are 5 different "participants" possibly involved in an ETTV broadcast:

  • Master - the gameserver hosting the actual game
  • Viewer - the viewer wanting to view a game (duh)
  • Broadcaster - a server that is directly connected to a gameserver and allows viewer to connect directly to itself
  • Hub - a server that is directly connected to a gameserver and allows other ETTV 'slaves' to connect to itself, but not viewers
  • Slave - a server that connects to a hub or perhaps a broadcaster and and allows viewers to connect to itself


Keep this terminology in mind when you stroll through my text ;-).

Today's broadcasts

Most ETTV games I see today use this set-up:


Viewer -> Broadcaster -> Master


If you remember that an ETTV server connects at an unlimited rate to another server, and as from ETTV b9 the slaves are in fact not limited at all by the original ET netcode, you might see a problem arising when lots of people would like to see a "big match".


The trouble was / is that before ETTV b8 and 'autodelay', we had to do some fancy flying to get a delayed broadcast or delayed hub up. Usually you would start a 'recorder' daemon that recorded demos and a 'playback' daemon from that same directory, so that it started playing back the recorded demo after roughly 60 or 90 seconds. This does require fancy scripting and lots of manual work to sort out demos, connect slaves to hubs etc...


With ettv_autodelay, things have become a lot easier. Ideally the gameserver now only allows 2 or 4 ETTV hubs to connect to it, which delay and relay the signal. The responsibility for the admins of the hub is of course greater as they should not have any PK3s active on their hubs that are not on the pure list of the server. The less PK3s you need, the better!


Deej's proposition

The best setup IMHO is to have the following:


Viewers -> Slave 1   |
Viewers -> Slave 2   |
Viewers -> Slave 3   |--> Hub 1 |
                     |--> Hub 2 | --> Master
Viewers -> Slave ... |--> Hub n |
                     |
Viewers -> Slave n   |


This alleviates the load on the Master Game Server firmly as only 2 or 4 hubs are required where slaves can then connect to! Furthermore with autodelay all the 'slave' administrators only need to connect their slave to a given hub. No more playing around with delays, demos, symbolic links, PIDs that get screwed up etc...


Some scripts I use

Hub script

This script launches a hub that delays its feed by x seconds, configurable inside the script. You can safely remove the stuff like PERONI_IP, FRAGLAND_IP etc... at the beginning since those only store the IPs of the root servers we manage (it's easier for me to keep track of them that way).


How do you use this script? Copy / paste this script and save it as hub.sh or any other name you prefer. Then use ./hub.sh start to start and ./hub.sh stop to stop your hub. The script generates the server.cfg dynamically every time you start it. If you just want to generate server.cfg do ./hub.sh sim.


Be aware that it's much better to actually do "quit" in the console of your hub instead of ./hub.sh stop as this cleanly disconnects the hub from a game server. With ./hub.sh stop the hub stays with ping 999 on the gameserver and needs to time out. Maybe we should ask Bani to improve POSIX signal interpretation of the ETTV binary :-).


#!/bin/bash

#################################################################
#                                                               #
#                    ettv delayed hub script                    #
#                             -                                 #
#                           deej.                               #
#                                                               #
#################################################################
#                                                               #
#  This script can be used to start up a delayed ETTV stream    #
#  where ETTV slaves connect to the hub to relay the signal.    #
#                                                               #
#  The daemon serves as a hub for other ETTV slaves to connect  #
#  to and as such alleviate the load on the game server hosting #
#  the match.                                                   #
#                                                               #
#  This script creates a subdirectory which represents the      #
#  date of the match and stores the demos in this subdir.       #
#                                                               #
#  The script generates etmain/server.cfg dynamically.          #
#                                                               #
#  The script launches the daemon in a different screen         #
#  which you can reattach with "screen -r hub".                 #
#                                                               #
#  Credits:                                                     #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#                                                               #
# Questions? Contact me on deej@fragland.org or go to #r0f.et   #
#                                                               #
#################################################################

# Webperoni Game Server IP
# ettv.fragland.org
PERONI_IP="83.133.81.192"

# Deinprovider WebServer IP
# ettv2.fragland.org
FRAGLAND_IP="217.20.115.116"

# Ionmedia Game Server IP
# ettv3.fragland.org
IONMEDIA_IP="62.216.174.68"

# Hetzner Game Server IP
# ettv4.fragland.org
HETZNER_IP="213.239.207.195"

# Planet Hosting Game Server IP
# ettv5.fragland.org
PLANET_IP="85.190.1.13"

#################################################################
#                                                               #
#                 Start Modifying From Here                     #
#                                                               #
#################################################################
#
# Parameters of the Game Server to Connect to
#
# IMPORTANT: Let the admin of the game server do 
# "fdir *.pk3" in his console and give you the output!
#
# PK3 mismatches between game server and ETTV hosts
# account for the majority of crashes of ETTV.
#
MATCH_DATE=`date +%Y%m%d`		# Do NOT modify
MATCH_HOST="et.fragland.org:27965"	# Match server port & address
MATCH_ETTV_PASS="[get_pass_from_admin]"	# Match server ETTV password
MATCH_PASS="[get_pass_from_admin]"	# Match server password

MATCH_HOME_TEAM="uQ"			# Making our hostname more fancy ;-)
MATCH_AWAY_TEAM="Logitech"
MATCH_CUP="Warleagues"

#
# IPs & Ports For Your Host
#
HUB_IP="$PERONI_IP"			# This host is Webperoni
HUB_PORT="30000"			# Port of public hub for ETTV slaves

#
# Hostnames & ETTV Client name
#
# - hostname shows up in server browsers
# - ETTV client name shows up as the name
#   of your server in the game server.
#
ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^7hub ^1#^71"
HUB_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"

#
# Passwords
#
HUB_RCON_PASS="[put_your_pass_here]"
HUB_PRIVATE_PASS="[put_your_pass_here]"
HUB_ETTV_PASS="[put_your_pass_here]"
HUB_PASS="[put_your_pass_here]"

#
# Directories
#
BASEPATH="/srv/et/ETTV/ettv_hub"	# Use absolute paths here!

#
# ETTV Net settings for ETTV b8 & up
#
ETTV_NETBLAST="1"
ETTV_TV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_MTU="1400"

#
# Other relevant ETTV settings
#
HUB_DELAY="1"				# Delay between live match & hub in seconds
HUB_SLAVES="8"				# 1 ETTV slave connects at an UNLIMITED rate!
HUB_PRIVATE_SLOTS="0"

RECORD_GAME="1"				# Record the game?

ALLOW_DL="0"				# Slaves don't download from the hub
ALLOW_WWW_DL="0"
WWW_DL_URL="http://www.yoursite.com"

# 
# User To Launch Daemon
#
# Good practice:
# What doesn't need root priviliges doesn't get them!
#
# User gamed mentioned here under is not a standard linux user,
# he was created on our systems by us.
#
# gamed cannot log in. His homedir is equal to the path where
# all our servers are installed.
#
USER="gamed"

#################################################################
#                                                               #
#                     STOP Modifying Here                       #
#                                                               #
#################################################################
#
# Make sure buffers are high enough!
#
echo "524288" > /proc/sys/net/core/rmem_max 
echo "524288" > /proc/sys/net/core/wmem_max 

#
# Assembling the Command Line
#
BINARY="ettv.x86"
DAEMON="$BASEPATH/$BINARY"
HOMEPATH="$BASEPATH/$MATCH_DATE"

HUB_OPTIONS="\
+set fs_game etpro \
+set dedicated 2 \
+set net_ip $HUB_IP \
+set net_port $HUB_PORT \
+set fs_basepath $BASEPATH \
+set fs_homepath $HOMEPATH \
+set com_hunkMegs 128 \
+set sv_maxclients $HUB_SLAVES \
+exec server.cfg"

#
# Functions
#

hub_start () {
	#
	# FYI'ing the user
	#
	echo -n "Match Date is "
	echo -n "$MATCH_DATE"
	
	echo -e ".\nDemos are stored in $HOMEPATH/etpro/demos/.\n"

	echo -n "Starting Hub: "
	screen -dmS hub su -m -c "$DAEMON $HUB_OPTIONS" - $USER
	sleep 1
	echo -e "done.\n"

	echo -e "Getting PID...\n"
	
	get_pids
	
	echo -n "Hub has PID "
	echo -e "$HUB_PID\n"

	echo "ETTV slaves can now connect to your box by issuing:"
	echo -e "tv connect $HUB_IP:$HUB_PORT $HUB_ETTV_PASS $HUB_PASS\n"
}

hub_stop () {
	#	
	# Refresh the PIDs
	#
	get_pids
	
	echo -n "Shutting Down Hub: "
	sleep 1
	if [ -n $HUB_PID ]
		then
			kill -SIGTERM $HUB_PID
			echo -e "done."
		else
			echo -e "failed.\nHub wasn't active anymore.\n"
	fi

	sleep 1
}

create_config (){
	#
	# Generate etmain/server.cfg
	#	
	TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
	
	echo "//" > $BASEPATH/etmain/server.cfg
	echo "// server.cfg generated $TIMESTAMP" >> $BASEPATH/etmain/server.cfg
	echo -e "//\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set sv_privateclients $HUB_PRIVATE_SLOTS" >> $BASEPATH/etmain/server.cfg
	echo "set sv_maxRate 25000" >> $BASEPATH/etmain/server.cfg
	echo -e "set sv_hostname \"$HUB_HOSTNAME\"\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set g_password \"$HUB_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set rconpassword \"$HUB_RCON_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set sv_privatepassword \"$HUB_PRIVATE_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set sv_allowDownload $ALLOW_DL" >> $BASEPATH/etmain/server.cfg
	echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $BASEPATH/etmain/server.cfg
	echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $BASEPATH/etmain/server.cfg
	echo -e "set sv_wwwDlDisconnected 0\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set b_ettv_flags 3" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_delay $HUB_DELAY" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_autorecord $RECORD_GAME" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_sv_maxslaves \"$HUB_ETTV_SLAVES\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_password \"$HUB_ETTV_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_netblast $ETTV_NETBLAST" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_sv_iptos $ETTV_SV_IPTOS" >> $BASEPATH/etmain/server.cfg
	echo -e "set ettv_mtu $ETTV_MTU\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set b_crashlogpath \"$BASEPATH/etpro\"" >> $BASEPATH/etmain/server.cfg
	echo "set g_log \"slave.log\"" >> $BASEPATH/etmain/server.cfg
	echo -e "set logfile 2\n" >> $BASEPATH/etmain/server.cfg
	
	echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $BASEPATH/etmain/server.cfg
}

get_pids (){
	#
	# We used to launch the same binary twice so pidof didn't work.
	# As from beta 8 ettv delayed feeds were automatic so
	# no more fancy scripting tricks are required :-)
	#
	HUB_PID=`pidof $DAEMON`
}

clean_up (){
	#
	# Clean up prompt
	#
	echo -n "Clean up demos directory [y/n]? "
	read ANSWER
	case "$ANSWER" in
		y)
			rm -Rf $BASEPATH/$MATCH_DATE
			ls -l --color=always $BASEPATH
			;;
		*)
			echo "Following demos still exist:"
			ls -l --color=always $BASEPATH/$MATCH_DATE/etpro/demos/
			;;
	esac
}

#
# Performing The magic :-)
#

case "$1" in
	start)
		create_config
		hub_start
		;;
	stop)
		hub_stop
		clean_up
		;;
	sim)
		create_config
		echo -e "\nFollowing config was generated automatically:\n"
		cat $BASEPATH/etmain/server.cfg
		;;
	*)
		SCRIPT_NAME=`basename $0`
		echo "Usage: $SCRIPT_NAME {start|stop|sim}"
		exit 1
		;;
esac
exit 0


Slave script

This script connects a delayed or undelayed slave to a Hub or directly to a gameserver. The usage of this script is very similar to the Hub script. Copy / paste it and save it as slave.sh or any other name you prefer. Then issue ./slave.sh start to start your slave and ./slave.sh stop to stop it. Use ./slave.sh sim to only create etmain/server.cfg. Like above, it is actually better to do quit in the console instead of just killing the slave with this script.


#!/bin/bash

#################################################################
#                                                               #
#                     ETTV slave script                         #
#                             -                                 #
#                           deej.                               #
#                                                               #
#################################################################
#                                                               #
#  This script can be used to start up an ETTV slave to connect #
#  to an ETTV HUB or directly to a game server.                 #
#                                                               #
#  The script generates etmain/server.cfg dynamically.          #
#                                                               #
#  This script launches the daemon in a different screen which  #
#  you can reattach with "screen -r slave"                      #
#                                                               #
#  Credits:                                                     #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#                                                               #
# Questions? deej@fragland.org or go to #gamestv.org            #
#                                                               #
#################################################################

# Webperoni Game Server IP
# ettv.fragland.org
PERONI_IP="83.133.81.192"

# Deinprovider WebServer IP
# ettv2.fragland.org
FRAGLAND_IP="217.20.115.116"

# Ionmedia Game Server IP
# ettv3.fragland.org
IONMEDIA_IP="62.216.174.68"

# Hetzner Game Server IP
# ettv4.fragland.org
HETZNER_IP="213.239.207.195"

# Planet Hosting Game Server IP
# ettv5.fragland.org
PLANET_IP="85.190.1.13"

#################################################################
#                                                               #
#                 Start Modifying From Here                     #
#                                                               #
#################################################################
#
# Hub Info
#
# IMPORTANT: Let the admin of the hub do a
# fdir *.pk3 in his console and give you the output!
#
# PK3 mismatches between game server and ETTV hosts
# account for the majority of crashes of ETTV.
# 
MATCH_DATE=`date +%Y%m%d`			# Do NOT modify
MATCH_HOST="et.fragland.org:27965"		# HUB / Match server port & address
MATCH_ETTV_PASS="[get_pass_from_admin]"		# HUB / Match server ETTV password
MATCH_PASS="[get_pass_from_admin]"		# HUB / Match server password

MATCH_HOME_TEAM="uQ"				# Making our hostname more fancy ;-)
MATCH_AWAY_TEAM="Logitech"
MATCH_CUP="Warleagues"

#
# Slave Info 
#
SLAVE_IP="$PERONI_IP"				# This host is Peroni
SLAVE_PORT="27960"				# port of public broadcaster

ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^1#^71"	# shows up on the Hub
SLAVE_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"

SLAVE_SLOTS="100"
SLAVE_PASS="[put_your_pass_here]"

SLAVE_PRIVATE_SLOTS="20"
SLAVE_PRIVATE_PASS="[put_your_pass_here]"

SLAVE_ETTV_SLAVES="5"				# Allow chaining?
SLAVE_ETTV_PASS="[put_your_pass_here]"

SLAVE_RCON_PASS="[put_your_pass_here]"

RECORD_GAME="1"					# 1 = record game, 0 = don't
SLAVE_DELAY="60"				# Time in seconds

REDIRECT="Server is full"			# Message displayed when server is full
#REDIRECT="ET://ettv2.fragland.org:27960"	# Allows redirecting to other ettv's

#
# Downloading
#
ALLOW_DL="1"					# Can clients download stuff?
ALLOW_WWW_DL="1"				# Allow downloading over http?
WWW_DL_URL="http://www.yoursite.com"		# No "/" at the end!

#
# ETTV Net settings for ETTV b8 & up
#
ETTV_NETBLAST="1"
ETTV_TV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_MTU="1400"

#
# Directories
#
BASEPATH="/srv/et/ETTV/ettv_slave"		# Path to ettv.x86
						# Use absolute paths here!

# 
# User To Launch Daemon
#
# Good practice:
# What doesn't need root priviliges doesn't get them!
#
# User gamed mentioned here under is not a standard linux user,
# he was created on our systems by us.
#
# gamed cannot log in. His homedir is equal to the path where
# all our servers are installed.
#
USER="gamed"

#################################################################
#                                                               #
#                     STOP Modifying Here                       #
#                                                               #
#################################################################
#
# Make sure buffers are ok!
#
echo "524288" > /proc/sys/net/core/rmem_max 
echo "524288" > /proc/sys/net/core/wmem_max 

#
# Assembling the Command Line
#
BINARY="ettv.x86"
DAEMON="$BASEPATH/$BINARY"
HOMEPATH="$BASEPATH/$MATCH_DATE"

SLAVE_OPTIONS="\
+set fs_game etpro \
+set dedicated 2 \
+set com_hunkMegs 256 \
+set net_ip $SLAVE_IP \
+set net_port $SLAVE_PORT \
+set fs_basepath $BASEPATH \
+set fs_homepath $HOMEPATH \
+set sv_maxclients $SLAVE_SLOTS \
+exec server.cfg"

#
# Functions
#

slave_start (){
	#
	# FYI the user
	#
	echo -n "Match Date is "
	echo -n "$MATCH_DATE"
	
	echo -e ".\nDemos are stored in $HOMEPATH/etpro/demos/.\n"

	#
	# Start the slave
	#
	echo -n "Starting Slave: "

	screen -dmS slave su -m -c "$DAEMON $SLAVE_OPTIONS" - $USER

	echo -e "done.\n"

	echo -e "Getting PID...\n"
	sleep 1
	
	SLAVE_PID=`pidof $DAEMON`
	
	echo -n "Slave has PID "
	echo -e "$SLAVE_PID.\n"
	
	if [ $SLAVE_ETTV_SLAVES != 0 ]
		then
			echo "ETTV slaves can now connect to your box by issuing:"
			echo -e "tv connect $SLAVE_IP:$SLAVE_PORT $SLAVE_ETTV_PASS $SLAVE_PASS\n"
	fi
}

slave_stop (){
	#	
	# Refresh the PID
	#
	SLAVE_PID=`pidof $DAEMON`
	
	echo -n "Shutting Down Slave: "
	sleep 1
	if [ $SLAVE_PID ]
		then
			kill -SIGTERM $SLAVE_PID
			echo -e "done."
		else
			echo -e "failed.\nSlave wasn't active anymore.\n"
	fi
}

create_config (){
	#
	# Generate etmain/server.cfg
	#	
	TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
	
	echo "//" > $BASEPATH/etmain/server.cfg
	echo "// server.cfg generated $TIMESTAMP" >> $BASEPATH/etmain/server.cfg
	echo -e "//\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set sv_privateclients $SLAVE_PRIVATE_SLOTS" >> $BASEPATH/etmain/server.cfg
	echo "set sv_maxRate 25000" >> $BASEPATH/etmain/server.cfg
	echo -e "set sv_hostname \"$SLAVE_HOSTNAME\"\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set g_password \"$SLAVE_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set rconpassword \"$SLAVE_RCON_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set sv_privatepassword \"$SLAVE_PRIVATE_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set sv_allowDownload $ALLOW_DL" >> $BASEPATH/etmain/server.cfg
	echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $BASEPATH/etmain/server.cfg
	echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $BASEPATH/etmain/server.cfg
	echo -e "set sv_wwwDlDisconnected 0\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set b_ettv_flags 3" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_delay $SLAVE_DELAY" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_autorecord $RECORD_GAME" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_sv_maxslaves \"$SLAVE_ETTV_SLAVES\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_password \"$SLAVE_ETTV_PASS\"" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_netblast $ETTV_NETBLAST" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $BASEPATH/etmain/server.cfg
	echo "set ettv_sv_iptos $ETTV_SV_IPTOS" >> $BASEPATH/etmain/server.cfg
	echo -e "set ettv_mtu $ETTV_MTU\n" >> $BASEPATH/etmain/server.cfg
	
	echo "set b_crashlogpath \"$BASEPATH/etpro\"" >> $BASEPATH/etmain/server.cfg
	echo "set g_log \"slave.log\"" >> $BASEPATH/etmain/server.cfg
	echo -e "set logfile 2\n" >> $BASEPATH/etmain/server.cfg
	
	echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $BASEPATH/etmain/server.cfg
}

clean_up (){
	#
	# Clean up prompt
	#
	echo -n "Clean up demos directory [y/n]? "
	read ANSWER
	case "$ANSWER" in
		y)
		rm -Rf $BASEPATH/$MATCH_DATE
		ls -l --color=always $BASEPATH
		;;
		*)
		echo "Following demos still exist:"
		ls -l --color=always $BASEPATH/$MATCH_DATE/etpro/demos/
		;;
	esac	
}

#
# Performing The magic :-)
#

case "$1" in
	start)
		create_config
		slave_start
		;;
	stop)
		slave_stop
		clean_up
		;;
	restart)
		$0 stop
		sleep 1
		$0 start
		;;	
	sim)
		create_config
		echo -e "\nFollowing config was generated automatically:\n"
		cat $BASEPATH/etmain/server.cfg
		;;
	*)
		SCRIPT_NAME=`basename $0`
		echo "Usage: $SCRIPT_NAME {start|stop|restart|sim}"
		exit 1
	;;
esac
exit 0

Old school record / playback script

This is a script to broadcast a game the old-fashioned way. It records a demo and starts playing it back after roughly 60 seconds. There's some symbolic linking stuff done inside to make sure it stores all the logs, otherwise the 'broadcaster' would override the recorder's log, which makes broadcasting very hard to debug :-)!


Copy / paste this script and save it as broadcast.sh or any other name you prefer. The usual comments on quit and 999 are applicable here as well. This script "should" work with ETTV earlier then b8. However, YMMV.


#!/bin/bash

#################################################################
#                                                               #
#            reT!reD.ettv delayed broadcast script              #
#                             -                                 #
#                        reT!reD.deej                           #
#                                                               #
#################################################################
#                                                               #
#  This script can be used to start up a delayed ETTV stream    #
#  where viewers connect directly to the broadcaster.           #
#                                                               #
#  This script creates a subdirectory which represents the      #
#  date of the match and stores the demos in this subdir.       #
#                                                               #
#  The script launches the daemons in different screens         #
#  which you can reattach with "screen -r recorder"             #
#  or "screen -r broadcaster".                                  #
#                                                               #
#  Credits:                                                     #
#  - Daita (pourix.net) for the original idea & script          #
#  - Tony J. White (et.tjw.org) for his ETDED on Linux guide    #
#                                                               #
# Questions? Contact me on deej@fragland.org or go to #r0f.et   #
#                                                               #
#################################################################
#                                                               #
#                   http://www.fragland.org                     #
#                                                               #
#################################################################

# Webperoni Game Server IP
# ettv.fragland.org
PERONI_IP="83.133.81.192"

# Deinprovider WebServer IP
# ettv2.fragland.org
FRAGLAND_IP="217.20.115.116"

# Ionmedia Game Server IP
# ettv3.fragland.org
IONMEDIA_IP="62.216.174.68"

# Hetzner Game Server IP
# WServer2.ath.cx IP
# ettv4.fragland.org
HETZNER_IP="213.239.207.195"

# Planet Hosting Game Server IP
# ettv.fragland.org
KLEIN_IP="83.243.82.88"

#################################################################
#                                                               #
#                       START Modifying                         #
#                                                               #
#################################################################
#
# Parameters of the Game Server to Connect to
#
# IMPORTANT: Let the admin of the game server do a
# fdir *.pk3 in his console and give you the output!
#
# PK3 mismatches between game server and ETTV hosts
# account for the majority of crashes of ETTV.
#
MATCH_DATE=`date +%Y%m%d`		# Do NOT modify
MATCH_HOST="et.fragland.org:27970"	# Match server port & address
MATCH_ETTV_PASS="[put_your_pass_here]"	# Match server ETTV password
MATCH_PASS="[put_your_pass_here]"	# Match server password

#
# Match info for setting hostname & storing demos
#
MATCH_HOME_TEAM="NED"
MATCH_AWAY_TEAM="BEL"
MATCH_CUP="NationsCup"

#
# IPs & Ports For Your Host
#
THISHOST_IP="$KLEIN_IP"			# Select from list above
RECORDER_PORT="29995"			# Port of the private recorder
SLAVE_PORT="27960"			# Port of the public broadcaster

#
# Hostnames & ETTV Client name
#
# - hostname shows up in server browsers
# - ETTV client name shows up as the name
#   of your server in the game server.
#
RECORDER_HOSTNAME="^7reT^1!^7reD^1.^7ettv ^7recorder ^1#^71"
ETTV_CLIENT="^7reT^1!^7reD^1.^7ettv ^1#^71"
SLAVE_HOSTNAME="$ETTV_CLIENT - ^3$MATCH_CUP^7: $MATCH_HOME_TEAM vs $MATCH_AWAY_TEAM"


#
# Passwords
#
RECORDER_RCON_PASS="[put_your_pass_here]"
RECORDER_PASS="[put_your_pass_here]"
SLAVE_RCON_PASS="[put_your_pass_here]"
SLAVE_PRIVATE_PASS="[put_your_pass_here]"
SLAVE_ETTV_PASS="[put_your_pass_here]"
SLAVE_PASS="[put_your_pass_here]"	# /rcon g_password "" to clear

#
# Other relevant settings
#
SLAVE_DELAY="60"			# Delay between live match &
					# broadcaster in seconds

SLAVE_SLOTS="100"
SLAVE_PRIVATE_SLOTS="25"
SLAVE_ETTV_SLAVES="0"			# Allow chaining?

REDIRECT="Server is full"		# Message displayed when server is full
#REDIRECT="ET://ettv2.fragland.org:27960"

#
# ETTV Net settings for ETTV b8 & up
#
ETTV_NETBLAST="1"
ETTV_TV_IPTOS="0"
ETTV_SV_IPTOS="0"
ETTV_MTU="1400"

#
# Download settings
#
ALLOW_DL="1"
ALLOW_WWW_DL="1"			# Allow downloading over http?
WWW_DL_URL="http://wwww.fragland.org/maps"

#
# Directories
#
BASEPATH="/srv/et/ETTV"			# Use absolute paths here!
RECORDER_BASEPATH="$BASEPATH/ettv_recorder"
SLAVE_BASEPATH="$BASEPATH/ettv_slave"

# 
# User To Launch Daemon
#
# Good practice:
# What doesn't need root priviliges doesn't get them!
#
# User gamed mentioned here under is not a standard linux user,
# he was created on our systems by us.
#
# gamed cannot log in. His homedir is equal to the path where
# all our servers are installed.
#
USER="gamed"

#################################################################
#                                                               #
#                        STOP Modifying                         #
#                                                               #
#################################################################
#
# Make sure buffers are ok!
#
echo "262144" > /proc/sys/net/core/rmem_max 
echo "262144" > /proc/sys/net/core/wmem_max 

#
# Assembling the Command Line
#
MATCH=""$MATCH_HOME_TEAM"vs"$MATCH_AWAY_TEAM""
HOMEPATH="$BASEPATH/$MATCH"

BINARY="ettv.x86"
RECORDER_DAEMON="$RECORDER_BASEPATH/$BINARY"
SLAVE_DAEMON="$SLAVE_BASEPATH/$BINARY"

RECORDER_OPTIONS="\
+set fs_game etpro \
+set dedicated 1 \
+set net_ip $THISHOST_IP \
+set net_port $RECORDER_PORT \
+set fs_basepath $RECORDER_BASEPATH \
+set fs_homepath $HOMEPATH \
+set com_hunkMegs 128 \
+exec recorder.cfg"

SLAVE_OPTIONS="\
+set fs_game etpro \
+set dedicated 2 \
+set net_ip $THISHOST_IP \
+set net_port $SLAVE_PORT \
+set fs_basepath $SLAVE_BASEPATH \
+set fs_homepath $HOMEPATH \
+set sv_maxclients $SLAVE_SLOTS \
+set com_hunkMegs 160 \
+exec slave.cfg"

#
# Only add for ETTV b8 & up
#
#+set ettv_mtu $ETTV_MTU \

#
# Functions
#

broadcast_start (){
	#
	# FYI'ing the user
	#
	echo -e "\n"
	echo -n "Match Date is "
	echo -n "$MATCH_DATE"

	echo -e ".\nDemos are stored in $HOMEPATH/etpro/demos/.\n"

	echo -n "Starting Recorder: "
	screen -dmS recorder su -m -c "$RECORDER_DAEMON $RECORDER_OPTIONS" - $USER
	echo "done."

	echo "Sleeping for $SLAVE_DELAY seconds."
	sleep $SLAVE_DELAY

	echo -n "Starting Broadcaster: "
	screen -dmS slave su -m -c "$SLAVE_DAEMON $SLAVE_OPTIONS" - $USER
	echo -e "done.\n"

	echo -e "Getting PIDs...\n"
	sleep 1

	get_pids
	
	echo -n "Recorder has PID "
	echo $RECORDER_PID
	renice -8 $RECORDER_PID
	echo -n "Broadcaster has PID "
	echo -e "$SLAVE_PID\n"
	renice -7 $SLAVE_PID
}

broadcast_stop (){

	get_pids
	
	echo -n "Shutting Down Slave: "
	sleep 1
	if [ $SLAVE_PID ]
		then
			kill -SIGTERM $SLAVE_PID
			echo -e "done."
		else
			echo -e "failed.\nSlave wasn't active anymore.\n"
	fi

	echo -n "Shutting Down Recorder: "
	sleep 1
	if [ $RECORDER_PID ]
		then
			kill -SIGTERM $RECORDER_PID
			echo -e "done."
		else
			echo -e "failed.\nRecorder wasn't active anymore.\n"
	fi

	sleep 1
}

clean_up (){
	#
	# Clean up prompt
	#
	echo -n "Clean up demos directory [y/n]? "
	read ANSWER
	case "$ANSWER" in
		y)
		rm -Rf $BASEPATH/$MATCH
		ls -l $BASEPATH
		;;
		*)
		echo "Following demos still exist:"
		ls -l $BASEPATH/$MATCH/etpro/demos/
		;;
	esac	
}

create_recorder_config (){
	#
	# Generate etmain/recorder.cfg
	#	
	TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
	RECORDER_CFG="$RECORDER_BASEPATH/etmain/recorder.cfg"
	
	echo "//" > $RECORDER_CFG
	echo "// config generated $TIMESTAMP" >> $RECORDER_CFG
	echo -e "//\n" >> $RECORDER_CFG
	
	echo "set sv_maxclients 2" >> $RECORDER_CFG
	echo "set sv_privateclients 0" >> $RECORDER_CFG
	echo "set sv_maxRate 25000" >> $RECORDER_CFG
	echo -e "set sv_hostname \"$RECORDER_HOSTNAME\"\n" >> $RECORDER_CFG
	
	echo "set g_password \"$RECORDER_PASS\"" >> $RECORDER_CFG
	echo "set rconpassword \"$RECORDER_RCON_PASS\"" >> $RECORDER_CFG
	echo -e "set sv_allowDownload 0\n" >> $RECORDER_CFG
		
	echo "set ettv_delay 1" >> $RECORDER_CFG
	echo "set ettv_autorecord 1" >> $RECORDER_CFG
	echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $RECORDER_CFG
	echo "set ettv_sv_maxslaves 0" >> $RECORDER_CFG
	echo "set ettv_netblast $ETTV_NETBLAST" >> $RECORDER_CFG
	echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $RECORDER_CFG
	echo -e "set ettv_sv_iptos $ETTV_SV_IPTOS\n" >> $RECORDER_CFG
	
	echo "set b_crashlogpath \"$RECORDER_BASEPATH/etpro\"" >> $RECORDER_CFG
	echo "set g_log \"recorder.log\"" >> $RECORDER_CFG
	echo -e "set logfile 2\n" >> $RECORDER_CFG
	
	echo "tv connect $MATCH_HOST $MATCH_ETTV_PASS $MATCH_PASS" >> $RECORDER_CFG
}

create_slave_config (){
	#
	# Generate etmain/slave.cfg
	#	
	TIMESTAMP=`date +"%d/%m/%Y %H:%M:%S"`
	SLAVE_CFG="$SLAVE_BASEPATH/etmain/slave.cfg"
	
	echo "//" > $SLAVE_CFG
	echo "// config generated $TIMESTAMP" >> $SLAVE_CFG
	echo -e "//\n" >> $SLAVE_CFG
	
	echo "set sv_maxclients $SLAVE_SLOTS" >> $SLAVE_CFG
	echo "set sv_privateclients $SLAVE_PRIVATE_SLOTS" >> $SLAVE_CFG
	echo "set sv_maxRate 25000" >> $SLAVE_CFG
	echo -e "set sv_hostname \"$SLAVE_HOSTNAME\"\n" >> $SLAVE_CFG
	
	echo "set g_password \"$SLAVE_PASS\"" >> $SLAVE_CFG
	echo "set rconpassword \"$SLAVE_RCON_PASS\"" >> $SLAVE_CFG
	echo "set sv_privatepassword \"$SLAVE_PRIVATE_PASS\"" >> $SLAVE_CFG
	echo "set sv_allowDownload $ALLOW_DL" >> $SLAVE_CFG
	echo "set sv_wwwDownload $ALLOW_WWW_DL" >> $SLAVE_CFG
	echo "set sv_wwwBaseURL \"$WWW_DL_URL\"" >> $SLAVE_CFG
	echo -e "set sv_wwwDlDisconnected 0\n" >> $SLAVE_CFG
	
	echo "set b_ettv_flags 3" >> $SLAVE_CFG
	echo "set ettv_delay 0" >> $SLAVE_CFG
	echo "set ettv_autorecord 0" >> $SLAVE_CFG
	echo "set ettv_clientname \"$ETTV_CLIENT\"" >> $SLAVE_CFG
	echo "set ettv_sv_maxslaves \"$SLAVE_ETTV_SLAVES\"" >> $SLAVE_CFG
	echo "set ettv_password \"$SLAVE_ETTV_PASS\"" >> $SLAVE_CFG
	echo "set ettv_netblast $ETTV_NETBLAST" >> $SLAVE_CFG
	echo "set ettv_tv_iptos $ETTV_TV_IPTOS" >> $SLAVE_CFG
	echo -e "set ettv_sv_iptos $ETTV_SV_IPTOS\n" >> $SLAVE_CFG
		
	echo "set b_crashlogpath \"$SLAVE_BASEPATH/etpro\"" >> $SLAVE_CFG
	echo "set g_log \"slave.log\"" >> $SLAVE_CFG
	echo -e "set logfile 2\n" >> $SLAVE_CFG
	
	echo "demo demo0000" >> $SLAVE_CFG
}

get_pids (){
	#
	# Since we want to run multiple casts in parallel we launch the same
	# binary twice or more. pidof then doesn't work so we have to recreate
	# the human behaviour of looking for the PID.
	#
	RECORDER_PID=`ps aux|grep "+set net_port $RECORDER_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"|grep -v grep|awk '{ print $2 }'`
	SLAVE_PID=`ps aux|grep "+set net_port $SLAVE_PORT"|grep -v "su -m -c"|grep -v "SCREEN -dmS"|grep -v grep|awk '{ print $2 }'`

}

#
# Performing The magic :-)
#

case "$1" in
	start)
		create_recorder_config
		create_slave_config
		broadcast_start
    		;;
	stop)
		broadcast_stop
		clean_up
		;;
	sim)
		create_recorder_config
		create_slave_config
		echo -e "\nFollowing configs were generated automatically:\n"
		cat $RECORDER_CFG | more
		cat $SLAVE_CFG | more
		;;
	*)
		SCRIPT_NAME=`basename $0`
		echo "Usage: $SCRIPT_NAME {start|stop|sim}"
		exit 1
		;;
esac
exit 0

Sanitization script

This is a script to restore an ETTV directory to the bare minimum required to broadcast matches or be a hub. It isn't a very advanced script but it gets the job done. Copy / paste this script and save it as sanitize.sh or any other name you prefer. Just do ./sanitize.sh do delete all files in etmain & etpro that are not needed anymore.


Note: this script deletes everything it finds in the etmain and etpro directories. If you have stuff that you do not want to delete in there, add it to the ETMAIN_FILES & ETPRO_FILES arrays.


#!/bin/bash

#################################################################
#                                                               #
#                     ettv clean-up script                      #
#                             -                                 #
#                           deej.                               #
#                                                               #
#################################################################
#                                                               #
# This script is used to restore an ETTV directory to the bare  #
# minimum in terms of files.                                    #
#                                                               #
# Use it to clean up after an ETTV session so you can start the #
# next session with a minimum of PK3s.                          #
#                                                               #
# Questions? Contact me on deej@fragland.org or go to #r0f.et   #
#                                                               #
#################################################################

ETMAIN_FILES=(\
"description.txt" \
"hunkusage.dat" \
"mp_bin.pk3" \
"pak0.pk3" \
"pak1.pk3" \
"pak2.pk3" \
"et_ice.pk3" \
"braundorf_b4.pk3" \
"supplydepot2.pk3" \
"sw_goldrush_te.pk3" \
"sw_oasis_b3.pk3")

ETPRO_FILES=(\
"etpro-3_2_4.pk3" \
"etpro_cheats.dat" \
"qagame.mp.i386.so" \
"tvgame.mp.i386.so")

SCRIPT_NAME=`basename $0`

case $1 in
	hub)
		BASEPATH="/srv/et/ETTV/ettv_hub"
		;;
	slave)
		BASEPATH="/srv/et/ETTV/ettv_slave"
		;;
	*)
		echo -e "\nError: $1 is not a valid installation target."
		echo -e "Usage: $SCRIPT_NAME {hub|slave}\n"
		exit 1
esac

#
# Test for existence of backup directories
#
if [ ! -d "$BASEPATH/etmain/bak/" ]; then
	mkdir "$BASEPATH/etmain/bak"
fi

if [ ! -d "$BASEPATH/etpro/bak/" ]; then
	mkdir "$BASEPATH/etpro/bak"
fi

#
# Clear etmain
#
for i in ${ETMAIN_FILES[@]}
do
	mv "$BASEPATH/etmain/$i" "$BASEPATH/etmain/bak/"
done
rm $BASEPATH/etmain/*

#
# Clear etpro
#
for i in ${ETPRO_FILES[@]}
do
	mv "$BASEPATH/etpro/$i" "$BASEPATH/etpro/bak/"
done
rm $BASEPATH/etpro/*

#
# Restore etmain
#
for i in ${ETMAIN_FILES[@]}
do
	mv "$BASEPATH/etmain/bak/$i" "$BASEPATH/etmain/"
done

#
# Restore etpro
#
for i in ${ETPRO_FILES[@]}
do
	mv "$BASEPATH/etpro/bak/$i" "$BASEPATH/etpro/"
done

#
# Clean the backup directories
#
rm -Rf $BASEPATH/etmain/bak
rm -Rf $BASEPATH/etpro/bak

Switching beta's script

This script allows you to quickly switch between the different beta's Bani has released. Just save it as switchbeta.sh and adapt the directory fields to your setup. Usage example: ./switchbeta.sh 9 hub switches the hub to beta 9. ./switchbeta.sh 4 all switches hub & slave (or others you can define of course) back to beta 4.

#!/bin/bash

#################################################################
#                                                               #
#                  switching ettv betas script                  #
#                             -                                 #
#                           deej.                               #
#                                                               #
#################################################################
#                                                               #
# This script allows you to easily switch ETTV beta versions.   #
#                                                               #
# Just put the ettv-beta[x].zip files in directory $REPODIR,    #
# adapt settings for hub & slave and start switching!           #
#                                                               #
# Questions? Contact me on deej@fragland.org or go to #r0f.et   #
#                                                               #
#################################################################

#
# Paths & files
#
REPODIR="/srv/et"			# Where the ettv-betaX.zip files reside
HUB_DIR="/srv/et/ETTV/ettv_hub"
SLAVE_DIR="/srv/et/ETTV/ettv_slave"

#
# Argument check
#
SCRIPT_NAME=`basename $0`
ARGS=2
E_BADARGS=65

if [ $# -lt "$ARGS" ]
then
	echo -e "\nError: missing arguments"
	echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|broadcast|all}\n"
	exit $E_BADARGS
fi

FILENAME="ettv-beta$1.zip"

if [ ! -e "$REPODIR/$FILENAME" ]
then
	echo -e "\nError: beta version $1 is not present in $REPODIR."
	echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|all}\n"
	exit $E_BADARGS
fi

case $2 in
	hub)
		unzip -o "$REPODIR/$FILENAME" -d "$HUB_DIR" ettv.x86
		chmod +x "$HUB_DIR/ettv.x86"
		unzip -o "$REPODIR/$FILENAME" -d "$HUB_DIR/etpro" tvgame.mp.i386.so
		;;
	slave)
		unzip -o "$REPODIR/$FILENAME" -d "$SLAVE_DIR" ettv.x86
		chmod +x "$SLAVE_DIR/ettv.x86"
		unzip -o "$REPODIR/$FILENAME" -d "$SLAVE_DIR/etpro" tvgame.mp.i386.so
		;;
	all)
		$0 $1 hub
		$0 $1 slave
		;;
	*)
		echo -e "\nError: $2 is not a valid installation target."
		echo -e "Usage: $SCRIPT_NAME {beta number} {hub|slave|all}\n"
		exit $E_BADARGS
esac
exit 0

Have fun broadcasting!

deej 01:46, 3 January 2006 (PST)