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