that is called for mail sending. If it is empty, then no mail processing
will be performed from that node. Sendmail command
@command{["/bin/foo", "bar"]} called the following way:
-@command{NNCP_SENDER=NODEID /bin/foo bar RCPT1 RCPT2 ... < MSG}.
+@command{NNCP_NICE=NICE NNCP_SENDER=NODEID /bin/foo bar RCPT1 RCPT2 ... < MSG}.
@anchor{CfgIncoming}
@item incoming
@node Новости
@section Новости
-@node Релиз 2.1
-@subsection Релиз 2.1
+@node Релиз 3.0
+@subsection Релиз 3.0
@itemize
@item
Возможность переопределить @option{via} опцию конфигурации для целевого
@item
Chunked файлы, меньшего размера чем указанный chunk, отправляются просто
в виде одного файла.
+@item
+@strong{Несовместимое} изменение формата простых пакетов. Добавлено поле
+@emph{NICE}. Работа со старыми версиями не поддерживается.
+@item
+Sendmail команда вызывается с дополнительной переменной окружения
+@env{NNCP_NICE} содержащая значение приоритета пакета с сообщением.
+@item
+Отправляемые файлы в ответ на запрос имеют приоритет указанный в запросе.
+Указать их желаемый приоритет во время вызова @command{nncp-freq} можно
+аргументом @option{-replynice}.
@end itemize
@node Релиз 2.0
@option{-mkdir} для ясности.
@item
-Опция @option{-minsize} задётся в KiB, а не байтах, для удобства.
+Опция @option{-minsize} задаётся в KiB, а не байтах, для удобства.
@item
Команда @command{nncp-newcfg} переименована в @command{nncp-cfgnew},
See also this page @ref{Новости, on russian}.
-@node Release 2.1
-@section Release 2.1
+@node Release 3.0
+@section Release 3.0
@itemize
@item
Ability to override @option{via} configuration option for destination
@item
Chunked files, having size less than specified chunk size, will be sent
as an ordinary single file.
+@item
+@strong{Incompatible} plain packet format changes. @emph{NICE} field is
+added. Older versions are not supported.
+@item
+Sendmail command is invoked with additional @env{NNCP_FILE} environment
+variable containing niceness level from incoming message packet.
+@item
+Files, that are sent as a reply to freq, have niceness level taken from
+the freq packet. You can set desired niceness during @command{nncp-freq}
+invocation using @option{-replynice} option.
@end itemize
@node Release 2.0
@verbatim
HEADER
-+-------------------------------+--...---+
-| MAGIC | TYPE | PATHLEN | PATH | PAYLOAD|
-+-------------------------------+--...---+
++--------------------------------------+--...---+
+| MAGIC | TYPE | NICE | PATHLEN | PATH | PAYLOAD|
++--------------------------------------+--...---+
@end verbatim
@multitable @columnfractions 0.2 0.3 0.5
@item Payload type @tab
unsigned integer @tab
0 (file), 1 (freq), 2 (mail), 3 (transition)
+@item Niceness @tab
+ unsigned integer @tab
+ 1-255, preferred packet @ref{Niceness, niceness} level
@item Path length @tab
unsigned integer @tab
actual length of @emph{path} field's payload
@item Whole encrypted packet we need to relay on
@end itemize
+Also depending on packet's type, niceness level means:
+
+@itemize
+@item Preferable niceness level for files sent by freq
+@item @env{NNCP_NICE} variable's value passed during
+ @ref{CfgSendmail} invocation.
+@end itemize
+
@node Encrypted
@section Encrypted packet
func main() {
var (
- cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness")
- minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
- viaOverride = flag.String("via", "", "Override Via path to destination node")
- spoolPath = flag.String("spool", "", "Override path to spool")
- logPath = flag.String("log", "", "Override path to logfile")
- quiet = flag.Bool("quiet", false, "Print only errors")
- debug = flag.Bool("debug", false, "Print debug messages")
- version = flag.Bool("version", false, "Print version information")
- warranty = flag.Bool("warranty", false, "Print warranty information")
+ cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
+ niceRaw = flag.Int("nice", nncp.DefaultNiceFreq, "Outbound packet niceness")
+ replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Reply file packet niceness")
+ minSize = flag.Uint64("minsize", 0, "Minimal required resulting packet size, in KiB")
+ viaOverride = flag.String("via", "", "Override Via path to destination node")
+ spoolPath = flag.String("spool", "", "Override path to spool")
+ logPath = flag.String("log", "", "Override path to logfile")
+ quiet = flag.Bool("quiet", false, "Print only errors")
+ debug = flag.Bool("debug", false, "Print debug messages")
+ version = flag.Bool("version", false, "Print version information")
+ warranty = flag.Bool("warranty", false, "Print warranty information")
)
flag.Usage = usage
flag.Parse()
log.Fatalln("-nice must be between 1 and 255")
}
nice := uint8(*niceRaw)
+ if *replyNiceRaw < 1 || *replyNiceRaw > 255 {
+ log.Fatalln("-replynice must be between 1 and 255")
+ }
+ replyNice := uint8(*replyNiceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
if err = ctx.TxFreq(
node,
nice,
+ replyNice,
splitted[1],
dst,
int64(*minSize)*1024,
}
var pkt nncp.Pkt
_, err = xdr.Unmarshal(bytes.NewReader(beginning), &pkt)
- if err == nil && pkt.Magic == nncp.MagicNNCPPv1 {
+ if err == nil && pkt.Magic == nncp.MagicNNCPPv2 {
if *dump {
bufW := bufio.NewWriter(os.Stdout)
var r io.Reader
default:
path = string(pkt.Path[:pkt.PathLen])
}
- fmt.Printf("Packet type: plain\nPayload type: %s\nPath: %s\n", payloadType, path)
+ fmt.Printf(
+ "Packet type: plain\nPayload type: %s\nNiceness: %d\nPath: %s\n",
+ payloadType, pkt.Nice, path,
+ )
return
}
var pktEnc nncp.PktEnc
)
var (
- MagicNNCPPv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 1}
+ MagicNNCPPv2 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 2}
MagicNNCPEv3 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 3}
BadMagic error = errors.New("Unknown magic number")
BadPktType error = errors.New("Unknown packet type")
type Pkt struct {
Magic [8]byte
Type PktType
+ Nice uint8
PathLen uint8
Path *[MaxPathSize]byte
}
PktEncOverhead = int64(n)
}
-func NewPkt(typ PktType, path string) (*Pkt, error) {
+func NewPkt(typ PktType, nice uint8, path string) (*Pkt, error) {
pb := []byte(path)
if len(pb) > MaxPathSize {
return nil, errors.New("Too long path")
}
pkt := Pkt{
- Magic: MagicNNCPPv1,
+ Magic: MagicNNCPPv2,
Type: typ,
+ Nice: nice,
PathLen: uint8(len(pb)),
Path: new([MaxPathSize]byte),
}
if len(path) > int(pathSize) {
path = path[:int(pathSize)]
}
- pkt, err := NewPkt(PktTypeFile, path)
+ pkt, err := NewPkt(PktTypeFile, 123, path)
if err != nil {
panic(err)
}
if len(path) > int(pathSize) {
path = path[:int(pathSize)]
}
- pkt, err := NewPkt(PktTypeFile, path)
+ pkt, err := NewPkt(PktTypeFile, 123, path)
if err != nil {
panic(err)
}
)...,
)
cmd.Env = append(cmd.Env, "NNCP_SENDER="+sender.Id.String())
+ cmd.Env = append(cmd.Env, "NNCP_NICE="+strconv.Itoa(int(pkt.Nice)))
cmd.Stdin = decompressor
if err = cmd.Run(); err != nil {
ctx.LogE("rx", SdsAdd(sds, SDS{"err": err}), "sendmail")
if sender.FreqChunked == 0 {
err = ctx.TxFile(
sender,
- job.PktEnc.Nice,
+ pkt.Nice,
filepath.Join(*freq, src),
dst,
sender.FreqMinSize,
} else {
err = ctx.TxFileChunked(
sender,
- job.PktEnc.Nice,
+ pkt.Nice,
filepath.Join(*freq, src),
dst,
sender.FreqMinSize,
}
func TestTossFreq(t *testing.T) {
- f := func(fileSizes []uint8) bool {
+ f := func(fileSizes []uint8, replyNice uint8) bool {
if len(fileSizes) == 0 {
return true
}
if err := ctx.TxFreq(
ctx.Neigh[*nodeOur.Id],
DefaultNiceFreq,
+ replyNice,
fileName,
fileName,
1<<15,
t.Error(err)
return false
}
+ if pkt.Nice != replyNice {
+ return false
+ }
dst := string(pkt.Path[:int(pkt.PathLen)])
if bytes.Compare(buf.Bytes(), files[dst]) != 0 {
return false
os.MkdirAll(txPath, os.FileMode(0700))
for _, data := range datum {
pktTrans := Pkt{
- Magic: MagicNNCPPv1,
+ Magic: MagicNNCPPv2,
Type: PktTypeTrns,
PathLen: blake2b.Size256,
Path: new([MaxPathSize]byte),
var pipeRPrev io.Reader
for i := 1; i < len(hops); i++ {
pktTrans := Pkt{
- Magic: MagicNNCPPv1,
+ Magic: MagicNNCPPv2,
Type: PktTypeTrns,
PathLen: blake2b.Size256,
Path: new([MaxPathSize]byte),
if filepath.IsAbs(dstPath) {
return errors.New("Relative destination path required")
}
- pkt, err := NewPkt(PktTypeFile, dstPath)
+ pkt, err := NewPkt(PktTypeFile, nice, dstPath)
if err != nil {
return err
}
}
if fileSize <= chunkSize {
- pkt, err := NewPkt(PktTypeFile, dstPath)
+ pkt, err := NewPkt(PktTypeFile, nice, dstPath)
if err != nil {
return err
}
sizeToSend = chunkSize
}
path = dstPath + ChunkedSuffixPart + strconv.Itoa(chunkNum)
- pkt, err = NewPkt(PktTypeFile, path)
+ pkt, err = NewPkt(PktTypeFile, nice, path)
if err != nil {
return err
}
return err
}
path = dstPath + ChunkedSuffixMeta
- pkt, err = NewPkt(PktTypeFile, path)
+ pkt, err = NewPkt(PktTypeFile, nice, path)
if err != nil {
return err
}
return err
}
-func (ctx *Ctx) TxFreq(node *Node, nice uint8, srcPath, dstPath string, minSize int64) error {
+func (ctx *Ctx) TxFreq(node *Node, nice, replyNice uint8, srcPath, dstPath string, minSize int64) error {
dstPath = filepath.Clean(dstPath)
if filepath.IsAbs(dstPath) {
return errors.New("Relative destination path required")
if filepath.IsAbs(srcPath) {
return errors.New("Relative source path required")
}
- pkt, err := NewPkt(PktTypeFreq, srcPath)
+ pkt, err := NewPkt(PktTypeFreq, replyNice, srcPath)
if err != nil {
return err
}
}
func (ctx *Ctx) TxMail(node *Node, nice uint8, recipient string, body []byte, minSize int64) error {
- pkt, err := NewPkt(PktTypeMail, recipient)
+ pkt, err := NewPkt(PktTypeMail, nice, recipient)
if err != nil {
return err
}
privates[*node.Id] = node
nodeTgt.Via = append(nodeTgt.Via, node.Id)
}
- pkt, err := NewPkt(PktTypeMail, pathSrc)
+ pkt, err := NewPkt(PktTypeMail, 123, pathSrc)
src := strings.NewReader(data)
dstNode, err := ctx.Tx(
nodeTgt,