Example #1
0
  /**
   * Splits an octet stream into the separate parts that would be the payloads of concatenated SMS
   * messages.
   *
   * @param messageBinary
   * @param sourcePort
   * @param destinationPort
   * @return Supplied byte[] split into parts. These parts should reconcatenate to form the original
   *     byte array. Supplying a zero-length byte[] should return a single, empty part.
   */
  public static byte[][] getPayloads(byte[] messageBinary, int sourcePort, int destinationPort) {
    if (messageBinary.length == 0) return new byte[][] {new byte[0]};

    boolean isPorted = sourcePort > 0 || destinationPort > 0;
    int totalParts = getMessagesNeeded_8bit(messageBinary.length, isPorted);
    byte[][] payloadParts = new byte[totalParts][];
    int udhLength = getUDHSize(true, isPorted, totalParts > 1);
    String encodedText = HexUtils.encode(messageBinary);
    for (int i = 0; i < payloadParts.length; i++) {
      payloadParts[i] = HexUtils.decode(extractPayload(encodedText, i + 1, udhLength));
    }
    return payloadParts;
  }
Example #2
0
  /**
   * Generates the TPDUs for a UCS-2-encoded text message. The TPDUs are returned as hex-encoded
   * binary strings.
   *
   * @param messageText
   * @param smscNumber
   * @param recipientMsisdn
   * @param concatReferenceNumber Reference number to embed in multipart message parts' UDH
   * @param sourcePort
   * @param destinationPort
   * @param requestStatusReport
   * @param validityPeriod Validity period of this message, in hours. Maximum validity will be
   *     requested if this is set to zero.
   * @param protocolIdentifier
   * @param dataCodingScheme
   * @return The PDUs to be sent for the message
   */
  public static String[] generatePdus_ucs2(
      String messageText,
      String smscNumber,
      String recipientMsisdn,
      int concatReferenceNumber,
      int sourcePort,
      int destinationPort,
      boolean requestStatusReport,
      int validityPeriod,
      int protocolIdentifier,
      int dataCodingScheme) {
    boolean isPorted = sourcePort > 0 || destinationPort > 0;
    String[] messageParts = splitText_ucs2(messageText, isPorted);
    final int totalParts = messageParts.length;
    boolean isMultipart = totalParts > 1;

    boolean requiresUdh = isMultipart || isPorted;

    String[] pdus = new String[totalParts];

    try {
      for (int partNumber = 1; partNumber <= totalParts; ++partNumber) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        out.write(encodeMsisdnAsAddressField(smscNumber, true));

        // get the front byte, which identifies message content
        out.write(getByteZero(TP_MTI_MO_SUBMIT, requiresUdh, requestStatusReport));

        // Message reference.  Always zero here.
        /** [TP-MR: TP-Message-Reference] Parameter identifying the SMS-SUBMIT. */
        out.write(0);

        // Add the recipient's MSISDN
        /** [TP-DA: TP-Destination-Address] Address of the destination SME. */
        out.write(encodeMsisdnAsAddressField(recipientMsisdn, false));

        /**
         * [TP-PID: TP-Protocol-Identifier] Parameter identifying the above layer protocol, if any.
         */
        out.write(protocolIdentifier);

        /**
         * [TP-DCS: TP-Data-CodingScheme] Parameter identifying the coding scheme within the
         * TP-User-Data.
         */
        out.write(dataCodingScheme);

        /**
         * [TP-VP: TP-Validity-Period] Parameter identifying the time from where the message is no
         * longer valid. Here, this is always relative.
         */
        out.write(getRelativeVP(validityPeriod));

        // Build the UD

        // First build the UDH
        /**
         * Total length of the udh, including the UDHL. Do not confuse with udhBytes.length, which
         * is the length of the UDH's content
         */
        int udhTotalLength = getUDHSize(true, isPorted, isMultipart);

        byte[] encodedText = encodeUcs2Text(messageParts[partNumber - 1]);

        /** The length, in octets, of the user data, including the header. */
        int dataLen = encodedText.length + udhTotalLength;

        /** [TP-UDL: TP-User-Data-Length] Length of the UD, specific to the encoding. */
        out.write(dataLen);
        if (requiresUdh) {
          /** Now write the octet content of the UDH */
          out.write(
              generateUDH(
                  partNumber, totalParts, concatReferenceNumber, sourcePort, destinationPort));
        }

        /** Add the MS to the PDU */
        out.write(encodedText);

        pdus[partNumber - 1] = HexUtils.encode(out.toByteArray());
      }
      return pdus;
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }
Example #3
0
  /**
   * Generate PDUs for a text message encoded using {@link SmsMessageEncoding#GSM_7BIT}.
   *
   * @param messageText
   * @param smscNumber
   * @param recipientMsisdn
   * @param concatReferenceNumber
   * @param sourcePort
   * @param destinationPort
   * @param requestStatusReport
   * @param validityPeriod
   * @param protocolIdentifier
   * @param dataCodingScheme
   * @return An ordered list of PDUs encoded as hexadecimal strings which combine to recreate the
   *     original text message.
   */
  public static String[] generatePdus_gsm7bit(
      String messageText,
      String smscNumber,
      String recipientMsisdn,
      int concatReferenceNumber,
      int sourcePort,
      int destinationPort,
      boolean requestStatusReport,
      int validityPeriod,
      int protocolIdentifier,
      int dataCodingScheme) {
    boolean isPorted = sourcePort > 0 || destinationPort > 0;
    String[] messageParts = GsmAlphabet.splitText(messageText, isPorted);

    final int totalParts = messageParts.length;
    boolean isMultipart = totalParts > 1;
    boolean requiresUdh = isMultipart || isPorted;

    /** PDUs that make up this message, encoded as hexadecimal strings. */
    String[] pdus = new String[totalParts];

    try {
      for (int partNumber = 1; partNumber <= totalParts; ++partNumber) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        out.write(encodeMsisdnAsAddressField(smscNumber, true));

        // get the front byte, which identifies message content
        out.write(getByteZero(TP_MTI_MO_SUBMIT, requiresUdh, requestStatusReport));

        // Message reference.  Always zero here.
        /** [TP-MR: TP-Message-Reference] Parameter identifying the SMS-SUBMIT. */
        out.write(0);

        // Add the recipient's MSISDN
        /** [TP-DA: TP-Destination-Address] Address of the destination SME. */
        out.write(encodeMsisdnAsAddressField(recipientMsisdn, false));

        /**
         * [TP-PID: TP-Protocol-Identifier] Parameter identifying the above layer protocol, if any.
         */
        out.write(protocolIdentifier);

        /**
         * [TP-DCS: TP-Data-CodingScheme] Parameter identifying the coding scheme within the
         * TP-User-Data.
         */
        out.write(dataCodingScheme);

        /**
         * [TP-VP: TP-Validity-Period] Parameter identifying the time from where the message is no
         * longer valid. Here, this is always relative.
         */
        out.write(getRelativeVP(validityPeriod));

        // Build the UD

        // First build the UDH
        /**
         * Total length of the udh, including the UDHL. Do not confuse with udhBytes.length, which
         * is the length of the UDH's content
         */
        int udhTotalLength = getUDHSize(true, isPorted, isMultipart);

        byte[] encodedMessageSeptets = GsmAlphabet.stringToBytes(messageParts[partNumber - 1]);
        /** Encode the message text using the standard 7-bit GSM alphabet. */
        int skipBits = GsmAlphabet.calculateBitSkip(udhTotalLength);
        byte[] encodedMessageText =
            GsmAlphabet.septetStream2octetStream(encodedMessageSeptets, skipBits);

        /**
         * [TP-UDL: TP-User-Data-Length] Length of the UD, specific to the encoding. For a 7-bit GSM
         * charset message, this is the number of septets in the UD.
         */
        int udLength =
            (int)
                Math.ceil(
                    ((udhTotalLength * 8) + (encodedMessageSeptets.length * 7) + skipBits) / 7.0);
        out.write(udLength);

        if (requiresUdh) {
          /** Now write the octet content of the UDH */
          out.write(
              generateUDH(
                  partNumber, totalParts, concatReferenceNumber, sourcePort, destinationPort));
        }

        out.write(encodedMessageText);

        pdus[partNumber - 1] = HexUtils.encode(out.toByteArray());
      }
      return pdus;
    } catch (IOException ex) {
      throw new RuntimeException(ex);
    }
  }