├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── SSL.md ├── pom.xml └── src ├── etc ├── SMPP_v3_4_Issue1_2.pdf └── SMPP_v5_0.pdf ├── main └── java │ └── com │ └── cloudhopper │ └── smpp │ ├── PduAsyncResponse.java │ ├── SmppBindType.java │ ├── SmppClient.java │ ├── SmppConstants.java │ ├── SmppServer.java │ ├── SmppServerConfiguration.java │ ├── SmppServerCounters.java │ ├── SmppServerHandler.java │ ├── SmppServerSession.java │ ├── SmppSession.java │ ├── SmppSessionConfiguration.java │ ├── SmppSessionCounters.java │ ├── SmppSessionHandler.java │ ├── SmppSessionListener.java │ ├── channel │ ├── ChannelUtil.java │ ├── SmppChannelConstants.java │ ├── SmppClientConnector.java │ ├── SmppServerConnector.java │ ├── SmppSessionLogger.java │ ├── SmppSessionPduDecoder.java │ ├── SmppSessionThreadRenamer.java │ └── SmppSessionWrapper.java │ ├── impl │ ├── DefaultPduAsyncResponse.java │ ├── DefaultSmppClient.java │ ├── DefaultSmppServer.java │ ├── DefaultSmppServerCounters.java │ ├── DefaultSmppSession.java │ ├── DefaultSmppSessionCounters.java │ ├── DefaultSmppSessionHandler.java │ ├── PollableSmppSessionHandler.java │ ├── SmppSessionChannelListener.java │ └── UnboundSmppSession.java │ ├── jmx │ ├── DefaultSmppServerMXBean.java │ └── DefaultSmppSessionMXBean.java │ ├── pdu │ ├── AlertNotification.java │ ├── BaseBind.java │ ├── BaseBindResp.java │ ├── BaseSm.java │ ├── BaseSmResp.java │ ├── BindReceiver.java │ ├── BindReceiverResp.java │ ├── BindTransceiver.java │ ├── BindTransceiverResp.java │ ├── BindTransmitter.java │ ├── BindTransmitterResp.java │ ├── CancelSm.java │ ├── CancelSmResp.java │ ├── DataSm.java │ ├── DataSmResp.java │ ├── DeliverSm.java │ ├── DeliverSmResp.java │ ├── EmptyBody.java │ ├── EmptyBodyResp.java │ ├── EnquireLink.java │ ├── EnquireLinkResp.java │ ├── GenericNack.java │ ├── PartialPdu.java │ ├── PartialPduResp.java │ ├── Pdu.java │ ├── PduRequest.java │ ├── PduResponse.java │ ├── QuerySm.java │ ├── QuerySmResp.java │ ├── ReplaceSm.java │ ├── ReplaceSmResp.java │ ├── SubmitMulti.java │ ├── SubmitMultiResp.java │ ├── SubmitSm.java │ ├── SubmitSmResp.java │ ├── Unbind.java │ └── UnbindResp.java │ ├── simulator │ ├── SmppSimulatorBindProcessor.java │ ├── SmppSimulatorPduProcessor.java │ ├── SmppSimulatorServer.java │ ├── SmppSimulatorServerHandler.java │ └── SmppSimulatorSessionHandler.java │ ├── ssl │ ├── AliasedX509ExtendedKeyManager.java │ ├── CertificateValidator.java │ ├── SslConfiguration.java │ └── SslContextFactory.java │ ├── tlv │ ├── Tlv.java │ └── TlvConvertException.java │ ├── transcoder │ ├── DefaultPduTranscoder.java │ ├── DefaultPduTranscoderContext.java │ ├── PduTranscoder.java │ └── PduTranscoderContext.java │ ├── type │ ├── Address.java │ ├── GenericNackException.java │ ├── LoggingOptions.java │ ├── NotEnoughDataInBufferException.java │ ├── RecoverablePduException.java │ ├── SmppBindException.java │ ├── SmppChannelConnectException.java │ ├── SmppChannelConnectTimeoutException.java │ ├── SmppChannelException.java │ ├── SmppConnectionConfiguration.java │ ├── SmppInvalidArgumentException.java │ ├── SmppProcessingException.java │ ├── SmppTimeoutException.java │ ├── TerminatingNullByteNotFoundException.java │ ├── UnexpectedPduResponseException.java │ ├── UnknownCommandIdException.java │ ├── UnrecoverablePduException.java │ └── UnsucessfulSME.java │ └── util │ ├── ChannelBufferUtil.java │ ├── ConcurrentCommandCounter.java │ ├── ConcurrentCommandStatusCounter.java │ ├── DaemonExecutors.java │ ├── DeliveryReceipt.java │ ├── DeliveryReceiptException.java │ ├── InvalidSequenceNumberException.java │ ├── PduUtil.java │ ├── SequenceNumber.java │ ├── SmppSessionUtil.java │ ├── SmppUtil.java │ ├── StatisticsSample.java │ └── TlvUtil.java └── test ├── java └── com │ └── cloudhopper │ └── smpp │ ├── demo │ ├── ClientMain.java │ ├── DeliveryReceiptMain.java │ ├── ParserMain.java │ ├── PerformanceClientMain.java │ ├── QueryCancelMain.java │ ├── RebindMain.java │ ├── ServerEchoMain.java │ ├── ServerMain.java │ ├── SimulatorMain.java │ ├── SlowServerMain.java │ ├── SslClientMain.java │ ├── SslServerMain.java │ └── persist │ │ ├── Client.java │ │ ├── ClientSmppSessionHandler.java │ │ ├── DummySmppClientMessageService.java │ │ ├── EnquireLinkTask.java │ │ ├── LoggingUtil.java │ │ ├── Main.java │ │ ├── OutboundClient.java │ │ ├── ReconnectionDaemon.java │ │ ├── ReconnectionTask.java │ │ └── SmppClientMessageService.java │ ├── impl │ ├── DefaultSmppServerTest.java │ └── DefaultSmppSessionTest.java │ ├── pdu │ ├── BufferHelper.java │ └── PduTest.java │ ├── ssl │ ├── SslContextFactoryTest.java │ └── SslSessionTest.java │ ├── tlv │ └── TlvTest.java │ ├── transcoder │ ├── PduDecoderTest.java │ └── PduEncoderTest.java │ └── util │ ├── ChannelBufferUtilTest.java │ ├── ConcurrentCommandStatusCounterTest.java │ ├── DeliveryReceiptTest.java │ ├── PduUtilTest.java │ ├── SequenceNumberTest.java │ ├── SmppUtilTest.java │ └── TlvUtilTest.java └── resources ├── keystore ├── logback-test.xml ├── server.crt ├── server.key └── stunnel.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target/ 3 | .classpath 4 | .project 5 | .settings/ 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk7 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | client: 3 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.ClientMain" 4 | 5 | performance-client: 6 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.PerformanceClientMain" 7 | 8 | ssl-client: 9 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.SslClientMain" 10 | 11 | server: 12 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.ServerMain" 13 | 14 | ssl-server: 15 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.SslServerMain" 16 | 17 | slow-server: 18 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.SlowServerMain" 19 | 20 | simulator: 21 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.SimulatorMain" 22 | 23 | rebind: 24 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.RebindMain" 25 | 26 | parser: 27 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.ParserMain" 28 | 29 | dlr: 30 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.DeliveryReceiptMain" 31 | 32 | persist-client: 33 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.persist.Main" 34 | 35 | server-echo: 36 | mvn -e test-compile exec:java -Dexec.classpathScope="test" -Dexec.mainClass="com.cloudhopper.smpp.demo.ServerEchoMain" 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!NOTE] 2 | > On 29 June 2023, Mobius Software LTD signed an agreement with Mavenir to assume development and support of the RestcommOne on prem products. For more details regarding open source / commercial differentiation, roadmap, licensing and other details please visit the [Mobius Website](https://www.mobius-software.com/telestaxannouncement). 3 | 4 | Cloudhopper SMPP by Fizzed (forked from Twitter) 5 | ================================================ 6 | 7 | [![Build Status](https://travis-ci.org/RestComm/cloudhopper-smpp.svg?branch=master)](https://travis-ci.org/RestComm/cloudhopper-smpp) 8 | 9 | News 10 | ------------------------ 11 | 12 | **Nov 2016** 13 | 14 | While Fizzed, Inc. took over from Twitter for a while, there is now an apparent lack of commits on the original repository for almost a year and PR pending reviews for more than 6 months. 15 | The project was forked here and will be updated regularly as it is being used in Restcomm SMSC 16 | 17 | -------------------------------------------------------------------------------- /SSL.md: -------------------------------------------------------------------------------- 1 | # How to use SSL with cloudhopper-smpp 2 | 3 | The purpose of this document is to provide a summary of how to configuration SSL for ch-smpp servers and clients. The internal implementation uses Java Secure Sockets Extension (JSSE). 4 | 5 | ## Configuring a SMPP server with SSL transport 6 | 7 | ### Example: 8 | 9 | // Configure the server as you normally would: 10 | SmppServerConfiguration configuration = new SmppServerConfiguration(); 11 | configuration.setPort(2776); 12 | ... 13 | 14 | // Then create a SSL configuration: 15 | SslConfiguration sslConfig = new SslConfiguration(); 16 | sslConfig.setKeyStorePath("path/to/keystore"); 17 | sslConfig.setKeyStorePassword("changeit"); 18 | sslConfig.setKeyManagerPassword("changeit"); 19 | sslConfig.setTrustStorePath("path/to/keystore"); 20 | sslConfig.setTrustStorePassword("changeit"); 21 | ... 22 | 23 | // And add it to the server configuration: 24 | configuration.setUseSsl(true); 25 | configuration.setSslConfiguration(sslConfig); 26 | 27 | 28 | ### Require client auth 29 | 30 | sslConfig.setNeedClientAuth(true); 31 | 32 | 33 | ## Configuring a SMPP client with SSL transport 34 | 35 | ### Example: 36 | 37 | // Configure the server as you normally would: 38 | SmppSessionConfiguration configuration = new SmppSessionConfiguration(); 39 | configuration.setType(SmppBindType.TRANSCEIVER); 40 | configuration.setHost("127.0.0.1"); 41 | configuration.setPort(2776); 42 | ... 43 | 44 | // Then create a SSL configuration: 45 | SslConfiguration sslConfig = new SslConfiguration(); 46 | // Which trusts all certs by default. You can turn this off with 47 | // sslConfig.setTrustAll(false); 48 | ... 49 | 50 | // And add it to the server configuration: 51 | configuration.setSslConfiguration(sslConfig); 52 | configuration.setUseSsl(true); 53 | 54 | ### Validate certificates 55 | 56 | sslConfig.setValidateCerts(true); 57 | sslConfig.setValidatePeerCerts(true); 58 | 59 | 60 | ## Generating key pairs and certificates 61 | 62 | Generating Keys and Certificates with the JDK's keytool 63 | 64 | keytool -keystore keystore -alias smpp -genkey -keyalg RSA 65 | 66 | Generating Keys and Certificates with OpenSSL 67 | 68 | openssl genrsa -des3 -out smpp.key 69 | openssl req -new -x509 -key smpp.key -out smpp.crt 70 | 71 | ## Requesting a trusted certificate 72 | 73 | Generating a CSR from keytool 74 | 75 | keytool -certreq -alias smpp -keystore keystore -file smpp.csr 76 | 77 | Generating a CSR from OpenSSL 78 | 79 | openssl req -new -key smpp.key -out smpp.csr 80 | 81 | ## Loading keys and certificates 82 | 83 | Loading Certificates with keytool 84 | 85 | The following command loads a PEM encoded certificate in the smpp.crt file into a JSSE keystore: 86 | 87 | keytool -keystore keystore -import -alias smpp -file smpp.crt -trustcacerts 88 | 89 | Loading Keys and Certificates via PKCS12 90 | 91 | If you have a key and certificate in separate files, you need to combine them into a PKCS12 format file to load into a new keystore. The certificate can be one you generated yourself or one returned from a CA in response to your CSR. 92 | 93 | The following OpenSSL command combines the keys in smpp.key and the certificate in the smpp.crt file into the smpp.pkcs12 file. 94 | 95 | openssl pkcs12 -inkey smpp.key -in smpp.crt -export -out smpp.pkcs12 96 | keytool -importkeystore -srckeystore smpp.pkcs12 -srcstoretype PKCS12 -destkeystore keystore 97 | 98 | 99 | ## Appendix 100 | 101 | ### Interop with stunnel 102 | 103 | This library has been tested with stunnel4 wrapping both client and servers. There is a sample stunnel.conf in src/test/resources that works with `make server` and `make ssl-client`. The SSL implementation should be compatible with other TLS/SSL encryption wrappers, assuming the JDK you are using supports the same cryptographic algorithms as the encryption wrapper. 104 | 105 | ### Known issues 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | org.restcomm.smpp 5 | ch-smpp 6 | jar 7 | 5.0.10-SNAPSHOT 8 | ch-smpp 9 | Efficient, scalable, and flexible Java implementation of the Short Messaging Peer to Peer Protocol (SMPP) 10 | https://github.com/Restcomm/cloudhopper-smpp 11 | 2009 12 | 13 | 14 | https://github.com/Restcomm/cloudhopper-smpp 15 | scm:git:https://github.com/Restcomm/cloudhopper-smpp.git 16 | scm:git:git@github.com:Restcomm/cloudhopper-smpp.git 17 | master 18 | 19 | 20 | 21 | org.restcomm 22 | restcomm-parent 23 | 3.0.5 24 | 25 | 26 | 27 | com.cloudhopper.smpp 28 | 7.0.6-3 29 | 7.0.6 30 | 7.0.6 31 | 3.9.6.Final 32 | 1.7.13 33 | 34 | 3.2.5 35 | 36 | 37 | 38 | 39 | 40 | org.restcomm.smpp 41 | ch-commons-util 42 | ${ch-commons-util.version} 43 | 44 | 45 | org.restcomm.smpp 46 | ch-commons-charset 47 | ${ch-commons-charset.version} 48 | 49 | 50 | org.slf4j 51 | slf4j-api 52 | ${slf4j.version} 53 | 54 | 55 | io.netty 56 | netty 57 | ${netty.version} 58 | 59 | 60 | 61 | 62 | 63 | junit 64 | junit 65 | 4.12 66 | test 67 | 68 | 69 | org.restcomm.smpp 70 | ch-commons-gsm 71 | 7.0.4 72 | test 73 | 74 | 75 | ch.qos.logback 76 | logback-classic 77 | 1.1.3 78 | test 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/etc/SMPP_v3_4_Issue1_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RestComm/cloudhopper-smpp/99a45b7e9389c79566a369f0f1d7902f20027353/src/etc/SMPP_v3_4_Issue1_2.pdf -------------------------------------------------------------------------------- /src/etc/SMPP_v5_0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RestComm/cloudhopper-smpp/99a45b7e9389c79566a369f0f1d7902f20027353/src/etc/SMPP_v5_0.pdf -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/PduAsyncResponse.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.PduRequest; 24 | import com.cloudhopper.smpp.pdu.PduResponse; 25 | 26 | /** 27 | * A container to hold an asynchronous response and include information tracked 28 | * internally by an SmppSession. For example, an instance of this class will 29 | * contain the original request, the response, and a few timestamps. 30 | * 31 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 32 | */ 33 | public interface PduAsyncResponse { 34 | 35 | /** 36 | * Gets the original request associated with the response. 37 | * @return The original request 38 | */ 39 | public PduRequest getRequest(); 40 | 41 | /** 42 | * Gets the response from the remote endpoint. 43 | * @return The response 44 | */ 45 | public PduResponse getResponse(); 46 | 47 | /** 48 | * Gets the size of the window after this request was added. 49 | * @return The size of the window after this request was added. 50 | */ 51 | public int getWindowSize(); 52 | 53 | /** 54 | * Gets the amount of time required to accept the request into the session 55 | * send window (for a free slot to open up). 56 | * @return The amount of time (in ms) to accept the request into the send window 57 | */ 58 | public long getWindowWaitTime(); 59 | 60 | /** 61 | * Gets the amount of time required for the remote endpoint to acknowledge 62 | * the request with a response. This value is based on the time the request 63 | * went out on the wire till a response was received on the wire. Does not 64 | * include any time required waiting for a slot in the window to become 65 | * available. 66 | *

67 | * NOTE: If the window size is > 1, this value can be somewhat misleading. 68 | * The remote endpoint would process X number of requests ahead of this one 69 | * that went out ahead of it in the window. This does represent the total 70 | * response time, but doesn't mean the remote endpoint is this slow at processing 71 | * one request. In cases of high load where the window is always full, the 72 | * windowWaitTime actually represents how fast the remote endpoint is processing 73 | * requests. 74 | * @return The amount of time (in ms) to receive a response from remote endpoint 75 | */ 76 | public long getResponseTime(); 77 | 78 | /** 79 | * Gets an estimate of the processing time required by the remote endpoint 80 | * to process this request. The value is calculated with the following 81 | * formula: "response time" divided by the "window size" at the time of the 82 | * request. 83 | * @return The amount of estimated time (in ms) to receive a response from 84 | * the remote endpoint just for this request (as opposed to potentially 85 | * this request and all requests ahead of it in the window). 86 | */ 87 | public long getEstimatedProcessingTime(); 88 | 89 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppBindType.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Enumeration of all SMPP session types. 25 | * 26 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 27 | */ 28 | public enum SmppBindType { 29 | 30 | TRANSCEIVER, 31 | TRANSMITTER, 32 | RECEIVER 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppClient.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.SmppBindException; 24 | import com.cloudhopper.smpp.type.SmppChannelException; 25 | import com.cloudhopper.smpp.type.SmppTimeoutException; 26 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 27 | 28 | /** 29 | * Interface representing an SmppClient. 30 | * 31 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 32 | */ 33 | public interface SmppClient { 34 | 35 | /** 36 | * Binds a client to a remote SMPP endpoint by opening the socket, sending 37 | * a bind request, and waiting for a bind response. 38 | * @param config The client session configuration 39 | * @param sessionHandler The session handler 40 | * @return If the bind is successful will be the new session 41 | * @throws SmppTimeoutException Thrown if either the underlying TCP/IP connection 42 | * cannot connect within the "connectTimeout" or we can connect but don't 43 | * receive a response back to the bind request within the "bindTimeout". 44 | * @throws SmppChannelException Thrown if there is an error with the underlying 45 | * TCP/IP connection such as a bad host name or the remote server's port 46 | * is not accepting connections. 47 | * @throws SmppBindException Thrown only in the case where the "bind" request 48 | * was successfully sent to the remote system and we actually got back 49 | * a "bind" response that rejected the bind attempt. 50 | * @throws UnrecoverablePduException Thrown in the case where we were able 51 | * to connect and send our "bind" request, but we got back data that 52 | * was not failed parsing into a PDU. 53 | * @throws InterruptedException Thrown if the calling thread is interrupted 54 | * while we are attempting the bind. 55 | */ 56 | public SmppSession bind(SmppSessionConfiguration config, SmppSessionHandler sessionHandler) throws SmppTimeoutException, SmppChannelException, SmppBindException, UnrecoverablePduException, InterruptedException; 57 | 58 | /** 59 | * Destroy a client by ensuring that all session sockets are closed and all 60 | * resources are cleaned up. This method should the last method called 61 | * before discarding or losing a reference to a client. Since this method 62 | * cleans up all resources, make sure that any data you need to access is 63 | * accessed before calling this method. After calling this method 64 | * it is not guaranteed that any other method will correctly work. 65 | */ 66 | public void destroy(); 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppServer.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.SmppChannelException; 24 | import org.jboss.netty.channel.group.ChannelGroup; 25 | 26 | /** 27 | * Interface representing an SmppServer. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public interface SmppServer { 32 | 33 | /** 34 | * Returns true if the SMPP server is started. 35 | * @return True if started, otherwise false. 36 | */ 37 | public boolean isStarted(); 38 | 39 | /** 40 | * Returns true if the SMPP server is stopped. 41 | * @return True if stopped, otherwise false. 42 | */ 43 | public boolean isStopped(); 44 | 45 | /** 46 | * Returns true if the SMPP server is destroyed. 47 | * @return True if destroyed, otherwise false. 48 | */ 49 | public boolean isDestroyed(); 50 | 51 | /** 52 | * Starts the SMPP server. Binds all server socket connectors to configured 53 | * ports. 54 | */ 55 | public void start() throws SmppChannelException; 56 | 57 | /** 58 | * Stops the SMPP server. Closes all child sockets and then closes all server 59 | * socket connectors by unbinding them from ports. Once stopped, the server 60 | * can be started again. If a server will no longer be used, please follow 61 | * a call to stop by calling {@see #shutdown()} 62 | */ 63 | public void stop(); 64 | 65 | /** 66 | * Destroys the SMPP server. Ensures the server is first stopped, then 67 | * releases all resources, and unregisters from JMX (if it was enabled). 68 | */ 69 | public void destroy(); 70 | 71 | public ChannelGroup getChannels(); 72 | 73 | public SmppServerCounters getCounters(); 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppServerCounters.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Interface defining the counters that will be tracked for an SMPP server. 25 | * 26 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 27 | */ 28 | public interface SmppServerCounters { 29 | 30 | /** 31 | * Clears all counters (including session size(s)). 32 | */ 33 | public void clear(); 34 | 35 | /** 36 | * Resets counters that don't track any state (e.g. session size(s)). 37 | */ 38 | public void reset(); 39 | 40 | public int getChannelConnects(); 41 | 42 | public int getChannelDisconnects(); 43 | 44 | public int getBindTimeouts(); 45 | 46 | public int getBindRequested(); 47 | 48 | public int getSessionCreated(); 49 | 50 | public int getSessionDestroyed(); 51 | 52 | public int getReceiverSessionSize(); 53 | 54 | public int getSessionSize(); 55 | 56 | public int getTransceiverSessionSize(); 57 | 58 | public int getTransmitterSessionSize(); 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppServerSession.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * An extended interface for a Server (SMSC) SMPP session. 25 | * 26 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 27 | */ 28 | public interface SmppServerSession extends SmppSession { 29 | 30 | /** 31 | * Indicates that the local endpoint (server) is ready to start processing 32 | * requests for the session. Completes the bind process by the remote 33 | * endpoint by setting up the handler for the session, sending back the 34 | * prepared bind response and setting the socket/channel as readable. 35 | * 36 | * Please note that when the SmppServer accepts a new socket connection 37 | * from a client, it reads the bind request, but does not automatically 38 | * send back a bind response. The bind response can only be sent back 39 | * by calling this method to indicate that the server is now fully ready 40 | * to process requests from the client. 41 | 42 | * @param sessionHandler The handler for the session to use for processing 43 | */ 44 | public void serverReady(SmppSessionHandler sessionHandler); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppSessionCounters.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.util.ConcurrentCommandCounter; 24 | 25 | /** 26 | * Interface defining the counters that can be optionally tracked for an SMPP session. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public interface SmppSessionCounters { 31 | 32 | public void reset(); 33 | 34 | public ConcurrentCommandCounter getRxDataSM(); 35 | 36 | public ConcurrentCommandCounter getRxDeliverSM(); 37 | 38 | public ConcurrentCommandCounter getRxEnquireLink(); 39 | 40 | public ConcurrentCommandCounter getRxSubmitSM(); 41 | 42 | public ConcurrentCommandCounter getTxDataSM(); 43 | 44 | public ConcurrentCommandCounter getTxDeliverSM(); 45 | 46 | public ConcurrentCommandCounter getTxEnquireLink(); 47 | 48 | public ConcurrentCommandCounter getTxSubmitSM(); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/SmppSessionListener.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | 25 | /** 26 | * Low-level PDU traffic listener. 27 | * Could be used for PDU filtering. 28 | * Use with caution. 29 | * 30 | * @author t3hk0d3 31 | */ 32 | public interface SmppSessionListener extends SmppSessionHandler { 33 | 34 | /** 35 | * Called when ANY PDU received from connection. 36 | * This method could be used to sniff all incoming SMPP packet traffic, 37 | * and also permit/deny it from futher processing. 38 | * Could be used for advanced packet logging, counters and filtering. 39 | * @param pdu 40 | * @return boolean allow PDU processing. If false PDU would be discarded. 41 | */ 42 | public boolean firePduReceived(Pdu pdu); 43 | 44 | /** 45 | * Called when ANY PDU received from connection. 46 | * This method could be used to sniff all outgoing SMPP packet traffic, 47 | * and also permit/deny it from sending. 48 | * Could be used for advanced packet logging, counters and filtering. 49 | * @param pdu 50 | * @return boolean allow PDU sending. If false PDU would be discarded. 51 | */ 52 | public boolean firePduDispatch(Pdu pdu); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/ChannelUtil.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import java.net.InetSocketAddress; 24 | import org.jboss.netty.channel.Channel; 25 | 26 | /** 27 | * Utility methods for working with Netty Channels. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class ChannelUtil { 32 | 33 | /** 34 | * Create a name for the channel based on the remote host's IP and port. 35 | */ 36 | static public String createChannelName(Channel channel) { 37 | // check if anything is null 38 | if (channel == null || channel.getRemoteAddress() == null) { 39 | return "ChannelWasNull"; 40 | } 41 | // create a channel name 42 | if (channel.getRemoteAddress() instanceof InetSocketAddress) { 43 | InetSocketAddress addr = (InetSocketAddress)channel.getRemoteAddress(); 44 | // just get the raw IP address 45 | String remoteHostAddr = addr.getAddress().getHostAddress(); 46 | int remoteHostPort = addr.getPort(); 47 | return remoteHostAddr + ":" + remoteHostPort; 48 | } else { 49 | return channel.getRemoteAddress().toString(); 50 | } 51 | } 52 | 53 | static public String getChannelRemoteHost(Channel channel) { 54 | if (channel == null || channel.getRemoteAddress() == null) { 55 | return null; 56 | } 57 | // create a channel name 58 | if (channel.getRemoteAddress() instanceof InetSocketAddress) { 59 | InetSocketAddress addr = (InetSocketAddress)channel.getRemoteAddress(); 60 | // just get the raw IP address 61 | return addr.getAddress().getHostAddress(); 62 | } 63 | return null; 64 | } 65 | 66 | static public int getChannelRemotePort(Channel channel) { 67 | if (channel == null || channel.getRemoteAddress() == null) { 68 | return 0; 69 | } 70 | // create a channel name 71 | if (channel.getRemoteAddress() instanceof InetSocketAddress) { 72 | InetSocketAddress addr = (InetSocketAddress)channel.getRemoteAddress(); 73 | // just get the raw IP address 74 | return addr.getPort(); 75 | } 76 | return 0; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/SmppChannelConstants.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Constants used for SMPP channels and pipelines. 25 | * 26 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 27 | */ 28 | public class SmppChannelConstants { 29 | 30 | public static final String PIPELINE_SERVER_CONNECTOR_NAME = "smppServerConnector"; 31 | 32 | // default channel handler used only during connects 33 | public static final String PIPELINE_CLIENT_CONNECTOR_NAME = "smppClientConnector"; 34 | 35 | // channel handlers used for once a session is connected 36 | public static final String PIPELINE_SESSION_THREAD_RENAMER_NAME = "smppSessionThreadRenamer"; 37 | public static final String PIPELINE_SESSION_LOGGER_NAME = "smppSessionLogger"; 38 | public static final String PIPELINE_SESSION_PDU_DECODER_NAME = "smppSessionPduDecoder"; 39 | public static final String PIPELINE_SESSION_WRAPPER_NAME = "smppSessionWrapper"; 40 | public static final String PIPELINE_SESSION_SSL_NAME = "smppSessionSSL"; 41 | public static final String PIPELINE_SESSION_WRITE_TIMEOUT_NAME = "smppSessionWriteTimeout"; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/SmppClientConnector.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import org.jboss.netty.channel.ChannelHandlerContext; 24 | import org.jboss.netty.channel.ChannelPipelineCoverage; 25 | import org.jboss.netty.channel.ChannelStateEvent; 26 | import org.jboss.netty.channel.ExceptionEvent; 27 | import org.jboss.netty.channel.SimpleChannelUpstreamHandler; 28 | import org.jboss.netty.channel.group.ChannelGroup; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | /** 33 | * The default handler used just during a "connect" for a Channel when attempting 34 | * to bind into an SMSC. The reason is that some handler must be added to create 35 | * a channel and then replaced before the actual "bind" is attempted. This 36 | * handler basically does nothing. Until a "bind" request is received by the SMSC, 37 | * nothing should actually be received so its safe to have a handler that does 38 | * nothing. 39 | * 40 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 41 | */ 42 | @ChannelPipelineCoverage("all") 43 | public class SmppClientConnector extends SimpleChannelUpstreamHandler { 44 | private static final Logger logger = LoggerFactory.getLogger(SmppClientConnector.class); 45 | 46 | private ChannelGroup channels; 47 | 48 | public SmppClientConnector(ChannelGroup channels) { 49 | this.channels = channels; 50 | } 51 | 52 | @Override 53 | public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 54 | // called every time a new channel connects 55 | channels.add(e.getChannel()); 56 | } 57 | 58 | @Override 59 | public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 60 | // called every time a channel disconnects 61 | channels.remove(e.getChannel()); 62 | } 63 | 64 | /** 65 | * Invoked when an exception was raised by an I/O thread or an upstream handler. 66 | * NOTE: Not implementing this causes annoying log statements to STDERR 67 | */ 68 | @Override 69 | public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { 70 | // the client smpp implementation relies on this to catch errors upstream 71 | // however, during a connect sequence, we don't have any upstream handlers 72 | // yet and the framework logged the exceptions to STDERR causing issues 73 | // on the console. So, we'll implement a default handling of it here 74 | // where we just pass it further upstream and basically discard it 75 | ctx.sendUpstream(e); 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/SmppSessionPduDecoder.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.transcoder.PduTranscoder; 24 | import org.jboss.netty.buffer.ChannelBuffer; 25 | import org.jboss.netty.channel.Channel; 26 | import org.jboss.netty.channel.ChannelHandlerContext; 27 | import org.jboss.netty.handler.codec.frame.FrameDecoder; 28 | 29 | /** 30 | * Channel handler responsible for decoding a ChannelBuffer into a PDU. A 31 | * decoded PDU is then passed up the pipeline for further processing. 32 | * 33 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 34 | */ 35 | public class SmppSessionPduDecoder extends FrameDecoder { 36 | 37 | private final PduTranscoder transcoder; 38 | 39 | public SmppSessionPduDecoder(PduTranscoder transcoder) { 40 | this.transcoder = transcoder; 41 | } 42 | 43 | @Override 44 | protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { 45 | // try to decode the frame into a PDU 46 | // NOTE: this already returns null if there isn't enough data yet 47 | return transcoder.decode(buffer); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/SmppSessionThreadRenamer.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | 24 | import org.jboss.netty.channel.ChannelEvent; 25 | import org.jboss.netty.channel.ChannelHandlerContext; 26 | import org.jboss.netty.channel.ChannelPipelineCoverage; 27 | import org.jboss.netty.channel.ChannelUpstreamHandler; 28 | 29 | /** 30 | * Channel handler responsible for renaming the current thread, passing the 31 | * event upstream, then renaming the thread back after its done processing. This 32 | * handler should be the first one in the pipeline to make sure all handlers 33 | * after it have the correct thread name for proper logging. 34 | * 35 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 36 | */ 37 | @ChannelPipelineCoverage("one") 38 | public class SmppSessionThreadRenamer implements ChannelUpstreamHandler { 39 | 40 | private String threadName; 41 | 42 | public SmppSessionThreadRenamer(String threadName) { 43 | this.threadName = threadName; 44 | } 45 | 46 | public String getThreadName() { 47 | return this.threadName; 48 | } 49 | 50 | public void setThreadName(String value) { 51 | this.threadName = value; 52 | } 53 | 54 | @Override 55 | public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { 56 | // always rename the current thread and then rename it back 57 | String currentThreadName = Thread.currentThread().getName(); 58 | Thread.currentThread().setName(threadName); 59 | ctx.sendUpstream(e); 60 | Thread.currentThread().setName(currentThreadName); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/channel/SmppSessionWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.channel; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.impl.SmppSessionChannelListener; 24 | import com.cloudhopper.smpp.pdu.Pdu; 25 | import org.jboss.netty.channel.ChannelHandlerContext; 26 | import org.jboss.netty.channel.ChannelPipelineCoverage; 27 | import org.jboss.netty.channel.ChannelStateEvent; 28 | import org.jboss.netty.channel.ExceptionEvent; 29 | import org.jboss.netty.channel.MessageEvent; 30 | import org.jboss.netty.channel.SimpleChannelHandler; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | /** 35 | * 36 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 37 | */ 38 | @ChannelPipelineCoverage("one") 39 | public class SmppSessionWrapper extends SimpleChannelHandler { 40 | private static final Logger logger = LoggerFactory.getLogger(SmppSessionWrapper.class); 41 | 42 | private SmppSessionChannelListener listener; 43 | 44 | public SmppSessionWrapper(SmppSessionChannelListener listener) { 45 | this.listener = listener; 46 | } 47 | 48 | @Override 49 | public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { 50 | if (e.getMessage() instanceof Pdu) { 51 | Pdu pdu = (Pdu)e.getMessage(); 52 | this.listener.firePduReceived(pdu); 53 | } 54 | } 55 | 56 | /** 57 | * Invoked when an exception was raised by an I/O thread or an upstream handler. 58 | */ 59 | @Override 60 | public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { 61 | //logger.warn("Exception triggered in upstream ChannelHandler: {}", e.getCause()); 62 | this.listener.fireExceptionThrown(e.getCause()); 63 | } 64 | 65 | /** 66 | * Invoked when a Channel was disconnected from its remote peer. 67 | */ 68 | @Override 69 | public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 70 | //logger.info(e.toString()); 71 | //ctx.sendUpstream(e); 72 | } 73 | 74 | /** 75 | * Invoked when a Channel was unbound from the current local address. 76 | */ 77 | @Override 78 | public void channelUnbound(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 79 | //logger.info(e.toString()); 80 | } 81 | 82 | /** 83 | * Invoked when a Channel was closed and all its related resources were released. 84 | */ 85 | @Override 86 | public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { 87 | //logger.info(e.toString()); 88 | this.listener.fireChannelClosed(); 89 | } 90 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/impl/DefaultPduAsyncResponse.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.impl; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import com.cloudhopper.commons.util.windowing.WindowFuture; 25 | import com.cloudhopper.smpp.PduAsyncResponse; 26 | import com.cloudhopper.smpp.pdu.PduRequest; 27 | import com.cloudhopper.smpp.pdu.PduResponse; 28 | 29 | /** 30 | * Default implementation of an SmppAsyncResponse. 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public class DefaultPduAsyncResponse implements PduAsyncResponse { 35 | // we internally "wrap" a PDU window future 36 | private final WindowFuture future; 37 | 38 | public DefaultPduAsyncResponse(WindowFuture future) { 39 | this.future = future; 40 | } 41 | 42 | @Override 43 | public PduRequest getRequest() { 44 | return future.getRequest(); 45 | } 46 | 47 | @Override 48 | public PduResponse getResponse() { 49 | return future.getResponse(); 50 | } 51 | 52 | @Override 53 | public int getWindowSize() { 54 | return future.getWindowSize(); 55 | } 56 | 57 | @Override 58 | public long getWindowWaitTime() { 59 | return future.getOfferToAcceptTime(); 60 | } 61 | 62 | @Override 63 | public long getResponseTime() { 64 | return future.getAcceptToDoneTime(); 65 | } 66 | 67 | @Override 68 | public long getEstimatedProcessingTime() { 69 | long responseTime = getResponseTime(); 70 | if (responseTime == 0 || future.getWindowSize() == 0) { 71 | return 0; 72 | } 73 | return (responseTime / future.getWindowSize()); 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | StringBuilder buf = new StringBuilder(100); 79 | buf.append("smpp_async_resp: seqNum [0x"); 80 | buf.append(HexUtil.toHexString(this.future.getKey())); 81 | buf.append("] windowSize ["); 82 | buf.append(getWindowSize()); 83 | buf.append("] windowWaitTime ["); 84 | buf.append(getWindowWaitTime()); 85 | buf.append(" ms] responseTime ["); 86 | buf.append(getResponseTime()); 87 | buf.append(" ms] estProcessingTime ["); 88 | buf.append(getEstimatedProcessingTime()); 89 | buf.append(" ms] reqType ["); 90 | buf.append(getRequest().getName()); 91 | buf.append("] respType ["); 92 | buf.append(getResponse().getName()); 93 | buf.append("]"); 94 | return buf.toString(); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/impl/DefaultSmppSessionCounters.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.impl; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppSessionCounters; 24 | import com.cloudhopper.smpp.util.ConcurrentCommandCounter; 25 | 26 | /** 27 | * Default implementation of a SmppServerCounters interface. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class DefaultSmppSessionCounters implements SmppSessionCounters { 32 | 33 | private ConcurrentCommandCounter txSubmitSM; 34 | private ConcurrentCommandCounter txDeliverSM; 35 | private ConcurrentCommandCounter txEnquireLink; 36 | private ConcurrentCommandCounter txDataSM; 37 | private ConcurrentCommandCounter rxSubmitSM; 38 | private ConcurrentCommandCounter rxDeliverSM; 39 | private ConcurrentCommandCounter rxEnquireLink; 40 | private ConcurrentCommandCounter rxDataSM; 41 | 42 | public DefaultSmppSessionCounters() { 43 | this.txSubmitSM = new ConcurrentCommandCounter(); 44 | this.txDeliverSM = new ConcurrentCommandCounter(); 45 | this.txEnquireLink = new ConcurrentCommandCounter(); 46 | this.txDataSM = new ConcurrentCommandCounter(); 47 | this.rxSubmitSM = new ConcurrentCommandCounter(); 48 | this.rxDeliverSM = new ConcurrentCommandCounter(); 49 | this.rxEnquireLink = new ConcurrentCommandCounter(); 50 | this.rxDataSM = new ConcurrentCommandCounter(); 51 | } 52 | 53 | @Override 54 | public void reset() { 55 | this.txSubmitSM.reset(); 56 | this.txDeliverSM.reset(); 57 | this.txEnquireLink.reset(); 58 | this.txDataSM.reset(); 59 | this.rxSubmitSM.reset(); 60 | this.rxDeliverSM.reset(); 61 | this.rxEnquireLink.reset(); 62 | this.rxDataSM.reset(); 63 | } 64 | 65 | @Override 66 | public ConcurrentCommandCounter getRxDataSM() { 67 | return rxDataSM; 68 | } 69 | 70 | @Override 71 | public ConcurrentCommandCounter getRxDeliverSM() { 72 | return rxDeliverSM; 73 | } 74 | 75 | @Override 76 | public ConcurrentCommandCounter getRxEnquireLink() { 77 | return rxEnquireLink; 78 | } 79 | 80 | @Override 81 | public ConcurrentCommandCounter getRxSubmitSM() { 82 | return rxSubmitSM; 83 | } 84 | 85 | @Override 86 | public ConcurrentCommandCounter getTxDataSM() { 87 | return txDataSM; 88 | } 89 | 90 | @Override 91 | public ConcurrentCommandCounter getTxDeliverSM() { 92 | return txDeliverSM; 93 | } 94 | 95 | @Override 96 | public ConcurrentCommandCounter getTxEnquireLink() { 97 | return txEnquireLink; 98 | } 99 | 100 | @Override 101 | public ConcurrentCommandCounter getTxSubmitSM() { 102 | return txSubmitSM; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/impl/SmppSessionChannelListener.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.impl; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | 25 | /** 26 | * Interface for listening for events on an SmppSessionChannelHandler. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public interface SmppSessionChannelListener { 31 | 32 | /** 33 | * Fired when a PDU was successfully decoded and received on this Channel. 34 | * @param pdu The PDU decoded from the Channel 35 | */ 36 | public void firePduReceived(Pdu pdu); 37 | 38 | /** 39 | * Fired when an exception was raised by an I/O thread or an upstream handler. 40 | * @param t The exception thrown 41 | */ 42 | public void fireExceptionThrown(Throwable t); 43 | 44 | /** 45 | * Fired when the Channel is closed (reached EOF or timed out) 46 | */ 47 | public void fireChannelClosed(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/jmx/DefaultSmppServerMXBean.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.jmx; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.SmppChannelException; 24 | 25 | /** 26 | * Defines the interface for managing an SmppServer. 27 | * 28 | * @author joelauer 29 | */ 30 | public interface DefaultSmppServerMXBean { 31 | 32 | public boolean isStarted(); 33 | 34 | public boolean isStopped(); 35 | 36 | public boolean isDestroyed(); 37 | 38 | public void start() throws SmppChannelException; 39 | 40 | public void stop(); 41 | 42 | public void destroy(); 43 | 44 | // access to various configuration, stats, and counters useful for monitoring 45 | 46 | public void resetCounters(); 47 | 48 | public int getSessionSize(); 49 | 50 | public int getTransceiverSessionSize(); 51 | 52 | public int getTransmitterSessionSize(); 53 | 54 | public int getReceiverSessionSize(); 55 | 56 | public int getMaxConnectionSize(); 57 | 58 | public int getConnectionSize(); 59 | 60 | public long getBindTimeout(); 61 | 62 | public boolean isNonBlockingSocketsEnabled(); 63 | 64 | public boolean isReuseAddress(); 65 | 66 | public int getChannelConnects(); 67 | 68 | public int getChannelDisconnects(); 69 | 70 | public int getBindTimeouts(); 71 | 72 | public int getBindRequested(); 73 | 74 | public int getSessionCreated(); 75 | 76 | public int getSessionDestroyed(); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/AlertNotification.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import org.jboss.netty.buffer.ChannelBuffer; 24 | 25 | import com.cloudhopper.commons.util.StringUtil; 26 | import com.cloudhopper.smpp.SmppConstants; 27 | import com.cloudhopper.smpp.type.Address; 28 | import com.cloudhopper.smpp.type.RecoverablePduException; 29 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 30 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 31 | import com.cloudhopper.smpp.util.PduUtil; 32 | 33 | public class AlertNotification extends Pdu { 34 | 35 | protected Address sourceAddress; 36 | protected Address esmeAddress; 37 | 38 | public AlertNotification(){ 39 | super( SmppConstants.CMD_ID_ALERT_NOTIFICATION, "alert_notification", true ); 40 | } 41 | 42 | public Address getSourceAddress() { 43 | return this.sourceAddress; 44 | } 45 | 46 | public void setSourceAddress(Address value) { 47 | this.sourceAddress = value; 48 | } 49 | 50 | public Address getEsmeAddress() { 51 | return this.esmeAddress; 52 | } 53 | 54 | public void setEsmeAddress(Address value) { 55 | this.esmeAddress = value; 56 | } 57 | 58 | @Override 59 | protected int calculateByteSizeOfBody(){ 60 | int bodyLength = 0; 61 | bodyLength += PduUtil.calculateByteSizeOfAddress(this.sourceAddress); 62 | bodyLength += PduUtil.calculateByteSizeOfAddress(this.esmeAddress); 63 | return bodyLength; 64 | } 65 | 66 | @Override 67 | public void readBody( ChannelBuffer buffer ) throws UnrecoverablePduException, RecoverablePduException{ 68 | this.sourceAddress = ChannelBufferUtil.readAddress(buffer); 69 | this.esmeAddress = ChannelBufferUtil.readAddress(buffer); 70 | } 71 | 72 | @Override 73 | public void writeBody( ChannelBuffer buffer ) throws UnrecoverablePduException, RecoverablePduException{ 74 | ChannelBufferUtil.writeAddress(buffer, this.sourceAddress); 75 | ChannelBufferUtil.writeAddress(buffer, this.esmeAddress); 76 | } 77 | 78 | @Override 79 | protected void appendBodyToString( StringBuilder buffer ){ 80 | buffer.append("( sourceAddr ["); 81 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.sourceAddress)); 82 | buffer.append("] esmeAddr ["); 83 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.esmeAddress)); 84 | buffer.append("])"); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BaseBindResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.commons.util.StringUtil; 26 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 27 | import com.cloudhopper.smpp.util.PduUtil; 28 | import org.jboss.netty.buffer.ChannelBuffer; 29 | 30 | /** 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public abstract class BaseBindResp extends PduResponse { 35 | 36 | private String systemId; 37 | 38 | public BaseBindResp(int commandId, String name) { 39 | super(commandId, name); 40 | } 41 | 42 | public void setSystemId(String value) { 43 | this.systemId = value; 44 | } 45 | 46 | public String getSystemId() { 47 | return this.systemId; 48 | } 49 | 50 | @Override 51 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 52 | // the body may or may not contain a systemId -- the helper utility 53 | // method will take care of returning null if there aren't any readable bytes 54 | this.systemId = ChannelBufferUtil.readNullTerminatedString(buffer); 55 | } 56 | 57 | @Override 58 | public int calculateByteSizeOfBody() { 59 | int bodyLength = 0; 60 | bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.systemId); 61 | return bodyLength; 62 | } 63 | 64 | @Override 65 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 66 | ChannelBufferUtil.writeNullTerminatedString(buffer, this.systemId); 67 | } 68 | 69 | @Override 70 | public void appendBodyToString(StringBuilder buffer) { 71 | buffer.append("systemId ["); 72 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.systemId)); 73 | buffer.append("]"); 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BaseSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.commons.util.StringUtil; 26 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 27 | import com.cloudhopper.smpp.util.PduUtil; 28 | import org.jboss.netty.buffer.ChannelBuffer; 29 | 30 | /** 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public abstract class BaseSmResp extends PduResponse { 35 | 36 | private String messageId; 37 | 38 | public BaseSmResp(int commandId, String name) { 39 | super(commandId, name); 40 | } 41 | 42 | public String getMessageId() { 43 | return this.messageId; 44 | } 45 | 46 | public void setMessageId(String value) { 47 | this.messageId = value; 48 | } 49 | 50 | @Override 51 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 52 | // the body may or may not contain a messageId -- the helper utility 53 | // method will take care of returning null if there aren't any readable bytes 54 | this.messageId = ChannelBufferUtil.readNullTerminatedString(buffer); 55 | } 56 | 57 | @Override 58 | public int calculateByteSizeOfBody() { 59 | int bodyLength = 0; 60 | bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.messageId); 61 | return bodyLength; 62 | } 63 | 64 | @Override 65 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 66 | // when this PDU was parsed, it's possible it was missing the messageId instead 67 | // of having a NULL messageId. If that's the case, the commandLength will be just 68 | // enough for the headers (and theoretically any optional TLVs). Don't try to 69 | // write the NULL byte for that case. 70 | // See special note in 4.4.2 of SMPP 3.4 spec 71 | if (!((buffer.writableBytes() == 0) && (this.messageId == null))) { 72 | ChannelBufferUtil.writeNullTerminatedString(buffer, this.messageId); 73 | } 74 | } 75 | 76 | @Override 77 | public void appendBodyToString(StringBuilder buffer) { 78 | buffer.append("(messageId ["); 79 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.messageId)); 80 | buffer.append("])"); 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindReceiver.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class BindReceiver extends BaseBind { 30 | 31 | public BindReceiver() { 32 | super(SmppConstants.CMD_ID_BIND_RECEIVER, "bind_receiver"); 33 | } 34 | 35 | @Override 36 | public BindReceiverResp createResponse() { 37 | BindReceiverResp resp = new BindReceiverResp(); 38 | resp.setSequenceNumber(this.getSequenceNumber()); 39 | return resp; 40 | } 41 | 42 | @Override 43 | public Class getResponseClass() { 44 | return BindReceiverResp.class; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindReceiverResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class BindReceiverResp extends BaseBindResp { 30 | 31 | public BindReceiverResp() { 32 | super(SmppConstants.CMD_ID_BIND_RECEIVER_RESP, "bind_receiver_resp"); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindTransceiver.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class BindTransceiver extends BaseBind { 30 | 31 | public BindTransceiver() { 32 | super(SmppConstants.CMD_ID_BIND_TRANSCEIVER, "bind_transceiver"); 33 | } 34 | 35 | @Override 36 | public BindTransceiverResp createResponse() { 37 | BindTransceiverResp resp = new BindTransceiverResp(); 38 | resp.setSequenceNumber(this.getSequenceNumber()); 39 | return resp; 40 | } 41 | 42 | @Override 43 | public Class getResponseClass() { 44 | return BindTransceiverResp.class; 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindTransceiverResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class BindTransceiverResp extends BaseBindResp { 30 | 31 | public BindTransceiverResp() { 32 | super(SmppConstants.CMD_ID_BIND_TRANSCEIVER_RESP, "bind_transceiver_resp"); 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindTransmitter.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class BindTransmitter extends BaseBind { 26 | 27 | public BindTransmitter() { 28 | super(SmppConstants.CMD_ID_BIND_TRANSMITTER, "bind_transmitter"); 29 | } 30 | 31 | @Override 32 | public BindTransmitterResp createResponse() { 33 | BindTransmitterResp resp = new BindTransmitterResp(); 34 | resp.setSequenceNumber(this.getSequenceNumber()); 35 | return resp; 36 | } 37 | 38 | @Override 39 | public Class getResponseClass() { 40 | return BindTransmitterResp.class; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/BindTransmitterResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class BindTransmitterResp extends BaseBindResp { 26 | 27 | public BindTransmitterResp() { 28 | super(SmppConstants.CMD_ID_BIND_TRANSMITTER_RESP, "bind_transmitter_resp"); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/CancelSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2013 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 26 | import org.jboss.netty.buffer.ChannelBuffer; 27 | 28 | /** 29 | * SMPP cancel_sm_resp implementation. 30 | * 31 | * @author chris.matthews 32 | */ 33 | public class CancelSmResp extends PduResponse { 34 | 35 | public CancelSmResp() { 36 | super(SmppConstants.CMD_ID_CANCEL_SM_RESP, "cancel_sm_resp"); 37 | } 38 | 39 | @Override 40 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 41 | // nothing 42 | } 43 | 44 | @Override 45 | public int calculateByteSizeOfBody() { 46 | return 0; 47 | } 48 | 49 | @Override 50 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 51 | // do nothing 52 | } 53 | 54 | @Override 55 | public void appendBodyToString(StringBuilder buffer) { 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/DataSm.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 26 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 27 | import com.cloudhopper.smpp.util.PduUtil; 28 | import org.jboss.netty.buffer.ChannelBuffer; 29 | 30 | public class DataSm extends BaseSm { 31 | 32 | public DataSm() { 33 | super(SmppConstants.CMD_ID_DATA_SM, "data_sm"); 34 | } 35 | 36 | @Override 37 | public DataSmResp createResponse() { 38 | DataSmResp resp = new DataSmResp(); 39 | resp.setSequenceNumber(this.getSequenceNumber()); 40 | return resp; 41 | } 42 | 43 | @Override 44 | public Class getResponseClass() { 45 | return DataSmResp.class; 46 | } 47 | 48 | @Override 49 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 50 | this.serviceType = ChannelBufferUtil.readNullTerminatedString(buffer); 51 | this.sourceAddress = ChannelBufferUtil.readAddress(buffer); 52 | this.destAddress = ChannelBufferUtil.readAddress(buffer); 53 | this.esmClass = buffer.readByte(); 54 | this.registeredDelivery = buffer.readByte(); 55 | this.dataCoding = buffer.readByte(); 56 | } 57 | 58 | @Override 59 | public int calculateByteSizeOfBody() { 60 | int bodyLength = 0; 61 | bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.serviceType); 62 | bodyLength += PduUtil.calculateByteSizeOfAddress(this.sourceAddress); 63 | bodyLength += PduUtil.calculateByteSizeOfAddress(this.destAddress); 64 | bodyLength += 3; // esmClass, regDelivery, dataCoding bytes 65 | return bodyLength; 66 | } 67 | 68 | @Override 69 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 70 | ChannelBufferUtil.writeNullTerminatedString(buffer, this.serviceType); 71 | ChannelBufferUtil.writeAddress(buffer, this.sourceAddress); 72 | ChannelBufferUtil.writeAddress(buffer, this.destAddress); 73 | buffer.writeByte(this.esmClass); 74 | buffer.writeByte(this.registeredDelivery); 75 | buffer.writeByte(this.dataCoding); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/DataSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class DataSmResp extends BaseSmResp { 26 | 27 | public DataSmResp() { 28 | super(SmppConstants.CMD_ID_DATA_SM_RESP, "data_sm_resp"); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/DeliverSm.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class DeliverSm extends BaseSm { 26 | 27 | public DeliverSm() { 28 | super(SmppConstants.CMD_ID_DELIVER_SM, "deliver_sm"); 29 | } 30 | 31 | @Override 32 | public DeliverSmResp createResponse() { 33 | DeliverSmResp resp = new DeliverSmResp(); 34 | resp.setSequenceNumber(this.getSequenceNumber()); 35 | return resp; 36 | } 37 | 38 | @Override 39 | public Class getResponseClass() { 40 | return DeliverSmResp.class; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/DeliverSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class DeliverSmResp extends BaseSmResp { 26 | 27 | public DeliverSmResp() { 28 | super(SmppConstants.CMD_ID_DELIVER_SM_RESP, "deliver_sm_resp"); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/EmptyBody.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import org.jboss.netty.buffer.ChannelBuffer; 26 | 27 | public abstract class EmptyBody extends PduRequest { 28 | 29 | public EmptyBody(int commandId, String name) { 30 | super(commandId, name); 31 | } 32 | 33 | @Override 34 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 35 | // no body 36 | } 37 | 38 | @Override 39 | public int calculateByteSizeOfBody() { 40 | return 0; // no body 41 | } 42 | 43 | @Override 44 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 45 | /// no body 46 | } 47 | 48 | @Override 49 | public void appendBodyToString(StringBuilder buffer) { 50 | // no body 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/EmptyBodyResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import org.jboss.netty.buffer.ChannelBuffer; 26 | 27 | public abstract class EmptyBodyResp extends PduResponse { 28 | 29 | public EmptyBodyResp(int commandId, String name) { 30 | super(commandId, name); 31 | } 32 | 33 | @Override 34 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 35 | // no body 36 | } 37 | 38 | @Override 39 | public int calculateByteSizeOfBody() { 40 | return 0; // no body 41 | } 42 | 43 | @Override 44 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 45 | // no body 46 | } 47 | 48 | @Override 49 | public void appendBodyToString(StringBuilder buffer) { 50 | // no body 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/EnquireLink.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class EnquireLink extends EmptyBody { 26 | 27 | public EnquireLink() { 28 | super(SmppConstants.CMD_ID_ENQUIRE_LINK, "enquire_link"); 29 | } 30 | 31 | @Override 32 | public EnquireLinkResp createResponse() { 33 | EnquireLinkResp resp = new EnquireLinkResp(); 34 | resp.setSequenceNumber(this.getSequenceNumber()); 35 | return resp; 36 | } 37 | 38 | @Override 39 | public Class getResponseClass() { 40 | return EnquireLinkResp.class; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/EnquireLinkResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class EnquireLinkResp extends EmptyBodyResp { 26 | 27 | public EnquireLinkResp() { 28 | super(SmppConstants.CMD_ID_ENQUIRE_LINK_RESP, "enquire_link_resp"); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/GenericNack.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.smpp.SmppConstants; 26 | import org.jboss.netty.buffer.ChannelBuffer; 27 | 28 | public class GenericNack extends PduResponse { 29 | 30 | public GenericNack() { 31 | super(SmppConstants.CMD_ID_GENERIC_NACK, "generic_nack"); 32 | } 33 | 34 | @Override 35 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 36 | // no body 37 | } 38 | 39 | @Override 40 | public int calculateByteSizeOfBody() { 41 | return 0; // no body 42 | } 43 | 44 | @Override 45 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 46 | /// no body 47 | } 48 | 49 | @Override 50 | public void appendBodyToString(StringBuilder buffer) { 51 | // no body 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/PartialPdu.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | public class PartialPdu extends EmptyBody { 24 | 25 | public PartialPdu(int commandId) { 26 | super(commandId, "partial_pdu"); 27 | } 28 | 29 | @Override 30 | public GenericNack createResponse() { 31 | GenericNack resp = new GenericNack(); 32 | resp.setSequenceNumber(this.getSequenceNumber()); 33 | return resp; 34 | } 35 | 36 | @Override 37 | public Class getResponseClass() { 38 | return GenericNack.class; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/PartialPduResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | public class PartialPduResp extends EmptyBodyResp { 24 | 25 | public PartialPduResp(int commandId) { 26 | super(commandId, "partial_pdu_resp"); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/PduRequest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | public abstract class PduRequest extends Pdu { 24 | 25 | public PduRequest(int commandId, String name) { 26 | super(commandId, name, true); 27 | } 28 | 29 | abstract public R createResponse(); 30 | 31 | abstract public Class getResponseClass(); 32 | 33 | public GenericNack createGenericNack(int commandStatus) { 34 | GenericNack nack = new GenericNack(); 35 | nack.setCommandStatus(commandStatus); 36 | nack.setSequenceNumber(this.getSequenceNumber()); 37 | return nack; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/PduResponse.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | public abstract class PduResponse extends Pdu { 24 | 25 | private String resultMessage; 26 | 27 | public PduResponse(int commandId, String name) { 28 | super(commandId, name, false); 29 | } 30 | 31 | public void setResultMessage(String value) { 32 | this.resultMessage = value; 33 | } 34 | 35 | public String getResultMessage() { 36 | return this.resultMessage; 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/QuerySm.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2013 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.StringUtil; 24 | import com.cloudhopper.smpp.SmppConstants; 25 | import com.cloudhopper.smpp.type.Address; 26 | import com.cloudhopper.smpp.type.RecoverablePduException; 27 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 28 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 29 | import com.cloudhopper.smpp.util.PduUtil; 30 | import org.jboss.netty.buffer.ChannelBuffer; 31 | 32 | /** 33 | * SMPP query_sm implementation. 34 | * 35 | * @author chris.matthews 36 | */ 37 | public class QuerySm extends PduRequest { 38 | 39 | private String messageId; 40 | private Address sourceAddress; 41 | 42 | public QuerySm() { 43 | super(SmppConstants.CMD_ID_QUERY_SM, "query_sm"); 44 | } 45 | 46 | public String getMessageId() { 47 | return this.messageId; 48 | } 49 | 50 | public void setMessageId(String value) { 51 | this.messageId = value; 52 | } 53 | 54 | public Address getSourceAddress() { 55 | return this.sourceAddress; 56 | } 57 | 58 | public void setSourceAddress(Address value) { 59 | this.sourceAddress = value; 60 | } 61 | 62 | 63 | @Override 64 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 65 | this.messageId = ChannelBufferUtil.readNullTerminatedString(buffer); 66 | this.sourceAddress = ChannelBufferUtil.readAddress(buffer); 67 | } 68 | 69 | @Override 70 | public int calculateByteSizeOfBody() { 71 | int bodyLength = 0; 72 | bodyLength += PduUtil.calculateByteSizeOfNullTerminatedString(this.messageId); 73 | bodyLength += PduUtil.calculateByteSizeOfAddress(this.sourceAddress); 74 | return bodyLength; 75 | } 76 | 77 | @Override 78 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 79 | ChannelBufferUtil.writeNullTerminatedString(buffer, this.messageId); 80 | ChannelBufferUtil.writeAddress(buffer, this.sourceAddress); 81 | } 82 | 83 | @Override 84 | public void appendBodyToString(StringBuilder buffer) { 85 | buffer.append("(messageId ["); 86 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.messageId)); 87 | buffer.append("] sourceAddr ["); 88 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.sourceAddress)); 89 | buffer.append("])"); 90 | 91 | } 92 | 93 | @Override 94 | public QuerySmResp createResponse() { 95 | QuerySmResp resp = new QuerySmResp(); 96 | resp.setSequenceNumber(this.getSequenceNumber()); 97 | return resp; 98 | } 99 | 100 | @Override 101 | public Class getResponseClass() { 102 | return QuerySmResp.class; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/ReplaceSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import org.jboss.netty.buffer.ChannelBuffer; 24 | 25 | import com.cloudhopper.smpp.SmppConstants; 26 | import com.cloudhopper.smpp.type.RecoverablePduException; 27 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 28 | 29 | public class ReplaceSmResp extends PduResponse { 30 | 31 | public ReplaceSmResp() { 32 | super(SmppConstants.CMD_ID_REPLACE_SM_RESP, "replace_sm_resp"); 33 | } 34 | 35 | @Override 36 | public void readBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 37 | // nothing 38 | } 39 | 40 | @Override 41 | public int calculateByteSizeOfBody() { 42 | return 0; 43 | } 44 | 45 | @Override 46 | public void writeBody(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 47 | // do nothing 48 | } 49 | 50 | @Override 51 | public void appendBodyToString(StringBuilder buffer) { 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/SubmitMultiResp.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.cloudhopper.smpp.pdu; 5 | 6 | /* 7 | * #%L 8 | * ch-smpp 9 | * %% 10 | * Copyright (C) 2009 - 2013 Cloudhopper by Twitter 11 | * %% 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | * #L% 24 | */ 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | import org.jboss.netty.buffer.ChannelBuffer; 30 | 31 | import com.cloudhopper.smpp.SmppConstants; 32 | import com.cloudhopper.smpp.type.Address; 33 | import com.cloudhopper.smpp.type.RecoverablePduException; 34 | import com.cloudhopper.smpp.type.SmppInvalidArgumentException; 35 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 36 | import com.cloudhopper.smpp.type.UnsucessfulSME; 37 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 38 | import com.cloudhopper.smpp.util.PduUtil; 39 | 40 | /** 41 | * @author Amit Bhayani 42 | * 43 | */ 44 | public class SubmitMultiResp extends BaseSmResp { 45 | 46 | private int numberOfUnsucessfulDest; 47 | private List unsucessfulSmes = new ArrayList(); 48 | 49 | /** 50 | * @param commandId 51 | * @param name 52 | */ 53 | public SubmitMultiResp() { 54 | super(SmppConstants.CMD_ID_SUBMIT_MULTI_RESP, "submit_multi_resp"); 55 | } 56 | 57 | public void addUnsucessfulSME(UnsucessfulSME unsucessfulSME) 58 | throws SmppInvalidArgumentException { 59 | this.numberOfUnsucessfulDest++; 60 | this.unsucessfulSmes.add(unsucessfulSME); 61 | } 62 | 63 | public int getNumberOfUnsucessfulDest() { 64 | return numberOfUnsucessfulDest; 65 | } 66 | 67 | public List getUnsucessfulSmes() { 68 | return unsucessfulSmes; 69 | } 70 | 71 | @Override 72 | public void readBody(ChannelBuffer buffer) 73 | throws UnrecoverablePduException, RecoverablePduException { 74 | super.readBody(buffer); 75 | 76 | this.numberOfUnsucessfulDest = buffer.readByte() & 0xFF; 77 | 78 | for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { 79 | Address address = ChannelBufferUtil.readAddress(buffer); 80 | int errorStatusCode = buffer.readInt(); 81 | 82 | this.unsucessfulSmes.add(new UnsucessfulSME(errorStatusCode, 83 | address)); 84 | 85 | } 86 | } 87 | 88 | @Override 89 | public int calculateByteSizeOfBody() { 90 | int bodyLength = 0; 91 | bodyLength = super.calculateByteSizeOfBody(); 92 | 93 | bodyLength += 1; // no_unsuccess 94 | 95 | for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { 96 | UnsucessfulSME unsucessfulSME = this.unsucessfulSmes.get(count); 97 | bodyLength += PduUtil.calculateByteSizeOfAddress(unsucessfulSME 98 | .getAddress()); 99 | bodyLength += 4; // error_status_code 100 | } 101 | 102 | return bodyLength; 103 | } 104 | 105 | @Override 106 | public void writeBody(ChannelBuffer buffer) 107 | throws UnrecoverablePduException, RecoverablePduException { 108 | super.writeBody(buffer); 109 | 110 | buffer.writeByte(this.numberOfUnsucessfulDest); 111 | 112 | for (int count = 0; count < this.numberOfUnsucessfulDest; count++) { 113 | UnsucessfulSME unsucessfulSME = this.unsucessfulSmes.get(count); 114 | ChannelBufferUtil.writeAddress(buffer, unsucessfulSME.getAddress()); 115 | buffer.writeInt(unsucessfulSME.getErrorStatusCode()); 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/SubmitSm.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class SubmitSm extends BaseSm { 26 | 27 | public SubmitSm() { 28 | super(SmppConstants.CMD_ID_SUBMIT_SM, "submit_sm"); 29 | } 30 | 31 | @Override 32 | public SubmitSmResp createResponse() { 33 | SubmitSmResp resp = new SubmitSmResp(); 34 | resp.setSequenceNumber(this.getSequenceNumber()); 35 | return resp; 36 | } 37 | 38 | @Override 39 | public Class getResponseClass() { 40 | return SubmitSmResp.class; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/SubmitSmResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class SubmitSmResp extends BaseSmResp { 26 | 27 | public SubmitSmResp() { 28 | super(SmppConstants.CMD_ID_SUBMIT_SM_RESP, "submit_sm_resp"); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/Unbind.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | public class Unbind extends EmptyBody { 26 | 27 | public Unbind() { 28 | super(SmppConstants.CMD_ID_UNBIND, "unbind"); 29 | } 30 | 31 | @Override 32 | public UnbindResp createResponse() { 33 | UnbindResp resp = new UnbindResp(); 34 | resp.setSequenceNumber(this.getSequenceNumber()); 35 | return resp; 36 | } 37 | 38 | @Override 39 | public Class getResponseClass() { 40 | return UnbindResp.class; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/pdu/UnbindResp.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.type.RecoverablePduException; 25 | import com.cloudhopper.smpp.SmppConstants; 26 | import org.jboss.netty.buffer.ChannelBuffer; 27 | 28 | public class UnbindResp extends EmptyBodyResp { 29 | 30 | public UnbindResp() { 31 | super(SmppConstants.CMD_ID_UNBIND_RESP, "unbind_resp"); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/simulator/SmppSimulatorBindProcessor.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.simulator; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | import com.cloudhopper.smpp.pdu.BaseBind; 25 | import com.cloudhopper.smpp.pdu.BaseBindResp; 26 | import com.cloudhopper.smpp.pdu.Pdu; 27 | import com.cloudhopper.smpp.pdu.PduRequest; 28 | import org.jboss.netty.channel.Channel; 29 | 30 | /** 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public class SmppSimulatorBindProcessor implements SmppSimulatorPduProcessor { 35 | 36 | private String systemId; 37 | private String password; 38 | 39 | public SmppSimulatorBindProcessor(String systemId, String password) { 40 | this.systemId = systemId; 41 | this.password = password; 42 | } 43 | 44 | @Override 45 | public boolean process(SmppSimulatorSessionHandler session, Channel channel, Pdu pdu) throws Exception { 46 | // anything other than a bind is super bad! 47 | if (!(pdu instanceof BaseBind)) { 48 | if (pdu instanceof PduRequest) { 49 | session.addPduToWriteOnNextPduReceived(((PduRequest)pdu).createGenericNack(SmppConstants.STATUS_INVBNDSTS)); 50 | return true; 51 | } else { 52 | //logger.error("PDU response received, but not bound"); 53 | channel.close(); 54 | return true; 55 | } 56 | } 57 | 58 | BaseBind bind = (BaseBind)pdu; 59 | BaseBindResp bindResp = (BaseBindResp)bind.createResponse(); 60 | 61 | if (!bind.getSystemId().equals(systemId)) { 62 | bindResp.setCommandStatus(SmppConstants.STATUS_INVSYSID); 63 | } else if (!bind.getPassword().equals(password)) { 64 | bindResp.setCommandStatus(SmppConstants.STATUS_INVPASWD); 65 | } 66 | 67 | session.addPduToWriteOnNextPduReceived(bindResp); 68 | return true; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/simulator/SmppSimulatorPduProcessor.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.simulator; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | import org.jboss.netty.channel.Channel; 25 | 26 | /** 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public interface SmppSimulatorPduProcessor { 31 | 32 | public boolean process(SmppSimulatorSessionHandler session, Channel channel, Pdu pdu) throws Exception; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/tlv/TlvConvertException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.tlv; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.RecoverablePduException; 24 | 25 | /** 26 | * Thrown when attempting to cast a TLV value into a different type such as a 27 | * byte, string, etc. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class TlvConvertException extends RecoverablePduException { 32 | static final long serialVersionUID = 1L; 33 | 34 | public TlvConvertException(String msg) { 35 | super(msg); 36 | } 37 | 38 | public TlvConvertException(String typeName, String extraMsg) { 39 | super("Unable to cast TLV value into " + typeName + ": " + extraMsg); 40 | } 41 | 42 | public TlvConvertException(String msg, Throwable t) { 43 | super(msg, t); 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/transcoder/DefaultPduTranscoderContext.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.transcoder; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * Provides a default context for a PduTranscoder by looking everything up 27 | * using SMPP constants or default settings. An "override" context can be 28 | * supplied in the constructor. By default, this context will then attempt 29 | * to call the overridden context and any null value returned will then be 30 | * looked up using standard rules. 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public class DefaultPduTranscoderContext implements PduTranscoderContext { 35 | 36 | private final PduTranscoderContext overrideContext; 37 | 38 | public DefaultPduTranscoderContext() { 39 | this(null); 40 | } 41 | 42 | public DefaultPduTranscoderContext(PduTranscoderContext overrideContext) { 43 | this.overrideContext = overrideContext; 44 | } 45 | 46 | @Override 47 | public String lookupResultMessage(int commandStatus) { 48 | String resultMessage = null; 49 | if (overrideContext != null) { 50 | resultMessage = overrideContext.lookupResultMessage(commandStatus); 51 | } 52 | if (resultMessage == null) { 53 | resultMessage = SmppConstants.STATUS_MESSAGE_MAP.get(new Integer(commandStatus)); 54 | } 55 | return resultMessage; 56 | } 57 | 58 | @Override 59 | public String lookupTlvTagName(short tag) { 60 | String tagName = null; 61 | if (overrideContext != null) { 62 | tagName = overrideContext.lookupTlvTagName(tag); 63 | } 64 | if (tagName == null) { 65 | tagName = SmppConstants.TAG_NAME_MAP.get(new Short(tag)); 66 | } 67 | return tagName; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/transcoder/PduTranscoder.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.transcoder; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 25 | import com.cloudhopper.smpp.type.RecoverablePduException; 26 | import org.jboss.netty.buffer.ChannelBuffer; 27 | 28 | /** 29 | * Interface for encoding/decoding PDUs to/from ChannelBuffers. 30 | * 31 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 32 | */ 33 | public interface PduTranscoder { 34 | 35 | /** 36 | * Encodes a PDU into a new ChannelBuffer. 37 | * @param pdu The PDU to convert into a buffer 38 | * @return The new ChannelBuffer ready to send on a Channel 39 | * @throws UnrecoverablePduEncodingException Thrown if there is an unrecoverable 40 | * error while encoding the buffer. Recommended action is to rebind 41 | * the session. 42 | * @throws RecoverablePduEncodingException Thrown if there is recoverable 43 | * error while encoding the buffer. A good example is an optional parameter 44 | * that is invalid or a terminating null byte wasn't found. 45 | */ 46 | public ChannelBuffer encode(Pdu pdu) throws UnrecoverablePduException, RecoverablePduException; 47 | 48 | /** 49 | * Decodes a ChannelBuffer into a new PDU. 50 | * @param buffer The buffer to read data from 51 | * @return The new PDU created from the data 52 | * @throws UnrecoverablePduEncodingException Thrown if there is an unrecoverable 53 | * error while decoding the buffer. Recommended action is to rebind 54 | * the session. 55 | * @throws RecoverablePduEncodingException Thrown if there is recoverable 56 | * error while decoding the buffer. A good example is an optional parameter 57 | * that is invalid or a terminating null byte wasn't found. 58 | */ 59 | public Pdu decode(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException; 60 | 61 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/transcoder/PduTranscoderContext.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.transcoder; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Interface for providing a "context" to the transcoding process for SMPP PDUs. 25 | * For example, custom status messages, sequence number validators, or custom 26 | * TLV tag names, and other logic in the future. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public interface PduTranscoderContext { 31 | 32 | /** 33 | * Lookup a "command_status" value and returns a String that represents a result 34 | * message (description) of what the value means. A way to add helpful 35 | * debugging information into logfiles or management interfaces. This value 36 | * is printed out via the toString() method for a PDU response. 37 | * 38 | * @param commandStatus The command_status field to lookup 39 | * @return A String representing a short description of what the command_status 40 | * value represents. For example, a command_status of 0 usually means "OK" 41 | */ 42 | public String lookupResultMessage(int commandStatus); 43 | 44 | /** 45 | * Lookup a name for the tag of a TLV and returns a String that represents a 46 | * name for it. A way to add helpful debugging information into logfiles or 47 | * management interfaces. 48 | * 49 | * @param tag The TLV's tag value to lookup 50 | * @return A String representing a short name of what the tag 51 | * value represents. For example, a tag of 0x001E usually means "receipted_message_id" 52 | */ 53 | public String lookupTlvTagName(short tag); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/Address.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import com.cloudhopper.commons.util.StringUtil; 25 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 26 | import com.cloudhopper.smpp.util.PduUtil; 27 | import org.jboss.netty.buffer.ChannelBuffer; 28 | 29 | /** 30 | * Simple representation of an Address in SMPP. 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public class Address { 35 | 36 | private byte ton; 37 | private byte npi; 38 | private String address; 39 | 40 | public Address() { 41 | this((byte)0, (byte)0, (String)null); 42 | } 43 | 44 | public Address(byte ton, byte npi, String address) { 45 | this.ton = ton; 46 | this.npi = npi; 47 | this.address = address; 48 | } 49 | 50 | public byte getTon() { 51 | return this.ton; 52 | } 53 | 54 | public void setTon(byte value) { 55 | this.ton = value; 56 | } 57 | 58 | public byte getNpi() { 59 | return this.npi; 60 | } 61 | 62 | public void setNpi(byte value) { 63 | this.npi = value; 64 | } 65 | 66 | public String getAddress() { 67 | return this.address; 68 | } 69 | 70 | public void setAddress(String value) { 71 | this.address = value; 72 | } 73 | 74 | public int calculateByteSize() { 75 | return 2 + PduUtil.calculateByteSizeOfNullTerminatedString(this.address); 76 | } 77 | 78 | public void read(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 79 | this.ton = buffer.readByte(); 80 | this.npi = buffer.readByte(); 81 | this.address = ChannelBufferUtil.readNullTerminatedString(buffer); 82 | } 83 | 84 | public void write(ChannelBuffer buffer) throws UnrecoverablePduException, RecoverablePduException { 85 | buffer.writeByte(this.ton); 86 | buffer.writeByte(this.npi); 87 | ChannelBufferUtil.writeNullTerminatedString(buffer, this.address); 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | StringBuilder buffer = new StringBuilder(40); 93 | buffer.append("0x"); 94 | buffer.append(HexUtil.toHexString(this.ton)); 95 | buffer.append(" 0x"); 96 | buffer.append(HexUtil.toHexString(this.npi)); 97 | buffer.append(" ["); 98 | buffer.append(StringUtil.toStringWithNullAsEmpty(this.address)); 99 | buffer.append("]"); 100 | return buffer.toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/GenericNackException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import com.cloudhopper.smpp.pdu.GenericNack; 25 | 26 | /** 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class GenericNackException extends RecoverablePduException { 31 | static final long serialVersionUID = 1L; 32 | 33 | public GenericNackException(GenericNack nack) { 34 | super(buildErrorMessage(nack)); 35 | } 36 | 37 | static public String buildErrorMessage(GenericNack nack) { 38 | return "Negative acknowledgement for request [error: 0x" + HexUtil.toHexString(nack.getCommandStatus()) + " \"" + nack.getResultMessage() + "\"]"; 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/LoggingOptions.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * 25 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 26 | */ 27 | public class LoggingOptions { 28 | 29 | public static final int LOG_PDU = 0x00000001; 30 | public static final int LOG_BYTES = 0x00000002; 31 | public static final int DEFAULT_LOG_OPTION = LOG_PDU; 32 | 33 | private int option; 34 | 35 | public LoggingOptions() { 36 | this.option = DEFAULT_LOG_OPTION; 37 | } 38 | 39 | public void setLogPdu(boolean value) { 40 | if (value) { 41 | this.option |= LOG_PDU; 42 | } else { 43 | this.option &= ~LOG_PDU; 44 | } 45 | } 46 | 47 | public boolean isLogPduEnabled() { 48 | return ((this.option & LOG_PDU) > 0); 49 | } 50 | 51 | public void setLogBytes(boolean value) { 52 | if (value) { 53 | this.option |= LOG_BYTES; 54 | } else { 55 | this.option &= ~LOG_BYTES; 56 | } 57 | } 58 | 59 | public boolean isLogBytesEnabled() { 60 | return ((this.option & LOG_BYTES) > 0); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/NotEnoughDataInBufferException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Exception that represents more data is required in order to parse an SMPP PDU. 25 | * In as many cases as possible, this exception should include an 26 | * estimate of how many bytes are needed/missing in order to succeed in parsing. 27 | * An estimate of -1 represents an uknown amount of data. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class NotEnoughDataInBufferException extends RecoverablePduException { 32 | static final long serialVersionUID = 1L; 33 | 34 | private int available; 35 | private int expected; 36 | 37 | /** 38 | * Constructs an instance of AtNotEnoughDataInBufferException 39 | * with the specified detail message and estimated number of bytes required. 40 | * An estimate of -1 represents an unknown amount. 41 | * @param msg the detail message. 42 | * @param available Number of bytes that were available 43 | * @param expected Number of bytes expected or -1 if unknown 44 | */ 45 | public NotEnoughDataInBufferException(int available, int expected) { 46 | this(null, available, expected); 47 | } 48 | 49 | /** 50 | * Constructs an instance of AtNotEnoughDataInBufferException 51 | * with the specified detail message and estimated number of bytes required. 52 | * An estimate of -1 represents an unknown amount. 53 | * @param msg the detail message. 54 | * @param available Number of bytes that were available 55 | * @param expected Number of bytes expected or -1 if unknown 56 | */ 57 | public NotEnoughDataInBufferException(String msg, int available, int expected) { 58 | super("Not enough data in byte buffer to complete encoding/decoding [expected: " + expected + ", available: " + available + "]" + (msg == null ? "" : ": " + msg)); 59 | this.available = available; 60 | this.expected = expected; 61 | } 62 | 63 | public int getAvailable() { 64 | return available; 65 | } 66 | 67 | public int getExpected() { 68 | return expected; 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/RecoverablePduException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | 25 | /** 26 | * Thrown when a recoverable PDU decoding error occurs. A recoverable PDU 27 | * error includes the partially decoded PDU in order to generate a negative 28 | * acknowledgement response (if needed). 29 | * 30 | * A good example is that the PDU header was read, but the body of the PDU 31 | * failed to parse correctly. 32 | * 33 | * The recommended action for "recoverable" errors is to return a NACK. 34 | * 35 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 36 | */ 37 | public class RecoverablePduException extends Exception { 38 | static final long serialVersionUID = 1L; 39 | 40 | private Pdu partialPdu; 41 | 42 | public RecoverablePduException(String msg) { 43 | super(msg); 44 | } 45 | 46 | public RecoverablePduException(String msg, Throwable t) { 47 | super(msg, t); 48 | } 49 | 50 | public RecoverablePduException(Pdu partialPdu, String msg) { 51 | super(msg); 52 | this.partialPdu = partialPdu; 53 | } 54 | 55 | public RecoverablePduException(Pdu partialPdu, String msg, Throwable t) { 56 | super(msg, t); 57 | this.partialPdu = partialPdu; 58 | } 59 | 60 | public void setPartialPdu(Pdu pdu) { 61 | this.partialPdu = pdu; 62 | } 63 | 64 | public Pdu getPartialPdu() { 65 | return this.partialPdu; 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppBindException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import com.cloudhopper.smpp.pdu.BaseBindResp; 25 | 26 | /** 27 | * Thrown only when a "bind" attempt fails and a BaseBindResp was returned. 28 | * This exception can only be created from the BaseBindResp instance which is 29 | * used to create the error message as well. 30 | *
31 | * If no BindResp was received and we timed out while waiting, then an 32 | * SmppTimeoutException or SmppConnectionException would have occurred, not this 33 | * specific error. The underlying status code and mapped message can be figured 34 | * out as well. 35 | * 36 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 37 | */ 38 | public class SmppBindException extends UnrecoverablePduException { 39 | static final long serialVersionUID = 1L; 40 | 41 | private final BaseBindResp bindResponse; 42 | 43 | public SmppBindException(BaseBindResp bindResponse) { 44 | super(buildErrorMessage(bindResponse)); 45 | this.bindResponse = bindResponse; 46 | } 47 | 48 | public BaseBindResp getBindResponse() { 49 | return this.bindResponse; 50 | } 51 | 52 | static public String buildErrorMessage(BaseBindResp bindResponse) { 53 | if (bindResponse == null) { 54 | return "Bind request failed (response was null)"; 55 | } else { 56 | return "Unable to bind [error: 0x" + HexUtil.toHexString(bindResponse.getCommandStatus()) + " \"" + bindResponse.getResultMessage() + "\"]"; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppChannelConnectException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown for exceptions occuring while attempting to connect to a remote 25 | * system and cannot complete within a period of time. 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class SmppChannelConnectException extends SmppChannelException { 30 | static final long serialVersionUID = 1L; 31 | 32 | public SmppChannelConnectException(String msg) { 33 | super(msg); 34 | } 35 | 36 | public SmppChannelConnectException(String msg, Throwable t) { 37 | super(msg, t); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppChannelConnectTimeoutException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown for exceptions occuring while attempting to connect to a remote 25 | * system and cannot complete within a period of time. 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class SmppChannelConnectTimeoutException extends SmppChannelConnectException { 30 | static final long serialVersionUID = 1L; 31 | 32 | public SmppChannelConnectTimeoutException(String msg) { 33 | super(msg); 34 | } 35 | 36 | public SmppChannelConnectTimeoutException(String msg, Throwable t) { 37 | super(msg, t); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppChannelException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown for exceptions occurring with the underlying Channel or TCP/IP 25 | * connection such as read/write errors, closed connections, etc. 26 | * 27 | * Its best to restart a session if this occurs. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class SmppChannelException extends Exception { 32 | static final long serialVersionUID = 1L; 33 | 34 | public SmppChannelException(String msg) { 35 | super(msg); 36 | } 37 | 38 | public SmppChannelException(String msg, Throwable t) { 39 | super(msg, t); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppConnectionConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | 25 | /** 26 | * Configuration to create a TCP/IP connection (Channel) for an SmppSession. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class SmppConnectionConfiguration { 31 | 32 | private String host; 33 | private int port; 34 | private long connectTimeout; 35 | 36 | public SmppConnectionConfiguration() { 37 | this(null, 0, SmppConstants.DEFAULT_CONNECT_TIMEOUT); 38 | } 39 | 40 | public SmppConnectionConfiguration(String host, int port, long connectTimeout) { 41 | this.host = host; 42 | this.port = port; 43 | this.connectTimeout = connectTimeout; 44 | } 45 | 46 | public void setHost(String value) { 47 | this.host = value; 48 | } 49 | 50 | public String getHost() { 51 | return this.host; 52 | } 53 | 54 | public void setPort(int value) { 55 | this.port = value; 56 | } 57 | 58 | public int getPort() { 59 | return this.port; 60 | } 61 | 62 | public void setConnectTimeout(long value) { 63 | this.connectTimeout = value; 64 | } 65 | 66 | public long getConnectTimeout() { 67 | return this.connectTimeout; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppInvalidArgumentException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown when an argument was used that is invalid. 25 | * 26 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 27 | */ 28 | public class SmppInvalidArgumentException extends RecoverablePduException { 29 | static final long serialVersionUID = 1L; 30 | 31 | public SmppInvalidArgumentException(String msg) { 32 | super(null, msg); 33 | } 34 | 35 | public SmppInvalidArgumentException(String msg, Throwable t) { 36 | super(null, msg, t); 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppProcessingException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | 25 | /** 26 | * Thrown for exceptions while processing an SMPP request. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class SmppProcessingException extends Exception { 31 | static final long serialVersionUID = 1L; 32 | 33 | private int errorCode; 34 | 35 | public SmppProcessingException(int errorCode) { 36 | this(errorCode, null); 37 | } 38 | 39 | public SmppProcessingException(int errorCode, String msg) { 40 | super("SMPP processing error [0x" + HexUtil.toHexString(errorCode) + "]" + (msg == null ? "" : " message [" + msg + "]")); 41 | this.errorCode = errorCode; 42 | } 43 | 44 | public int getErrorCode() { 45 | return this.errorCode; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/SmppTimeoutException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown specifically when an operation times out vs. some sort of underlying 25 | * I/O exception like the channel was closed. 26 | * 27 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 28 | */ 29 | public class SmppTimeoutException extends Exception { 30 | static final long serialVersionUID = 1L; 31 | 32 | public SmppTimeoutException(String msg) { 33 | super(msg); 34 | } 35 | 36 | public SmppTimeoutException(String msg, Throwable t) { 37 | super(msg, t); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/TerminatingNullByteNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * 25 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 26 | */ 27 | public class TerminatingNullByteNotFoundException extends RecoverablePduException { 28 | static final long serialVersionUID = 1L; 29 | 30 | public TerminatingNullByteNotFoundException(String msg) { 31 | super(msg); 32 | } 33 | 34 | public TerminatingNullByteNotFoundException(String msg, Throwable t) { 35 | super(msg, t); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/UnexpectedPduResponseException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import com.cloudhopper.smpp.pdu.PduResponse; 25 | 26 | /** 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class UnexpectedPduResponseException extends UnrecoverablePduException { 31 | static final long serialVersionUID = 1L; 32 | 33 | private final PduResponse responsePdu; 34 | 35 | public UnexpectedPduResponseException(PduResponse responsePdu) { 36 | super(buildErrorMessage(responsePdu)); 37 | this.responsePdu = responsePdu; 38 | } 39 | 40 | public PduResponse getResponsePdu() { 41 | return this.responsePdu; 42 | } 43 | 44 | static public String buildErrorMessage(PduResponse responsePdu) { 45 | return "Unexpected response PDU [" + responsePdu.getClass().getName() + "] [error: 0x" + HexUtil.toHexString(responsePdu.getCommandStatus()) + " \"" + responsePdu.getResultMessage() + "\"]"; 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/UnknownCommandIdException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.Pdu; 24 | 25 | /** 26 | * Thrown when an unsupported or invalid Command ID was decoded. This is likely 27 | * a recoverable error. The recommended action is to either return a NAK or 28 | * a specific SMPP error code. 29 | * 30 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 31 | */ 32 | public class UnknownCommandIdException extends RecoverablePduException { 33 | static final long serialVersionUID = 1L; 34 | 35 | public UnknownCommandIdException(Pdu partialPdu, String msg) { 36 | super(partialPdu, msg); 37 | } 38 | 39 | public UnknownCommandIdException(Pdu partialPdu, String msg, Throwable t) { 40 | super(partialPdu, msg, t); 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/UnrecoverablePduException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.type; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Thrown when an unrecoverable PDU decoding error occurs. A good example is 25 | * a PDU length that is so large its signed negative (31st bit is 1). This is 26 | * an impossible error and likely means something is drastically wrong with 27 | * the sequence of bytes. 28 | * 29 | * Another example is an invalid sequence number in an invalid range. If 30 | * an invalid sequenceNumber is used, the recommended action is to close the 31 | * session. 32 | * 33 | * The recommended action for an unrecoverable error is to close the SMPP 34 | * connection. 35 | * 36 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 37 | */ 38 | public class UnrecoverablePduException extends Exception { 39 | static final long serialVersionUID = 1L; 40 | 41 | public UnrecoverablePduException(String msg) { 42 | super(msg); 43 | } 44 | 45 | public UnrecoverablePduException(String msg, Throwable t) { 46 | super(msg, t); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/type/UnsucessfulSME.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.cloudhopper.smpp.type; 5 | 6 | /* 7 | * #%L 8 | * ch-smpp 9 | * %% 10 | * Copyright (C) 2009 - 2013 Cloudhopper by Twitter 11 | * %% 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | * #L% 24 | */ 25 | 26 | import org.jboss.netty.buffer.ChannelBuffer; 27 | 28 | import com.cloudhopper.smpp.util.ChannelBufferUtil; 29 | 30 | /** 31 | * @author Amit Bhayani 32 | * 33 | */ 34 | public class UnsucessfulSME { 35 | 36 | private int errorStatusCode; 37 | private Address address; 38 | 39 | /** 40 | * 41 | */ 42 | public UnsucessfulSME() { 43 | } 44 | 45 | public UnsucessfulSME(int errorStatusCode, Address address) { 46 | super(); 47 | this.errorStatusCode = errorStatusCode; 48 | this.address = address; 49 | } 50 | 51 | public int getErrorStatusCode() { 52 | return errorStatusCode; 53 | } 54 | 55 | public void setErrorStatusCode(int errorStatusCode) { 56 | this.errorStatusCode = errorStatusCode; 57 | } 58 | 59 | public Address getAddress() { 60 | return address; 61 | } 62 | 63 | public void setAddress(Address address) { 64 | this.address = address; 65 | } 66 | 67 | public void read(ChannelBuffer buffer) throws UnrecoverablePduException, 68 | RecoverablePduException { 69 | this.address = ChannelBufferUtil.readAddress(buffer); 70 | this.errorStatusCode = buffer.readInt(); 71 | } 72 | 73 | public void write(ChannelBuffer buffer) throws UnrecoverablePduException, 74 | RecoverablePduException { 75 | ChannelBufferUtil.writeAddress(buffer, this.address); 76 | buffer.writeInt(this.errorStatusCode); 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | StringBuilder buffer = new StringBuilder(44); 82 | buffer.append(this.address.toString()); 83 | buffer.append(" errorStatusCode ["); 84 | buffer.append(this.errorStatusCode); 85 | buffer.append("]"); 86 | return buffer.toString(); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/DaemonExecutors.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import java.util.concurrent.ExecutorService; 24 | import java.util.concurrent.Executors; 25 | import java.util.concurrent.ThreadFactory; 26 | 27 | /** 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class DaemonExecutors { 32 | 33 | /** 34 | * Utility method for creating a cached pool of "daemon" threads. A daemon 35 | * thread does not limit the JVM from exiting if they aren't shutdown. 36 | * @return A new cached pool of daemon threads 37 | */ 38 | static public ExecutorService newCachedDaemonThreadPool() { 39 | return Executors.newCachedThreadPool(new ThreadFactory() { 40 | @Override 41 | public Thread newThread(Runnable r) { 42 | Thread t = new Thread(r); 43 | t.setDaemon(true); 44 | return t; 45 | } 46 | }); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/DeliveryReceiptException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * 25 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 26 | */ 27 | public class DeliveryReceiptException extends Exception { 28 | 29 | /** 30 | * Constructs an instance of DeliveryReceiptException with the specified detail message. 31 | * @param msg the detail message. 32 | */ 33 | public DeliveryReceiptException(String msg) { 34 | super(msg); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/InvalidSequenceNumberException.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.type.UnrecoverablePduException; 24 | import com.cloudhopper.smpp.pdu.*; 25 | 26 | /** 27 | * Thrown if a sequence number is not valid. 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class InvalidSequenceNumberException extends UnrecoverablePduException { 32 | static final long serialVersionUID = 1L; 33 | 34 | public InvalidSequenceNumberException(String msg) { 35 | super(msg); 36 | } 37 | 38 | public InvalidSequenceNumberException(String msg, Throwable t) { 39 | super(msg, t); 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/PduUtil.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppConstants; 24 | import com.cloudhopper.smpp.type.Address; 25 | 26 | /** 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class PduUtil { 31 | 32 | /** 33 | * Calculates size of a "C-String" by returning the length of the String 34 | * plus 1 (for the NULL byte). If the parameter is null, will return 1. 35 | * @param value 36 | * @return 37 | */ 38 | static public int calculateByteSizeOfNullTerminatedString(String value) { 39 | if (value == null) { 40 | return 1; 41 | } 42 | return value.length() + 1; 43 | } 44 | 45 | /** 46 | * Calculates the byte size of an Address. Safe to call with nulls as a 47 | * parameter since this will then just return the size of an empty address. 48 | * @param value 49 | * @return 50 | */ 51 | static public int calculateByteSizeOfAddress(Address value) { 52 | if (value == null) { 53 | return SmppConstants.EMPTY_ADDRESS.calculateByteSize(); 54 | } else { 55 | return value.calculateByteSize(); 56 | } 57 | } 58 | 59 | static public boolean isRequestCommandId(int commandId) { 60 | // if the 31st bit is not set, this is a request 61 | return ((commandId & SmppConstants.PDU_CMD_ID_RESP_MASK) == 0); 62 | } 63 | 64 | static public boolean isResponseCommandId(int commandId) { 65 | // if the 31st bit is not set, this is a request 66 | return ((commandId & SmppConstants.PDU_CMD_ID_RESP_MASK) == SmppConstants.PDU_CMD_ID_RESP_MASK); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/SequenceNumber.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | /** 24 | * Utility class for atomically generating SMPP PDU sequence numbers. This 25 | * implementation will atomically increment the sequence number and wrap it 26 | * around back to 1 when it hits the max 0x7FFFFFFF. 27 | * 28 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 29 | */ 30 | public class SequenceNumber { 31 | 32 | // AT&T Wireless uses a sequence number of 0 to start. This violates SMPP 3.4 33 | // specifications of the valid range of sequence numbers, but we'll need 34 | // to permit it. 35 | public static final int MIN_VALUE = 0x00000000; 36 | public static final int DEFAULT_VALUE = 0x00000001; 37 | public static final int MAX_VALUE = 0x7FFFFFFF; 38 | 39 | private int value; 40 | 41 | public SequenceNumber() { 42 | this.value = DEFAULT_VALUE; 43 | } 44 | 45 | public SequenceNumber(int initialValue) throws InvalidSequenceNumberException { 46 | assertValid(initialValue); 47 | this.value = initialValue; 48 | } 49 | 50 | /** 51 | * Get the next number in this sequence's scheme. This method is synchronized 52 | * so its safe for multiple threads to call. 53 | */ 54 | synchronized public int next() { 55 | // the next value is the current value 56 | int nextValue = this.value; 57 | 58 | if (this.value == MAX_VALUE) { 59 | // wrap this around back to 1 60 | this.value = DEFAULT_VALUE; 61 | } else { 62 | this.value++; 63 | } 64 | 65 | return nextValue; 66 | } 67 | 68 | /** 69 | * Get the next number in this sequence's scheme without causing it to move 70 | * to the next-in-sequence. This method returns the number that will be 71 | * returned by the next call to next() without actually 72 | * increasing the sequence. Multiple calls to peek will 73 | * return the same number until a call to next() is made. 74 | */ 75 | synchronized public int peek() { 76 | return this.value; 77 | } 78 | 79 | /** 80 | * Reset the sequence scheme to the beginning of the sequence (min value 81 | * which is 1). 82 | */ 83 | synchronized public void reset() { 84 | this.value = DEFAULT_VALUE; 85 | } 86 | 87 | static public void assertValid(int sequenceNumber) throws InvalidSequenceNumberException { 88 | // turns out that some operators ignore the specifications and actually 89 | // use all 32 bits of the sequence number -- instead of validating it 90 | // we'll just assert that everything is valid 91 | /** 92 | if (sequenceNumber < MIN_VALUE || sequenceNumber > MAX_VALUE) { 93 | throw new InvalidSequenceNumberException("Sequence number [" + sequenceNumber + "] is not in range from " + MIN_VALUE + " to " + MAX_VALUE); 94 | } 95 | */ 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /src/main/java/com/cloudhopper/smpp/util/SmppSessionUtil.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppSession; 24 | import com.cloudhopper.smpp.pdu.GenericNack; 25 | import com.cloudhopper.smpp.pdu.PduRequest; 26 | import com.cloudhopper.smpp.pdu.PduResponse; 27 | import com.cloudhopper.smpp.type.GenericNackException; 28 | import com.cloudhopper.smpp.type.UnexpectedPduResponseException; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | /** 33 | * 34 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 35 | */ 36 | public class SmppSessionUtil { 37 | private static final Logger logger = LoggerFactory.getLogger(SmppSessionUtil.class); 38 | 39 | static public void close(SmppSession session) { 40 | if (session != null) { 41 | try { 42 | session.close(); 43 | } catch (Throwable t) { 44 | logger.warn("Unable to cleanly close session: {}", t); 45 | } 46 | } 47 | } 48 | 49 | /** 50 | * Asserts that a PDU response matches a PDU request. A good example is that 51 | * a PDU response may be a "Generic_Nack" to our request. 52 | * @param request The PDU request 53 | * @param response The PDU response 54 | * @throws GenericNackException Thrown if the response was a "Generic_Nack" 55 | * @throws UnexpectedPduResponseException Thrown if the response type did 56 | * not match the request type. For example, if the request was a 57 | * "submit_sm", but the response was "data_sm_resp". 58 | */ 59 | static public void assertExpectedResponse(PduRequest request, PduResponse response) throws GenericNackException, UnexpectedPduResponseException { 60 | if (request.getResponseClass().isInstance(response)) { 61 | return; 62 | } else if (response instanceof GenericNack) { 63 | throw new GenericNackException((GenericNack)response); 64 | } else { 65 | throw new UnexpectedPduResponseException(response); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/DeliveryReceiptMain.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.util.DeliveryReceipt; 24 | import org.joda.time.DateTimeZone; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | /** 29 | * 30 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 31 | */ 32 | public class DeliveryReceiptMain { 33 | private static final Logger logger = LoggerFactory.getLogger(DeliveryReceiptMain.class); 34 | 35 | static public void main(String[] args) throws Exception { 36 | //DeliveryReceipt dlr = DeliveryReceipt.parseShortMessage("id:4 sub:001 dlvrd:001 submit date:1006020051 done date:1006020051 stat:DELIVRD err:000 Text:Hello", DateTimeZone.UTC, true); 37 | 38 | //DeliveryReceipt dlr = DeliveryReceipt.parseShortMessage("sub:001 id:4 dlvrd:001 done date:1006020051 stat:DELIVRD submit date:1006020051 err:000 Text:Hello", DateTimeZone.UTC, true); 39 | 40 | //DeliveryReceipt dlr = DeliveryReceipt.parseShortMessage("sub:001 id:4 dlvrd:001 done date:1006020051 stat:DELIVRD submit date:1006020051 err:000 text:", DateTimeZone.UTC, true); 41 | 42 | DeliveryReceipt dlr = DeliveryReceipt.parseShortMessage("id:2E179B310EDE971B2760C72B7F026E1B submit date:20110314181534 done date:20110314181741 stat:DELIVRD err:0", DateTimeZone.UTC, false); 43 | 44 | logger.debug("{}", dlr); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/ParserMain.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.pdu.BufferHelper; 24 | import com.cloudhopper.smpp.pdu.Pdu; 25 | import com.cloudhopper.smpp.transcoder.DefaultPduTranscoder; 26 | import com.cloudhopper.smpp.transcoder.DefaultPduTranscoderContext; 27 | import com.cloudhopper.smpp.transcoder.PduTranscoder; 28 | import com.cloudhopper.smpp.transcoder.PduTranscoderContext; 29 | import org.jboss.netty.buffer.ChannelBuffer; 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | /** 34 | * 35 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 36 | */ 37 | public class ParserMain { 38 | private static final Logger logger = LoggerFactory.getLogger(ParserMain.class); 39 | 40 | static public void main(String[] args) throws Exception { 41 | PduTranscoderContext context = new DefaultPduTranscoderContext(); 42 | PduTranscoder transcoder = new DefaultPduTranscoder(context); 43 | ChannelBuffer buffer = BufferHelper.createBuffer("000000420000000400000000000000030001003633393238383032000101343439353133363139323035004000000000000000000774657374323232020B00020D05"); 44 | Pdu pdu = transcoder.decode(buffer); 45 | logger.debug("{}", pdu); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/SimulatorMain.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.impl.DefaultSmppSessionHandler; 24 | import com.cloudhopper.smpp.pdu.PduRequest; 25 | import com.cloudhopper.smpp.pdu.PduResponse; 26 | import com.cloudhopper.smpp.simulator.SmppSimulatorServer; 27 | import com.cloudhopper.smpp.simulator.SmppSimulatorSessionHandler; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | /** 32 | * 33 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 34 | */ 35 | public class SimulatorMain { 36 | private static final Logger logger = LoggerFactory.getLogger(SimulatorMain.class); 37 | 38 | static public void main(String[] args) throws Exception { 39 | SmppSimulatorServer server = new SmppSimulatorServer(); 40 | server.start(2776); 41 | logger.info("SMPP simulator server started"); 42 | 43 | // wait for a session 44 | logger.info("Waiting for the first smsc session within 30 seconds"); 45 | SmppSimulatorSessionHandler smscSession = server.pollNextSession(30000); 46 | 47 | logger.info("Successfully got an new session!"); 48 | 49 | System.out.println("Press any key to shutdown simulator server"); 50 | System.in.read(); 51 | 52 | server.stop(); 53 | } 54 | 55 | public static class SimulatorSmppSessionHandler extends DefaultSmppSessionHandler { 56 | 57 | public SimulatorSmppSessionHandler() { 58 | super(logger); 59 | } 60 | 61 | @Override 62 | public PduResponse firePduRequestReceived(PduRequest pduRequest) { 63 | // ignore for now (already logged) 64 | return pduRequest.createResponse(); 65 | } 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/SlowServerMain.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppServer; 24 | import com.cloudhopper.smpp.SmppServerConfiguration; 25 | import com.cloudhopper.smpp.SmppServerHandler; 26 | import com.cloudhopper.smpp.SmppServerSession; 27 | import com.cloudhopper.smpp.SmppSessionConfiguration; 28 | import com.cloudhopper.smpp.impl.DefaultSmppServer; 29 | import com.cloudhopper.smpp.impl.DefaultSmppSessionHandler; 30 | import com.cloudhopper.smpp.pdu.BaseBind; 31 | import com.cloudhopper.smpp.pdu.BaseBindResp; 32 | import com.cloudhopper.smpp.pdu.PduRequest; 33 | import com.cloudhopper.smpp.pdu.PduResponse; 34 | import com.cloudhopper.smpp.type.SmppProcessingException; 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | /** 39 | * 40 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 41 | */ 42 | public class SlowServerMain { 43 | private static final Logger logger = LoggerFactory.getLogger(SlowServerMain.class); 44 | 45 | private static final long DELAY_BEFORE_RESPONSE = 3000; 46 | 47 | static public void main(String[] args) throws Exception { 48 | SmppServerConfiguration configuration = new SmppServerConfiguration(); 49 | configuration.setPort(2776); 50 | configuration.setMaxConnectionSize(10); 51 | configuration.setNonBlockingSocketsEnabled(false); 52 | 53 | SmppServer smppServer = new DefaultSmppServer(configuration, new DefaultSmppServerHandler()); 54 | 55 | logger.info("About to start SMPP server"); 56 | smppServer.start(); 57 | logger.info("SMPP server started"); 58 | 59 | System.out.println("Press any key to stop server"); 60 | System.in.read(); 61 | 62 | logger.info("SMPP server stopping"); 63 | smppServer.stop(); 64 | logger.info("SMPP server stopped"); 65 | } 66 | 67 | public static class DefaultSmppServerHandler implements SmppServerHandler { 68 | @Override 69 | public void sessionBindRequested(Long sessionId, SmppSessionConfiguration sessionConfiguration, final BaseBind bindRequest) throws SmppProcessingException { 70 | // this name actually shows up as thread context.... 71 | sessionConfiguration.setName("Application.SMPP." + sessionId); 72 | } 73 | 74 | @Override 75 | public void sessionCreated(Long sessionId, SmppServerSession session, BaseBindResp preparedBindResponse) throws SmppProcessingException { 76 | logger.info("Session created: {}", session); 77 | // need to do something it now (flag we're ready) 78 | session.serverReady(new SlowSmppSessionHandler()); 79 | } 80 | 81 | @Override 82 | public void sessionDestroyed(Long sessionId, SmppServerSession session) { 83 | logger.info("Session destroyed: {}", session); 84 | } 85 | 86 | } 87 | 88 | public static class SlowSmppSessionHandler extends DefaultSmppSessionHandler { 89 | @Override 90 | public PduResponse firePduRequestReceived(PduRequest pduRequest) { 91 | try { 92 | Thread.sleep(DELAY_BEFORE_RESPONSE); 93 | } catch (Exception e) { } 94 | 95 | // ignore for now (already logged) 96 | return pduRequest.createResponse(); 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/Client.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppSession; 24 | import com.cloudhopper.smpp.SmppSessionConfiguration; 25 | 26 | public abstract class Client { 27 | 28 | protected volatile SmppSession smppSession; 29 | 30 | public SmppSessionConfiguration getConfiguration() { 31 | return smppSession.getConfiguration(); 32 | } 33 | 34 | public boolean isConnected() { 35 | SmppSession session = smppSession; 36 | if (session != null) { 37 | return session.isBound(); 38 | } 39 | return false; 40 | } 41 | 42 | public SmppSession getSession() { 43 | return smppSession; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/ClientSmppSessionHandler.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | 24 | import com.cloudhopper.smpp.SmppConstants; 25 | import com.cloudhopper.smpp.impl.DefaultSmppSessionHandler; 26 | import com.cloudhopper.smpp.pdu.*; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import java.io.IOException; 31 | import java.nio.channels.ClosedChannelException; 32 | 33 | public class ClientSmppSessionHandler extends DefaultSmppSessionHandler { 34 | 35 | private static final Logger logger = LoggerFactory.getLogger(ClientSmppSessionHandler.class); 36 | 37 | private OutboundClient client; 38 | private SmppClientMessageService smppClientMessageService; 39 | 40 | public ClientSmppSessionHandler(OutboundClient client, 41 | SmppClientMessageService smppClientMessageService) { 42 | super(logger); 43 | this.client = client; 44 | this.smppClientMessageService = smppClientMessageService; 45 | } 46 | 47 | @Override 48 | public void firePduRequestExpired(PduRequest pduRequest) { 49 | logger.warn("PDU request expired: {}", pduRequest); 50 | } 51 | 52 | @Override 53 | public PduResponse firePduRequestReceived(PduRequest request) { 54 | PduResponse response = null; 55 | try { 56 | if (request instanceof DeliverSm) { 57 | logger.info("request {}", request); 58 | response = smppClientMessageService.received(client, (DeliverSm) request); 59 | logger.info("response {}", response); 60 | } else { 61 | response = request.createResponse(); 62 | } 63 | } catch (Throwable e) { 64 | LoggingUtil.log(logger, e); 65 | response = request.createResponse(); 66 | response.setResultMessage(e.getMessage()); 67 | response.setCommandStatus(SmppConstants.STATUS_UNKNOWNERR); 68 | } 69 | 70 | return response; 71 | } 72 | 73 | /** 74 | * TODO not sure if we really need to call reconnect here 75 | */ 76 | @Override 77 | public void fireUnknownThrowable(Throwable t) { 78 | if (t instanceof ClosedChannelException) { 79 | logger.warn("Unknown throwable received, but it was a ClosedChannelException, executing reconnect" + " " 80 | + LoggingUtil.toString(client.getConfiguration())); 81 | client.scheduleReconnect(); 82 | } else if (t instanceof IOException) { 83 | logger.warn(t + " " + LoggingUtil.toString(client.getConfiguration())); 84 | //#fireChannelUnexpectedlyClosed will be called from a different place 85 | } else { 86 | logger.warn(String.valueOf(t) + " " + LoggingUtil.toString(client.getConfiguration()), t); 87 | } 88 | } 89 | 90 | @Override 91 | public void fireChannelUnexpectedlyClosed() { 92 | client.scheduleReconnect(); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/DummySmppClientMessageService.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | 24 | import com.cloudhopper.smpp.pdu.DeliverSm; 25 | import com.cloudhopper.smpp.pdu.PduResponse; 26 | 27 | public class DummySmppClientMessageService implements SmppClientMessageService { 28 | 29 | /** delivery receipt, or MO */ 30 | @Override 31 | public PduResponse received(OutboundClient client, DeliverSm deliverSm) { 32 | return deliverSm.createResponse(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/EnquireLinkTask.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.smpp.SmppSession; 24 | import com.cloudhopper.smpp.pdu.EnquireLink; 25 | import com.cloudhopper.smpp.pdu.EnquireLinkResp; 26 | import com.cloudhopper.smpp.type.SmppChannelException; 27 | import com.cloudhopper.smpp.type.SmppTimeoutException; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | class EnquireLinkTask implements Runnable { 32 | 33 | private static final Logger logger = LoggerFactory.getLogger(EnquireLinkTask.class); 34 | private OutboundClient client; 35 | private Integer enquireLinkTimeout; 36 | 37 | public EnquireLinkTask(OutboundClient client, Integer enquireLinkTimeout) { 38 | this.client = client; 39 | this.enquireLinkTimeout = enquireLinkTimeout; 40 | } 41 | 42 | @Override 43 | public void run() { 44 | SmppSession smppSession = client.getSession(); 45 | if (smppSession != null && smppSession.isBound()) { 46 | try { 47 | logger.debug("sending enquire_link"); 48 | EnquireLinkResp enquireLinkResp = smppSession.enquireLink(new EnquireLink(), enquireLinkTimeout); 49 | logger.debug("enquire_link_resp: {}", enquireLinkResp); 50 | } catch (SmppTimeoutException e) { 51 | logger.warn("Enquire link failed, executing reconnect; " + e); 52 | logger.debug("", e); 53 | client.scheduleReconnect(); 54 | } catch (SmppChannelException e) { 55 | logger.warn("Enquire link failed, executing reconnect; " + e); 56 | logger.debug("", e); 57 | client.scheduleReconnect(); 58 | } catch (InterruptedException e) { 59 | logger.info("Enquire link interrupted, probably killed by reconnecting"); 60 | } catch (Exception e) { 61 | logger.error("Enquire link failed, executing reconnect", e); 62 | client.scheduleReconnect(); 63 | } 64 | } else { 65 | logger.error("enquire link running while session is not connected"); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/LoggingUtil.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | 24 | import org.slf4j.Logger; 25 | 26 | import com.cloudhopper.smpp.SmppSessionConfiguration; 27 | 28 | public class LoggingUtil { 29 | 30 | public static String toString(SmppSessionConfiguration config) { 31 | StringBuilder sb = new StringBuilder(); 32 | sb.append("["); 33 | sb.append(config.getSystemId()); 34 | sb.append(":"); 35 | sb.append(config.getPassword()); 36 | 37 | sb.append(";"); 38 | 39 | sb.append(config.getHost()); 40 | sb.append(":"); 41 | sb.append(config.getPort()); 42 | 43 | sb.append(";"); 44 | sb.append(config.getType()); 45 | sb.append("]"); 46 | return sb.toString(); 47 | } 48 | 49 | public static String toString2(SmppSessionConfiguration config) { 50 | StringBuilder sb = new StringBuilder(); 51 | sb.append("["); 52 | 53 | sb.append(config.getName()); 54 | 55 | sb.append(";"); 56 | 57 | sb.append(config.getSystemId()); 58 | 59 | sb.append(";"); 60 | 61 | sb.append(config.getHost()); 62 | sb.append(":"); 63 | sb.append(config.getPort()); 64 | 65 | sb.append(";"); 66 | sb.append(config.getType()); 67 | sb.append("]"); 68 | return sb.toString(); 69 | } 70 | 71 | public static void log(Logger log, Throwable e) { 72 | log.warn(String.valueOf(e.getMessage()), e); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/ReconnectionDaemon.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import javax.annotation.PreDestroy; 27 | import java.util.concurrent.*; 28 | import java.util.concurrent.atomic.AtomicInteger; 29 | 30 | /** 31 | * #schedule cannot spawn more threads than corePoolSize, so the blocking work is done by separate executor 32 | */ 33 | public class ReconnectionDaemon { 34 | 35 | private static final Logger log = LoggerFactory.getLogger(ReconnectionDaemon.class); 36 | 37 | private static final ReconnectionDaemon RECONNECTION_DAEMON = new ReconnectionDaemon("0,5,15"); 38 | private static final long KEEP_ALIVE_TIME = 60L; 39 | 40 | private final String[] reconnectionPeriods; 41 | 42 | private final ThreadPoolExecutor executor; 43 | private final ScheduledExecutorService scheduledExecutorService; 44 | 45 | public ReconnectionDaemon(String reconnectionPeriods) { 46 | this.reconnectionPeriods = reconnectionPeriods.split(","); 47 | scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(getThreadFactory("ReconnectionSchedulerDaemon-")); 48 | 49 | executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, 50 | new SynchronousQueue(), getThreadFactory("ReconnectionExecutorDaemon-")); 51 | } 52 | 53 | private ThreadFactory getThreadFactory(final String name) { 54 | return new ThreadFactory() { 55 | 56 | private AtomicInteger sequence = new AtomicInteger(0); 57 | 58 | @Override 59 | public Thread newThread(Runnable r) { 60 | Thread t = new Thread(r); 61 | t.setName(name + sequence.getAndIncrement()); 62 | return t; 63 | } 64 | }; 65 | } 66 | 67 | public static ReconnectionDaemon getInstance() { 68 | return RECONNECTION_DAEMON; 69 | } 70 | 71 | public void scheduleReconnect(OutboundClient outboundClient, Integer failureCount, 72 | ReconnectionTask reconnectionTask) { 73 | long delay = getReconnectionPeriod(failureCount); 74 | log.info("Scheduling reconnect for {} in {} seconds", outboundClient, delay); 75 | scheduledExecutorService.schedule(new ScheduledTask(reconnectionTask), delay, 76 | TimeUnit.SECONDS); 77 | } 78 | 79 | private long getReconnectionPeriod(Integer failureCount) { 80 | String reconnectionPeriod; 81 | if (reconnectionPeriods.length > failureCount) { 82 | reconnectionPeriod = reconnectionPeriods[failureCount]; 83 | } else { 84 | reconnectionPeriod = reconnectionPeriods[reconnectionPeriods.length - 1]; 85 | } 86 | return Long.parseLong(reconnectionPeriod); 87 | } 88 | 89 | @PreDestroy 90 | public void shutdown() { 91 | executor.shutdown(); 92 | scheduledExecutorService.shutdown(); 93 | } 94 | 95 | private class ScheduledTask implements Runnable { 96 | 97 | private final Runnable task; 98 | 99 | public ScheduledTask(Runnable task) { 100 | this.task = task; 101 | } 102 | 103 | @Override 104 | public void run() { 105 | executor.execute(task); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/ReconnectionTask.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | public class ReconnectionTask implements Runnable { 24 | 25 | private final OutboundClient client; 26 | private Integer connectionFailedTimes; 27 | 28 | protected ReconnectionTask(OutboundClient client, Integer connectionFailedTimes) { 29 | this.client = client; 30 | this.connectionFailedTimes = connectionFailedTimes; 31 | } 32 | 33 | @Override 34 | public void run() { 35 | client.reconnect(connectionFailedTimes); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/demo/persist/SmppClientMessageService.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.demo.persist; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2014 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | 24 | import com.cloudhopper.smpp.pdu.DeliverSm; 25 | import com.cloudhopper.smpp.pdu.PduResponse; 26 | 27 | public interface SmppClientMessageService { 28 | 29 | PduResponse received(OutboundClient client, DeliverSm deliverSm); 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/pdu/BufferHelper.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import com.cloudhopper.commons.util.HexUtil; 24 | import org.jboss.netty.buffer.BigEndianHeapChannelBuffer; 25 | import org.jboss.netty.buffer.ChannelBuffer; 26 | 27 | /** 28 | * 29 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 30 | */ 31 | public class BufferHelper 32 | { 33 | 34 | static public ChannelBuffer createBuffer(byte[] bytes) throws Exception { 35 | return new BigEndianHeapChannelBuffer(bytes); 36 | } 37 | 38 | static public ChannelBuffer createBuffer(String hexString) throws Exception { 39 | return createBuffer(HexUtil.toByteArray(hexString)); 40 | } 41 | 42 | static public byte[] createByteArray(ChannelBuffer buffer) throws Exception { 43 | byte[] bytes = new byte[buffer.readableBytes()]; 44 | // temporarily read bytes from the buffer 45 | buffer.getBytes(buffer.readerIndex(), bytes); 46 | return bytes; 47 | } 48 | 49 | static public String createHexString(ChannelBuffer buffer) throws Exception { 50 | return HexUtil.toHexString(createByteArray(buffer)); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/pdu/PduTest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.pdu; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | // third party imports 24 | import org.junit.*; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | // my imports 29 | 30 | /** 31 | * 32 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 33 | */ 34 | public class PduTest { 35 | private static final Logger logger = LoggerFactory.getLogger(PduTest.class); 36 | 37 | @Test 38 | public void hasSequenceNumberAssigned() throws Exception { 39 | Pdu pdu0 = new EnquireLink(); 40 | 41 | Assert.assertEquals(false, pdu0.hasSequenceNumberAssigned()); 42 | 43 | pdu0.setSequenceNumber(0); 44 | 45 | Assert.assertEquals(true, pdu0.hasSequenceNumberAssigned()); 46 | 47 | pdu0.removeSequenceNumber(); 48 | 49 | Assert.assertEquals(false, pdu0.hasSequenceNumberAssigned()); 50 | Assert.assertEquals(0, pdu0.getSequenceNumber()); 51 | } 52 | 53 | @Test 54 | public void hasCommandLengthCalculatedAndSet() throws Exception { 55 | Pdu pdu0 = new EnquireLink(); 56 | 57 | Assert.assertEquals(false, pdu0.hasCommandLengthCalculated()); 58 | Assert.assertEquals(16, pdu0.calculateAndSetCommandLength()); 59 | Assert.assertEquals(true, pdu0.hasCommandLengthCalculated()); 60 | Assert.assertEquals(16, pdu0.getCommandLength()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/ssl/SslContextFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.ssl; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2013 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.security.KeyStore; 26 | import java.security.UnrecoverableKeyException; 27 | import org.junit.Assert; 28 | import org.junit.Test; 29 | 30 | public class SslContextFactoryTest { 31 | 32 | @Test 33 | public void testNoTsFileKs() throws Exception { 34 | SslConfiguration cf = new SslConfiguration(); 35 | cf.setKeyStorePath("src/test/resources/keystore"); 36 | cf.setKeyStorePassword("changeit"); 37 | cf.setKeyManagerPassword("changeit"); 38 | SslContextFactory factory = new SslContextFactory(cf); 39 | Assert.assertTrue(factory.getSslContext() != null); 40 | } 41 | 42 | @Test 43 | public void testNoTsNoKs() throws Exception { 44 | SslConfiguration cf = new SslConfiguration(); 45 | SslContextFactory factory = new SslContextFactory(cf); 46 | Assert.assertTrue(factory.getSslContext() != null); 47 | } 48 | 49 | @Test 50 | public void testFileTsFileKs() throws Exception { 51 | SslConfiguration cf = new SslConfiguration(); 52 | cf.setKeyStorePath("src/test/resources/keystore"); 53 | cf.setKeyStorePassword("changeit"); 54 | cf.setKeyManagerPassword("changeit"); 55 | cf.setTrustStorePath("src/test/resources/keystore"); 56 | cf.setTrustStorePassword("changeit"); 57 | SslContextFactory factory = new SslContextFactory(cf); 58 | Assert.assertTrue(factory.getSslContext() != null); 59 | } 60 | 61 | @Test 62 | public void testFileTsFileKsWrongPW() throws Exception { 63 | SslConfiguration cf = new SslConfiguration(); 64 | cf.setKeyStorePath("src/test/resources/keystore"); 65 | cf.setKeyStorePassword("bad_password"); 66 | cf.setKeyManagerPassword("changeit"); 67 | cf.setTrustStorePath("src/test/resources/keystore"); 68 | cf.setTrustStorePassword("changeit"); 69 | try { 70 | SslContextFactory factory = new SslContextFactory(cf); 71 | Assert.fail(); 72 | } catch(IOException e) { 73 | } 74 | } 75 | 76 | @Test 77 | public void testPathTsWrongPWPathKs() throws Exception { 78 | SslConfiguration cf = new SslConfiguration(); 79 | cf.setKeyStorePath("src/test/resources/keystore"); 80 | cf.setKeyStorePassword("changeit"); 81 | cf.setKeyManagerPassword("changeit"); 82 | cf.setTrustStorePath("src/test/resources/keystore"); 83 | cf.setTrustStorePassword("bad_password"); 84 | try { 85 | SslContextFactory factory = new SslContextFactory(cf); 86 | Assert.fail(); 87 | } catch(IOException e) { 88 | } 89 | } 90 | 91 | @Test 92 | public void testNoKeyConfig() throws Exception { 93 | try { 94 | SslConfiguration cf = new SslConfiguration(); 95 | cf.setTrustStorePath("src/test/resources/keystore"); 96 | SslContextFactory factory = new SslContextFactory(cf); 97 | Assert.fail(); 98 | } catch (IllegalStateException e) { 99 | } catch (Exception e) { 100 | Assert.fail("Unexpected exception"); 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/util/ConcurrentCommandStatusCounterTest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | /* 3 | * #%L 4 | * ch-smpp 5 | * %% 6 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 7 | * %% 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * #L% 20 | */ 21 | 22 | import com.cloudhopper.smpp.SmppConstants; 23 | import org.junit.Test; 24 | import static org.junit.Assert.assertEquals; 25 | 26 | /** 27 | * 28 | * @author Maria Farooq 29 | */ 30 | public class ConcurrentCommandStatusCounterTest { 31 | 32 | @Test 33 | public void incrementAndGetTest (){ 34 | ConcurrentCommandStatusCounter concurrentCommandStatusCounter = new ConcurrentCommandStatusCounter(); 35 | assertEquals(0, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 36 | assertEquals(0, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 37 | 38 | concurrentCommandStatusCounter.incrementAndGet(SmppConstants.STATUS_OK); 39 | assertEquals(0, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 40 | assertEquals(0, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 41 | 42 | 43 | concurrentCommandStatusCounter.incrementAndGet(SmppConstants.STATUS_INVDSTADR); 44 | assertEquals(1, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 45 | assertEquals(0, concurrentCommandStatusCounter.getServerErrorCounter().intValue()); 46 | 47 | 48 | concurrentCommandStatusCounter.incrementAndGet(SmppConstants.STATUS_INVSYSID); 49 | assertEquals(1, concurrentCommandStatusCounter.getClientErrorCounter().intValue()); 50 | assertEquals(1, concurrentCommandStatusCounter.getServerErrorCounter().intValue()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/util/SequenceNumberTest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | // third party imports 24 | import org.junit.*; 25 | 26 | // my imports 27 | 28 | /** 29 | * 30 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 31 | */ 32 | public class SequenceNumberTest { 33 | 34 | @Test 35 | public void usage() throws Exception { 36 | SequenceNumber seqNum = new SequenceNumber(); 37 | Assert.assertEquals(1, seqNum.next()); 38 | Assert.assertEquals(2, seqNum.next()); 39 | Assert.assertEquals(3, seqNum.next()); 40 | Assert.assertEquals(4, seqNum.next()); 41 | 42 | seqNum = new SequenceNumber(0x7FFFFFFF); 43 | Assert.assertEquals(0x7FFFFFFF, seqNum.next()); 44 | Assert.assertEquals(1, seqNum.next()); // wrap around 45 | Assert.assertEquals(2, seqNum.next()); 46 | Assert.assertEquals(3, seqNum.next()); 47 | 48 | Assert.assertEquals(4, seqNum.peek()); 49 | 50 | seqNum.reset(); 51 | 52 | Assert.assertEquals(1, seqNum.peek()); 53 | Assert.assertEquals(1, seqNum.next()); 54 | Assert.assertEquals(2, seqNum.next()); 55 | Assert.assertEquals(3, seqNum.next()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/cloudhopper/smpp/util/TlvUtilTest.java: -------------------------------------------------------------------------------- 1 | package com.cloudhopper.smpp.util; 2 | 3 | /* 4 | * #%L 5 | * ch-smpp 6 | * %% 7 | * Copyright (C) 2009 - 2015 Cloudhopper by Twitter 8 | * %% 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * #L% 21 | */ 22 | 23 | // third party imports 24 | import com.cloudhopper.commons.util.HexUtil; 25 | import com.cloudhopper.smpp.tlv.Tlv; 26 | import com.cloudhopper.smpp.tlv.TlvConvertException; 27 | import org.junit.*; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | // my imports 32 | 33 | /** 34 | * 35 | * @author joelauer (twitter: @jjlauer or http://twitter.com/jjlauer) 36 | */ 37 | public class TlvUtilTest { 38 | private static final Logger logger = LoggerFactory.getLogger(TlvUtilTest.class); 39 | 40 | @Test 41 | public void createNullTerminatedStringTlv() throws Exception { 42 | Tlv tlv0 = null; 43 | 44 | // null string should just be 0x00 45 | tlv0 = TlvUtil.createNullTerminatedStringTlv((short)0x0001, null, "ISO-8859-1"); 46 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 47 | Assert.assertArrayEquals(HexUtil.toByteArray("00"), tlv0.getValue()); 48 | 49 | tlv0 = TlvUtil.createNullTerminatedStringTlv((short)0x0001, "", "ISO-8859-1"); 50 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 51 | Assert.assertArrayEquals(HexUtil.toByteArray("00"), tlv0.getValue()); 52 | 53 | tlv0 = TlvUtil.createNullTerminatedStringTlv((short)0x0001, "a"); 54 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 55 | Assert.assertArrayEquals(HexUtil.toByteArray("6100"), tlv0.getValue()); 56 | 57 | tlv0 = TlvUtil.createNullTerminatedStringTlv((short)0x0001, "c1net"); 58 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 59 | Assert.assertArrayEquals(HexUtil.toByteArray("63316e657400"), tlv0.getValue()); 60 | } 61 | 62 | @Test 63 | public void createFixedLengthStringTlv() throws Exception { 64 | Tlv tlv0 = null; 65 | 66 | tlv0 = TlvUtil.createFixedLengthStringTlv((short)0x0001, null, 2, "ISO-8859-1"); 67 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 68 | Assert.assertArrayEquals(HexUtil.toByteArray("0000"), tlv0.getValue()); 69 | 70 | tlv0 = TlvUtil.createFixedLengthStringTlv((short)0x0001, "", 2); 71 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 72 | Assert.assertArrayEquals(HexUtil.toByteArray("0000"), tlv0.getValue()); 73 | 74 | tlv0 = TlvUtil.createFixedLengthStringTlv((short)0x0001, "1", 2, "ISO-8859-1"); 75 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 76 | Assert.assertArrayEquals(HexUtil.toByteArray("3100"), tlv0.getValue()); 77 | 78 | tlv0 = TlvUtil.createFixedLengthStringTlv((short)0x0001, "12", 2); 79 | Assert.assertEquals((short)0x0001, tlv0.getTag()); 80 | Assert.assertArrayEquals(HexUtil.toByteArray("3132"), tlv0.getValue()); 81 | 82 | try { 83 | tlv0 = TlvUtil.createFixedLengthStringTlv((short)0x0001, "12", 1, "ISO-8859-1"); 84 | Assert.fail(); 85 | } catch (TlvConvertException e) { 86 | // correct behavior 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/test/resources/keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RestComm/cloudhopper-smpp/99a45b7e9389c79566a369f0f1d7902f20027353/src/test/resources/keystore -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | 23 | 24 | System.err 25 | 26 | %-23d [%thread] %-5level %logger{32} - %m%n 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/test/resources/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICATCCAWoCCQCEwdEo1Uc29TANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB 3 | VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 4 | cyBQdHkgTHRkMB4XDTEzMDQxMDIzNTI1M1oXDTE0MDQxMDIzNTI1M1owRTELMAkG 5 | A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 6 | IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs9ao 7 | eqfWIKjMQ+hggOclu6/zftOrvoCcZ8HYoE5G2YOQuvT2zIcTDR5EHcMuhlkF/5SV 8 | ta4baG6EZdO/WE3sJcVjJ64/5gBAXAOzw+f/pNoPyEGnFzpJugKemy0WntdHZZ9h 9 | 83OO2iKdk1Oco+7qc7MFaItoQsempiQPniQa+uMCAwEAATANBgkqhkiG9w0BAQUF 10 | AAOBgQBxUQtSeudvSUFNZSR7QdW3Kh8Gb1+ay9LNnQ/rcW+5pXk88inHIIzIdjo9 11 | NUwhRNLRyQUzW7sHTOut5lEZpkkOTFopoa2lmwyw7pZqDoVm71aKmxoCK5nwC8t7 12 | O4cHK2mWeZ1moUuemdKQZFVMAGS8TBgTlCump311o/2qOzEZaw== 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /src/test/resources/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQCz1qh6p9YgqMxD6GCA5yW7r/N+06u+gJxnwdigTkbZg5C69PbM 3 | hxMNHkQdwy6GWQX/lJW1rhtoboRl079YTewlxWMnrj/mAEBcA7PD5/+k2g/IQacX 4 | Okm6Ap6bLRae10dln2Hzc47aIp2TU5yj7upzswVoi2hCx6amJA+eJBr64wIDAQAB 5 | AoGALzCboxvZb1Z7yzH16L0+xIJGJbiLb4C2Ce/u1RnVM4x3dOeEv2SOVjnj699k 6 | nPJNRaSKqFLYdE3TxhiLNDO2TD5fhCHdwN+bczNLX7FH2LRGgVNi7WNGLcFOKXkp 7 | WPke9zxcqTT6QiCw9upa2VrzzMFK7mb1pYPaGDOktdraWBkCQQDa1KSQ5n3OL6ue 8 | xHS4Nl+AJhu0dtbaHD4/lKZMINbH5x/yZ8Jl0YI16cWf0ERfSqIjCWLybYaWp23D 9 | y36YHkh1AkEA0mKHzFMg/StWojLGOQmYS8SGEm6g5USOiovq2v5LYVN+kPpJj9qf 10 | ju6cPsfOuFnXpknw/x0dji0dKvHTAgSK9wJBAIwmRiN7SzVjeIHdhnd4c1+KiJHi 11 | zqWwEvn7hSoamhQ7ZU2FwI4fSUqoJua8px10mjTgTRvAo8MXBgiw6qoYMwUCQQC1 12 | hbIpx6f1CMmtFSYW3IJ9DUmo6a8FYkuimuq+nR6pEQNpT6rc5gM5rgM93+QrB8mb 13 | frzjQVnY7G/4N8KaQRUtAkAaJnEV2MFXgKdiE8uLuGnrRBjRovDxM93H3zjlTAaO 14 | fSkL6WL8/g2RYrw2/W4WNu8I9Eqh0XlqSelFQYLd5FQE 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /src/test/resources/stunnel.conf: -------------------------------------------------------------------------------- 1 | client=no 2 | foreground=yes 3 | debug=7 4 | pid=/tmp/stunnel.pid 5 | cert=src/test/resources/server.crt 6 | key=src/test/resources/server.key 7 | [smpp] 8 | accept=2777 9 | connect=127.0.0.1:2776 10 | --------------------------------------------------------------------------------