/*
NNCP -- Node to Node copy, utilities for store-and-forward data exchange
-Copyright (C) 2016-2019 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2016-2022 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
package nncp
import (
+ "errors"
+ "fmt"
"net"
- "strconv"
+ "os"
+ "strings"
+ "time"
+ "github.com/dustin/go-humanize"
"github.com/gorhill/cronexpr"
+ nncpYggdrasil "go.cypherpunks.ru/nncp/v8/yggdrasil"
)
type Call struct {
RxRate int
TxRate int
Addr *string
- OnlineDeadline uint
- MaxOnlineTime uint
+ OnlineDeadline time.Duration
+ MaxOnlineTime time.Duration
+ WhenTxExists bool
+ NoCK bool
+ MCDIgnore bool
+
+ AutoToss bool
+ AutoTossDoSeen bool
+ AutoTossNoFile bool
+ AutoTossNoFreq bool
+ AutoTossNoExec bool
+ AutoTossNoTrns bool
+ AutoTossNoArea bool
+ AutoTossNoACK bool
}
func (ctx *Ctx) CallNode(
nice uint8,
xxOnly TRxTx,
rxRate, txRate int,
- onlineDeadline, maxOnlineTime uint,
+ onlineDeadline, maxOnlineTime time.Duration,
listOnly bool,
- onlyPkts map[[32]byte]bool,
+ noCK bool,
+ onlyPkts map[[MTHSize]byte]bool,
) (isGood bool) {
for _, addr := range addrs {
- sds := SDS{"node": node.Id, "addr": addr}
- ctx.LogD("call", sds, "dialing")
- conn, err := net.Dial("tcp", addr)
+ les := LEs{{"Node", node.Id}, {"Addr", addr}}
+ ctx.LogD("calling", les, func(les LEs) string {
+ return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
+ })
+ var conn ConnDeadlined
+ var err error
+ if addr[0] == '|' {
+ conn, err = NewPipeConn(addr[1:])
+ } else if addr == UCSPITCPClient {
+ ucspiConn := UCSPIConn{R: os.NewFile(6, "R"), W: os.NewFile(7, "W")}
+ if ucspiConn.R == nil {
+ err = errors.New("no 6 file descriptor")
+ }
+ if ucspiConn.W == nil {
+ err = errors.New("no 7 file descriptor")
+ }
+ conn = ucspiConn
+ addr = UCSPITCPRemoteAddr()
+ if addr == "" {
+ addr = UCSPITCPClient
+ }
+ } else if strings.HasPrefix(addr, "yggdrasilc://") {
+ conn, err = nncpYggdrasil.NewConn(ctx.YggdrasilAliases, addr)
+ } else {
+ conn, err = net.Dial("tcp", addr)
+ }
if err != nil {
- ctx.LogD("call", SdsAdd(sds, SDS{"err": err}), "dialing")
+ ctx.LogE("calling", les, err, func(les LEs) string {
+ return fmt.Sprintf("Calling %s (%s)", node.Name, addr)
+ })
continue
}
- ctx.LogD("call", sds, "connected")
+ ctx.LogD("call-connected", les, func(les LEs) string {
+ return fmt.Sprintf("Connected %s (%s)", node.Name, addr)
+ })
state := SPState{
Ctx: ctx,
Node: node,
rxRate: rxRate,
txRate: txRate,
listOnly: listOnly,
+ NoCK: noCK,
onlyPkts: onlyPkts,
}
if err = state.StartI(conn); err == nil {
- ctx.LogI("call-start", sds, "connected")
- state.Wait()
- ctx.LogI("call-finish", SDS{
- "node": state.Node.Id,
- "duration": strconv.FormatInt(int64(state.Duration.Seconds()), 10),
- "rxbytes": strconv.FormatInt(state.RxBytes, 10),
- "txbytes": strconv.FormatInt(state.TxBytes, 10),
- "rxspeed": strconv.FormatInt(state.RxSpeed, 10),
- "txspeed": strconv.FormatInt(state.TxSpeed, 10),
- }, "")
- isGood = true
+ ctx.LogI("call-started", les, func(les LEs) string {
+ return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
+ })
+ isGood = state.Wait()
+ ctx.LogI("call-finished", append(
+ les,
+ LE{"Duration", int64(state.Duration.Seconds())},
+ LE{"RxBytes", state.RxBytes},
+ LE{"RxSpeed", state.RxSpeed},
+ LE{"TxBytes", state.TxBytes},
+ LE{"TxSpeed", state.TxSpeed},
+ ), func(les LEs) string {
+ return fmt.Sprintf(
+ "Finished call with %s (%d:%d:%d): %s received (%s/sec), %s transferred (%s/sec)",
+ node.Name,
+ int(state.Duration.Hours()),
+ int(state.Duration.Minutes()),
+ int(state.Duration.Seconds())%60,
+ humanize.IBytes(uint64(state.RxBytes)),
+ humanize.IBytes(uint64(state.RxSpeed)),
+ humanize.IBytes(uint64(state.TxBytes)),
+ humanize.IBytes(uint64(state.TxSpeed)),
+ )
+ })
conn.Close()
break
} else {
- ctx.LogE("call-start", SdsAdd(sds, SDS{"err": err}), "")
+ ctx.LogE("call-started", les, err, func(les LEs) string {
+ return fmt.Sprintf("Connection to %s (%s)", node.Name, addr)
+ })
conn.Close()
}
}