commit 0ca20205f1d320ec19d1b0091c5a998fbe2b6cde
parent 3e58d2fb3e30da2e28c8fbc94731f64ecd645ef9
Author: parazyd <parazyd@dyne.org>
Date: Mon, 8 Mar 2021 00:55:09 +0100
Implement writing of JSON peer database file.
We use semaphores to limit concurrency.
Diffstat:
6 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/config.go b/config.go
@@ -18,8 +18,11 @@
package tordam
import (
+ "context"
"crypto/ed25519"
"net"
+
+ "golang.org/x/sync/semaphore"
)
// Config is the configuration structure, to be filled by library user.
@@ -42,3 +45,12 @@ var Cfg = Config{}
// Peers is the global map of peers
var Peers = map[string]Peer{}
+
+// dbSem is the internal semaphore for writing the peer db
+var dbSem = semaphore.NewWeighted(1)
+
+// dbSemCtx is the context for dbSem
+var dbSemCtx = context.Background()
+
+// dbFile is the filename for the Peers JSON database
+var dbFile = "peers.json"
diff --git a/database.go b/database.go
@@ -0,0 +1,50 @@
+// Copyright (c) 2017-2021 Ivan Jelincic <parazyd@dyne.org>
+//
+// This file is part of tordam
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+package tordam
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+)
+
+// WritePeersDB marshals the Peers global to JSON and writes to given file.
+// Please note that this should be probably used in conjuction with a semaphore.
+func WritePeersDB(file string) error {
+ j, err := json.Marshal(Peers)
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(file, j, 0600)
+}
+
+// writePeersDBWithSem is an internal function to call WritePeersDB safely
+// using an internal semafore. Programs using this library should probably
+// implement something similar.
+func writePeersDBWithSem(file string) {
+ if err := dbSem.Acquire(dbSemCtx, 1); err != nil {
+ log.Println("warning: failed to acquire sem for writing:", err)
+ return
+ }
+ go func() {
+ if err := WritePeersDB(file); err != nil {
+ log.Println("warning: failed to write peers db:", err)
+ }
+ dbSem.Release(1)
+ }()
+}
diff --git a/go.mod b/go.mod
@@ -5,4 +5,5 @@ go 1.16
require (
github.com/creachadair/jrpc2 v0.12.0
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
+ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
)
diff --git a/go.sum b/go.sum
@@ -11,6 +11,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxW
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
diff --git a/peer_announce.go b/peer_announce.go
@@ -105,5 +105,7 @@ func AppendPeers(p []string) error {
}
Peers[i] = Peer{}
}
+
+ writePeersDBWithSem(strings.Join([]string{Cfg.Datadir, dbFile}, "/"))
return nil
}
diff --git a/rpc_announce.go b/rpc_announce.go
@@ -122,6 +122,7 @@ func (Ann) Init(ctx context.Context, vals []string) ([]string, error) {
peer.Trusted = 0
Peers[onion] = peer
+ writePeersDBWithSem(strings.Join([]string{Cfg.Datadir, dbFile}, "/"))
return []string{nonce, newrevoke}, nil
}
@@ -194,6 +195,8 @@ func (Ann) Validate(ctx context.Context, vals []string) ([]string, error) {
peer.LastSeen = time.Now().Unix()
Peers[onion] = peer
+ writePeersDBWithSem(strings.Join([]string{Cfg.Datadir, dbFile}, "/"))
+
rpcInfo("ann.Validate", "sending back list of peers to", onion)
return ret, nil
}