]> Cypherpunks.ru repositories - nncp.git/blob - src/call.go
Merge branch 'develop'
[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
41         AutoToss       bool
42         AutoTossDoSeen bool
43         AutoTossNoFile bool
44         AutoTossNoFreq bool
45         AutoTossNoExec bool
46         AutoTossNoTrns bool
47 }
48
49 func (ctx *Ctx) CallNode(
50         node *Node,
51         addrs []string,
52         nice uint8,
53         xxOnly TRxTx,
54         rxRate, txRate int,
55         onlineDeadline, maxOnlineTime time.Duration,
56         listOnly bool,
57         noCK bool,
58         onlyPkts map[[32]byte]bool,
59 ) (isGood bool) {
60         for _, addr := range addrs {
61                 les := LEs{{"Node", node.Id}, {"Addr", addr}}
62                 ctx.LogD("calling", les, func(les LEs) string {
63                         return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
64                 })
65                 var conn ConnDeadlined
66                 var err error
67                 if addr[0] == '|' {
68                         conn, err = NewPipeConn(addr[1:])
69                 } else {
70                         conn, err = net.Dial("tcp", addr)
71                 }
72                 if err != nil {
73                         ctx.LogD("calling", append(les, LE{"Err", err}), func(les LEs) string {
74                                 return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
75                         })
76                         continue
77                 }
78                 ctx.LogD("call-connected", les, func(les LEs) string {
79                         return fmt.Sprintf("Connected %s (%s)", node.Name, addr)
80                 })
81                 state := SPState{
82                         Ctx:            ctx,
83                         Node:           node,
84                         Nice:           nice,
85                         onlineDeadline: onlineDeadline,
86                         maxOnlineTime:  maxOnlineTime,
87                         xxOnly:         xxOnly,
88                         rxRate:         rxRate,
89                         txRate:         txRate,
90                         listOnly:       listOnly,
91                         NoCK:           noCK,
92                         onlyPkts:       onlyPkts,
93                 }
94                 if err = state.StartI(conn); err == nil {
95                         ctx.LogI("call-started", les, func(les LEs) string {
96                                 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
97                         })
98                         state.Wait()
99                         ctx.LogI("call-finished", append(
100                                 les,
101                                 LE{"Duration", int64(state.Duration.Seconds())},
102                                 LE{"RxBytes", state.RxBytes},
103                                 LE{"RxSpeed", state.RxSpeed},
104                                 LE{"TxBytes", state.TxBytes},
105                                 LE{"TxSpeed", state.TxSpeed},
106                         ), func(les LEs) string {
107                                 return fmt.Sprintf(
108                                         "Finished call with %s (%d:%d:%d): %s received (%s/sec), %s transferred (%s/sec)",
109                                         node.Name,
110                                         int(state.Duration.Hours()),
111                                         int(state.Duration.Minutes()),
112                                         int(state.Duration.Seconds()),
113                                         humanize.IBytes(uint64(state.RxBytes)),
114                                         humanize.IBytes(uint64(state.RxSpeed)),
115                                         humanize.IBytes(uint64(state.TxBytes)),
116                                         humanize.IBytes(uint64(state.TxSpeed)),
117                                 )
118                         })
119                         isGood = true
120                         conn.Close() // #nosec G104
121                         break
122                 } else {
123                         ctx.LogE("call-started", les, err, func(les LEs) string {
124                                 return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
125                         })
126                         conn.Close() // #nosec G104
127                 }
128         }
129         return
130 }