📄 connection.java
字号:
} /** Get the current state of the ESME. One of UNBOUND, BINDING, BOUND or * UNBINDING. */ public synchronized int getState() { return (this.state); } /** Method to open the link to the SMSC. This method will connect the * underlying SmscLink object if necessary and reset the sequence numbering * scheme to the beginning. * @throws java.io.IOException if an i/o error occurs while opening the * connection. */ protected void openLink() throws java.io.IOException { if (!this.link.isConnected()) { logger.info("Opening network link."); this.link.open(); if (this.seqNumScheme != null) this.seqNumScheme.reset(); } else { logger.debug("openLink called, link already open"); } } /** Close the underlying network link to the SMSC. This method calls the * underlying link's <code>close</code> method to actually shutdown * the network connection to the SMSC. * @throws ie.omk.smpp.IllegalStateException if an attempt is made to close * the connection while bound to the SMSC. * @throws java.io.IOException if an I/O exception occurs while trying to * close the link. * @see ie.omk.smpp.net.SmscLink#close */ public void closeLink() throws IOException { if (getState() != UNBOUND) throw new IllegalStateException("Cannot close the link while bound to the SMSC"); if (this.link.isConnected()) { logger.info("Shutting down the network link"); this.link.close(); } else { logger.debug("closeLink called on an unopen connection"); } } /** Get the interface version. * @see #setInterfaceVersion(SMPPVersion) */ public SMPPVersion getInterfaceVersion() { return (this.interfaceVersion); } /** Set the desired interface version for this connection. The default * version is 3.4. The bind operation may negotiate an eariler version of * the protocol if the SC does not understand the version sent by the ESME. * This API will not support any version eariler than SMPP v3.3. The * interface version is encoded as follows: * <table border="1" cellspacing="1" cellpadding="1"> * <tr><th>SMPP version</th><th>Version value</th></tr> * <tr><td>v3.4</td><td>0x34</td></tr> * <tr><td>v3.3</td><td>0x33</td></tr> * <tr> * <td colspan="2" align="center"><i>All other values reserved.</i></td> * </tr> * </table> */ public void setInterfaceVersion(SMPPVersion interfaceVersion) { logger.info("setInterfaceVersion " + interfaceVersion); this.interfaceVersion = interfaceVersion; this.supportOptionalParams = interfaceVersion.isSupportOptionalParams(); } /** Set the behaviour of automatically acking ENQUIRE_LINK's from the SMSC. * By default, the listener thread will automatically ack an enquire_link * message from the Smsc so as not to lose the connection. This * can be turned off with this method. * @param b true to activate automatic acknowledgment, false to disable */ public void autoAckLink(boolean b) { this.ackQryLinks = b; } /** Set the behaviour of automatically acking Deliver_Sm's from the Smsc. * By default the listener thread will <b>not</b> acknowledge a message. * @param b true to activate this function, false to deactivate. */ public void autoAckMessages(boolean b) { this.ackDeliverSm = b; } /** Check is this connection automatically acking Enquire link requests. */ public boolean isAckingLinks() { return (ackQryLinks); } /** Check is this connection automatically acking delivered messages */ public boolean isAckingMessages() { return (ackDeliverSm); } /** Acknowledge a DeliverSM command received from the Smsc. * @param rq The deliver_sm request to respond to. * @throws java.io.IOException If an I/O error occurs writing the response * packet to the network connection. */ public void ackDeliverSm(DeliverSM rq) throws java.io.IOException { DeliverSMResp rsp = new DeliverSMResp(rq); sendResponse(rsp); logger.info("deliver_sm_resp sent."); } /** Send an smpp request to the SMSC. * No fields in the SMPPRequest packet will be altered except possibly the * sequence number. The sequence number will be assigned the next number as * defined by this Connection's sequence numbering scheme. If the sequence * numbering scheme class is <code>null</code> for this Connection, no * number will be assigned. By default, the * {@link ie.omk.smpp.util.DefaultSequenceScheme} class is used to assign * sequence numbers to packets.<br /> * <b>IMPORTANT</b>: You <i>must</i> use the <code>bind</code> and * <code>unbind</code> methods to carry out those operations. Attempting * to send an bind or unbind packet using this method will result in an * <code>UnsupportedOperationException</code> being thrown. * @param r The request packet to send to the SMSC * @return The response packet returned by the SMSC, or null if * asynchronous communication is being used. * @throws java.lang.NullPointerException if <code>r</code> is null. * @throws java.net.SocketTimeoutException If a socket timeout occurs while * waiting for a response packet. (Only in synchronized mode). * @throws java.io.IOException If an I/O error occurs while writing the * request packet to the network connection. * @throws ie.omk.smpp.UnsupportedOperationException If this connection * type does not support operation <code>r</code>. For example, a receiver * link does not support the submit_sm operation. * @throws ie.omk.smpp.AlreadyBoundException If the request type is a bind * packet and this connection is already bound. * @throws ie.omk.smpp.message.SMPPProtocolException If synchronous * communications is in use and the incoming response packet violates the * SMPP specification, this exception will be thrown. * @see #setSeqNumScheme */ public SMPPResponse sendRequest(SMPPRequest r) throws java.net.SocketTimeoutException, java.io.IOException, AlreadyBoundException, VersionException, SMPPProtocolException, UnsupportedOperationException { SMPPResponse resp = null; int id = r.getCommandId(); if (this.state != BOUND) throw new NotBoundException("Must be bound to the SMSC before " + "sending packets"); // Force applications to use bind and unbind if (id == SMPPPacket.BIND_RECEIVER || id == SMPPPacket.BIND_TRANSCEIVER || id == SMPPPacket.BIND_TRANSMITTER || id == SMPPPacket.UNBIND) { throw new UnsupportedOperationException("You must use the bind and unbind methods to send those requests"); } // Very few request types allowed by a receiver connection. if (connectionType == RECEIVER) { if (id != SMPPPacket.ENQUIRE_LINK) throw new UnsupportedOperationException( "Operation not permitted over receiver connection"); } return (sendRequestInternal(r)); } /** Send a request to the SMSC. * XXX complete javadoc for this method. * @throws ie.omk.smpp.version.VersionException if the version in use * does not support the request being sent. */ protected SMPPResponse sendRequestInternal(SMPPRequest r) throws java.net.SocketTimeoutException, java.io.IOException, AlreadyBoundException, VersionException, SMPPProtocolException { SMPPResponse resp = null; int id = r.getCommandId(); if (link == null) throw new IOException("No SMSC connection."); // Check the command is supported by the interface version.. if (!this.interfaceVersion.isSupported(id)) { throw new VersionException("Command ID 0x" + Integer.toHexString(id) + " is not supported by SMPP " + this.interfaceVersion); } if (id == SMPPPacket.BIND_TRANSMITTER || id == SMPPPacket.BIND_RECEIVER || id == SMPPPacket.BIND_TRANSCEIVER) { if (this.state != UNBOUND) throw new AlreadyBoundException("Already bound to the SMSC"); openLink(); setState(BINDING); if (asyncComms) { if (rcvThread == null) createRecvThread(); // Set the socket timeout to the bind timeout try { long bindTimeout = APIConfig.getInstance().getLong(APIConfig.BIND_TIMEOUT, 0L); if (bindTimeout > 0L) { this.link.setTimeout(bindTimeout); if (logger.isDebugEnabled()) { logger.debug("Set bind timeout to " + bindTimeout); } } } catch (UnsupportedOperationException x) { logger.warn("Link does not support read timeouts - bind timeout will not work"); } if (!rcvThread.isAlive()) rcvThread.start(); } } else if (id == SMPPPacket.UNBIND) { if (!asyncComms && packetQueue.size() > 0) throw new IllegalStateException("Cannot unbind while there are incoming packets " + "waiting responses"); if (this.state != BOUND) throw new IllegalStateException("Not currently bound"); setState(UNBINDING); } // XXX temporary...this should be removed once it's safe to assume that // no packet can be submitted that has been constructed outside the // confines of this connection's factory method. if (r.getSequenceNum() == 0 && seqNumScheme != null) r.setSequenceNum(seqNumScheme.nextNumber()); link.write(r, this.supportOptionalParams); if (!asyncComms) resp = waitForResponsePacket(r); return ((SMPPResponse)resp); } /** Wait for a response packet from the SMSC. A response packet with the * same sequence number as <code>req</code> will be waited for from the * SMSC. If an unexpected packet arrives, either a response packet with a * different sequence number or a request packet, it will be queued for * later retrieval by the application via <code>readNextPacket</code>. * @param req the request packet to wait for a response to. * @return A response packet with the same sequence number as * <code>req</code>. * @throws java.net.SocketTimeoutException if the read on the socket times * out. * @see #readNextPacket * @see java.net.SocketTimeoutException */ protected SMPPResponse waitForResponsePacket(SMPPPacket req) throws java.net.SocketTimeoutException, java.io.IOException, SMPPProtocolException { try { int id = -1; SMPPPacket resp = null; int expectedSeq = req.getSequenceNum(); while (true) { resp = readNextPacketInternal(); id = resp.getCommandId(); if ((id & 0x80000000) != 0 && resp.getSequenceNum() == expectedSeq) { break; } else { logger.info("Queuing unexpected sequence numbered packet."); if (logger.isDebugEnabled()) { StringBuffer b = new StringBuffer("Expected:") .append(Integer.toString(expectedSeq)) .append(" but got ") .append(Integer.toString(resp.getSequenceNum())); logger.debug(b.toString()); } packetQueue.add(resp); } } return ((SMPPResponse)resp); } catch (java.net.SocketTimeoutException x) { // Must set our state and re-throw the exception.. logger.error("Received a socket timeout exception", x); throw x; } } /** Determine if there are packets available for reading using * <code>readNextPacket</code>. This method is only valid for synchronous * communications...it will always return 0 if asynchronous mode is in * use. * @return 0 if there is no packet available for reading, 1 if there is data * available but the call to <code>readNextPacket</code> may block or 2 if * there is a full packet available. */ public int packetAvailable() { int ret = 0; if (!asyncComms) { if (packetQueue.size() > 0) ret = 2; else if (link.available() > 0) ret = 1; } return (ret); } /** Send an smpp response packet to the SMSC * @param resp The response packet to send to the SMSC * @throws java.io.IOException If an I/O error occurs while writing the * response packet to the output stream. */ public void sendResponse(SMPPResponse resp) throws java.io.IOException { Integer key = null; if (link == null) throw new IOException("Connection to SMSC is not valid."); try { link.write(resp, this.supportOptionalParams); } catch (java.net.SocketTimeoutException x) { logger.warn("Got a socket timeout exception", x); setState(UNBOUND); throw x; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -