Beispiel #1
0
  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));
  }
Beispiel #2
0
  /**
   * We need to resend our first message with our conn_id
   *
   * @param sender
   * @param seqno Resend the non null messages in the range [lowest .. seqno]
   */
  protected void handleResendingOfFirstMessage(Address sender, long seqno) {
    if (log.isTraceEnabled())
      log.trace(local_addr + " <-- SEND_FIRST_SEQNO(" + sender + "," + seqno + ")");
    SenderEntry entry = send_table.get(sender);
    Table<Message> win = entry != null ? entry.sent_msgs : null;
    if (win == null) {
      if (log.isErrorEnabled())
        log.error(local_addr + ": sender window for " + sender + " not found");
      return;
    }

    boolean first_sent = false;
    for (long i = win.getLow() + 1; i <= seqno; i++) {
      Message rsp = win.get(i);
      if (rsp == null) continue;
      if (first_sent) {
        down_prot.down(new Event(Event.MSG, rsp));
      } else {
        first_sent = true;
        // We need to copy the UnicastHeader and put it back into the message because Message.copy()
        // doesn't copy
        // the headers and therefore we'd modify the original message in the sender retransmission
        // window
        // (https://jira.jboss.org/jira/browse/JGRP-965)
        Message copy = rsp.copy();
        Unicast2Header hdr = (Unicast2Header) copy.getHeader(this.id);
        Unicast2Header newhdr = hdr.copy();
        newhdr.first = true;
        copy.putHeader(this.id, newhdr);
        down_prot.down(new Event(Event.MSG, copy));
      }
    }
  }
Beispiel #3
0
  /**
   * Send all fragments as separate messages (with same ID !). Example:
   *
   * <pre>
   * Given the generated ID is 2344, number of fragments=3, message {dst,src,buf}
   * would be fragmented into:
   *
   * [2344,3,0]{dst,src,buf1},
   * [2344,3,1]{dst,src,buf2} and
   * [2344,3,2]{dst,src,buf3}
   * </pre>
   */
  private void fragment(Message msg) {
    try {
      byte[] buffer = msg.getRawBuffer();
      List<Range> fragments = Util.computeFragOffsets(msg.getOffset(), msg.getLength(), frag_size);
      int num_frags = fragments.size();
      num_sent_frags.addAndGet(num_frags);

      if (log.isTraceEnabled()) {
        Address dest = msg.getDest();
        StringBuilder sb = new StringBuilder("fragmenting packet to ");
        sb.append((dest != null ? dest.toString() : "<all members>"))
            .append(" (size=")
            .append(buffer.length);
        sb.append(") into ")
            .append(num_frags)
            .append(" fragment(s) [frag_size=")
            .append(frag_size)
            .append(']');
        log.trace(sb.toString());
      }

      long frag_id = getNextId(); // used as a seqno
      for (int i = 0; i < fragments.size(); i++) {
        Range r = fragments.get(i);
        // don't copy the buffer, only src, dest and headers. Only copy the headers one time !
        Message frag_msg = msg.copy(false, i == 0);
        frag_msg.setBuffer(buffer, (int) r.low, (int) r.high);
        FragHeader hdr = new FragHeader(frag_id, i, num_frags);
        frag_msg.putHeader(this.id, hdr);
        down_prot.down(new Event(Event.MSG, frag_msg));
      }
    } catch (Exception e) {
      if (log.isErrorEnabled()) log.error("fragmentation failure", e);
    }
  }
Beispiel #4
0
  public void up(MessageBatch batch) {
    for (Message msg : batch) {
      DaisyHeader hdr = (DaisyHeader) msg.getHeader(getId());
      if (hdr != null) {
        // 1. forward the message to the next in line if ttl > 0
        short ttl = hdr.getTTL();
        if (log.isTraceEnabled())
          log.trace(local_addr + ": received message from " + msg.getSrc() + " with ttl=" + ttl);
        if (--ttl > 0) {
          Message copy = msg.copy(true);
          copy.setDest(next);
          copy.putHeader(getId(), new DaisyHeader(ttl));
          msgs_forwarded++;
          if (log.isTraceEnabled())
            log.trace(local_addr + ": forwarding message to " + next + " with ttl=" + ttl);
          down_prot.down(new Event(Event.MSG, copy));
        }

        // 2. Pass up
        msg.setDest(null);
      }
    }

    if (!batch.isEmpty()) up_prot.up(batch);
  }
Beispiel #5
0
  public Object up(Event evt) {
    switch (evt.getType()) {
      case Event.MSG:
        Message msg = (Message) evt.getArg();
        DaisyHeader hdr = (DaisyHeader) msg.getHeader(getId());
        if (hdr == null) break;

        // 1. forward the message to the next in line if ttl > 0
        short ttl = hdr.getTTL();
        if (log.isTraceEnabled())
          log.trace(local_addr + ": received message from " + msg.getSrc() + " with ttl=" + ttl);
        if (--ttl > 0) {
          Message copy = msg.copy(true);
          copy.setDest(next);
          copy.putHeader(getId(), new DaisyHeader(ttl));
          msgs_forwarded++;
          if (log.isTraceEnabled())
            log.trace(local_addr + ": forwarding message to " + next + " with ttl=" + ttl);
          down_prot.down(new Event(Event.MSG, copy));
        }

        // 2. Pass up
        msg.setDest(null);
        break;
    }
    return up_prot.up(evt);
  }
Beispiel #6
0
  /** Send a message to the address specified in msg.dest */
  private void sendUnicastMessage(Message msg) {
    IpAddress dest;
    Message copy;
    Object hdr;
    Event evt;

    dest = (IpAddress) msg.getDest(); // guaranteed not to be null
    if (!(dest instanceof IpAddress)) {
      Trace.error("TCP.sendUnicastMessage()", "destination address is not of type IpAddress !");
      return;
    }
    setSourceAddress(msg);

    /* Don't send if destination is local address. Instead, switch dst and src and put in up_queue  */
    if (loopback && local_addr != null && dest != null && dest.equals(local_addr)) {
      copy = msg.copy();
      hdr = copy.getHeader(getName());
      if (hdr != null && hdr instanceof TcpHeader) copy.removeHeader(getName());
      copy.setSrc(local_addr);
      copy.setDest(local_addr);

      evt = new Event(Event.MSG, copy);

      /* Because Protocol.up() is never called by this bottommost layer, we call up() directly in the observer.
      This allows e.g. PerfObserver to get the time of reception of a message */
      if (observer != null) observer.up(evt, up_queue.size());

      passUp(evt);
      return;
    }
    if (Trace.trace)
      Trace.info(
          "TCP.sendUnicastMessage()",
          "dest=" + msg.getDest() + ", hdrs:\n" + msg.printObjectHeaders());
    try {
      if (skip_suspected_members) {
        if (suspected_mbrs.contains(dest)) {
          if (Trace.trace)
            Trace.info(
                "TCP.sendUnicastMessage()",
                "will not send unicast message to " + dest + " as it is currently suspected");
          return;
        }
      }
      ct.send(msg);
    } catch (SocketException e) {
      if (members.contains(dest)) {
        if (!suspected_mbrs.contains(dest)) {
          suspected_mbrs.add(dest);
          passUp(new Event(Event.SUSPECT, dest));
        }
      }
    }
  }
Beispiel #7
0
  private void loopback(Message msg) {
    final Message rsp = msg.copy(true);
    if (rsp.getSrc() == null) rsp.setSrc(localAddress());

    // pretty inefficient: creates one thread per message, okay for testing only
    Thread thread =
        new Thread(
            () -> {
              up_prot.up(rsp);
            });
    thread.start();
  }
Beispiel #8
0
  /** Send a message to the address specified in dest */
  void sendUdpMessage(Message msg) throws Exception {
    IpAddress dest;
    Message copy;
    Event evt;

    dest = (IpAddress) msg.getDest(); // guaranteed not to be null
    setSourceAddress(msg);

    if (Trace.debug) {
      Trace.debug(
          "UDP.sendUdpMessage()",
          "sending message to "
              + msg.getDest()
              + " (src="
              + msg.getSrc()
              + "), headers are "
              + msg.getHeaders());

      // Don't send if destination is local address. Instead, switch dst and src and put in
      // up_queue.
      // If multicast message, loopback a copy directly to us (but still multicast). Once we receive
      // this,
      // we will discard our own multicast message
    }
    if (loopback && (dest.equals(local_addr) || dest.isMulticastAddress())) {
      copy = msg.copy();
      copy.removeHeader(name);
      copy.setSrc(local_addr);
      copy.setDest(dest);
      evt = new Event(Event.MSG, copy);

      /* Because Protocol.up() is never called by this bottommost layer, we call up() directly in the observer.
      This allows e.g. PerfObserver to get the time of reception of a message */
      if (observer != null) {
        observer.up(evt, up_queue.size());
      }
      if (Trace.debug) {
        Trace.info("UDP.sendUdpMessage()", "looped back local message " + copy);
      }
      passUp(evt);
      if (!dest.isMulticastAddress()) {
        return;
      }
    }

    if (use_outgoing_packet_handler) {
      outgoing_queue.add(msg);
      return;
    }

    send(msg);
  }
Beispiel #9
0
 /**
  * used to drain the up queue - synchronized so we can call it safely despite access from
  * potentially two threads at once
  */
 private void drainUpQueue() {
   if (log.isTraceEnabled()) {
     int size = upMessageQueue.size();
     if (size > 0) log.trace("draining %d messages from the up queue", size);
   }
   while (true) {
     try {
       Message tmp = upMessageQueue.poll(0L, TimeUnit.MILLISECONDS);
       if (tmp == null) break;
       Message msg = decryptMessage(null, tmp.copy()); // need to copy for possible xmits
       if (msg != null) up_prot.up(new Event(Event.MSG, msg));
     } catch (Throwable t) {
       log.error(Util.getMessage("FailedDecryptingAndSendingMessageUpWhenDrainingQueue"), t);
     }
   }
 }
Beispiel #10
0
  /**
   * We need to resend our first message with our conn_id
   *
   * @param sender
   * @param seqno Resend messages in the range [lowest .. seqno]
   */
  private void handleResendingOfFirstMessage(Address sender, long seqno) {
    if (log.isTraceEnabled())
      log.trace(local_addr + " <-- SEND_FIRST_SEQNO(" + sender + "," + seqno + ")");
    SenderEntry entry = send_table.get(sender);
    AckSenderWindow win = entry != null ? entry.sent_msgs : null;
    if (win == null) {
      if (log.isErrorEnabled())
        log.error(local_addr + ": sender window for " + sender + " not found");
      return;
    }
    long lowest = win.getLowest();
    Message rsp = win.get(lowest);
    if (rsp == null) return;

    // We need to copy the UnicastHeader and put it back into the message because Message.copy()
    // doesn't copy
    // the headers and therefore we'd modify the original message in the sender retransmission
    // window
    // (https://jira.jboss.org/jira/browse/JGRP-965)
    Message copy = rsp.copy();
    Unicast2Header hdr = (Unicast2Header) copy.getHeader(this.id);
    Unicast2Header newhdr = hdr.copy();
    newhdr.first = true;
    copy.putHeader(this.id, newhdr);

    if (log.isTraceEnabled()) {
      StringBuilder sb = new StringBuilder();
      sb.append(local_addr)
          .append(" --> DATA(")
          .append(copy.getDest())
          .append(": #")
          .append(newhdr.seqno)
          .append(", conn_id=")
          .append(newhdr.conn_id);
      if (newhdr.first) sb.append(", first");
      sb.append(')');
      log.trace(sb);
    }
    down_prot.down(new Event(Event.MSG, copy));

    if (++lowest > seqno) return;
    for (long i = lowest; i <= seqno; i++) {
      rsp = win.get(i);
      if (rsp != null) down_prot.down(new Event(Event.MSG, rsp));
    }
  }
Beispiel #11
0
    public Message visit(Message msg, MessageBatch batch) {
      EncryptHeader hdr;

      if (msg == null
          || (msg.getLength() == 0 && !encrypt_entire_message)
          || ((hdr = (EncryptHeader) msg.getHeader(id)) == null)) return null;

      if (hdr.getType() == EncryptHeader.ENCRYPT) {
        // if queueing then pass into queue to be dealt with later
        if (queue_up) {
          queueUpMessage(msg, batch);
          return null;
        }

        // make sure we pass up any queued messages first
        if (!suppliedKey) drainUpQueue();

        if (lock == null) {
          int index = getNextIndex();
          lock = decoding_locks[index];
          cipher = decoding_ciphers[index];
          lock.lock();
        }

        try {
          Message tmpMsg = decryptMessage(cipher, msg.copy()); // need to copy for possible xmits
          if (tmpMsg != null) batch.replace(msg, tmpMsg);
        } catch (Exception e) {
          log.error(
              "failed decrypting message from %s (offset=%d, length=%d, buf.length=%d): %s, headers are %s",
              msg.getSrc(),
              msg.getOffset(),
              msg.getLength(),
              msg.getRawBuffer().length,
              e,
              msg.printHeaders());
        }
      } else {
        batch.remove(
            msg); // a control message will get handled by ENCRYPT and should not be passed up
        handleUpEvent(msg, hdr);
      }
      return null;
    }
Beispiel #12
0
  public Object down(final Event evt) {
    switch (evt.getType()) {
      case Event.MSG:
        final Message msg = (Message) evt.getArg();
        if (msg.getDest() != null) break; // only process multicast messages

        if (next == null) // view hasn't been received yet, use the normal transport
        break;

        // we need to copy the message, as we cannot do a msg.setSrc(next): the next retransmission
        // would use 'next' as destination  !
        Message copy = msg.copy(true);
        short hdr_ttl = (short) (loopback ? view_size - 1 : view_size);
        DaisyHeader hdr = new DaisyHeader(hdr_ttl);
        copy.setDest(next);
        copy.putHeader(getId(), hdr);

        msgs_sent++;

        if (loopback) {
          if (log.isTraceEnabled())
            log.trace(new StringBuilder("looping back message ").append(msg));
          if (msg.getSrc() == null) msg.setSrc(local_addr);

          Executor pool = msg.isFlagSet(Message.Flag.OOB) ? oob_pool : default_pool;
          pool.execute(() -> up_prot.up(evt));
        }
        return down_prot.down(new Event(Event.MSG, copy));

      case Event.VIEW_CHANGE:
        handleView((View) evt.getArg());
        break;

      case Event.TMP_VIEW:
        view_size = ((View) evt.getArg()).size();
        break;

      case Event.SET_LOCAL_ADDRESS:
        local_addr = (Address) evt.getArg();
        break;
    }
    return down_prot.down(evt);
  }
Beispiel #13
0
  @SuppressWarnings("UnusedParameters")
  protected Object handleEncryptedMessage(Message msg, Event evt, EncryptHeader hdr)
      throws Exception {
    // if queueing then pass into queue to be dealt with later
    if (queue_up) {
      log.trace("queueing up message as no session key established: %s", msg);
      upMessageQueue.put(msg);
      return null;
    }

    // make sure we pass up any queued messages first
    // could be more optimised but this can wait we only need this if not using supplied key
    if (!suppliedKey) drainUpQueue();

    // try and decrypt the message - we need to copy msg as we modify its
    // buffer (http://jira.jboss.com/jira/browse/JGRP-538)
    Message tmpMsg = decryptMessage(null, msg.copy()); // need to copy for possible xmits
    if (tmpMsg != null) return up_prot.up(new Event(Event.MSG, tmpMsg));
    log.warn("unrecognised cipher; discarding message");
    return null;
  }