/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.axis2.transport.sms.smpp; import org.jsmpp.session.*; import org.jsmpp.util.MessageId; import org.jsmpp.util.MessageIDGenerator; import org.jsmpp.util.RandomMessageIDGenerator; import org.jsmpp.bean.*; import org.jsmpp.extra.ProcessRequestException; import org.jsmpp.PDUStringException; import org.jsmpp.SMPPConstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeoutException; import java.io.IOException; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * This is a simulator of a Shot message service center * this is written for the test perposes of the SMPP * implementation of the SMS Transport * */ public class SimpleSMSC extends ServerResponseDeliveryAdapter implements Runnable, ServerMessageReceiverListener { private static final Integer DEFAULT_PORT = 2776; private static final Logger logger = LoggerFactory.getLogger(SimpleSMSC.class); private final ExecutorService execService = Executors.newFixedThreadPool(5); private final MessageIDGenerator messageIDGenerator = new RandomMessageIDGenerator(); private int port = DEFAULT_PORT; private SMSCMessageNotifier notifier; private boolean started =false; private SMPPServerSession serverSession = null; private Semaphore control = new Semaphore(0); public SimpleSMSC() { notifier = SMSCMessageNotifier.getInstence(); } /** * Delever short message to a bineded ESMC s * @param sender * @param receiver * @param content * @throws Exception */ public void deliverSMS(String sender , String receiver , String content) throws Exception{ this.serverSession.deliverShortMessage( "CMT", TypeOfNumber.UNKNOWN , NumberingPlanIndicator.UNKNOWN , receiver , TypeOfNumber.UNKNOWN , NumberingPlanIndicator.UNKNOWN , sender , new ESMClass() , (byte)0 , (byte)0, new RegisteredDelivery(0), DataCoding.newInstance(0), content.getBytes()); } public void run() { try { SMPPServerSessionListener sessionListener = null; sessionListener = new SMPPServerSessionListener(port); logger.info("Simple SMSC Listening on port :: " + port); control.release(); while (true) { serverSession = sessionListener.accept(); serverSession.setMessageReceiverListener(this); serverSession.setResponseDeliveryListener(this); // TODO: quick fix for build instability; if not set, the Hudson build // may fail with a message such as "No response after waiting for 2000 millis // when executing deliver_sm with sessionId 8cc2b5f5 and sequenceNumber 1" serverSession.setTransactionTimer(10000); execService.execute(new WaitBindTask(serverSession)); Thread.sleep(1000); } } catch (Exception e) { logger.error("IO error occured", e); } } public MessageId onAcceptSubmitSm(SubmitSm submitSm, SMPPServerSession smppServerSession) throws ProcessRequestException { MessageId messageId = messageIDGenerator.newMessageId(); notifier.notifyObservers(submitSm); return messageId; } public SubmitMultiResult onAcceptSubmitMulti(SubmitMulti submitMulti, SMPPServerSession smppServerSession) throws ProcessRequestException { return null; } public QuerySmResult onAcceptQuerySm(QuerySm querySm, SMPPServerSession smppServerSession) throws ProcessRequestException { return null; } public void onAcceptReplaceSm(ReplaceSm replaceSm, SMPPServerSession smppServerSession) throws ProcessRequestException { } public void onAcceptCancelSm(CancelSm cancelSm, SMPPServerSession smppServerSession) throws ProcessRequestException { } public DataSmResult onAcceptDataSm(DataSm dataSm) throws ProcessRequestException { return null; } private class WaitBindTask implements Runnable { private final SMPPServerSession serverSession; public WaitBindTask(SMPPServerSession serverSession) { this.serverSession = serverSession; } public void run() { try { BindRequest bindRequest = serverSession.waitForBind(1000); logger.info("Accepting bind for session {}", serverSession.getSessionId()); try { bindRequest.accept("sys"); } catch (PDUStringException e) { logger.error("Invalid system id", e); bindRequest.reject(SMPPConstant.STAT_ESME_RSYSERR); } } catch (IllegalStateException e) { logger.error("System error", e); } catch (TimeoutException e) { logger.warn("Wait for bind has reach timeout", e); } catch (IOException e) { logger.error("Failed accepting bind request for session {}", serverSession.getSessionId()); } } } /** * Start the SimpleSMSC server */ public void startServer() { Thread t = new Thread(this); t.start(); } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public boolean isStarted() { return started; } public Semaphore getControl() { return control; } }