1 package org.metricshub.ipmi.core.coding.protocol.encoder; 2 3 /*- 4 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ 5 * IPMI Java Client 6 * ჻჻჻჻჻჻ 7 * Copyright 2023 Verax Systems, MetricsHub 8 * ჻჻჻჻჻჻ 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Lesser General Public License as 11 * published by the Free Software Foundation, either version 3 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Lesser Public License for more details. 18 * 19 * You should have received a copy of the GNU General Lesser Public 20 * License along with this program. If not, see 21 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 22 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ 23 */ 24 25 import org.metricshub.ipmi.core.coding.protocol.AuthenticationType; 26 import org.metricshub.ipmi.core.common.TypeConverter; 27 28 /** 29 * Adds IPMI session header to encrypted payload. Should be used to encode 30 * regular RMCP+ messages (excluding Open Session and RAKP Messages) 31 */ 32 public abstract class ProtocolEncoder implements IpmiEncoder { 33 34 protected byte encodeAuthenticationType( 35 AuthenticationType authenticationType) { 36 return TypeConverter.intToByte(authenticationType.getCode()); 37 } 38 39 /** 40 * Converts integer value into byte array using little endian convention and 41 * inserts it into message at given offset. 42 * 43 * @param value 44 * @param message 45 * - IPMI message being created 46 * @param offset 47 * @throws IndexOutOfBoundsException 48 * when message is too short to hold value at given offset 49 */ 50 protected void encodeInt(int value, byte[] message, int offset) { 51 byte[] array = TypeConverter.intToLittleEndianByteArray(value); 52 53 if (array.length + offset > message.length) { 54 throw new IndexOutOfBoundsException("Message is too short"); 55 } 56 57 System.arraycopy(array, 0, message, offset, array.length); 58 } 59 60 /** 61 * Encodes session sequence number and inserts it into message at given 62 * offset. 63 * 64 * @param value 65 * @param message 66 * - IPMI message being created 67 * @param offset 68 * @throws IndexOutOfBoundsException 69 * when message is too short to hold value at given offset 70 */ 71 protected void encodeSessionSequenceNumber(int value, byte[] message, int offset) { 72 encodeInt(value, message, offset); 73 } 74 75 /** 76 * Encodes session id and inserts it into message at given offset. 77 * 78 * @param value 79 * @param message 80 * - IPMI message being created 81 * @param offset 82 * @throws IndexOutOfBoundsException 83 * when message is too short to hold value at given offset 84 */ 85 protected void encodeSessionId(int value, byte[] message, int offset) { 86 encodeInt(value, message, offset); 87 } 88 89 /** 90 * Encodes payload length and inserts it into message at given offset. 91 * 92 * @param value 93 * @param message 94 * - IPMI message being created 95 * @param offset 96 * @throws IndexOutOfBoundsException 97 * when message is too short to hold value at given offset 98 */ 99 protected abstract void encodePayloadLength(int value, byte[] message, int offset); 100 101 /** 102 * Encodes payload and inserts it into message at given offset. <br> 103 * When payload == null it will not be inserted. 104 * 105 * @param payload 106 * - IPMI payload to encode. 107 * @param message 108 * - IPMI message being created. 109 * @param offset 110 * @throws IndexOutOfBoundsException 111 * when message is too short to hold value at given offset 112 * @return offset + encoded message length 113 */ 114 protected int encodePayload(byte[] payload, byte[] message, int offset) { 115 if (payload == null) { 116 return offset; 117 } 118 if (payload.length + offset > message.length) { 119 throw new IndexOutOfBoundsException("Message is too short"); 120 } 121 System.arraycopy(payload, 0, message, offset, payload.length); 122 return offset + payload.length; 123 } 124 }