@Override
	public void receive(Message m){
	
	// Get the process ID from the message
	int processID = m.getSource();
	
	long time =  System.currentTimeMillis();
	
	String[] messageParts =  m.getPayload().split(" ");
	
	
	// Get payload information for  heartbeat ID and when heartbeat was sent
	int heartbeatID = Integer.parseInt(messageParts[0]);
	long heartbeatTime =  Long.parseLong(messageParts[1]);
	// int messageSource = Integer.parseInt(messageParts[2]);

	// if (messageSource != p.pid){ //this message was not meant for us.
	//     Utils.out(p.pid, "dumped " + messageSource );
	//     return;
	//}
	
	// Calculate the delay for the message
	long delay = time- heartbeatTime;

        // If this heartbeat is received in the correct time period
	if ( heartbeatTime + maxDelays[processID-1] >= time){
         
            // Make note that this process is still active
            successfulReplies[processID-1] = true;

	    //if this process was previously suspected .. unsuspect it
	    if (suspectedProcesses[processID-1] ){
		suspectedProcesses[processID-1] = false;
		getLeader();
	    } 

	}

	TreeSet<Integer> processTree = missingMessageIDs[processID-1];

	// If there is a huge delay on the transmission this is still deemed to 
	// be correct behaviour if all the packets have the same delay (ie they
	// still arrive in order).  This implies that even if a process is 
	// 50 times slower than the rest we will still consider it correct
	maxDelays[processID -1] = Math.max(maxDelays[processID-1],delay);
	Utils.out(p.pid,"Reply process " + processID + " delay " + delay + " max " + maxDelays[processID -1]);

	/*******
		This checks whether all heartbeats are here or not.. if more than 50 hearbeats go missing
		the process is deemed to be permanently faulty. This is to deal with unstable networks 
		where messages might arrive out of order or with heavy delays. Using this we are somewhat
		reliably able to detect if the process is faulty by ensuring that the messages arrive in
		sequence
	*******/



	// If processTree is null then this is permanently suspected 
	if (processTree == null) return;  

	if (highestMessageIDRecieved[processID-1] + 1 == heartbeatID ) {
	// Case where we receive the next message we expect to receive
	    highestMessageIDRecieved[processID-1]++;

	} else if (highestMessageIDRecieved[processID-1] + 1 > heartbeatID) {
	    // This is the case where we have previously missed this ID and it has	 
	    // come in late
	    if (processTree.contains(heartbeatID)) {
		    processTree.remove(heartbeatID);
	    } else {
		Utils.out(p.pid, "Error removing heartbeat from tree");
	    }
	    
	} else {
	    // this is the case where we receive a message ID greater than the one we expect
	    for (int i = highestMessageIDRecieved[processID-1] + 1; i < heartbeatID; i++) {
		processTree.add(i);
	    } 

	    if (processTree.size() > TOLERANCE) {
		missingMessageIDs[processID-1] = null;
		getLeader();
		Utils.out(p.pid, "Process now permanently suspected" + processID);
	    }

	    highestMessageIDRecieved[processID-1] = heartbeatID;
	}


    }