View Javadoc
1   package org.metricshub.ipmi.core.connection;
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.PayloadCoder;
26  import org.metricshub.ipmi.core.coding.commands.ResponseData;
27  import org.metricshub.ipmi.core.coding.payload.sol.SolAckState;
28  import org.metricshub.ipmi.core.coding.payload.sol.SolInboundMessage;
29  import org.metricshub.ipmi.core.coding.payload.sol.SolMessage;
30  import org.metricshub.ipmi.core.coding.protocol.Ipmiv20Message;
31  
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  import java.io.IOException;
36  
37  /**
38   * Implementation of {@link MessageHandler} for {@link org.metricshub.ipmi.core.coding.protocol.PayloadType#Sol}.
39   */
40  public class SolMessageHandler extends MessageHandler {
41  
42      private static final Logger logger = LoggerFactory.getLogger(SolMessageHandler.class);
43  
44      public SolMessageHandler(Connection connection, int timeout) throws IOException {
45          super(connection, timeout, SolMessage.MIN_SEQUENCE_NUMBER, SolMessage.MAX_SEQUENCE_NUMBER);
46      }
47  
48      /**
49       * Assuming that given message is SOL message, reads both data and acknowledge information from it,
50       * notifying registered listeners about incoming data.
51       *
52       * @param message
53       *          received IPMI message.
54       */
55      @Override
56      protected void handleIncomingMessageInternal(Ipmiv20Message message) {
57          SolInboundMessage payload = (SolInboundMessage) message.getPayload();
58  
59          if (payload.isAcknowledgeMessage()) {
60              handleIncomingAcknowledgeMessage(message, payload);
61          }
62  
63          if (payload.isDataCarrier()) {
64              handleIncomingDataMessage(payload);
65          }
66      }
67  
68      private void handleIncomingAcknowledgeMessage(Ipmiv20Message message, SolInboundMessage payload) {
69          PayloadCoder coder = messageQueue.getMessageFromQueue(payload.getAckNackSequenceNumber());
70          int tag = payload.getAckNackSequenceNumber();
71  
72          logger.debug("Received message with tag " + tag);
73  
74          if (coder == null) {
75              logger.debug("No message tagged with " + tag + " in queue. Dropping orphan message.");
76              return;
77          }
78  
79          try {
80              ResponseData responseData = coder.getResponseData(message);
81              connection.notifyResponseListeners(connection.getHandle(), tag, responseData, null);
82          } catch (Exception e) {
83              connection.notifyResponseListeners(connection.getHandle(), tag, null, e);
84          }
85  
86          // Remove message from queue only when it was fully or partially acknowledged. Otherwise, we want to keep it in queue for further retries
87          if (payload.getStatusField().getAckState() == SolAckState.ACK || payload.getAcceptedCharacterCount() > 0) {
88              messageQueue.remove(payload.getAckNackSequenceNumber());
89          }
90      }
91  
92      private void handleIncomingDataMessage(SolInboundMessage payload) {
93          connection.notifyRequestListeners(payload);
94      }
95  
96  }