summaryrefslogtreecommitdiffhomepage
path: root/indextable.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-05-13 18:23:40 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-05-13 18:26:09 +0200
commit2c27ab205c992d3387574aa6d57780744d35d36f (patch)
treee95bb88db16bac5d2050d3db13cd28570f44cd72 /indextable.go
parent233f079a9479279d2aab68f4accb139ee87ad664 (diff)
Rework index hashtable
Diffstat (limited to 'indextable.go')
-rw-r--r--indextable.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/indextable.go b/indextable.go
new file mode 100644
index 0000000..2d947cd
--- /dev/null
+++ b/indextable.go
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+package main
+
+import (
+ "crypto/rand"
+ "sync"
+ "unsafe"
+)
+
+type IndexTableEntry struct {
+ peer *Peer
+ handshake *Handshake
+ keypair *Keypair
+}
+
+type IndexTable struct {
+ mutex sync.RWMutex
+ table map[uint32]IndexTableEntry
+}
+
+func randUint32() (uint32, error) {
+ var integer [4]byte
+ _, err := rand.Read(integer[:])
+ return *(*uint32)(unsafe.Pointer(&integer[0])), err
+}
+
+func (table *IndexTable) Init() {
+ table.mutex.Lock()
+ defer table.mutex.Unlock()
+ table.table = make(map[uint32]IndexTableEntry)
+}
+
+func (table *IndexTable) Delete(index uint32) {
+ table.mutex.Lock()
+ defer table.mutex.Unlock()
+ delete(table.table, index)
+}
+
+func (table *IndexTable) SwapIndexForKeypair(index uint32, keypair *Keypair) {
+ table.mutex.Lock()
+ defer table.mutex.Unlock()
+ entry, ok := table.table[index]
+ if !ok {
+ return
+ }
+ table.table[index] = IndexTableEntry{
+ peer: entry.peer,
+ keypair: keypair,
+ handshake: nil,
+ }
+}
+
+func (table *IndexTable) NewIndexForHandshake(peer *Peer, handshake *Handshake) (uint32, error) {
+ for {
+ // generate random index
+
+ index, err := randUint32()
+ if err != nil {
+ return index, err
+ }
+
+ // check if index used
+
+ table.mutex.RLock()
+ _, ok := table.table[index]
+ table.mutex.RUnlock()
+ if ok {
+ continue
+ }
+
+ // check again while locked
+
+ table.mutex.Lock()
+ _, found := table.table[index]
+ if found {
+ table.mutex.Unlock()
+ continue
+ }
+ table.table[index] = IndexTableEntry{
+ peer: peer,
+ handshake: handshake,
+ keypair: nil,
+ }
+ table.mutex.Unlock()
+ return index, nil
+ }
+}
+
+func (table *IndexTable) Lookup(id uint32) IndexTableEntry {
+ table.mutex.RLock()
+ defer table.mutex.RUnlock()
+ return table.table[id]
+}