View Javadoc
1   package org.metricshub.ipmi.core.coding.commands.sdr;
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 java.security.InvalidKeyException;
26  import java.security.NoSuchAlgorithmException;
27  
28  import org.metricshub.ipmi.core.coding.commands.CommandCodes;
29  import org.metricshub.ipmi.core.coding.commands.IpmiCommandCoder;
30  import org.metricshub.ipmi.core.coding.payload.IpmiPayload;
31  import org.metricshub.ipmi.core.coding.payload.lan.IPMIException;
32  import org.metricshub.ipmi.core.coding.payload.lan.IpmiLanRequest;
33  import org.metricshub.ipmi.core.coding.payload.lan.NetworkFunction;
34  import org.metricshub.ipmi.core.coding.protocol.IpmiMessage;
35  import org.metricshub.ipmi.core.common.TypeConverter;
36  
37  /**
38   * Wrapper for Get SDR command.
39   */
40  public class GetSdr extends IpmiCommandCoder<GetSdrResponseData> {
41  
42  	private int reservationId;
43  
44  	private int recordId;
45  
46  	private int offset;
47  
48  	private int bytesToRead;
49  
50  	/**
51  	 * Initiates GetSdr for both encoding and decoding. 'Offset info record' and
52  	 * 'bytes to read' fields are set to read whole record.
53  	 *
54  	 * @param reservationId
55  	 *        - SDR reservation ID received via {@link ReserveSdrRepository}
56  	 *        command
57  	 * @param recordId
58  	 *        - ID of the record to get
59  	 */
60  	public GetSdr(int reservationId, int recordId) {
61  		this(reservationId, recordId, 0, 0xFF);
62  	}
63  
64  	/**
65  	 * Initiates GetSdr for both encoding and decoding.
66  	 *
67  	 * @param reservationId
68  	 *        - SDR reservation ID received via {@link ReserveSdrRepository}
69  	 *        command
70  	 * @param recordId
71  	 *        - ID of the record to get
72  	 * @param offset
73  	 *        - the offset into record, at which reading should be started
74  	 * @param bytesToRead
75  	 *        - number of bytes to read
76  	 */
77  	public GetSdr(int reservationId, int recordId, int offset, int bytesToRead) {
78  		this.recordId = recordId;
79  		this.reservationId = reservationId;
80  		this.offset = offset;
81  		this.bytesToRead = bytesToRead;
82  	}
83  
84  	@Override
85  	public byte getCommandCode() {
86  		return CommandCodes.GET_SDR;
87  	}
88  
89  	@Override
90  	public NetworkFunction getNetworkFunction() {
91  		return NetworkFunction.StorageRequest;
92  	}
93  
94  	@Override
95  	protected IpmiPayload preparePayload(int sequenceNumber) throws NoSuchAlgorithmException, InvalidKeyException {
96  		byte[] payload = new byte[6];
97  
98  		byte[] buffer = TypeConverter.intToByteArray(reservationId);
99  
100 		payload[0] = buffer[3];
101 		payload[1] = buffer[2]; // reservation ID
102 
103 		buffer = TypeConverter.intToByteArray(recordId);
104 
105 		payload[2] = buffer[3];
106 		payload[3] = buffer[2]; // record ID
107 
108 		payload[4] = TypeConverter.intToByte(offset);
109 		payload[5] = TypeConverter.intToByte(bytesToRead);
110 
111 		return new IpmiLanRequest(getNetworkFunction(), getCommandCode(), payload, TypeConverter.intToByte(sequenceNumber));
112 	}
113 
114 	@Override
115 	public GetSdrResponseData getResponseData(IpmiMessage message)
116 			throws IPMIException,
117 			NoSuchAlgorithmException,
118 			InvalidKeyException {
119 		byte[] raw = validateResponse(message);
120 
121 		// Two bytes (the next record ID) and no record data is a valid, if unhelpful, answer: the walk must go on
122 		if (raw == null || raw.length < 2) {
123 			throw new IllegalArgumentException("Invalid response payload length");
124 		}
125 
126 		GetSdrResponseData responseData = new GetSdrResponseData();
127 
128 		byte[] buffer = new byte[4];
129 
130 		buffer[0] = raw[0];
131 		buffer[1] = raw[1];
132 		buffer[2] = 0;
133 		buffer[3] = 0;
134 
135 		responseData.setNextRecordId(TypeConverter.littleEndianByteArrayToInt(buffer));
136 
137 		byte[] recordData = new byte[raw.length - 2];
138 
139 		System.arraycopy(raw, 2, recordData, 0, recordData.length);
140 
141 		responseData.setSensorRecordData(recordData);
142 
143 		return responseData;
144 	}
145 
146 }