URI: 
       tImplement writing of JSON peer database file. - tordam - A library for peer discovery inside the Tor network
  HTML git clone https://git.parazyd.org/tordam
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 0ca20205f1d320ec19d1b0091c5a998fbe2b6cde
   DIR parent 3e58d2fb3e30da2e28c8fbc94731f64ecd645ef9
  HTML 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:
         M config.go                           |      12 ++++++++++++
         A database.go                         |      50 +++++++++++++++++++++++++++++++
         M go.mod                              |       1 +
         M go.sum                              |       2 ++
         M peer_announce.go                    |       2 ++
         M rpc_announce.go                     |       3 +++
       
       6 files changed, 70 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/config.go b/config.go
       t@@ -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.
       t@@ -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"
   DIR diff --git a/database.go b/database.go
       t@@ -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)
       +        }()
       +}
   DIR diff --git a/go.mod b/go.mod
       t@@ -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
        )
   DIR diff --git a/go.sum b/go.sum
       t@@ -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=
   DIR diff --git a/peer_announce.go b/peer_announce.go
       t@@ -105,5 +105,7 @@ func AppendPeers(p []string) error {
                        }
                        Peers[i] = Peer{}
                }
       +
       +        writePeersDBWithSem(strings.Join([]string{Cfg.Datadir, dbFile}, "/"))
                return nil
        }
   DIR diff --git a/rpc_announce.go b/rpc_announce.go
       t@@ -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
        }
        
       t@@ -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
        }