Class AX25Message

java.lang.Object
org.ka2ddo.ax25.AX25Message
All Implemented Interfaces:
Serializable, Cloneable, Comparable<AX25Message>
Direct Known Subclasses:
Message, OpenTracMessage

public abstract class AX25Message extends Object implements Comparable<AX25Message>, Serializable, Cloneable
This class defines the common infrastructure for one decoded AX.25 message. Subclasses implement the details for different layer 3 and above protocols.
Author:
Andrew Pavlin, KA2DDO
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static enum 
    This enum defines the allowed traffic precedence levels for messages.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected static final Set<ProtocolFamily>
    A read-only protocol set that includes both APRS and OpenTRAC.
    The AX.25 frame object from which this Message was extracted.
    protected Map<Enum,Object>
    Optional map of extracted data fields in this APRS message.
    protected boolean
    Indicates whether message was correctly formatted or otherwise parseable.
    Callsign of the station originating this message.
    Destination "callsign" from the station originating this message.
    static final long
    Reserved constant for non-expiring objects' timestamp.
    long
    The time the message was received by the system in Java standard milliseconds since 1970 UTC.
    The entire third-party routing path for this AX25Message, or null if this AX25message is still on its original network.
    long
    Message timestamp in Java standard milliseconds since 1970 UTC.
    static final TimeZone
    TimeZone object for Greenwich Mean Time (or Universal Coordinated Time), used for converting text string times and dates into binary.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    Constructor for partially initialized AX25Message.
    protected
    AX25Message(String thirdParty, long rcptTime)
    Constructor for AX25Message specifying the third-party network routing and receive time of the message.
  • Method Summary

    Modifier and Type
    Method
    Description
    protected abstract boolean
    Compare the contents of the body of the message, reporting if they match.
    int
    Compares this object with the specified object for order.
    dup()
    Creates and returns a copy of this AX25Message.
    boolean
    Test if the Object o is a duplicate of this Message.
    void
    Extract the originating station callsign for this AX25Message.
    final AX25Frame
    Get the AX.25 frame from which this Message was extracted.
    Get a particular extension value from this message.
    Return the callsign of the first digipeat station for this message.
    Return the callsign of the last digipeat station for this message.
    getNthDigipeat(AX25Callsign[] digipeaters, int index)
    Return the callsign of the Nth digipeat station for this message.
    static String
    Extract the callsign of the original destination of this message.
    static String
    Extract the callsign of the original destination of this message.
    Get the callsign of the station that originated this message (not of any Tx-Igate relay).
    Get the destination address oeiginally specified bv the station that originated this message.
    Report the traffic-handling precedence for this message instance.
    Get the protocol family or families that this message corresponds to, so ports that don't support all protocols will not forward inappropriate packets.
    long
    Get the timestamp this AX25Message was received in milliseconds since 1 Jan 1970 UTC.
    Get a reference to the extension map that should not be modified.
    long
    Get the timestamp associated with this Message in milliseconds since 1 Jan 1970 UTC.
    int
    Returns a hash code for this Message.
    boolean
    Report if this AX25Message contains position data.
    boolean
    hasThisFirstDigi(AX25Callsign[] digipeaters, String digiCallsign)
    Test if the specified callsign is the first digipeat station for this message.
    abstract boolean
    Report if this AX25Message contains weather information.
    static int
    indexOf(byte[] buf, int bufLen, char matchCh, int startPos)
    Search a byte array (assumed to be an ASCII string) for a matching character.
    static int
    indexOf(byte[] buf, int bufLen, String matchStr, int startPos)
    Search a byte array (assumed to be an ASCII string) for a matching ASCII string.
    boolean
    Test if this message was sent directly (without any relay station).
    boolean
    Test if this message was flagged as invalid.
    isRf(int maxDigis)
    Test if this AX25Message came from an RF connection.
    static boolean
    onlyDigits(byte[] body, int pos, int len)
    Test if the specified part of the message body is strictly only ASCII digits.
    static boolean
    onlyDigits(String body, int pos, int len)
    Test if the specified part of the message body is strictly only ASCII digits.
    static boolean
    onlyDigitsOrMinus(byte[] body, int pos, int len)
    Test if the specified part of the message body is strictly only ASCII digits.
    static boolean
    onlyDigitsOrPeriod(String body, int pos, int len)
    Test if the specified part of the message body is strictly only ASCII digits.
    protected static boolean
    onlyDigitsOrSpace(byte[] body, int pos, int len)
    Test if the specified part of the message body is strictly only ASCII digits or space characters.
    protected static boolean
    onlyDigitsPlus(byte[] body, int pos, int len)
    Test if the specified part of the message body is only ASCII digits or characters just after the digits (to support base+offset message codes in APRS).
    protected static boolean
    onlyPeriods(byte[] body, int pos, int len)
    Test if the specified part of the message body is strictly only period characters.
    Descriptive text about this message, to be included in the toString() method's response.
    final void
    Attach the AX.25 frame from which this Message was extracted.
    void
    setInvalid(boolean invalid)
    Mark if this message is invalid or not.
    void
    setOriginatingCallsign(String originatingCallsign)
    Set the originating callsign for this AX25Message.
    void
    setRcptTime(long rcptTime)
    Change the receive time of this message.
    void
    setTimestamp(long timestamp)
    Change the timestamp of this message.
    static String[]
    split(String line, char separator)
    This is a more optimized version of String.split() that doesn't require compiling and evaluating regular expression patterns to do it, thereby saving chunks of transient heap (and probably some CPU time as well).
    <K extends Enum, V>
    void
    storeExtension(K key, V value)
    Store an extracted data element in the Message.
    Returns a string representation of the object.

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Field Details

    • PERMANENT

      public static final long PERMANENT
      Reserved constant for non-expiring objects' timestamp.
      See Also:
    • ax25Frame

      public AX25Frame ax25Frame
      The AX.25 frame object from which this Message was extracted.
    • originatingCallsign

      public String originatingCallsign
      Callsign of the station originating this message. This may not match the sender callsign if the message was relayed through a third-party network (such as APRS-IS). In such cases, sender will be the callsign of the station transmitting the message onto RF, and originatingCallsign will be taken from the third-party routing information to indicate the station that originally injected this message into the network of networks.
      See Also:
    • originatingDest

      public String originatingDest
      Destination "callsign" from the station originating this message. This may not match the destination callsign if the message was relayed through a third-party network (such as APRS-IS). In such cases, destination will be the "tocall" (assuming APRS) of the station transmitting the message onto RF, and originatingDest will be taken from the third-party routing information to indicate the destination that originally injected this message into the network of networks.
      See Also:
    • thirdParty

      public String thirdParty
      The entire third-party routing path for this AX25Message, or null if this AX25message is still on its original network.
    • timestamp

      public long timestamp
      Message timestamp in Java standard milliseconds since 1970 UTC. May be different from rcptTime if the message body has a time value in it.
    • rcptTime

      public long rcptTime
      The time the message was received by the system in Java standard milliseconds since 1970 UTC.
    • invalid

      protected boolean invalid
      Indicates whether message was correctly formatted or otherwise parseable.
    • extensions

      protected Map<Enum,Object> extensions
      Optional map of extracted data fields in this APRS message. May be null if no extensions present in the message.
    • UTC

      public static final TimeZone UTC
      TimeZone object for Greenwich Mean Time (or Universal Coordinated Time), used for converting text string times and dates into binary.
    • APRS_AND_OPENTRAC

      protected static final Set<ProtocolFamily> APRS_AND_OPENTRAC
      A read-only protocol set that includes both APRS and OpenTRAC.
      See Also:
  • Constructor Details

    • AX25Message

      protected AX25Message()
      Constructor for partially initialized AX25Message.
    • AX25Message

      protected AX25Message(String thirdParty, long rcptTime)
      Constructor for AX25Message specifying the third-party network routing and receive time of the message.
      Parameters:
      thirdParty - The entire third-party routing path for this AX25Message, or null if this AX25message is still on its original network.
      rcptTime - The time the message was received by the system in Java standard milliseconds since 1970 UTC.
  • Method Details

    • equals

      public boolean equals(Object o)
      Test if the Object o is a duplicate of this Message.
      Overrides:
      equals in class Object
      Parameters:
      o - Object to compare against this message.
      Returns:
      true if o is a Message with the same contents as this Message
    • bodyEquals

      protected abstract boolean bodyEquals(AX25Message other)
      Compare the contents of the body of the message, reporting if they match. This method must be overridden by concrete subclasses, but will only be called when the Class of the other message equals the Class of this message.
      Parameters:
      other - another AX25Message to compare against
      Returns:
      boolean true if the body values are equivalent
    • hashCode

      public int hashCode()
      Returns a hash code for this Message.
      Overrides:
      hashCode in class Object
      Returns:
      a hash code value for this object.
    • compareTo

      public int compareTo(AX25Message o)
      Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
      Specified by:
      compareTo in interface Comparable<AX25Message>
      Parameters:
      o - the object to be compared.
      Returns:
      a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
      Throws:
      ClassCastException - if the specified object's type prevents it from being compared to this object.
    • onlyDigits

      public static boolean onlyDigits(String body, int pos, int len)
      Test if the specified part of the message body is strictly only ASCII digits.
      Parameters:
      body - String containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are ASCII digits
    • onlyDigitsOrPeriod

      public static boolean onlyDigitsOrPeriod(String body, int pos, int len)
      Test if the specified part of the message body is strictly only ASCII digits.
      Parameters:
      body - String containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are ASCII digits
    • onlyDigits

      public static boolean onlyDigits(byte[] body, int pos, int len)
      Test if the specified part of the message body is strictly only ASCII digits.
      Parameters:
      body - byte array containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are ASCII digits
    • onlyDigitsOrMinus

      public static boolean onlyDigitsOrMinus(byte[] body, int pos, int len)
      Test if the specified part of the message body is strictly only ASCII digits.
      Parameters:
      body - byte array containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are ASCII digits
    • onlyDigitsPlus

      protected static boolean onlyDigitsPlus(byte[] body, int pos, int len)
      Test if the specified part of the message body is only ASCII digits or characters just after the digits (to support base+offset message codes in APRS).
      Parameters:
      body - byte array containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are in the 16-byte block containing ASCII digits
    • onlyDigitsOrSpace

      protected static boolean onlyDigitsOrSpace(byte[] body, int pos, int len)
      Test if the specified part of the message body is strictly only ASCII digits or space characters.
      Parameters:
      body - byte array containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are ASCII digits or spaces
    • onlyPeriods

      protected static boolean onlyPeriods(byte[] body, int pos, int len)
      Test if the specified part of the message body is strictly only period characters.
      Parameters:
      body - byte array containing the message body
      pos - starting index in the array to test
      len - number of bytes to test
      Returns:
      boolean true if all the bytes are periods
    • indexOf

      public static int indexOf(byte[] buf, int bufLen, char matchCh, int startPos)
      Search a byte array (assumed to be an ASCII string) for a matching character.
      Parameters:
      buf - byte array to search
      bufLen - index of end of used part of buffer
      matchCh - character value to search for in a forward search
      startPos - zero-based index to start searching at
      Returns:
      first index of character occurrence after the start pos, or -1 if not found
    • indexOf

      public static int indexOf(byte[] buf, int bufLen, String matchStr, int startPos)
      Search a byte array (assumed to be an ASCII string) for a matching ASCII string.
      Parameters:
      buf - byte array to search
      bufLen - index of end of used part of buffer
      matchStr - String value to search for in a forward search
      startPos - zero-based index to start searching at
      Returns:
      first index of string occurrence after the start pos, or -1 if not found
    • paramString

      public String paramString()
      Descriptive text about this message, to be included in the toString() method's response. This method may be overridden. Its default implementation returns an empty string.
      Returns:
      String describing the contents of this message
      See Also:
    • toString

      public String toString()
      Returns a string representation of the object.
      Overrides:
      toString in class Object
      Returns:
      a string representation of the object.
    • extractSource

      public void extractSource() throws IllegalArgumentException
      Extract the originating station callsign for this AX25Message.
      Throws:
      IllegalArgumentException - if thirdParty string is provided but doesn't have a sender>dest delimiter
    • getAx25Frame

      public final AX25Frame getAx25Frame()
      Get the AX.25 frame from which this Message was extracted.
      Returns:
      transport-compatible AX25Frame for this Message
    • setAx25Frame

      public final void setAx25Frame(AX25Frame ax25Frame)
      Attach the AX.25 frame from which this Message was extracted.
      Parameters:
      ax25Frame - AX25Frame object containing the encoding of this Message
    • getOriginalSource

      public static String getOriginalSource(AX25Callsign src, String thirdParty)
      Extract the callsign of the original destination of this message.
      Parameters:
      src - AX25Callsign of the source of the original AX25Frame
      thirdParty - String of the third-party routing of this message, or null if not routed over another network
      Returns:
      source callsign String
    • getOriginalDestination

      public static String getOriginalDestination(AX25Callsign dest, String thirdParty)
      Extract the callsign of the original destination of this message.
      Parameters:
      dest - AX25Callsign of the destination (tocall) of the original AX25Frame
      thirdParty - String of the third-party routing of this message, or null if not routed over another network
      Returns:
      destination callsign String
    • getLastDigipeat

      public String getLastDigipeat(AX25Callsign[] digipeaters)
      Return the callsign of the last digipeat station for this message.
      Parameters:
      digipeaters - array of AX25Callsign digipeater addresses in AX.25 frame
      Returns:
      String station ID of last digipeat station, or empty string if received directly from originating station
    • getFirstDigipeat

      public String getFirstDigipeat(AX25Callsign[] digipeaters)
      Return the callsign of the first digipeat station for this message. Note this code considers a direct receive by an I-gate as the I-gate being the first "digipeater".
      Parameters:
      digipeaters - array of AX25Callsign digipeater addresses in AX.25 frame
      Returns:
      String station ID of first digipeat station, or empty string if received directly from originating station
    • getNthDigipeat

      public String getNthDigipeat(AX25Callsign[] digipeaters, int index)
      Return the callsign of the Nth digipeat station for this message. Note this code considers a direct receive by an I-gate as the I-gate being the first "digipeater". If the index is past all the third-party digipeaters and I-gate and this is an RF packet, the RF digipeaters used by the transmitting I-gate will then be iterated through. Note that RF digipeater aliases that are not marked has-been-repeated will not be counted, nor will "q" codes in a third-party prefix.
      Parameters:
      digipeaters - array of AX25Callsign digipeater addresses in AX.25 frame
      index - zero-based index into the list of digipeat aliases
      Returns:
      String station ID of Nth digipeat station, or null if past end of used digipeat list
    • hasThisFirstDigi

      public boolean hasThisFirstDigi(AX25Callsign[] digipeaters, String digiCallsign)
      Test if the specified callsign is the first digipeat station for this message.
      Parameters:
      digipeaters - array of AX25Callsign digipeater addresses in AX.25 frame
      digiCallsign - String callsign/SSID of digipeater
      Returns:
      boolean true if the specified digipeater is the first digi for this message
    • getTimestamp

      public long getTimestamp()
      Get the timestamp associated with this Message in milliseconds since 1 Jan 1970 UTC.
      Returns:
      time message was received or the timestamp in the message, or -1 if this is a permanent (non-timing-out message)
    • hasWeather

      public abstract boolean hasWeather()
      Report if this AX25Message contains weather information.
      Returns:
      boolean true if weather information in this AX25Message
    • hasPosition

      public boolean hasPosition()
      Report if this AX25Message contains position data. The default implementation returns false; position-reporting subclasses are expected to override this.
      Returns:
      boolean true if message contains position information
    • setTimestamp

      public void setTimestamp(long timestamp)
      Change the timestamp of this message. Intended only for use by the Transmitter class when creating a time-stamped duplicate of a periodically-repeated APRS Message.
      Parameters:
      timestamp - new time in Java milliseconds since epoch
    • setOriginatingCallsign

      public void setOriginatingCallsign(String originatingCallsign)
      Set the originating callsign for this AX25Message. This should only be called on SendableMessages to initialize them before transmission.
      Parameters:
      originatingCallsign - String of the originating station callsign of this message
    • getOriginatingCallsign

      public String getOriginatingCallsign()
      Get the callsign of the station that originated this message (not of any Tx-Igate relay).
      Returns:
      String callsign
    • getOriginatingDest

      public String getOriginatingDest()
      Get the destination address oeiginally specified bv the station that originated this message.
      Returns:
      String callsign
    • getRcptTime

      public long getRcptTime()
      Get the timestamp this AX25Message was received in milliseconds since 1 Jan 1970 UTC.
      Returns:
      time message was received
    • setRcptTime

      public void setRcptTime(long rcptTime)
      Change the receive time of this message. Intended only for use by the Transmitter class when creating a time-stamped duplicate of a periodically-repeated APRS Message.
      Parameters:
      rcptTime - new time in Java milliseconds since epoch
    • isInvalid

      public boolean isInvalid()
      Test if this message was flagged as invalid.
      Returns:
      boolean true if this message is marked as invalid
    • setInvalid

      public void setInvalid(boolean invalid)
      Mark if this message is invalid or not.
      Parameters:
      invalid - boolean true if message should be considered invalid or incorrect syntax
    • getPrecedence

      public AX25Message.Precedence getPrecedence()
      Report the traffic-handling precedence for this message instance. Expected to be overridden by subclasses that have precedence fields.
      Returns:
      Precedence level for this AX25Message
    • dup

      public AX25Message dup()
      Creates and returns a copy of this AX25Message.
      Returns:
      a clone of this instance.
      See Also:
    • storeExtension

      public <K extends Enum, V> void storeExtension(K key, V value)
      Store an extracted data element in the Message.
      Type Parameters:
      K - any enum subclass
      V - any Java object class
      Parameters:
      key - Enum that identifies the particular data item
      value - the data value
      See Also:
    • getReadOnlyExtensionMap

      public Map<Enum,Object> getReadOnlyExtensionMap()
      Get a reference to the extension map that should not be modified.
      Returns:
      Map of extension data element (may be an empty Map)
      See Also:
    • getExtension

      public Object getExtension(Enum key)
      Get a particular extension value from this message.
      Parameters:
      key - Enum instance identifying the desired extension
      Returns:
      value for that extension, or null if no value stored
      See Also:
    • getProtocols

      public Set<ProtocolFamily> getProtocols()
      Get the protocol family or families that this message corresponds to, so ports that don't support all protocols will not forward inappropriate packets.
      Returns:
      array of supported ProtocolFamily enums
    • isRf

      public Boolean isRf(int maxDigis)
      Test if this AX25Message came from an RF connection.
      Parameters:
      maxDigis - int maximum number of digipeat hops before we're not going to count it
      Returns:
      Boolean.TRUE if a local Rf transmission, Boolean.FALSE if not RF-only, null if we can't tell
    • isDirect

      public boolean isDirect()
      Test if this message was sent directly (without any relay station).
      Returns:
      boolean true if direct, false if not
    • split

      public static String[] split(String line, char separator)
      This is a more optimized version of String.split() that doesn't require compiling and evaluating regular expression patterns to do it, thereby saving chunks of transient heap (and probably some CPU time as well).
      Parameters:
      line - the String to split at occurrences of the separator
      separator - the String delimiting substrings of the line
      Returns:
      array of Strings split at the various points the separator appears