fonoster/routr

View on GitHub
mod/core/processor/request_processor.js

Summary

Maintainability
B
5 hrs
Test Coverage
/**
 * @author Pedro Sanders
 * @since v1
 */
const { sendResponse } = require('@routr/core/processor/processor_utils')
const RegisterHandler = require('@routr/core/processor/register_handler')
const RegistryHandler = require('@routr/core/processor/registry_handler')
const CancelHandler = require('@routr/core/processor/cancel_handler')
const RequestHandler = require('@routr/core/processor/request_handler')
const RouteInfo = require('@routr/core/processor/route_info')
const AclUtil = require('@routr/core/acl/acl_util')
const { RoutingType } = require('@routr/core/routing_type')
const { RouteEntityType } = require('@routr/core/route_entity_type')
const { Status } = require('@routr/core/status')
const config = require('@routr/core/config_util')()
const Request = Java.type('javax.sip.message.Request')
const Response = Java.type('javax.sip.message.Response')
const LogManager = Java.type('org.apache.logging.log4j.LogManager')
const LOG = LogManager.getLogger(Java.type('io.routr.core.Launcher'))

const globalACL = config.spec.accessControlList

class RequestProcessor {
  constructor (sipProvider, dataAPIs, contextStorage) {
    this.sipProvider = sipProvider
    this.contextStorage = contextStorage
    this.dataAPIs = dataAPIs
    this.domainsAPI = dataAPIs.DomainsAPI
    this.registryHandler = new RegistryHandler(sipProvider)
  }

  async process (event) {
    const request = event.getRequest()
    let transaction = event.getServerTransaction()

    if (
      transaction === null &&
      request.getMethod().equals(Request.ACK) === false
    ) {
      transaction = this.sipProvider.getNewServerTransaction(request)
    }

    const routeInfo = new RouteInfo(request, this.dataAPIs)

    const callee = routeInfo.getCallee()
    if (
      callee &&
      callee.spec &&
      callee.spec.credentials &&
      callee.spec.credentials.secret
    ) {
      callee.spec.credentials.secret = '****'
    }
    LOG.debug(
      `core.processor.RequestProcessor.process [route type ${routeInfo.getRoutingType()}]`
    )
    LOG.debug(
      `core.processor.RequestProcessor.process [entity info ${JSON.stringify(
        callee
      )}]`
    )

    // Warning: This is a very expensive function. Consider making it optional
    // Or optimize
    if (this.allowedAccess(event, routeInfo) === false) {
      LOG.debug(
        `core.processor.RequestProcessor.process [access denied for ${JSON.stringify(
          callee
        )}]`
      )
      return sendResponse(transaction, Response.FORBIDDEN)
    }

    LOG.debug(
      `core.processor.RequestProcessor.process [running handler for method \`${request.getMethod()}\`]`
    )

    switch (request.getMethod()) {
      case Request.PUBLISH:
      case Request.NOTIFY:
      case Request.SUBSCRIBE:
        sendResponse(transaction, Response.METHOD_NOT_ALLOWED)
        break
      case Request.REGISTER:
        if (
          !routeInfo.isLocalDomain() &&
          routeInfo.getCallerType() === RouteEntityType.THRU_GW
        ) {
          this.registryHandler.doProcess(transaction)
          break
        }
        new RegisterHandler().doProcess(transaction)
        break
      case Request.CANCEL:
        new CancelHandler().doProcess(transaction)
        break
      default:
        new RequestHandler(this.sipProvider, this.contextStorage).doProcess(
          transaction,
          request,
          routeInfo
        )
    }
  }

  allowedAccess (event, routeInfo) {
    const request = event.getRequest()
    const remoteIp = event.getRemoteIpAddress()

    if (globalACL) {
      if (new AclUtil(globalACL).isIpAllowed(remoteIp) === false) {
        return false
      }
    }

    if (routeInfo.getRoutingType().equals(RoutingType.INTRA_DOMAIN_ROUTING)) {
      const addressOfRecord = request.getRequestURI()
      const response = this.domainsAPI.getDomainByUri(addressOfRecord.getHost())
      if (response.status === Status.OK) {
        const acl = response.data.spec.context.accessControlList
        if (acl) {
          return new AclUtil(acl).isIpAllowed(remoteIp)
        }
      }
    }
    return true
  }
}

module.exports = RequestProcessor