package torrent import ( "crypto/rand" "log/slog" "os" "git.kmsign.ru/royalcat/tstor/src/config" "git.kmsign.ru/royalcat/tstor/src/logwrap" "github.com/anacrolix/dht/v2/bep44" tlog "github.com/anacrolix/log" "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/storage" "github.com/anacrolix/torrent/types/infohash" ) func newClientConfig(st storage.ClientImpl, fis bep44.Store, cfg *config.TorrentClient, id [20]byte) *torrent.ClientConfig { l := slog.With("component", "torrent-client") // TODO download and upload limits torrentCfg := torrent.NewDefaultClientConfig() torrentCfg.PeerID = string(id[:]) torrentCfg.DefaultStorage = st // torrentCfg.AlwaysWantConns = true torrentCfg.DropMutuallyCompletePeers = true // torrentCfg.TorrentPeersLowWater = 100 // torrentCfg.TorrentPeersHighWater = 1000 // torrentCfg.AcceptPeerConnections = true torrentCfg.Seed = true torrentCfg.DisableAggressiveUpload = false torrentCfg.PeriodicallyAnnounceTorrentsToDht = true // torrentCfg.ConfigureAnacrolixDhtServer = func(cfg *dht.ServerConfig) { // cfg.Store = fis // cfg.Exp = dhtTTL // cfg.PeerStore = fis // } tl := tlog.NewLogger("torrent-client") tl.SetHandlers(&logwrap.Torrent{L: l}) torrentCfg.Logger = tl torrentCfg.Callbacks.NewPeer = append(torrentCfg.Callbacks.NewPeer, func(p *torrent.Peer) { l.With(peerAttrs(p)...).Debug("new peer") }) torrentCfg.Callbacks.PeerClosed = append(torrentCfg.Callbacks.PeerClosed, func(p *torrent.Peer) { l.With(peerAttrs(p)...).Debug("peer closed") }) torrentCfg.Callbacks.CompletedHandshake = func(pc *torrent.PeerConn, ih infohash.T) { attrs := append(peerAttrs(&pc.Peer), slog.String("infohash", ih.HexString())) l.With(attrs...).Debug("completed handshake") } torrentCfg.Callbacks.PeerConnAdded = append(torrentCfg.Callbacks.PeerConnAdded, func(pc *torrent.PeerConn) { l.With(peerAttrs(&pc.Peer)...).Debug("peer conn added") }) torrentCfg.Callbacks.PeerConnClosed = func(pc *torrent.PeerConn) { l.With(peerAttrs(&pc.Peer)...).Debug("peer conn closed") } torrentCfg.Callbacks.CompletedHandshake = func(pc *torrent.PeerConn, ih infohash.T) { attrs := append(peerAttrs(&pc.Peer), slog.String("infohash", ih.HexString())) l.With(attrs...).Debug("completed handshake") } torrentCfg.Callbacks.ReceivedRequested = append(torrentCfg.Callbacks.ReceivedRequested, func(pme torrent.PeerMessageEvent) { l.With(peerAttrs(pme.Peer)...).Debug("received requested") }) torrentCfg.Callbacks.ReceivedUsefulData = append(torrentCfg.Callbacks.ReceivedUsefulData, func(pme torrent.PeerMessageEvent) { l.With(peerAttrs(pme.Peer)...).Debug("received useful data") }) return torrentCfg } var emptyBytes [20]byte func getOrCreatePeerID(p string) ([20]byte, error) { idb, err := os.ReadFile(p) if err == nil { var out [20]byte copy(out[:], idb) return out, nil } if !os.IsNotExist(err) { return emptyBytes, err } var out [20]byte _, err = rand.Read(out[:]) if err != nil { return emptyBytes, err } return out, os.WriteFile(p, out[:], 0755) } func peerAttrs(peer *torrent.Peer) []any { out := []any{ slog.String("ip", peer.RemoteAddr.String()), slog.String("discovery", string(peer.Discovery)), slog.Int("max-requests", peer.PeerMaxRequests), slog.Bool("prefers-encryption", peer.PeerPrefersEncryption), } if peer.Torrent() != nil { out = append(out, slog.String("torrent", peer.Torrent().Name())) } return out }