Skip to content
Snippets Groups Projects
Select Git revision
  • b7edf7d9ca8b049b5cb63fbb637624e0acd5c241
  • release default protected
  • 11-22-implement-kv-interface-defined-in-collectiveversionedkvgo
  • hotfix/TestHostPool_UpdateNdf_AddFilter
  • XX-4719/announcementChannels
  • xx-4717/logLevel
  • jonah/noob-channel
  • master protected
  • XX-4707/tagDiskJson
  • xx-4698/notification-retry
  • hotfix/notifylockup
  • syncNodes
  • hotfix/localCB
  • XX-4677/NewChanManagerMobile
  • XX-4689/DmSync
  • duplicatePrefix
  • XX-4601/HavenInvites
  • finalizedUICallbacks
  • XX-4673/AdminKeySync
  • debugNotifID
  • anne/test
  • v4.7.5
  • v4.7.4
  • v4.7.3
  • v4.7.2
  • v4.7.1
  • v4.6.3
  • v4.6.1
  • v4.5.0
  • v4.4.4
  • v4.3.11
  • v4.3.8
  • v4.3.7
  • v4.3.6
  • v4.3.5
  • v4.2.0
  • v4.3.0
  • v4.3.4
  • v4.3.3
  • v4.3.2
  • v4.3.1
41 results

listener.go

  • user avatar
    Benjamin Wenger authored
    b7edf7d9
    History
    listener.go 3.16 KiB
    package single
    
    import (
    	jww "github.com/spf13/jwalterweatherman"
    	"gitlab.com/elixxir/client/cmix"
    	"gitlab.com/elixxir/client/cmix/identity/receptionID"
    	cmixMsg "gitlab.com/elixxir/client/cmix/message"
    	"gitlab.com/elixxir/client/cmix/rounds"
    	"gitlab.com/elixxir/client/single/message"
    	"gitlab.com/elixxir/crypto/cyclic"
    	cAuth "gitlab.com/elixxir/crypto/e2e/auth"
    	"gitlab.com/elixxir/crypto/e2e/singleUse"
    	"gitlab.com/elixxir/primitives/format"
    	"gitlab.com/xx_network/primitives/id"
    )
    
    type Receiver interface {
    	Callback(*Request, receptionID.EphemeralIdentity, rounds.Round)
    }
    
    type Listener interface {
    	// Stop unregisters the listener
    	Stop()
    }
    
    type listener struct {
    	myId      *id.ID
    	myPrivkey *cyclic.Int
    	tag       string
    	grp       *cyclic.Group
    	cb        Receiver
    	net       cmix.Client
    }
    
    // Listen allows a server to listen for single use requests. It will register
    // a service relative to the tag and myID as the identifier.  Only a single
    // listener can be active for a tag-myID pair, and error will return if that
    // is violated. When requests are receved, they will be called on the
    // Receiver interface.
    func Listen(tag string, myId *id.ID, privkey *cyclic.Int, net cmix.Client,
    	e2eGrp *cyclic.Group, cb Receiver) Listener {
    
    	l := &listener{
    		myId:      myId,
    		myPrivkey: privkey,
    		tag:       tag,
    		grp:       e2eGrp,
    		cb:        cb,
    		net:       net,
    	}
    
    	svc := cmixMsg.Service{
    		Identifier: myId[:],
    		Tag:        tag,
    		Metadata:   myId[:],
    	}
    
    	net.AddService(myId, svc, l)
    
    	return l
    }
    
    func (l *listener) Process(ecrMsg format.Message,
    	receptionID receptionID.EphemeralIdentity,
    	round rounds.Round) {
    
    	// Unmarshal the CMIX message contents to a transmission message
    	transmitMsg, err := message.UnmarshalRequest(ecrMsg.GetContents(),
    		l.grp.GetP().ByteLen())
    	if err != nil {
    		jww.WARN.Printf("failed to unmarshal contents on single use "+
    			"request to %s on tag %s: %+v", l.myId, l.tag, err)
    		return
    	}
    
    	// Generate DH key and symmetric key
    	senderPubkey := transmitMsg.GetPubKey(l.grp)
    	dhKey := l.grp.Exp(senderPubkey, l.myPrivkey,
    		l.grp.NewInt(1))
    	key := singleUse.NewTransmitKey(dhKey)
    
    	// Verify the MAC
    	if !singleUse.VerifyMAC(key, transmitMsg.GetPayload(), ecrMsg.GetMac()) {
    		jww.WARN.Printf("mac check failed on single use request to %s "+
    			"on tag %s", l.myId, l.tag)
    		return
    	}
    
    	// Decrypt the transmission message payload
    	fp := ecrMsg.GetKeyFP()
    	decryptedPayload := cAuth.Crypt(key, fp[:24], transmitMsg.GetPayload())
    
    	// Unmarshal payload
    	payload, err := message.UnmarshalRequestPayload(decryptedPayload)
    	if err != nil {
    		jww.WARN.Printf("failed to unmarshal decrypted payload on "+
    			"single use request to %s on tag %s: %+v", l.myId, l.tag, err)
    		return
    	}
    
    	used := uint32(0)
    
    	r := Request{
    		sender:         payload.GetRID(transmitMsg.GetPubKey(l.grp)),
    		senderPubKey:   senderPubkey,
    		dhKey:          dhKey,
    		tag:            l.tag,
    		maxParts:       0,
    		used:           &used,
    		requestPayload: payload.GetContents(),
    		net:            l.net,
    	}
    
    	go l.cb.Callback(&r, receptionID, round)
    }
    
    func (l *listener) Stop() {
    	svc := cmixMsg.Service{
    		Identifier: l.myId[:],
    		Tag:        l.tag,
    	}
    	l.net.DeleteService(l.myId, svc, l)
    }