github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/samples/go/decent/lib/pubsub.go (about)

     1  // See: https://github.com/attic-labs/noms/issues/3808
     2  // +build ignore
     3  
     4  // Copyright 2017 Attic Labs, Inc. All rights reserved.
     5  // Licensed under the Apache License, version 2.0:
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  
     8  package lib
     9  
    10  import (
    11  	"context"
    12  	"encoding/json"
    13  	"sync"
    14  
    15  	"github.com/attic-labs/noms/go/d"
    16  	"github.com/attic-labs/noms/go/hash"
    17  	"github.com/attic-labs/noms/samples/go/decent/dbg"
    18  	"github.com/ipfs/go-ipfs/core"
    19  	"github.com/mr-tron/base58/base58"
    20  )
    21  
    22  var (
    23  	PubsubUser    = "default"
    24  	seenHash      = map[hash.Hash]bool{}
    25  	seenHashMutex = sync.Mutex{}
    26  )
    27  
    28  func lockSeenF() func() {
    29  	seenHashMutex.Lock()
    30  	return func() {
    31  		seenHashMutex.Unlock()
    32  	}
    33  }
    34  
    35  // RecieveMessages listens for messages sent by other chat nodes. It filters out
    36  // any msgs that have already been received and adds events to teh events channel
    37  // for any msgs that it hasn't seen yet.
    38  func ReceiveMessages(node *core.IpfsNode, events chan ChatEvent, cInfo ClientInfo) {
    39  	sub, err := node.Floodsub.Subscribe(cInfo.Topic)
    40  	d.Chk.NoError(err)
    41  
    42  	listenForAndHandleMessage := func() {
    43  		msg, err := sub.Next(context.Background())
    44  		d.PanicIfError(err)
    45  		sender := base58.Encode(msg.From)
    46  		msgMap := map[string]string{}
    47  		err = json.Unmarshal(msg.Data, &msgMap)
    48  		if err != nil {
    49  			dbg.Debug("ReceiveMessages: received non-json msg: %s from: %s, error: %s", msg.Data, sender, err)
    50  			return
    51  		}
    52  		msgData := msgMap["data"]
    53  		h, err := cInfo.Delegate.HashFromMsgData(msgData)
    54  		if err != nil {
    55  			dbg.Debug("ReceiveMessages: received unknown msg: %s from: %s", msgData, sender)
    56  			return
    57  		}
    58  
    59  		defer lockSeenF()()
    60  		if !seenHash[h] {
    61  			events <- ChatEvent{EventType: SyncEvent, Event: msgData}
    62  			seenHash[h] = true
    63  			dbg.Debug("got msgData: %s from: %s(%s)", msgData, sender, msgMap["user"])
    64  		}
    65  	}
    66  
    67  	dbg.Debug("start listening for msgs on channel: %s", cInfo.Topic)
    68  	for {
    69  		listenForAndHandleMessage()
    70  	}
    71  	panic("unreachable")
    72  }
    73  
    74  // Publish asks the delegate to format a hash/ClientInfo into a suitable msg
    75  // and publishes that using IPFS pubsub.
    76  func Publish(node *core.IpfsNode, cInfo ClientInfo, h hash.Hash) {
    77  	defer func() {
    78  		if r := recover(); r != nil {
    79  			dbg.Debug("Publish failed, error: %s", r)
    80  		}
    81  	}()
    82  	msgData := cInfo.Delegate.GenMessageData(cInfo, h)
    83  	m, err := json.Marshal(map[string]string{"user": cInfo.Username, "data": msgData})
    84  	if err != nil {
    85  
    86  	}
    87  	d.PanicIfError(err)
    88  	dbg.Debug("publishing to topic: %s, msg: %s", cInfo.Topic, m)
    89  	node.Floodsub.Publish(cInfo.Topic, append(m, []byte("\r\n")...))
    90  
    91  	defer lockSeenF()()
    92  	seenHash[h] = true
    93  }