/*
* TeleStax, Open Source Cloud Communications Copyright 2012.
* TeleStax and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.smsc.tools.smppsimulator;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.mobicents.protocols.ss7.map.api.smstpdu.DataCodingScheme;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharset;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetDecoder;
import org.mobicents.protocols.ss7.map.datacoding.GSMCharsetDecodingData;
import org.mobicents.protocols.ss7.map.datacoding.Gsm7EncodingStyle;
import org.mobicents.protocols.ss7.map.smstpdu.DataCodingSchemeImpl;
import org.mobicents.smsc.library.ErrorCode;
import org.mobicents.smsc.library.MessageUtil;
import org.mobicents.smsc.tools.smppsimulator.SmppSimulatorParameters.DeliveryResponseGenerating;
import com.cloudhopper.commons.util.windowing.WindowFuture;
import com.cloudhopper.smpp.PduAsyncResponse;
import com.cloudhopper.smpp.SmppConstants;
import com.cloudhopper.smpp.impl.DefaultSmppSessionHandler;
import com.cloudhopper.smpp.pdu.BaseSm;
import com.cloudhopper.smpp.pdu.BaseSmResp;
import com.cloudhopper.smpp.pdu.DeliverSm;
import com.cloudhopper.smpp.pdu.PduRequest;
import com.cloudhopper.smpp.pdu.PduResponse;
import com.cloudhopper.smpp.tlv.Tlv;
import com.cloudhopper.smpp.type.Address;
import com.cloudhopper.smpp.type.RecoverablePduException;
import com.cloudhopper.smpp.type.UnrecoverablePduException;
/**
*
* @author sergey vetyutnev
*
*/
public class ClientSmppSessionHandler extends DefaultSmppSessionHandler {
private SmppTestingForm testingForm;
private static Charset utf8Charset = Charset.forName("UTF-8");
private static Charset ucs2Charset = Charset.forName("UTF-16BE");
private static Charset isoCharset = Charset.forName("ISO-8859-1");
private static Charset gsm7Charset = new GSMCharset("GSM", new String[] {});
public ClientSmppSessionHandler(SmppTestingForm testingForm) {
this.testingForm = testingForm;
}
@Override
public void fireChannelUnexpectedlyClosed() {
testingForm.addMessage("ChannelUnexpectedlyClosed", "SMPP channel unexpectedly closed by a peer or by TCP connection dropped");
testingForm.doStop();
}
// private int incMsgCnt = 0;
@Override
public PduResponse firePduRequestReceived(PduRequest pduRequest) {
// incMsgCnt++;
// if (incMsgCnt > 150) {
// incMsgCnt = 0;
// try {
// Thread.sleep(60000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
testingForm.addMessage("PduRequestReceived: " + pduRequest.getName(), pduRequest.toString());
this.testingForm.messagesRcvd.incrementAndGet();
PduResponse resp = pduRequest.createResponse();
// here we can insert responses
if (pduRequest.getCommandId() == SmppConstants.CMD_ID_DELIVER_SM || pduRequest.getCommandId() == SmppConstants.CMD_ID_DATA_SM
|| pduRequest.getCommandId() == SmppConstants.CMD_ID_SUBMIT_SM) {
if (pduRequest instanceof BaseSm) {
BaseSm dev = (BaseSm) pduRequest;
byte[] data = dev.getShortMessage();
if (dev.getShortMessageLength() == 0) {
// Probably the message_payload Optional Parameter is being used
Tlv messagePaylod = dev.getOptionalParameter(SmppConstants.TAG_MESSAGE_PAYLOAD);
if (messagePaylod != null) {
data = messagePaylod.getValue();
}
}
DataCodingScheme dcs = new DataCodingSchemeImpl(dev.getDataCoding());
boolean udhPresent = (dev.getEsmClass() & SmppConstants.ESM_CLASS_UDHI_MASK) != 0;
byte[] textPart = data;
byte[] udhData = null;
if (udhPresent && data.length > 2) {
// UDH exists
int udhLen = (data[0] & 0xFF) + 1;
if (udhLen <= data.length) {
textPart = new byte[textPart.length - udhLen];
udhData = new byte[udhLen];
System.arraycopy(data, udhLen, textPart, 0, textPart.length);
System.arraycopy(data, 0, udhData, 0, udhLen);
}
}
String s = null;
switch (dcs.getCharacterSet()) {
case GSM7:
case UCS2:
if (this.testingForm.getSmppSimulatorParameters().getSmppEncoding() == 0) {
s = new String(textPart, utf8Charset);
} else if (this.testingForm.getSmppSimulatorParameters().getSmppEncoding() == 1) {
s = new String(textPart, ucs2Charset);
} else {
GSMCharsetDecoder decoder = (GSMCharsetDecoder) gsm7Charset.newDecoder();
decoder.setGSMCharsetDecodingData(new GSMCharsetDecodingData(Gsm7EncodingStyle.bit8_smpp_style,
Integer.MAX_VALUE, 0));
ByteBuffer bb = ByteBuffer.wrap(textPart);
CharBuffer bf = null;
try {
bf = decoder.decode(bb);
} catch (CharacterCodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
s = bf.toString();
}
break;
case GSM8:
s = new String(textPart, isoCharset);
break;
}
String s2 = "";
if (udhData != null) {
StringBuilder sb = new StringBuilder();
sb.append("[");
int i2 = 0;
for (byte b : udhData) {
int i1 = (b & 0xFF);
if (i2 == 0)
i2 = 1;
else
sb.append(", ");
sb.append(i1);
}
sb.append("] ");
s2 = sb.toString();
}
testingForm.addMessage("TextReceived: ", s2 + s);
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
if (this.testingForm.getSmppSimulatorParameters().isRejectIncomingDeliveryMessage()) {
resp.setCommandStatus(1);
}
long mId = this.testingForm.getMsgIdGenerator().incrementAndGet();
String msgId;
String msgId2;
String msgId3;
if (this.testingForm.getSmppSimulatorParameters().isIdResponseTlv()) {
msgId = String.format("%08X", mId);
msgId2 = MessageUtil.createMessageIdString(mId);
msgId3 = msgId;
if (this.testingForm.getSmppSimulatorParameters().isWrongMessageIdInDlr())
msgId3 = msgId3 + "XYZ";
} else {
msgId = MessageUtil.createMessageIdString(mId);
msgId2 = MessageUtil.createMessageIdString(mId);
if (this.testingForm.getSmppSimulatorParameters().isWrongMessageIdInDlr())
msgId2 = msgId2 + "XYZ";
msgId3 = null;
}
((BaseSmResp) resp).setMessageId(msgId);
// scheduling of delivery receipt if needed
if (this.testingForm.getSmppSimulatorParameters().getDeliveryResponseGenerating() != DeliveryResponseGenerating.No) {
int delay = 100;
if (this.testingForm.getSmppSimulatorParameters().isDeliveryResponseAfter2Min())
delay = 2 * 60 * 1000;
this.testingForm.getExecutor().schedule(
new DeliveryReceiptSender(
this.testingForm.getSmppSimulatorParameters().getDeliveryResponseGenerating(), new Date(),
msgId2, msgId3), delay, TimeUnit.MILLISECONDS);
}
testingForm.addMessage("PduResponseSent: " + resp.getName(), resp.toString());
}
return resp;
}
@Override
public void firePduRequestExpired(PduRequest pduRequest) {
testingForm.addMessage("PduRequestExpired: " + pduRequest.getName(), pduRequest.toString());
}
@Override
public void fireExpectedPduResponseReceived(PduAsyncResponse pduAsyncResponse) {
this.testingForm.responsesRcvd.incrementAndGet();
if (this.testingForm.timer == null) {
testingForm.addMessage("Response=" + pduAsyncResponse.getResponse().getName(), "Req: " + pduAsyncResponse.getRequest().toString() + "\nResp: "
+ pduAsyncResponse.getResponse().toString());
}
}
@Override
public void fireUnexpectedPduResponseReceived(PduResponse pduResponse) {
testingForm.addMessage("UnexpectedPduResponseReceived: " + pduResponse.getName(), pduResponse.toString());
}
@Override
public void fireUnrecoverablePduException(UnrecoverablePduException e) {
testingForm.addMessage("UnrecoverablePduException", e.toString());
testingForm.doStop();
}
@Override
public void fireRecoverablePduException(RecoverablePduException e) {
testingForm.addMessage("RecoverablePduException", e.toString());
}
@Override
public void fireUnknownThrowable(Throwable t) {
if (t instanceof ClosedChannelException) {
testingForm.addMessage("UnknownThrowable",
"Unknown throwable received, but it was a ClosedChannelException, calling fireChannelUnexpectedlyClosed instead");
fireChannelUnexpectedlyClosed();
} else {
testingForm.addMessage("UnknownThrowable", t.toString());
testingForm.doStop();
}
}
// @Override
// public String lookupResultMessage(int commandStatus) {
// return null;
// }
//
// @Override
// public String lookupTlvTagName(short tag) {
// return null;
// }
public class DeliveryReceiptSender implements Runnable {
private DeliveryResponseGenerating deliveryResponseGenerating;
private Date submitDate;
private String messageId;
private String messageIdTlv;
public DeliveryReceiptSender(DeliveryResponseGenerating deliveryResponseGenerating, Date submitDate, String messageId,
String messageIdTlv) {
this.deliveryResponseGenerating = deliveryResponseGenerating;
this.submitDate = submitDate;
this.messageId = messageId;
this.messageIdTlv = messageIdTlv;
}
@Override
public void run() {
SmppSimulatorParameters param = testingForm.getSmppSimulatorParameters();
BaseSm pdu;
// switch(param.getSendingMessageType()){
// case SubmitSm:
// SubmitSm submitPdu = new SubmitSm();
// pdu = submitPdu;
// break;
// case DataSm:
// DataSm dataPdu = new DataSm();
// pdu = dataPdu;
// break;
// case DeliverSm:
// DeliverSm deliverPdu = new DeliverSm();
// pdu = deliverPdu;
// break;
// case SubmitMulti:
// SubmitMulti submitMulti = new SubmitMulti();
// pdu = submitMulti;
// break;
// default:
// return;
// }
DeliverSm deliverPdu = new DeliverSm();
pdu = deliverPdu;
pdu.setSourceAddress(new Address((byte) param.getSourceTON().getCode(), (byte) param.getSourceNPI().getCode(),
param.getSourceAddress()));
pdu.setDestAddress(new Address(pdu.getSourceAddress().getTon(), pdu.getSourceAddress().getNpi(), pdu
.getSourceAddress().getAddress()));
pdu.setEsmClass((byte) (0x04 + 1)); // delivery receipt + datagramm mode
pdu.setDataCoding((byte) 0);
pdu.setRegisteredDelivery((byte) 0);
boolean tempFailure = false;
boolean delivered = true;
ErrorCode errorCode = ErrorCode.SUCCESS;
if (deliveryResponseGenerating == DeliveryResponseGenerating.Error8) {
delivered = false;
errorCode = ErrorCode.ABSENT_SUBSCRIBER;
}
String rcpt = MessageUtil.createDeliveryReceiptMessage(messageId, submitDate, new Date(), errorCode.getCode(), "origMsgText",
delivered, null, tempFailure);
byte[] buf = rcpt.getBytes(utf8Charset);
if (messageIdTlv != null) {
byte[] data0 = messageIdTlv.getBytes();
byte[] data = new byte[data0.length + 1];
System.arraycopy(data0, 0, data, 0, data0.length);
Tlv tlv = new Tlv(SmppConstants.TAG_RECEIPTED_MSG_ID, data, "rec_msg_id");
pdu.addOptionalParameter(tlv);
}
try {
pdu.setShortMessage(buf);
testingForm.addMessage("Adding receipt=" + pdu.getName(), pdu.toString() + " Text:" + rcpt);
WindowFuture<Integer, PduRequest, PduResponse> future0 = testingForm.getSession().sendRequestPdu(pdu, 10000,
false);
} catch (Exception e) {
}
}
}
}