]> Cypherpunks.ru repositories - nncp.git/blob - src/call.go
a201825f82358777700b3af793a9f4905526debd
[nncp.git] / src / call.go
1 /*
2 NNCP -- Node to Node copy, utilities for store-and-forward data exchange
3 Copyright (C) 2016-2021 Sergey Matveev <stargrave@stargrave.org>
4
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.
8
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.
13
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/>.
16 */
17
18 package nncp
19
20 import (
21         "fmt"
22         "net"
23         "time"
24
25         "github.com/dustin/go-humanize"
26         "github.com/gorhill/cronexpr"
27 )
28
29 type Call struct {
30         Cron           *cronexpr.Expression
31         Nice           uint8
32         Xx             TRxTx
33         RxRate         int
34         TxRate         int
35         Addr           *string
36         OnlineDeadline time.Duration
37         MaxOnlineTime  time.Duration
38         WhenTxExists   bool
39         NoCK           bool
40         MCDIgnore      bool
41
42         AutoToss       bool
43         AutoTossDoSeen bool
44         AutoTossNoFile bool
45         AutoTossNoFreq bool
46         AutoTossNoExec bool
47         AutoTossNoTrns bool
48 }
49
50 func (ctx *Ctx) CallNode(
51         node *Node,
52         addrs []string,
53         nice uint8,
54         xxOnly TRxTx,
55         rxRate, txRate int,
56         onlineDeadline, maxOnlineTime time.Duration,
57         listOnly bool,
58         noCK bool,
59         onlyPkts map[[32]byte]bool,
60 ) (isGood bool) {
61         for _, addr := range addrs {
62                 les := LEs{{"Node", node.Id}, {"Addr", addr}}
63                 ctx.LogD("calling", les, func(les LEs) string {
64                         return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
65                 })
66                 var conn ConnDeadlined
67                 var err error
68                 if addr[0] == '|' {
69                         conn, err = NewPipeConn(addr[1:])
70                 } else {
71                         conn, err = net.Dial("tcp", addr)
72                 }
73                 if err != nil {
74                         ctx.LogD("calling", append(les, LE{"Err", err}), func(les LEs) string {
75                                 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
76                         })
77                         continue
78                 }
79                 ctx.LogD("call-connected", les, func(les LEs) string {
80                         return fmt.Sprintf("Connected %s (%s)", node.Name, addr)
81                 })
82                 state := SPState{
83                         Ctx:            ctx,
84                         Node:           node,
85                         Nice:           nice,
86                         onlineDeadline: onlineDeadline,
87                         maxOnlineTime:  maxOnlineTime,
88                         xxOnly:         xxOnly,
89                         rxRate:         rxRate,
90                         txRate:         txRate,
91                         listOnly:       listOnly,
92                         NoCK:           noCK,
93                         onlyPkts:       onlyPkts,
94                 }
95                 if err = state.StartI(conn); err == nil {
96                         ctx.LogI("call-started", les, func(les LEs) string {
97                                 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
98                         })
99                         state.Wait()
100                         ctx.LogI("call-finished", append(
101                                 les,
102                                 LE{"Duration", int64(state.Duration.Seconds())},
103                                 LE{"RxBytes", state.RxBytes},
104                                 LE{"RxSpeed", state.RxSpeed},
105                                 LE{"TxBytes", state.TxBytes},
106                                 LE{"TxSpeed", state.TxSpeed},
107                         ), func(les LEs) string {
108                                 return fmt.Sprintf(
109                                         "Finished call with %s (%d:%d:%d): %s received (%s/sec), %s transferred (%s/sec)",
110                                         node.Name,
111                                         int(state.Duration.Hours()),
112                                         int(state.Duration.Minutes()),
113                                         int(state.Duration.Seconds()/60),
114                                         humanize.IBytes(uint64(state.RxBytes)),
115                                         humanize.IBytes(uint64(state.RxSpeed)),
116                                         humanize.IBytes(uint64(state.TxBytes)),
117                                         humanize.IBytes(uint64(state.TxSpeed)),
118                                 )
119                         })
120                         isGood = true
121                         conn.Close() // #nosec G104
122                         break
123                 } else {
124                         ctx.LogE("call-started", les, err, func(les LEs) string {
125                                 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
126                         })
127                         conn.Close() // #nosec G104
128                 }
129         }
130         return
131 }