@routr/connect 2.0.5-alpha.8 → 2.0.6-alpha.0

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,25 @@
1
+ import { ROUTING_DIRECTION } from "./types";
2
+ /**
3
+ * Throw when the API server is unavailable.
4
+ */
5
+ export declare class ServiceUnavailableError extends Error {
6
+ code: number;
7
+ /**
8
+ * Create a new ServiceUnavailableError.
9
+ *
10
+ * @param {string} message - The error message
11
+ */
12
+ constructor(message: string);
13
+ }
14
+ /**
15
+ * Throw when the route is not supported.
16
+ */
17
+ export declare class UnsuportedRoutingError extends Error {
18
+ code: number;
19
+ /**
20
+ * Create a new ServiceUnavailableError.
21
+ *
22
+ * @param {string} routingDir - The routing direction
23
+ */
24
+ constructor(routingDir: ROUTING_DIRECTION);
25
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.UnsuportedRoutingError = exports.ServiceUnavailableError = void 0;
27
+ /*
28
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
29
+ * http://github.com/fonoster/routr
30
+ *
31
+ * This file is part of Routr
32
+ *
33
+ * Licensed under the MIT License (the "License");
34
+ * you may not use this file except in compliance with
35
+ * the License. You may obtain a copy of the License at
36
+ *
37
+ * https://opensource.org/licenses/MIT
38
+ *
39
+ * Unless required by applicable law or agreed to in writing, software
40
+ * distributed under the License is distributed on an "AS IS" BASIS,
41
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42
+ * See the License for the specific language governing permissions and
43
+ * limitations under the License.
44
+ */
45
+ const grpc = __importStar(require("@grpc/grpc-js"));
46
+ /**
47
+ * Throw when the API server is unavailable.
48
+ */
49
+ class ServiceUnavailableError extends Error {
50
+ /**
51
+ * Create a new ServiceUnavailableError.
52
+ *
53
+ * @param {string} message - The error message
54
+ */
55
+ constructor(message) {
56
+ super(message);
57
+ this.code = grpc.status.UNAVAILABLE;
58
+ // Set the prototype explicitly.
59
+ Object.setPrototypeOf(this, ServiceUnavailableError.prototype);
60
+ }
61
+ }
62
+ exports.ServiceUnavailableError = ServiceUnavailableError;
63
+ /**
64
+ * Throw when the route is not supported.
65
+ */
66
+ class UnsuportedRoutingError extends Error {
67
+ /**
68
+ * Create a new ServiceUnavailableError.
69
+ *
70
+ * @param {string} routingDir - The routing direction
71
+ */
72
+ constructor(routingDir) {
73
+ super("unsupported routing direction: " + routingDir);
74
+ this.code = grpc.status.UNKNOWN;
75
+ // Set the prototype explicitly.
76
+ Object.setPrototypeOf(this, ServiceUnavailableError.prototype);
77
+ }
78
+ }
79
+ exports.UnsuportedRoutingError = UnsuportedRoutingError;
@@ -0,0 +1,6 @@
1
+ import { MessageRequest, Response } from "@routr/processor";
2
+ import { ILocationService } from "@routr/location/src/types";
3
+ import { CommonConnect as CC } from "@routr/common";
4
+ export declare const handleRegister: (location: ILocationService) => (request: MessageRequest, res: Response) => Promise<void>;
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>;
@@ -0,0 +1,74 @@
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.handleRequest = exports.handleRegistry = exports.handleRegister = void 0;
13
+ /*
14
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster/routr
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 location_1 = require("@routr/location");
32
+ const tailor_1 = require("./tailor");
33
+ const processor_1 = require("@routr/processor");
34
+ const function_1 = require("fp-ts/function");
35
+ const router_1 = require("./router");
36
+ const common_1 = require("@routr/common");
37
+ const handleRegister = (location) => {
38
+ 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();
44
+ });
45
+ };
46
+ exports.handleRegister = handleRegister;
47
+ // TODO: Needs test
48
+ const handleRegistry = (req, res) => {
49
+ 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);
52
+ };
53
+ exports.handleRegistry = handleRegistry;
54
+ // TODO: If request has X-Connect-Token then validate the JWT value and continue
55
+ const handleRequest = (location, dataAPI) => (req, res) => __awaiter(void 0, void 0, void 0, function* () {
56
+ try {
57
+ const route = processor_1.Extensions.getHeaderValue(req, common_1.CommonTypes.ExtraHeader.EDGEPORT_REF)
58
+ ? processor_1.Helper.createRouteFromLastMessage(req)
59
+ : yield (0, router_1.router)(location, dataAPI)(req);
60
+ if (!route)
61
+ 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);
67
+ }
68
+ res.send((0, tailor_1.tailor)(route, req));
69
+ }
70
+ catch (err) {
71
+ res.sendError(err);
72
+ }
73
+ });
74
+ exports.handleRequest = handleRequest;
@@ -0,0 +1,5 @@
1
+ import { Route } from "@routr/common";
2
+ import { MessageRequest } from "@routr/processor";
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>;
package/dist/router.js ADDED
@@ -0,0 +1,138 @@
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.router = void 0;
13
+ /*
14
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster/routr
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 types_1 = require("./types");
32
+ const utils_1 = require("./utils");
33
+ const processor_1 = require("@routr/processor");
34
+ const errors_1 = require("./errors");
35
+ const location_1 = require("@routr/location");
36
+ const logger_1 = require("@fonoster/logger");
37
+ const common_1 = require("@routr/common");
38
+ const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
39
+ const getSIPURI = (uri) => `sip:${uri.user}@${uri.host}`;
40
+ // eslint-disable-next-line require-jsdoc
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;
45
+ logger.verbose("routing request from: " +
46
+ getSIPURI(fromURI) +
47
+ ", to: " +
48
+ getSIPURI(requestURI), { fromURI: getSIPURI(fromURI), requestURI: getSIPURI(requestURI) });
49
+ const caller = yield (0, utils_1.findResource)(dataAPI, fromURI.host, fromURI.user);
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);
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);
59
+ default:
60
+ throw new errors_1.UnsuportedRoutingError(routingDir);
61
+ }
62
+ });
63
+ }
64
+ exports.router = router;
65
+ // eslint-disable-next-line require-jsdoc
66
+ function agentToAgent(location, req) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ return (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req) }))[0];
69
+ });
70
+ }
71
+ /**
72
+ * From PSTN routing.
73
+ *
74
+ * @param {ILocationService} location - Location service
75
+ * @param {uknown} _
76
+ * @param {Resource} callee - The callee
77
+ * @return {Promise<Route>}
78
+ */
79
+ function fromPSTN(location, _, callee) {
80
+ var _a;
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ const route = (yield location.findRoutes({
83
+ aor: callee.spec.location.aorLink
84
+ }))[0];
85
+ if (!route) {
86
+ throw new location_1.NotRoutesFoundForAOR(callee.spec.location.aorLink);
87
+ }
88
+ if (!route.headers)
89
+ route.headers = [];
90
+ (_a = callee.spec.location.props) === null || _a === void 0 ? void 0 : _a.forEach((prop) => {
91
+ const p = {
92
+ name: prop.name,
93
+ value: prop.value,
94
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
95
+ };
96
+ route.headers.push(p);
97
+ });
98
+ return route;
99
+ });
100
+ }
101
+ // eslint-disable-next-line require-jsdoc
102
+ function toPSTN(dataAPI, req, caller) {
103
+ var _a;
104
+ return __awaiter(this, void 0, void 0, function* () {
105
+ const domain = yield dataAPI.get(caller.spec.domainRef);
106
+ const number = yield dataAPI.get((_a = domain.spec.context.egressPolicy) === null || _a === void 0 ? void 0 : _a.numberRef);
107
+ const trunk = yield dataAPI.get(number === null || number === void 0 ? void 0 : number.spec.trunkRef);
108
+ if (!domain.spec.context.egressPolicy) {
109
+ // TODO: Create custom error
110
+ throw new Error("no egress policy found for Domain ref" + domain.metadata.ref);
111
+ }
112
+ if (!trunk) {
113
+ // TODO: Create custom error
114
+ throw new Error("no trunk associated with Number ref: " + number.metadata.ref);
115
+ }
116
+ const uri = (0, utils_1.getTrunkURI)(trunk);
117
+ return {
118
+ user: uri.user,
119
+ host: uri.host,
120
+ port: uri.port,
121
+ transport: uri.transport,
122
+ edgePortRef: req.edgePortRef,
123
+ listeningPoint: req.listeningPoint,
124
+ headers: [
125
+ {
126
+ name: "Privacy",
127
+ value: caller.spec.privacy === common_1.CommonTypes.Privacy.PRIVATE
128
+ ? common_1.CommonTypes.Privacy.PRIVATE
129
+ : common_1.CommonTypes.Privacy.NONE,
130
+ action: common_1.CommonTypes.HeaderModifierAction.ADD
131
+ },
132
+ (0, utils_1.createRemotePartyId)(trunk, number),
133
+ (0, utils_1.createPAssertedIdentity)(req, trunk, number),
134
+ yield (0, utils_1.createTrunkAuthentication)(dataAPI, trunk)
135
+ ]
136
+ };
137
+ });
138
+ }
package/dist/runner.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
+ var _a;
6
7
  Object.defineProperty(exports, "__esModule", { value: true });
7
8
  /*
8
9
  * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
@@ -22,15 +23,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
23
  * See the License for the specific language governing permissions and
23
24
  * limitations under the License.
24
25
  */
25
- const logger_1 = __importDefault(require("@fonoster/logger"));
26
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
27
+ require("./tracer").init("dispatcher");
26
28
  const service_1 = __importDefault(require("./service"));
27
- if (process.env.LOCATION_ADDR) {
28
- service_1.default({
29
- bindAddr: process.env.BIND_ADDR || "0.0.0.0:51904",
30
- locationAddr: process.env.LOCATION_ADDR
31
- });
32
- }
33
- else {
34
- logger_1.default.error("environment variable LOCATION_ADDR is required but was not found");
35
- process.exit(1);
36
- }
29
+ const common_1 = require("@routr/common");
30
+ common_1.Assertions.assertEnvsAreSet(["LOCATION_ADDR", "API_ADDR"]);
31
+ (0, service_1.default)({
32
+ bindAddr: (_a = process.env.BIND_ADDR) !== null && _a !== void 0 ? _a : "0.0.0.0:51904",
33
+ locationAddr: process.env.LOCATION_ADDR,
34
+ apiAddr: process.env.API_ADDR
35
+ });
package/dist/service.js CHANGED
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,33 +31,66 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
31
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
32
  });
10
33
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
+ const common_1 = require("@routr/common");
15
36
  const location_1 = require("@routr/location");
16
- const utils_1 = require("./utils");
17
- const processor_1 = __importDefault(require("@routr/processor"));
18
- const logger_1 = __importDefault(require("@fonoster/logger"));
37
+ const handlers_1 = require("./handlers");
38
+ const processor_1 = __importStar(require("@routr/processor"));
39
+ const common_2 = require("@routr/common");
40
+ const tailor_1 = require("./tailor");
41
+ const logger_1 = require("@fonoster/logger");
42
+ const logger = (0, logger_1.getLogger)({ service: "connect", filePath: __filename });
43
+ // eslint-disable-next-line require-jsdoc
19
44
  function ConnectProcessor(config) {
20
45
  const { bindAddr, locationAddr } = config;
21
46
  const location = new location_1.LocationClient({ addr: locationAddr });
22
- new processor_1.default({ bindAddr, name: "connect" })
23
- .listen((req, res) => __awaiter(this, void 0, void 0, function* () {
24
- logger_1.default.silly(JSON.stringify(req, null, ' '));
47
+ new processor_1.default({ bindAddr, name: "connect" }).listen((req, res) => __awaiter(this, void 0, void 0, function* () {
48
+ logger.verbose("connect processor received new request", {
49
+ ref: req.ref,
50
+ method: req.method,
51
+ type: req.message.messageType === common_2.CommonTypes.MessageType.RESPONSE
52
+ ? "(response)"
53
+ : "(request)",
54
+ edgePort: req.edgePortRef
55
+ });
56
+ logger.silly(JSON.stringify(req, null, " "));
57
+ // Check if is response and simply forwards to endpoint
58
+ if (processor_1.Helper.isTypeResponse(req)) {
59
+ // Remove the proxy via before forwarding response
60
+ return res.send(processor_1.Alterations.removeTopVia(req));
61
+ }
25
62
  switch (req.method.toString()) {
26
- case 'PUBLISH':
27
- case 'NOTIFY':
28
- case 'SUBSCRIBE':
63
+ case common_1.Method.PUBLISH:
64
+ case common_1.Method.NOTIFY:
65
+ case common_1.Method.SUBSCRIBE:
29
66
  res.sendMethodNotAllowed();
30
67
  break;
31
- case 'REGISTER':
32
- yield utils_1.createRegisterHandler(location)(req, res);
68
+ case common_1.Method.CANCEL:
69
+ // eslint-disable-next-line no-case-declarations
70
+ const route = (yield location.findRoutes({ aor: processor_1.Target.getTargetAOR(req) }))[0];
71
+ if (route) {
72
+ res.sendOk([
73
+ {
74
+ name: common_2.CommonTypes.ExtraHeader.REQUEST_URI,
75
+ value: `${route === null || route === void 0 ? void 0 : route.user},${route.host},${route.port},${route.transport}`
76
+ }
77
+ ]);
78
+ }
79
+ break;
80
+ case common_1.Method.REGISTER:
81
+ if (processor_1.Extensions.getHeaderValue(req, common_2.CommonTypes.ExtraHeader.GATEWAY_AUTH)) {
82
+ (0, handlers_1.handleRegistry)(req, res);
83
+ }
84
+ else {
85
+ (0, handlers_1.handleRegister)(location)(req, res);
86
+ }
33
87
  break;
34
- case 'CANCEL':
88
+ case common_1.Method.BYE:
89
+ case common_1.Method.ACK:
90
+ res.send((0, tailor_1.tailor)(processor_1.Helper.createRouteFromLastMessage(req), req));
35
91
  break;
36
92
  default:
37
- res.sendNotImplemented();
93
+ yield (0, handlers_1.handleRequest)(location, common_2.CommonConnect.dataAPI(config.apiAddr))(req, res);
38
94
  }
39
95
  }));
40
96
  }
@@ -0,0 +1,3 @@
1
+ import { MessageRequest } from "@routr/processor";
2
+ import { Route } from "@routr/common";
3
+ export declare const tailor: (route: Route, req: MessageRequest) => MessageRequest;
package/dist/tailor.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tailor = void 0;
4
+ /*
5
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/routr
7
+ *
8
+ * This file is part of Routr
9
+ *
10
+ * Licensed under the MIT License (the "License")
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ const processor_1 = require("@routr/processor");
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)(req, 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
26
+ // Add updateContact for SIP.js support
27
+ );
28
+ exports.tailor = tailor;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This function registers the instrumentations for the service.
3
+ *
4
+ * @param {string} serviceName - The name of the service.
5
+ * @return {Tracer} The tracer object.
6
+ */
7
+ export declare function init(serviceName: string): import("@opentelemetry/api").Tracer;
package/dist/tracer.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.init = void 0;
7
+ /*
8
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
9
+ * http://github.com/fonoster/routr
10
+ *
11
+ * This file is part of Routr
12
+ *
13
+ * Licensed under the MIT License (the "License")
14
+ * you may not use this file except in compliance with
15
+ * the License. You may obtain a copy of the License at
16
+ *
17
+ * https://opensource.org/licenses/MIT
18
+ *
19
+ * Unless required by applicable law or agreed to in writing, software
20
+ * distributed under the License is distributed on an "AS IS" BASIS,
21
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ * See the License for the specific language governing permissions and
23
+ * limitations under the License.
24
+ */
25
+ const api_1 = __importDefault(require("@opentelemetry/api"));
26
+ const instrumentation_1 = require("@opentelemetry/instrumentation");
27
+ const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
28
+ const resources_1 = require("@opentelemetry/resources");
29
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
30
+ const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
31
+ const exporter_jaeger_1 = require("@opentelemetry/exporter-jaeger");
32
+ const instrumentation_grpc_1 = require("@opentelemetry/instrumentation-grpc");
33
+ /**
34
+ * This function registers the instrumentations for the service.
35
+ *
36
+ * @param {string} serviceName - The name of the service.
37
+ * @return {Tracer} The tracer object.
38
+ */
39
+ function init(serviceName) {
40
+ const provider = new sdk_trace_node_1.NodeTracerProvider({
41
+ resource: new resources_1.Resource({
42
+ [semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAME]: serviceName
43
+ })
44
+ });
45
+ const exporter = new exporter_jaeger_1.JaegerExporter();
46
+ provider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(exporter));
47
+ provider.register();
48
+ (0, instrumentation_1.registerInstrumentations)({
49
+ instrumentations: [new instrumentation_grpc_1.GrpcInstrumentation()]
50
+ });
51
+ return api_1.default.trace.getTracer("routr-tracer");
52
+ }
53
+ exports.init = init;
package/dist/types.d.ts CHANGED
@@ -1,4 +1,17 @@
1
+ import { HeaderModifier } from "@routr/common";
2
+ export declare enum ROUTING_DIRECTION {
3
+ FROM_PSTN = "from-pstn",
4
+ AGENT_TO_AGENT = "agent-to-agent",
5
+ AGENT_TO_PSTN = "agent-to-pstn",
6
+ PEER_TO_AGENT = "peer-to-agent",
7
+ PEER_TO_PSTN = "peer-to-pstn",
8
+ UNKNOWN = "unknown"
9
+ }
1
10
  export interface ConnectProcessorConfig {
2
11
  bindAddr: string;
3
12
  locationAddr: string;
13
+ apiAddr: string;
14
+ }
15
+ export interface ConnectObject {
16
+ headers?: HeaderModifier[];
4
17
  }
package/dist/types.js CHANGED
@@ -1,2 +1,12 @@
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 = {}));
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,16 @@
1
- import { MessageRequest } from "@routr/common";
2
- import { Response } from "@routr/processor";
3
- export declare const createRegisterHandler: (location: any) => (request: MessageRequest, res: Response) => Promise<void>;
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;
5
+ export declare const findDomain: (dataAPI: CC.DataAPI, domainUri: string) => Promise<CC.Resource>;
6
+ 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 createPAssertedIdentity: (req: MessageRequest, trunk: CC.Resource, number: CC.Resource) => HeaderModifier;
9
+ export declare const createRemotePartyId: (trunk: CC.Resource, number: CC.Resource) => HeaderModifier;
10
+ export declare const createTrunkAuthentication: (dataAPI: CC.DataAPI, trunk: CC.Resource) => Promise<HeaderModifier>;
11
+ export declare const getTrunkURI: (trunk: CC.Resource) => {
12
+ host: string;
13
+ port: number;
14
+ user: string;
15
+ transport: Transport;
16
+ };
package/dist/utils.js CHANGED
@@ -9,16 +9,136 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.createRegisterHandler = void 0;
13
- const location_1 = require("@routr/location");
14
- const processor_1 = require("@routr/processor");
15
- const createRegisterHandler = (location) => {
16
- return (request, res) => __awaiter(void 0, void 0, void 0, function* () {
17
- yield location.addRoute({
18
- aor: processor_1.Target.getTargetAOR(request),
19
- route: location_1.Helper.createRoute(request)
20
- });
21
- res.sendOk();
22
- });
12
+ exports.getTrunkURI = exports.createTrunkAuthentication = exports.createRemotePartyId = exports.createPAssertedIdentity = exports.getRoutingDirection = exports.findResource = exports.findDomain = exports.isKind = void 0;
13
+ /*
14
+ * Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
15
+ * http://github.com/fonoster/routr
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 common_1 = require("@routr/common");
32
+ const common_2 = require("@routr/common");
33
+ const types_1 = require("./types");
34
+ const isKind = (res, kind) => {
35
+ if (res == null && kind === common_2.CommonConnect.KIND.UNKNOWN) {
36
+ return true;
37
+ }
38
+ return (res === null || res === void 0 ? void 0 : res.kind.toLowerCase()) === kind;
39
+ };
40
+ exports.isKind = isKind;
41
+ const findDomain = (dataAPI, domainUri) => __awaiter(void 0, void 0, void 0, function* () {
42
+ return (yield dataAPI.findBy({
43
+ kind: common_2.CommonConnect.KIND.DOMAIN,
44
+ criteria: common_2.CommonConnect.FindCriteria.FIND_DOMAIN_BY_DOMAINURI,
45
+ parameters: {
46
+ domainUri
47
+ }
48
+ }))[0];
49
+ });
50
+ 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,
57
+ parameters: {
58
+ telUrl: `tel:${userpart}`
59
+ }
60
+ }))[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) &&
72
+ res.spec.domainRef != (domain === null || domain === void 0 ? void 0 : domain.metadata.ref)) {
73
+ // Not in the same domain
74
+ return null;
75
+ }
76
+ return res;
77
+ });
78
+ exports.findResource = findResource;
79
+ const getRoutingDirection = (caller, callee) => {
80
+ if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.AGENT) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.AGENT)) {
81
+ return types_1.ROUTING_DIRECTION.AGENT_TO_AGENT;
82
+ }
83
+ if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.AGENT) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.UNKNOWN)) {
84
+ return types_1.ROUTING_DIRECTION.AGENT_TO_PSTN;
85
+ }
86
+ if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.PEER) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.AGENT)) {
87
+ return types_1.ROUTING_DIRECTION.PEER_TO_AGENT;
88
+ }
89
+ // All we know is that the Number is managed by this instance of Routr
90
+ if ((0, exports.isKind)(callee, common_2.CommonConnect.KIND.NUMBER)) {
91
+ return types_1.ROUTING_DIRECTION.FROM_PSTN;
92
+ }
93
+ if ((0, exports.isKind)(caller, common_2.CommonConnect.KIND.PEER) && (0, exports.isKind)(callee, common_2.CommonConnect.KIND.UNKNOWN)) {
94
+ return types_1.ROUTING_DIRECTION.PEER_TO_PSTN;
95
+ }
96
+ return types_1.ROUTING_DIRECTION.UNKNOWN;
97
+ };
98
+ exports.getRoutingDirection = getRoutingDirection;
99
+ const createPAssertedIdentity = (req, trunk, number) => {
100
+ const displayName = req.message.from.address.displayName;
101
+ const remoteNumber = number.spec.location.telUrl.split(":")[1];
102
+ const trunkHost = (0, exports.getTrunkURI)(trunk).host;
103
+ return {
104
+ name: "P-Asserted-Identity",
105
+ value: displayName
106
+ ? `"${displayName}" <sip:${remoteNumber}@${trunkHost};user=phone>`
107
+ : `<sip:${remoteNumber}@${trunkHost};user=phone>`,
108
+ action: common_2.CommonTypes.HeaderModifierAction.ADD
109
+ };
110
+ };
111
+ exports.createPAssertedIdentity = createPAssertedIdentity;
112
+ const createRemotePartyId = (trunk, number) => {
113
+ const remoteNumber = number.spec.location.telUrl.split(":")[1];
114
+ const trunkHost = (0, exports.getTrunkURI)(trunk).host;
115
+ return {
116
+ name: "Remote-Party-ID",
117
+ value: `<sip:${remoteNumber}@${trunkHost}>;screen=yes;party=calling`,
118
+ action: common_2.CommonTypes.HeaderModifierAction.ADD
119
+ };
120
+ };
121
+ exports.createRemotePartyId = createRemotePartyId;
122
+ const createTrunkAuthentication = (dataAPI, trunk) => __awaiter(void 0, void 0, void 0, function* () {
123
+ const credentials = yield dataAPI.get(trunk.spec.outbound.credentialsRef);
124
+ return {
125
+ name: common_2.CommonTypes.ExtraHeader.GATEWAY_AUTH,
126
+ value: Buffer.from(`${credentials.spec.credentials.username}:${credentials.spec.credentials.password}`).toString("base64"),
127
+ action: common_2.CommonTypes.HeaderModifierAction.ADD
128
+ };
129
+ });
130
+ exports.createTrunkAuthentication = createTrunkAuthentication;
131
+ 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;
134
+ const t = !transport
135
+ ? common_1.Transport.UDP
136
+ : Object.keys(common_1.Transport)[Object.values(common_1.Transport).indexOf(transport.toUpperCase())];
137
+ return {
138
+ user,
139
+ host,
140
+ port: port !== null && port !== void 0 ? port : 5060,
141
+ transport: t
142
+ };
23
143
  };
24
- exports.createRegisterHandler = createRegisterHandler;
144
+ exports.getTrunkURI = getTrunkURI;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routr/connect",
3
- "version": "2.0.5-alpha.8",
3
+ "version": "2.0.6-alpha.0",
4
4
  "description": "Default processor",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/routr#readme",
@@ -19,10 +19,18 @@
19
19
  "run_connect": "dist/runner.js"
20
20
  },
21
21
  "dependencies": {
22
- "@fonoster/logger": "^0.3.3",
23
- "@routr/common": "^2.0.5-alpha.8",
24
- "@routr/location": "^2.0.5-alpha.8",
25
- "@routr/processor": "^2.0.5-alpha.8"
22
+ "@fonoster/logger": "0.3.17-alpha.2",
23
+ "@opentelemetry/api": "^1.0.4",
24
+ "@opentelemetry/exporter-jaeger": "^1.0.4",
25
+ "@opentelemetry/instrumentation": "^0.27.0",
26
+ "@opentelemetry/instrumentation-grpc": "^0.27.0",
27
+ "@opentelemetry/resources": "^1.0.4",
28
+ "@opentelemetry/sdk-trace-base": "^1.0.4",
29
+ "@opentelemetry/sdk-trace-node": "^1.0.4",
30
+ "@opentelemetry/semantic-conventions": "^1.0.4",
31
+ "@routr/common": "^2.0.6-alpha.0",
32
+ "@routr/location": "^2.0.6-alpha.0",
33
+ "@routr/processor": "^2.0.6-alpha.0"
26
34
  },
27
35
  "files": [
28
36
  "dist"
@@ -37,5 +45,5 @@
37
45
  "bugs": {
38
46
  "url": "https://github.com/fonoster/routr/issues"
39
47
  },
40
- "gitHead": "e093bd9f05f7600a419f4e3d9eb41643b3682218"
48
+ "gitHead": "0829f7e9b5b3ebba7eb984da5436d7c07689d776"
41
49
  }