Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client Not reciving DLR Report #244

Open
dotsinspace opened this issue Nov 11, 2023 · 0 comments
Open

Client Not reciving DLR Report #244

dotsinspace opened this issue Nov 11, 2023 · 0 comments

Comments

@dotsinspace
Copy link

dotsinspace commented Nov 11, 2023

I am in big trouble..I want to know why my client is only receiving submit_sm not deliver_sm. even though i tried online simulator for testing. it do shows me Deliver_sm ( https://melroselabs.com/tools/smppsender/?host=smscsim.melroselabs.com ) ..But in client dashboard it only shows Accepted ( Submit_sm ) not Delivered ( delivered_sm )

/*
 * IMPORTS
 */
import Debug from 'debug/src/node' // NPM: Debug module for debugging.
import Smpp from './node_modules/smpp' // NPM: Smpp module for handling Smpp connections.
import { Buffer } from 'safer-buffer' // NPM: Buffer module for handling buffers.
import _ from 'underscore' // NPM: Utility module for handling objects.
import { format } from 'fecha' // NPM: Date formatting module.


/*
 * PACKAGES
 */
import Context from 'context'
import Tag from 'tag'

const generateDeliverSmBuffer = (sequenceNumber, serviceType, sourceAddr, destAddr, shortMessage) => {
  // Command ID for deliver_sm
  const commandId = 0x00000005

  // Create a buffer to hold the PDU
  const buffer = Buffer.alloc(100) // Adjust the size as needed

  // Write the PDU fields to the buffer
  buffer.writeUInt32BE(buffer.length, 0) // Command Length
  buffer.writeUInt32BE(commandId, 4) // Command ID
  buffer.writeUInt32BE(0, 8) // Command Status (No Error)
  buffer.writeUInt32BE(sequenceNumber, 12) // Sequence Number

  // Service Type
  buffer.write(serviceType, 16, 'ascii')
  buffer.writeUInt8(0, 16 + serviceType.length) // Null-terminated

  // Source Address
  buffer.write(sourceAddr, 40, 'ascii')
  buffer.writeUInt8(0, 40 + sourceAddr.length) // Null-terminated

  // Destination Address
  buffer.write(destAddr, 70, 'ascii')
  buffer.writeUInt8(0, 70 + destAddr.length) // Null-terminated

  // Short Message
  buffer.write(shortMessage, 100, 'utf8')

  return buffer
}

/*
 * OBJECTS
 */
Smpp.createServer({ 'enable_proxy_protocol_detection': true, 'debug': global.WORKING_ENV.DEVELOPMENT.value !== global.CONFIG_RC.env }, __Session => {
  // Local variable.
  let _functionName

  // Const assignment.
  const _events = ['submit_sm', 'query_sm', 'cancel_sm', 'deliver_sm']

  // Object assignment.
  const _BindTransceiver = async __pdu => {
    // Create Context for incoming request.
    const _SharedContext = await Context({ 'request': __Session })

    console.log(__pdu)

    // Variable assignment.
    _functionName = 'WwwSmppBindTransceiver'

    // Error handling.
    try {
      /*
       * We pause the session to prevent further incoming pdu events,
       * until we authorize the session with some async operation.
       */
      __Session.pause()

      // Debug incoming request.
      _SharedContext.Debug({ 'message': `Bind request received from ${String.ipv6ToIpv4(__Session.remoteAddress)}`, 'status': 'BIND_TRANSCEIVER' }, _functionName)

      // Get smpp details from database.
      const _SmppFindMany = await _SharedContext.DataBase.smpp.findMany({ 'where': { 'ip': { 'equals': 'smscsim.melroselabs.com' } } })

      // If details are empty then report failure.
      if (_SmppFindMany instanceof Error || _.isEmpty(_SmppFindMany)) {
        // Style guide.
        await _SharedContext.Debug({ 'message': `Could not find smpp with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}`, 'error': _SmppFindMany instanceof Error ? _SmppFindMany : new Error('NO_SMPP_WITH_THIS_IP_FOUND') }, _functionName)

        // Close the session.
        return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RBINDFAIL }))
      }

      // Style Guide.
      await _SharedContext.Debug({ 'message': `Found ${_SmppFindMany.length} smpp with given username for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}.` }, _functionName)
      await _SharedContext.Debug({ 'message': `Looking for smpp with correct password for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      /*
       * Loop over all smpp details.
       * and look if any one smpp finds a match.
       */
      for await (const josh of _SmppFindMany) {
        // Respond with success if given username and password matches.
        if (josh.username === __pdu.system_id.toString() && josh.password === __pdu.password.toString()) {
          // Style guide.
          await _SharedContext.Debug({ 'message': `Found smpp with correct password for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)
          await _SharedContext.Debug({ 'message': `Responding ip: ${String.ipv6ToIpv4(__Session.remoteAddress)} with successful bind.` }, _functionName)

          // Send successful pdu response.
          __Session.send(__pdu.response({ 'command_status': Smpp.ESME_ROK }))

          // Resume the session.
          __Session.resume()

          // Debug incoming request.
          return _SharedContext.Debug({ 'message': `Bind request accepted from ${String.ipv6ToIpv4(__Session.remoteAddress)}`, 'status': 'BIND_TRANSCEIVER' }, _functionName)
        }
      }

      // Style guide.
      await _SharedContext.Debug({ 'message': `Could not find smpp with correct password for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      // Close the session.
      __Session.close()

      // Report failure.
      return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RBINDFAIL }))
    } catch (error) {
      // Report failure.
      _SharedContext.Debug({ error })

      // End the session.
      return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RBINDFAIL }))
    }
  }
  const _PushPDU = async (__command, __pdu) => {
    // Create Context for incoming request.
    const _SharedContext = await Context({ 'request': __Session })

    console.log(__command, __pdu)

    // Variable assignment.
    _functionName = 'WwwSmppSubmitSm'

    // Error handling.
    try {
      // Debug incoming request.
      _SharedContext.Debug({ 'message': `Message received from ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      // Get client by source and destination.
      const _RouteGet = _SharedContext.Route.get(Tag.Route.ClientByIp('smscsim.melroselabs.com'))

      // If route is empty then report failure.
      if (_.isEmpty(_RouteGet)) {
        // Style guide.
        await _SharedContext.Debug({ 'message': `Could not find client for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

        // Report failure.
        return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RSYSERR }))
      }

      // Style guide.
      await _SharedContext.Debug({ 'message': `Found client for given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      // Get pooled client.
      const _RouteGetUse = _RouteGet.use()

      // Style Guide.
      await _SharedContext.Debug({ 'message': `Pooled route from route pool for ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)
      await _SharedContext.Debug({ 'message': `Pushing pdu to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      // Push pdu to this route.
      const _RouteGetUsePush = await _RouteGetUse.Push(__command, __pdu)

      // If pushing pdu caught exception then report failure.
      if (_RouteGetUsePush instanceof Error) {
        // Style Guide.
        await _SharedContext.Debug({ 'message': `Failed to push pdu to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}`, 'error': _RouteGetUsePush }, _functionName)

        // Report failure.
        return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RSYSERR }))
      }

      // Style Guide.
      await _SharedContext.Debug({ 'message': `Successfully pushed pdu to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

      console.log(_RouteGetUsePush)
      // Respond with submit response.
      __Session.send(__pdu.response({ 'message_state': Smpp.ESME_ROK, 'message_id': _RouteGetUsePush.message_id }))

      // Report success.
      if ('submit_sm' === __command) {
        // Style Guide.
        await _SharedContext.Debug({ 'message': `Responding to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

        // Object assignment.
        const _DeliverSm = () => __Session.deliver_sm({
          'source_addr': __pdu.destination_addr,
          'destination_addr': __pdu.source_addr,
          'short_message': __pdu.short_message,
          'esm_class': 4,
          'delivery_state': 0,
          'message_id': _RouteGetUsePush.message_id,
          'final_date': new Date(),
          'message_state': 'DELIVERED',
          'receipted_message_id': _RouteGetUsePush.message_id,
          'text': _RouteGetUsePush.message
        })

        // Handle registered delivery accordingly.
        if (1 === __pdu.registered_delivery) {
          // Respond with receipt.
          _DeliverSm()
        } else if (2 === __pdu.registered_delivery) {
          /*
           * Only response with receipt if
           * error has been occurred.
           */
          if (0 !== _RouteGetUsePush.command_status) {
            // Respond with receipt.
            _DeliverSm()
          }
        } else if (3 === __pdu.registered_delivery) {
          // Only respond back if no error has been occurred.
          if (0 === _RouteGetUsePush.command_status) {
            // Respond with receipt.
            _DeliverSm()
          }
        }
      } else if ('query_sm' === __command) {
        // Style Guide.
        await _SharedContext.Debug({ 'message': `Responding to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

        // Respond with success.
        __Session.send(__pdu.response({
          'message_id': __pdu.message_id,
          'final_date': new Date(),
          'message_state': 'DELIVERED',
          'receipted_message_id': __pdu.message_id,
          'text': _RouteGetUsePush.message
        }))
      } else if ('cancel_sm' === __command) {
        // Style Guide.
        await _SharedContext.Debug({ 'message': `Responding to client with given ip: ${String.ipv6ToIpv4(__Session.remoteAddress)}` }, _functionName)

        // Respond with success.
        __Session.send(__pdu.response({ 'message_state': Smpp.ESME_ROK }))
      }

      // Recycle route.
      return _RouteGet.recycle(_RouteGetUse)
    } catch (error) {
      // Report failure.
      _SharedContext.Debug({ error })

      // Report failure that pdu has not been sent.
      return __Session.send(__pdu.response({ 'command_status': Smpp.ESME_RSYSERR }))
    }
  }

  // Smpp handler for handling server bind.
  __Session.on('bind_transceiver', _BindTransceiver)

  // Loop over events which can be handled by Route.
  _events.forEach(_event => __Session.on(_event, __pdu => _PushPDU(_event, __pdu)))

  // Other common events to listen on.
  __Session.on('error', async error => {
    // Create Context for incoming request.
    const _SharedContext = await Promise.resolve(Context(__Session))

    // Handle errors
    _SharedContext.Debug({ error })

    // Close smpp connection and return success.
    __Session.close()
  })
  __Session.on('unbind', pdu => {
    // Close smpp connection and return success.
    __Session.send(pdu.response())
    __Session.close()
  })
  __Session.on('enquire_link', __pdu => __Session.send(__pdu.response()))
  __Session.on('close', () => __Session.close())
}).listen(global.CONFIG_RC.smppPort, () => Debug('WwwSmpp')(`=> Executing => Running on ${global.CONFIG_RC.smppPort}`))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant