Check the frame preamble and MPDU length before parsing
Due to errors in mspsim and/or radio drivers, packets of incorrect length are sometimes transmitted. The length might be larger than the 127-byte maximum (considered negative in the current code) or not matching the actual number of transmitted bytes. This leads to wrong packet delimiting when converting from the mspsim-level stream of bytes to Cooja-level packets causing unhandled exceptions that terminate the simulation. This patch checks the frame preamble (0000007A) and the length field. If they are wrong, no decoding attempt is done. The transmitted bytes are still delivered to the receivers untouched. The connection is terminated when the radio state is changed (which alway s happens when TX is done).
This commit is contained in:
parent
df2cdbbd79
commit
eae25d622d
|
@ -165,7 +165,7 @@ public class CC2420RadioPacketConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1 byte length */
|
/* 1 byte length */
|
||||||
len = data[pos];
|
len = data[pos] & 0xFF;
|
||||||
originalLen = len;
|
originalLen = len;
|
||||||
pos += 1;
|
pos += 1;
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
||||||
private boolean isInterfered = false;
|
private boolean isInterfered = false;
|
||||||
private boolean isTransmitting = false;
|
private boolean isTransmitting = false;
|
||||||
private boolean isReceiving = false;
|
private boolean isReceiving = false;
|
||||||
|
private boolean isSynchronized = false;
|
||||||
|
|
||||||
private byte lastOutgoingByte;
|
private byte lastOutgoingByte;
|
||||||
private byte lastIncomingByte;
|
private byte lastIncomingByte;
|
||||||
|
@ -91,22 +92,19 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
||||||
|
|
||||||
radio.addRFListener(new RFListener() {
|
radio.addRFListener(new RFListener() {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int expLen = 0;
|
int expMpduLen = 0;
|
||||||
byte[] buffer = new byte[127 + 15];
|
byte[] buffer = new byte[127 + 6];
|
||||||
|
final private byte[] syncSeq = {0,0,0,0,0x7A};
|
||||||
|
|
||||||
public void receivedByte(byte data) {
|
public void receivedByte(byte data) {
|
||||||
if (!isTransmitting()) {
|
if (!isTransmitting()) {
|
||||||
lastEvent = RadioEvent.TRANSMISSION_STARTED;
|
lastEvent = RadioEvent.TRANSMISSION_STARTED;
|
||||||
isTransmitting = true;
|
isTransmitting = true;
|
||||||
len = 0;
|
len = 0;
|
||||||
/*logger.debug("----- 802.15.4 TRANSMISSION STARTED -----");*/
|
expMpduLen = 0;
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
/*logger.debug("----- 802.15.4 TRANSMISSION STARTED -----");*/
|
||||||
|
|
||||||
if (len >= buffer.length) {
|
|
||||||
/* Bad size packet, too large */
|
|
||||||
logger.debug("Error: bad size: " + len + ", dropping outgoing byte: " + data);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send this byte to all nodes */
|
/* send this byte to all nodes */
|
||||||
|
@ -115,31 +113,40 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
|
|
||||||
buffer[len++] = data;
|
if (len < buffer.length)
|
||||||
|
buffer[len] = data;
|
||||||
|
|
||||||
if (len == 6) {
|
len ++;
|
||||||
|
|
||||||
|
if (len == 5) {
|
||||||
|
isSynchronized = true;
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
|
if (buffer[i] != syncSeq[i]) {
|
||||||
|
// this should never happen, but it happens
|
||||||
|
logger.error(String.format("Bad outgoing sync sequence %x %x %x %x %x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]));
|
||||||
|
isSynchronized = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (len == 6) {
|
||||||
// System.out.println("## CC2420 Packet of length: " + data + " expected...");
|
// System.out.println("## CC2420 Packet of length: " + data + " expected...");
|
||||||
expLen = data + 6;
|
expMpduLen = data & 0xFF;
|
||||||
|
if ((expMpduLen & 0x80) != 0) {
|
||||||
|
logger.error("Outgoing length field is larger than 127: " + expMpduLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == expLen) {
|
if (((expMpduLen & 0x80) == 0) && len == expMpduLen + 6 && isSynchronized) {
|
||||||
/*logger.debug("----- 802.15.4 CUSTOM DATA TRANSMITTED -----");*/
|
|
||||||
|
|
||||||
lastOutgoingPacket = CC2420RadioPacketConverter.fromCC2420ToCooja(buffer);
|
lastOutgoingPacket = CC2420RadioPacketConverter.fromCC2420ToCooja(buffer);
|
||||||
lastEvent = RadioEvent.PACKET_TRANSMITTED;
|
lastEvent = RadioEvent.PACKET_TRANSMITTED;
|
||||||
/*logger.debug("----- 802.15.4 PACKET TRANSMITTED -----");*/
|
//logger.debug("----- 802.15.4 PACKET TRANSMITTED -----");
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
|
isSynchronized = false;
|
||||||
/*logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----");*/
|
|
||||||
isTransmitting = false;
|
|
||||||
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
|
|
||||||
setChanged();
|
|
||||||
notifyObservers();
|
|
||||||
len = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}); /* addRFListener */
|
||||||
|
|
||||||
radio.addOperatingModeListener(new OperatingModeListener() {
|
radio.addOperatingModeListener(new OperatingModeListener() {
|
||||||
public void modeChanged(Chip source, int mode) {
|
public void modeChanged(Chip source, int mode) {
|
||||||
|
@ -148,7 +155,7 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
} else {
|
} else {
|
||||||
radioOff();
|
radioOff(); // actually it is a state change, not necessarily to OFF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -163,32 +170,23 @@ public class Msp802154Radio extends Radio implements CustomDataRadio {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void radioOff() {
|
|
||||||
/* Radio was turned off during transmission.
|
private void finishTransmission()
|
||||||
* May for example happen if watchdog triggers */
|
{
|
||||||
if (isTransmitting()) {
|
if (isTransmitting()) {
|
||||||
logger.warn("Turning off radio while transmitting, ending packet prematurely");
|
//logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----");
|
||||||
|
|
||||||
/* Simulate end of packet */
|
|
||||||
lastOutgoingPacket = new RadioPacket() {
|
|
||||||
public byte[] getPacketData() {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
lastEvent = RadioEvent.PACKET_TRANSMITTED;
|
|
||||||
/*logger.debug("----- 802.15.4 PACKET TRANSMITTED -----");*/
|
|
||||||
setChanged();
|
|
||||||
notifyObservers();
|
|
||||||
|
|
||||||
/* Register that transmission ended in radio medium */
|
|
||||||
/*logger.debug("----- 802.15.4 TRANSMISSION FINISHED -----");*/
|
|
||||||
isTransmitting = false;
|
isTransmitting = false;
|
||||||
|
isSynchronized = false;
|
||||||
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
|
lastEvent = RadioEvent.TRANSMISSION_FINISHED;
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void radioOff() {
|
||||||
|
if (isSynchronized)
|
||||||
|
logger.warn("Turning off radio while transmitting a packet");
|
||||||
|
finishTransmission();
|
||||||
lastEvent = RadioEvent.HW_OFF;
|
lastEvent = RadioEvent.HW_OFF;
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
|
|
Loading…
Reference in a new issue