""" Urvashi Soni gives the connectivity graph and latency information of all nodes in a group. """ # send a probe message to each neighbor def probe_neighbors_forever(): # Call me again in 10 seconds while True: for neighborip in mycontext["neighborlist"]: mycontext['sendtime'][neighborip] = getruntime() if neighborip == mycontext['myip']: #do nothing continue sendmessage(neighborip, mycontext['port'], 'ping',mycontext['myip'],mycontext['port']) sendmessage(neighborip,mycontext['port'],'share'+encode_row(mycontext['myip'],mycontext["neighborlist"],mycontext['latency'].copy()),mycontext['myip'],mycontext['port']) sleep(0.5) #sleep for 10 sec and start from while loop again sleep(10) # Handle an incoming message def got_message(srcip,srcport,mess): if mess == 'ping': sendmessage(srcip,srcport,'pong',mycontext['myip'], pingport) elif mess == 'pong': # elapsed time is now - time when I sent the ping mycontext['latency'][srcip] = getruntime() - mycontext['sendtime'][srcip] elif mess.startswith('share'): mycontext['row'][srcip] = mess[len('share'):] def encode_row(rowip, neighborlist, latencylist): retstring = ""+rowip+"" for neighborip in neighborlist: if neighborip in latencylist: retstring = retstring + ""+str(latencylist[neighborip])[:4]+"s" else: retstring = retstring + "Unknown" retstring = retstring + "" return retstring # Generates a HTML page that represents the current status of the program def generate_status_page(): webpage = "Latency Information

Latency information from "+mycontext['myip']+'

' webpage = webpage + "" for nodeip in mycontext['neighborlist']: if nodeip in mycontext['row']: webpage = webpage + mycontext['row'][nodeip]+'\n' elif nodeip == mycontext['myip']: webpage = webpage + encode_row(mycontext['myip'],mycontext["neighborlist"],mycontext['latency'].copy()) + '\n' else: webpage = webpage + '\n' # now the footer... webpage = webpage + '
"+ "".join(mycontext['neighborlist'])+"
'+nodeip+'No Data Reported
' return webpage # Displays a web page with the latency information def handle_http_request(srcip,srcport,connobj): log('received request from',srcip,'\n') # Get the header total_data = '' # The HTTP header ends once we see the char combination '\n\n', which # is an empty string. while '\n\n' not in total_data: # Receive in chunks to avoid reading too much data try: data = connobj.recv(4096) except SocketWouldBlockError: # retry if they haven't completed sending the header sleep(.05) continue except SocketClosedRemote: log('client from',srcip,'aborted before sending HTTP header...\n') return total_data += data total_data = total_data.replace('\r\n', '\n') header, overflow = total_data.split('\n\n', 1) # Get the request path, which is inbetween the HTTP action keyword and the # HTTP version number. # The http action keyword is the first word with no whitespace. everything_after_httpaction = header.split(None, 1)[1] # Following the path is the HTTP/[VERSION_NUMBER]. # We can use that as a delimiter to extract the path. request_path = everything_after_httpaction.split(" HTTP/")[0] # Generate the data to send back # Don't respond with anything if they have something in the request path. # This include favicons. We don't want to generate the webpage needlessly. if request_path != '/': data = 'HTTP/1.1 404 Not Found\n\n' else: webpage = generate_status_page() # combine everything into one unit for sending data = 'HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length: '+str(len(webpage))+'\nServer: Seattle Testbed\n\n'+webpage # send the response sent = 0 while sent < len(data): try: sent += connobj.send(data[sent:]) except SocketWouldBlockError: # retry if response hasn't been sent yet sleep(.05) continue except SocketClosedRemote: log('client from',srcip,'aborted before response could be sent...\n') return # and we're done, so let's close this connection... connobj.close() def handle_message_forever(): while True: try: srcip, srcport, mess = udpserversocket.getmessage() got_message(srcip, srcport, mess) except SocketWouldBlockError: sleep(0.1) def handle_connection_forever(): while True: try: ret_ip, ret_port, ret_socket = connobj.getconnection() handle_http_request(ret_ip, ret_port, ret_socket) except SocketWouldBlockError: sleep(0.1) if callfunc == 'initialize': # this holds the response information (i.e. when nodes responded) mycontext['latency'] = {} mycontext['myip'] = getmyip() log(mycontext['myip']) # this remembers when we sent a probe mycontext['sendtime'] = {} # this remembers row data from the other nodes mycontext['row'] = {} # get the nodes to probe mycontext['neighborlist'] = [] try: fileobject = openfile('neighboriplist.txt',False) filecontent = fileobject.readat(None,0) neighbor_array = filecontent.splitlines() for line in neighbor_array: mycontext['neighborlist'].append(line.strip()) except FileNotFoundError, e: raise FileNotFoundError("neighboriplist.txt file doesn't exist. Please provide the required file in same directory.") if len(callargs) != 1: raise Exception, "Must specify the port to use" pingport = int(callargs[0]) mycontext['port'] = pingport #listen for a new message and call handle_message in new thread udpserversocket = listenformessage(mycontext['myip'], mycontext['port']) createthread(handle_message_forever) createthread(probe_neighbors_forever) #listen for connection and call handle_http_request once a connection is got connobj = listenforconnection(mycontext['myip'],mycontext['port']) createthread(handle_connection_forever)