/** * Create an Action object * * @param context Android context * @param messageTypeToListenTo the type of message that concern this action * @param poll the poll to fill in this action * @param timeOut the maximum time in millisecond that this action can last */ public AbstractAction( Context context, String messageTypeToListenTo, ProtocolPoll poll, long timeOut) { TAG = this.getClass().getSimpleName(); // Map of message received this.messagesReceived = new HashMap<String, ProtocolMessageContainer>(); // Store some important entities that will be used in the actions this.context = context; this.poll = poll; this.timeOut = timeOut; for (Participant p : poll.getParticipants().values()) { if (p.getUniqueId() .equals(AndroidApplication.getInstance().getNetworkInterface().getMyUniqueId())) { this.me = (ProtocolParticipant) p; } } if (messageTypeToListenTo != null) { // Subscribing to the messageArrived events to update immediately LocalBroadcastManager.getInstance(context) .registerReceiver(this.voteMessageReceiver, new IntentFilter(messageTypeToListenTo)); } }
/** * Method called when a received message has been processed and values contained in the message * must be saved * * @param round Round to which the received message belongs * @param sender the sender of the message * @param message the message received * @param exclude if the processing of the message done imply the exclusion of the participant */ public void savedProcessedMessage( Round round, String sender, ProtocolMessageContainer message, boolean exclude) { this.numberOfProcessedMessages++; if (!messagesReceived.containsKey(sender)) { messagesReceived.put(sender, message); Log.d( TAG, "Message received from " + poll.getParticipants().get(sender).getIdentification() + " (" + sender + ") back from processing."); } }
@Override public void onReceive(Context context, Intent intent) { String action = intent.getStringExtra("action"); if (action == null || action.equals("")) { return; } else if (action.equals("left")) { Participant p = poll.getParticipants().get(intent.getStringExtra("id")); if (p != null) { if (AbstractAction.this instanceof SetupRoundAction) { poll.getCompletelyExcludedParticipants().put(p.getUniqueId(), p); // notify exclusion LocalBroadcastManager.getInstance(AndroidApplication.getInstance()) .sendBroadcast( new Intent(BroadcastIntentTypes.proofVerificationFailed) .putExtra("type", 2) .putExtra("participant", p.getIdentification())); Log.w( TAG, "Participant " + p.getIdentification() + " (" + p.getUniqueId() + ") went out of the network before submitting the setup value, so he was completely excluded (also from recovery)."); } else { poll.getExcludedParticipants().put(p.getUniqueId(), p); // notify exclusion LocalBroadcastManager.getInstance(AndroidApplication.getInstance()) .sendBroadcast( new Intent(BroadcastIntentTypes.proofVerificationFailed) .putExtra("type", 3) .putExtra("participant", p.getIdentification())); Log.w( TAG, "Participant " + p.getIdentification() + " (" + p.getUniqueId() + ") was added to excluded list since he went out of the network."); } } } if (readyToGoToNextState() && !actionTerminated) { goToNextState(); } }
/** * Indicate if conditions to go to next step are fulfilled * * @return true if conditions are fulfilled, false otherwise */ protected boolean readyToGoToNextState() { Collection<Participant> activeParticipants = new ArrayList<Participant>(); for (Participant p : poll.getParticipants().values()) { activeParticipants.add(p); } activeParticipants.removeAll(poll.getExcludedParticipants().values()); activeParticipants.removeAll(poll.getCompletelyExcludedParticipants().values()); for (Participant p : activeParticipants) { if (!this.messagesReceived.containsKey(p.getUniqueId())) { Log.w( TAG, "Message from " + p.getUniqueId() + " (" + p.getIdentification() + ") not received"); return false; } } return true; }
@Override public void onReceive(Context context, Intent intent) { if (actionTerminated) return; // Get the message ProtocolMessageContainer message = (ProtocolMessageContainer) intent.getSerializableExtra("message"); String sender = intent.getStringExtra("sender"); if (messagesReceived.get(sender) != null && messagesReceived.get(sender).equals(message)) { // when resending message, check if message differs from one received previously Log.w(TAG, "Seems to receive a different message from same source !!!"); return; } // When a new message arrives, we re-execute the action of the step if (actionTerminated) { Log.w(TAG, "Action was called by an incoming message, but was already terminated"); return; } // Ignore messages from excluded participant if (poll.getExcludedParticipants().containsKey(sender)) { Log.w(TAG, "Ignoring message from previously excluded participant!"); return; } if (sender.equals(me.getUniqueId())) { Log.d(TAG, "Message received from myself, not needed to process it."); if (!messagesReceived.containsKey(sender)) { messagesReceived.put(sender, message); Log.d(TAG, "Message received from " + sender); } if (readyToGoToNextState()) goToNextState(); return; } numberMessagesReceived++; Log.d( TAG, "Message received from " + poll.getParticipants().get(sender).getIdentification() + " (" + sender + "). Going to process it"); Round round = null; if (AbstractAction.this instanceof SetupRoundAction) { round = Round.setup; } else if (AbstractAction.this instanceof CommitmentRoundAction) { round = Round.commit; poll.getParticipants().get(sender).setHasVoted(true); // notify UI about new incomed vote Intent i = new Intent(BroadcastIntentTypes.newIncomingVote); i.putExtra("votes", numberMessagesReceived); i.putExtra("options", (Serializable) poll.getOptions()); i.putExtra("participants", (Serializable) poll.getParticipants()); LocalBroadcastManager.getInstance(context).sendBroadcast(i); } else if (AbstractAction.this instanceof VotingRoundAction) { round = Round.voting; } else if (AbstractAction.this instanceof RecoveryRoundAction) { round = Round.recovery; } Log.d(TAG, "Sending to processing service"); Intent intent2 = new Intent(context, ProcessingService.class); intent2.putExtra("round", (Serializable) round); intent2.putExtra("message", (Serializable) message); intent2.putExtra("sender", sender); context.startService(intent2); }