1 /* 2 * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 package software.amazon.eventstream; 16 17 import java.nio.ByteBuffer; 18 import java.util.zip.CRC32; 19 import java.util.zip.Checksum; 20 21 import static java.lang.String.format; 22 23 final class Prelude { 24 static final int LENGTH = 8; 25 static final int LENGTH_WITH_CRC = LENGTH + 4; 26 27 private final int totalLength; 28 private final long headersLength; 29 Prelude(int totalLength, long headersLength)30 private Prelude(int totalLength, long headersLength) { 31 this.totalLength = totalLength; 32 this.headersLength = headersLength; 33 } 34 decode(ByteBuffer buf)35 static Prelude decode(ByteBuffer buf) { 36 buf = buf.duplicate(); 37 38 long computedPreludeCrc = computePreludeCrc(buf); 39 40 long totalLength = Integer.toUnsignedLong(buf.getInt()); 41 long headersLength = Integer.toUnsignedLong(buf.getInt()); 42 long wirePreludeCrc = Integer.toUnsignedLong(buf.getInt()); 43 if (computedPreludeCrc != wirePreludeCrc) { 44 throw new IllegalArgumentException(format("Prelude checksum failure: expected 0x%x, computed 0x%x", 45 wirePreludeCrc, computedPreludeCrc)); 46 } 47 48 if (headersLength < 0 || headersLength > 131_072) { 49 throw new IllegalArgumentException("Illegal headers_length value: " + headersLength); 50 } 51 52 long payloadLength = (totalLength - headersLength) - Message.MESSAGE_OVERHEAD; 53 // This implementation temporarily accepts larger payloads than the spec permits. 54 if (payloadLength < 0 || payloadLength > 25_165_824) { 55 throw new IllegalArgumentException("Illegal payload size: " + payloadLength); 56 } 57 58 return new Prelude(Math.toIntExact(totalLength), headersLength); 59 } 60 computePreludeCrc(ByteBuffer buf)61 private static long computePreludeCrc(ByteBuffer buf) { 62 byte[] prelude = new byte[Prelude.LENGTH]; 63 buf.duplicate().get(prelude); 64 65 Checksum crc = new CRC32(); 66 crc.update(prelude, 0, prelude.length); 67 return crc.getValue(); 68 } 69 getTotalLength()70 int getTotalLength() { 71 return totalLength; 72 } 73 getHeadersLength()74 long getHeadersLength() { 75 return headersLength; 76 } 77 } 78