private void connect() throws IOException { if (connected) { return; } final SlooceSMPPSession smpp = this; smppSession = new SMPPSession( new SynchronizedPDUSender(new DefaultPDUSender(new DefaultComposer())), new DefaultPDUReader(), new SlooceSMPPSocketConnectionFactory(useSSL)); smppSession.setEnquireLinkTimer( provider .getEnquireLinkTimer()); // Depends on the provider's inactivity timeout (actually, this // is the SMPP Socket Read Timeout before enquiring to keep the // link alive) smppSession.setTransactionTimer( provider .getTransactionTimer()); // Depends on the provider's response timeout (responses should // be returned within a second) smppSession.setMessageReceiverListener( new MessageReceiverListener() { @Override public void onAcceptDeliverSm(final DeliverSm deliverSm) throws ProcessRequestException { try { doAcceptDeliverSm(deliverSm); } catch (Throwable t) { logger.error( "Failed to process incoming SMPP message " + deliverSm.toDebugString(), t); } } public void doAcceptDeliverSm(final DeliverSm deliverSm) throws ProcessRequestException { final Alphabet alphabet = smpp.provider.getAlphabet(deliverSm, logger); if (MessageType.SMSC_DEL_RECEIPT.containedIn(deliverSm.getEsmClass())) { // this message is a delivery receipt try { final DeliveryReceipt delReceipt = deliverSm.getShortMessageAsDeliveryReceipt(); String messageId = delReceipt.getId(); if (smpp.provider.isMessageIdDecimal()) { // Provider sends the messageId in a delivery receipt as a decimal value string // per the SMPP spec. // Convert it to hex to match the messageId hex string returned when submitting // the MT. messageId = Long.toHexString(Long.valueOf(messageId)); } final String operator = getOptionalParameterValueAsString( OptionalParameters.get( smpp.provider.getOperatorTag(), deliverSm.getOptionalParameters())); final SlooceSMPPMessage mt = new SlooceSMPPMessage( messageId, deliverSm.getSourceAddr(), operator, deliverSm.getDestAddress()); String message; if (alphabet == Alphabet.ALPHA_DEFAULT) { message = SlooceSMPPUtil.fromGSMCharset(delReceipt.getText().getBytes()); } else { message = delReceipt.getText(); } mt.setMessage(message); logger.info( "Received delivery receipt - mt:{} dataCoding:{} alphabet:{} esmClass:0x{} {}{} - {}", mt, deliverSm.getDataCoding(), alphabet, conventBytesToHexString(new byte[] {deliverSm.getEsmClass()}), sanitizeCharacters(delReceipt.toString()), paramsToString(deliverSm.getOptionalParameters()), smpp.toShortString()); if (smpp.receiver != null) { smpp.receiver.deliveryReceipt( mt, delReceipt.getFinalStatus(), delReceipt.getError(), smpp); } } catch (InvalidDeliveryReceiptException e) { logger.error("Failed getting delivery receipt - " + smpp.toShortString(), e); } } else { // this message is an incoming MO final String messageId = getOptionalParameterValueAsString( deliverSm.getOptionalParameter(OptionalParameter.Tag.RECEIPTED_MESSAGE_ID)); final String operator = getOptionalParameterValueAsString( OptionalParameters.get( smpp.provider.getOperatorTag(), deliverSm.getOptionalParameters())); byte[] messageBytes = deliverSm.getShortMessage(); byte[] udhBytes = new byte[0]; final SlooceSMPPMessage mo = new SlooceSMPPMessage( messageId, deliverSm.getSourceAddr(), operator, deliverSm.getDestAddress()); final boolean hasUDHI = GSMSpecificFeature.UDHI.containedIn(deliverSm.getEsmClass()); if (hasUDHI) { final int udhLength = messageBytes[0]; udhBytes = new byte[udhLength + 1]; System.arraycopy(messageBytes, 0, udhBytes, 0, udhLength + 1); byte[] messageBytesCopy = new byte[messageBytes.length - udhLength - 1]; System.arraycopy( messageBytes, udhLength + 1, messageBytesCopy, 0, messageBytes.length - udhLength - 1); messageBytes = messageBytesCopy; if (udhBytes[1] == 0x00) { // Concatenated short messages, 8-bit reference number mo.setCsmsReference(udhBytes[3] & 0xff); mo.setCsmsTotalParts(udhBytes[4] & 0xff); mo.setCsmsPartNumber(udhBytes[5] & 0xff); } else if (udhBytes[1] == 0x08) { // Concatenated short messages, 16-bit reference number mo.setCsmsReference(((udhBytes[3] & 0xff) << 8) | (udhBytes[4] & 0xff)); mo.setCsmsTotalParts(udhBytes[5] & 0xff); mo.setCsmsPartNumber(udhBytes[6] & 0xff); } else { // unsupported logger.warn("Unsupported udh:{}", conventBytesToHexString(udhBytes)); } } String message; if (alphabet == Alphabet.ALPHA_DEFAULT) { message = SlooceSMPPUtil.fromGSMCharset(messageBytes); } else if (alphabet == Alphabet.ALPHA_UCS2) { try { message = new String(messageBytes, "UTF-16"); } catch (UnsupportedEncodingException e) { logger.warn(e.getMessage()); message = new String(messageBytes); } } else { try { message = new String(messageBytes, "ISO-8859-1"); } catch (UnsupportedEncodingException e) { logger.warn(e.getMessage()); message = new String(messageBytes); } } if (smpp.stripSystemType && smpp.systemType != null) { message = Pattern.compile(smpp.systemType + "\\s*", Pattern.CASE_INSENSITIVE) .matcher(message) .replaceFirst(""); } mo.setMessage(message); logger.info( "Received message - mo:{} dataCoding:{} alphabet:{} esmClass:0x{} udh:0x{}{} - {}", mo, deliverSm.getDataCoding(), alphabet, conventBytesToHexString(new byte[] {deliverSm.getEsmClass()}), conventBytesToHexString(udhBytes), paramsToString(deliverSm.getOptionalParameters()), smpp.toShortString()); if (smpp.receiver != null) { smpp.receiver.mo(mo, smpp); } } } private String getOptionalParameterValueAsString( final OptionalParameter optionalParameter) { if (optionalParameter == null) { return null; } if (optionalParameter instanceof OptionalParameter.OctetString) { return ((OptionalParameter.OctetString) optionalParameter).getValueAsString(); } else { throw new RuntimeException( "OptionalParameter type is not yet supported: " + optionalParameter.getClass()); } } @Override public void onAcceptAlertNotification(final AlertNotification alertNotification) {} @Override public DataSmResult onAcceptDataSm(final DataSm dataSm, final Session source) throws ProcessRequestException { return null; } }); smppSession.addSessionStateListener( new SessionStateListener() { @Override public void onStateChange( final SessionState newState, final SessionState oldState, final Session source) { if (newState.equals(SessionState.CLOSED)) { if (smpp.connected) { logger.warn("Session closed - {}", smpp); smpp.connected = false; new Thread() { @Override public void run() { smpp.receiver.onClose(smpp); } }.start(); } else { logger.info("Session was already closed - {}", smpp); } } } }); smppSession.connectAndBind( host, port, new BindParameter( BindType.BIND_TRX, systemId, password, systemType, TypeOfNumber.UNKNOWN, NumberingPlanIndicator.UNKNOWN, null)); connected = true; logger.info("Connected to {} using {}@{}:{} - {}", provider, systemId, host, port, smpp); }