]> Cypherpunks.ru repositories - govpn.git/blobdiff - identify.go
Ability to bind human readable name to the peer
[govpn.git] / identify.go
index 8547e6081ef659c022c1f7f113ef222148491915..6c16da08a2a3c1cc124f0b0995b99142e24aad59 100644 (file)
@@ -21,14 +21,20 @@ package govpn
 import (
        "crypto/subtle"
        "encoding/hex"
+       "io/ioutil"
        "log"
        "os"
+       "path"
+       "strings"
+       "sync"
+       "time"
 
        "golang.org/x/crypto/xtea"
 )
 
 const (
-       IDSize = 128 / 8
+       IDSize      = 128 / 8
+       RefreshRate = 60 * time.Second
 )
 
 type PeerId [IDSize]byte
@@ -37,18 +43,45 @@ func (id PeerId) String() string {
        return hex.EncodeToString(id[:])
 }
 
+// Return human readable name of the peer.
+// It equals either to peers/PEER/name file contents or PEER's hex.
+func (id PeerId) MarshalJSON() ([]byte, error) {
+       result := id.String()
+       if name, err := ioutil.ReadFile(path.Join(PeersPath, result, "name")); err == nil {
+               result = strings.TrimRight(string(name), "\n")
+       }
+       return []byte(`"` + result + `"`), nil
+}
+
 type cipherCache map[PeerId]*xtea.Cipher
 
 var (
-       PeersPath string
-       IDsCache  cipherCache
+       PeersPath       string
+       IDsCache        cipherCache
+       cipherCacheLock sync.RWMutex
 )
 
 // Initialize (pre-cache) available peers info.
 func PeersInit(path string) {
        PeersPath = path
        IDsCache = make(map[PeerId]*xtea.Cipher)
-       IDsCache.refresh()
+       go func() {
+               for {
+                       IDsCache.refresh()
+                       time.Sleep(RefreshRate)
+               }
+       }()
+}
+
+// Initialize dummy cache for client-side usage. It will consist only
+// of single key.
+func PeersInitDummy(id *PeerId) {
+       IDsCache = make(map[PeerId]*xtea.Cipher)
+       cipher, err := xtea.NewCipher(id[:])
+       if err != nil {
+               panic(err)
+       }
+       IDsCache[*id] = cipher
 }
 
 // Refresh IDsCache: remove disappeared keys, add missing ones with
@@ -70,6 +103,8 @@ func (cc cipherCache) refresh() {
                }
                available[*id] = true
        }
+
+       cipherCacheLock.Lock()
        // Cleanup deleted ones from cache
        for k, _ := range cc {
                if _, exists := available[k]; !exists {
@@ -88,20 +123,27 @@ func (cc cipherCache) refresh() {
                        cc[peerId] = cipher
                }
        }
+       cipherCacheLock.Unlock()
 }
 
 // Try to find peer's identity (that equals to an encryption key)
-// by providing cipher and plain texts.
-func (cc cipherCache) Find(plaintext, ciphertext []byte) *PeerId {
-       cc.refresh()
+// by taking first blocksize sized bytes from data at the beginning
+// as plaintext and last bytes as cyphertext.
+func (cc cipherCache) Find(data []byte) *PeerId {
+       if len(data) < xtea.BlockSize*2 {
+               return nil
+       }
        buf := make([]byte, xtea.BlockSize)
+       cipherCacheLock.RLock()
        for pid, cipher := range cc {
-               cipher.Decrypt(buf, ciphertext)
-               if subtle.ConstantTimeCompare(buf, plaintext) == 1 {
+               cipher.Decrypt(buf, data[len(data)-xtea.BlockSize:])
+               if subtle.ConstantTimeCompare(buf, data[:xtea.BlockSize]) == 1 {
                        ppid := PeerId(pid)
+                       cipherCacheLock.RUnlock()
                        return &ppid
                }
        }
+       cipherCacheLock.RUnlock()
        return nil
 }