📄 connection.java
字号:
/* * Java SMPP API * Copyright (C) 1998 - 2002 by Oran Kelly * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * A copy of the LGPL can be viewed at http://www.gnu.org/copyleft/lesser.html * Java SMPP API author: orank@users.sf.net * Java SMPP API Homepage: http://smppapi.sourceforge.net/ * $Id: Connection.java,v 1.18 2004/10/09 22:02:43 orank Exp $ */package ie.omk.smpp;import ie.omk.smpp.event.ConnectionObserver;import ie.omk.smpp.event.EventDispatcher;import ie.omk.smpp.event.ReceiverExceptionEvent;import ie.omk.smpp.event.ReceiverExitEvent;import ie.omk.smpp.event.ReceiverStartEvent;import ie.omk.smpp.event.SMPPEvent;import ie.omk.smpp.event.SimpleEventDispatcher;import ie.omk.smpp.message.Bind;import ie.omk.smpp.message.BindReceiver;import ie.omk.smpp.message.BindResp;import ie.omk.smpp.message.BindTransceiver;import ie.omk.smpp.message.BindTransmitter;import ie.omk.smpp.message.DeliverSM;import ie.omk.smpp.message.DeliverSMResp;import ie.omk.smpp.message.EnquireLink;import ie.omk.smpp.message.EnquireLinkResp;import ie.omk.smpp.message.InvalidParameterValueException;import ie.omk.smpp.message.SMPPPacket;import ie.omk.smpp.message.SMPPProtocolException;import ie.omk.smpp.message.SMPPRequest;import ie.omk.smpp.message.SMPPResponse;import ie.omk.smpp.message.Unbind;import ie.omk.smpp.message.UnbindResp;import ie.omk.smpp.message.tlv.Tag;import ie.omk.smpp.net.SmscLink;import ie.omk.smpp.net.TcpLink;import ie.omk.smpp.util.APIConfig;import ie.omk.smpp.util.AlphabetEncoding;import ie.omk.smpp.util.DefaultSequenceScheme;import ie.omk.smpp.util.PacketFactory;import ie.omk.smpp.util.PropertyNotFoundException;import ie.omk.smpp.util.SMPPIO;import ie.omk.smpp.util.SequenceNumberScheme;import ie.omk.smpp.version.SMPPVersion;import ie.omk.smpp.version.VersionException;import java.io.EOFException;import java.io.IOException;import java.net.SocketTimeoutException;import java.util.ArrayList;import java.util.Iterator;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** SMPP client connection (ESME). An SMPP Connection represents any kind of * connection to the SMSC, be it a transmitter, receiver or transceiver. It also * supports both synchronous and asynchronous modes of communication. * Synchronous mode is only useful for very simple applications that use * single-threading. Asynchronous mode is recommended for more complex * applications, especially those that will be running many threads. * <p><b>Important Note</b>: if you wish to use synchronous mode in a * multi-threaded environment, it is the <u>application's</u> responsiblity to * ensure there is only one thread executing a call to either or both of the * <code>sendRequest</code> and <code>readNextPacket</code> methods. If there * are concurrent calls to these methods executing, there is a strong * possibility of the incorrect packet being returned in a particular thread and * both the API and the application getting confused. These are the only methods * that contain such a race condition.</p> * @author Oran Kelly * @version 1.0 */public class Connection implements java.lang.Runnable{ /** Get the logger for this Connection. */ protected Log logger = LogFactory.getLog(Connection.class); /** SMPP Transmitter connection type. */ public static final int TRANSMITTER = 1; /** SMPP Receiver connection type. */ public static final int RECEIVER = 2; /** SMPP Transciever connection type. */ public static final int TRANSCEIVER = 3; /** Connection state: not bound to the SMSC. */ public static final int UNBOUND = 0; /** Connection state: waiting for successful acknowledgement to bind * request. */ public static final int BINDING = 1; /** Connection state: bound to the SMSC. */ public static final int BOUND = 2; /** Connection state: waiting for successful acknowledgement to unbind * request or waiting for application to respond to unbind request. */ public static final int UNBINDING = 3; /** Type of this SMPP connection. */ private int connectionType = 0; /** Packet listener thread for Asyncronous comms. */ private Thread rcvThread = null; /** Queue of incoming packets to deliver to application before reading from * the network. The queue is used only in syncrhonized mode. In the case * where an application has sent a request to the SMSC and is blocked * waiting a response and the SMSC initiates a request of it's own (an * unbind request or an enquire_link), the API will cache the request packet * and wait for the response to it's packet. Any other type of packet will * be added to the packetQueue and subsequent calls to * <code>readNextPacket</code> will clear this queue. */ private ArrayList packetQueue = null; /** Object used to notify observers of SMPP events. */ private EventDispatcher eventDispatcher = null; /** Byte buffer used in readNextPacketInternal. */ private byte[] buf = new byte[300]; /** Sequence numbering scheme to use for this connection. */ private SequenceNumberScheme seqNumScheme = new DefaultSequenceScheme(); /** The network link (virtual circuit) to the SMSC */ private SmscLink link = null; /** SMPP protocol version number. */ protected SMPPVersion interfaceVersion = SMPPVersion.getDefaultVersion(); /** Does the remote end support optional parameters? * According to the SMPPv3.4 specification, if the SMSC does not return * the sc_interface_version optional parameter in its bind response * packet, then we must assume it does not support optional parameters. */ protected boolean supportOptionalParams = true; /** Current state of the SMPP connection. * Possible states are UNBOUND, BINDING, BOUND and UNBINDING. */ private int state = UNBOUND; /** Specify whether the listener thread will automatically ack * enquire_link primitives received from the Smsc */ protected boolean ackQryLinks = true; /** Automatically acknowledge incoming deliver_sm messages. * Only valid for the Receiver */ protected boolean ackDeliverSm = false; /** Is the user using synchronous are async communication?. */ protected boolean asyncComms = false; /** The default alphabet to use for this connection. */ protected AlphabetEncoding defaultAlphabet = null; /** Initialise a new SMPP connection object. This is a convenience * constructor that will create a new {@link ie.omk.smpp.net.TcpLink} object * using the host name and port provided. The connection created will use * synchronous communications. * @param host the hostname of the SMSC. * @param port the port to connect to. If 0, use the default SMPP port * number. */ public Connection(String host, int port) throws java.net.UnknownHostException { this (new TcpLink(host, port), false); } /** Initialise a new SMPP connection object. This is a convenience * constructor that will create a new {@link ie.omk.smpp.net.TcpLink} object * using the host name and port provided. * @param host the hostname of the SMSC. * @param port the port to connect to. If 0, use the default SMPP port * number. * @param async true for asyncronous communication, false for synchronous. */ public Connection(String host, int port, boolean async) throws java.net.UnknownHostException { this (new TcpLink(host, port), async); } /** Initialise a new SMPP connection object. The connection will use * synchronous communications. * @param link The network link object to the Smsc (cannot be null) */ public Connection(SmscLink link) { this (link, false); } /** Initialise a new SMPP connection object, specifying the type of * communication desired. See the {@link Connection} class description for * some required knowledge on using the Connection in syncrhonous mode. * @param link The network link object to the Smsc (cannot be null) * @param async true for asyncronous communication, false for synchronous. */ public Connection(SmscLink link, boolean async) { this.link = link; this.asyncComms = async; if (asyncComms) { initAsyncComms(); } else { initSyncComms(); } } private void initAsyncComms() { String className = ""; try { className = APIConfig.getInstance().getProperty(APIConfig.EVENT_DISPATCHER_CLASS); if (className != null && !"".equals(className)) { Class cl = Class.forName(className); eventDispatcher = (EventDispatcher)cl.newInstance(); } else { logger.info("EventDispatcher property value is empty."); } } catch (PropertyNotFoundException x) { logger.debug("No event dispatcher specified in properties. Using default."); } catch (ClassNotFoundException x) { logger.error("Cannot locate event dispatcher class " + className, x); } catch (Exception x) { // Something wrong with the implementation. StringBuffer errorMessage = new StringBuffer(); errorMessage.append("Event dispatcher implementation is ") .append("incorrect.\n") .append(className) .append(" should implement ie.omk.smpp.event.EventDispatcher ") .append("and have a default constructor.\n") .append("Falling back to default implementation after ") .append("receiving exception."); logger.error(errorMessage.toString(), x); } finally { if (eventDispatcher == null) eventDispatcher = new SimpleEventDispatcher(); } // Initialise the event dispatcher eventDispatcher.init(); // Create the receiver daemon thread. createRecvThread(); } private void initSyncComms() { packetQueue = new ArrayList(); } /** Create the receiver thread if asynchronous communications is on, does * nothing otherwise. */ private void createRecvThread() { logger.info("Creating receiver thread"); rcvThread = new Thread(this, "ReceiverDaemon"); rcvThread.setDaemon(true); } /** Set the default alphabet of the SMSC this <code>Connection</code> is * communicating with. Each SMSC has its own default alphabet it uses. When * messages arrive and announce themselves with a data coding value of zero, * that means the message is encoded in the SMSC's default alphabet. The * smppapi assumes the GSM default alphabet as it's default alphabet. By * setting the default alphabet on the <code>Connection</code> all packets * returned by {@link #newInstance(int)} will use the Connection's default * alphabet plus any packets read from the wire with a data coding value of * zero will have their default alphabet initialised appropriately. * @param alphabet the alphabet to use as the default for this connection * (may be <code>null</code> in which case the API falls back to using its * own internal default). */ public void setDefaultAlphabet(AlphabetEncoding alphabet) { this.defaultAlphabet = alphabet; } /** Get the current alphabet this <code>Connection</code> is using as its * default. * @return the default alphabet for this <code>Connection</code>. */ public AlphabetEncoding getDefaultAlphabet() { return (defaultAlphabet); } /** Set the state of this ESME. * @see ie.omk.smpp.Connection#getState */ private synchronized void setState(int state) { logger.info("Setting state " + state); this.state = state; } /** Set the SMPP version this connection will use. Setting the version is * only a valid operation before the connection is bound. Any attempt to set * the version after binding to the SMSC will result in an exception being * thrown. * @param version the SMPP version to use. * @throws ie.omk.smpp.version.VersionException if an attempt is made to set * the version of the connection after binding to the SMSC. * @see ie.omk.smpp.version.SMPPVersion */ public void setVersion(SMPPVersion version) throws VersionException { if (getState() != UNBOUND) throw new VersionException("Cannot set SMPP version after binding"); if (version == null) this.interfaceVersion = SMPPVersion.getDefaultVersion(); else this.interfaceVersion = version; } /** Get the SMPP version in use by this connection. The version in use by * the connection <b>may</b> be different to that specified before the bind * operation as binding to the SMSC may result in an alternative SMPP * version being negotiated. For instance, if the client sends a bind packet * to the SMSC specifying that it supports SMPP version 3.4 but the SMSC * returns a bind_resp stating it supports version 3.3, the Connection * automatically sets it's internal version to use down to 3.3. */ public SMPPVersion getVersion() { return (interfaceVersion);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -