Skip to content

Commit

Permalink
Merge pull request #253 from bobjacobsen/oir-corrected
Browse files Browse the repository at this point in the history
Unknown MTI to node will now reply with OIR
  • Loading branch information
dpharris authored Mar 25, 2024
2 parents ffeb4e0 + 6f3cf94 commit fb47854
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 10 deletions.
9 changes: 9 additions & 0 deletions src/org/openlcb/MessageDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,13 @@ public void handleTractionProxyReply(TractionProxyReplyMessage msg, Connection s
defaultHandler(msg, sender);
}

/**
* Handle internal "Unknown MTI" message
* @param msg message to handle
* @param sender connection where it came from
*/
public void handleUnknownMTI(UnknownMtiMessage msg, Connection sender) {
defaultHandler(msg, sender);
}

}
4 changes: 3 additions & 1 deletion src/org/openlcb/MessageTypeIdentifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ public enum MessageTypeIdentifier {
StreamInitiateReply ( true, false, false, 0, 2, 3, 0, "StreamInitiateReply"),
StreamDataSend ( true, false, false, 1, 3, 28, 0, "StreamDataSend"),
StreamDataProceed ( true, false, false, 0, 2, 4, 0, "StreamDataProceed"),
StreamDataComplete ( true, false, false, 0, 2, 5, 0, "StreamDataComplete");
StreamDataComplete ( true, false, false, 0, 2, 5, 0, "StreamDataComplete"),

UnknownMTI ( true, false, false, 0, 0, 0, 0, "UnknownMTI"); // invalid external MTI, used internally

private static java.util.Map<Integer, MessageTypeIdentifier> mapping;
private static java.util.Map<Integer, MessageTypeIdentifier> getMap() {
Expand Down
2 changes: 2 additions & 0 deletions src/org/openlcb/OlcbInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.openlcb.implementations.DatagramService;
import org.openlcb.implementations.EventTable;
import org.openlcb.implementations.MemoryConfigurationService;
import org.openlcb.protocols.UnknownMtiHandler;
import org.openlcb.protocols.VerifyNodeIdHandler;

import java.util.ArrayList;
Expand Down Expand Up @@ -129,6 +130,7 @@ public OlcbInterface(NodeID nodeId_, Connection outputConnection_,ThreadPoolExec
inputConnection.registerMessageListener(nodeStore);
inputConnection.registerMessageListener(dmb.connectionForRepliesFromDownstream());
inputConnection.registerMessageListener(dcs);
new UnknownMtiHandler(nodeId, this); // will register itself.
new VerifyNodeIdHandler(nodeId, this); // will register itself.

outputConnection.registerStartNotification(new Connection.ConnectionListener() {
Expand Down
68 changes: 68 additions & 0 deletions src/org/openlcb/UnknownMtiMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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 UnknownMtiMessage extends AddressedPayloadMessage {
public UnknownMtiMessage(NodeID source, NodeID dest, int originalMTI, byte[] content) {
super(source, dest, content);
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 UnknownMtiMessage) {
return equals((UnknownMtiMessage) o);
}
return false;
}

public boolean equals(UnknownMtiMessage o) {
if ((o == null) || (this.originalMTI != o.getOriginalMTI()) ) {
return false;
}
return super.equals(o);
}

/**
* Implement message-type-specific processing when this message is received by a node.
* <p>
* Default is to do nothing.
*/
@Override
public void applyTo(MessageDecoder decoder, Connection sender) {
decoder.handleUnknownMTI(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);
}

@Override
public MessageTypeIdentifier getEMTI() {
return MessageTypeIdentifier.UnknownMTI;
}
}
14 changes: 10 additions & 4 deletions src/org/openlcb/can/MessageBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,11 @@ List<Message> processFormat1(CanFrame f) {
// something bad happened
String mtiString = "000"+Integer.toHexString(mti).toUpperCase();
mtiString = mtiString.substring(mtiString.length()-3);
logger.log(Level.SEVERE, " failed to parse MTI 0x{0}", mtiString);
return retlist; // nothing in it from this
logger.log(Level.SEVERE, "Failed to parse MTI 0x{0}", mtiString);

// return internal-only message
retlist.add(new UnknownMtiMessage(source, dest, mti, content ) );
return retlist;
}

switch (value) {
Expand Down Expand Up @@ -380,8 +383,11 @@ List<Message> processFormat1(CanFrame f) {
return retlist;

default:
logger.warning(String.format(" received unhandled MTI 0x%03X: %s", mti, value.toString()));
return null;
logger.warning(String.format(" received known but unhandled MTI 0x%03X: %s", mti, value.toString()));

// return internal-only message
retlist.add(new UnknownMtiMessage(source, dest, mti, content ) );
return retlist;
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/org/openlcb/can/NIDaAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,17 @@ public void processFrame(OpenLcbCanFrame f) {
if (f.isAliasMapDefinition()) {
// complete == true is (mostly) Permitted state
if (complete) {
if (compareDataAndNodeID(f)) {
if (compareDataAndNodeID(f) || f.getSourceAlias() == nida.getNIDa()) {
// AMD for us, reply with AMR and restart
OpenLcbCanFrame frame = new OpenLcbCanFrame(nida.getNIDa());
frame.setAMR(nida.getNIDa(), nid);
sendInterface.send(frame);
// reset and start over
index = 0;
complete = false;
nida.nextAlias();
cancelTimer();
timerExpired(); // starts the sequence
return;
}
}
Expand Down Expand Up @@ -164,7 +170,7 @@ protected void timerExpired() {
while (index < 4) {
sendInterface.send(nextFrame());
}
scheduleTimer(200);
scheduleTimer(400);
} else if (index == 4) {
sendInterface.send(nextFrame());
sendInterface.send(nextFrame());
Expand Down
46 changes: 46 additions & 0 deletions src/org/openlcb/protocols/UnknownMtiHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.openlcb.protocols;

import org.openlcb.Connection;
import org.openlcb.Message;
import org.openlcb.MessageDecoder;
import org.openlcb.NodeID;
import org.openlcb.OlcbInterface;
import org.openlcb.UnknownMtiMessage;
import org.openlcb.OptionalIntRejectedMessage;

/**
* Handler for unknown MTI requests to the local node.
* <p>
* Created by Bob Jacobsen 2/2024 from VerifyNodeIdHandler
*/
public class UnknownMtiHandler extends MessageDecoder {
private final OlcbInterface iface;
private final NodeID id;

/**
* Instantiates the handler.
*
* @param id is the Node ID on behalf which to reply to messages.
* @param iface is where to send replies to, and where to listen for incoming messages.
*/
public UnknownMtiHandler(NodeID id, OlcbInterface iface) {
this.iface = iface;
this.id = id;
iface.registerMessageListener(this);
}

@Override
public void handleUnknownMTI(UnknownMtiMessage msg, Connection sender) {
/*
* This is an unknown MTI message that could be to anybody
*/

// Only reply if addressed to this node
if (msg.getDestNodeID() == this.id) {
int mti = msg.getOriginalMTI();
int code = 0x1040; // See message std 3.5.5; permanent error, not implemented
Message omsg = new OptionalIntRejectedMessage(this.id, msg.getSourceNodeID(), mti, code);
iface.getOutputConnection().put(omsg, this);
}
}
}
10 changes: 7 additions & 3 deletions test/org/openlcb/can/MessageBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.openlcb.StreamInitiateReplyMessage;
import org.openlcb.StreamInitiateRequestMessage;
import org.openlcb.Utilities;
import org.openlcb.UnknownMtiMessage;
import org.openlcb.VerifiedNodeIDNumberMessage;
import org.openlcb.VerifyNodeIDNumberGlobalMessage;
import org.openlcb.implementations.DatagramUtils;
Expand Down Expand Up @@ -714,17 +715,20 @@ public void testOptionalRejectFrame3() {

@Test
public void testBogusMti() {
// should emit "failed to parse MTI 0x541"
// should emit "Failed to parse MTI 0x541"
OpenLcbCanFrame frame = new OpenLcbCanFrame(0x123);
frame.setHeader(0x19541071);
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\"");
System.err.println("Expect next line to be \"Failed to parse MTI 0x541\"");
List<Message> list = b.processFrame(frame);

Assert.assertEquals("count", 0, list.size());
// expect that UnknownMTI message will be returned
Assert.assertEquals("count", 1, list.size());
Message msg = list.get(0);
Assert.assertTrue(msg instanceof UnknownMtiMessage);
}

@Test
Expand Down

0 comments on commit fb47854

Please sign in to comment.