arnacon-webrtc-service 0.1.2 → 0.1.3

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,42 @@
1
+ {
2
+ "development": {
3
+ "roflBaseUrl": "https://p8000.m1485.test-proxy-b.rofl.app",
4
+ "messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
5
+ "polygon": {
6
+ "rpc": "https://polygon-bor-rpc.publicnode.com",
7
+ "ENSRegistry": "0x6e0A65396233B8A29d76cA2DDd87bc5F19A82c36",
8
+ "NameWrapper": "0xCAb1585C37118d066Bc3AD79919B4CAE5cd42BC2",
9
+ "ServiceProviderRegistry": "0x86F58E4AadCB0188a11447641F4df3d66323959d",
10
+ "ProvisionRegistry": "0x461f38fdCD44a92cD0fBE7ba9498903EFd944740",
11
+ "CustomENS": "0xb32Feb0530C73FEc90BB985fA40894196938a9f6"
12
+ },
13
+ "sapphire": {
14
+ "rpc": "https://sapphire.oasis.io",
15
+ "NotificationManagerRegistry": "0xB5B5a6320BB0Fdf3F08122475F71B51f5210B437"
16
+ },
17
+ "sapphireTestnet": {
18
+ "rpc": "https://testnet.sapphire.oasis.io",
19
+ "NFTCallerIdPool": "0xFB3DD146F1aFfbA661533Ec49298D01f20104CF6"
20
+ }
21
+ },
22
+ "production": {
23
+ "roflBaseUrl": "https://p8000.m206.opf-mainnet-rofl-35.rofl.app",
24
+ "messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
25
+ "polygon": {
26
+ "rpc": "https://polygon-bor-rpc.publicnode.com",
27
+ "ENSRegistry": "0x6e0A65396233B8A29d76cA2DDd87bc5F19A82c36",
28
+ "NameWrapper": "0xCAb1585C37118d066Bc3AD79919B4CAE5cd42BC2",
29
+ "ServiceProviderRegistry": "0x86F58E4AadCB0188a11447641F4df3d66323959d",
30
+ "ProvisionRegistry": "0x461f38fdCD44a92cD0fBE7ba9498903EFd944740",
31
+ "CustomENS": "0xb32Feb0530C73FEc90BB985fA40894196938a9f6"
32
+ },
33
+ "sapphire": {
34
+ "rpc": "https://sapphire.oasis.io",
35
+ "NotificationManagerRegistry": "0xB5B5a6320BB0Fdf3F08122475F71B51f5210B437"
36
+ },
37
+ "sapphireTestnet": {
38
+ "rpc": "https://sapphire.oasis.io",
39
+ "NFTCallerIdPool": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269"
40
+ }
41
+ }
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arnacon-webrtc-service",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Arnacon WebRTC core runtime and service modules",
5
5
  "main": "./webRTCservice/core.js",
6
6
  "type": "commonjs",
@@ -17,7 +17,7 @@
17
17
  "files": [
18
18
  "webRTCservice/**/*",
19
19
  "services/**/*",
20
- "config.json"
20
+ "globalserviceconfig.json"
21
21
  ],
22
22
  "scripts": {
23
23
  "build": "node webRTCservice/build.js",
@@ -86,9 +86,27 @@ function createCallRuntimeCore({
86
86
  async function routeCall(sessionId, session, destination, parsedFrom) {
87
87
  if (destination.route === "sbc") {
88
88
  const callerIdResult = await resolveCallerId(parsedFrom, session.walletAddress, session.serviceId || null);
89
- const sipFrom = callerIdResult.callerId || session.callerEns;
90
- const sipTo = destination.number;
91
- await openSipSession(sessionId, sipFrom, sipTo);
89
+ const sipFrom = callerIdResult?.callerId || session.callerEns;
90
+ const sipTo = destination?.number;
91
+ const sipDirective = {
92
+ target: destination?.target || null,
93
+ identity: callerIdResult?.identity || null,
94
+ privacy: callerIdResult?.privacy || null,
95
+ headers: {
96
+ ...(callerIdResult?.headers || {}),
97
+ "X-Arnacon-Service-Id": session?.serviceId || "",
98
+ "X-Arnacon-Session-Id": sessionId,
99
+ },
100
+ trace: {
101
+ serviceId: session?.serviceId || "",
102
+ sessionId,
103
+ callId: session?.callId || "",
104
+ },
105
+ // Backward-compatible fallback fields from current services.
106
+ callerId: callerIdResult?.callerId || null,
107
+ privateId: callerIdResult?.privateId || null,
108
+ };
109
+ await openSipSession(sessionId, sipFrom, sipTo, sipDirective);
92
110
  return "sbc";
93
111
  }
94
112
  if (destination.route === "webrtc") {
@@ -15,7 +15,7 @@ function createSipClient({
15
15
  logger = console,
16
16
  }) {
17
17
  async function openSipSession(sessionId, sessionStore, options = {}) {
18
- const { callerEns, calleeIdentity } = options;
18
+ const { callerEns, calleeIdentity, sipDirective } = options;
19
19
  const session = sessionStore.get(sessionId);
20
20
  if (!session) throw new Error("Session not found");
21
21
 
@@ -24,7 +24,9 @@ function createSipClient({
24
24
  server: kamailioWssUrl,
25
25
  webSocketConstruction: (url, protocols) => new WsWebSocket(url, protocols),
26
26
  };
27
- const sipUri = UserAgent.makeURI(`sip:${callerEns}@${kamailioDomain}`);
27
+ const fromUri = sipDirective?.identity?.fromUri || `sip:${callerEns}@${kamailioDomain}`;
28
+ const sipUri = UserAgent.makeURI(fromUri);
29
+ if (!sipUri) throw new Error(`Invalid From URI for SIP session: ${fromUri}`);
28
30
  const userAgent = new UserAgent({
29
31
  uri: sipUri,
30
32
  transportOptions,
@@ -35,9 +37,33 @@ function createSipClient({
35
37
  const registerer = new Registerer(userAgent, { expires: registerExpires });
36
38
  await registerer.register();
37
39
 
38
- const targetUri = UserAgent.makeURI(`sip:${calleeIdentity}@${kamailioDomain}`);
40
+ const toUri = sipDirective?.identity?.toUri || `sip:${calleeIdentity}@${kamailioDomain}`;
41
+ const targetUri = UserAgent.makeURI(toUri);
42
+ if (!targetUri) throw new Error(`Invalid To URI for SIP session: ${toUri}`);
43
+ const extraHeaders = [];
44
+ if (sipDirective?.identity?.paiUri) {
45
+ extraHeaders.push(`P-Asserted-Identity: <${sipDirective.identity.paiUri}>`);
46
+ } else if (sipDirective?.privateId) {
47
+ extraHeaders.push(`P-Asserted-Identity: <sip:${sipDirective.privateId}@${kamailioDomain}>`);
48
+ }
49
+ if (sipDirective?.identity?.rpidUri) {
50
+ extraHeaders.push(`Remote-Party-ID: <${sipDirective.identity.rpidUri}>`);
51
+ } else if (sipDirective?.privateId) {
52
+ extraHeaders.push(`Remote-Party-ID: <sip:${sipDirective.privateId}@${kamailioDomain}>`);
53
+ }
54
+ const privacyEnabled = sipDirective?.privacy?.enabled === true || Boolean(sipDirective?.privateId);
55
+ if (privacyEnabled) {
56
+ extraHeaders.push(`Privacy: ${sipDirective?.privacy?.value || "id"}`);
57
+ }
58
+ if (sipDirective?.headers && typeof sipDirective.headers === "object") {
59
+ for (const [name, value] of Object.entries(sipDirective.headers)) {
60
+ if (!name || value === undefined || value === null || value === "") continue;
61
+ extraHeaders.push(`${name}: ${value}`);
62
+ }
63
+ }
39
64
  const inviter = new Inviter(userAgent, targetUri, {
40
65
  sessionDescriptionHandlerOptions: { constraints: { audio: true, video: false } },
66
+ extraHeaders,
41
67
  });
42
68
 
43
69
  const SIP_INVITE_TIMEOUT = 30000;
@@ -156,8 +156,16 @@ const CONFIG_OVERRIDE = process.env.WEBRTC_CONFIG_PATH || process.env.ARNACON_WE
156
156
  const CONFIG_PATH = CONFIG_OVERRIDE
157
157
  ? (path.isAbsolute(CONFIG_OVERRIDE) ? CONFIG_OVERRIDE : path.resolve(process.cwd(), CONFIG_OVERRIDE))
158
158
  : path.join(PACKAGE_ROOT, "config.json");
159
+ const GLOBAL_CONFIG_OVERRIDE = process.env.WEBRTC_GLOBAL_CONFIG_PATH || process.env.ARNACON_WEBRTC_GLOBAL_CONFIG_PATH || "";
160
+ const GLOBAL_CONFIG_PATH = GLOBAL_CONFIG_OVERRIDE
161
+ ? (path.isAbsolute(GLOBAL_CONFIG_OVERRIDE) ? GLOBAL_CONFIG_OVERRIDE : path.resolve(process.cwd(), GLOBAL_CONFIG_OVERRIDE))
162
+ : path.join(PACKAGE_ROOT, "globalserviceconfig.json");
159
163
  const CONFIG_BASE_DIR = path.dirname(CONFIG_PATH);
160
164
  const fullConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
165
+ let fullGlobalConfig = {};
166
+ if (fs.existsSync(GLOBAL_CONFIG_PATH)) {
167
+ fullGlobalConfig = JSON.parse(fs.readFileSync(GLOBAL_CONFIG_PATH, "utf8"));
168
+ }
161
169
 
162
170
  function resolveRuntimePath(entryPath) {
163
171
  if (!entryPath) return "";
@@ -169,6 +177,7 @@ function resolveRuntimePath(entryPath) {
169
177
  const deployEnv = process.env.DEPLOY_ENV || "development";
170
178
  const envConfig = fullConfig[deployEnv] || {};
171
179
  const commonConfig = envConfig.common || {};
180
+ const globalEnvConfig = fullGlobalConfig[deployEnv] || {};
172
181
  const serviceRegistry = envConfig.services || {};
173
182
  const loadedServices = {};
174
183
 
@@ -208,7 +217,25 @@ for (const [serviceId, serviceEntry] of Object.entries(serviceRegistry)) {
208
217
  };
209
218
  }
210
219
 
211
- const config = commonConfig;
220
+ function pickRuntimeConfig(key, fallback = undefined) {
221
+ if (globalEnvConfig[key] !== undefined) return globalEnvConfig[key];
222
+ if (commonConfig[key] !== undefined) return commonConfig[key];
223
+ return fallback;
224
+ }
225
+
226
+ const config = {
227
+ // Source-of-truth stays in Kamailio config.json (no duplication in globalserviceconfig.json).
228
+ domain: commonConfig.domain,
229
+ kamailioWssHost: commonConfig.kamailioWssHost,
230
+ kamailioWssPort: commonConfig.kamailioWssPort,
231
+ bindIp: commonConfig.bindIp,
232
+ tlsCertPath: commonConfig.tlsCertPath,
233
+ roflBaseUrl: pickRuntimeConfig("roflBaseUrl"),
234
+ messageProcessorUrl: pickRuntimeConfig("messageProcessorUrl"),
235
+ polygon: pickRuntimeConfig("polygon", {}),
236
+ sapphire: pickRuntimeConfig("sapphire", {}),
237
+ sapphireTestnet: pickRuntimeConfig("sapphireTestnet", {}),
238
+ };
212
239
  const serviceRuntimes = loadedServices;
213
240
  const selectedServiceId = process.env.SERVICE_ID || null;
214
241
  const allowMultiListenerMode = process.env.ALLOW_MULTI_LISTENER === "true";
@@ -866,8 +893,8 @@ async function handleIceRestart(sessionId, payload) {
866
893
  * a werift RTCPeerConnection. After the call is established, we access PC2 via
867
894
  * inviter.sessionDescriptionHandler.peerConnection for RTP piping.
868
895
  */
869
- async function openSipSession(sessionId, callerEns, calleeIdentity) {
870
- return sipClientApi.openSipSession(sessionId, sessionStore, { callerEns, calleeIdentity });
896
+ async function openSipSession(sessionId, callerEns, calleeIdentity, sipDirective = null) {
897
+ return sipClientApi.openSipSession(sessionId, sessionStore, { callerEns, calleeIdentity, sipDirective });
871
898
  }
872
899
 
873
900
  /**
package/config.json DELETED
@@ -1,146 +0,0 @@
1
- {
2
- "development": {
3
- "common": {
4
- "domain": "test2.cellact.nl",
5
- "kamailioWssHost": "172.31.24.141",
6
- "publicIp": "3.125.225.232",
7
- "bindIp": "172.31.24.141",
8
- "tlsCertPath": "/etc/letsencrypt/live/test2.cellact.nl",
9
- "kamailioWssPort": 8443,
10
- "roflBaseUrl": "https://p8000.m1485.test-proxy-b.rofl.app",
11
- "messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
12
- "polygon": {
13
- "rpc": "https://polygon-bor-rpc.publicnode.com",
14
- "ENSRegistry": "0x6e0A65396233B8A29d76cA2DDd87bc5F19A82c36",
15
- "NameWrapper": "0xCAb1585C37118d066Bc3AD79919B4CAE5cd42BC2",
16
- "ServiceProviderRegistry": "0x86F58E4AadCB0188a11447641F4df3d66323959d",
17
- "ProvisionRegistry": "0x461f38fdCD44a92cD0fBE7ba9498903EFd944740",
18
- "CustomENS": "0xb32Feb0530C73FEc90BB985fA40894196938a9f6"
19
- },
20
- "sapphire": {
21
- "rpc": "https://sapphire.oasis.io",
22
- "NotificationManagerRegistry": "0xB5B5a6320BB0Fdf3F08122475F71B51f5210B437"
23
- },
24
- "sapphireTestnet": {
25
- "rpc": "https://testnet.sapphire.oasis.io",
26
- "NFTCallerIdPool": "0xFB3DD146F1aFfbA661533Ec49298D01f20104CF6"
27
- }
28
- },
29
- "services": {
30
- "esimera": {
31
- "providerId": "esimera",
32
- "notifyPort": 9000,
33
- "callbackPort": 9100,
34
- "configPath": "./services/esimera.json",
35
- "modulePath": "./webRTCservice/services/esimera.js"
36
- },
37
- "secnum": {
38
- "providerId": "secnum",
39
- "notifyPort": 9001,
40
- "callbackPort": 9101,
41
- "configPath": "./services/secnum.json",
42
- "modulePath": "./webRTCservice/services/secnum.js"
43
- },
44
- "phonemyemail": {
45
- "providerId": "phonemyemail",
46
- "notifyPort": 9002,
47
- "callbackPort": 9102,
48
- "configPath": "./services/phonemyemail.json",
49
- "modulePath": "./webRTCservice/services/phonemyemail.js"
50
- },
51
- "email": {
52
- "providerId": "email",
53
- "notifyPort": 9003,
54
- "callbackPort": 9103,
55
- "configPath": "./services/email.json",
56
- "modulePath": "./webRTCservice/services/email.js"
57
- },
58
- "vodaphone": {
59
- "providerId": "vodaphone",
60
- "notifyPort": 9004,
61
- "callbackPort": 9104,
62
- "configPath": "./services/vodaphone.json",
63
- "modulePath": "./webRTCservice/services/vodaphone.js"
64
- },
65
- "basicService": {
66
- "providerId": "basicService",
67
- "notifyPort": 9005,
68
- "callbackPort": 9105,
69
- "configPath": "./services/basicService.json",
70
- "modulePath": "./webRTCservice/services/basicService.js"
71
- }
72
- }
73
- },
74
- "production": {
75
- "common": {
76
- "domain": "ron1.cellact.nl",
77
- "kamailioWssHost": "172.31.6.219",
78
- "publicIp": "51.17.152.103",
79
- "bindIp": "172.31.6.219",
80
- "tlsCertPath": "/etc/letsencrypt/live/ron1.cellact.nl",
81
- "kamailioWssPort": 8443,
82
- "roflBaseUrl": "https://p8000.m206.opf-mainnet-rofl-35.rofl.app",
83
- "messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
84
- "polygon": {
85
- "rpc": "https://polygon-bor-rpc.publicnode.com",
86
- "ENSRegistry": "0x6e0A65396233B8A29d76cA2DDd87bc5F19A82c36",
87
- "NameWrapper": "0xCAb1585C37118d066Bc3AD79919B4CAE5cd42BC2",
88
- "ServiceProviderRegistry": "0x86F58E4AadCB0188a11447641F4df3d66323959d",
89
- "ProvisionRegistry": "0x461f38fdCD44a92cD0fBE7ba9498903EFd944740",
90
- "CustomENS": "0xb32Feb0530C73FEc90BB985fA40894196938a9f6"
91
- },
92
- "sapphire": {
93
- "rpc": "https://sapphire.oasis.io",
94
- "NotificationManagerRegistry": "0xB5B5a6320BB0Fdf3F08122475F71B51f5210B437"
95
- },
96
- "sapphireTestnet": {
97
- "rpc": "https://sapphire.oasis.io",
98
- "NFTCallerIdPool": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269"
99
- }
100
- },
101
- "services": {
102
- "esimera": {
103
- "providerId": "esimera",
104
- "notifyPort": 9000,
105
- "callbackPort": 9100,
106
- "configPath": "./services/esimera.json",
107
- "modulePath": "./webRTCservice/services/esimera.js"
108
- },
109
- "secnum": {
110
- "providerId": "secnum",
111
- "notifyPort": 9001,
112
- "callbackPort": 9101,
113
- "configPath": "./services/secnum.json",
114
- "modulePath": "./webRTCservice/services/secnum.js"
115
- },
116
- "phonemyemail": {
117
- "providerId": "phonemyemail",
118
- "notifyPort": 9002,
119
- "callbackPort": 9102,
120
- "configPath": "./services/phonemyemail.json",
121
- "modulePath": "./webRTCservice/services/phonemyemail.js"
122
- },
123
- "email": {
124
- "providerId": "email",
125
- "notifyPort": 9003,
126
- "callbackPort": 9103,
127
- "configPath": "./services/email.json",
128
- "modulePath": "./webRTCservice/services/email.js"
129
- },
130
- "vodaphone": {
131
- "providerId": "vodaphone",
132
- "notifyPort": 9004,
133
- "callbackPort": 9104,
134
- "configPath": "./services/vodaphone.json",
135
- "modulePath": "./webRTCservice/services/vodaphone.js"
136
- },
137
- "basicService": {
138
- "providerId": "basicService",
139
- "notifyPort": 9005,
140
- "callbackPort": 9105,
141
- "configPath": "./services/basicService.json",
142
- "modulePath": "./webRTCservice/services/basicService.js"
143
- }
144
- }
145
- }
146
- }