tordam

A library for peer discovery inside the Tor network
git clone https://git.parazyd.org/tordam
Log | Files | Refs | README | LICENSE

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:
Mconfig.go | 12++++++++++++
Adatabase.go | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Mgo.mod | 1+
Mgo.sum | 2++
Mpeer_announce.go | 2++
Mrpc_announce.go | 3+++
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 }