private void encryptAndSend(Message msg) throws Exception { EncryptHeader hdr = new EncryptHeader(EncryptHeader.ENCRYPT, getSymVersion()); if (this.encrypt_entire_message) hdr.type |= EncryptHeader.ENCRYPT_ENTIRE_MSG; if (encrypt_entire_message) { if (msg.getSrc() == null) msg.setSrc(local_addr); Buffer serialized_msg = Util.streamableToBuffer(msg); byte[] encrypted_msg = code( serialized_msg.getBuf(), serialized_msg.getOffset(), serialized_msg.getLength(), false); // exclude existing headers, they will be seen again when we decrypt and unmarshal the msg at // the receiver Message tmp = msg.copy(false, false).setBuffer(encrypted_msg).putHeader(this.id, hdr); down_prot.down(new Event(Event.MSG, tmp)); return; } // copy neeeded because same message (object) may be retransmitted -> no double encryption Message msgEncrypted = msg.copy(false) .putHeader(this.id, hdr) .setBuffer(code(msg.getRawBuffer(), msg.getOffset(), msg.getLength(), false)); down_prot.down(new Event(Event.MSG, msgEncrypted)); }
protected void forward(final Message msg, long seqno, boolean flush) { Address target = coord; if (target == null) return; byte type = flush ? SequencerHeader.FLUSH : SequencerHeader.FORWARD; try { SequencerHeader hdr = new SequencerHeader(type, seqno); Message forward_msg = new Message(target, Util.streamableToBuffer(msg)).putHeader(this.id, hdr); down_prot.down(new Event(Event.MSG, forward_msg)); forwarded_msgs++; } catch (Exception ex) { log.error(Util.getMessage("FailedForwardingMessageTo") + msg.getDest(), ex); } }
/** * Sends all messages currently in forward_table to the new coordinator (changing the dest field). * This needs to be done, so the underlying reliable unicast protocol (e.g. UNICAST) adds these * messages to its retransmission mechanism<br> * Note that we need to resend the messages in order of their seqnos ! We also need to prevent * other message from being inserted until we're done, that's why there's synchronization.<br> * Access to the forward_table doesn't need to be synchronized as there won't be any insertions * during flushing (all down-threads are blocked) */ protected void flushMessagesInForwardTable() { if (is_coord) { for (Map.Entry<Long, Message> entry : forward_table.entrySet()) { Long key = entry.getKey(); Message msg = entry.getValue(); Buffer buf; try { buf = Util.streamableToBuffer(msg); } catch (Exception e) { log.error(Util.getMessage("FlushingBroadcastingFailed"), e); continue; } SequencerHeader hdr = new SequencerHeader(SequencerHeader.WRAPPED_BCAST, key); Message forward_msg = new Message(null, buf).putHeader(this.id, hdr); if (log.isTraceEnabled()) log.trace(local_addr + ": flushing (broadcasting) " + local_addr + "::" + key); down_prot.down(new Event(Event.MSG, forward_msg)); } return; } // for forwarded messages, we need to receive the forwarded message from the coordinator, to // prevent this case: // - V1={A,B,C} // - A crashes // - C installs V2={B,C} // - C forwards messages 3 and 4 to B (the new coord) // - B drops 3 because its view is still V1 // - B installs V2 // - B receives message 4 and broadcasts it // ==> C's message 4 is delivered *before* message 3 ! // ==> By resending 3 until it is received, then resending 4 until it is received, we make sure // this won't happen // (see https://issues.jboss.org/browse/JGRP-1449) while (flushing && running && !forward_table.isEmpty()) { Map.Entry<Long, Message> entry = forward_table.firstEntry(); final Long key = entry.getKey(); Message msg = entry.getValue(); Buffer buf; try { buf = Util.streamableToBuffer(msg); } catch (Exception e) { log.error(Util.getMessage("FlushingBroadcastingFailed"), e); continue; } while (flushing && running && !forward_table.isEmpty()) { SequencerHeader hdr = new SequencerHeader(SequencerHeader.FLUSH, key); Message forward_msg = new Message(coord, buf).putHeader(this.id, hdr).setFlag(Message.Flag.DONT_BUNDLE); if (log.isTraceEnabled()) log.trace( local_addr + ": flushing (forwarding) " + local_addr + "::" + key + " to coord " + coord); ack_promise.reset(); down_prot.down(new Event(Event.MSG, forward_msg)); Long ack = ack_promise.getResult(500); if ((Objects.equals(ack, key)) || !forward_table.containsKey(key)) break; } } }
public static Buffer marshal(PingData data) { return Util.streamableToBuffer(data); }