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