View Javadoc
1   package org.metricshub.ipmi.core.coding.commands.payload;
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.commands.CommandCodes;
26  import org.metricshub.ipmi.core.coding.commands.IpmiCommandCoder;
27  import org.metricshub.ipmi.core.coding.commands.IpmiVersion;
28  import org.metricshub.ipmi.core.coding.commands.ResponseData;
29  import org.metricshub.ipmi.core.coding.payload.CompletionCode;
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.IpmiLanResponse;
34  import org.metricshub.ipmi.core.coding.payload.lan.NetworkFunction;
35  import org.metricshub.ipmi.core.coding.protocol.AuthenticationType;
36  import org.metricshub.ipmi.core.coding.protocol.IpmiMessage;
37  import org.metricshub.ipmi.core.coding.protocol.PayloadType;
38  import org.metricshub.ipmi.core.coding.security.CipherSuite;
39  import org.metricshub.ipmi.core.common.MessageComposer;
40  import org.metricshub.ipmi.core.common.MessageReader;
41  import org.metricshub.ipmi.core.common.TypeConverter;
42  
43  import java.security.InvalidKeyException;
44  import java.security.NoSuchAlgorithmException;
45  
46  /**
47   * An abstract wrapper class for Activate Payload Command. Every {@link PayloadType} should have it's own concrete implementation.
48   */
49  public abstract class ActivatePayload extends IpmiCommandCoder {
50  
51      /**
52       * Length (in bytes) of request data payload.
53       */
54      private static final int REQUEST_DATA_LENGTH = 6;
55  
56      /**
57       * Length (in bytes) of auxilary data field in request/response payload.
58       */
59      private static final int AUXILARY_DATA_LENGTH = 4;
60  
61      /**
62       * Length (in bytes) of inbound payload size field in response payload.
63       */
64      private static final int INBOUND_PAYLOAD_SIZE_LENGTH = 2;
65  
66      /**
67       * Length (in bytes) of outbound data field response payload.
68       */
69      private static final int OUTBOUND_PAYLOAD_SIZE_LENGTH = 2;
70  
71      /**
72       * Length (in bytes) of udp port number field in response payload.
73       */
74      private static final int PAYLOAD_UDP_PORT_NUMBER_DATA_LENGTH = 2;
75  
76      /**
77       * Length (in bytes) of VLAN number field in response payload.
78       */
79      private static final int PAYLOAD_VLAN_NUMBER_DATA_LENGTH = 2;
80  
81      /**
82       * Number of payload instance to use when activating.
83       */
84      private final int payloadInstance;
85  
86      /**
87       * @return type of the payload activated by this command.
88       */
89      public abstract PayloadType getPayloadType();
90  
91      protected ActivatePayload(IpmiVersion ipmiVersion, CipherSuite cipherSuite, AuthenticationType authenticationType, int payloadInstance) {
92          super(ipmiVersion, cipherSuite, authenticationType);
93  
94          this.payloadInstance = payloadInstance;
95      }
96  
97      @Override
98      public byte getCommandCode() {
99          return CommandCodes.ACTIVATE_PAYLOAD;
100     }
101 
102     @Override
103     public NetworkFunction getNetworkFunction() {
104         return NetworkFunction.ApplicationRequest;
105     }
106 
107     @Override
108     protected IpmiPayload preparePayload(int sequenceNumber) throws NoSuchAlgorithmException, InvalidKeyException {
109        byte[] message = MessageComposer.get(REQUEST_DATA_LENGTH)
110                .appendField(TypeConverter.intToByte(getPayloadType().getCode()))
111                .appendField(TypeConverter.intToByte(payloadInstance))
112                .appendField(prepareAuxilaryRequestData())
113                .getMessage();
114 
115         return new IpmiLanRequest(getNetworkFunction(), getCommandCode(), message, TypeConverter.intToByte(sequenceNumber));
116     }
117 
118     /**
119      * Prepares Auxilary Data field for the request payload.
120      *
121      * @return Auxilary Data bytes.
122      */
123     protected abstract byte[] prepareAuxilaryRequestData();
124 
125     @Override
126     public ResponseData getResponseData(IpmiMessage message) throws IPMIException, NoSuchAlgorithmException, InvalidKeyException {
127         if (!isCommandResponse(message)) {
128             throw new IllegalArgumentException("This is not a response for Activate Payload command");
129         }
130 
131         if (!(message.getPayload() instanceof IpmiLanResponse)) {
132             throw new IllegalArgumentException("Invalid response payload");
133         }
134 
135         if (((IpmiLanResponse) message.getPayload()).getCompletionCode() != CompletionCode.Ok) {
136             throw new IPMIException(((IpmiLanResponse) message.getPayload()).getCompletionCode());
137         }
138 
139         MessageReader messageReader = new MessageReader(message.getPayload().getData());
140 
141         ActivatePayloadResponseData responseData = createEmptyResponse();
142 
143         responseData.setAuxilaryInformationData(messageReader.readNextField(AUXILARY_DATA_LENGTH));
144         responseData.setInboundPayloadSize(messageReader.readNextField(INBOUND_PAYLOAD_SIZE_LENGTH));
145         responseData.setOutboundPayloadSize(messageReader.readNextField(OUTBOUND_PAYLOAD_SIZE_LENGTH));
146         responseData.setPayloadUdpPortNumber(messageReader.readNextField(PAYLOAD_UDP_PORT_NUMBER_DATA_LENGTH));
147         responseData.setPayloadVlanNumber(messageReader.readNextField(PAYLOAD_VLAN_NUMBER_DATA_LENGTH));
148 
149         return responseData;
150     }
151 
152     /**
153      * Creates empty {@link ResponseData} object.
154      *
155      * @return created {@link ActivatePayloadResponseData} instance.
156      */
157     protected abstract ActivatePayloadResponseData createEmptyResponse();
158 
159     @Override
160     public boolean equals(Object o) {
161         if (this == o) return true;
162         if (o == null || getClass() != o.getClass()) return false;
163 
164         ActivatePayload that = (ActivatePayload) o;
165 
166         if (payloadInstance != that.payloadInstance) {
167             return false;
168         }
169 
170         if (getPayloadType() != that.getPayloadType()) {
171             return false;
172         }
173 
174         return getCipherSuite().equals(that.getCipherSuite());
175     }
176 
177     @Override
178     public int hashCode() {
179         int result = payloadInstance;
180         result = 31 * result + getPayloadType().getCode();
181         result = 31 * result + (getCipherSuite() != null ? getCipherSuite().hashCode() : 0);
182         return result;
183     }
184 }