@routr/connect 2.0.8-alpha.1 → 2.0.8-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ import { MessageRequest, CommonConnect as CC } from "@routr/common";
2
+ import { RoutingDirection } from "./types";
3
+ export declare const checkAccess: (accessRequest: {
4
+ dataAPI: CC.DataAPI;
5
+ request: MessageRequest;
6
+ caller: CC.Resource;
7
+ callee: CC.Resource;
8
+ routingDirection: RoutingDirection;
9
+ }) => Promise<Record<string, unknown>>;
10
+ export declare const checkAgentOrPeerAccess: (dataAPI: CC.DataAPI, request: MessageRequest, caller: CC.Resource) => Promise<{
11
+ message: {
12
+ responseType: number;
13
+ wwwAuthenticate: {
14
+ scheme: string;
15
+ realm: string;
16
+ qop: string;
17
+ opaque: string;
18
+ stale: boolean;
19
+ nonce: string;
20
+ algorithm: string;
21
+ };
22
+ };
23
+ }>;
24
+ export declare const checkAccessFromPSTN: (dataAPI: CC.DataAPI, request: MessageRequest, callee: CC.Resource) => Promise<{
25
+ message: {
26
+ responseType: number;
27
+ };
28
+ }>;
package/dist/access.js ADDED
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.checkAccessFromPSTN = exports.checkAgentOrPeerAccess = exports.checkAccess = void 0;
13
+ /*
14
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster
16
+ *
17
+ * This file is part of Routr.
18
+ *
19
+ * Licensed under the MIT License (the "License");
20
+ * you may not use this file except in compliance with
21
+ * the License. You may obtain a copy of the License at
22
+ *
23
+ * https://opensource.org/licenses/MIT
24
+ *
25
+ * Unless required by applicable law or agreed to in writing, software
26
+ * distributed under the License is distributed on an "AS IS" BASIS,
27
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28
+ * See the License for the specific language governing permissions and
29
+ * limitations under the License.
30
+ */
31
+ const logger_1 = require("@fonoster/logger");
32
+ const common_1 = require("@routr/common");
33
+ const types_1 = require("./types");
34
+ const utils_1 = require("./utils");
35
+ const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
36
+ const checkAccess = (accessRequest) => __awaiter(void 0, void 0, void 0, function* () {
37
+ const { dataAPI, request, caller, callee, routingDirection } = accessRequest;
38
+ switch (routingDirection) {
39
+ case types_1.RoutingDirection.PEER_TO_PSTN:
40
+ case types_1.RoutingDirection.AGENT_TO_AGENT:
41
+ case types_1.RoutingDirection.AGENT_TO_PSTN:
42
+ return (0, exports.checkAgentOrPeerAccess)(dataAPI, request, caller);
43
+ case types_1.RoutingDirection.FROM_PSTN:
44
+ return (0, exports.checkAccessFromPSTN)(dataAPI, request, callee);
45
+ case types_1.RoutingDirection.UNKNOWN:
46
+ return common_1.Auth.createForbideenResponse();
47
+ }
48
+ });
49
+ exports.checkAccess = checkAccess;
50
+ const checkAgentOrPeerAccess = (dataAPI, request, caller) => __awaiter(void 0, void 0, void 0, function* () {
51
+ // Calculate and return challenge
52
+ if (request.message.authorization) {
53
+ const auth = Object.assign({}, request.message.authorization);
54
+ auth.method = request.method;
55
+ const credentials = yield dataAPI.get(caller.spec.credentialsRef);
56
+ // Calculate response and compare with the one send by the endpoint
57
+ const calcRes = common_1.Auth.calculateAuthResponse(auth, {
58
+ username: credentials === null || credentials === void 0 ? void 0 : credentials.spec.credentials.username,
59
+ secret: credentials === null || credentials === void 0 ? void 0 : credentials.spec.credentials.password
60
+ });
61
+ if (calcRes !== auth.response) {
62
+ return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
63
+ }
64
+ }
65
+ else {
66
+ return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
67
+ }
68
+ });
69
+ exports.checkAgentOrPeerAccess = checkAgentOrPeerAccess;
70
+ const checkAccessFromPSTN = (dataAPI, request, callee) => __awaiter(void 0, void 0, void 0, function* () {
71
+ var _a, _b;
72
+ // Get the Trunk associated with the SIP URI
73
+ const trunk = yield (0, utils_1.findTrunkByRequestURI)(dataAPI, request.message.requestUri.host);
74
+ // If the Trunk or Number doesn't exist reject the call
75
+ if (!callee || !trunk) {
76
+ return common_1.Auth.createForbideenResponse();
77
+ }
78
+ if (callee.spec.trunkRef !== trunk.ref) {
79
+ return common_1.Auth.createForbideenResponse();
80
+ }
81
+ // Verify that the IP is whitelisted which means getting the access control list for the trunk
82
+ if ((_a = trunk.spec.inbound) === null || _a === void 0 ? void 0 : _a.accessControlListRef) {
83
+ try {
84
+ const acl = yield dataAPI.get(trunk.spec.inbound.accessControlListRef);
85
+ if (!acl) {
86
+ // Should never happen since the ACL is required
87
+ return common_1.Auth.createServerInternalErrorResponse();
88
+ }
89
+ const allow = acl.spec.accessControlList.allow.filter((net) => {
90
+ return common_1.IpUtils.hasIp(net, request.sender.host);
91
+ })[0];
92
+ if (!allow) {
93
+ // TODO: Replace with Unauthorized
94
+ return common_1.Auth.createUnauthorizedResponseWithoutChallenge();
95
+ }
96
+ }
97
+ catch (e) {
98
+ logger.error(e);
99
+ }
100
+ }
101
+ // If the Trunk has a User/Password we must verify that the User/Password are valid
102
+ if ((_b = trunk.spec.inbound) === null || _b === void 0 ? void 0 : _b.credentialsRef) {
103
+ const credentials = yield dataAPI.get(trunk.spec.inbound.credentialsRef);
104
+ if (!credentials) {
105
+ // Should never happen since the Credentials is required
106
+ return common_1.Auth.createServerInternalErrorResponse();
107
+ }
108
+ // Calculate and return challenge
109
+ if (request.message.authorization) {
110
+ const auth = Object.assign({}, request.message.authorization);
111
+ auth.method = request.method;
112
+ // Calculate response and compare with the one send by the endpoint
113
+ const calcRes = common_1.Auth.calculateAuthResponse(auth, {
114
+ username: credentials.spec.credentials.username,
115
+ secret: credentials.spec.credentials.password
116
+ });
117
+ if (calcRes !== auth.response) {
118
+ return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
119
+ }
120
+ }
121
+ else {
122
+ return common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host);
123
+ }
124
+ }
125
+ });
126
+ exports.checkAccessFromPSTN = checkAccessFromPSTN;
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ROUTING_DIRECTION } from "./types";
1
+ import { RoutingDirection } from "./types";
2
2
  /**
3
3
  * Throw when the API server is unavailable.
4
4
  */
@@ -19,7 +19,7 @@ export declare class UnsuportedRoutingError extends Error {
19
19
  /**
20
20
  * Create a new ServiceUnavailableError.
21
21
  *
22
- * @param {string} routingDir - The routing direction
22
+ * @param {RoutingDirection} routingDirection - The routing direction
23
23
  */
24
- constructor(routingDir: ROUTING_DIRECTION);
24
+ constructor(routingDirection: RoutingDirection);
25
25
  }
package/dist/errors.js CHANGED
@@ -67,10 +67,10 @@ class UnsuportedRoutingError extends Error {
67
67
  /**
68
68
  * Create a new ServiceUnavailableError.
69
69
  *
70
- * @param {string} routingDir - The routing direction
70
+ * @param {RoutingDirection} routingDirection - The routing direction
71
71
  */
72
- constructor(routingDir) {
73
- super("unsupported routing direction: " + routingDir);
72
+ constructor(routingDirection) {
73
+ super("unsupported routing direction: " + routingDirection);
74
74
  this.code = grpc.status.UNKNOWN;
75
75
  // Set the prototype explicitly.
76
76
  Object.setPrototypeOf(this, ServiceUnavailableError.prototype);
@@ -1,6 +1,6 @@
1
1
  import { MessageRequest, Response } from "@routr/processor";
2
- import { ILocationService } from "@routr/location/src/types";
2
+ import { ILocationService } from "@routr/location";
3
3
  import { CommonConnect as CC } from "@routr/common";
4
- export declare const handleRegister: (location: ILocationService) => (request: MessageRequest, res: Response) => Promise<void>;
4
+ export declare const handleRegister: (dataAPI: CC.DataAPI, location: ILocationService) => (request: MessageRequest, res: Response) => Promise<void>;
5
5
  export declare const handleRegistry: (req: MessageRequest, res: Response) => void;
6
6
  export declare const handleRequest: (location: ILocationService, dataAPI?: CC.DataAPI) => (req: MessageRequest, res: Response) => Promise<void | MessageRequest>;
package/dist/handlers.js CHANGED
@@ -34,13 +34,37 @@ const processor_1 = require("@routr/processor");
34
34
  const function_1 = require("fp-ts/function");
35
35
  const router_1 = require("./router");
36
36
  const common_1 = require("@routr/common");
37
- const handleRegister = (location) => {
37
+ const utils_1 = require("./utils");
38
+ const handleRegister = (dataAPI, location) => {
38
39
  return (request, res) => __awaiter(void 0, void 0, void 0, function* () {
39
- yield location.addRoute({
40
- aor: processor_1.Target.getTargetAOR(request),
41
- route: location_1.Helper.createRoute(request)
42
- });
43
- res.sendOk();
40
+ // Calculate and return challenge
41
+ if (request.message.authorization) {
42
+ const auth = Object.assign({}, request.message.authorization);
43
+ auth.method = request.method;
44
+ const fromURI = request.message.from.address.uri;
45
+ const peerOrAgent = yield (0, utils_1.findResource)(dataAPI, fromURI.host, fromURI.user);
46
+ if (!peerOrAgent) {
47
+ return res.send(common_1.Auth.createForbideenResponse());
48
+ }
49
+ const credentials = yield dataAPI.get(peerOrAgent.spec.credentialsRef);
50
+ // Calculate response and compare with the one send by the endpoint
51
+ const calcRes = common_1.Auth.calculateAuthResponse(auth, {
52
+ username: credentials === null || credentials === void 0 ? void 0 : credentials.spec.credentials.username,
53
+ secret: credentials === null || credentials === void 0 ? void 0 : credentials.spec.credentials.password
54
+ });
55
+ if (calcRes !== auth.response) {
56
+ return res.send(common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host));
57
+ }
58
+ // TODO: Needs test
59
+ yield location.addRoute({
60
+ aor: peerOrAgent.spec.aor || processor_1.Target.getTargetAOR(request),
61
+ route: location_1.Helper.createRoute(request)
62
+ });
63
+ res.sendOk();
64
+ }
65
+ else {
66
+ return res.send(common_1.Auth.createUnauthorizedResponse(request.message.requestUri.host));
67
+ }
44
68
  });
45
69
  };
46
70
  exports.handleRegister = handleRegister;
@@ -58,13 +82,17 @@ const handleRequest = (location, dataAPI) => (req, res) => __awaiter(void 0, voi
58
82
  : yield (0, router_1.router)(location, dataAPI)(req);
59
83
  if (!route)
60
84
  return res.sendNotFound();
61
- // Forward request to peer edgeport
62
- if (req.edgePortRef !== route.edgePortRef) {
63
- return (0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route),
64
- // The LP address belongs to another edgeport
65
- processor_1.Alterations.addRouteToListeningPoint(route), processor_1.Alterations.addXEdgePortRef, processor_1.Alterations.decreaseMaxForwards);
85
+ // If route is not type Route then return
86
+ if (!("user" in route)) {
87
+ return res.send(route);
88
+ }
89
+ else {
90
+ // Forward request to peer edgeport
91
+ if (req.edgePortRef !== route.edgePortRef) {
92
+ return (0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.addRouteToPeerEdgePort(route), processor_1.Alterations.addXEdgePortRef, processor_1.Alterations.decreaseMaxForwards);
93
+ }
94
+ res.send((0, tailor_1.tailor)(route, req));
66
95
  }
67
- res.send((0, tailor_1.tailor)(route, req));
68
96
  }
69
97
  catch (err) {
70
98
  res.sendError(err);
package/dist/router.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { Route } from "@routr/common";
1
+ import { CommonConnect as CC, Route } from "@routr/common";
2
2
  import { MessageRequest } from "@routr/processor";
3
3
  import { ILocationService } from "@routr/location";
4
- import { CommonConnect as CC } from "@routr/common";
5
- export declare function router(location: ILocationService, dataAPI: CC.DataAPI): (req: MessageRequest) => Promise<Route>;
4
+ export declare function router(location: ILocationService, dataAPI: CC.DataAPI): (request: MessageRequest) => Promise<Route | Record<string, unknown>>;
package/dist/router.js CHANGED
@@ -32,33 +32,46 @@ const types_1 = require("./types");
32
32
  const common_1 = require("@routr/common");
33
33
  const utils_1 = require("./utils");
34
34
  const processor_1 = require("@routr/processor");
35
- const errors_1 = require("./errors");
36
35
  const location_1 = require("@routr/location");
36
+ const errors_1 = require("./errors");
37
37
  const logger_1 = require("@fonoster/logger");
38
- const common_2 = require("@routr/common");
38
+ const access_1 = require("./access");
39
39
  const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
40
- const getSIPURI = (uri) => `sip:${uri.user}@${uri.host}`;
41
40
  // eslint-disable-next-line require-jsdoc
42
41
  function router(location, dataAPI) {
43
- return (req) => __awaiter(this, void 0, void 0, function* () {
44
- const fromURI = req.message.from.address.uri;
45
- const requestURI = req.message.requestUri;
42
+ return (request) => __awaiter(this, void 0, void 0, function* () {
43
+ const fromURI = request.message.from.address.uri;
44
+ const requestURI = request.message.requestUri;
46
45
  logger.verbose("routing request from: " +
47
- getSIPURI(fromURI) +
46
+ (0, utils_1.getSIPURI)(fromURI) +
48
47
  ", to: " +
49
- getSIPURI(requestURI), { fromURI: getSIPURI(fromURI), requestURI: getSIPURI(requestURI) });
48
+ (0, utils_1.getSIPURI)(requestURI), { fromURI: (0, utils_1.getSIPURI)(fromURI), requestURI: (0, utils_1.getSIPURI)(requestURI) });
50
49
  const caller = yield (0, utils_1.findResource)(dataAPI, fromURI.host, fromURI.user);
51
50
  const callee = yield (0, utils_1.findResource)(dataAPI, requestURI.host, requestURI.user);
52
- const routingDir = (0, utils_1.getRoutingDirection)(caller, callee);
53
- switch (routingDir) {
54
- case types_1.ROUTING_DIRECTION.AGENT_TO_PSTN:
55
- return yield toPSTN(dataAPI, req, caller, requestURI.user);
56
- case types_1.ROUTING_DIRECTION.AGENT_TO_AGENT:
57
- return agentToAgent(location, req);
58
- case types_1.ROUTING_DIRECTION.FROM_PSTN:
59
- return yield fromPSTN(location, dataAPI, callee);
51
+ const routingDirection = (0, utils_1.getRoutingDirection)(caller, callee);
52
+ if (request.method === common_1.CommonTypes.Method.INVITE) {
53
+ const failedCheck = yield (0, access_1.checkAccess)({
54
+ dataAPI,
55
+ request,
56
+ caller,
57
+ callee,
58
+ routingDirection
59
+ });
60
+ if (failedCheck) {
61
+ return failedCheck;
62
+ }
63
+ }
64
+ switch (routingDirection) {
65
+ case types_1.RoutingDirection.AGENT_TO_AGENT:
66
+ return agentToAgent(location, request);
67
+ case types_1.RoutingDirection.AGENT_TO_PSTN:
68
+ return yield agentToPSTN(dataAPI, request, caller, requestURI.user);
69
+ case types_1.RoutingDirection.FROM_PSTN:
70
+ return yield fromPSTN(location, callee);
71
+ case types_1.RoutingDirection.PEER_TO_PSTN:
72
+ return yield peerToPSTN(dataAPI, request);
60
73
  default:
61
- throw new errors_1.UnsuportedRoutingError(routingDir);
74
+ throw new errors_1.UnsuportedRoutingError(routingDirection);
62
75
  }
63
76
  });
64
77
  }
@@ -73,11 +86,10 @@ function agentToAgent(location, req) {
73
86
  * From PSTN routing.
74
87
  *
75
88
  * @param {ILocationService} location - Location service
76
- * @param {uknown} _
77
89
  * @param {Resource} callee - The callee
78
90
  * @return {Promise<Route>}
79
91
  */
80
- function fromPSTN(location, _, callee) {
92
+ function fromPSTN(location, callee) {
81
93
  var _a;
82
94
  return __awaiter(this, void 0, void 0, function* () {
83
95
  const route = (yield location.findRoutes({
@@ -92,7 +104,7 @@ function fromPSTN(location, _, callee) {
92
104
  const p = {
93
105
  name: prop.name,
94
106
  value: prop.value,
95
- action: common_2.CommonTypes.HeaderModifierAction.ADD
107
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
96
108
  };
97
109
  route.headers.push(p);
98
110
  });
@@ -100,46 +112,91 @@ function fromPSTN(location, _, callee) {
100
112
  });
101
113
  }
102
114
  // eslint-disable-next-line require-jsdoc
103
- function toPSTN(dataAPI, req, caller, calleeNumber) {
104
- var _a, _b;
115
+ function agentToPSTN(dataAPI, req, caller, calleeNumber) {
116
+ var _a;
105
117
  return __awaiter(this, void 0, void 0, function* () {
106
118
  const domain = yield dataAPI.get(caller.spec.domainRef);
119
+ if (!domain.spec.context.egressPolicies) {
120
+ // TODO: Create custom error
121
+ throw new Error(`no egress policy found for Domain ref: ${domain.ref}`);
122
+ }
107
123
  // Look for Number in domain that matches regex callee
108
- const policy = (_a = domain.spec.context.egressPolicies) === null || _a === void 0 ? void 0 : _a.find((policy) => {
124
+ const policy = domain.spec.context.egressPolicies.find((policy) => {
109
125
  const regex = new RegExp(policy.rule);
110
126
  return regex.test(calleeNumber);
111
127
  });
112
128
  const number = yield dataAPI.get(policy === null || policy === void 0 ? void 0 : policy.numberRef);
113
129
  const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
114
- if (!domain.spec.context.egressPolicies) {
115
- // TODO: Create custom error
116
- throw new Error(`no egress policy found for Domain ref: ${domain.ref}`);
130
+ if (!trunk) {
131
+ // This should never happen
132
+ throw new Error(`no trunk associated with Number ref: ${number.ref}`);
133
+ }
134
+ const uri = (0, utils_1.getTrunkURI)(trunk);
135
+ return {
136
+ user: uri.user,
137
+ host: uri.host,
138
+ port: uri.port,
139
+ transport: uri.transport,
140
+ edgePortRef: req.edgePortRef,
141
+ listeningPoints: req.listeningPoints,
142
+ localnets: req.localnets,
143
+ externalAddrs: req.externalAddrs,
144
+ headers: [
145
+ // TODO: Find a more deterministic way to re-add the Privacy header
146
+ {
147
+ name: "Privacy",
148
+ action: common_1.CommonTypes.HeaderModifierAction.REMOVE
149
+ },
150
+ {
151
+ name: "Privacy",
152
+ value: ((_a = caller.spec.privacy) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
153
+ ? common_1.CommonTypes.Privacy.PRIVATE
154
+ : common_1.CommonTypes.Privacy.NONE,
155
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
156
+ },
157
+ (0, utils_1.createRemotePartyId)(trunk, number),
158
+ (0, utils_1.createPAssertedIdentity)(req, trunk, number),
159
+ yield (0, utils_1.createTrunkAuthentication)(dataAPI, trunk)
160
+ ]
161
+ };
162
+ });
163
+ }
164
+ // eslint-disable-next-line require-jsdoc
165
+ function peerToPSTN(dataAPI, req) {
166
+ return __awaiter(this, void 0, void 0, function* () {
167
+ const numberTel = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_NUMBER);
168
+ const privacy = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_PRIVACY);
169
+ const number = yield (0, utils_1.findNumberByTelUrl)(dataAPI, `tel:${numberTel}`);
170
+ if (!number) {
171
+ throw new Error(`no Number found for tel: ${numberTel}`);
117
172
  }
173
+ const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
118
174
  if (!trunk) {
119
175
  // TODO: Create custom error
120
- throw new Error(`no trunk associated with Number ref: ${number === null || number === void 0 ? void 0 : number.ref}`);
176
+ throw new Error(`no trunk associated with Number ref: ${number.ref}`);
121
177
  }
122
178
  const uri = (0, utils_1.getTrunkURI)(trunk);
123
- const egressListeningPoint = common_1.Helper.getListeningPoint(req, uri.transport);
124
179
  return {
125
180
  user: uri.user,
126
181
  host: uri.host,
127
182
  port: uri.port,
128
183
  transport: uri.transport,
129
184
  edgePortRef: req.edgePortRef,
130
- egressListeningPoint,
185
+ listeningPoints: req.listeningPoints,
186
+ localnets: req.localnets,
187
+ externalAddrs: req.externalAddrs,
131
188
  headers: [
132
189
  // TODO: Find a more deterministic way to re-add the Privacy header
133
190
  {
134
191
  name: "Privacy",
135
- action: common_2.CommonTypes.HeaderModifierAction.REMOVE
192
+ action: common_1.CommonTypes.HeaderModifierAction.REMOVE
136
193
  },
137
194
  {
138
195
  name: "Privacy",
139
- value: ((_b = caller.spec.privacy) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === common_2.CommonTypes.Privacy.PRIVATE
140
- ? common_2.CommonTypes.Privacy.PRIVATE
141
- : common_2.CommonTypes.Privacy.NONE,
142
- action: common_2.CommonTypes.HeaderModifierAction.ADD
196
+ value: (privacy === null || privacy === void 0 ? void 0 : privacy.toLocaleLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
197
+ ? common_1.CommonTypes.Privacy.PRIVATE
198
+ : common_1.CommonTypes.Privacy.NONE,
199
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
143
200
  },
144
201
  (0, utils_1.createRemotePartyId)(trunk, number),
145
202
  (0, utils_1.createPAssertedIdentity)(req, trunk, number),
package/dist/service.js CHANGED
@@ -70,7 +70,7 @@ function ConnectProcessor(config) {
70
70
  (0, handlers_1.handleRegistry)(req, res);
71
71
  }
72
72
  else {
73
- (0, handlers_1.handleRegister)(location)(req, res);
73
+ (0, handlers_1.handleRegister)(common_2.CommonConnect.dataAPI(config.apiAddr), location)(req, res);
74
74
  }
75
75
  break;
76
76
  case common_1.Method.BYE:
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HeaderModifier } from "@routr/common";
2
- export declare enum ROUTING_DIRECTION {
2
+ export declare enum RoutingDirection {
3
3
  FROM_PSTN = "from-pstn",
4
4
  AGENT_TO_AGENT = "agent-to-agent",
5
5
  AGENT_TO_PSTN = "agent-to-pstn",
package/dist/types.js CHANGED
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ROUTING_DIRECTION = void 0;
4
- var ROUTING_DIRECTION;
5
- (function (ROUTING_DIRECTION) {
6
- ROUTING_DIRECTION["FROM_PSTN"] = "from-pstn";
7
- ROUTING_DIRECTION["AGENT_TO_AGENT"] = "agent-to-agent";
8
- ROUTING_DIRECTION["AGENT_TO_PSTN"] = "agent-to-pstn";
9
- ROUTING_DIRECTION["PEER_TO_AGENT"] = "peer-to-agent";
10
- ROUTING_DIRECTION["PEER_TO_PSTN"] = "peer-to-pstn";
11
- ROUTING_DIRECTION["UNKNOWN"] = "unknown";
12
- })(ROUTING_DIRECTION = exports.ROUTING_DIRECTION || (exports.ROUTING_DIRECTION = {}));
3
+ exports.RoutingDirection = void 0;
4
+ var RoutingDirection;
5
+ (function (RoutingDirection) {
6
+ RoutingDirection["FROM_PSTN"] = "from-pstn";
7
+ RoutingDirection["AGENT_TO_AGENT"] = "agent-to-agent";
8
+ RoutingDirection["AGENT_TO_PSTN"] = "agent-to-pstn";
9
+ // WARNING: This is not supported yet
10
+ RoutingDirection["PEER_TO_AGENT"] = "peer-to-agent";
11
+ RoutingDirection["PEER_TO_PSTN"] = "peer-to-pstn";
12
+ RoutingDirection["UNKNOWN"] = "unknown";
13
+ })(RoutingDirection = exports.RoutingDirection || (exports.RoutingDirection = {}));
package/dist/utils.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { HeaderModifier, MessageRequest, Transport } from "@routr/common";
2
- import { CommonConnect as CC } from "@routr/common";
3
- import { ROUTING_DIRECTION } from "./types";
4
- export declare const isKind: (res: CC.Resource, kind: CC.KIND) => boolean;
1
+ import { HeaderModifier, MessageRequest, Transport, CommonConnect as CC } from "@routr/common";
2
+ import { RoutingDirection } from "./types";
3
+ export declare const isKind: (res: CC.Resource, kind: CC.Kind) => boolean;
5
4
  export declare const findDomain: (dataAPI: CC.DataAPI, domainUri: string) => Promise<CC.Resource>;
5
+ export declare const findTrunkByRequestURI: (dataAPI: CC.DataAPI, requestUri: string) => Promise<CC.Resource>;
6
+ export declare const findNumberByTelUrl: (dataAPI: CC.DataAPI, telUrl: string) => Promise<CC.Resource>;
6
7
  export declare const findResource: (dataAPI: CC.DataAPI, domainUri: string, userpart: string) => Promise<CC.Resource>;
7
- export declare const getRoutingDirection: (caller: CC.Resource, callee: CC.Resource) => ROUTING_DIRECTION;
8
+ export declare const getRoutingDirection: (caller: CC.Resource, callee: CC.Resource) => RoutingDirection;
8
9
  export declare const createPAssertedIdentity: (req: MessageRequest, trunk: CC.Resource, number: CC.Resource) => HeaderModifier;
9
10
  export declare const createRemotePartyId: (trunk: CC.Resource, number: CC.Resource) => HeaderModifier;
10
11
  export declare const createTrunkAuthentication: (dataAPI: CC.DataAPI, trunk: CC.Resource) => Promise<HeaderModifier>;
@@ -14,3 +15,7 @@ export declare const getTrunkURI: (trunk: CC.Resource) => {
14
15
  user: string;
15
16
  transport: Transport;
16
17
  };
18
+ export declare const getSIPURI: (uri: {
19
+ user?: string;
20
+ host: string;
21
+ }) => string;
package/dist/utils.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePartyId = exports.createPAssertedIdentity = exports.getRoutingDirection = exports.findResource = exports.findDomain = exports.isKind = void 0;
12
+ exports.getSIPURI = exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePartyId = exports.createPAssertedIdentity = exports.getRoutingDirection = exports.findResource = exports.findNumberByTelUrl = exports.findTrunkByRequestURI = exports.findDomain = exports.isKind = void 0;
13
13
  /*
14
14
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
15
15
  * http://github.com/fonoster/routr
@@ -29,10 +29,9 @@ exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePa
29
29
  * limitations under the License.
30
30
  */
31
31
  const common_1 = require("@routr/common");
32
- const common_2 = require("@routr/common");
33
32
  const types_1 = require("./types");
34
33
  const isKind = (res, kind) => {
35
- if (res == null && kind === common_2.CommonConnect.KIND.UNKNOWN) {
34
+ if (res == null && kind === common_1.CommonConnect.Kind.UNKNOWN) {
36
35
  return true;
37
36
  }
38
37
  return (res === null || res === void 0 ? void 0 : res.kind.toLowerCase()) === kind;
@@ -40,35 +39,59 @@ const isKind = (res, kind) => {
40
39
  exports.isKind = isKind;
41
40
  const findDomain = (dataAPI, domainUri) => __awaiter(void 0, void 0, void 0, function* () {
42
41
  return (yield dataAPI.findBy({
43
- kind: common_2.CommonConnect.KIND.DOMAIN,
44
- criteria: common_2.CommonConnect.FindCriteria.FIND_DOMAIN_BY_DOMAINURI,
42
+ kind: common_1.CommonConnect.Kind.DOMAIN,
43
+ criteria: common_1.CommonConnect.FindCriteria.FIND_DOMAIN_BY_DOMAINURI,
45
44
  parameters: {
46
45
  domainUri
47
46
  }
48
47
  }))[0];
49
48
  });
50
49
  exports.findDomain = findDomain;
51
- const findResource = (dataAPI, domainUri, userpart) => __awaiter(void 0, void 0, void 0, function* () {
52
- const domain = yield (0, exports.findDomain)(dataAPI, domainUri);
53
- // TODO: Fix jsonpath not working for logical AND and OR
54
- let res = (yield dataAPI.findBy({
55
- kind: common_2.CommonConnect.KIND.NUMBER,
56
- criteria: common_2.CommonConnect.FindCriteria.FIND_NUMBER_BY_TELURL,
50
+ const findTrunkByRequestURI = (dataAPI, requestUri) => __awaiter(void 0, void 0, void 0, function* () {
51
+ return (yield dataAPI.findBy({
52
+ kind: common_1.CommonConnect.Kind.TRUNK,
53
+ criteria: common_1.CommonConnect.FindCriteria.FIND_TRUNK_BY_REQUEST_URI,
54
+ parameters: {
55
+ requestUri
56
+ }
57
+ }))[0];
58
+ });
59
+ exports.findTrunkByRequestURI = findTrunkByRequestURI;
60
+ const findNumberByTelUrl = (dataAPI, telUrl) => __awaiter(void 0, void 0, void 0, function* () {
61
+ return (yield dataAPI.findBy({
62
+ kind: common_1.CommonConnect.Kind.NUMBER,
63
+ criteria: common_1.CommonConnect.FindCriteria.FIND_NUMBER_BY_TELURL,
57
64
  parameters: {
58
- telUrl: `tel:${userpart}`
65
+ telUrl
59
66
  }
60
67
  }))[0];
61
- res =
62
- res == null
63
- ? (yield dataAPI.findBy({
64
- kind: common_2.CommonConnect.KIND.AGENT,
65
- criteria: common_2.CommonConnect.FindCriteria.FIND_AGENT_BY_USERNAME,
66
- parameters: {
67
- username: userpart
68
- }
69
- }))[0]
70
- : res;
71
- if ((0, exports.isKind)(res, common_2.CommonConnect.KIND.AGENT) && res.spec.domainRef != (domain === null || domain === void 0 ? void 0 : domain.ref)) {
68
+ });
69
+ exports.findNumberByTelUrl = findNumberByTelUrl;
70
+ const findResource = (dataAPI, domainUri, userpart) => __awaiter(void 0, void 0, void 0, function* () {
71
+ const domain = yield (0, exports.findDomain)(dataAPI, domainUri);
72
+ // TODO: Fix jsonpath not working for logical AND and OR
73
+ let res = yield (0, exports.findNumberByTelUrl)(dataAPI, `tel:${userpart}`);
74
+ // Next, try to find an agent
75
+ if (res == null) {
76
+ res = (yield dataAPI.findBy({
77
+ kind: common_1.CommonConnect.Kind.AGENT,
78
+ criteria: common_1.CommonConnect.FindCriteria.FIND_AGENT_BY_USERNAME,
79
+ parameters: {
80
+ username: userpart
81
+ }
82
+ }))[0];
83
+ }
84
+ // Next, try to find a peer
85
+ if (res == null) {
86
+ res = (yield dataAPI.findBy({
87
+ kind: common_1.CommonConnect.Kind.PEER,
88
+ criteria: common_1.CommonConnect.FindCriteria.FIND_PEER_BY_USERNAME,
89
+ parameters: {
90
+ username: userpart
91
+ }
92
+ }))[0];
93
+ }
94
+ if ((0, exports.isKind)(res, common_1.CommonConnect.Kind.AGENT) && res.spec.domainRef != (domain === null || domain === void 0 ? void 0 : domain.ref)) {
72
95
  // Not in the same domain
73
96
  return null;
74
97
  }
@@ -76,23 +99,23 @@ const findResource = (dataAPI, domainUri, userpart) => __awaiter(void 0, void 0,
76
99
  });
77
100
  exports.findResource = findResource;
78
101
  const getRoutingDirection = (caller, callee) => {
79
- if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.AGENT) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.AGENT)) {
80
- return types_1.ROUTING_DIRECTION.AGENT_TO_AGENT;
102
+ if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.AGENT) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.AGENT)) {
103
+ return types_1.RoutingDirection.AGENT_TO_AGENT;
81
104
  }
82
- if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.AGENT) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.UNKNOWN)) {
83
- return types_1.ROUTING_DIRECTION.AGENT_TO_PSTN;
105
+ if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.AGENT) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.UNKNOWN)) {
106
+ return types_1.RoutingDirection.AGENT_TO_PSTN;
84
107
  }
85
- if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.PEER) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.AGENT)) {
86
- return types_1.ROUTING_DIRECTION.PEER_TO_AGENT;
108
+ if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.PEER) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.AGENT)) {
109
+ return types_1.RoutingDirection.PEER_TO_AGENT;
87
110
  }
88
111
  // All we know is that the Number is managed by this instance of Routr
89
- if ((0, exports.isKind)(callee, common_2.CommonConnect.KIND.NUMBER)) {
90
- return types_1.ROUTING_DIRECTION.FROM_PSTN;
112
+ if ((0, exports.isKind)(callee, common_1.CommonConnect.Kind.NUMBER)) {
113
+ return types_1.RoutingDirection.FROM_PSTN;
91
114
  }
92
- if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.PEER) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.UNKNOWN)) {
93
- return types_1.ROUTING_DIRECTION.PEER_TO_PSTN;
115
+ if ((0, exports.isKind)(caller, common_1.CommonConnect.Kind.PEER) && (0, exports.isKind)(callee, common_1.CommonConnect.Kind.UNKNOWN)) {
116
+ return types_1.RoutingDirection.PEER_TO_PSTN;
94
117
  }
95
- return types_1.ROUTING_DIRECTION.UNKNOWN;
118
+ return types_1.RoutingDirection.UNKNOWN;
96
119
  };
97
120
  exports.getRoutingDirection = getRoutingDirection;
98
121
  const createPAssertedIdentity = (req, trunk, number) => {
@@ -104,7 +127,7 @@ const createPAssertedIdentity = (req, trunk, number) => {
104
127
  value: displayName
105
128
  ? `"${displayName}" <sip:${remoteNumber}@${trunkHost};user=phone>`
106
129
  : `<sip:${remoteNumber}@${trunkHost};user=phone>`,
107
- action: common_2.CommonTypes.HeaderModifierAction.ADD
130
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
108
131
  };
109
132
  };
110
133
  exports.createPAssertedIdentity = createPAssertedIdentity;
@@ -114,7 +137,7 @@ const createRemotePartyId = (trunk, number) => {
114
137
  return {
115
138
  name: "Remote-Party-ID",
116
139
  value: `<sip:${remoteNumber}@${trunkHost}>;screen=yes;party=calling`,
117
- action: common_2.CommonTypes.HeaderModifierAction.ADD
140
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
118
141
  };
119
142
  };
120
143
  exports.createRemotePartyId = createRemotePartyId;
@@ -122,15 +145,17 @@ const createTrunkAuthentication = (dataAPI, trunk) => __awaiter(void 0, void 0,
122
145
  var _a, _b;
123
146
  const credentials = yield dataAPI.get(trunk.spec.outbound.credentialsRef);
124
147
  return {
125
- name: common_2.CommonTypes.ExtraHeader.GATEWAY_AUTH,
148
+ name: common_1.CommonTypes.ExtraHeader.GATEWAY_AUTH,
126
149
  value: Buffer.from(`${(_a = credentials.spec.credentials) === null || _a === void 0 ? void 0 : _a.username}:${(_b = credentials.spec.credentials) === null || _b === void 0 ? void 0 : _b.password}`).toString("base64"),
127
- action: common_2.CommonTypes.HeaderModifierAction.ADD
150
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
128
151
  };
129
152
  });
130
153
  exports.createTrunkAuthentication = createTrunkAuthentication;
131
154
  const getTrunkURI = (trunk) => {
132
- var _a;
133
- const { user, host, port, transport } = (_a = trunk.spec.outbound) === null || _a === void 0 ? void 0 : _a.uris[0].uri;
155
+ if (!trunk.spec.outbound) {
156
+ throw new Error(`trunk ${trunk.ref} has no outbound settings`);
157
+ }
158
+ const { user, host, port, transport } = trunk.spec.outbound.uris[0].uri;
134
159
  const t = !transport
135
160
  ? common_1.Transport.UDP
136
161
  : Object.values(common_1.Transport)[Object.values(common_1.Transport).indexOf(transport.toLowerCase())];
@@ -142,3 +167,5 @@ const getTrunkURI = (trunk) => {
142
167
  };
143
168
  };
144
169
  exports.getTrunkURI = getTrunkURI;
170
+ const getSIPURI = (uri) => uri.user ? `sip:${uri.user}@${uri.host}` : `sip:${uri.host}`;
171
+ exports.getSIPURI = getSIPURI;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routr/connect",
3
- "version": "2.0.8-alpha.1",
3
+ "version": "2.0.8-alpha.10",
4
4
  "description": "Default processor",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/routr#readme",
@@ -28,9 +28,9 @@
28
28
  "@opentelemetry/sdk-trace-base": "^1.0.4",
29
29
  "@opentelemetry/sdk-trace-node": "^1.0.4",
30
30
  "@opentelemetry/semantic-conventions": "^1.0.4",
31
- "@routr/common": "^2.0.8-alpha.1",
32
- "@routr/location": "^2.0.8-alpha.1",
33
- "@routr/processor": "^2.0.8-alpha.1"
31
+ "@routr/common": "^2.0.8-alpha.10",
32
+ "@routr/location": "^2.0.8-alpha.10",
33
+ "@routr/processor": "^2.0.8-alpha.10"
34
34
  },
35
35
  "files": [
36
36
  "dist"
@@ -45,5 +45,5 @@
45
45
  "bugs": {
46
46
  "url": "https://github.com/fonoster/routr/issues"
47
47
  },
48
- "gitHead": "0824e725362fae3df83467f0f8989a2e4fa1f794"
48
+ "gitHead": "5082233fb155ddb8535f934550fa4013da87468e"
49
49
  }