@Override
        public void handle(PutHeader event) {

          logger.debug("({}): putHeader on ({})", self, dest);

          ByteBuffer buffer = ByteBuffer.allocate(ImmutableShareFile.HEADER_SIZE);

          buffer.putInt(1);
          buffer.putInt(block_size);
          buffer.putInt((int) data_size); // FIXME: in Version 2 all offsets
          // are of type long (8 bytes) to
          // hold larger files
          buffer.putInt(offsets.get("data"));
          buffer.putInt(offsets.get("plaintext_hash_tree"));
          buffer.putInt(offsets.get("crypttext_hash_tree"));
          buffer.putInt(offsets.get("block_hashes"));
          buffer.putInt(offsets.get("share_hashes"));
          buffer.putInt(offsets.get("uri_extension"));

          currentOperation = Operation.PutHeader;

          notifyonFailureEvent = new NotifyonFailure(dest.getAddress());
          trigger(notifyonFailureEvent, cfd);

          trigger(new RemoteWrite(self, dest, 0, buffer.array()), network);
        }
        @Override
        public void handle(Close event) {

          logger.debug("({}): close ({})", self, dest);

          currentOperation = Operation.Close;

          notifyonFailureEvent = new NotifyonFailure(dest.getAddress());
          trigger(notifyonFailureEvent, cfd);

          trigger(new CloseShareFile(self, dest), network);
        }
        @Override
        public void handle(PutCryptHashData event) {

          logger.debug("({}): putCrypttextHashes on ({})", self, dest);
          long offset = offsets.get("crypttext_hash_tree");
          byte[] data = DataUtils.packHashesList(event.getHashes());

          currentOperation = Operation.PutCryptoHashes;

          notifyonFailureEvent = new NotifyonFailure(dest.getAddress());
          trigger(notifyonFailureEvent, cfd);

          logger.debug(
              "({}): remoteWrite on ({}) offset={},len={}",
              new Object[] {self, dest, offset, data.length});
          trigger(new RemoteWrite(self, dest, offset, data), network);
        }
        @Override
        public void handle(PutBlock event) {

          logger.debug("({}): putBlock on ({})", self, dest);
          long offset = offsets.get("data") + event.getSegnum() * block_size;
          logger.debug(
              "({}): block={}, offset={}, size={}",
              new Object[] {self, event.getSegnum(), offset, block_size});

          currentOperation = Operation.PutBlock;

          notifyonFailureEvent = new NotifyonFailure(dest.getAddress());
          trigger(notifyonFailureEvent, cfd);

          logger.debug(
              "({}): remoteWrite on ({}) offset={},len={}",
              new Object[] {self, dest, offset, block_size});
          trigger(new RemoteWrite(self, dest, offset, event.getBlockData()), network);
        }
        @Override
        public void handle(PutUEB event) {

          logger.debug("({}): putUEB on ({})", self, dest);
          long offset = offsets.get("uri_extension");

          int length = event.getData().length;
          ByteBuffer buffer = ByteBuffer.allocate(length + 4);
          buffer.putInt(length);
          buffer.put(event.getData());
          byte[] data = buffer.array();

          currentOperation = Operation.PutUEB;

          notifyonFailureEvent = new NotifyonFailure(dest.getAddress());
          trigger(notifyonFailureEvent, cfd);

          logger.debug(
              "({}): remoteWrite on ({}) offset={},len={}",
              new Object[] {self, dest, offset, data.length});
          trigger(new RemoteWrite(self, dest, offset, data), network);
        }