2 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
3 Copyright (C) 2016-2022 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 "github.com/dustin/go-humanize"
29 "github.com/gorhill/cronexpr"
32 const YggdrasilPrefix = "yggdrasil:"
35 Cron *cronexpr.Expression
41 OnlineDeadline time.Duration
42 MaxOnlineTime time.Duration
56 func (ctx *Ctx) CallNode(
62 onlineDeadline, maxOnlineTime time.Duration,
65 onlyPkts map[[MTHSize]byte]bool,
67 for _, addr := range addrs {
68 les := LEs{{"Node", node.Id}, {"Addr", addr}}
69 ctx.LogD("calling", les, func(les LEs) string {
70 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
72 var conn ConnDeadlined
75 conn, err = NewPipeConn(addr[1:])
76 } else if addr == UCSPITCPClient {
77 ucspiConn := UCSPIConn{R: os.NewFile(6, "R"), W: os.NewFile(7, "W")}
78 if ucspiConn.R == nil {
79 err = errors.New("no 6 file descriptor")
81 if ucspiConn.W == nil {
82 err = errors.New("no 7 file descriptor")
85 addr = UCSPITCPRemoteAddr()
89 } else if strings.HasPrefix(addr, YggdrasilPrefix) {
90 conn, err = NewYggdrasilConn(
92 strings.TrimPrefix(addr, YggdrasilPrefix),
95 conn, err = net.Dial("tcp", addr)
98 ctx.LogE("calling", les, err, func(les LEs) string {
99 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
103 ctx.LogD("call-connected", les, func(les LEs) string {
104 return fmt.Sprintf("Connected %s (%s)", node.Name, addr)
110 onlineDeadline: onlineDeadline,
111 maxOnlineTime: maxOnlineTime,
119 if err = state.StartI(conn); err == nil {
120 ctx.LogI("call-started", les, func(les LEs) string {
121 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
124 ctx.LogI("call-finished", append(
126 LE{"Duration", int64(state.Duration.Seconds())},
127 LE{"RxBytes", state.RxBytes},
128 LE{"RxSpeed", state.RxSpeed},
129 LE{"TxBytes", state.TxBytes},
130 LE{"TxSpeed", state.TxSpeed},
131 ), func(les LEs) string {
133 "Finished call with %s (%d:%d:%d): %s received (%s/sec), %s transferred (%s/sec)",
135 int(state.Duration.Hours()),
136 int(state.Duration.Minutes()),
137 int(state.Duration.Seconds())%60,
138 humanize.IBytes(uint64(state.RxBytes)),
139 humanize.IBytes(uint64(state.RxSpeed)),
140 humanize.IBytes(uint64(state.TxBytes)),
141 humanize.IBytes(uint64(state.TxSpeed)),
148 ctx.LogE("call-started", les, err, func(les LEs) string {
149 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)