Explorar o código

Use mutex for accessing go-whatsapp contacts and chats maps

Tulir Asokan %!s(int64=4) %!d(string=hai) anos
pai
achega
bc7a82c0be
Modificáronse 4 ficheiros con 20 adicións e 1 borrados
  1. 6 0
      commands.go
  2. 6 0
      portal.go
  3. 2 0
      puppet.go
  4. 6 1
      user.go

+ 6 - 0
commands.go

@@ -779,7 +779,9 @@ func (handler *CommandHandler) CommandList(ce *CommandEvent) {
 	if contacts {
 		typeName = "Contacts"
 	}
+	ce.User.Conn.Store.ContactsLock.RLock()
 	result := formatContacts(contacts, ce.User.Conn.Store.Contacts)
+	ce.User.Conn.Store.ContactsLock.RUnlock()
 	if len(result) == 0 {
 		ce.Reply("No %s found", strings.ToLower(typeName))
 		return
@@ -817,7 +819,9 @@ func (handler *CommandHandler) CommandOpen(ce *CommandEvent) {
 		return
 	}
 
+	user.Conn.Store.ContactsLock.RLock()
 	contact, ok := user.Conn.Store.Contacts[jid]
+	user.Conn.Store.ContactsLock.RUnlock()
 	if !ok {
 		ce.Reply("Group JID not found in contacts. Try syncing contacts with `sync` first.")
 		return
@@ -863,7 +867,9 @@ func (handler *CommandHandler) CommandPM(ce *CommandEvent) {
 
 	handler.log.Debugln("Importing", jid, "for", user)
 
+	user.Conn.Store.ContactsLock.RLock()
 	contact, ok := user.Conn.Store.Contacts[jid]
+	user.Conn.Store.ContactsLock.RUnlock()
 	if !ok {
 		if !force {
 			ce.Reply("Phone number not found in contacts. Try syncing contacts with `sync` first. " +

+ 6 - 0
portal.go

@@ -201,7 +201,9 @@ func (portal *Portal) syncDoublePuppetDetailsAfterCreate(source *User) {
 	if doublePuppet == nil {
 		return
 	}
+	source.Conn.Store.ChatsLock.RLock()
 	chat, ok := source.Conn.Store.Chats[portal.Key.JID]
+	source.Conn.Store.ChatsLock.RUnlock()
 	if !ok {
 		portal.log.Debugln("Not syncing chat mute/tags with %s: chat info not found", source.MXID)
 		return
@@ -598,7 +600,9 @@ func (portal *Portal) UpdateMetadata(user *User) bool {
 			portal.SyncBroadcastRecipients(user, broadcastMetadata)
 			update = portal.UpdateName(broadcastMetadata.Name, "", nil, false) || update
 		} else {
+			user.Conn.Store.ContactsLock.RLock()
 			contact, _ := user.Conn.Store.Contacts[portal.Key.JID]
+			user.Conn.Store.ContactsLock.RUnlock()
 			update = portal.UpdateName(contact.Name, "", nil, false) || update
 		}
 		update = portal.UpdateTopic(BroadcastTopic, "", nil, false) || update
@@ -1085,7 +1089,9 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
 		if err == nil && broadcastMetadata.Status == 200 {
 			portal.Name = broadcastMetadata.Name
 		} else {
+			user.Conn.Store.ContactsLock.RLock()
 			contact, _ := user.Conn.Store.Contacts[portal.Key.JID]
+			user.Conn.Store.ContactsLock.RUnlock()
 			portal.Name = contact.Name
 		}
 		if len(portal.Name) == 0 {

+ 2 - 0
puppet.go

@@ -293,7 +293,9 @@ func (puppet *Puppet) SyncContactIfNecessary(source *User) {
 		return
 	}
 
+	source.Conn.Store.ContactsLock.RLock()
 	contact, ok := source.Conn.Store.Contacts[puppet.JID]
+	source.Conn.Store.ContactsLock.RUnlock()
 	if !ok {
 		puppet.log.Warnfln("No contact info found through %s in SyncContactIfNecessary", source.MXID)
 		contact.JID = puppet.JID

+ 6 - 1
user.go

@@ -667,9 +667,11 @@ func (user *User) HandleStreamEvent(evt whatsapp.StreamEvent) {
 func (user *User) HandleChatList(chats []whatsapp.Chat) {
 	user.log.Infoln("Chat list received")
 	chatMap := make(map[string]whatsapp.Chat)
+	user.Conn.Store.ChatsLock.RLock()
 	for _, chat := range user.Conn.Store.Chats {
 		chatMap[chat.JID] = chat
 	}
+	user.Conn.Store.ChatsLock.RUnlock()
 	for _, chat := range chats {
 		chatMap[chat.JID] = chat
 	}
@@ -798,10 +800,13 @@ func (user *User) collectChatList(chatMap map[string]whatsapp.Chat) ChatList {
 	for _, chat := range chatMap {
 		portal := user.GetPortalByJID(chat.JID)
 
+		user.Conn.Store.ContactsLock.RLock()
+		contact, _ := user.Conn.Store.Contacts[chat.JID]
+		user.Conn.Store.ContactsLock.RUnlock()
 		chats = append(chats, Chat{
 			Chat:    chat,
 			Portal:  portal,
-			Contact: user.Conn.Store.Contacts[chat.JID],
+			Contact: contact,
 		})
 		var inCommunity, ok bool
 		if inCommunity, ok = existingKeys[portal.Key]; !ok || !inCommunity {