mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 01:27:34 -05:00
Initial commit of redesigned internal processing and audio management.
Note: Several of the decoders are currently non-functioning in this commit. If you want the latest functioning codebase, please checkout the commit prior to this one. All decoders will eventually be updated with this new architecture. Currently broken: - Logging and recording - Aux decoders (Fleetsync/MDC/LoJack/Tait) - LTR/Passport decoders Changes in this commit: - Module architecture for decoders and components with central provisioning by the DecoderFactory - Transition from Complex sample stream processing to float buffer processing for improved memory management - Redesigned filter structures - to support buffers and streams - Resolved several memory leak issues - Universal sharing of the thread pool manager - Added centralized audio management with call/user prioritization and new gui with mute/volume controls - Embedded audio metadata for eventual streaming support - Redesigned ProcessingChain to support independent re-use - Added new TrafficChannelManager to handle traffic channel allocations - Traffic Channel pool size and Call timeout available in P25 and MPT1327 configs - Redesigned channel and decoder gui components
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class PDUConfirmedMessage extends PDUMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( PDUConfirmedMessage.class );
|
||||
|
||||
public static final int SEQUENCE_RESET_FLAG = 128; //SYN
|
||||
public static final int[] PACKET_SEQUENCE_NUMBER = { 129,130,131 };
|
||||
public static final int FINAL_FRAGMENT_FLAG = 132;
|
||||
public static final int[] FRAGMENT_SEQUENCE_NUMBER = { 133,134,135 };
|
||||
public static final int[] PDU_TYPE = { 176,177,178,179 };
|
||||
|
||||
public PDUConfirmedMessage( BinaryMessage message, AliasList aliasList )
|
||||
{
|
||||
super( message, DataUnitID.PDUC, aliasList );
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to support subclassing of this message. Initial construction
|
||||
* of the message enables CRC checks to be calculated and message type to
|
||||
* be inspected so that we can construct an accurate subclass message,
|
||||
* without having to recalculate CRC checksums.
|
||||
*/
|
||||
protected PDUConfirmedMessage( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message.getSourceMessage(), DataUnitID.PDUC, message.getAliasList() );
|
||||
mCRC = message.getCRCResults();
|
||||
}
|
||||
|
||||
private void checkCRC()
|
||||
{
|
||||
int blocks = getBlocksToFollowCount();
|
||||
|
||||
/* The NID and Header have already passed CRC */
|
||||
mCRC = new CRC[ 2 + blocks ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
for( int x = 0; x < getBlocksToFollowCount(); x++ )
|
||||
{
|
||||
/* Data blocks start at 160 and every 144 thereafter */
|
||||
mCRC[ x + 2 ] = CRCP25.checkCRC9( mMessage, 160 + ( x * 144 ) );
|
||||
}
|
||||
|
||||
//TODO: check the final 4-byte end of block sequence CRC
|
||||
}
|
||||
|
||||
/* Override for now */
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "[" + this.getClass() + "]" );
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
sb.append( " " );
|
||||
sb.append( getDirection() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( getFormat().getLabel() );
|
||||
sb.append( " SAP:" );
|
||||
sb.append( getServiceAccessPoint().getLabel() );
|
||||
|
||||
if( getVendor() != Vendor.STANDARD )
|
||||
{
|
||||
sb.append( " VEND:" );
|
||||
sb.append( getVendor().getLabel() );
|
||||
}
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " BLOCKS:" );
|
||||
sb.append( getBlocksToFollowCount() );
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet Data Unit Type
|
||||
*/
|
||||
public PDUType getPDUType()
|
||||
{
|
||||
return PDUType.fromValue( mMessage.getInt( PDU_TYPE ), isOutbound() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Number of bytes/octets contained in the message, exclusive of the data
|
||||
* header.
|
||||
*/
|
||||
public int getOctetCount()
|
||||
{
|
||||
/* 16 octets per block, and 12 octets in final block */
|
||||
int count = getBlocksToFollowCount() * 16 - 4;
|
||||
|
||||
int padding = getPadOctetCount();
|
||||
|
||||
/* Hack: motorola sndcp packet data control - when it says there are 15
|
||||
* pad octets and only 1 data block of 12 data octets, that means there
|
||||
* are more pad octets than available data and they appear to suppress
|
||||
* the final padded data block containing the 12 pad octets. The data
|
||||
* block count should be 2, but it says 1, so they're either not sending
|
||||
* the final block, or there is an error in the block count */
|
||||
if( padding > count )
|
||||
{
|
||||
count -= ( padding - 12 );
|
||||
}
|
||||
else
|
||||
{
|
||||
count -= padding;
|
||||
}
|
||||
|
||||
|
||||
count -= getDataHeaderOffset();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the receiver should accept this packet, despite the
|
||||
* apparent out-of-order packet and fragment sequence numbering. This
|
||||
* indicates that something happened to the synchronization between
|
||||
* the tower and the radio and now the tower commands the radio to reset
|
||||
* the sequence numbers and accept this packet/fragment instead of discarding
|
||||
* it as a duplicate.
|
||||
*/
|
||||
public boolean isSequenceReset()
|
||||
{
|
||||
return mMessage.get( SEQUENCE_RESET_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet sequence number. Numbers run from 0 to 7 and will continually
|
||||
* roll-over if there are more than 8 total packets.
|
||||
*/
|
||||
public int getPacketSequenceNumber()
|
||||
{
|
||||
return mMessage.getInt( PACKET_SEQUENCE_NUMBER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this packet fragment is the final fragment
|
||||
*/
|
||||
public boolean isFinalFragment()
|
||||
{
|
||||
return mMessage.get( FINAL_FRAGMENT_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet fragment sequence number
|
||||
*/
|
||||
public int getFragmentSequenceNumber()
|
||||
{
|
||||
return mMessage.getInt( FRAGMENT_SEQUENCE_NUMBER );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class PDUConfirmedMessageFactory
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( PDUConfirmedMessage.class );
|
||||
|
||||
public static PDUConfirmedMessage getMessage( PDUConfirmedMessage message )
|
||||
{
|
||||
switch( message.getServiceAccessPoint() )
|
||||
{
|
||||
case ADDRESS_RESOLUTION_PROTOCOL:
|
||||
break;
|
||||
case CHANNEL_REASSIGNMENT:
|
||||
break;
|
||||
case CIRCUIT_DATA:
|
||||
break;
|
||||
case CIRCUIT_DATA_CONTROL:
|
||||
break;
|
||||
case ENCRYPTED_KEY_MANAGEMENT_MESSAGE:
|
||||
break;
|
||||
case ENCRYPTED_TRUNKING_CONTROL:
|
||||
break;
|
||||
case ENCRYPTED_USER_DATA:
|
||||
break;
|
||||
case EXTENDED_ADDRESS:
|
||||
break;
|
||||
case MR_CONFIGURATION:
|
||||
break;
|
||||
case MR_LOOPBACK:
|
||||
break;
|
||||
case MR_OUT_OF_SERVICE:
|
||||
break;
|
||||
case MR_PAGING:
|
||||
break;
|
||||
case MR_STATISTICS:
|
||||
break;
|
||||
case PACKET_DATA:
|
||||
break;
|
||||
case REGISTRATION_AND_AUTHORIZATION:
|
||||
break;
|
||||
/* Deliberate fall-through */
|
||||
case SNDCP_PACKET_DATA_CONTROL:
|
||||
case UNENCRYPTED_USER_DATA:
|
||||
switch( message.getPDUType() )
|
||||
{
|
||||
case SN_ACTIVATE_TDS_CONTEXT_ACCEPT:
|
||||
return new SNDCPActivateTDSContextAccept( message );
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REJECT:
|
||||
return new SNDCPActivateTDSContextReject( message );
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
return new SNDCPActivateTDSContextRequest( message );
|
||||
case SN_DEACTIVATE_TDS_CONTEXT_ACCEPT:
|
||||
case SN_DEACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
return new SNDCPDeactivateTDSContext( message );
|
||||
case SN_RF_CONFIRMED_DATA:
|
||||
return new SNDCPUserData( message );
|
||||
case SN_RF_UNCONFIRMED_DATA:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SYSTEM_CONFIGURATION:
|
||||
break;
|
||||
case UNENCRYPTED_KEY_MANAGEMENT_MESSAGE:
|
||||
break;
|
||||
case UNENCRYPTED_TRUNKING_CONTROL:
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.MDPConfigurationOption;
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class SNDCPActivateTDSContextAccept extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextAccept.class );
|
||||
|
||||
/* SN-Activate TDS Context Accept */
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] PDUPM = { 184,185,186,187 };
|
||||
public static final int[] READY = { 188,189,190,191 };
|
||||
public static final int[] STANDBY = { 192,193,194,195 };
|
||||
public static final int[] NAT = { 196,197,198,199 };
|
||||
public static final int[] IP_1 = { 200,201,202,203,204,205,206,207 };
|
||||
public static final int[] IP_2 = { 208,209,210,211,212,213,214,215 };
|
||||
public static final int[] IP_3 = { 216,217,218,219,220,221,222,223 };
|
||||
public static final int[] IP_4 = { 224,225,226,227,228,229,230,231 };
|
||||
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TCPSS = { 240,241,242,243 };
|
||||
public static final int[] UDPSS = { 244,245,246,247 };
|
||||
public static final int[] MTU = { 248,249,250,251 };
|
||||
public static final int[] UDPC = { 252,253,254,255 };
|
||||
public static final int[] MDPCO = { 256,257,258,259,260,261,262,263 };
|
||||
public static final int[] DATA_ACCESS_CONTROL = { 264,265,266,267,268,
|
||||
269,270,271,272,273,274,275,276,277,278,279 };
|
||||
|
||||
public SNDCPActivateTDSContextAccept( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " ACCEPT SNDCP PACKET DATA ACTIVATE " );
|
||||
sb.append( getNetworkAddressType() );
|
||||
sb.append( " " );
|
||||
sb.append( getIPAddress() );
|
||||
sb.append( " NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " MTU:" );
|
||||
sb.append( getMaximumTransmissionUnit() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public int getPDUPriorityMaximum()
|
||||
{
|
||||
return mMessage.getInt( PDUPM );
|
||||
}
|
||||
|
||||
public String getReadyTimer()
|
||||
{
|
||||
switch( mMessage.getInt( READY ) )
|
||||
{
|
||||
case 1:
|
||||
return "1 Second";
|
||||
case 2:
|
||||
return "2 Seconds";
|
||||
case 3:
|
||||
return "4 Seconds";
|
||||
case 4:
|
||||
return "6 Seconds";
|
||||
case 5:
|
||||
return "8 Seconds";
|
||||
case 6:
|
||||
return "10 Seconds";
|
||||
case 7:
|
||||
return "15 Seconds";
|
||||
case 8:
|
||||
return "20 Seconds";
|
||||
case 9:
|
||||
return "25 Seconds";
|
||||
case 10:
|
||||
return "30 Seconds";
|
||||
case 11:
|
||||
return "60 Seconds";
|
||||
case 12:
|
||||
return "120 Seconds";
|
||||
case 13:
|
||||
return "180 Seconds";
|
||||
case 14:
|
||||
return "300 Seconds";
|
||||
case 15:
|
||||
return "Always in Ready";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
public String getStandbyTimer()
|
||||
{
|
||||
switch( mMessage.getInt( STANDBY ) )
|
||||
{
|
||||
case 1:
|
||||
return "10 Seconds";
|
||||
case 2:
|
||||
return "30 Seconds";
|
||||
case 3:
|
||||
return "1 Minutes";
|
||||
case 4:
|
||||
return "5 Minutes";
|
||||
case 5:
|
||||
return "10 Minutes";
|
||||
case 6:
|
||||
return "30 Minutes";
|
||||
case 7:
|
||||
return "1 Hour";
|
||||
case 8:
|
||||
return "2 Hours";
|
||||
case 9:
|
||||
return "4 Hours";
|
||||
case 10:
|
||||
return "8 Hours";
|
||||
case 11:
|
||||
return "12 Hours";
|
||||
case 12:
|
||||
return "24 Hours";
|
||||
case 13:
|
||||
return "48 Hours";
|
||||
case 14:
|
||||
return "72 Hours";
|
||||
case 15:
|
||||
return "Always in Ready";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public String getNetworkAddressType()
|
||||
{
|
||||
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
|
||||
}
|
||||
|
||||
public String getIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean hasIPHeaderCompression()
|
||||
{
|
||||
return mMessage.getInt( IPHC ) == 1;
|
||||
}
|
||||
|
||||
public boolean hasUserDataPayloadCompression()
|
||||
{
|
||||
return mMessage.getInt( UDPC ) == 1;
|
||||
}
|
||||
|
||||
public int getTCPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( TCPSS );
|
||||
}
|
||||
|
||||
public int getUDPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( UDPSS );
|
||||
}
|
||||
|
||||
public String getMaximumTransmissionUnit()
|
||||
{
|
||||
int mtu = mMessage.getInt( MTU );
|
||||
|
||||
switch( mtu )
|
||||
{
|
||||
case 1:
|
||||
return "296 BYTES";
|
||||
case 2:
|
||||
return "510 BYTES";
|
||||
case 3:
|
||||
return "1020 BYTES";
|
||||
case 4:
|
||||
return "1500 BYTES";
|
||||
default:
|
||||
return "UNK-" + mtu;
|
||||
}
|
||||
}
|
||||
|
||||
public MDPConfigurationOption getMDPConfigurationOption()
|
||||
{
|
||||
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
|
||||
}
|
||||
|
||||
public String getDataAccessControl()
|
||||
{
|
||||
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPActivateTDSContextReject extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextReject.class );
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] REJECT_CODE = { 184,185,186,187,188,189,190,191 };
|
||||
|
||||
public SNDCPActivateTDSContextReject( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REJECT SNDCP PACKET DATA ACTIVATE - REASON:" );
|
||||
sb.append( getReason().getLabel() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public SNDCPActivationRejectReason getReason()
|
||||
{
|
||||
return SNDCPActivationRejectReason.fromValue( mMessage.getInt( REJECT_CODE ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.MDPConfigurationOption;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPActivateTDSContextRequest extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextRequest.class );
|
||||
|
||||
public static final int[] SNDCP_VERSION = { 180,181,182,183 };
|
||||
public static final int[] NSAPI = { 184,185,186,187 };
|
||||
public static final int[] NAT = { 188,189,190,191 };
|
||||
public static final int[] IP_1 = { 192,193,194,195,196,197,198,199 };
|
||||
public static final int[] IP_2 = { 200,201,202,203,204,205,206,207 };
|
||||
public static final int[] IP_3 = { 208,209,210,211,212,213,214,215 };
|
||||
public static final int[] IP_4 = { 216,217,218,219,220,221,222,223 };
|
||||
public static final int[] DSUT = { 224,225,226,227 };
|
||||
public static final int[] UDPC = { 228,229,230,231 };
|
||||
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TCPSS = { 240,241,242,243 };
|
||||
public static final int[] UDPSS = { 244,245,246,247 };
|
||||
public static final int[] MDPCO = { 248,249,250,251,252,253,254,255 };
|
||||
|
||||
public SNDCPActivateTDSContextRequest( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REQUEST SNDCP PACKET DATA ACTIVATE " );
|
||||
sb.append( getNetworkAddressType() );
|
||||
sb.append( " " );
|
||||
sb.append( getIPAddress() );
|
||||
sb.append( " NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* SNDCP Version: 1 = P25 SNDCP Version 1
|
||||
*/
|
||||
public int getSNDCPVersion()
|
||||
{
|
||||
return mMessage.getInt( SNDCP_VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public String getNetworkAddressType()
|
||||
{
|
||||
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
|
||||
}
|
||||
|
||||
public String getIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getDataSubscriberUnitType()
|
||||
{
|
||||
switch( mMessage.getInt( DSUT ) )
|
||||
{
|
||||
case 0:
|
||||
return "DATA ONLY MRC";
|
||||
case 1:
|
||||
return "DATA AND VOICE MRC";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
public boolean hasIPHeaderCompression()
|
||||
{
|
||||
return mMessage.getInt( IPHC ) == 1;
|
||||
}
|
||||
|
||||
public boolean hasUserDataPayloadCompression()
|
||||
{
|
||||
return mMessage.getInt( UDPC ) == 1;
|
||||
}
|
||||
|
||||
public int getTCPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( TCPSS );
|
||||
}
|
||||
|
||||
public int getUDPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( UDPSS );
|
||||
}
|
||||
|
||||
public MDPConfigurationOption getMDPConfigurationOption()
|
||||
{
|
||||
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPDeactivateTDSContext extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPDeactivateTDSContext.class );
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] DEACTIVATION_TYPE = { 184,185,186,187,188,189,
|
||||
190,191 };
|
||||
|
||||
public SNDCPDeactivateTDSContext( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REQUEST SNDCP PACKET DATA DEACTIVATE " );
|
||||
sb.append( getDeactivationType() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public String getDeactivationType()
|
||||
{
|
||||
if( getPDUType() == PDUType.SN_DEACTIVATE_TDS_CONTEXT_REQUEST )
|
||||
{
|
||||
return mMessage.getInt( DEACTIVATION_TYPE ) == 0 ?
|
||||
"ALL NSAPIS" : "THIS NSAPI";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
356
src/module/decode/p25/message/pdu/confirmed/SNDCPUserData.java
Normal file
356
src/module/decode/p25/message/pdu/confirmed/SNDCPUserData.java
Normal file
@@ -0,0 +1,356 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.IPHeaderCompression;
|
||||
import module.decode.p25.reference.IPProtocol;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPUserData extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPUserData.class );
|
||||
|
||||
public static final int DATA_BLOCK_START = 176;
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] PCOMP = { 184,185,186,187 };
|
||||
public static final int[] DCOMP = { 188,189,190,191 };
|
||||
|
||||
/* IP Packet Header */
|
||||
public static final int[] IP_VERSION = { 192,193,194,195 };
|
||||
public static final int[] IHL = { 196,197,198,199 };
|
||||
public static final int[] DSCP = { 200,201,202,203,204,205 };
|
||||
public static final int[] ECN = { 206,207 };
|
||||
public static final int[] TOTAL_LENGTH = { 208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223 };
|
||||
public static final int[] IDENTIFICATION = { 224,225,226,227,228,229,230,231,
|
||||
232,233,234,235,236,237,238,239 };
|
||||
public static final int[] FLAGS = { 240,241,242 };
|
||||
public static final int[] FRAGMENT_OFFSET = { 243,244,245,246,247,248,249,
|
||||
250,251,252,253,254,255 };
|
||||
public static final int[] TTL = { 256,257,258,259,260,261,262,263 };
|
||||
public static final int[] PROTOCOL = { 264,265,266,267,268,269,270,271 };
|
||||
public static final int[] HEADER_CHECKSUM = { 272,273,274,275,276,277,278,
|
||||
279,280,281,282,283,284,285,286,287 };
|
||||
public static final int[] SOURCE_IP_1 = { 288,289,290,291,292,293,294,295 };
|
||||
public static final int[] SOURCE_IP_2 = { 296,297,298,299,300,301,302,303 };
|
||||
public static final int[] BLOCK_SERIAL_2 = { 304,305,306,307,308,309,310 };
|
||||
public static final int[] BLOCK_CRC9_2 = { 311,312,313,314,315,316,317,318,
|
||||
319 };
|
||||
public static final int[] SOURCE_IP_3 = { 320,321,322,323,324,325,326,327 };
|
||||
public static final int[] SOURCE_IP_4 = { 328,329,330,331,332,333,334,335 };
|
||||
public static final int[] DESTINATION_IP_1 = { 336,337,338,339,340,341,342,343 };
|
||||
public static final int[] DESTINATION_IP_2 = { 344,345,346,347,348,349,350,351 };
|
||||
public static final int[] DESTINATION_IP_3 = { 352,353,354,355,356,357,358,359 };
|
||||
public static final int[] DESTINATION_IP_4 = { 360,361,362,363,364,365,366,367 };
|
||||
|
||||
public static final int IP_DATA_START = 368;
|
||||
|
||||
/* User Datagram Protocol */
|
||||
public static final int[] UDP_SOURCE_PORT = { 368,369,370,371,372,373,374,
|
||||
375 };
|
||||
public static final int[] UDP_DESTINATION_PORT = { 376,377,378,379,380,381,
|
||||
382,383 };
|
||||
public static final int[] UDP_LENGTH = { 384,385,386,387,388,389,390,391,
|
||||
392,393,394,395,396,397,398,399 };
|
||||
public static final int[] UDP_CHECKSUM = { 400,401,402,403,404,405,406,407,
|
||||
408,409,410,411,412,413,414,415 };
|
||||
public static final int UDP_DATA_START = 416;
|
||||
|
||||
public SNDCPUserData( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " SNDCP NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " " );
|
||||
IPProtocol protocol = getIPProtocol();
|
||||
|
||||
sb.append( protocol.getLabel() );
|
||||
sb.append( "/IP" );
|
||||
|
||||
sb.append( " FM:" );
|
||||
sb.append( getSourceIPAddress() );
|
||||
|
||||
if( protocol == IPProtocol.UDP )
|
||||
{
|
||||
sb.append( ":" );
|
||||
sb.append( getUDPSourcePort() );
|
||||
}
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getDestinationIPAddress() );
|
||||
|
||||
if( protocol == IPProtocol.UDP )
|
||||
{
|
||||
sb.append( ":" );
|
||||
sb.append( getUDPDestinationPort() );
|
||||
}
|
||||
|
||||
sb.append( " DATA:" );
|
||||
sb.append( getPayload() );
|
||||
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public IPHeaderCompression getIPHeaderCompressionState()
|
||||
{
|
||||
return IPHeaderCompression.fromValue( mMessage.getInt( PCOMP ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* No enum values were defined for this
|
||||
*/
|
||||
public boolean hasUserDataCompression()
|
||||
{
|
||||
return mMessage.getInt( DCOMP ) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP Version - should always be 4 (IPV4)
|
||||
*/
|
||||
public int getIPVersion()
|
||||
{
|
||||
return mMessage.getInt( IP_VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet header length in 32-bit words
|
||||
*/
|
||||
public int getInternetHeaderLength()
|
||||
{
|
||||
return mMessage.getInt( IHL );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet DSCP
|
||||
*/
|
||||
public int getDifferentiatedServicesCodePoint()
|
||||
{
|
||||
return mMessage.getInt( DSCP );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet ECN
|
||||
*/
|
||||
public int getExplicitCongestionNotification()
|
||||
{
|
||||
return mMessage.getInt( ECN );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet size in bytes, including header and data
|
||||
*/
|
||||
public int getTotalLength()
|
||||
{
|
||||
return mMessage.getInt( TOTAL_LENGTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet identification
|
||||
*/
|
||||
public int getIdentification()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFICATION );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet flags. 0-Reserved, 1-Don't Fragment, 2-More Fragments
|
||||
*/
|
||||
public int getFlags()
|
||||
{
|
||||
return mMessage.getInt( FLAGS );
|
||||
}
|
||||
|
||||
public boolean isFragment()
|
||||
{
|
||||
return getFlags() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet - identifies the offset value in 8-byte blocks (64-bit blocks)
|
||||
* for this packet fragment from the beginning.
|
||||
*/
|
||||
public int getFragmentOffset()
|
||||
{
|
||||
return mMessage.getInt( FRAGMENT_OFFSET );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet time (hops) to live
|
||||
*/
|
||||
public int getTimeToLive()
|
||||
{
|
||||
return mMessage.getInt( TTL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the IP protocol carried by the IP packet
|
||||
*/
|
||||
public IPProtocol getIPProtocol()
|
||||
{
|
||||
return IPProtocol.fromValue( mMessage.getInt( PROTOCOL ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Source IPV4 address
|
||||
*/
|
||||
public String getSourceIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( SOURCE_IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destination IPV4 address
|
||||
*/
|
||||
public String getDestinationIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP source port
|
||||
*/
|
||||
public int getUDPSourcePort()
|
||||
{
|
||||
return mMessage.getInt( UDP_SOURCE_PORT );
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP destination port
|
||||
*/
|
||||
public int getUDPDestinationPort()
|
||||
{
|
||||
return mMessage.getInt( UDP_DESTINATION_PORT );
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP data payload size in bytes
|
||||
*/
|
||||
public int getUDPDataLength()
|
||||
{
|
||||
return mMessage.getInt( UDP_LENGTH );
|
||||
}
|
||||
/**
|
||||
* Hex string representation of the packet data, including packet header
|
||||
* data if present.
|
||||
*/
|
||||
public String getPayload()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
/* Adjust for PDU header (2 bytes) plus IP Packet header (20 bytes) */
|
||||
int start = 22;
|
||||
|
||||
if( getIPProtocol() == IPProtocol.UDP )
|
||||
{
|
||||
/* Adjust for UDP header (8 bytes) */
|
||||
start = 30;
|
||||
}
|
||||
|
||||
int spacingCounter = 0;
|
||||
|
||||
/* Append octets inserting a space between each 32-bit value */
|
||||
int octets = getOctetCount() + getDataHeaderOffset();
|
||||
|
||||
for( int x = start; x < octets; x++ )
|
||||
{
|
||||
sb.append( getPacketOctet( x ) );
|
||||
|
||||
spacingCounter++;
|
||||
|
||||
if( spacingCounter >= 4 )
|
||||
{
|
||||
sb.append( " " );
|
||||
spacingCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the octet identified by the 0-indexed 'octet' argument location.
|
||||
* If there is a Data Header Offset, the 0 index points to the first octet
|
||||
* of the data header. Otherwise, the 0 index points to the first octet
|
||||
* of the packet. You must account for the data header offset when
|
||||
* specifying the octet.
|
||||
*/
|
||||
public String getPacketOctet( int octet )
|
||||
{
|
||||
int block = (int)( octet / 16 );
|
||||
int offset = octet % 16;
|
||||
|
||||
int start = DATA_BLOCK_START + ( block * 144 ) + ( offset * 8 );
|
||||
|
||||
return mMessage.getHex( start, start + 7, 2 );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user