arnacon-webrtc-service 0.1.2 → 0.1.4

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,130 @@
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
+ "services": {
22
+ "esimera": {
23
+ "providerId": "esimera",
24
+ "notifyPort": 9000,
25
+ "callbackPort": 9100,
26
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/esimera.json",
27
+ "modulePath": "./webRTCservice/services/esimera.js"
28
+ },
29
+ "secnum": {
30
+ "providerId": "secnum",
31
+ "notifyPort": 9001,
32
+ "callbackPort": 9101,
33
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/secnum.json",
34
+ "modulePath": "./webRTCservice/services/secnum.js"
35
+ },
36
+ "phonemyemail": {
37
+ "providerId": "phonemyemail",
38
+ "notifyPort": 9002,
39
+ "callbackPort": 9102,
40
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/phonemyemail.json",
41
+ "modulePath": "./webRTCservice/services/phonemyemail.js"
42
+ },
43
+ "email": {
44
+ "providerId": "email",
45
+ "notifyPort": 9003,
46
+ "callbackPort": 9103,
47
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/email.json",
48
+ "modulePath": "./webRTCservice/services/email.js"
49
+ },
50
+ "vodaphone": {
51
+ "providerId": "vodaphone",
52
+ "notifyPort": 9004,
53
+ "callbackPort": 9104,
54
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/vodaphone.json",
55
+ "modulePath": "./webRTCservice/services/vodaphone.js"
56
+ },
57
+ "basicService": {
58
+ "providerId": "basicService",
59
+ "notifyPort": 9005,
60
+ "callbackPort": 9105,
61
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/basicService.json",
62
+ "modulePath": "./webRTCservice/services/basicService.js"
63
+ }
64
+ }
65
+ },
66
+ "production": {
67
+ "roflBaseUrl": "https://p8000.m206.opf-mainnet-rofl-35.rofl.app",
68
+ "messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
69
+ "polygon": {
70
+ "rpc": "https://polygon-bor-rpc.publicnode.com",
71
+ "ENSRegistry": "0x6e0A65396233B8A29d76cA2DDd87bc5F19A82c36",
72
+ "NameWrapper": "0xCAb1585C37118d066Bc3AD79919B4CAE5cd42BC2",
73
+ "ServiceProviderRegistry": "0x86F58E4AadCB0188a11447641F4df3d66323959d",
74
+ "ProvisionRegistry": "0x461f38fdCD44a92cD0fBE7ba9498903EFd944740",
75
+ "CustomENS": "0xb32Feb0530C73FEc90BB985fA40894196938a9f6"
76
+ },
77
+ "sapphire": {
78
+ "rpc": "https://sapphire.oasis.io",
79
+ "NotificationManagerRegistry": "0xB5B5a6320BB0Fdf3F08122475F71B51f5210B437"
80
+ },
81
+ "sapphireTestnet": {
82
+ "rpc": "https://sapphire.oasis.io",
83
+ "NFTCallerIdPool": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269"
84
+ },
85
+ "services": {
86
+ "esimera": {
87
+ "providerId": "esimera",
88
+ "notifyPort": 9000,
89
+ "callbackPort": 9100,
90
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/esimera.json",
91
+ "modulePath": "./webRTCservice/services/esimera.js"
92
+ },
93
+ "secnum": {
94
+ "providerId": "secnum",
95
+ "notifyPort": 9001,
96
+ "callbackPort": 9101,
97
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/secnum.json",
98
+ "modulePath": "./webRTCservice/services/secnum.js"
99
+ },
100
+ "phonemyemail": {
101
+ "providerId": "phonemyemail",
102
+ "notifyPort": 9002,
103
+ "callbackPort": 9102,
104
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/phonemyemail.json",
105
+ "modulePath": "./webRTCservice/services/phonemyemail.js"
106
+ },
107
+ "email": {
108
+ "providerId": "email",
109
+ "notifyPort": 9003,
110
+ "callbackPort": 9103,
111
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/email.json",
112
+ "modulePath": "./webRTCservice/services/email.js"
113
+ },
114
+ "vodaphone": {
115
+ "providerId": "vodaphone",
116
+ "notifyPort": 9004,
117
+ "callbackPort": 9104,
118
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/vodaphone.json",
119
+ "modulePath": "./webRTCservice/services/vodaphone.js"
120
+ },
121
+ "basicService": {
122
+ "providerId": "basicService",
123
+ "notifyPort": 9005,
124
+ "callbackPort": 9105,
125
+ "configPath": "/etc/webrtcservice/node_modules/arnacon-webrtc-service/services/basicService.json",
126
+ "modulePath": "./webRTCservice/services/basicService.js"
127
+ }
128
+ }
129
+ }
130
+ }
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.4",
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;
@@ -158,6 +158,16 @@ const CONFIG_PATH = CONFIG_OVERRIDE
158
158
  : path.join(PACKAGE_ROOT, "config.json");
159
159
  const CONFIG_BASE_DIR = path.dirname(CONFIG_PATH);
160
160
  const fullConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
161
+ const _deployEnvEarly = process.env.DEPLOY_ENV || "development";
162
+ const _commonEarly = (fullConfig[_deployEnvEarly] || {}).common || {};
163
+ const GLOBAL_CONFIG_OVERRIDE = process.env.WEBRTC_GLOBAL_CONFIG_PATH || process.env.ARNACON_WEBRTC_GLOBAL_CONFIG_PATH || "";
164
+ const GLOBAL_CONFIG_PATH = GLOBAL_CONFIG_OVERRIDE
165
+ ? (path.isAbsolute(GLOBAL_CONFIG_OVERRIDE) ? GLOBAL_CONFIG_OVERRIDE : path.resolve(process.cwd(), GLOBAL_CONFIG_OVERRIDE))
166
+ : (_commonEarly.globalServiceConfigPath || path.join(PACKAGE_ROOT, "globalserviceconfig.json"));
167
+ let fullGlobalConfig = {};
168
+ if (fs.existsSync(GLOBAL_CONFIG_PATH)) {
169
+ fullGlobalConfig = JSON.parse(fs.readFileSync(GLOBAL_CONFIG_PATH, "utf8"));
170
+ }
161
171
 
162
172
  function resolveRuntimePath(entryPath) {
163
173
  if (!entryPath) return "";
@@ -169,7 +179,8 @@ function resolveRuntimePath(entryPath) {
169
179
  const deployEnv = process.env.DEPLOY_ENV || "development";
170
180
  const envConfig = fullConfig[deployEnv] || {};
171
181
  const commonConfig = envConfig.common || {};
172
- const serviceRegistry = envConfig.services || {};
182
+ const globalEnvConfig = fullGlobalConfig[deployEnv] || {};
183
+ const serviceRegistry = globalEnvConfig.services || envConfig.services || {};
173
184
  const loadedServices = {};
174
185
 
175
186
  for (const [serviceId, serviceEntry] of Object.entries(serviceRegistry)) {
@@ -208,7 +219,25 @@ for (const [serviceId, serviceEntry] of Object.entries(serviceRegistry)) {
208
219
  };
209
220
  }
210
221
 
211
- const config = commonConfig;
222
+ function pickRuntimeConfig(key, fallback = undefined) {
223
+ if (globalEnvConfig[key] !== undefined) return globalEnvConfig[key];
224
+ if (commonConfig[key] !== undefined) return commonConfig[key];
225
+ return fallback;
226
+ }
227
+
228
+ const config = {
229
+ // Source-of-truth stays in Kamailio config.json (no duplication in globalserviceconfig.json).
230
+ domain: commonConfig.domain,
231
+ kamailioWssHost: commonConfig.kamailioWssHost,
232
+ kamailioWssPort: commonConfig.kamailioWssPort,
233
+ bindIp: commonConfig.bindIp,
234
+ tlsCertPath: commonConfig.tlsCertPath,
235
+ roflBaseUrl: pickRuntimeConfig("roflBaseUrl"),
236
+ messageProcessorUrl: pickRuntimeConfig("messageProcessorUrl"),
237
+ polygon: pickRuntimeConfig("polygon", {}),
238
+ sapphire: pickRuntimeConfig("sapphire", {}),
239
+ sapphireTestnet: pickRuntimeConfig("sapphireTestnet", {}),
240
+ };
212
241
  const serviceRuntimes = loadedServices;
213
242
  const selectedServiceId = process.env.SERVICE_ID || null;
214
243
  const allowMultiListenerMode = process.env.ALLOW_MULTI_LISTENER === "true";
@@ -866,8 +895,8 @@ async function handleIceRestart(sessionId, payload) {
866
895
  * a werift RTCPeerConnection. After the call is established, we access PC2 via
867
896
  * inviter.sessionDescriptionHandler.peerConnection for RTP piping.
868
897
  */
869
- async function openSipSession(sessionId, callerEns, calleeIdentity) {
870
- return sipClientApi.openSipSession(sessionId, sessionStore, { callerEns, calleeIdentity });
898
+ async function openSipSession(sessionId, callerEns, calleeIdentity, sipDirective = null) {
899
+ return sipClientApi.openSipSession(sessionId, sessionStore, { callerEns, calleeIdentity, sipDirective });
871
900
  }
872
901
 
873
902
  /**
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
- }