From 67be394c536c6c66d364d75daf207605218cc56d Mon Sep 17 00:00:00 2001 From: Pedro Sanders Date: Thu, 29 Aug 2019 19:27:46 -0400 Subject: [PATCH] Workinf towards moving schema version from v1beta1 to v1 --- config/dids.yml | 12 ----- config/domains.yml | 2 +- config/gateways.yml | 11 +++++ config/stack.properties | 2 +- docs/administration/cli/cheatsheet.md | 34 +++++++------- docs/api/dids/create.md | 12 ++--- docs/api/dids/delete.md | 8 ++-- docs/api/dids/get.md | 8 ++-- docs/api/dids/list.md | 10 ++--- docs/api/dids/update.md | 12 ++--- docs/api/gateways/delete.md | 2 +- docs/concepts.md | 16 +++---- docs/configuration/domains.md | 6 +-- docs/configuration/gateways.md | 2 +- docs/configuration/general.md | 11 ++--- docs/configuration/{dids.md => numbers.md} | 20 ++++----- docs/guides/basic-setup.md | 16 +++---- docs/introduction/glossary.md | 2 +- etc/schemas/config_schema.json | 6 --- etc/schemas/gateways_schema.json | 1 + .../{dids_schema.json => numbers_schema.json} | 6 +-- mkdocs.yml | 14 +++--- mod/core/account_manager_service.js | 5 ++- mod/core/config_util.js | 7 ++- mod/core/main.js | 4 +- mod/core/processor/request_handler.js | 6 +-- mod/core/processor/request_processor.js | 2 +- mod/core/processor/route_info.js | 10 ++--- mod/core/processor/test.js | 4 +- mod/core/processor/utils.js | 21 --------- mod/core/route_entity_type.js | 2 +- mod/data_api/domains_api.js | 8 ++-- mod/data_api/files_datasource.js | 35 +++++++-------- mod/data_api/gateways_api.js | 44 ++++++++++++++----- mod/data_api/{dids_api.js => numbers_api.js} | 28 ++++++------ mod/data_api/test_files_datasource.js | 15 +++++++ mod/data_api/test_redis_datasource.js | 2 +- mod/data_api/test_utils.js | 10 ++--- mod/data_api/utils.js | 6 +-- mod/location/locator.js | 37 ++++++++-------- mod/location/test.js | 8 ++-- mod/location/utils.js | 9 ++-- mod/registry/registry.js | 6 ++- mod/rest/rest.js | 2 +- mod/utils/misc_util.js | 2 + 45 files changed, 249 insertions(+), 237 deletions(-) delete mode 100644 config/dids.yml rename docs/configuration/{dids.md => numbers.md} (57%) rename etc/schemas/{dids_schema.json => numbers_schema.json} (95%) rename mod/data_api/{dids_api.js => numbers_api.js} (74%) diff --git a/config/dids.yml b/config/dids.yml deleted file mode 100644 index 57fa13a2d..000000000 --- a/config/dids.yml +++ /dev/null @@ -1,12 +0,0 @@ -- apiVersion: v1beta1 - kind: DID - metadata: - gwRef: gw50a1a4ca - geoInfo: # Replace this using your DID's info - city: City, State - country: Country - countryISOCode: US - spec: - location: - telUrl: 'tel:0000000000' # Use your DID number as given by your provider - aorLink: 'sip:1001@sip.local' diff --git a/config/domains.yml b/config/domains.yml index 49a224ea0..79fcd2f4c 100644 --- a/config/domains.yml +++ b/config/domains.yml @@ -7,7 +7,7 @@ domainUri: sip.local egressPolicy: rule: .* - didRef: dd76afc94b + numberRef: dd76afc94b - apiVersion: v1beta1 kind: Domain metadata: diff --git a/config/gateways.yml b/config/gateways.yml index e52c8f705..2888abd4f 100644 --- a/config/gateways.yml +++ b/config/gateways.yml @@ -8,3 +8,14 @@ credentials: username: 'youruser' secret: 'yoursecret' +- apiVersion: v1beta1 + kind: Gateway + metadata: + name: Provider Inc. + spec: + host: sip2.provider.net + port: 5061 + transport: udp + credentials: + username: 'youruser' + secret: 'yoursecret' diff --git a/config/stack.properties b/config/stack.properties index 83f56c658..c43611e54 100644 --- a/config/stack.properties +++ b/config/stack.properties @@ -1,5 +1,5 @@ # This entry is needed to avoid connections issues with the end-to-end tests -gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY=gov.nist.javax.sip.stack.OIOMessageProcessorFactory +# gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY=gov.nist.javax.sip.stack.OIOMessageProcessorFactory # Logging settings #gov.nist.javax.sip.LOG_MESSAGE_CONTENT=true diff --git a/docs/administration/cli/cheatsheet.md b/docs/administration/cli/cheatsheet.md index ab7aa129b..4ddb65aac 100644 --- a/docs/administration/cli/cheatsheet.md +++ b/docs/administration/cli/cheatsheet.md @@ -28,8 +28,8 @@ The --filter flag uses [JsonPath](https://github.com/json-path/JsonPath) to perf All you need to add is the path to the property and the filter operators. For example: ``` -# This returns all the DIDs in Gateway 'gweef506' -./rctl get dids --filter "@.metadata.gwRef=='gweef506'" +# This returns all the Numbers in Gateway 'gweef506' +./rctl get numbers --filter "@.metadata.gwRef=='gweef506'" ``` If you need help, just run `rctl --help` from the terminal window. @@ -80,14 +80,14 @@ $ rctl reg `rctl get` - List one or more resources. ``` -// List all dids -$ rctl get dids +// List all numbers +$ rctl get numbers -// List all dids that belong to gateway reference gweef506 -$ rctl get dids --filter "@.metadata.ref=='gweef506'" +// List all numbers that belong to gateway reference gweef506 +$ rctl get numbers --filter "@.metadata.ref=='gweef506'" -// List did by reference -$ rctl get dids dd50baa4 +// List numberby reference +$ rctl get numbers dd50baa4 // List all agents $ rctl get agents @@ -110,8 +110,8 @@ $ rctl apply -f new-gateway.yaml `rctl delete` - delete a resource. ``` -// Delete all did for gateway reference gweef506 -$ rctl delete dids --filter "@.metadata.gwRef=='gweef506'" +// Delete all numbers for gateway reference gweef506 +$ rctl delete numbers --filter "@.metadata.gwRef=='gweef506'" // Delete a single agent (using delete alias) $ rctl del agent ag3f77f6 @@ -139,7 +139,7 @@ $ rctl registry # Shows only current regis ``` # Find all sip devices available at the location service -$ rctl locate # This list does not include did-ingress-routes or domain-egress-routes +$ rctl locate # This list does not include number-ingress-routes or domain-egress-routes ``` ### Creating Resources @@ -153,11 +153,11 @@ $ rctl create -f agents-list.yaml # Create Agents in file ag ### Finding Resources ``` -# Get DIDs -$ rctl get dids # List all available DIDs -$ rctl get did # List all available DIDs -$ rctl get did --filter "@.metadata.ref=='dd50baa4'" # Shows DID with reference 'DID0001' -$ rctl get did --filter "@.metadata.gwRef=='gweef506'" # Shows DIDs with Gateway reference 'GW1232' +# Get Numbers +$ rctl get numbers # List all available Numbers +$ rctl get number # List all available Numbers +$ rctl get number--filter "@.metadata.ref=='dd50baa4'" # Shows Number with reference 'Number0001' +$ rctl get number--filter "@.metadata.gwRef=='gweef506'" # Shows Numbers with Gateway reference 'GW1232' # Get agents $ rctl get agents # List all Agents @@ -168,7 +168,7 @@ $ rctl get agents # List all Agents ``` # Delete command by refernce or filter $ rctl delete agent ag3f77f6 # Delete Agent by reference -$ rctl del dids --filter '@.metadata.gwRef=gweef506' # Delete DIDs using a filter +$ rctl del numbers --filter '@.metadata.gwRef=gweef506' # Delete Numbers using a filter ``` ### Updating Resources diff --git a/docs/api/dids/create.md b/docs/api/dids/create.md index 755870cbf..33f6b0fe0 100644 --- a/docs/api/dids/create.md +++ b/docs/api/dids/create.md @@ -1,9 +1,9 @@ -Creates a new DID resource. The Gateway must exist before creating the DID. +Creates a new Number. The Gateway must exist before creating the Number. Otherwise, this method responds with a `UNFULFILLED_DEPENDENCY_RESPONSE`. **URL** -`/dids` +`/numbers` **Method** @@ -15,19 +15,19 @@ This method does not receive any parameters. **Request body** -A file containing a [DID](/configuration/dids) resource in `json` format. +A file containing a [Number](/configuration/numbers) resource in `json` format. **Response** -If successful this method creates an DID resource. +If successful this method creates a Number. **Sample Call** ```json -POST /api/v1beta1/dids +POST /api/v1beta1/numbers { "apiVersion": "v1beta1", - "kind": "DID", + "kind": "Number", "metadata": { "gwRef": "gweef506", "geoInfo": { diff --git a/docs/api/dids/delete.md b/docs/api/dids/delete.md index de81dce9d..fac32420f 100644 --- a/docs/api/dids/delete.md +++ b/docs/api/dids/delete.md @@ -1,8 +1,8 @@ -Removes a DID resource from a persistent database. +Removes a Number from a persistent database. **URL** -`/dids/{ref}` +`/numbers/{ref}` **Method** @@ -20,12 +20,12 @@ Do not supply a request body with this method. **Response** -If successful this method removes a DID resource. +If successful this method removes a Number. **Sample Call** ```json -DELETE /api/v1beta1/dids/dd50baa4 +DELETE /api/v1beta1/numbers/dd50baa4 { } diff --git a/docs/api/dids/get.md b/docs/api/dids/get.md index 49467f13a..8a22b70b5 100644 --- a/docs/api/dids/get.md +++ b/docs/api/dids/get.md @@ -2,7 +2,7 @@ This method returns an Agent resource. **URL** -`/dids/{ref}` +`/numbers/{ref}` **Method** @@ -20,12 +20,12 @@ Do not supply a request body with this method. **Response** -If successful this method returns a DID resource. +If successful this method returns a Number. **Sample Call** ```json -GET /api/v1beta1/dids/dd50baa4 +GET /api/v1beta1/numbers/dd50baa4 { } @@ -36,7 +36,7 @@ HTTP/1.1 200 OK "message": "Successful request", "result" : { "apiVersion": "v1beta1", - "kind": "DID", + "kind": "Number", "metadata": { "ref": "dd50baa4", "gwRef": "gweef506", diff --git a/docs/api/dids/list.md b/docs/api/dids/list.md index 394cdfbfe..9c5339a83 100644 --- a/docs/api/dids/list.md +++ b/docs/api/dids/list.md @@ -1,8 +1,8 @@ -This method returns a list of DID resources. +This method returns a list of Numbers. **URL** -`/dids` +`/numbers` **Method** @@ -22,12 +22,12 @@ Do not supply a request body with this method. **Response** -If successful this method returns a list of DID resources. +If successful this method returns a list of Numbers. **Sample Call** ```json -GET /api/v1beta1/dids +GET /api/v1beta1/numbers { } @@ -38,7 +38,7 @@ HTTP/1.1 200 OK "message": "Successful request", "result" : [{ "apiVersion": "v1beta1", - "kind": "DID", + "kind": "Number", "metadata": { "ref": "dd50baa4", "gwRef": "gweef506", diff --git a/docs/api/dids/update.md b/docs/api/dids/update.md index b5a3ddcbb..6c239944f 100644 --- a/docs/api/dids/update.md +++ b/docs/api/dids/update.md @@ -1,8 +1,8 @@ -Updates an existing DID resource. +Updates an existing Number. **URL** -`/dids/{ref}` +`/numbers/{ref}` **Method** @@ -14,19 +14,19 @@ This method does not receive any parameters. **Request body** -A file containing a [DID](/configuration/dids) resource in `json` format. +A file containing a [Number](/configuration/numbers) resource in `json` format. **Response** -If successful this method updates a DID resource. +If successful this method updates a Number. **Sample Call** ```json -PUT /api/v1beta1/dids/dd50baa4 +PUT /api/v1beta1/numbers/dd50baa4 { "apiVersion": "v1beta1", - "kind": "DID", + "kind": "Number", "metadata": { "ref": "dd50baa4", "gwRef": "gweef506", diff --git a/docs/api/gateways/delete.md b/docs/api/gateways/delete.md index 17f9215c7..7995fdc6b 100644 --- a/docs/api/gateways/delete.md +++ b/docs/api/gateways/delete.md @@ -1,5 +1,5 @@ Removes a Gateway resource from a persistent database. Before removing -a Gateway, ensure you have remove all of it child DIDs. Otherwise, +a Gateway, ensure you have remove all of it child Numbers. Otherwise, this method returns a `FOUND_DEPENDENT_OBJECTS_RESPONSE` **URL** diff --git a/docs/concepts.md b/docs/concepts.md index d5e8502dd..0d2cdb4b4 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -86,13 +86,13 @@ In Routr, the process of receiving a call from PSTN to a Domain is as _Domain In registries: [sip.nyc.provider.net] # These are additional registrars within the provider's network ``` -You also need to define DIDs. Routr uses the Address Of Record(AOR) to routes incoming calls from a DID to an existing Agent or Peer. The AOR must be available in the location service at the time of the call, or the call gets rejected. +You also need to define Numbers. Routr uses the Address Of Record(AOR) to routes incoming calls from a Number to an existing Agent or Peer. The AOR must be available in the location service at the time of the call, or the call gets rejected. Please examine the following example: ```yaml - apiVersion: v1beta1 - kind: DID + kind: Number metadata: gwRef: dd50baa4 geoInfo: @@ -105,21 +105,21 @@ Please examine the following example: aorLink: 'sip:john@sip.local' # This is the sip uri of an agent that is expected to be logged in ``` -Easy right? Any incoming call is routed from this Gateway and DID to "Jhon Doe" @ Ocean New York. +Easy right? Any incoming call is routed from this Gateway and Number to "Jhon Doe" @ Ocean New York. **Routing Rules** -The `spec.location` block of a `DID` resource configuration, determines the path of an inbound call from the PSTN. The `aorLink` refers to an Address of Record(Agent or Peer) that is available in the `location service`. +The `spec.location` block of a `Number` resource configuration, determines the path of an inbound call from the PSTN. The `aorLink` refers to an Address of Record(Agent or Peer) that is available in the `location service`. ## Domain Egress Routing -_Domain Egress Routing(DER)_ is the way that **Routr** deals with a call request to a _callee_ that exists in the Public Switched Telephone Network(PSTN) and not in the _callers'_ Domain. The EgressPolicy consists of a `rule`, and a `didRef` defined in the `spec.context` section of `Domains` resources. +_Domain Egress Routing(DER)_ is the way that **Routr** deals with a call request to a _callee_ that exists in the Public Switched Telephone Network(PSTN) and not in the _callers'_ Domain. The EgressPolicy consists of a `rule`, and a `numberRef` defined in the `spec.context` section of `Domains` resources. -The `rule` and `didRef` is defined as follows: +The `rule` and `numberRef` is defined as follows: * `rule` is a regex to match callee in the call request. The location service uses this only after a search in the caller's Domain first. -* `didRef` is the identifier of the DID that will to route the call. The DID must already exist and have a parent Gateway. +* `numberRef` is the identifier of the Number that will to route the call. The Number must already exist and have a parent Gateway. **Routing Rules** @@ -131,7 +131,7 @@ Peers are very similar to Agents, but they are not bound to any Domain, and usua Peers can perform inbound/outbound signaling within the network without any special consideration since they exist inside the _Location Service_ just like Agents. So it is possible to perform signaling from Peer to Peer, Peer to Agent. -The same is true for Inbound from the PSTN. For example, we can redirect incoming calls from the PSTN using the `spec.location` settings in the `dids.yml` configuration file. +The same is true for Inbound from the PSTN. For example, we can redirect incoming calls from the PSTN using the `spec.location` settings in the `numbers.yml` configuration file. **Routing Rules** diff --git a/docs/configuration/domains.md b/docs/configuration/domains.md index 60bb62419..36402752d 100644 --- a/docs/configuration/domains.md +++ b/docs/configuration/domains.md @@ -11,8 +11,8 @@ outgoing calling. The domains configuration can be provided using the file `conf | kind | Defines the type of resource | Yes | | metadata.name | Friendly name for the SIP domain | Yes | | spec.context.domainUri | Domain URI. FQDN is recommended | Yes | -| spec.context.egressPolicy.rule | Regular expression indicating when a call will be routed via $spec.context.egressPolicy.didRef | No | -| spec.context.egressPolicy.didRef | Reference to the DID that will route the call | No | +| spec.context.egressPolicy.rule | Regular expression indicating when a call will be routed via $spec.context.egressPolicy.numberRef | No | +| spec.context.egressPolicy.numberRef | Reference to the Number that will route the call | No | | spec.context.accessControlList.allow[*] | Traffic allow for Network in list | No | | spec.context.accessControlList.deny[*] | Traffic disabled for Network in list| No | @@ -34,7 +34,7 @@ ACL Rules may be in CIDR, IP/Mask, or single IP format. Example of rules are: domainUri: sip.local egressPolicy: rule: .* - didRef: DID0001 + numberRef: Number0001 accessControlList: deny: [0.0.0.0/1] # Deny all allow: [192.168.0.1/31] diff --git a/docs/configuration/gateways.md b/docs/configuration/gateways.md index 989b647c0..5189dd7b8 100644 --- a/docs/configuration/gateways.md +++ b/docs/configuration/gateways.md @@ -13,7 +13,7 @@ For static IP authentication be sure to properly configure the `spec.externAddr` | apiVersion | Indicates the version of the resource (Not yet implemented)| Yes | | kind | Defines the type of resource | Yes | | metadata.name | Friendly name for the SIP device | Yes | -| metadata.ref | Reference to this resource | Yes | +| metadata.ref | Reference to this resource | No | | spec.credentials.username | Gateway username. No required for static IP authentication | No | | spec.credentials.secret | Gateway secret. No required for static IP authentication | No | | spec.host | Gateway host | Yes | diff --git a/docs/configuration/general.md b/docs/configuration/general.md index d1d0dbe05..51dcead4e 100644 --- a/docs/configuration/general.md +++ b/docs/configuration/general.md @@ -11,9 +11,7 @@ can be provided using the file `config/config.yml` located at the root of your R | spec.externAddr | IP address to advertise | No | | spec.localnets | Local networks. Use in combination with spec.externAddr | No | | spec.recordRoute | Stay within the signaling path | No | -| spec.useToAsAOR | Use the TO header instead of Request URI | No | | spec.registrarIntf | `Internal` causes the server to use the IP and port it "sees"(received & rport) from a device attempting to register. Default is `External` | No | -| spec.addressInfo.[*] | Custom tag with the DID information | No | | spec.accessControlList.deny.[*] | Deny incoming traffic from network list | No | | spec.accessControlList.allow.[*] | Allow incoming traffic from network list | No | | spec.restService.bindAddr | Restful service listening address | No | @@ -26,9 +24,9 @@ can be provided using the file `config/config.yml` located at the root of your R | spec.restService.trueStore | Path to trueStore | No | | spec.restService.keyStorePassword | Password for keyStore | No | | spec.restService.trueStorePassword | Password for trueStore | No | -| spec.transport.bindAddr | Overwrites `spec.bindAddr` for transport entry | No | -| spec.transport.port | Transport port | Yes | -| spec.transport.protocol | Valid values are: `tcp`, `udp`, `tls`, `sctp`, `ws`, `wss` | Yes | +| spec.transport.[*].bindAddr | Overwrites `spec.bindAddr` for transport entry | No | +| spec.transport.[*].port | Transport port | Yes | +| spec.transport.[*].protocol | Valid values are: `tcp`, `udp`, `tls`, `sctp`, `ws`, `wss` | Yes | | spec.securityContext.keyStore | Path to keyStore | Yes | | spec.securityContext.trustStore | Path to trueStore | Yes | | spec.securityContext.keyStorePassword | Password for keyStore | Yes | @@ -38,7 +36,6 @@ can be provided using the file `config/config.yml` located at the root of your R | spec.securityContext.debugging | Turns ON or OFF ssl debugging. Default is `false` | No | | spec.dataSource.provider | Defines data provider. Defaults to `files_data_provider` | No | | spec.dataSource.parameters | Provider specific parameters | No | -| spec.logging.traceLevel | Verbosity of the sip-stack logging. Default is `0` | No | ## Transport Configuration @@ -69,7 +66,7 @@ The parameters for `files_data_provider` are: | Parameter | Description | Required | | --- | --- | --- | -| path | Path to configuration files. Defaults to 'config' folder | No | +| path | Path to configuration files. Defaults to the `config` folder | No | This implementation has the limitation that writes operations have to be performed manually on the files. diff --git a/docs/configuration/dids.md b/docs/configuration/numbers.md similarity index 57% rename from docs/configuration/dids.md rename to docs/configuration/numbers.md index aec1ac30a..b4c20ffc9 100644 --- a/docs/configuration/dids.md +++ b/docs/configuration/numbers.md @@ -1,30 +1,30 @@ -DIDs represent virtual numbers use to route calls from/to the PSTN through Gateways. +Numbers represent virtual numbers use to route calls from/to the PSTN through Gateways. -The DIDs configuration can be provided using the file `config/dids.yml` located at the root of your Routr installation. +The Numbers configuration can be provided using the file `config/numbers.yml` located at the root of your Routr installation. > If using Redis this configuration gets stored in the database. -## DID Resource +## Number Resource | Property | Description | Required | | --- | --- | --- | | apiVersion | Indicates the version of the resource (Not yet implemented) | Yes | | kind | Defines the type of resource | Yes | -| metadata.ref| Reference to this resource | Yes | +| metadata.ref| Reference to this resource | No | | metadata.gwRef| Reference to parent Gateway | Yes | -| metadata.geoInfo.city | City of the DID | No | -| metadata.geoInfo.country | Country of the DID | No | -| metadata.geoInfo.countryISOCode| The Country ISO code for the DID (i.e., US) | No | -| spec.location.telUrl | DID URI available in the location server | Yes | +| metadata.geoInfo.city | City of the Number | No | +| metadata.geoInfo.country | Country of the Number | No | +| metadata.geoInfo.countryISOCode| The Country ISO code for the Number (i.e., US) | No | +| spec.location.telUrl | Number URI available in the location server | Yes | | spec.location.aorLink | Address of record of SIP device for call routing | Yes | ## Example ```yaml - apiVersion: v1beta1 - kind: DID + kind: Number metadata: - ref: DID0001 + ref: Number0001 gwRef: GW0001 geoInfo: city: Columbus, GA diff --git a/docs/guides/basic-setup.md b/docs/guides/basic-setup.md index f309862be..64956c1b8 100755 --- a/docs/guides/basic-setup.md +++ b/docs/guides/basic-setup.md @@ -1,11 +1,11 @@ -This document is a step-by-step guide on VoIP setup at home or the office. For calls to the PSTN you need to have a SIP provider like `voip.ms` or `didlogic.com`. +This document is a step-by-step guide on VoIP setup at home or the office. For calls to the PSTN you need to have a SIP provider like `voip.ms` or `did.logic.com`. **Content** - [Requirements](#requirements) - [Setting up the Server](#setting-up-the-server) - [Configuring the Gateway](#configuring-the-gateway) - - [Configuring the DID ](#configuring-the-did) + - [Configuring the Number ](#configuring-the-number) - [Creating a new Domain and EgressPolicy](#creating-a-new-domain-and-egresspolicy) - [Creating the Agents](#creating-the-agents) - [Configuring the SIP devices](#configuring-the-sip-devices) @@ -18,7 +18,7 @@ This tutorial assumes the following: - Two SIP phones connected to the same LAN - A fresh installation of Routr -- SIP providers such as `voip.ms` or `didlogic.com` +- SIP providers such as `voip.ms` or `did.logic.com` ## Setting up the Server @@ -42,13 +42,13 @@ To configure the Gateway, you must consult your SIP provider and obtain the cred transport: udp ``` -### Configuring the DID +### Configuring the Number -To configure your DID or virtual number, you must open and edit the file `config/dids.yml`. Notice in the example below, how your reference the Gateway by using the field `metadata.geRef`. The key field while configuring DIDs are `spec.location.telUrl` and `spec.location.aorLink`. Keep in mind that the value in `spec.location.telUrl` must be formatted, precisely, as sent by the provider. +To configure your Number or virtual number, you must open and edit the file `config/numbers.yml`. Notice in the example below, how your reference the Gateway by using the field `metadata.geRef`. The key field while configuring Numbers are `spec.location.telUrl` and `spec.location.aorLink`. Keep in mind that the value in `spec.location.telUrl` must be formatted, precisely, as sent by the provider. ```yml - apiVersion: v1beta1 - kind: DID + kind: Number metadata: gwRef: gweef506 geoInfo: @@ -75,7 +75,7 @@ To configure your DID or virtual number, you must open and edit the file `config domainUri: sip.local egressPolicy: rule: .* - didRef: dd50baa4 + numberRef: dd50baa4 ``` ### Creating the Agents @@ -108,7 +108,7 @@ Pay close attention to the credentials block since it contains the username and To verify your configuration, start the server by issuing the command `routr`. In a separate window, use the following commands: - `rctl get gateway` -- `rctl get did` +- `rctl get number` - `rctl get domain` - `rctl get agents` diff --git a/docs/introduction/glossary.md b/docs/introduction/glossary.md index 2788b71a7..a1cfccf25 100644 --- a/docs/introduction/glossary.md +++ b/docs/introduction/glossary.md @@ -20,7 +20,7 @@ Similar to Agents but without Domain boundaries IP entity that allows call termination -### DID +### Number Routes and translate calls between the PSTN and Routr diff --git a/etc/schemas/config_schema.json b/etc/schemas/config_schema.json index 831af981e..b4748b017 100644 --- a/etc/schemas/config_schema.json +++ b/etc/schemas/config_schema.json @@ -137,12 +137,6 @@ }, "minItems": 1, "uniqueItems": true - }, - "logging": { - "type": "object", - "properties": { - "traceLevel": {"type": "integer"} - } } }, "required": ["transport"] diff --git a/etc/schemas/gateways_schema.json b/etc/schemas/gateways_schema.json index c91eb54a7..87c178933 100644 --- a/etc/schemas/gateways_schema.json +++ b/etc/schemas/gateways_schema.json @@ -35,6 +35,7 @@ }, "expires": {"type": "integer"}, "host": {"type": "string"}, + "port": {"type": "integer"}, "transport": {"type": "string"}, "registries": { "type": "array", diff --git a/etc/schemas/dids_schema.json b/etc/schemas/numbers_schema.json similarity index 95% rename from etc/schemas/dids_schema.json rename to etc/schemas/numbers_schema.json index 982dea1ad..38e6e6797 100644 --- a/etc/schemas/dids_schema.json +++ b/etc/schemas/numbers_schema.json @@ -1,9 +1,9 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "DID set", + "title": "Number set", "type": "array", "items": { - "title": "DID", + "title": "Number", "type": "object", "properties": { "apiVersion": { @@ -37,4 +37,4 @@ }, "required": ["apiVersion", "kind", "metadata", "spec"] } -} \ No newline at end of file +} diff --git a/mkdocs.yml b/mkdocs.yml index dd829ae14..a99bb6ed4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -27,7 +27,7 @@ nav: - General Configuration: configuration/general.md - Users Configuration: configuration/users.md - Carriers(Gateways) Configuration: configuration/gateways.md - - Virtual Numbers(DIDs) Configuration: configuration/dids.md + - Numbers(DID/DOD) Configuration: configuration/numbers.md - Domains Configuration: configuration/domains.md - Agents Configuration: configuration/agents.md - Peers Configuration: configuration/peers.md @@ -69,12 +69,12 @@ nav: - get: api/gateways/get.md - list: api/gateways/list.md - update: api/gateways/update.md - - DIDs: - - create: api/dids/create.md - - delete: api/dids/delete.md - - get: api/dids/get.md - - list: api/dids/list.md - - update: api/dids/update.md + - Numbers: + - create: api/numbers/create.md + - delete: api/numbers/delete.md + - get: api/numbers/get.md + - list: api/numbers/list.md + - update: api/numbers/update.md - System: - Status: api/system/status.md - Info: api/system/info.md diff --git a/mod/core/account_manager_service.js b/mod/core/account_manager_service.js index c215ba4c6..794a09e46 100644 --- a/mod/core/account_manager_service.js +++ b/mod/core/account_manager_service.js @@ -2,6 +2,7 @@ * @author Pedro Sanders * @since v1 */ +const { gatewayPatch } = require('@routr/utils/misc_util') const { Status } = require('@routr/core/status') @@ -33,7 +34,7 @@ class AccountManagerService { return { username: gateway.spec.credentials.username, secret: gateway.spec.credentials.secret, - host: gateway.spec.host + host: gatewayPatch(gateway.spec.host, gateway.spec.port) } } @@ -50,7 +51,7 @@ class AccountManagerService { return new UserCredentials({ getUserName: () => gateway.username, getPassword: () => gateway.secret, - getSipDomain: () => gateway.host + getSipDomain: () => gatewayPatch(gateway.spec.host, gateway.spec.port) }) } }) diff --git a/mod/core/config_util.js b/mod/core/config_util.js index ec06eeb55..6bd5e793e 100644 --- a/mod/core/config_util.js +++ b/mod/core/config_util.js @@ -28,11 +28,10 @@ function loadConfig() { config.system = getSystemConfig() if (config.spec.registrarIntf === undefined) config.spec.registrarIntf = 'External' - if (config.spec.useToAsAOR === undefined) config.spec.useToAsAOR = false if (config.spec.bindAddr === undefined) config.spec.bindAddr = InetAddress.getLocalHost().getHostAddress() - if (config.spec.logging === undefined) config.spec.logging = { - traceLevel: '0' - } + //if (config.spec.logging === undefined) config.spec.logging = { + // traceLevel: '0' + //} if (config.spec.dataSource === undefined) config.spec.dataSource = { provider: 'files_data_provider' } diff --git a/mod/core/main.js b/mod/core/main.js index 2015d622a..ad87d8957 100644 --- a/mod/core/main.js +++ b/mod/core/main.js @@ -14,7 +14,7 @@ const AgentsAPI = require('@routr/data_api/agents_api') const DomainsAPI = require('@routr/data_api/domains_api') const PeersAPI = require('@routr/data_api/peers_api') const GatewaysAPI = require('@routr/data_api/gateways_api') -const DIDsAPI = require('@routr/data_api/dids_api') +const NumbersAPI = require('@routr/data_api/numbers_api') // Data sources const FilesDataSource = require('@routr/data_api/files_datasource') @@ -45,7 +45,7 @@ const dataAPIs = { UsersAPI: new UsersAPI(dataSource), AgentsAPI: new AgentsAPI(dataSource), DomainsAPI: new DomainsAPI(dataSource), - DIDsAPI: new DIDsAPI(dataSource), + NumbersAPI: new NumbersAPI(dataSource), GatewaysAPI: new GatewaysAPI(dataSource), PeersAPI: new PeersAPI(dataSource) } diff --git a/mod/core/processor/request_handler.js b/mod/core/processor/request_handler.js index a61107281..8a5064bb2 100644 --- a/mod/core/processor/request_handler.js +++ b/mod/core/processor/request_handler.js @@ -70,7 +70,7 @@ class RequestHandler { channel: "locator", topic: "endpoint.find", data: { - addressOfRecord: ProcessorUtils.getAOR(request), + addressOfRecord: request.getRequestURI(), requestId: requestId } }) @@ -178,11 +178,11 @@ class RequestHandler { } const gwRefHeader = headerFactory.createHeader('X-Gateway-Ref', route.gwRef) const remotePartyIdHeader = headerFactory - .createHeader('Remote-Party-ID', `;screen=yes;party=calling`) + .createHeader('Remote-Party-ID', `;screen=yes;party=calling`) const dp = request.getHeader(FromHeader.NAME).getAddress().getDisplayName() const displayName = dp? `"${dp}" ` : '' const pAssertedIdentity = headerFactory - .createHeader('P-Asserted-Identity', `${displayName}`) + .createHeader('P-Asserted-Identity', `${displayName}`) request.setHeader(gwRefHeader) request.setHeader(remotePartyIdHeader) request.setHeader(pAssertedIdentity) diff --git a/mod/core/processor/request_processor.js b/mod/core/processor/request_processor.js index e705da698..bd86cb064 100644 --- a/mod/core/processor/request_processor.js +++ b/mod/core/processor/request_processor.js @@ -83,7 +83,7 @@ class RequestProcessor { } if (routeInfo.getRoutingType().equals(RoutingType.INTRA_DOMAIN_ROUTING)) { - const addressOfRecord = ProcessorUtils.getAOR(request) + const addressOfRecord = request.getRequestURI() const response = this.domainsAPI.getDomainByUri(addressOfRecord.getHost()) if (response.status === Status.OK) { const acl = response.result.spec.context.accessControlList diff --git a/mod/core/processor/route_info.js b/mod/core/processor/route_info.js index d135e009a..5ba35a1ec 100644 --- a/mod/core/processor/route_info.js +++ b/mod/core/processor/route_info.js @@ -40,7 +40,7 @@ class RouteInfo { this.peersAPI = dataAPIs.PeersAPI this.domainsAPI = dataAPIs.DomainsAPI - this.didsAPI = dataAPIs.DIDsAPI + this.numbersAPI = dataAPIs.NumbersAPI this.agentsAPI = dataAPIs.AgentsAPI } @@ -79,10 +79,10 @@ class RouteInfo { if (callerType === RouteEntityType.PEER && calleetype === RouteEntityType.AGENT && belongToSameDomain) routingType = RoutingType.INTRA_DOMAIN_ROUTING if (callerType === RouteEntityType.PEER && this.getCalleeType() === RouteEntityType.THRU_GW) routingType = RoutingType.PEER_EGRESS_ROUTING - if (callerType === RouteEntityType.THRU_GW && calleetype === RouteEntityType.DID) routingType = RoutingType.DOMAIN_INGRESS_ROUTING + if (callerType === RouteEntityType.THRU_GW && calleetype === RouteEntityType.NUMBER) routingType = RoutingType.DOMAIN_INGRESS_ROUTING // This is consider PEER_EGRESS_ROUTING because peers are the only one allow to overwrite the FromHeader. - if (callerType === RouteEntityType.DID && this.getCalleeType() === RouteEntityType.THRU_GW) routingType = RoutingType.PEER_EGRESS_ROUTING + if (callerType === RouteEntityType.NUMBER && this.getCalleeType() === RouteEntityType.THRU_GW) routingType = RoutingType.PEER_EGRESS_ROUTING return routingType } @@ -96,8 +96,8 @@ class RouteInfo { entityType = RouteEntityType.PEER } else if (StringUtils.isNumeric(entity)) { const telUrl = addressFactory.createTelURL(entity) - if (this.didsAPI.didExist(telUrl)) { - entityType = RouteEntityType.DID + if (this.numbersAPI.numberExist(telUrl)) { + entityType = RouteEntityType.NUMBER } } diff --git a/mod/core/processor/test.js b/mod/core/processor/test.js index 618619089..2f04fd666 100644 --- a/mod/core/processor/test.js +++ b/mod/core/processor/test.js @@ -10,7 +10,7 @@ const { createRequest } = require('@routr/utils/test_util') const FilesDataSource = require('@routr/data_api/files_datasource') const GatewaysAPI = require('@routr/data_api/gateways_api') const PeersAPI = require('@routr/data_api/peers_api') -const DIDsAPI = require('@routr/data_api/dids_api') +const NumbersAPI = require('@routr/data_api/numbers_api') const DomainsAPI = require('@routr/data_api/domains_api') const AgentsAPI = require('@routr/data_api/agents_api') const RouteInfo = require('@routr/core/processor/route_info') @@ -21,7 +21,7 @@ const ds = new FilesDataSource(config) const dataAPIs = { AgentsAPI: new AgentsAPI(ds), DomainsAPI: new DomainsAPI(ds), - DIDsAPI: new DIDsAPI(ds), + NumbersAPI: new NumbersAPI(ds), GatewaysAPI: new GatewaysAPI(ds), PeersAPI: new PeersAPI(ds) } diff --git a/mod/core/processor/utils.js b/mod/core/processor/utils.js index 0b6b9a4a9..d4d0647bd 100644 --- a/mod/core/processor/utils.js +++ b/mod/core/processor/utils.js @@ -18,27 +18,6 @@ class ProcessorUtils { sendResponse(responseType) { this.st.sendResponse(messageFactory.createResponse(responseType, this.request)) } - - /** - * Discover DIDs sent via a non-standard header - * The header must be added at config.spec.addressInfo[*] - * If the such header is present then overwrite the AOR - */ - static getAOR(request, addressInfo = []) { - for (const x in addressInfo) { - let info = addressInfo[x] - if (request.getHeader(info) !== undefined) { - let v = request.getHeader(info).getValue() - if (/sips?:.*@.*/.test(v) || /tel:\d+/.test(v)) { - return addressFactory.createURI(v) - } - LOG.error(`Invalid address: ${v}`) - } - } - - return getConfig().spec.useToAsAOR ? request.getHeader(ToHeader.NAME).getAddress().getURI() : - request.getRequestURI() - } } module.exports = ProcessorUtils diff --git a/mod/core/route_entity_type.js b/mod/core/route_entity_type.js index 1076e1fed..a044a8948 100644 --- a/mod/core/route_entity_type.js +++ b/mod/core/route_entity_type.js @@ -6,5 +6,5 @@ module.exports.RouteEntityType = { THRU_GW: 'THRU_GW', AGENT: 'AGENT', PEER: 'PEER', - DID: 'DID' + NUMBER: 'NUMBER' } diff --git a/mod/data_api/domains_api.js b/mod/data_api/domains_api.js index 52e0731ea..1cec05890 100644 --- a/mod/data_api/domains_api.js +++ b/mod/data_api/domains_api.js @@ -29,7 +29,7 @@ class DomainsAPI { createFromJSON(jsonObj) { if (jsonObj.spec.context.egressPolicy && - !this.doesDIDExist(jsonObj.spec.context.egressPolicy.didRef)) { + !this.doesNumberExist(jsonObj.spec.context.egressPolicy.numberRef)) { return UNFULFILLED_DEPENDENCY_RESPONSE } @@ -44,7 +44,7 @@ class DomainsAPI { updateFromJSON(jsonObj) { if (jsonObj.spec.context.egressPolicy && - !this.doesDIDExist(json.spec.context.egressPolicy.didRef)) { + !this.doesNumberExist(json.spec.context.egressPolicy.numberRef)) { return UNFULFILLED_DEPENDENCY_RESPONSE } @@ -98,8 +98,8 @@ class DomainsAPI { return agents.length === 0 ? this.ds.withCollection('domains').remove(ref) : foundDependentObjects } - doesDIDExist(didRef) { - const response = this.ds.withCollection('dids').get(didRef) + doesNumberExist(numberRef) { + const response = this.ds.withCollection('numbers').get(numberRef) return response.status === Status.OK } } diff --git a/mod/data_api/files_datasource.js b/mod/data_api/files_datasource.js index 8cad662ad..77b2dc9fb 100644 --- a/mod/data_api/files_datasource.js +++ b/mod/data_api/files_datasource.js @@ -22,7 +22,7 @@ const lock = new ReentrantLock() const LogManager = Java.type('org.apache.logging.log4j.LogManager') const LOG = LogManager.getLogger() -const RESOURCES = ['agents', 'domains', 'gateways', 'dids', 'peers', 'users'] +const RESOURCES = ['agents', 'domains', 'gateways', 'numbers', 'peers', 'users'] class FilesDataSource { @@ -67,11 +67,11 @@ class FilesDataSource { } } catch (e) { if (e instanceof Java.type('com.fasterxml.jackson.dataformat.yaml.snakeyaml.error.MarkedYAMLException')) { - throw `The format of file \`${this.filesPath}/${RESOURCES[CNT]}.yml\` is invalid` - exit(1) + LOG.error(`The format of file \`${this.filesPath}/${RESOURCES[CNT]}.yml\` is invalid`) + System.exit(1) } else { - throw `Unable to open configuration file \`${this.filesPath}/${RESOURCES[cnt]}.yml\`` - exit(1) + LOG.error(`Unable to open configuration file \`${this.filesPath}/${RESOURCES[cnt]}.yml\``) + System.exit(1) } } } @@ -79,25 +79,23 @@ class FilesDataSource { resourceConstraintValidation() { // Ensure GW for gwRef - let response = this.withCollection('dids').find() - response.result.forEach(did => { - const gwRef = did.metadata.gwRef + let response = this.withCollection('numbers').find() + response.result.forEach(number => { + const gwRef = number.metadata.gwRef response = this.withCollection('gateways').get(gwRef) if (response.status !== Status.OK) { - throw `Gateway with ref \`${gwRef}\`does not exist.` - exit(1) + LOG.error(`Gateway with ref \`${gwRef}\` does not exist`) } }) - // Ensure Domains have valid DIDs + // Ensure Domains have valid Numbers response = this.withCollection('domains').find() response.result.forEach(domain => { if (domain.spec.context.egressPolicy !== undefined) { - const didRef = domain.spec.context.egressPolicy.didRef - response = DSUtils.deepSearch(this.withCollection('dids').find(), "metadata.ref", didRef) + const numberRef = domain.spec.context.egressPolicy.numberRef + response = DSUtils.deepSearch(this.withCollection('numbers').find(), "metadata.ref", numberRef) if (response.status !== Status.OK) { - throw `DID with ref \`${didRef}\` does not exist.` - exit(1) + LOG.error(`Number with ref \`${numberRef}\` does not exist`) } } }) @@ -110,8 +108,7 @@ class FilesDataSource { const domain = domains[cnt] response = this.withCollection('domains').find(`@.spec.context.domainUri=='${domain}'`) if (response.result.length === 0) { - throw `Agent \`${agent.metadata.name}\`(${agent.spec.credentials.username}) has a non-existent domain/s.` - exit(1) + LOG.error(`Agent \`${agent.metadata.name}\`(${agent.spec.credentials.username}) has a non-existent domain/s`) } } }) @@ -124,7 +121,7 @@ class FilesDataSource { if (response.status === Status.OK) { const refs = response.result.map(entity => entity.metadata.ref) if (findDuplicates(refs).length > 0) { - throw `Found duplicate entries in ${this.filesPath}/${resource}.yml` + LOG.error(`Found duplicate entries in ${this.filesPath}/${resource}.yml`) exit(1) } } @@ -224,7 +221,7 @@ class FilesDataSource { case 'gateway': obj.metadata.ref = `gw${this.generateRef(obj.spec.host)}` break - case 'did': + case 'number': obj.metadata.ref = `dd${this.generateRef(obj.spec.location.telUrl)}` break case 'user': diff --git a/mod/data_api/gateways_api.js b/mod/data_api/gateways_api.js index 0bbc17dba..60c91fe60 100644 --- a/mod/data_api/gateways_api.js +++ b/mod/data_api/gateways_api.js @@ -2,6 +2,7 @@ * @author Pedro Sanders * @since v1 */ +const { gatewayPatch } = require('@routr/utils/misc_util') const CoreUtils = require('@routr/core/utils') const DSUtils = require('@routr/data_api/utils') const { @@ -23,9 +24,10 @@ class GatewaysAPI { } createFromJSON(jsonObj) { - if (!this.gatewayExist(jsonObj.spec.host)) { + if (!this.gatewayExist(jsonObj.spec.host, jsonObj.spec.port)) { const response = this.ds.insert(jsonObj) - this.cache.put(jsonObj.spec.host, response) + const host = gatewayPatch(jsonObj.spec.host, jsonObj.spec.port) + this.cache.put(host, response) return response } @@ -33,9 +35,10 @@ class GatewaysAPI { } updateFromJSON(jsonObj) { - if (this.gatewayExist(jsonObj.spec.host)) { + if (this.gatewayExist(jsonObj.spec.host, jsonObj.spec.port)) { const response = this.ds.update(jsonObj) - this.cache(jsonObj.spec.host, response) + const host = gatewayPatch(jsonObj.spec.host, jsonObj.spec.port) + this.cache(host, response) return response } @@ -50,19 +53,40 @@ class GatewaysAPI { return this.ds.withCollection('gateways').get(ref) } + getGatewayByHostAndPort(h, port) { + if (!port) return this.getGatewayByHost(host) + const host = gatewayPatch(h, port) + + let response = this.cache.getIfPresent(host) + + if (response === null) { + const r1 = DSUtils.deepSearch(this.getGateways(), 'spec.port', port) + const r2 = DSUtils.deepSearch(this.getGateways(), 'spec.host', host) + + if (r1.status === Status.NOT_FOUND || r2.status === Status.NOT_FOUND) { + response = { status: Status.NOT_FOUND } + } + + this.cache.put(host, response) + } + + return response + } + + getGatewayByHost(host) { let response = this.cache.getIfPresent(host) if (response === null) { - response = DSUtils.deepSearch(this.getGateways(), "spec.host", host) + response = DSUtils.deepSearch(this.getGateways(), 'spec.host', host) this.cache.put(host, response) } return response } - gatewayExist(host) { - return DSUtils.objExist(this.getGatewayByHost(host)) + gatewayExist(host, port) { + return DSUtils.objExist(this.getGatewayByHostAndPort(host, port)) } deleteGateway(ref) { @@ -78,10 +102,10 @@ class GatewaysAPI { const gateway = response.result - response = this.ds.withCollection('dids').find(`@.metadata.gwRef=='${gateway.metadata.ref}'`) - const dids = response.result + response = this.ds.withCollection('numbers').find(`@.metadata.gwRef=='${gateway.metadata.ref}'`) + const numbers = response.result - return dids.length === 0 ? this.ds.withCollection('gateways').remove(ref) : FOUND_DEPENDENT_OBJECTS_RESPONSE + return numbers.length === 0 ? this.ds.withCollection('gateways').remove(ref) : FOUND_DEPENDENT_OBJECTS_RESPONSE } } diff --git a/mod/data_api/dids_api.js b/mod/data_api/numbers_api.js similarity index 74% rename from mod/data_api/dids_api.js rename to mod/data_api/numbers_api.js index bbc1eeff5..b00bcb77c 100644 --- a/mod/data_api/dids_api.js +++ b/mod/data_api/numbers_api.js @@ -13,7 +13,7 @@ const { const Caffeine = Java.type('com.github.benmanes.caffeine.cache.Caffeine') const TimeUnit = Java.type('java.util.concurrent.TimeUnit') -class DIDsAPI { +class NumbersAPI { constructor(dataSource) { this.ds = dataSource @@ -29,7 +29,7 @@ class DIDsAPI { return UNFULFILLED_DEPENDENCY_RESPONSE } - if (!this.didExist(jsonObj.spec.location.telUrl)) { + if (!this.numberExist(jsonObj.spec.location.telUrl)) { const response = this.ds.insert(jsonObj) this.cache.put(jsonObj.spec.location.telUrl, response) return response @@ -45,7 +45,7 @@ class DIDsAPI { return UNFULFILLED_DEPENDENCY_RESPONSE } - if (this.didExist(jsonObj.spec.location.telUrl)) { + if (this.numberExist(jsonObj.spec.location.telUrl)) { const response = this.ds.update(jsonObj) this.cache.put(jsonObj.spec.location.telUrl, response) return response @@ -54,40 +54,40 @@ class DIDsAPI { return CoreUtils.buildResponse(Status.NOT_FOUND) } - getDIDs(filter) { - return this.ds.withCollection('dids').find(filter) + getNumbers(filter) { + return this.ds.withCollection('numbers').find(filter) } - getDID(ref) { - return this.ds.withCollection('dids').get(ref) + getNumber(ref) { + return this.ds.withCollection('numbers').get(ref) } /** * note: telUrl maybe a string in form of 'tel:${number}' or * a TelURL Object. */ - getDIDByTelUrl(telUrl) { + getNumberByTelUrl(telUrl) { let response = this.cache.getIfPresent(telUrl) if (response === null) { - response = DSUtils.deepSearch(this.getDIDs(), "spec.location.telUrl", telUrl) + response = DSUtils.deepSearch(this.getNumbers(), "spec.location.telUrl", telUrl) this.cache.put(telUrl, response) } return response } - didExist(telUrl) { - return DSUtils.objExist(this.getDIDByTelUrl(telUrl)) + numberExist(telUrl) { + return DSUtils.objExist(this.getNumberByTelUrl(telUrl)) } - deleteDID(ref) { + deleteNumber(ref) { if (this.cache.getIfPresent(ref)) { this.cache.invalidate(ref) } - return this.ds.withCollection('dids').remove(ref) + return this.ds.withCollection('numbers').remove(ref) } } -module.exports = DIDsAPI +module.exports = NumbersAPI diff --git a/mod/data_api/test_files_datasource.js b/mod/data_api/test_files_datasource.js index f67bf0e7f..8a70bc76a 100644 --- a/mod/data_api/test_files_datasource.js +++ b/mod/data_api/test_files_datasource.js @@ -6,6 +6,7 @@ */ const assert = require('assert') const FilesDataSource = require('@routr/data_api/files_datasource') +const GatewaysAPI = require('@routr/data_api/gateways_api') const FilesUtil = require('@routr/utils/files_util') const DSUtils = require('@routr/data_api/utils') const { @@ -16,6 +17,7 @@ const config = getConfig() // Forces data source to use its own default parameters... delete config.spec.dataSource.parameters const ds = new FilesDataSource(config) +const gwAPI = new GatewaysAPI(ds) describe('Files Data Source', () => { it('YAML from file', function(done) { @@ -38,4 +40,17 @@ describe('Files Data Source', () => { assert.ok(response.status === Status.BAD_REQUEST) done() }) + + it('Get gateway by host and port', function(done) { + let response = gwAPI.getGatewayByHostAndPort('sip.provider.net', 5090) + assert.ok(response.status !== Status.OK) + + response = gwAPI.getGatewayByHost('sip.provider.net') + assert.ok(response.status === Status.OK) + + response = gwAPI.getGatewayByHost('sip2.provider.net', 5061) + assert.ok(response.status === Status.OK) + + done() + }) }) diff --git a/mod/data_api/test_redis_datasource.js b/mod/data_api/test_redis_datasource.js index e1f27c206..fe91fa9d0 100644 --- a/mod/data_api/test_redis_datasource.js +++ b/mod/data_api/test_redis_datasource.js @@ -22,7 +22,7 @@ delete config.spec.dataSource.parameters const ds = null const agentsApi = new AgentsAPI(ds) -describe('Files Data Source', () => { +describe('Redis Data Source', () => { it.skip('Basic operations', function(done) { const agent = TestUtils.buildAgent('John Doe', ['sip.local'], '1001') const initSize = ds.withCollection('agents').find().result.length diff --git a/mod/data_api/test_utils.js b/mod/data_api/test_utils.js index 7a27d9169..a390e5fad 100644 --- a/mod/data_api/test_utils.js +++ b/mod/data_api/test_utils.js @@ -62,7 +62,7 @@ class TestUtils { domainUri: domainUri, egressPolicy: { rule: '.*', - didRef: 'DID0001' + numberRef: 'DID0001' } } } @@ -70,10 +70,10 @@ class TestUtils { return domain } - static buildDID() { - const did = { + static buildNumber() { + const number = { apiVersion: 'v1.0', - kind: 'DID', + kind: 'Number', metadata: { userId: 'john@doe.com', gwRef: '595bc68492bccf1454883d0b', @@ -90,7 +90,7 @@ class TestUtils { } } } - return did + return number } } diff --git a/mod/data_api/utils.js b/mod/data_api/utils.js index e0aa0efcd..14a087e73 100644 --- a/mod/data_api/utils.js +++ b/mod/data_api/utils.js @@ -78,9 +78,9 @@ class DSUtils { } static getKind(obj) { - if (['user', 'agent', 'peer', 'domain', 'gateway', 'did'] + if (['user', 'agent', 'peer', 'domain', 'gateway', 'number'] .indexOf(obj.kind.toLowerCase()) === -1) { - throw "Not a valid entity. `kind` must be: User, Agent, Peer, Domain, Gateway, DID" + throw 'Not a valid entity. \`kind\` must be: User, Agent, Peer, Domain, Gateway, Number' } return obj.kind } @@ -88,7 +88,7 @@ class DSUtils { static deepSearch(response, path, value) { let result response.result.forEach(obj => { - if (DSUtils.resolve(path, obj) === value.toString()) { + if (value && DSUtils.resolve(path, obj) === value.toString()) { result = obj } }) diff --git a/mod/location/locator.js b/mod/location/locator.js index c75d0ebd8..3ef0963b2 100644 --- a/mod/location/locator.js +++ b/mod/location/locator.js @@ -9,6 +9,7 @@ const postal = require('postal') const CoreUtils = require('@routr/core/utils') const LocatorUtils = require('@routr/location/utils') const isEmpty = require('@routr/utils/obj_util') +const { gatewayPatch } = require('@routr/utils/misc_util') const { Status } = require('@routr/core/status') @@ -50,7 +51,7 @@ class Locator { this.agentsAPI = dataAPIs.AgentsAPI this.peersAPI = dataAPIs.PeersAPI - this.didsAPI = dataAPIs.DIDsAPI + this.numbersAPI = dataAPIs.NumbersAPI this.domainsAPI = dataAPIs.DomainsAPI this.gatewaysAPI = dataAPIs.GatewaysAPI @@ -135,18 +136,18 @@ class Locator { } /** - * DIDs required an "aorLink" to enter the network + * Numbers required an "aorLink" to enter the network */ findEndpointByTelUrl(addressOfRecord) { - const response = this.didsAPI.getDIDByTelUrl(LocatorUtils.aorAsString(addressOfRecord)) + const response = this.numbersAPI.getNumberByTelUrl(LocatorUtils.aorAsString(addressOfRecord)) if (response.status === Status.OK) { - const did = response.result - const route = this.db.getIfPresent(LocatorUtils.aorAsString(did.spec.location.aorLink)) + const number = response.result + const route = this.db.getIfPresent(LocatorUtils.aorAsString(number.spec.location.aorLink)) if (route !== null) { return CoreUtils.buildResponse(Status.OK, route) } - return CoreUtils.buildResponse(Status.NOT_FOUND, `No route for aorLink: ${did.spec.location.aorLink}`) + return CoreUtils.buildResponse(Status.NOT_FOUND, `No route for aorLink: ${number.spec.location.aorLink}`) } return CoreUtils.buildResponse(Status.NOT_FOUND) } @@ -168,9 +169,9 @@ class Locator { return response } - // Then search for a DID + // Then search for a Number try { - response = this.findEndpointForDID(aorString) + response = this.findEndpointForNumber(aorString) if (response.status === Status.OK) { return response } @@ -195,11 +196,11 @@ class Locator { return response.status === Status.OK ? response : CoreUtils.buildResponse(Status.NOT_FOUND) } - findEndpointForDID(addressOfRecord) { - const response = this.didsAPI.getDIDByTelUrl(LocatorUtils.aorAsString(addressOfRecord)) + findEndpointForNumber(addressOfRecord) { + const response = this.numbersAPI.getNumberByTelUrl(LocatorUtils.aorAsString(addressOfRecord)) if (response.status === Status.OK) { - const did = response.result - const route = this.db.getIfPresent(LocatorUtils.aorAsString(did.spec.location.aorLink)) + const number = response.result + const route = this.db.getIfPresent(LocatorUtils.aorAsString(number.spec.location.aorLink)) if (route !== null) { return CoreUtils.buildResponse(Status.OK, route) } @@ -252,12 +253,12 @@ class Locator { const addressFactory = SipFactory.getInstance().createAddressFactory() if (!isEmpty(domain.spec.context.egressPolicy)) { - // Get DID and Gateway info - let response = this.didsAPI.getDID(domain.spec.context.egressPolicy.didRef) - const did = response.result + // Get Number and Gateway info + let response = this.numbersAPI.getNumber(domain.spec.context.egressPolicy.numberRef) + const number = response.result if (response.status === Status.OK) { - response = this.gatewaysAPI.getGateway(did.metadata.gwRef) + response = this.gatewaysAPI.getGateway(number.metadata.gwRef) if (response.status === Status.OK) { const gateway = response.result @@ -266,9 +267,9 @@ class Locator { if (new RegExp(pattern).test(addressOfRecord)) { const contactURI = addressFactory - .createSipURI(aorObj.getUser(), gateway.spec.host) + .createSipURI(aorObj.getUser(), gatewayPatch(gateway.spec.host, gateway.spec.port)) contactURI.setSecure(aorObj.isSecure()) - const route = LocatorUtils.buildEgressRoute(contactURI, gateway, did, domain) + const route = LocatorUtils.buildEgressRoute(contactURI, gateway, number, domain) return CoreUtils.buildResponse(Status.OK, [route]) } } diff --git a/mod/location/test.js b/mod/location/test.js index 15a4e9d34..464111ae6 100644 --- a/mod/location/test.js +++ b/mod/location/test.js @@ -10,7 +10,7 @@ const Locator = require('@routr/location/locator') const LocatorUtils = require('@routr/location/utils') const AgentsAPI = require('@routr/data_api/agents_api') const PeersAPI = require('@routr/data_api/peers_api') -const DIDsAPI = require('@routr/data_api/dids_api') +const NumbersAPI = require('@routr/data_api/numbers_api') const DomainsAPI = require('@routr/data_api/domains_api') const GatewaysAPI = require('@routr/data_api/gateways_api') const { @@ -28,7 +28,7 @@ const dataAPIs = { AgentsAPI: new AgentsAPI(ds), DomainsAPI: new DomainsAPI(ds), GatewaysAPI: new GatewaysAPI(ds), - DIDsAPI: new DIDsAPI(ds) + NumbersAPI: new NumbersAPI(ds) } const addressFactory = SipFactory.getInstance().createAddressFactory() const locator = new Locator(dataAPIs) @@ -103,8 +103,8 @@ describe('Location Service Module', () => { done() }) - it('Find endpoint for did', function(done) { - // This is the local aor for the did '0000000000' + it('Find endpoint for number', function(done) { + // This is the local aor for the number '0000000000' const endpoint = buildEndpoint('1001', 'sip.local', '192.168.1.2:5061') locator.addEndpoint(endpoint.aor, endpoint.route) testFE(addressFactory.createSipURI('0000000000', 'sip.local'), true) diff --git a/mod/location/utils.js b/mod/location/utils.js index 5562e42e0..20b0f5a8c 100644 --- a/mod/location/utils.js +++ b/mod/location/utils.js @@ -2,6 +2,7 @@ * @author Pedro Sanders * @since v1 */ +const { gatewayPatch } = require('@routr/utils/misc_util') const StringBuilder = Java.type('java.lang.StringBuilder') const SipFactory = Java.type('javax.sip.SipFactory') const addressFactory = SipFactory.getInstance().createAddressFactory() @@ -83,7 +84,7 @@ class LocatorUtils { }] } - static buildEgressRoute(contactURI, gateway, did, domain) { + static buildEgressRoute(contactURI, gateway, number, domain) { const username = gateway.spec.credentials ? gateway.spec.credentials.username : null const route = { @@ -91,9 +92,9 @@ class LocatorUtils { thruGw: true, gwUsername: username, gwRef: gateway.metadata.ref, - gwHost: gateway.spec.host, - didRef: did.metadata.ref, - did: did.spec.location.telUrl.split(':')[1], + gwHost: gatewayPatch(gateway.spec.host, gateway.spec.port), + numberRef: number.metadata.ref, + number: number.spec.location.telUrl.split(':')[1], contactURI: contactURI } if (domain) { diff --git a/mod/registry/registry.js b/mod/registry/registry.js index 8b6a28d3a..74076594b 100644 --- a/mod/registry/registry.js +++ b/mod/registry/registry.js @@ -2,6 +2,7 @@ * @author Pedro Sanders * @since v1 */ +const { gatewayPatch } = require('@routr/utils/misc_util') const getConfig = require('@routr/core/config_util') const LocatorUtils = require('@routr/location/utils') const { @@ -179,10 +180,11 @@ class Registry { if (gateway.spec.credentials === undefined) continue - const gwURIStr = `sip:${gateway.spec.credentials.username}@${gateway.spec.host}` + const host = gatewayPatch(gateway.spec.host, gateway.spec.port) + const gwURIStr = `sip:${gateway.spec.credentials.username}@${host}` const expires = gateway.spec.expires ? gateway.spec.expires : 3600 if (self.isExpired(gwURIStr)) { - LOG.debug(`Register with ${gateway.metadata.name} using ${gateway.spec.credentials.username}@${gateway.spec.host}`) + LOG.debug(`Register with ${gateway.metadata.name} using ${gateway.spec.credentials.username}@${host}`) self.requestChallenge(gateway.spec.credentials.username, gateway.metadata.ref, gateway.spec.host, gateway.spec.transport, null, null, expires) } diff --git a/mod/rest/rest.js b/mod/rest/rest.js index ac3877625..c785e5bbc 100644 --- a/mod/rest/rest.js +++ b/mod/rest/rest.js @@ -118,7 +118,7 @@ class Rest { resourcesService(this.dataAPIs.PeersAPI, 'Peer') resourcesService(this.dataAPIs.DomainsAPI, 'Domain') resourcesService(this.dataAPIs.GatewaysAPI, 'Gateway') - resourcesService(this.dataAPIs.DIDsAPI, 'DID') + resourcesService(this.dataAPIs.NumbersAPI, 'Number') }) } diff --git a/mod/utils/misc_util.js b/mod/utils/misc_util.js index bdbc94511..c617ef5d1 100644 --- a/mod/utils/misc_util.js +++ b/mod/utils/misc_util.js @@ -1,2 +1,4 @@ module.exports.equalsIgnoreCase = (a, b) => a.toLowerCase() === b.toLowerCase() + +module.exports.gatewayPatch = (h, p) => `${h}${p? ':' + p: ''}`