set ns [new Simulator]

#arg0: racer1
#arg1: racer2
#arg2: packetSize
#arg3: backbone bandwidth
#arg4: "	delay
#arg5: local	bandwidth
#arg6: "	delay
#arg7: TCPwindow
#arg8: rto


#STRIP ARGUMENTS
set i 0
foreach arg $argv {
        #puts "Arg $i : $arg"
        set args($i) $arg
        incr i
}

#SET DEFAULTS IF NO ARGUMENTS GIVEN
if {$argc == 3 } {
  #set args(2) 1460
  set args(3) "45Mb"
  set args(4) "20ms"
  set args(5) "1000Mb"
  set args(6) ".001ms"
  set args(7) 200
  set args(8) 50

} elseif {$argc != 9 } {
  puts "Incompatible arguments!"
  exit 0
}

#OPEN TRACE FILE
#set nf [open $args(0).vs.$args(1).nam w]
#set fTrace [open trace w]
#set fWin [open cwnd w ]

#UNCOMMENT THIS FOR FULL TRACE TO STDOUT
#$ns trace stdout

#######
#GLOBE##
#########

$ns use-scheduler List

Agent/TCP set window_ $args(7)  
Agent/TCP set packetSize_ $args(2)
#Agent/TCP set maxrto_ $args(8)
Agent/TCP set tcpTick_ 0.01
Agent/TCPSink/DelAck set interval_ 50ms
Agent/UDP set packetSize_ $args(2)
Application/FTP instproc start {} {
	[$self agent] send 104857600;
}

##########
#TOPOLOGY##
############

set n0 [$ns node]
set n1 [$ns node]

set n2 [$ns node]
set n3 [$ns node]

set n4 [$ns node]
set n5 [$ns node]

#LINKS
$ns duplex-link $n4 $n5 $args(3) $args(4) DropTail
$ns queue-limit $n4 $n5 100

$ns duplex-link $n0 $n4 $args(5) $args(6) DropTail
$ns duplex-link $n2 $n4 $args(5) $args(6) DropTail
$ns duplex-link $n5 $n1 $args(5) $args(6) DropTail
$ns duplex-link $n5 $n3 $args(5) $args(6) DropTail

#PRESENTATION
$ns duplex-link-op $n0 $n4 orient left-up
$ns duplex-link-op $n2 $n4 orient left-down
$ns duplex-link-op $n5 $n1 orient right-up
$ns duplex-link-op $n5 $n3 orient right-down
$ns color 1 Blue
$ns color 2 Red

###########
#FUNCTIONS##
#############

proc finish {} {
        global ns #fTrace fWin
        $ns flush-trace
	#close $fTrace
	#close $fWin
        #iexec nam out.nam &
        exit 0
}
proc newSource {node type color } {
  	global ns

	set src [new $type]
	$src set class_ $color
	$ns attach-agent $node $src
	return $src
}
proc newTCPSource {node type color } {
  	global ns #fWin

	set src [new $type]
	$src trace cwnd_
	#$src trace ssthresh_ 
	$src attach stdout
	$src set class_ $color
	$ns attach-agent $node $src
	return $src
}
proc newSink {node type} {
	global ns

	set snk [new $type]
	$ns attach-agent $node $snk
	#$snk listen;
	return $snk
}
proc ftp {src} {
	set ftp [new Application/FTP]
	$ftp attach-agent $src
	return $ftp
}
proc cbr {src} {
	set cbr [new Application/Traffic/CBR]
	$cbr attach-agent $src
	$cbr set type_ CBR
	$cbr set packetSize_ 1460b
	$cbr set interval_ .4ms
	return $cbr
}
proc poisson {src} {
	set e [new Application/Traffic/Exponential]
	$e attach-agent $src
	$e set packetSize_ $args(2)
	$e set burst_time_ 50ms
	$e set idle_time_ 100ms
	$e set rate_ 879Kb
	return $e
}
proc pareto {src} {
	set p [new Application/Traffic/Pareto]
	$p attach-agent $src
	$p set packetSize_ $args(2)
	$p set burst_time_ 50ms
	$p set idle_time_ 100ms
	$p set rate_ 879Kb
	$p set shape_ 1.1
	return $p
}

proc createDude { type color n0 n1} {
	global ns args

	#TAHOE
	if {[string compare $type "tahoe"] == 0}  {
		set src [newTCPSource $n0 Agent/TCP $color]
		set snk [newSink   $n1 Agent/TCPSink/DelAck]
		$ns connect $src $snk
		set ftp0 [ftp $src]
		$ns at 0 "$ftp0 start"
		return
	} elseif {[string compare $type "reno"] == 0}  {
	#RENO
		set src [newTCPSource $n0 Agent/TCP/Newreno $color]
		set snk [newSink   $n1 Agent/TCPSink/DelAck]
		$ns connect $src $snk
		set ftp0 [ftp $src]
		$ns at 0 "$ftp0 start"
		return
	} elseif {[string compare $type "sack"] == 0}  {
	#SACK
		set src [newTCPSource $n0 Agent/TCP/Sack1 $color]
		set snk [newSink   $n1 Agent/TCPSink/Sack1/DelAck]
		$ns connect $src $snk
		set ftp0 [ftp $src]
		$ns at 0 "$ftp0 start"
		return
	} elseif {[string compare $type "cbr"] == 0}  {
	#CBR
		set src [newSource $n0 Agent/UDP $color]
		set snk [newSink   $n1 Agent/Null]
		$ns connect $src $snk
		set cbr0 [cbr $src]
		$ns at 0 "$cbr0 start"
		return
	} elseif {[string compare $type "poisson"] == 0}  {
	#POISSON
		for {set i 0} {$i < 10} {incr i} {
			set src($i) [newSource $n0 Agent/UDP 10]
			set snk($i) [newSink   $n1 Agent/Null]
			$ns connect $src($i) $snk($i)
			set poisson($i) [poisson $src($i)]
			$ns at 0 "$poisson($i) start"
		}
		return
	} elseif {[string compare $type "pareto"] == 0}  {
	#PARETO
		for {set i 0} {$i < 10} {incr i} {
			set src($i) [newSource $n0 Agent/UDP 10]
			set snk($i) [newSink   $n1 Agent/Null]
			$ns connect $src($i) $snk($i)
			set pareto($i) [pareto $src($i)]
			$ns at 0 "$pareto($i) start"
		}
		return
	} elseif {[string compare $type "mirror"] == 0}  {
	#MIRROR	
		if {[string compare $args(0) "mirror"] == 0} {
			createDude $args(1) 2 $n0 $n1
		}
		if {[string compare $args(1) "mirror"] == 0} {
			createDude $args(0) 2 $n0 $n1
		}
		return
	} else {
		puts "You Can't Type"
		exit 0
	}
}

#FIRST RACER
createDude $args(0) 1 $n0 $n1
#SECOND RACER
createDude $args(1) 2 $n2 $n3

$ns at 80 "finish"
$ns run

