#!env python
# Inleiding Telematica, opdracht 2.
# 0440949, Andreas van Cranenburgh, 2007.
#
# This code connects to a set of "routers" (SOAP servers), and finds
# out what servers can be reached, and which is the best route for each.

PythonPath = "['~/lib/python']"
from SOAPpy import SOAPProxy

def main():
	url = '146.50.7.30:8080'	# ow120.science.uva.nl

	print "initial connection:", url, " . . .",
	
	name, peers = visitVR(url)
	names, costs = {url:name}, {url:peers}
	stack = peers.keys()
	visited = [url]
	
	# PART 1: find VRs and their names
	while not stack == []:
		while url in visited:
			url = stack.pop()
		print "connecting to", url, " . . .",
		name, peers = visitVR(url)
		visited.append(url)
		#check if VR could be reached, ignore results if not.
		if not name == '':
			names[url] = name
			costs[url] = peers
			#add new VRs, but only ones not visited or queued yet.
			for a in peers.keys(): 
				if not a in stack and not a in visited:
					stack.append(a)
	
	# PART 2: calculate cheapest routes (offline)
	routes = FloydWarshall(costs)
	# pretty print
	print "Routes:"
	for a,b in routes.keys():
		print names[a], "-->", names[b], "=", routes[(a,b)][0], ":", [names[x] for x in routes[(a,b)][1]]

def FloydWarshall(costs):
	pairs = []
	path = {}
	
	#initialize the path dictionary with direct links and their costs
	#the rest will be initialized to 'infinity'
	#path is indexed by a tuple of source and destination, and contains
	#a tuple of cost and the list of hops (including both source and destination).
	for a in costs.keys():
		for b in costs.keys():
			if not a ==b:
				pairs.append((a,b))
				try:
					path[(a,b)] = (int(costs[a][b]), [a,b])
				except:
					path[(a,b)] = (32767, [a,b])	#infinity...
	
	#find paths by comparing cost of direct route with the route via k,
	#updating path where applicable.
	for k in costs.keys():
		for a,b in pairs:
			if not k in (a, b):
				if path[(a,k)][0] + path[(k,b)][0] < path[(a,b)][0]:
					path[(a,b)] = (path[(a,k)][0] + path[(k,b)][0], path[(a,k)][1][:-1] + path[(k,b)][1])
				
	return path
	
def visitVR(url):
	#visit VR, return name and IPs of connected VRs.
	server = SOAPProxy(url)
	VRname, VRcosts = "", {}
	try:
		VRname = server.getVRName()
		print "found name:", VRname
		print "List of VRs:",
		VRs = server.getConnected().split(",")
		for a in VRs:
			try:
				VRcosts[a] = server.getLinkSpeed(a.split(":")[0])
				print a, "(linkcost", VRcosts[a], ")"
			except:
				VRcosts[a] = 0
				print "getLinkSpeed for", a, "failed."
		print
	except:
		print "some error with:", url
	return VRname, VRcosts

main()
