📄 smppsession.java
字号:
/*
* 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.
*
*/
package org.jsmpp.session;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jsmpp.DefaultPDUReader;
import org.jsmpp.DefaultPDUSender;
import org.jsmpp.InvalidCommandLengthException;
import org.jsmpp.InvalidResponseException;
import org.jsmpp.PDUException;
import org.jsmpp.PDUReader;
import org.jsmpp.PDUSender;
import org.jsmpp.PDUStringException;
import org.jsmpp.SMPPConstant;
import org.jsmpp.SynchronizedPDUSender;
import org.jsmpp.bean.Address;
import org.jsmpp.bean.AlertNotification;
import org.jsmpp.bean.BindResp;
import org.jsmpp.bean.BindType;
import org.jsmpp.bean.Command;
import org.jsmpp.bean.DataCoding;
import org.jsmpp.bean.DataSm;
import org.jsmpp.bean.DeliverSm;
import org.jsmpp.bean.ESMClass;
import org.jsmpp.bean.InterfaceVersion;
import org.jsmpp.bean.NumberingPlanIndicator;
import org.jsmpp.bean.OptionalParameter;
import org.jsmpp.bean.QuerySmResp;
import org.jsmpp.bean.RegisteredDelivery;
import org.jsmpp.bean.ReplaceIfPresentFlag;
import org.jsmpp.bean.SubmitMultiResp;
import org.jsmpp.bean.SubmitMultiResult;
import org.jsmpp.bean.SubmitSmResp;
import org.jsmpp.bean.TypeOfNumber;
import org.jsmpp.extra.NegativeResponseException;
import org.jsmpp.extra.PendingResponse;
import org.jsmpp.extra.ProcessRequestException;
import org.jsmpp.extra.ResponseTimeoutException;
import org.jsmpp.extra.SessionState;
import org.jsmpp.session.connection.Connection;
import org.jsmpp.session.connection.ConnectionFactory;
import org.jsmpp.session.connection.socket.SocketConnectionFactory;
import org.jsmpp.util.DefaultComposer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is an object that used to communicate with SMPP Server or SMSC. It hide
* all un-needed SMPP operation that might harm if the user code use it such as :
* <ul>
* <li>DELIVER_SM_RESP, should be called only as response to DELIVER_SM</li>
* <li>UNBIND_RESP, should be called only as response to UNBIND_RESP</li>
* <li>DATA_SM_RESP, should be called only as response to DATA_SM</li>
* <li>ENQUIRE_LINK_RESP, should be called only as response to ENQUIRE_LINK</li>
* <li>GENERIC_NACK, should be called only as response to GENERIC_NACK</li>
* </ul>
*
* All SMPP operation (request-response) is blocking, for an example: SUBMIT_SM
* will be blocked until SUBMIT_SM_RESP received or timeout. This looks like
* synchronous communication, but the {@link SMPPClient} implementation give
* ability to the asynchronous way by executing the SUBMIT_SM operation parallel
* on a different thread. The very simple implementation by using Thread pool,
* {@link ExecutorService} will do.
*
* To receive the incoming message such as DELIVER_SM or DATA_SM will be managed
* by internal thread. User code only have to set listener
* {@link MessageReceiverListener}.
*
* @author uudashr
*
*/
public class SMPPSession extends AbstractSession implements ClientSession {
private static final Logger logger = LoggerFactory.getLogger(SMPPSession.class);
/* Utility */
private final PDUReader pduReader;
/* Connection */
private final ConnectionFactory connFactory;
private Connection conn;
private DataInputStream in;
private OutputStream out;
private final ResponseHandler responseHandler = new ResponseHandlerImpl();
private MessageReceiverListener messageReceiverListener;
private BoundSessionStateListener sessionStateListener = new BoundSessionStateListener();
private SMPPSessionContext sessionContext = new SMPPSessionContext(this, sessionStateListener);
private EnquireLinkSender enquireLinkSender;
/**
* Default constructor of {@link SMPPSession}. The next action might be
* connect and bind to a destination message center.
*
* @see #connectAndBind(String, int, BindType, String, String, String, TypeOfNumber, NumberingPlanIndicator, String)
*/
public SMPPSession() {
this(new SynchronizedPDUSender(new DefaultPDUSender(new DefaultComposer())),
new DefaultPDUReader(),
SocketConnectionFactory.getInstance());
}
public SMPPSession(PDUSender pduSender, PDUReader pduReader,
ConnectionFactory connFactory) {
super(pduSender);
this.pduReader = pduReader;
this.connFactory = connFactory;
addSessionStateListener(new BoundSessionStateListener());
}
public SMPPSession(String host, int port, BindParameter bindParam,
PDUSender pduSender, PDUReader pduReader,
ConnectionFactory connFactory) throws IOException {
this(pduSender, pduReader, connFactory);
connectAndBind(host, port, bindParam);
}
public SMPPSession(String host, int port, BindParameter bindParam) throws IOException {
this();
connectAndBind(host, port, bindParam);
}
/**
* Open connection and bind immediately.
*
* @param host is the SMSC host address.
* @param port is the SMSC listen port.
* @param bindType is the bind type.
* @param systemId is the system id.
* @param password is the password.
* @param systemType is the system type.
* @param addrTon is the address TON.
* @param addrNpi is the address NPI.
* @param addressRange is the address range.
* @throws IOException if there is an IO error found.
*/
public void connectAndBind(String host, int port, BindType bindType,
String systemId, String password, String systemType,
TypeOfNumber addrTon, NumberingPlanIndicator addrNpi,
String addressRange) throws IOException {
connectAndBind(host, port, new BindParameter(bindType, systemId,
password, systemType, addrTon, addrNpi, addressRange), 60000);
}
/**
* Open connection and bind immediately with specified timeout. The default
* timeout is 1 minutes.
*
* @param host is the SMSC host address.
* @param port is the SMSC listen port.
* @param bindType is the bind type.
* @param systemId is the system id.
* @param password is the password.
* @param systemType is the system type.
* @param addrTon is the address TON.
* @param addrNpi is the address NPI.
* @param addressRange is the address range.
* @param timeout is the timeout.
* @throws IOException if there is an IO error found.
*/
public void connectAndBind(String host, int port, BindType bindType,
String systemId, String password, String systemType,
TypeOfNumber addrTon, NumberingPlanIndicator addrNpi,
String addressRange, long timeout) throws IOException {
connectAndBind(host, port, new BindParameter(bindType, systemId,
password, systemType, addrTon, addrNpi, addressRange), timeout);
}
/**
* Open connection and bind immediately.
*
* @param host is the SMSC host address.
* @param port is the SMSC listen port.
* @param bindParam is the bind parameters.
* @return the SMSC system id.
* @throws IOException if there is an IO error found.
*/
public String connectAndBind(String host, int port,
BindParameter bindParam)
throws IOException {
return connectAndBind(host, port, bindParam, 60000);
}
/**
* Open connection and bind immediately.
*
* @param host is the SMSC host address.
* @param port is the SMSC listen port.
* @param bindParam is the bind parameters.
* @param timeout is the timeout.
* @return the SMSC system id.
* @throws IOException if there is an IO error found.
*/
public String connectAndBind(String host, int port,
BindParameter bindParam, long timeout)
throws IOException {
logger.debug("Connect and bind to {} port {}", host, port);
if (sequence().currentValue() != 1) {
throw new IOException("Failed connecting");
}
conn = connFactory.createConnection(host, port);
logger.info("Connected");
sessionContext.open();
try {
in = new DataInputStream(conn.getInputStream());
out = conn.getOutputStream();
new PDUReaderWorker().start();
String smscSystemId = sendBind(bindParam.getBindType(), bindParam.getSystemId(), bindParam.getPassword(), bindParam.getSystemType(),
InterfaceVersion.IF_34, bindParam.getAddrTon(), bindParam.getAddrNpi(), bindParam.getAddressRange(), timeout);
sessionContext.bound(bindParam.getBindType());
enquireLinkSender = new EnquireLinkSender();
enquireLinkSender.start();
return smscSystemId;
} catch (PDUException e) {
logger.error("Failed sending bind command", e);
throw new IOException("Failed sending bind since some string parameter area invalid : " + e.getMessage());
} catch (NegativeResponseException e) {
String message = "Receive negative bind response";
logger.error(message, e);
close();
throw new IOException(message + ": " + e.getMessage());
} catch (InvalidResponseException e) {
String message = "Receive invalid response of bind";
logger.error(message, e);
close();
throw new IOException(message + ": " + e.getMessage());
} catch (ResponseTimeoutException e) {
String message = "Waiting bind response take time to long";
logger.error(message, e);
close();
throw new IOException(message + ": " + e.getMessage());
} catch (IOException e) {
logger.error("IO Error occur", e);
close();
throw e;
}
}
/**
* Sending bind.
*
* @param bindType is the bind type.
* @param systemId is the system id.
* @param password is the password.
* @param systemTypeis the system type.
* @param interfaceVersion is the interface version.
* @param addrTon is the address TON.
* @param addrNpi is the address NPI.
* @param addressRange is the address range.
* @param timeout is the max time waiting for bind response.
* @return SMSC system id.
* @throws PDUException if we enter invalid bind parameter(s).
* @throws ResponseTimeoutException if there is no valid response after defined millisecond.
* @throws InvalidResponseException if there is invalid response found.
* @throws NegativeResponseException if we receive negative response.
* @throws IOException if there is an IO error occur.
*/
private String sendBind(BindType bindType, String systemId,
String password, String systemType,
InterfaceVersion interfaceVersion, TypeOfNumber addrTon,
NumberingPlanIndicator addrNpi, String addressRange, long timeout)
throws PDUException, ResponseTimeoutException,
InvalidResponseException, NegativeResponseException, IOException {
BindCommandTask task = new BindCommandTask(pduSender(), bindType,
systemId, password, systemType, interfaceVersion, addrTon,
addrNpi, addressRange);
BindResp resp = (BindResp)executeSendCommand(task, timeout);
return resp.getSystemId();
}
/* (non-Javadoc)
* @see org.jsmpp.session.ClientSession#submitShortMessage(java.lang.String, org.jsmpp.bean.TypeOfNumber, org.jsmpp.bean.NumberingPlanIndicator, java.lang.String, org.jsmpp.bean.TypeOfNumber, org.jsmpp.bean.NumberingPlanIndicator, java.lang.String, org.jsmpp.bean.ESMClass, byte, byte, java.lang.String, java.lang.String, org.jsmpp.bean.RegisteredDelivery, byte, org.jsmpp.bean.DataCoding, byte, byte[], org.jsmpp.bean.OptionalParameter[])
*/
public String submitShortMessage(String serviceType,
TypeOfNumber sourceAddrTon, NumberingPlanIndicator sourceAddrNpi,
String sourceAddr, TypeOfNumber destAddrTon,
NumberingPlanIndicator destAddrNpi, String destinationAddr,
ESMClass esmClass, byte protocolId, byte priorityFlag,
String scheduleDeliveryTime, String validityPeriod,
RegisteredDelivery registeredDelivery, byte replaceIfPresentFlag,
DataCoding dataCoding, byte smDefaultMsgId, byte[] shortMessage,
OptionalParameter... optionalParameters) throws PDUException,
ResponseTimeoutException, InvalidResponseException,
NegativeResponseException, IOException {
SubmitSmCommandTask submitSmTask = new SubmitSmCommandTask(
pduSender(), serviceType, sourceAddrTon, sourceAddrNpi,
sourceAddr, destAddrTon, destAddrNpi, destinationAddr,
esmClass, protocolId, priorityFlag, scheduleDeliveryTime,
validityPeriod, registeredDelivery, replaceIfPresentFlag,
dataCoding, smDefaultMsgId, shortMessage, optionalParameters);
SubmitSmResp resp = (SubmitSmResp)executeSendCommand(submitSmTask, getTransactionTimer());
return resp.getMessageId();
}
/* (non-Javadoc)
* @see org.jsmpp.session.ClientSession#submitMultiple(java.lang.String, org.jsmpp.bean.TypeOfNumber, org.jsmpp.bean.NumberingPlanIndicator, java.lang.String, org.jsmpp.bean.Address[], org.jsmpp.bean.ESMClass, byte, byte, java.lang.String, java.lang.String, org.jsmpp.bean.RegisteredDelivery, org.jsmpp.bean.ReplaceIfPresentFlag, org.jsmpp.bean.DataCoding, byte, byte[], org.jsmpp.bean.OptionalParameter[])
*/
public SubmitMultiResult submitMultiple(String serviceType,
TypeOfNumber sourceAddrTon, NumberingPlanIndicator sourceAddrNpi,
String sourceAddr, Address[] destinationAddresses,
ESMClass esmClass, byte protocolId, byte priorityFlag,
String scheduleDeliveryTime, String validityPeriod,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -