private String unwrapBytes(
     ByteBuffer[] dsts, int offset, int length, ByteBuffer src, boolean readHandshakeMsg) {
   // define unwrapped data to be written to dsts
   String wrapped = new String(Buffers.take(src), StandardCharsets.ISO_8859_1);
   int wrappedEndIndex = wrapped.length();
   int wrappedLeftOver = -1;
   while (wrappedEndIndex > 0 && !unwrapMap.containsKey(wrapped.substring(0, wrappedEndIndex))) {
     wrappedLeftOver = wrappedEndIndex--;
   }
   // undo the reading of data that won't be used now
   if (wrappedLeftOver != -1 && wrappedEndIndex > 0) {
     src.position(src.position() - (wrapped.length() - wrappedEndIndex));
     wrapped = wrapped.substring(0, wrappedEndIndex);
   } else {
     int msgIndex;
     if ((msgIndex = wrapped.indexOf(HANDSHAKE_MSG)) != -1) {
       if (msgIndex == 0) {
         src.position(src.position() - (wrapped.length() - HANDSHAKE_MSG.length()));
         wrapped = wrapped.substring(0, HANDSHAKE_MSG.length());
       } else {
         src.position(src.position() - (wrapped.length() - msgIndex));
         wrapped = wrapped.substring(0, msgIndex);
       }
     }
     if ((msgIndex = wrapped.indexOf(CLOSE_MSG)) != -1) {
       if (msgIndex == 0) {
         src.position(src.position() - (wrapped.length() - CLOSE_MSG.length()));
         wrapped = wrapped.substring(0, CLOSE_MSG.length());
       } else {
         src.position(src.position() - (wrapped.length() - msgIndex));
         wrapped = wrapped.substring(0, msgIndex);
       }
     }
   }
   String unwrapped = unwrapMap.containsKey(wrapped) ? unwrapMap.get(wrapped) : wrapped;
   if (unwrapped.equals(HANDSHAKE_MSG) && !readHandshakeMsg) {
     src.position(src.position() - wrapped.length());
     return "";
   }
   if (!unwrapped.equals(CLOSE_MSG) && !unwrapped.equals(HANDSHAKE_MSG)) {
     if (CLOSE_MSG.startsWith(unwrapped) || HANDSHAKE_MSG.startsWith(unwrapped)) {
       src.position(0);
       return null;
     }
     // check if there is enough space to write unwrapped data, if not, do not write
     if (Buffers.remaining(dsts, offset, length) < unwrapped.length()) {
       src.position(src.position() - wrapped.length());
       return null;
     }
     // copy data to dsts
     Buffers.copy(
         dsts, offset, length, ByteBuffer.wrap(unwrapped.getBytes(StandardCharsets.ISO_8859_1)));
   }
   return unwrapped;
 }