Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1626 Updates DMR call events to include timeslot and adds DMR encryp… #1627

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading