@routr/connect 2.0.8-alpha.0 → 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,21 +34,44 @@ 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;
47
71
  // TODO: Needs test
48
72
  const handleRegistry = (req, res) => {
49
73
  const route = processor_1.Helper.createRouteFromLastMessage(req);
50
- const newReq = (0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeRoutes, processor_1.Alterations.removeXEdgePortRef);
51
- res.send(newReq);
74
+ res.send((0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeRoutes, processor_1.Alterations.removeXEdgePortRef));
52
75
  };
53
76
  exports.handleRegistry = handleRegistry;
54
77
  // TODO: If request has X-Connect-Token then validate the JWT value and continue
@@ -59,13 +82,17 @@ const handleRequest = (location, dataAPI) => (req, res) => __awaiter(void 0, voi
59
82
  : yield (0, router_1.router)(location, dataAPI)(req);
60
83
  if (!route)
61
84
  return res.sendNotFound();
62
- // Forward request to peer edgeport
63
- if (req.edgePortRef !== route.edgePortRef) {
64
- return (0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route),
65
- // The LP address belongs to another edgeport
66
- 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));
67
95
  }
68
- res.send((0, tailor_1.tailor)(route, req));
69
96
  }
70
97
  catch (err) {
71
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
@@ -29,35 +29,49 @@ exports.router = void 0;
29
29
  * limitations under the License.
30
30
  */
31
31
  const types_1 = require("./types");
32
+ const common_1 = require("@routr/common");
32
33
  const utils_1 = require("./utils");
33
34
  const processor_1 = require("@routr/processor");
34
- const errors_1 = require("./errors");
35
35
  const location_1 = require("@routr/location");
36
+ const errors_1 = require("./errors");
36
37
  const logger_1 = require("@fonoster/logger");
37
- const common_1 = require("@routr/common");
38
+ const access_1 = require("./access");
38
39
  const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
39
- const getSIPURI = (uri) => `sip:${uri.user}@${uri.host}`;
40
40
  // eslint-disable-next-line require-jsdoc
41
41
  function router(location, dataAPI) {
42
- return (req) => __awaiter(this, void 0, void 0, function* () {
43
- const fromURI = req.message.from.address.uri;
44
- 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;
45
45
  logger.verbose("routing request from: " +
46
- getSIPURI(fromURI) +
46
+ (0, utils_1.getSIPURI)(fromURI) +
47
47
  ", to: " +
48
- 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) });
49
49
  const caller = yield (0, utils_1.findResource)(dataAPI, fromURI.host, fromURI.user);
50
50
  const callee = yield (0, utils_1.findResource)(dataAPI, requestURI.host, requestURI.user);
51
- const routingDir = (0, utils_1.getRoutingDirection)(caller, callee);
52
- switch (routingDir) {
53
- case types_1.ROUTING_DIRECTION.AGENT_TO_PSTN:
54
- return yield toPSTN(dataAPI, req, caller, requestURI.user);
55
- case types_1.ROUTING_DIRECTION.AGENT_TO_AGENT:
56
- return agentToAgent(location, req);
57
- case types_1.ROUTING_DIRECTION.FROM_PSTN:
58
- 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);
59
73
  default:
60
- throw new errors_1.UnsuportedRoutingError(routingDir);
74
+ throw new errors_1.UnsuportedRoutingError(routingDirection);
61
75
  }
62
76
  });
63
77
  }
@@ -72,11 +86,10 @@ function agentToAgent(location, req) {
72
86
  * From PSTN routing.
73
87
  *
74
88
  * @param {ILocationService} location - Location service
75
- * @param {uknown} _
76
89
  * @param {Resource} callee - The callee
77
90
  * @return {Promise<Route>}
78
91
  */
79
- function fromPSTN(location, _, callee) {
92
+ function fromPSTN(location, callee) {
80
93
  var _a;
81
94
  return __awaiter(this, void 0, void 0, function* () {
82
95
  const route = (yield location.findRoutes({
@@ -99,24 +112,68 @@ function fromPSTN(location, _, callee) {
99
112
  });
100
113
  }
101
114
  // eslint-disable-next-line require-jsdoc
102
- function toPSTN(dataAPI, req, caller, calleeNumber) {
103
- var _a, _b;
115
+ function agentToPSTN(dataAPI, req, caller, calleeNumber) {
116
+ var _a;
104
117
  return __awaiter(this, void 0, void 0, function* () {
105
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
+ }
106
123
  // Look for Number in domain that matches regex callee
107
- 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) => {
108
125
  const regex = new RegExp(policy.rule);
109
126
  return regex.test(calleeNumber);
110
127
  });
111
128
  const number = yield dataAPI.get(policy === null || policy === void 0 ? void 0 : policy.numberRef);
112
129
  const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
113
- if (!domain.spec.context.egressPolicies) {
114
- // TODO: Create custom error
115
- 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}`);
116
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}`);
172
+ }
173
+ const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
117
174
  if (!trunk) {
118
175
  // TODO: Create custom error
119
- 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}`);
120
177
  }
121
178
  const uri = (0, utils_1.getTrunkURI)(trunk);
122
179
  return {
@@ -125,11 +182,18 @@ function toPSTN(dataAPI, req, caller, calleeNumber) {
125
182
  port: uri.port,
126
183
  transport: uri.transport,
127
184
  edgePortRef: req.edgePortRef,
128
- listeningPoint: req.listeningPoint,
185
+ listeningPoints: req.listeningPoints,
186
+ localnets: req.localnets,
187
+ externalAddrs: req.externalAddrs,
129
188
  headers: [
189
+ // TODO: Find a more deterministic way to re-add the Privacy header
190
+ {
191
+ name: "Privacy",
192
+ action: common_1.CommonTypes.HeaderModifierAction.REMOVE
193
+ },
130
194
  {
131
195
  name: "Privacy",
132
- value: ((_b = caller.spec.privacy) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
196
+ value: (privacy === null || privacy === void 0 ? void 0 : privacy.toLocaleLowerCase()) === common_1.CommonTypes.Privacy.PRIVATE
133
197
  ? common_1.CommonTypes.Privacy.PRIVATE
134
198
  : common_1.CommonTypes.Privacy.NONE,
135
199
  action: common_1.CommonTypes.HeaderModifierAction.ADD
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/tailor.js CHANGED
@@ -21,10 +21,8 @@ exports.tailor = void 0;
21
21
  */
22
22
  const processor_1 = require("@routr/processor");
23
23
  const function_1 = require("fp-ts/function");
24
- // Q: Shoukd we add support for strict routing?
25
- const tailor = (route, req) => (0, function_1.pipe)(
26
- // TODO: Fix this hardcode
27
- processor_1.Extensions.removeHeader(req, "Privacy"), processor_1.Alterations.addSelfVia(route), processor_1.Alterations.applyXHeaders(route), processor_1.Alterations.addRoute(route), processor_1.Alterations.addSelfRecordRoute, processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeRoutes, processor_1.Alterations.removeXEdgePortRef
24
+ // Q: Should we add support for strict routing?
25
+ const tailor = (route, req) => (0, function_1.pipe)(req, processor_1.Alterations.addSelfVia(route), processor_1.Alterations.applyXHeaders(route), processor_1.Alterations.addRoute(route), processor_1.Alterations.addSelfRecordRoute(route), processor_1.Alterations.decreaseMaxForwards, processor_1.Alterations.removeAuthorization, processor_1.Alterations.removeRoutes, processor_1.Alterations.removeXEdgePortRef
28
26
  // Add updateContact for SIP.js support
29
27
  );
30
28
  exports.tailor = tailor;
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,18 +145,20 @@ 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
- : Object.keys(common_1.Transport)[Object.values(common_1.Transport).indexOf(transport.toUpperCase())];
161
+ : Object.values(common_1.Transport)[Object.values(common_1.Transport).indexOf(transport.toLowerCase())];
137
162
  return {
138
163
  user,
139
164
  host,
@@ -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.0",
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.0",
32
- "@routr/location": "^2.0.8-alpha.0",
33
- "@routr/processor": "^2.0.8-alpha.0"
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": "69c60f113c27bc00cbadb62dbdbbb70960ef0f4d"
48
+ "gitHead": "5082233fb155ddb8535f934550fa4013da87468e"
49
49
  }