content: /*
   * Copyright 2011 Aalto University, ComNet
   * Released under GPLv3. See LICENSE.txt for details.
   */
  package routing;
  
  import java.util.Vector;
  
  import core.DTNHost;
  import core.Message;
  import core.Settings;
  import core.Connection;
  
  /**
   * Router module mimicking the game-of-life behavior
   */
  public class LifeRouter extends ActiveRouter {
  
  	/**
  	 * Neighboring message count -setting id ({@value}). Two comma
  	 * separated values: min and max. Only if the amount of connected nodes
  	 * with the given message is between the min and max value, the message
  	 * is accepted for transfer and kept in the buffer.
  	 */
  	public static final String NM_COUNT_S = "nmcount";
  	private int countRange[];
  
  	/**
  	 * Constructor. Creates a new message router based on the settings in
  	 * the given Settings object.
  	 * @param s The settings object
  	 */
  	public LifeRouter(Settings s) {
  		super(s);
  		countRange = s.getCsvInts(NM_COUNT_S, 2);
  	}
  
  	/**
  	 * Copy constructor.
  	 * @param r The router prototype where setting values are copied from
  	 */
  	protected LifeRouter(LifeRouter r) {
  		super(r);
  		this.countRange = r.countRange;
  	}
  
  	/**
  	 * Counts how many of the connected peers have the given message
  	 * @param m The message to check
  	 * @return Amount of connected peers with the message
  	 */
  	private int getPeerMessageCount(Message m) {
  		DTNHost me = getHost();
  		String id = m.getId();
  		int peerMsgCount = 0;
  
  		for (Connection c : getConnections()) {
  			if (c.getOtherNode(me).getRouter().hasMessage(id)) {
  				peerMsgCount++;
  			}
  		}
  
  		return peerMsgCount;
  	}
  
  	@Override
  	protected int checkReceiving(Message m, DTNHost from) {
  		int peerMsgCount = getPeerMessageCount(m);
  
  		if (peerMsgCount < this.countRange[0] ||
  				peerMsgCount > this.countRange[1]) {
  			return DENIED_POLICY;
  		}
  
  		/* peer message count check OK; receive based on other checks */
  		return super.checkReceiving(m, from);
  	}
  
  	@Override
  	public void update() {
  		int peerMsgCount;
  		Vector<String> messagesToDelete = new Vector<String>();
  		super.update();
  
  		if (isTransferring() || !canStartTransfer()) {
  			return; /* transferring, don't try other connections yet */
  		}
  
  		/* Try first the messages that can be delivered to final recipient */
  		if (exchangeDeliverableMessages() != null) {
  			return;
  		}
  		this.tryAllMessagesToAllConnections();
  
  		/* see if need to drop some messages... */
  		for (Message m : getMessageCollection()) {
  			peerMsgCount = getPeerMessageCount(m);
  			if (peerMsgCount < this.countRange[0] ||
  					peerMsgCount > this.countRange[1]) {
  				messagesToDelete.add(m.getId());
  			}
  		}
  		for (String id : messagesToDelete) { /* ...and drop them */
  			this.deleteMessage(id, true);
  		}
  
  	}
  
  
  	@Override
  	public LifeRouter replicate() {
  		return new LifeRouter(this);
  	}
  
  }
  