1 // NNCP -- Node to Node copy, utilities for store-and-forward data exchange
2 // Copyright (C) 2016-2024 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
26 "github.com/dustin/go-humanize"
27 "github.com/gorhill/cronexpr"
28 nncpYggdrasil "go.cypherpunks.ru/nncp/v8/yggdrasil"
32 Cron *cronexpr.Expression
38 OnlineDeadline time.Duration
39 MaxOnlineTime time.Duration
55 func (ctx *Ctx) CallNode(
61 onlineDeadline, maxOnlineTime time.Duration,
64 onlyPkts map[[MTHSize]byte]bool,
66 for _, addr := range addrs {
67 les := LEs{{"Node", node.Id}, {"Addr", addr}}
68 ctx.LogD("calling", les, func(les LEs) string {
69 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
71 var conn ConnDeadlined
74 conn, err = NewPipeConn(addr[1:])
75 } else if addr == UCSPITCPClient {
76 ucspiConn := UCSPIConn{R: os.NewFile(6, "R"), W: os.NewFile(7, "W")}
77 if ucspiConn.R == nil {
78 err = errors.New("no 6 file descriptor")
80 if ucspiConn.W == nil {
81 err = errors.New("no 7 file descriptor")
84 addr = UCSPITCPRemoteAddr()
88 } else if strings.HasPrefix(addr, "yggdrasilc://") {
89 conn, err = nncpYggdrasil.NewConn(ctx.YggdrasilAliases, addr)
91 conn, err = net.Dial("tcp", addr)
94 ctx.LogE("calling", les, err, func(les LEs) string {
95 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
99 ctx.LogD("call-connected", les, func(les LEs) string {
100 return fmt.Sprintf("Connected %s (%s)", node.Name, addr)
106 onlineDeadline: onlineDeadline,
107 maxOnlineTime: maxOnlineTime,
115 if err = state.StartI(conn); err == nil {
116 ctx.LogI("call-started", les, func(les LEs) string {
117 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
119 isGood = state.Wait()
120 ctx.LogI("call-finished", append(
122 LE{"Duration", int64(state.Duration.Seconds())},
123 LE{"RxBytes", state.RxBytes},
124 LE{"RxSpeed", state.RxSpeed},
125 LE{"TxBytes", state.TxBytes},
126 LE{"TxSpeed", state.TxSpeed},
127 ), func(les LEs) string {
129 "Finished call with %s (%d:%d:%d): %s received (%s/sec), %s transferred (%s/sec)",
131 int(state.Duration.Hours()),
132 int(state.Duration.Minutes()),
133 int(state.Duration.Seconds())%60,
134 humanize.IBytes(uint64(state.RxBytes)),
135 humanize.IBytes(uint64(state.RxSpeed)),
136 humanize.IBytes(uint64(state.TxBytes)),
137 humanize.IBytes(uint64(state.TxSpeed)),
143 ctx.LogE("call-started", les, err, func(les LEs) string {
144 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)