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

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, CommonTypes as CT, 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: CT.ResponseType;
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: CT.ResponseType;
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 on start
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
+ return common_1.Auth.createUnauthorizedResponseWithoutChallenge();
94
+ }
95
+ }
96
+ catch (e) {
97
+ logger.error(e);
98
+ return common_1.Auth.createServerInternalErrorResponse();
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,11 +67,11 @@ 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);
74
- this.code = grpc.status.UNKNOWN;
72
+ constructor(routingDirection) {
73
+ super("unsupported routing direction: " + routingDirection);
74
+ this.code = grpc.status.UNIMPLEMENTED;
75
75
  // Set the prototype explicitly.
76
76
  Object.setPrototypeOf(this, ServiceUnavailableError.prototype);
77
77
  }
@@ -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
- export declare const handleRequest: (location: ILocationService, dataAPI?: CC.DataAPI) => (req: MessageRequest, res: Response) => Promise<void | MessageRequest>;
6
+ export declare const handleRequest: (location: ILocationService, dataAPI?: CC.DataAPI) => (req: MessageRequest, res: Response) => Promise<void>;
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 (!("listeningPoints" in route)) {
87
+ return res.send(route);
88
+ }
89
+ else {
90
+ // Forward request to peer edgeport
91
+ if (req.edgePortRef !== route.edgePortRef) {
92
+ return res.send((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, request);
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
  }
@@ -66,33 +79,36 @@ exports.router = router;
66
79
  // eslint-disable-next-line require-jsdoc
67
80
  function agentToAgent(location, req) {
68
81
  return __awaiter(this, void 0, void 0, function* () {
69
- return (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req) }))[0];
82
+ return (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req), callId: req.ref }))[0];
70
83
  });
71
84
  }
72
85
  /**
73
86
  * From PSTN routing.
74
87
  *
75
88
  * @param {ILocationService} location - Location service
76
- * @param {uknown} _
77
89
  * @param {Resource} callee - The callee
90
+ * @param {MessageRequest} req - The request
78
91
  * @return {Promise<Route>}
79
92
  */
80
- function fromPSTN(location, _, callee) {
93
+ function fromPSTN(location, callee, req) {
81
94
  var _a;
82
95
  return __awaiter(this, void 0, void 0, function* () {
96
+ const sessionAffinityRef = processor_1.Extensions.getHeaderValue(req, callee.spec.location.sessionAffinityHeader);
83
97
  const route = (yield location.findRoutes({
84
- aor: callee.spec.location.aorLink
98
+ aor: callee.spec.location.aorLink,
99
+ callId: req.ref,
100
+ sessionAffinityRef
85
101
  }))[0];
86
102
  if (!route) {
87
103
  throw new location_1.NotRoutesFoundForAOR(callee.spec.location.aorLink);
88
104
  }
89
105
  if (!route.headers)
90
106
  route.headers = [];
91
- (_a = callee.spec.location.props) === null || _a === void 0 ? void 0 : _a.forEach((prop) => {
107
+ (_a = callee.spec.location.extraHeaders) === null || _a === void 0 ? void 0 : _a.forEach((prop) => {
92
108
  const p = {
93
109
  name: prop.name,
94
110
  value: prop.value,
95
- action: common_2.CommonTypes.HeaderModifierAction.ADD
111
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
96
112
  };
97
113
  route.headers.push(p);
98
114
  });
@@ -100,46 +116,91 @@ function fromPSTN(location, _, callee) {
100
116
  });
101
117
  }
102
118
  // eslint-disable-next-line require-jsdoc
103
- function toPSTN(dataAPI, req, caller, calleeNumber) {
104
- var _a, _b;
119
+ function agentToPSTN(dataAPI, req, caller, calleeNumber) {
120
+ var _a;
105
121
  return __awaiter(this, void 0, void 0, function* () {
106
122
  const domain = yield dataAPI.get(caller.spec.domainRef);
123
+ if (!domain.spec.context.egressPolicies) {
124
+ // TODO: Create custom error
125
+ throw new Error(`no egress policy found for Domain ref: ${domain.ref}`);
126
+ }
107
127
  // 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) => {
128
+ const policy = domain.spec.context.egressPolicies.find((policy) => {
109
129
  const regex = new RegExp(policy.rule);
110
130
  return regex.test(calleeNumber);
111
131
  });
112
132
  const number = yield dataAPI.get(policy === null || policy === void 0 ? void 0 : policy.numberRef);
113
133
  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}`);
134
+ if (!trunk) {
135
+ // This should never happen
136
+ throw new Error(`no trunk associated with Number ref: ${number.ref}`);
137
+ }
138
+ const uri = (0, utils_1.getTrunkURI)(trunk);
139
+ return {
140
+ user: uri.user,
141
+ host: uri.host,
142
+ port: uri.port,
143
+ transport: uri.transport,
144
+ edgePortRef: req.edgePortRef,
145
+ listeningPoints: req.listeningPoints,
146
+ localnets: req.localnets,
147
+ externalAddrs: req.externalAddrs,
148
+ headers: [
149
+ // TODO: Find a more deterministic way to re-add the Privacy header
150
+ {
151
+ name: "Privacy",
152
+ action: common_1.CommonTypes.HeaderModifierAction.REMOVE
153
+ },
154
+ {
155
+ name: "Privacy",
156
+ value: ((_a = caller.spec.privacy) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
157
+ ? common_1.CommonTypes.Privacy.PRIVATE
158
+ : common_1.CommonTypes.Privacy.NONE,
159
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
160
+ },
161
+ (0, utils_1.createRemotePartyId)(trunk, number),
162
+ (0, utils_1.createPAssertedIdentity)(req, trunk, number),
163
+ yield (0, utils_1.createTrunkAuthentication)(dataAPI, trunk)
164
+ ]
165
+ };
166
+ });
167
+ }
168
+ // eslint-disable-next-line require-jsdoc
169
+ function peerToPSTN(dataAPI, req) {
170
+ return __awaiter(this, void 0, void 0, function* () {
171
+ const numberTel = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_NUMBER);
172
+ const privacy = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.DOD_PRIVACY);
173
+ const number = yield (0, utils_1.findNumberByTelUrl)(dataAPI, `tel:${numberTel}`);
174
+ if (!number) {
175
+ throw new Error(`no Number found for tel: ${numberTel}`);
117
176
  }
177
+ const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
118
178
  if (!trunk) {
119
179
  // TODO: Create custom error
120
- throw new Error(`no trunk associated with Number ref: ${number === null || number === void 0 ? void 0 : number.ref}`);
180
+ throw new Error(`no trunk associated with Number ref: ${number.ref}`);
121
181
  }
122
182
  const uri = (0, utils_1.getTrunkURI)(trunk);
123
- const egressListeningPoint = common_1.Helper.getListeningPoint(req, uri.transport);
124
183
  return {
125
184
  user: uri.user,
126
185
  host: uri.host,
127
186
  port: uri.port,
128
187
  transport: uri.transport,
129
188
  edgePortRef: req.edgePortRef,
130
- egressListeningPoint,
189
+ listeningPoints: req.listeningPoints,
190
+ localnets: req.localnets,
191
+ externalAddrs: req.externalAddrs,
131
192
  headers: [
132
193
  // TODO: Find a more deterministic way to re-add the Privacy header
133
194
  {
134
195
  name: "Privacy",
135
- action: common_2.CommonTypes.HeaderModifierAction.REMOVE
196
+ action: common_1.CommonTypes.HeaderModifierAction.REMOVE
136
197
  },
137
198
  {
138
199
  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
200
+ value: (privacy === null || privacy === void 0 ? void 0 : privacy.toLocaleLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
201
+ ? common_1.CommonTypes.Privacy.PRIVATE
202
+ : common_1.CommonTypes.Privacy.NONE,
203
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
143
204
  },
144
205
  (0, utils_1.createRemotePartyId)(trunk, number),
145
206
  (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:
@@ -78,7 +78,7 @@ function ConnectProcessor(config) {
78
78
  res.send((0, tailor_1.tailor)(processor_1.Helper.createRouteFromLastMessage(req), req));
79
79
  break;
80
80
  default:
81
- yield (0, handlers_1.handleRequest)(location, common_2.CommonConnect.dataAPI(config.apiAddr))(req, res);
81
+ (0, handlers_1.handleRequest)(location, common_2.CommonConnect.dataAPI(config.apiAddr))(req, res);
82
82
  }
83
83
  }));
84
84
  }
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.11",
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.11",
32
+ "@routr/location": "^2.0.8-alpha.11",
33
+ "@routr/processor": "^2.0.8-alpha.11"
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": "627659ac51d0814a3106bcaac31a15c581a5809f"
49
49
  }