From ac22633f3d61e73cf048cdc7c57fff328eff1176 Mon Sep 17 00:00:00 2001 From: "amit.bhayani@gmail.com" Date: Sun, 9 Jun 2013 14:01:22 +0530 Subject: [PATCH] Fixed Issue #33 Add submit_multi request/response support --- .../com/cloudhopper/smpp/SmppConstants.java | 4 +- .../java/com/cloudhopper/smpp/pdu/BaseSm.java | 16 +- .../com/cloudhopper/smpp/pdu/SubmitMulti.java | 202 ++++++++++++++++++ .../cloudhopper/smpp/pdu/SubmitMultiResp.java | 119 +++++++++++ .../smpp/transcoder/DefaultPduTranscoder.java | 4 + .../cloudhopper/smpp/type/UnsucessfulSME.java | 90 ++++++++ .../smpp/transcoder/PduDecoderTest.java | 78 +++++++ .../smpp/transcoder/PduEncoderTest.java | 49 +++++ 8 files changed, 552 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/cloudhopper/smpp/pdu/SubmitMulti.java create mode 100644 src/main/java/com/cloudhopper/smpp/pdu/SubmitMultiResp.java create mode 100644 src/main/java/com/cloudhopper/smpp/type/UnsucessfulSME.java diff --git a/src/main/java/com/cloudhopper/smpp/SmppConstants.java b/src/main/java/com/cloudhopper/smpp/SmppConstants.java index c12e1512..be45f4fc 100644 --- a/src/main/java/com/cloudhopper/smpp/SmppConstants.java +++ b/src/main/java/com/cloudhopper/smpp/SmppConstants.java @@ -61,8 +61,8 @@ public class SmppConstants { // // SUBMIT_MULTI destination type flags // - //public static final int SME_ADDRESS = 1; - //public static final int DISTRIBUTION_LIST_NAME = 2; + public static final int SME_ADDRESS = 1; + public static final int DISTRIBUTION_LIST_NAME = 2; // // SMPP Command ID (Requests) diff --git a/src/main/java/com/cloudhopper/smpp/pdu/BaseSm.java b/src/main/java/com/cloudhopper/smpp/pdu/BaseSm.java index 1f73b51d..d46feb5b 100644 --- a/src/main/java/com/cloudhopper/smpp/pdu/BaseSm.java +++ b/src/main/java/com/cloudhopper/smpp/pdu/BaseSm.java @@ -44,15 +44,15 @@ public abstract class BaseSm extends PduRequest { protected Address sourceAddress; protected Address destAddress; protected byte esmClass; - private byte protocolId; // not present in data_sm - private byte priority; // not present in data_sm - private String scheduleDeliveryTime; // not present in data_sm - private String validityPeriod; // not present in data_sm + protected byte protocolId; // not present in data_sm + protected byte priority; // not present in data_sm + protected String scheduleDeliveryTime; // not present in data_sm + protected String validityPeriod; // not present in data_sm protected byte registeredDelivery; - private byte replaceIfPresent; // not present in data_sm + protected byte replaceIfPresent; // not present in data_sm protected byte dataCoding; - private byte defaultMsgId; // not present in data_sm, not used in deliver_sm - private byte[] shortMessage; // not present in data_sm + protected byte defaultMsgId; // not present in data_sm, not used in deliver_sm + protected byte[] shortMessage; // not present in data_sm public BaseSm(int commandId, String name) { super(commandId, name); @@ -243,4 +243,4 @@ public void appendBodyToString(StringBuilder buffer) { HexUtil.appendHexString(buffer, this.shortMessage); buffer.append("])"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/cloudhopper/smpp/pdu/SubmitMulti.java b/src/main/java/com/cloudhopper/smpp/pdu/SubmitMulti.java new file mode 100644 index 00000000..75f39a63 --- /dev/null +++ b/src/main/java/com/cloudhopper/smpp/pdu/SubmitMulti.java @@ -0,0 +1,202 @@ +/** + * + */ +package com.cloudhopper.smpp.pdu; + +/* + * #%L + * ch-smpp + * %% + * Copyright (C) 2009 - 2013 Cloudhopper by Twitter + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; +import java.util.List; + +import com.cloudhopper.smpp.SmppConstants; +import com.cloudhopper.smpp.type.Address; +import com.cloudhopper.smpp.type.RecoverablePduException; +import com.cloudhopper.smpp.type.SmppInvalidArgumentException; +import com.cloudhopper.smpp.type.UnrecoverablePduException; +import com.cloudhopper.smpp.util.ByteBufUtil; +import com.cloudhopper.smpp.util.PduUtil; + +/** + * @author Amit Bhayani + * + */ +public class SubmitMulti extends BaseSm { + + private int numberOfDest; + + private List
destAddresses = new ArrayList
(); + private List destDistributionList = new ArrayList(); + + /** + * @param commandId + * @param name + */ + public SubmitMulti() { + super(SmppConstants.CMD_ID_SUBMIT_MULTI, "submit_multi"); + } + + /* + * (non-Javadoc) + * + * @see com.cloudhopper.smpp.pdu.PduRequest#createResponse() + */ + @Override + public SubmitMultiResp createResponse() { + SubmitMultiResp resp = new SubmitMultiResp(); + resp.setSequenceNumber(this.getSequenceNumber()); + return resp; + } + + /* + * (non-Javadoc) + * + * @see com.cloudhopper.smpp.pdu.PduRequest#getResponseClass() + */ + @Override + public Class getResponseClass() { + return SubmitMultiResp.class; + } + + @Override + public Address getDestAddress() { + return null; + } + + @Override + public void setDestAddress(Address value) { + + } + + public void addDestAddresses(Address address) + throws SmppInvalidArgumentException { + this.numberOfDest++; + this.destAddresses.add(address); + } + + public void addDestDestributionListName(String name) { + this.numberOfDest++; + this.destDistributionList.add(name); + } + + public List
getDestAddresses() { + return this.destAddresses; + } + + public List getDestDestributionListName() { + return this.destDistributionList; + } + + public int getNumberOfDest(){ + return this.numberOfDest; + } + + @Override + public void readBody(ByteBuf buffer) throws UnrecoverablePduException, RecoverablePduException { + this.serviceType = ByteBufUtil.readNullTerminatedString(buffer); + this.sourceAddress = ByteBufUtil.readAddress(buffer); + + this.numberOfDest = buffer.readUnsignedByte(); + + for (int count = 0; count < this.numberOfDest; count++) { + byte flag = buffer.readByte(); + if (flag == SmppConstants.SME_ADDRESS) { + this.destAddresses.add(ByteBufUtil.readAddress(buffer)); + } else if (flag == SmppConstants.DISTRIBUTION_LIST_NAME) { + this.destDistributionList.add(ByteBufUtil.readNullTerminatedString(buffer)); + } + } + + this.esmClass = buffer.readByte(); + this.protocolId = buffer.readByte(); + this.priority = buffer.readByte(); + this.scheduleDeliveryTime = ByteBufUtil.readNullTerminatedString(buffer); + this.validityPeriod = ByteBufUtil.readNullTerminatedString(buffer); + this.registeredDelivery = buffer.readByte(); + this.replaceIfPresent = buffer.readByte(); + this.dataCoding = buffer.readByte(); + this.defaultMsgId = buffer.readByte(); + // this is always an unsigned version of the short message length + short shortMessageLength = buffer.readUnsignedByte(); + this.shortMessage = new byte[shortMessageLength]; + buffer.readBytes(this.shortMessage); + } + + @Override + public void writeBody(ByteBuf buffer) throws UnrecoverablePduException, RecoverablePduException { + ByteBufUtil.writeNullTerminatedString(buffer, this.serviceType); + ByteBufUtil.writeAddress(buffer, this.sourceAddress); + + buffer.writeByte(this.numberOfDest); + + for (Address adress : this.destAddresses) { + buffer.writeByte(SmppConstants.SME_ADDRESS); + ByteBufUtil.writeAddress(buffer, adress); + } + + for (String s : this.destDistributionList) { + buffer.writeByte(SmppConstants.DISTRIBUTION_LIST_NAME); + ByteBufUtil.writeNullTerminatedString(buffer, s); + + } + + buffer.writeByte(this.esmClass); + buffer.writeByte(this.protocolId); + buffer.writeByte(this.priority); + ByteBufUtil.writeNullTerminatedString(buffer, this.scheduleDeliveryTime); + ByteBufUtil.writeNullTerminatedString(buffer, this.validityPeriod); + buffer.writeByte(this.registeredDelivery); + buffer.writeByte(this.replaceIfPresent); + buffer.writeByte(this.dataCoding); + buffer.writeByte(this.defaultMsgId); + buffer.writeByte(getShortMessageLength()); + if (this.shortMessage != null) { + buffer.writeBytes(this.shortMessage); + } + } + + @Override + public int calculateByteSizeOfBody() { + int bodyLength = 0; + bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.serviceType); + bodyLength += PduUtil.calculateByteSizeOfAddress(this.sourceAddress); + + bodyLength +=1; //number_of_dests + + for(Address adress : this.destAddresses){ + bodyLength += 1;//Flag + bodyLength += PduUtil.calculateByteSizeOfAddress(adress); + } + + for(String s : this.destDistributionList){ + bodyLength += 1;//Flag + bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(s); + } + + bodyLength += 3; // esmClass, priority, protocolId + bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.scheduleDeliveryTime); + bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.validityPeriod); + bodyLength += 5; // regDelivery, replace, dataCoding, defaultMsgId, messageLength bytes + bodyLength += getShortMessageLength(); + return bodyLength; + } +} diff --git a/src/main/java/com/cloudhopper/smpp/pdu/SubmitMultiResp.java b/src/main/java/com/cloudhopper/smpp/pdu/SubmitMultiResp.java new file mode 100644 index 00000000..ef10d33e --- /dev/null +++ b/src/main/java/com/cloudhopper/smpp/pdu/SubmitMultiResp.java @@ -0,0 +1,119 @@ +/** + * + */ +package com.cloudhopper.smpp.pdu; + +/* + * #%L + * ch-smpp + * %% + * Copyright (C) 2009 - 2013 Cloudhopper by Twitter + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; +import java.util.List; + +import com.cloudhopper.smpp.SmppConstants; +import com.cloudhopper.smpp.type.Address; +import com.cloudhopper.smpp.type.RecoverablePduException; +import com.cloudhopper.smpp.type.SmppInvalidArgumentException; +import com.cloudhopper.smpp.type.UnrecoverablePduException; +import com.cloudhopper.smpp.type.UnsucessfulSME; +import com.cloudhopper.smpp.util.ByteBufUtil; +import com.cloudhopper.smpp.util.PduUtil; + +/** + * @author Amit Bhayani + * + */ +public class SubmitMultiResp extends BaseSmResp { + + private int numberOfUnsucessfulDest; + private List unsucessfulSmes = new ArrayList(); + + /** + * @param commandId + * @param name + */ + public SubmitMultiResp() { + super(SmppConstants.CMD_ID_SUBMIT_MULTI_RESP, "submit_multi_resp"); + } + + public void addUnsucessfulSME(UnsucessfulSME unsucessfulSME) + throws SmppInvalidArgumentException { + this.numberOfUnsucessfulDest++; + this.unsucessfulSmes.add(unsucessfulSME); + } + + public int getNumberOfUnsucessfulDest() { + return numberOfUnsucessfulDest; + } + + public List getUnsucessfulSmes() { + return unsucessfulSmes; + } + + @Override + public void readBody(ByteBuf buffer) + throws UnrecoverablePduException, RecoverablePduException { + super.readBody(buffer); + + this.numberOfUnsucessfulDest = buffer.readUnsignedByte(); + + for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { + Address address = ByteBufUtil.readAddress(buffer); + int errorStatusCode = buffer.readInt(); + + this.unsucessfulSmes.add(new UnsucessfulSME(errorStatusCode, + address)); + + } + } + + @Override + public int calculateByteSizeOfBody() { + int bodyLength = 0; + bodyLength = super.calculateByteSizeOfBody(); + + bodyLength += 1; // no_unsuccess + + for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { + UnsucessfulSME unsucessfulSME = this.unsucessfulSmes.get(count); + bodyLength += PduUtil.calculateByteSizeOfAddress(unsucessfulSME + .getAddress()); + bodyLength += 4; // error_status_code + } + + return bodyLength; + } + + @Override + public void writeBody(ByteBuf buffer) + throws UnrecoverablePduException, RecoverablePduException { + super.writeBody(buffer); + + buffer.writeByte(this.numberOfUnsucessfulDest); + + for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { + UnsucessfulSME unsucessfulSME = this.unsucessfulSmes.get(count); + ByteBufUtil.writeAddress(buffer, unsucessfulSME.getAddress()); + buffer.writeInt(unsucessfulSME.getErrorStatusCode()); + } + } + +} diff --git a/src/main/java/com/cloudhopper/smpp/transcoder/DefaultPduTranscoder.java b/src/main/java/com/cloudhopper/smpp/transcoder/DefaultPduTranscoder.java index 777c2d88..6023b0ad 100644 --- a/src/main/java/com/cloudhopper/smpp/transcoder/DefaultPduTranscoder.java +++ b/src/main/java/com/cloudhopper/smpp/transcoder/DefaultPduTranscoder.java @@ -164,6 +164,8 @@ protected Pdu doDecode(int commandLength, ByteBuf buffer) throws UnrecoverablePd pdu = new BindReceiver(); } else if (commandId == SmppConstants.CMD_ID_UNBIND) { pdu = new Unbind(); + } else if (commandId == SmppConstants.CMD_ID_SUBMIT_MULTI) { + pdu = new SubmitMulti(); } else { pdu = new PartialPdu(commandId); } @@ -190,6 +192,8 @@ protected Pdu doDecode(int commandLength, ByteBuf buffer) throws UnrecoverablePd pdu = new UnbindResp(); } else if (commandId == SmppConstants.CMD_ID_GENERIC_NACK) { pdu = new GenericNack(); + } else if (commandId == SmppConstants.CMD_ID_SUBMIT_MULTI_RESP) { + pdu = new SubmitMultiResp(); } else { pdu = new PartialPduResp(commandId); } diff --git a/src/main/java/com/cloudhopper/smpp/type/UnsucessfulSME.java b/src/main/java/com/cloudhopper/smpp/type/UnsucessfulSME.java new file mode 100644 index 00000000..6bcdad52 --- /dev/null +++ b/src/main/java/com/cloudhopper/smpp/type/UnsucessfulSME.java @@ -0,0 +1,90 @@ +/** + * + */ +package com.cloudhopper.smpp.type; + +import com.cloudhopper.smpp.util.ByteBufUtil; + +import io.netty.buffer.ByteBuf; + +/* + * #%L + * ch-smpp + * %% + * Copyright (C) 2009 - 2013 Cloudhopper by Twitter + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + + +/** + * @author Amit Bhayani + * + */ +public class UnsucessfulSME { + + private int errorStatusCode; + private Address address; + + /** + * + */ + public UnsucessfulSME() { + } + + public UnsucessfulSME(int errorStatusCode, Address address) { + super(); + this.errorStatusCode = errorStatusCode; + this.address = address; + } + + public int getErrorStatusCode() { + return errorStatusCode; + } + + public void setErrorStatusCode(int errorStatusCode) { + this.errorStatusCode = errorStatusCode; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public void read(ByteBuf buffer) throws UnrecoverablePduException, + RecoverablePduException { + this.address = ByteBufUtil.readAddress(buffer); + this.errorStatusCode = buffer.readInt(); + } + + public void write(ByteBuf buffer) throws UnrecoverablePduException, + RecoverablePduException { + ByteBufUtil.writeAddress(buffer, this.address); + buffer.writeInt(this.errorStatusCode); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(44); + buffer.append(this.address.toString()); + buffer.append(" errorStatusCode ["); + buffer.append(this.errorStatusCode); + buffer.append("]"); + return buffer.toString(); + } + +} diff --git a/src/test/java/com/cloudhopper/smpp/transcoder/PduDecoderTest.java b/src/test/java/com/cloudhopper/smpp/transcoder/PduDecoderTest.java index 017143fb..1a748461 100644 --- a/src/test/java/com/cloudhopper/smpp/transcoder/PduDecoderTest.java +++ b/src/test/java/com/cloudhopper/smpp/transcoder/PduDecoderTest.java @@ -22,15 +22,21 @@ // third party imports +import java.util.List; + import com.cloudhopper.commons.util.HexUtil; import com.cloudhopper.smpp.SmppConstants; import com.cloudhopper.smpp.pdu.*; import com.cloudhopper.smpp.tlv.Tlv; +import com.cloudhopper.smpp.type.Address; import com.cloudhopper.smpp.type.TerminatingNullByteNotFoundException; import com.cloudhopper.smpp.type.UnknownCommandIdException; import com.cloudhopper.smpp.type.UnrecoverablePduException; +import com.cloudhopper.smpp.type.UnsucessfulSME; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; + import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -772,6 +778,78 @@ public void decodeSubmitSm() throws Exception { // interesting -- this example has optional parameters it happened to skip... Assert.assertEquals(0, buffer.readableBytes()); } + + @Test + public void decodeSubmitMulti() throws Exception { + ByteBuf buffer = BufferHelper + .createBuffer("00000065000000210000000000000002434d5400010031363136000201010036323831373635303436353700010100363238313736353034363538000000010000020111001f636c6f7564686f707065722d736d70702073696d706c7920617765736f6d65"); + + SubmitMulti pdu0 = (SubmitMulti) transcoder.decode(buffer); + + Assert.assertEquals(101, pdu0.getCommandLength()); + Assert.assertEquals(SmppConstants.CMD_ID_SUBMIT_MULTI, pdu0.getCommandId()); + Assert.assertEquals(0, pdu0.getCommandStatus()); + Assert.assertEquals(2, pdu0.getSequenceNumber()); + Assert.assertEquals(true, pdu0.isRequest()); + Assert.assertEquals("CMT", pdu0.getServiceType()); + Assert.assertEquals(0x01, pdu0.getSourceAddress().getTon()); + Assert.assertEquals(0x00, pdu0.getSourceAddress().getNpi()); + Assert.assertEquals("1616", pdu0.getSourceAddress().getAddress()); + + Assert.assertEquals(2, pdu0.getNumberOfDest()); + + List
destAddresses = pdu0.getDestAddresses(); + + Address add1 = destAddresses.get(0); + + Assert.assertEquals(0x01, add1.getTon()); + Assert.assertEquals(0x00, add1.getNpi()); + Assert.assertEquals("628176504657", add1.getAddress()); + + Assert.assertEquals(0x00, pdu0.getEsmClass()); + Assert.assertEquals(0x00, pdu0.getProtocolId()); + Assert.assertEquals(0x01, pdu0.getPriority()); + Assert.assertEquals("", pdu0.getScheduleDeliveryTime()); + Assert.assertEquals("", pdu0.getValidityPeriod()); + Assert.assertEquals(0x02, pdu0.getRegisteredDelivery()); + Assert.assertEquals(0x01, pdu0.getReplaceIfPresent()); + Assert.assertEquals(0x11, pdu0.getDataCoding()); + Assert.assertEquals(0x00, pdu0.getDefaultMsgId()); + Assert.assertEquals(31, pdu0.getShortMessage().length); + Assert.assertArrayEquals(HexUtil.toByteArray("636c6f7564686f707065722d736d70702073696d706c7920617765736f6d65"), + pdu0.getShortMessage()); + + Assert.assertEquals(null, pdu0.getOptionalParameters()); + + // interesting -- this example has optional parameters it happened to + // skip... + Assert.assertEquals(0, buffer.readableBytes()); + } + + @Test + public void decodeSubmitMultiResp() throws Exception { + ByteBuf buffer = BufferHelper + .createBuffer("0000002d8000002100000000000000023363613761306364000101003632383137363530343635370000000004"); + + SubmitMultiResp pdu0 = (SubmitMultiResp) transcoder.decode(buffer); + + Assert.assertEquals(45, pdu0.getCommandLength()); + Assert.assertEquals(SmppConstants.CMD_ID_SUBMIT_MULTI_RESP, pdu0.getCommandId()); + Assert.assertEquals(0, pdu0.getCommandStatus()); + Assert.assertEquals(2, pdu0.getSequenceNumber()); + + Assert.assertEquals(1, pdu0.getNumberOfUnsucessfulDest()); + + List unsucessfulSmes = pdu0.getUnsucessfulSmes(); + UnsucessfulSME unsucessfulSME = unsucessfulSmes.get(0); + Address add1 = unsucessfulSME.getAddress(); + + Assert.assertEquals(0x01, add1.getTon()); + Assert.assertEquals(0x00, add1.getNpi()); + Assert.assertEquals("628176504657", add1.getAddress()); + + Assert.assertEquals(0x04, unsucessfulSME.getErrorStatusCode()); + } @Test public void decodeUnbind() throws Exception { diff --git a/src/test/java/com/cloudhopper/smpp/transcoder/PduEncoderTest.java b/src/test/java/com/cloudhopper/smpp/transcoder/PduEncoderTest.java index 9e22c40e..d75b264a 100644 --- a/src/test/java/com/cloudhopper/smpp/transcoder/PduEncoderTest.java +++ b/src/test/java/com/cloudhopper/smpp/transcoder/PduEncoderTest.java @@ -28,7 +28,10 @@ import com.cloudhopper.smpp.tlv.Tlv; import com.cloudhopper.smpp.type.Address; import com.cloudhopper.smpp.type.SmppInvalidArgumentException; +import com.cloudhopper.smpp.type.UnsucessfulSME; + import io.netty.buffer.ByteBuf; + import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; @@ -316,6 +319,52 @@ public void encodeSubmitSm() throws Exception { //logger.debug("{}", HexUtil.toHexString(BufferHelper.createByteArray(buffer))); Assert.assertArrayEquals(HexUtil.toByteArray("00000039000000040000000000004FE80001013430343034000101343439353133363139323000000000000001000000084024232125262F3A"), BufferHelper.createByteArray(buffer)); } + + @Test + public void encodeSubmitMulti() throws Exception { + SubmitMulti pdu0 = new SubmitMulti(); + + pdu0.setSequenceNumber(2); + pdu0.setServiceType("CMT"); + + pdu0.setSourceAddress(new Address((byte)0x01, (byte)0x00, "1616")); + + pdu0.addDestAddresses(new Address((byte)0x01, (byte)0x00, "628176504657")); + pdu0.addDestAddresses(new Address((byte)0x01, (byte)0x00, "628176504658")); + + pdu0.setEsmClass((byte)0x00); + pdu0.setProtocolId((byte)0x00); + pdu0.setPriority((byte)0x01); + pdu0.setScheduleDeliveryTime(null); + pdu0.setValidityPeriod(null); + pdu0.setRegisteredDelivery((byte)0x02); + pdu0.setReplaceIfPresent((byte)0x01); + pdu0.setDataCoding((byte)0x11); + pdu0.setDefaultMsgId((byte)0x00); + pdu0.setShortMessage(HexUtil.toByteArray("636c6f7564686f707065722d736d70702073696d706c7920617765736f6d65")); + + ByteBuf buffer = transcoder.encode(pdu0); + //logger.debug("{}", HexUtil.toHexString(BufferHelper.createByteArray(buffer))); + Assert.assertArrayEquals(HexUtil.toByteArray("00000065000000210000000000000002434d5400010031363136000201010036323831373635303436353700010100363238313736353034363538000000010000020111001f636c6f7564686f707065722d736d70702073696d706c7920617765736f6d65"), BufferHelper.createByteArray(buffer)); + } + + + @Test + public void encodeSubmitMultiResp() throws Exception { + SubmitMultiResp pdu0 = new SubmitMultiResp(); + pdu0.setCommandStatus(0); + pdu0.setSequenceNumber(2); + pdu0.setMessageId("6802c438"); + + Address address = new Address((byte)0x01, (byte)0x00, "628176504657"); + UnsucessfulSME unsucessfulSME = new UnsucessfulSME(4, address); + + pdu0.addUnsucessfulSME(unsucessfulSME); + + ByteBuf buffer = transcoder.encode(pdu0); + Assert.assertArrayEquals(HexUtil.toByteArray("0000002d8000002100000000000000023638303263343338000101003632383137363530343635370000000004"), BufferHelper.createByteArray(buffer)); + + } @Test public void encodeUnbind() throws Exception {