📄 pdugenerator.java
字号:
// given the IEs in the pdu derive the max message body length
// this length will include the potential concat added in the previous step
int totalUDHLength = pdu.getTotalUDHLength();
int maxMessageLength = 160 - PduUtils.getNumSeptetsForOctets(totalUDHLength);
// get septets for part
byte[] textSeptets = getUnencodedSeptetsForPart(pdu, maxMessageLength, partNo);
// udlength is the sum of udh septet length and the text septet length
int udLength = PduUtils.getNumSeptetsForOctets(totalUDHLength) + textSeptets.length;
baos.write(udLength);
// generate UDH byte[]
// UDHL (sum of all IE lengths)
// IE list
byte[] udhBytes = null;
if (pdu.hasTpUdhi())
{
ByteArrayOutputStream udhBaos = new ByteArrayOutputStream();
writeUDH(pdu, udhBaos);
// buffer the udh since this needs to be 7-bit encoded with the text
udhBytes = udhBaos.toByteArray();
}
// encode both as one unit
byte[] udBytes = PduUtils.encode7bitUserData(udhBytes, textSeptets);
// write combined encoded array
baos.write(udBytes);
}
private byte[] getUnencodedSeptetsForPart(Pdu pdu, int maxMessageLength, int partNo)
{
// computes offset to which part of the string is to be encoded into the PDU
// also sets the MpMaxNo field of the concatInfo if message is multi-part
int offset;
int maxParts = 1;
// must use the unencoded septets not the actual string since
// it is possible that some special characters in string are multi-septet
byte[] unencodedSeptets = PduUtils.stringToUnencodedSeptets(pdu.getDecodedText());
maxParts = (unencodedSeptets.length / maxMessageLength) + 1;
if (pdu.hasTpUdhi())
{
if (pdu.getConcatInfo() != null)
{
if (partNo > 0)
{
pdu.getConcatInfo().setMpMaxNo(maxParts);
}
}
}
if ((maxParts > 1) && (partNo > 0))
{
// - if partNo > maxParts
// - error
if (partNo > maxParts) { throw new RuntimeException("Invalid partNo: " + partNo + ", maxParts=" + maxParts); }
offset = ((partNo - 1) * maxMessageLength);
}
else
{
// just get from the start
offset = 0;
}
// copy the portion of the full unencoded septet array for this part
byte[] septetsForPart = new byte[Math.min(maxMessageLength, unencodedSeptets.length-offset)];
System.arraycopy(unencodedSeptets, offset, septetsForPart, 0, septetsForPart.length);
return septetsForPart;
}
protected void writeUDData8bit(Pdu pdu, int mpRefNo, int partNo) throws Exception
{
// NOTE: binary messages are also handled here
byte[] data;
if (pdu.isBinary())
{
// use the supplied bytes
data = pdu.getDataBytes();
}
else
{
// encode the text
data = PduUtils.encode8bitUserData(pdu.getDecodedText());
}
// partNo states what part of the unencoded text will be used
// - max length is based on the size of the UDH
// for 8bit => maxLength = 140 - the total UDH bytes
// check if this message needs a concat
int potentialUdhLength = computePotentialUdhLength(pdu);
checkForConcat(pdu,
data.length,
140 - pdu.getTotalUDHLength(), // CHANGED
140 - potentialUdhLength,
mpRefNo,
partNo);
// given the IEs in the pdu derive the max message body length
// this length will include the potential concat added in the previous step
int totalUDHLength = pdu.getTotalUDHLength();
int maxMessageLength = 140 - totalUDHLength;
// compute which portion of the message will be part of the message
int offset = computeOffset(pdu, maxMessageLength, partNo);
byte[] dataToWrite = new byte[Math.min(maxMessageLength, data.length - offset)];
System.arraycopy(data, offset, dataToWrite, 0, dataToWrite.length);
// generate udlength
// based on partNo
// udLength is an octet count for 8bit/ucs2
int udLength = totalUDHLength + dataToWrite.length;
// write udlength
baos.write(udLength);
// write UDH to the stream directly
if (pdu.hasTpUdhi())
{
writeUDH(pdu, baos);
}
// write data
baos.write(dataToWrite);
}
protected void writeUDDataUCS2(Pdu pdu, int mpRefNo, int partNo) throws Exception
{
String decodedText = pdu.getDecodedText();
// partNo states what part of the unencoded text will be used
// - max length is based on the size of the UDH
// for ucs2 => maxLength = (140 - the total UDH bytes)/2
// check if this message needs a concat
int potentialUdhLength = computePotentialUdhLength(pdu);
checkForConcat(pdu,
decodedText.length(),
(140 - pdu.getTotalUDHLength()) / 2, // CHANGED
(140 - potentialUdhLength) / 2,
mpRefNo,
partNo);
// given the IEs in the pdu derive the max message body length
// this length will include the potential concat added in the previous step
int totalUDHLength = pdu.getTotalUDHLength();
int maxMessageLength = (140 - totalUDHLength) / 2;
// compute which portion of the message will be part of the message
int offset = computeOffset(pdu, maxMessageLength, partNo);
String textToEncode = decodedText.substring(offset, Math.min(offset + maxMessageLength, decodedText.length()));
// generate udlength
// based on partNo
// udLength is an octet count for 8bit/ucs2
int udLength = totalUDHLength + (textToEncode.length() * 2);
// write udlength
baos.write(udLength);
// write UDH to the stream directly
if (pdu.hasTpUdhi())
{
writeUDH(pdu, baos);
}
// write encoded text
baos.write(PduUtils.encodeUcs2UserData(textToEncode));
}
protected void writeByte(int i)
{
baos.write(i);
}
protected void writeBytes(byte[] b) throws Exception
{
baos.write(b);
}
public List<String> generatePduList(Pdu pdu, int mpRefNo)
{
// generate all required PDUs for a given message
// mpRefNo comes from the ModemGateway
ArrayList<String> pduList = new ArrayList<String>();
for (int i = 1; i <= pdu.getMpMaxNo(); i++)
{
String pduString = generatePduString(pdu, mpRefNo, i);
pduList.add(pduString);
}
return pduList;
}
public String generatePduString(Pdu pdu)
{
return generatePduString(pdu, -1, -1);
}
// NOTE: partNo indicates which part of a multipart message to generate
// assuming that the message is multipart, this will be ignored if the
// message is not a concat message
public String generatePduString(Pdu pdu, int mpRefNo, int partNo)
{
try
{
baos = new ByteArrayOutputStream();
firstOctetPosition = -1;
updateFirstOctet = false;
// process the PDU
switch (pdu.getTpMti())
{
case PduUtils.TP_MTI_SMS_DELIVER:
generateSmsDeliverPduString((SmsDeliveryPdu) pdu, mpRefNo, partNo);
break;
case PduUtils.TP_MTI_SMS_SUBMIT:
generateSmsSubmitPduString((SmsSubmitPdu) pdu, mpRefNo, partNo);
break;
case PduUtils.TP_MTI_SMS_STATUS_REPORT:
generateSmsStatusReportPduString((SmsStatusReportPdu) pdu);
break;
}
// in case concat is detected in the writeUD() method
// and there was no UDHI at the time of detection
// the old firstOctet must be overwritten with the new value
byte[] pduBytes = baos.toByteArray();
if (updateFirstOctet)
{
pduBytes[firstOctetPosition] = (byte) (pdu.getFirstOctet() & 0xFF);
}
return PduUtils.bytesToPdu(pduBytes);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
protected void generateSmsSubmitPduString(SmsSubmitPdu pdu, int mpRefNo, int partNo) throws Exception
{
// SMSC address info
writeSmscInfo(pdu);
// first octet
writeFirstOctet(pdu);
// message reference
writeByte(pdu.getMessageReference());
// destination address info
writeAddress(pdu.getAddress(), pdu.getAddressType(), pdu.getAddress().length());
// protocol id
writeByte(pdu.getProtocolIdentifier());
// data coding scheme
writeByte(pdu.getDataCodingScheme());
// validity period
switch (pdu.getTpVpf())
{
case PduUtils.TP_VPF_INTEGER:
writeValidityPeriodInteger(pdu.getValidityPeriod());
break;
case PduUtils.TP_VPF_TIMESTAMP:
writeTimeStampStringForDate(pdu.getValidityDate());
break;
}
// user data
// headers
writeUDData(pdu, mpRefNo, partNo);
}
// NOTE: the following are just for validation of the PduParser
// - there is no normal scenario where these are used
protected void generateSmsDeliverPduString(SmsDeliveryPdu pdu, int mpRefNo, int partNo) throws Exception
{
// SMSC address info
writeSmscInfo(pdu);
// first octet
writeFirstOctet(pdu);
// originator address info
writeAddress(pdu.getAddress(), pdu.getAddressType(), pdu.getAddress().length());
// protocol id
writeByte(pdu.getProtocolIdentifier());
// data coding scheme
writeByte(pdu.getDataCodingScheme());
// timestamp
writeTimeStampStringForDate(pdu.getTimestamp());
// user data
// headers
writeUDData(pdu, mpRefNo, partNo);
}
protected void generateSmsStatusReportPduString(SmsStatusReportPdu pdu) throws Exception
{
// SMSC address info
writeSmscInfo(pdu);
// first octet
writeFirstOctet(pdu);
// message reference
writeByte(pdu.getMessageReference());
// destination address info
writeAddress(pdu.getAddress(), pdu.getAddressType(), pdu.getAddress().length());
// timestamp
writeTimeStampStringForDate(pdu.getTimestamp());
// discharge time(timestamp)
writeTimeStampStringForDate(pdu.getDischargeTime());
// status
writeByte(pdu.getStatus());
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -