diff --git a/src/org/openlcb/Message.java b/src/org/openlcb/Message.java index ad1899a7..accb43b4 100644 --- a/src/org/openlcb/Message.java +++ b/src/org/openlcb/Message.java @@ -67,5 +67,8 @@ public String toString() { return getSourceNodeID().toString()+" "; } + /** + * Get the numerical value of the MTI + */ abstract public int getMTI(); } diff --git a/src/org/openlcb/MessageDecoder.java b/src/org/openlcb/MessageDecoder.java index ec4c7a7f..a12cbefa 100644 --- a/src/org/openlcb/MessageDecoder.java +++ b/src/org/openlcb/MessageDecoder.java @@ -302,7 +302,7 @@ public void handleTractionProxyReply(TractionProxyReplyMessage msg, Connection s } /** - * Handle internal "Unknown MTI" message + * Handle internal "Unknown MTI" addressed message * @param msg message to handle * @param sender connection where it came from */ @@ -310,4 +310,13 @@ public void handleUnknownMTI(UnknownMtiMessage msg, Connection sender) { defaultHandler(msg, sender); } + /** + * Handle internal "Unknown MTI" global message + * @param msg message to handle + * @param sender connection where it came from + */ + public void handleUnknownGlobalMTI(UnknownGlobalMtiMessage msg, Connection sender) { + defaultHandler(msg, sender); + } + } diff --git a/src/org/openlcb/MessageTypeIdentifier.java b/src/org/openlcb/MessageTypeIdentifier.java index f3efdbec..d40c3606 100644 --- a/src/org/openlcb/MessageTypeIdentifier.java +++ b/src/org/openlcb/MessageTypeIdentifier.java @@ -82,7 +82,8 @@ public enum MessageTypeIdentifier { StreamDataProceed ( true, false, false, 0, 2, 4, 0, "StreamDataProceed"), StreamDataComplete ( true, false, false, 0, 2, 5, 0, "StreamDataComplete"), - UnknownMTI ( true, false, false, 0, 0, 0, 0, "UnknownMTI"); // invalid external MTI, used internally + UnknownMTI ( true, false, false, 0, 0, 0, 0, "UnknownAddressedMTI"), // invalid external MTI, used internally + UnknownGlobalMTI ( false, false, false, 0, 0, 0, 0, "UnknownGlobalMTI"); // invalid external MTI, used internally private static java.util.Map mapping; private static java.util.Map getMap() { diff --git a/src/org/openlcb/UnknownGlobalMtiMessage.java b/src/org/openlcb/UnknownGlobalMtiMessage.java new file mode 100644 index 00000000..67b8e179 --- /dev/null +++ b/src/org/openlcb/UnknownGlobalMtiMessage.java @@ -0,0 +1,67 @@ +package org.openlcb; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +// For annotations +import net.jcip.annotations.Immutable; +import net.jcip.annotations.ThreadSafe; + +/** + * Message with unknown/unrecognized/unprocessed MTI + * Only relevant for addressed case; unrecognized globals are ignored in proessing. + * + * @author Bob Jacobsen Copyright 2024 + */ +@Immutable +@ThreadSafe +public class UnknownGlobalMtiMessage extends Message { + public UnknownGlobalMtiMessage(NodeID source, int originalMTI, byte[] content) { + super(source); + this.originalMTI = originalMTI; + } + + int originalMTI; + + public int getOriginalMTI() { + return originalMTI; + } + + /** + * To be equal, messages have to have the same type and content. + */ + @Override + public boolean equals(Object o) { + if (o instanceof UnknownGlobalMtiMessage) { + return equals((UnknownGlobalMtiMessage) o); + } + return false; + } + + public boolean equals(UnknownGlobalMtiMessage o) { + if ((o == null) || (this.originalMTI != o.getOriginalMTI()) ) { + return false; + } + return super.equals(o); + } + + @Override + public int getMTI() { + return MessageTypeIdentifier.UnknownGlobalMTI.mti(); + } + /** + * Implement message-type-specific processing when this message is received by a node. + *

+ * Default is to do nothing. + */ + @Override + public void applyTo(MessageDecoder decoder, Connection sender) { + decoder.handleUnknownGlobalMTI(this, sender); + } + + @Override + public String toString() { + StringBuilder value = new StringBuilder(super.toString()); + value.append(" Unknown MTI message for MTI 0x"); + value.append(Integer.toHexString(getOriginalMTI()&0xFFF).toUpperCase()); + return new String(value); + } +} diff --git a/src/org/openlcb/can/MessageBuilder.java b/src/org/openlcb/can/MessageBuilder.java index 531ec75d..bd73948c 100644 --- a/src/org/openlcb/can/MessageBuilder.java +++ b/src/org/openlcb/can/MessageBuilder.java @@ -231,7 +231,11 @@ List processFormat1(CanFrame f) { logger.log(Level.SEVERE, "Failed to parse MTI 0x{0}", mtiString); // return internal-only message - retlist.add(new UnknownMtiMessage(source, dest, mti, content ) ); + if (dest != null) { + retlist.add(new UnknownMtiMessage(source, dest, mti, content ) ); + } else { + retlist.add(new UnknownGlobalMtiMessage(source, mti, content ) ); + } return retlist; } diff --git a/test/org/openlcb/can/MessageBuilderTest.java b/test/org/openlcb/can/MessageBuilderTest.java index 3a078e5e..4e3f3521 100644 --- a/test/org/openlcb/can/MessageBuilderTest.java +++ b/test/org/openlcb/can/MessageBuilderTest.java @@ -27,6 +27,7 @@ import org.openlcb.StreamInitiateReplyMessage; import org.openlcb.StreamInitiateRequestMessage; import org.openlcb.Utilities; +import org.openlcb.UnknownGlobalMtiMessage; import org.openlcb.UnknownMtiMessage; import org.openlcb.VerifiedNodeIDNumberMessage; import org.openlcb.VerifyNodeIDNumberGlobalMessage; @@ -797,7 +798,25 @@ public void testOptionalRejectFrame3() { } @Test - public void testBogusMti() { + public void testBogusAddressedMti() { + // should emit "Failed to parse MTI 0x549" + OpenLcbCanFrame frame = new OpenLcbCanFrame(0x123); + frame.setHeader(0x19549071); + frame.setData(new byte[]{0x02, 0x02, (byte)0x12, 0x34}); + + MessageBuilder b = new MessageBuilder(map); + + System.err.println("Expect next line to be \"Failed to parse MTI 0x541\""); + List list = b.processFrame(frame); + + // expect that UnknownMTI message will be returned + Assert.assertEquals("count", 1, list.size()); + Message msg = list.get(0); + Assert.assertTrue(msg instanceof UnknownMtiMessage); + } + + @Test + public void testBogusGlobalMti() { // should emit "Failed to parse MTI 0x541" OpenLcbCanFrame frame = new OpenLcbCanFrame(0x123); frame.setHeader(0x19541071); @@ -811,7 +830,7 @@ public void testBogusMti() { // expect that UnknownMTI message will be returned Assert.assertEquals("count", 1, list.size()); Message msg = list.get(0); - Assert.assertTrue(msg instanceof UnknownMtiMessage); + Assert.assertTrue(msg instanceof UnknownGlobalMtiMessage); } @Test