blob: 764f1a1bc5cffc42bb9f437ddf987d59b3c8637b [file] [log] [blame]
Adrien Béraud6ecaa402021-04-06 17:37:25 -04001/*
2 * Copyright (c) 2017-2021 Savoir-faire Linux Inc.
3 *
4 * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
5 * Author: Asad Salman <me@asad.co>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20const Account = require('./model/Account')
Adrien Béraud0cb76c92021-04-07 19:59:08 -040021const Conversation = require('./model/Conversation')
Adrien Béraud6ecaa402021-04-06 17:37:25 -040022
23"use strict";
24class JamiDaemon {
25 constructor() {
26 this.accounts = []
27 this.dring = require("./dring.node")
28 this.dring.init({
29 "AccountsChanged": () => {
30 console.log("AccountsChanged")
31 const newAccounts = []
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040032 JamiDaemon.vectToJs(this.dring.getAccountList()).forEach(accountId => {
Adrien Béraud6ecaa402021-04-06 17:37:25 -040033 for (const account in this.accounts) {
34 if (account.id === accountId) {
35 newAccounts.push(account)
36 return
37 }
38 }
39 newAccounts.push(new Account(accountId,
Adrien Béraud35e7d7c2021-04-13 03:28:39 -040040 JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId)),
41 JamiDaemon.mapToJs(this.dring.getVolatileAccountDetails(accountId))
Adrien Béraud0cb76c92021-04-07 19:59:08 -040042 ))
Adrien Béraud6ecaa402021-04-06 17:37:25 -040043 })
44 this.accounts = newAccounts
45 },
46 "AccountDetailsChanged": (accountId, details) => {
47 console.log(`AccountDetailsChanged ${accountId}`)
48 const account = this.getAccount(accountId)
49 if (!account) {
50 console.log(`Unknown account ${accountId}`)
51 return
52 }
53 account.details = details
54 },
55 "VolatileDetailsChanged": (accountId, details) => {
56 console.log(`VolatileDetailsChanged ${accountId}`)
57 const account = this.getAccount(accountId)
58 if (!account) {
59 console.log(`Unknown account ${accountId}`)
60 return
61 }
62 account.volatileDetails = details
63 },
64 "IncomingAccountMessage": (accountId, from, message) => {
65 console.log(`Received message: ${accountId} ${from} ${message["text/plain"]}`)
66/*
67 if (parser.validate(message["text/plain"]) === true) {
68 console.log(message["text/plain"]);
69 } else {
70
71 user = connectedUsers[accountId];
72 console.log(user.socketId)
73 io.to(user.socketId).emit('receivedMessage', message["text/plain"]);
74 //io.emit('receivedMessage', message["text/plain"]);
75 }*/
76 },
77 "RegistrationStateChanged": (accountId, state, /*int*/ code, detail) => {
78 const account = this.getAccount(accountId)
79 if (!account) {
80 console.log(`Unknown account ${accountId}`)
81 return
82 }
83 account.registrationState = state
84 console.log("RegistrationStateChanged: " + accountId + " " + state + " " + code + " " + detail)
85 if (state === "REGISTERED") {
86 /*if (tempAccounts[accountId]) {
87
88 const ctx = tempAccounts[accountId]
89 ctx.newUser.accountId = accountId
90 ctx.newUser.jamiId = jami.dring.getAccountDetails(accountId).get("Account.username")
91 //connectedUsers[accountId] = ctx.newUser
92 ctx.done(null, ctx.newUser)
93 delete tempAccounts[accountId]
94 }*/
95 } else if (state === "ERROR_AUTH") {
96 //done(null, false)
97 //remove account
98 }
99 },
100 "RegisteredNameFound": (accountId, state, address, name) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400101 console.log(`RegisteredNameFound: ${accountId} ${state} ${address} ${name}`)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400102 const account = this.getAccount(accountId)
103 if (!account) {
104 console.log(`Unknown account ${accountId}`)
105 return
106 }
107 if (state == 0) {
108 const contact = account.getContactFromCache(address)
109 contact.setRegisteredName(name)
110 }
111 let index = account.lookups.length - 1;
112 while (index >= 0) {
113 const lookup = account.lookups[index]
114 if ((lookup.address && lookup.address === address) || (lookup.name && lookup.name === name)) {
115 lookup.resolve({address, name, state})
116 account.lookups.splice(index, 1);
117 }
118 index -= 1;
119 }
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400120 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400121 "ConversationReady": (accountId, conversationId) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400122 console.log(`conversationReady: ${accountId} ${conversationId}`)
123 const account = this.getAccount(accountId)
124 if (!account) {
125 console.log(`Unknown account ${accountId}`)
126 return
127 }
128 let conversation = account.getConversation(conversationId)
129 if (!conversation) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400130 const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId))
131 members.forEach(member => member.contact = account.getContactFromCache(member.uri))
132 conversation = new Conversation(conversationId, accountId, members)
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400133 account.addConversation(conversation)
134 }
135 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400136 "ConversationRemoved": (accountId, conversationId) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400137 console.log(`conversationRemoved: ${accountId} ${conversationId}`)
138 const account = this.getAccount(accountId)
139 if (!account) {
140 console.log(`Unknown account ${accountId}`)
141 return
142 }
143 account.removeConversation(conversationId)
144 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400145 "ConversationLoaded": (accountId, conversationId) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400146 console.log(`conversationLoaded: ${accountId} ${conversationId}`)
147 const account = this.getAccount(accountId)
148 if (!account) {
149 console.log(`Unknown account ${accountId}`)
150 return
151 }
152 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400153 "MessageReceived": (accountId, conversationId, message) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400154 console.log(`messageReceived: ${accountId} ${conversationId}`)
155 const account = this.getAccount(accountId)
156 if (!account) {
157 console.log(`Unknown account ${accountId}`)
158 return
159 }
160 const conversation = account.getConversation(conversationId)
161 if (!conversation) {
162 conversation.addMessage(message)
163 }
164 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400165 "ConversationRequestReceived": (accountId, conversationId, request) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400166 console.log(`conversationRequestReceived: ${accountId} ${conversationId}`)
167 const account = this.getAccount(accountId)
168 if (!account) {
169 console.log(`Unknown account ${accountId}`)
170 return
171 }
172 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400173 "ConversationMemberEvent": (accountId, conversationId, member, event) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400174 console.log(`conversationMemberEvent: ${accountId} ${conversationId}`)
175 const account = this.getAccount(accountId)
176 if (!account) {
177 console.log(`Unknown account ${accountId}`)
178 return
179 }
180 },
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400181 "OnConversationError": (accountId, conversationId, code, what) => {
Adrien Béraud0cb76c92021-04-07 19:59:08 -0400182 console.log(`onConversationError: ${accountId} ${conversationId}`)
183 const account = this.getAccount(accountId)
184 if (!account) {
185 console.log(`Unknown account ${accountId}`)
186 return
187 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400188 }
189 })
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400190
191 JamiDaemon.vectToJs(this.dring.getAccountList()).forEach(accountId => {
192 const account = new Account(accountId,
193 JamiDaemon.mapToJs(this.dring.getAccountDetails(accountId)),
194 JamiDaemon.mapToJs(this.dring.getVolatileAccountDetails(accountId))
195 )
196 JamiDaemon.vectToJs(this.dring.getConversations(accountId)).forEach(conversationId => {
197 const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, conversationId))
198 members.forEach(member => member.contact = account.getContactFromCache(member.uri))
199 const conversation = new Conversation(conversationId, accountId, members)
200 account.addConversation(conversation)
201 })
202 this.accounts.push(account)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400203 })
204 }
205
206 addAccount(account) {
207 const params = accountDetailsToNative(account)
208 params.set("Account.type", "RING")
209 return this.dring.addAccount(params)
210 }
211 getAccount(accountId) {
212 for (let i = 0; i < this.accounts.length; i++) {
213 const account = this.accounts[i]
214 if (account.getId() === accountId)
215 return account
216 }
217 return undefined
218 }
219 getAccountList() {
220 return this.accounts
221 }
222 /*getAccountDetails(accountId) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400223 return this.mapToJs(this.dring.getAccountDetails(accountId))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400224 }*/
225 setAccountDetails(accountId, details) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400226 this.dring.setAccountDetails(accountId, mapToNative(details))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400227 }
228 getAudioOutputDeviceList() {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400229 return JamiDaemon.vectToJs(this.dring.getAudioOutputDeviceList())
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400230 }
231 getVolume(deviceName) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400232 return this.dring.getVolume(deviceName)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400233 }
234 setVolume(deviceName, volume) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400235 return this.dring.setVolume(deviceName, volume)
236 }
237
238 lookupName(accountId, name) {
239 const p = new Promise((resolve, reject) => {
240 const account = this.getAccount(accountId)
241 if (!account) {
242 reject(new Error("Can't find account"))
243 } else {
244 account.lookups.push({name, resolve, reject})
245 }
246 })
247 this.dring.lookupName(accountId, "", name)
248 return p
249 }
250
251 lookupAddress(accountId, address) {
252 console.log(`lookupAddress ${accountId} ${address}`)
253 const p = new Promise((resolve, reject) => {
254 const account = this.getAccount(accountId)
255 if (!account) {
256 reject(new Error("Can't find account"))
257 } else {
258 account.lookups.push({address, resolve, reject})
259 }
260 })
261 this.dring.lookupAddress(accountId, "", address)
262 return p
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400263 }
264
265 stop() {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400266 this.dring.fini()
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400267 }
268
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400269 addContact(accountId, contactId) {
270 this.dring.addContact(accountId, contactId)
271 const details = JamiDaemon.mapToJs(this.dring.getContactDetails(accountId, contactId))
272 if (details.conversationId) {
273 const account = this.getAccount(accountId)
274 if (account) {
275 let conversation = account.getConversation(details.conversationId)
276 if (!conversation) {
277 const members = JamiDaemon.vectMapToJs(this.dring.getConversationMembers(accountId, details.conversationId))
278 members.forEach(member => member.contact = account.getContactFromCache(member.uri))
279 conversation = new Conversation(details.conversationId, accountId, members)
280 account.addConversation(conversation)
281 }
282 }
283 }
284 return details
285 }
286
287 //getContactDetails
288
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400289// private
290
291 boolToStr(bool) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400292 return bool ? "true" : "false"
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400293 }
294
295 accountDetailsToNative(account) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400296 const params = new this.dring.StringMap()
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400297 if (account.managerUri)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400298 params.set("Account.managerUri", account.managerUri)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400299 if (account.managerUsername)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400300 params.set("Account.managerUsername", account.managerUsername)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400301 if (account.archivePassword) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400302 params.set("Account.archivePassword", account.archivePassword)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400303 } else {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400304 console.log("archivePassword required")
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400305 return;
306 }
307 if (account.alias)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400308 params.set("Account.alias", account.alias)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400309 if (account.displayName)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400310 params.set("Account.displayName", account.displayName)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400311 if (account.enable)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400312 params.set("Account.enable", this.boolToStr(account.enable))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400313 if (account.autoAnswer)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400314 params.set("Account.autoAnswer", this.boolToStr(account.autoAnswer))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400315 if (account.ringtonePath)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400316 params.set("Account.ringtonePath", account.ringtonePath)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400317 if (account.ringtoneEnabled)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400318 params.set("Account.ringtoneEnabled", this.boolToStr(account.ringtoneEnabled))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400319 if (account.videoEnabled)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400320 params.set("Account.videoEnabled", this.boolToStr(account.videoEnabled))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400321 if (account.useragent) {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400322 params.set("Account.useragent", account.useragent)
323 params.set("Account.hasCustomUserAgent", "TRUE")
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400324 } else {
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400325 params.set("Account.hasCustomUserAgent", "FALSE")
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400326 }
327 if (account.audioPortMin)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400328 params.set("Account.audioPortMin", account.audioPortMin)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400329 if (account.audioPortMax)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400330 params.set("Account.audioPortMax", account.audioPortMax)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400331 if (account.videoPortMin)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400332 params.set("Account.videoPortMin", account.videoPortMin)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400333 if (account.videoPortMax)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400334 params.set("Account.videoPortMax", account.videoPortMax)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400335 if (account.localInterface)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400336 params.set("Account.localInterface", account.localInterface)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400337 if (account.publishedSameAsLocal)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400338 params.set("Account.publishedSameAsLocal", this.boolToStr(account.publishedSameAsLocal))
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400339 if (account.localPort)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400340 params.set("Account.localPort", account.localPort)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400341 if (account.publishedPort)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400342 params.set("Account.publishedPort", account.publishedPort)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400343 if (account.publishedAddress)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400344 params.set("Account.publishedAddress", account.publishedAddress)
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400345 if (account.upnpEnabled)
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400346 params.set("Account.upnpEnabled", this.boolToStr(account.upnpEnabled))
347 return params
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400348 }
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400349 static vectToJs(vect) {
350 const len = vect.size()
351 const outputArr = new Array(len)
352 for (let i = 0; i < len; i++)
353 outputArr[i] = vect.get(i)
354 return outputArr
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400355 }
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400356 static mapToJs(m) {
357 const outputObj = {}
358 JamiDaemon.vectToJs(m.keys())
359 .forEach(k => outputObj[k] = m.get(k))
360 return outputObj
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400361 }
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400362 static vectMapToJs(vectMap) {
363 const len = vectMap.size()
364 const outputArr = new Array(len)
365 for (let i = 0; i < len; i++)
366 outputArr[i] = JamiDaemon.mapToJs(vectMap.get(i))
367 return outputArr
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400368 }
369
Adrien Béraud35e7d7c2021-04-13 03:28:39 -0400370 mapToNative(map){
371 const ret = new this.dring.StringMap()
372 map.forEach((value, key) => ret.set(key, value))
373 return ret;
374 }
Adrien Béraud6ecaa402021-04-06 17:37:25 -0400375}
376
377module.exports = JamiDaemon;