Skip to content

Commit

Permalink
#1626 Updates DMR call events to include timeslot and adds DMR encryp…
Browse files Browse the repository at this point in the history
…tion information when available.
  • Loading branch information
Dennis Sheirer committed Aug 15, 2023
1 parent ddd9ca9 commit 6ca0dec
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
import io.github.dsheirer.module.decode.dmr.message.data.packet.UDTShortMessageService;
import io.github.dsheirer.module.decode.dmr.message.data.terminator.Terminator;
import io.github.dsheirer.module.decode.dmr.message.type.ServiceOptions;
import io.github.dsheirer.module.decode.dmr.message.voice.VoiceEMBMessage;
import io.github.dsheirer.module.decode.dmr.message.voice.VoiceMessage;
import io.github.dsheirer.module.decode.dmr.message.voice.embedded.Arc4EncryptionParameters;
import io.github.dsheirer.module.decode.dmr.message.voice.embedded.EmbeddedParameters;
import io.github.dsheirer.module.decode.event.DecodeEvent;
import io.github.dsheirer.module.decode.event.DecodeEventType;
import io.github.dsheirer.module.decode.event.PlottableDecodeEvent;
Expand Down Expand Up @@ -289,7 +292,7 @@ private void processSMS(UDTShortMessageService sms)
DecodeEvent smsEvent = DMRDecodeEvent.builder(DecodeEventType.SMS, sms.getTimestamp())
.details("MESSAGE: " + sms.getSMS())
.identifiers(new IdentifierCollection(sms.getIdentifiers()))
.timeslot(sms.getTimeslot())
.timeslot(getTimeslot())
.build();
broadcast(smsEvent);
}
Expand All @@ -312,7 +315,7 @@ private void processPacket(DMRPacketMessage packet)

DecodeEvent smsEvent = DMRDecodeEvent.builder(DecodeEventType.SMS, packet.getTimestamp())
.identifiers(mic)
.timeslot(packet.getTimeslot())
.timeslot(getTimeslot())
.details("SMS:" + hyteraSmsPacket.getSMS())
.build();
broadcast(smsEvent);
Expand All @@ -324,7 +327,7 @@ else if(packet.getPacket() instanceof HyteraUnknownPacket hyteraUnknownPacket)

DecodeEvent unknownTokenEvent = DMRDecodeEvent.builder(DecodeEventType.UNKNOWN_PACKET, packet.getTimestamp())
.identifiers(mic)
.timeslot(packet.getTimeslot())
.timeslot(getTimeslot())
.details("HYTERA UNK TOKEN MSG:" + hyteraUnknownPacket.getHeader().toString())
.build();
broadcast(unknownTokenEvent);
Expand All @@ -333,7 +336,7 @@ else if(packet.getPacket() instanceof HyteraUnknownPacket hyteraUnknownPacket)
{
DecodeEvent packetEvent = DMRDecodeEvent.builder(DecodeEventType.DATA_PACKET, packet.getTimestamp())
.identifiers(getMergedIdentifierCollection(packet.getIdentifiers()))
.timeslot(packet.getTimeslot())
.timeslot(getTimeslot())
.details(packet.toString())
.build();

Expand Down Expand Up @@ -370,6 +373,19 @@ private void processVoice(VoiceMessage message)
{
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL, getTimeslot()));
}

if(message.getSyncPattern() == DMRSyncPattern.BS_VOICE_FRAME_F && message instanceof VoiceEMBMessage voiceEmb)
{
if(voiceEmb.hasEmbeddedParameters())
{
EmbeddedParameters embedded = voiceEmb.getEmbeddedParameters();

if(embedded.getShortBurst() instanceof Arc4EncryptionParameters arc4)
{
updateEncryptedCall(arc4, true, voiceEmb.getTimestamp());
}
}
}
}

/**
Expand Down Expand Up @@ -778,7 +794,7 @@ private void processCSBK(CSBKMessage csbk)
DecodeEvent event = DMRDecodeEvent.builder(DecodeEventType.REQUEST, csbk.getTimestamp())
.details("Registration Request")
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
.timeslot(csbk.getTimeslot())
.timeslot(getTimeslot())
.build();
broadcast(event);
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CONTROL, getTimeslot()));
Expand All @@ -787,7 +803,7 @@ private void processCSBK(CSBKMessage csbk)
DecodeEvent regRespEvent = DMRDecodeEvent.builder(DecodeEventType.RESPONSE, csbk.getTimestamp())
.details("Registration Response")
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
.timeslot(csbk.getTimeslot())
.timeslot(getTimeslot())
.build();
broadcast(regRespEvent);
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CONTROL, getTimeslot()));
Expand Down Expand Up @@ -829,7 +845,7 @@ private void processCSBK(CSBKMessage csbk)
DecodeEvent affiliateEvent = DMRDecodeEvent.builder(DecodeEventType.AFFILIATE, csbk.getTimestamp())
.details("TALKGROUP AFFILIATION")
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
.timeslot(csbk.getTimeslot())
.timeslot(getTimeslot())
.build();
broadcast(affiliateEvent);
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CONTROL, getTimeslot()));
Expand All @@ -840,19 +856,20 @@ private void processCSBK(CSBKMessage csbk)
}
}

private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, DMRChannel channel, IdentifierCollection mergedIdentifiers) {
private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, DMRChannel channel,
IdentifierCollection mergedIdentifiers) {
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
.channel(channel)
.details(csbk.getOpcode().getLabel())
.identifiers(mergedIdentifiers)
.timeslot(channel.getTimeslot())
.timeslot(getTimeslot())
.build();
}

private DecodeEvent getDecodeEvent(CSBKMessage csbk, DecodeEventType decodeEventType, String details) {
return DMRDecodeEvent.builder(decodeEventType, csbk.getTimestamp())
.identifiers(getMergedIdentifierCollection(csbk.getIdentifiers()))
.timeslot(csbk.getTimeslot())
.timeslot(getTimeslot())
.details(details)
.build();
}
Expand Down Expand Up @@ -978,7 +995,7 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
}
}
break;
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
case FULL_MOTOROLA_GROUP_VOICE_CHANNEL_USER:
if(message instanceof MotorolaGroupVoiceChannelUser cpgvcu)
{
if(isTerminator)
Expand Down Expand Up @@ -1103,7 +1120,7 @@ private void processLinkControl(LCMessage message, boolean isTerminator)

DecodeEvent gpsEvent = DMRDecodeEvent.builder(DecodeEventType.GPS, message.getTimestamp())
.identifiers(ic)
.timeslot(message.getTimeslot())
.timeslot(getTimeslot())
.details("LOCATION:" + gpsInformation.getGPSLocation())
.build();

Expand All @@ -1119,6 +1136,41 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
}
}

/**
* Updates the current call with encryption information.
* @param encryptionParameters decoded from the Voice Frame F
* @param isGroup true for group or false for individual call.
*/
private void updateEncryptedCall(Arc4EncryptionParameters encryptionParameters, boolean isGroup, long timestamp)
{
if(mCurrentCallEvent != null)
{
String details = mCurrentCallEvent.getDetails();;

if(details == null)
{
details = encryptionParameters.toString();
}
else if(!details.contains(encryptionParameters.toString()))
{
details += " " + encryptionParameters;
}

mCurrentCallEvent.setDetails(details);
}
else
{
mCurrentCallEvent = DMRDecodeEvent.builder(isGroup ? DecodeEventType.CALL_GROUP_ENCRYPTED :
DecodeEventType.CALL_ENCRYPTED, timestamp)
.channel(getCurrentChannel())
.details(encryptionParameters.toString())
.identifiers(getIdentifierCollection().copyOf())
.timeslot(getTimeslot())
.build();
broadcast(mCurrentCallEvent);
}
}

/**
* Updates or creates a current call event.
*
Expand All @@ -1136,13 +1188,14 @@ private void updateCurrentCall(DecodeEventType type, String details, long timest
.channel(getCurrentChannel())
.details(details)
.identifiers(getIdentifierCollection().copyOf())
.timeslot(getTimeslot())
.build();

broadcast(mCurrentCallEvent);
}
else
{
if(type != DecodeEventType.CALL)
if(mCurrentCallEvent.getDetails() == null)
{
mCurrentCallEvent.setDetails(details);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ private void process(FullLCMessage message)
{
switch(message.getOpcode())
{
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
case FULL_MOTOROLA_GROUP_VOICE_CHANNEL_USER:
if(message instanceof MotorolaGroupVoiceChannelUser cpvcu)
{
if(mCallSequence == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ else if(message.size() == 96)
case FULL_STANDARD_TERMINATOR_DATA:
flc = new TerminatorData(message, timestamp, timeslot);
break;
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
case FULL_MOTOROLA_GROUP_VOICE_CHANNEL_USER:
flc = new MotorolaGroupVoiceChannelUser(message, timestamp, timeslot);
break;
case FULL_CAPACITY_PLUS_ENCRYPTED_VOICE_CHANNEL_USER:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public enum LCOpcode
FULL_STANDARD_TERMINATOR_DATA(Vendor.STANDARD, true, 48, "TERMINATOR DATA"),
FULL_STANDARD_UNKNOWN(Vendor.STANDARD,true, -1, "FULL UNKNOWN"),

FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 0, "GROUP VOICE CHANNEL USER"),
FULL_MOTOROLA_GROUP_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 0, "GROUP VOICE CHANNEL USER"),
FULL_CAPACITY_PLUS_WIDE_AREA_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 4, "WAN GROUP VOICE CHANNEL USER"),
//Observed on Cap+ Multi-Site System during an encrypted voice call
FULL_CAPACITY_PLUS_ENCRYPTED_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 32, "ENCRYPTED VOICE CHANNEL USER"),
Expand Down

0 comments on commit 6ca0dec

Please sign in to comment.