@multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
@headitem Version @tab Size @tab Tarball @tab SHA256 checksum
+@item @ref{Release 0.8, 0.8} @tab 932 KiB
+@tab @url{download/nncp-0.8.tar.xz, link} @url{download/nncp-0.8.tar.xz.sig, sign}
+@tab @code{9BD607D5 C5551857 B7E9277D 0E857936 1DB7353A E0F1556E EA9B1D91 8305B184}
+
@item @ref{Release 0.7, 0.7} @tab 783 KiB
@tab @url{download/nncp-0.7.tar.xz, link} @url{download/nncp-0.7.tar.xz.sig, sign}
@tab @code{D3407323 F89296DD 743FA764 51964B43 794E61BE 0E1D2DD4 ABD02042 B94FFC4F}
@node Новости
@section Новости
+@node Релиз 0.9
+@subsection Релиз 0.9
+@itemize
+@item
+Исправлена обработка @option{-rx}/@option{-tx} опций @command{nncp-call}
+команды. Они игнорировались.
+@end itemize
+
@node Релиз 0.8
@subsection Релиз 0.8
@itemize
See also this page @ref{Новости, on russian}.
+@node Release 0.9
+@section Release 0.9
+@itemize
+@item
+Fix @option{-rx}/@option{-tx} arguments processing in
+@command{nncp-call} command. They were ignored.
+@end itemize
+
@node Release 0.8
@section Release 0.8
@itemize
# $FreeBSD$
PORTNAME= nncp
-PORTVERSION= 0.8
+PORTVERSION= 0.9
CATEGORIES= net
MASTER_SITES= http://www.nncpgo.org/download/ \
http://sourceforge.net/projects/nncp/files/
"strconv"
)
-func (ctx *Ctx) CallNode(node *Node, addrs []string, nice uint8, xxOnly *TRxTx, onlineDeadline, maxOnlineTime uint) (isGood bool) {
+func (ctx *Ctx) CallNode(node *Node, addrs []string, nice uint8, xxOnly TRxTx, onlineDeadline, maxOnlineTime uint) (isGood bool) {
for _, addr := range addrs {
sds := SDS{"node": node.Id, "addr": addr}
ctx.LogD("call", sds, "dialing")
type CallYAML struct {
Cron string
Nice *int `nice,omitempty`
- Xx *string `xx,omitempty`
+ Xx string `xx,omitempty`
Addr *string `addr,omitempty`
OnlineDeadline *uint `onlinedeadline,omitempty`
MaxOnlineTime *uint `maxonlinetime,omitempty`
nice = uint8(*callYml.Nice)
}
var xx TRxTx
- if callYml.Xx != nil {
- switch *callYml.Xx {
- case "rx":
- xx = TRx
- case "tx":
- xx = TTx
- default:
- return nil, errors.New("xx field must be either \"rx\" or \"tx\"")
- }
+ switch callYml.Xx {
+ case "rx":
+ xx = TRx
+ case "tx":
+ xx = TTx
+ case "":
+ default:
+ return nil, errors.New("xx field must be either \"rx\" or \"tx\"")
}
var addr *string
if callYml.Addr != nil {
calls = append(calls, &Call{
Cron: expr,
Nice: nice,
- Xx: &xx,
+ Xx: xx,
Addr: addr,
OnlineDeadline: onlineDeadline,
MaxOnlineTime: maxOnlineTime,
}
}
- if !ctx.CallNode(node, addrs, nice, &xxOnly, *onlineDeadline, *maxOnlineTime) {
+ if !ctx.CallNode(node, addrs, nice, xxOnly, *onlineDeadline, *maxOnlineTime) {
os.Exit(1)
}
}
}
ctx.LogD("daemon", nncp.SDS{"addr": conn.RemoteAddr()}, "accepted")
go func(conn net.Conn) {
- state, err := ctx.StartR(conn, nice, nil)
+ state, err := ctx.StartR(conn, nice, "")
if err == nil {
ctx.LogI("call-start", nncp.SDS{"node": state.Node.Id}, "connected")
state.Wait()
if err, exists := sds["err"]; exists {
msg += ": " + err
}
+ case "lockdir":
+ msg = fmt.Sprintf("Acquire lock for %s: %s", sds["path"], sds["err"])
default:
return s
}
--- /dev/null
+/*
+NNCP -- Node to Node copy, utilities for store-and-forward data exchange
+Copyright (C) 2016-2017 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
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package nncp
+
+import (
+ "os"
+ "path/filepath"
+
+ "golang.org/x/sys/unix"
+)
+
+func (ctx *Ctx) LockDir(nodeId *NodeId, xx TRxTx) (*os.File, error) {
+ ctx.ensureRxDir(nodeId)
+ lockPath := filepath.Join(ctx.Spool, nodeId.String(), string(xx)) + ".lock"
+ dirLock, err := os.OpenFile(
+ lockPath,
+ os.O_CREATE|os.O_WRONLY,
+ os.FileMode(0600),
+ )
+ if err != nil {
+ ctx.LogE("lockdir", SDS{"path": lockPath, "err": err}, "")
+ return nil, err
+ }
+ err = unix.Flock(int(dirLock.Fd()), unix.LOCK_EX|unix.LOCK_NB)
+ if err != nil {
+ ctx.LogE("lockdir", SDS{"path": lockPath, "err": err}, "")
+ dirLock.Close()
+ return nil, err
+ }
+ return dirLock, nil
+}
+
+func (ctx *Ctx) UnlockDir(fd *os.File) {
+ if fd != nil {
+ unix.Flock(int(fd.Fd()), unix.LOCK_UN)
+ fd.Close()
+ }
+}
type Call struct {
Cron *cronexpr.Expression
Nice uint8
- Xx *TRxTx
+ Xx TRxTx
Addr *string
OnlineDeadline uint
MaxOnlineTime uint
TxSpeed int64
rxLock *os.File
txLock *os.File
- xxOnly *TRxTx
+ xxOnly TRxTx
isDead bool
sync.RWMutex
}
return payloadsSplit(payloads)
}
-func (ctx *Ctx) StartI(conn net.Conn, nodeId *NodeId, nice uint8, xxOnly *TRxTx, onlineDeadline, maxOnlineTime uint) (*SPState, error) {
+func (ctx *Ctx) StartI(conn net.Conn, nodeId *NodeId, nice uint8, xxOnly TRxTx, onlineDeadline, maxOnlineTime uint) (*SPState, error) {
err := ctx.ensureRxDir(nodeId)
if err != nil {
return nil, err
}
var rxLock *os.File
- if xxOnly != nil && *xxOnly == TRx {
+ if xxOnly == "" || xxOnly == TRx {
rxLock, err = ctx.LockDir(nodeId, TRx)
if err != nil {
return nil, err
}
}
var txLock *os.File
- if xxOnly != nil && *xxOnly == TTx {
+ if xxOnly == "" || xxOnly == TTx {
txLock, err = ctx.LockDir(nodeId, TTx)
if err != nil {
return nil, err
}
var infosPayloads [][]byte
- if xxOnly == nil || *xxOnly != TTx {
+ if xxOnly == "" || xxOnly == TTx {
infosPayloads = ctx.infosOur(nodeId, nice, &state.infosOurSeen)
}
var firstPayload []byte
return &state, err
}
-func (ctx *Ctx) StartR(conn net.Conn, nice uint8, xxOnly *TRxTx) (*SPState, error) {
+func (ctx *Ctx) StartR(conn net.Conn, nice uint8, xxOnly TRxTx) (*SPState, error) {
started := time.Now()
conf := noise.Config{
CipherSuite: NoiseCipherSuite,
return nil, err
}
var rxLock *os.File
- if xxOnly != nil && *xxOnly == TRx {
+ if xxOnly == "" || xxOnly == TRx {
rxLock, err = ctx.LockDir(node.Id, TRx)
if err != nil {
return nil, err
}
state.rxLock = rxLock
var txLock *os.File
- if xxOnly != nil && *xxOnly == TTx {
+ if xxOnly == "" || xxOnly == TTx {
txLock, err = ctx.LockDir(node.Id, TTx)
if err != nil {
return nil, err
state.txLock = txLock
var infosPayloads [][]byte
- if xxOnly == nil || *xxOnly != TTx {
+ if xxOnly == "" || xxOnly == TTx {
infosPayloads = ctx.infosOur(node.Id, nice, &state.infosOurSeen)
}
var firstPayload []byte
}
}()
- go func() {
- for range time.Tick(time.Second) {
- for _, payload := range state.ctx.infosOur(
- state.Node.Id,
- state.nice,
- &state.infosOurSeen,
- ) {
- state.ctx.LogD(
- "sp-work",
- SdsAdd(sds, SDS{"size": strconv.Itoa(len(payload))}),
- "queuing new info",
- )
- state.payloads <- payload
+ if state.xxOnly == "" || state.xxOnly == TTx {
+ go func() {
+ for range time.Tick(time.Second) {
+ for _, payload := range state.ctx.infosOur(
+ state.Node.Id,
+ state.nice,
+ &state.infosOurSeen,
+ ) {
+ state.ctx.LogD(
+ "sp-work",
+ SdsAdd(sds, SDS{"size": strconv.Itoa(len(payload))}),
+ "queuing new info",
+ )
+ state.payloads <- payload
+ }
}
- }
- }()
+ }()
+ }
state.wg.Add(1)
go func() {
continue
}
state.ctx.LogD("sp-process", sdsp, "received")
- if state.xxOnly != nil && *state.xxOnly == TTx {
+ if state.xxOnly == TTx {
continue
}
state.Lock()
"github.com/davecgh/go-xdr/xdr2"
"github.com/dustin/go-humanize"
"golang.org/x/crypto/blake2b"
- "golang.org/x/sys/unix"
)
func newNotification(fromTo *FromToYAML, subject string) io.Reader {
))
}
-func (ctx *Ctx) LockDir(nodeId *NodeId, xx TRxTx) (*os.File, error) {
- ctx.ensureRxDir(nodeId)
- lockPath := filepath.Join(ctx.Spool, nodeId.String(), string(xx)) + ".lock"
- dirLock, err := os.OpenFile(
- lockPath,
- os.O_CREATE|os.O_WRONLY,
- os.FileMode(0600),
- )
- if err != nil {
- ctx.LogE("lockdir", SDS{"path": lockPath, "err": err}, "")
- return nil, err
- }
- err = unix.Flock(int(dirLock.Fd()), unix.LOCK_EX|unix.LOCK_NB)
- if err != nil {
- ctx.LogE("lockdir", SDS{"path": lockPath, "err": err}, "")
- dirLock.Close()
- return nil, err
- }
- return dirLock, nil
-}
-
-func (ctx *Ctx) UnlockDir(fd *os.File) {
- if fd != nil {
- unix.Flock(int(fd.Fd()), unix.LOCK_UN)
- fd.Close()
- }
-}
-
func (ctx *Ctx) Toss(nodeId *NodeId, nice uint8, dryRun bool) bool {
- dirLock, err := ctx.LockDir(nodeId, TRx)
- if err != nil {
- return false
- }
- defer ctx.UnlockDir(dirLock)
isBad := false
for job := range ctx.Jobs(nodeId, TRx) {
pktName := filepath.Base(job.Fd.Name())
-Subproject commit 98b5b1e7e80eb60271c8dc4eba6521ec2c3e811e
+Subproject commit 0b25a408a50076fbbcae6b7ac0ea5fbb0b085e79