View Javadoc
1   package org.metricshub.ipmi.core.coding.payload.sol;
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.payload.IpmiPayload;
26  import org.metricshub.ipmi.core.common.MessageComposer;
27  import org.metricshub.ipmi.core.common.TypeConverter;
28  
29  /**
30   * Implementation of {@link IpmiPayload} for SOL (Serial over LAN) messages.
31   */
32  public abstract class SolMessage extends IpmiPayload {
33  
34      public static final byte MIN_SEQUENCE_NUMBER = 1;
35      public static final byte MAX_SEQUENCE_NUMBER = 15;
36  
37      private static final int PACKET_SEQUENCE_NUMBER_LENGTH = 1;
38      private static final int PACKET_ACK_SEQUENCE_NUMBER_LENGTH = 1;
39      private static final int ACCEPTED_CHARACTERS_LENGTH = 1;
40      private static final int OPERATION_STATUS_LENGTH = 1;
41  
42      public static final int PAYLOAD_HEADER_LENGTH =
43              PACKET_SEQUENCE_NUMBER_LENGTH +
44              PACKET_ACK_SEQUENCE_NUMBER_LENGTH +
45              ACCEPTED_CHARACTERS_LENGTH +
46              OPERATION_STATUS_LENGTH;
47  
48      /**
49       * Sequence number of this packet.
50       */
51      private final byte sequenceNumber;
52  
53      /**
54       * Sequence number of packet being ACKd/NACKd by this packet.
55       */
56      private final byte ackNackSequenceNumber;
57  
58      /**
59       * Number of characters being accepted from ACKd/NACKd packet.
60       */
61      private final byte acceptedCharacterCount;
62  
63      /**
64       * Operation to invoke or status of previously send packet.
65       */
66      private final byte operationStatus;
67  
68      protected SolMessage(byte sequenceNumber, byte ackNackSequenceNumber, byte acceptedCharacterCount, byte operationStatus) {
69          this.sequenceNumber = trimSequenceNumber(sequenceNumber);
70          this.ackNackSequenceNumber = trimSequenceNumber(ackNackSequenceNumber);
71          this.acceptedCharacterCount = acceptedCharacterCount;
72          this.operationStatus = operationStatus;
73      }
74  
75      /**
76       * Trims given sequence number to max allowed value for sequence numbers, applying MAX_SEQUENCE_NUMBER mask on it.
77       *
78       * @param sequenceNumber
79       *          Sequence number before trim
80       * @return trimmed sequence number
81       */
82      private byte trimSequenceNumber(byte sequenceNumber) {
83          return TypeConverter.intToByte(sequenceNumber & MAX_SEQUENCE_NUMBER);
84      }
85  
86      @Override
87      public byte[] getPayloadData() {
88          return MessageComposer.get(getPayloadLength())
89              .appendField(sequenceNumber)
90              .appendField(ackNackSequenceNumber)
91              .appendField(acceptedCharacterCount)
92              .appendField(operationStatus)
93              .appendField(getData())
94              .getMessage();
95      }
96  
97      @Override
98      public int getPayloadLength() {
99          return PAYLOAD_HEADER_LENGTH + getData().length;
100     }
101 
102     @Override
103     public byte[] getIpmiCommandData() {
104         return getData();
105     }
106 
107     @Override
108     public byte[] getData() {
109         byte[] data = super.getData();
110 
111         if (data == null) {
112             return new byte[0];
113         }
114 
115         return data;
116     }
117 
118     public byte getSequenceNumber() {
119         return sequenceNumber;
120     }
121 
122     public byte getAckNackSequenceNumber() {
123         return ackNackSequenceNumber;
124     }
125 
126     public byte getAcceptedCharacterCount() {
127         return acceptedCharacterCount;
128     }
129 
130     /**
131      * Checks if given message carries some data (or operation/status).
132      */
133     public boolean isDataCarrier() {
134         return sequenceNumber != 0 || getData().length > 0;
135     }
136 
137     /**
138      * Checks if given {@link SolMessage} is an ACK/NACK for some other message.
139      */
140     public boolean isAcknowledgeMessage() {
141         return ackNackSequenceNumber != 0;
142     }
143 }