-
cron: "*/1 * * * MON-FRI"
onlinedeadline: 3600
- nice: 64
+ nice: PRIORITY+10
-
cron: "30 * * * SAT,SUN"
onlinedeadline: 1800
maxonlinetime: 1750
- nice: 64
+ nice: NORMAL
rxrate: 10
txrate: 20
-
will be 4 KiB (containing file itself and some junk).
@item -nice
Set desired outgoing packet @ref{Niceness, niceness level}.
- 1-255 values are allowed.
@item -replynice
Set desired reply packet @ref{Niceness, niceness level}. Only freq
- and exec packets look at that niceness level. 1-255 values are
- allowed.
+ and exec packets look at that niceness level.
@item -node
Process only single specified node.
@item -via
К средствам связанным с online-соединениями (@command{nncp-daemon},
@command{nncp-call}, @command{nncp-caller}) добавлен простой
ограничитель скорости.
+@item
+Возможность задания приоритета символьными обозначениями:
+@verb{|NORMAL|}, @verb{|BULK+10|}, @verb{|PRIORITY-5|}, итд.
+@item
+Изменены значения приоритетов по-умолчанию:
+для @command{nncp-exec} с 64 на 96,
+для @command{nncp-freq} с 64 на 160,
+для @command{nncp-file} с 196 на 224.
@end itemize
@node Релиз 3.2
@item
Simple packet rate limiter added to online-related tools
(@command{nncp-daemon}, @command{nncp-call}, @command{nncp-caller}).
+@item
+Ability to specify niceness with symbolic notation:
+@verb{|NORMAL|}, @verb{|BULK+10|}, @verb{|PRIORITY-5|}, итд.
+@item
+Changed default niceness levels:
+for @command{nncp-exec} from 64 to 96,
+for @command{nncp-freq} from 64 to 160,
+for @command{nncp-file} from 196 to 224.
@end itemize
@node Release 3.2
that packet is "nicer" and allows other to bypass him -- that means
lower transmission precedence.
-Send big files with higher nicer level! That will guarantee you that
+Send big files with higher nice level! That will guarantee you that
higher priority packets, like mail messages, will pass first, even when
lower priority packet was already been partially downloaded.
There are default niceness levels built-in for @ref{nncp-exec},
@ref{nncp-file} and @ref{nncp-freq} commands. But pay attention that it
can give information about underlying payload to the adversary!
+
+There are 1-255 niceness levels. They could be specified either as
+integer, or using aliases with delta modifiers:
+
+@table @emph
+@item FLASH (F)
+Urgent priority.
+@item PRIORITY (P)
+High priority. Command execution/mail use that priority by default.
+@item NORMAL (N)
+Normal priority. File requests use that priority by default.
+@item BULK (B)
+Bundles shipped on a "least effort" basis. File transmission use that
+priority by default.
+@end table
+
+@verbatim
+ 1: F-31 65: P-31 129: N-31 193: B-31
+ 2: F-30 66: P-30 130: N-30 194: B-30
+ ... ... ... ...
+32: F 96: P 160: N 224: B
+33: F+1 97: P+1 161: N+1 225: B+1
+34: F+2 98: P+2 162: N+2 226: B+2
+ ... ... ... ...
+64: F+32 128: P+32 192: N+32 255: B+31 | MAX
+@end verbatim
+
+Precedence could be specified both with single-letter aliases and with
+whole strings. They are case insensitive. @emph{MAX} is an alias for 255
+niceness level.
type CallYAML struct {
Cron string
- Nice *int `yaml:"nice,omitempty"`
+ Nice *string `yaml:"nice,omitempty"`
Xx string `yaml:"xx,omitempty"`
RxRate *int `yaml:"rxrate,omitempty"`
TxRate *int `yaml:"txrate,omitempty"`
nice := uint8(255)
if callYml.Nice != nil {
- if *callYml.Nice < 1 || *callYml.Nice > 255 {
- return nil, errors.New("Nice must be between 1 and 255")
+ nice, err = NicenessParse(*callYml.Nice)
+ if err != nil {
+ return nil, err
}
- nice = uint8(*callYml.Nice)
}
var xx TRxTx
func main() {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", 255, "Minimal required niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(255), "Minimal required niceness")
doRx = flag.Bool("rx", false, "Receive packets")
doTx = flag.Bool("tx", false, "Transfer packets")
doDelete = flag.Bool("delete", false, "Delete transferred packets")
fmt.Println(nncp.VersionGet())
return
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
if *doRx && *doTx {
log.Fatalln("-rx and -tx can not be set simultaneously")
}
func main() {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", 255, "Minimal required niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(255), "Minimal required niceness")
rxOnly = flag.Bool("rx", false, "Only receive packets")
txOnly = flag.Bool("tx", false, "Only transmit packets")
rxRate = flag.Int("rxrate", 0, "Maximal receive rate, pkts/sec")
usage()
os.Exit(1)
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
if *rxOnly && *txOnly {
log.Fatalln("-rx and -tx can not be set simultaneously")
}
func main() {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", 255, "Minimal required niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(255), "Minimal required niceness")
bind = flag.String("bind", "[::]:5400", "Address to bind to")
maxConn = flag.Int("maxconn", 128, "Maximal number of simultaneous connections")
spoolPath = flag.String("spool", "", "Override path to spool")
fmt.Println(nncp.VersionGet())
return
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
func main() {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", nncp.DefaultNiceExec, "Outbound packet niceness")
- replyNiceRaw = flag.Int("replynice", nncp.DefaultNiceFile, "Possible reply packet niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(nncp.DefaultNiceExec), "Outbound packet niceness")
+ replyNiceRaw = flag.String("replynice", nncp.NicenessFmt(nncp.DefaultNiceFile), "Possible reply 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")
usage()
os.Exit(1)
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
- if *replyNiceRaw < 1 || *replyNiceRaw > 255 {
- log.Fatalln("-replynice must be between 1 and 255")
+ replyNice, err := nncp.NicenessParse(*replyNiceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- replyNice := uint8(*replyNiceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
func main() {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
- niceRaw = flag.Int("nice", nncp.DefaultNiceFile, "Outbound packet niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(nncp.DefaultNiceFile), "Outbound packet niceness")
argMinSize = flag.Int64("minsize", -1, "Minimal required resulting packet size, in KiB")
argChunkSize = flag.Int64("chunked", -1, "Split file on specified size chunks, in KiB")
viaOverride = flag.String("via", "", "Override Via path to destination node")
usage()
os.Exit(1)
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
"log"
"os"
"path/filepath"
+ "strconv"
"strings"
"cypherpunks.ru/nncp"
func main() {
var (
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")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(nncp.DefaultNiceFreq), "Outbound packet niceness")
+ replyNiceRaw = flag.String("replynice", strconv.Itoa(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")
usage()
os.Exit(1)
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
- if *replyNiceRaw < 1 || *replyNiceRaw > 255 {
- log.Fatalln("-replynice must be between 1 and 255")
+ replyNice, err := nncp.NicenessParse(*replyNiceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- replyNice := uint8(*replyNiceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
path = string(pkt.Path[:pkt.PathLen])
}
fmt.Printf(
- "Packet type: plain\nPayload type: %s\nNiceness: %d\nPath: %s\n",
- payloadType, pkt.Nice, path,
+ "Packet type: plain\nPayload type: %s\nNiceness: %s (%d)\nPath: %s\n",
+ payloadType, nncp.NicenessFmt(pkt.Nice), pkt.Nice, path,
)
return
}
return
}
fmt.Printf(
- "Packet type: encrypted\nNiceness: %d\nSender: %s\nRecipient: %s\n",
- pktEnc.Nice, pktEnc.Sender, pktEnc.Recipient,
+ "Packet type: encrypted\nNiceness: %s (%d)\nSender: %s\nRecipient: %s\n",
+ nncp.NicenessFmt(pktEnc.Nice), pktEnc.Nice, pktEnc.Sender, pktEnc.Recipient,
)
return
}
txBytes[job.PktEnc.Nice] = txBytes[job.PktEnc.Nice] + job.Size
}
fmt.Println(node.Name)
- for nice := 0; nice < 256; nice++ {
- rxNum, rxExists := rxNums[uint8(nice)]
- txNum, txExists := txNums[uint8(nice)]
+ var nice uint8
+ for nice = 1; nice > 0; nice++ {
+ rxNum, rxExists := rxNums[nice]
+ txNum, txExists := txNums[nice]
if !(rxExists || txExists) {
continue
}
fmt.Printf(
- "\tnice:% 3d | Rx: % 10s, % 3d pkts | Tx: % 10s, % 3d pkts\n",
- nice,
- humanize.IBytes(uint64(rxBytes[uint8(nice)])),
+ "\tnice:% 4s | Rx: % 10s, % 3d pkts | Tx: % 10s, % 3d pkts\n",
+ nncp.NicenessFmt(nice),
+ humanize.IBytes(uint64(rxBytes[nice])),
rxNum,
- humanize.IBytes(uint64(txBytes[uint8(nice)])),
+ humanize.IBytes(uint64(txBytes[nice])),
txNum,
)
}
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
nodeRaw = flag.String("node", "", "Process only that node")
- niceRaw = flag.Int("nice", 255, "Minimal required niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(255), "Minimal required niceness")
dryRun = flag.Bool("dryrun", false, "Do not actually write any tossed data")
doSeen = flag.Bool("seen", false, "Create .seen files")
cycle = flag.Uint("cycle", 0, "Repeat tossing after N seconds in infinite loop")
fmt.Println(nncp.VersionGet())
return
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
ctx, err := nncp.CtxFromCmdline(*cfgPath, *spoolPath, *logPath, *quiet, *debug)
if err != nil {
var (
cfgPath = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
nodeRaw = flag.String("node", "", "Process only that node")
- niceRaw = flag.Int("nice", 255, "Minimal required niceness")
+ niceRaw = flag.String("nice", nncp.NicenessFmt(255), "Minimal required niceness")
rxOnly = flag.Bool("rx", false, "Only receive packets")
txOnly = flag.Bool("tx", false, "Only transfer packets")
mkdir = flag.Bool("mkdir", false, "Create necessary outbound directories")
usage()
os.Exit(1)
}
- if *niceRaw < 1 || *niceRaw > 255 {
- log.Fatalln("-nice must be between 1 and 255")
+ nice, err := nncp.NicenessParse(*niceRaw)
+ if err != nil {
+ log.Fatalln(err)
}
- nice := uint8(*niceRaw)
if *rxOnly && *txOnly {
log.Fatalln("-rx and -tx can not be set simultaneously")
}
--- /dev/null
+package nncp
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+const (
+ NiceFlash = 32
+ NicePriority = 96
+ NiceNormal = 160
+ NiceBulk = 224
+
+ DefaultNiceExec = NicePriority
+ DefaultNiceFreq = NiceNormal
+ DefaultNiceFile = NiceBulk
+)
+
+var (
+ niceRe *regexp.Regexp = regexp.MustCompile(`^(\w+)([-+])(\d+)$`)
+ niceAliases map[string]uint8 = map[string]uint8{
+ "flash": NiceFlash,
+ "f": NiceFlash,
+ "priority": NicePriority,
+ "p": NicePriority,
+ "normal": NiceNormal,
+ "n": NiceNormal,
+ "bulk": NiceBulk,
+ "b": NiceBulk,
+ "max": 255,
+ }
+)
+
+func NicenessParse(s string) (uint8, error) {
+ if nice, err := strconv.Atoi(s); err == nil {
+ if nice <= 0 || nice > 255 {
+ return 0, errors.New("nice out of bounds")
+ }
+ return uint8(nice), nil
+ }
+ s = strings.ToLower(s)
+ var baseNice uint8
+ var found bool
+ if baseNice, found = niceAliases[s]; found {
+ return baseNice, nil
+ }
+ matches := niceRe.FindStringSubmatch(s)
+ if len(matches) != 1+3 {
+ return 0, errors.New("invalid niceness")
+ }
+ baseNice, found = niceAliases[matches[1]]
+ if !found {
+ return 0, errors.New("invalid niceness")
+ }
+ delta, err := strconv.Atoi(matches[3])
+ if err != nil {
+ return 0, err
+ }
+ if matches[2] == "-" {
+ if delta > 31 {
+ return 0, errors.New("too big niceness delta")
+ }
+ return baseNice - uint8(delta), nil
+ } else {
+ if delta > 32 || (baseNice == NiceBulk && delta > 31) {
+ return 0, errors.New("too big niceness delta")
+ }
+ return baseNice + uint8(delta), nil
+ }
+}
+
+func NicenessFmt(nice uint8) string {
+ switch {
+ case nice == 255:
+ return "MAX"
+ case NiceFlash-31 < nice && nice < NiceFlash:
+ return fmt.Sprintf("F-%d", NiceFlash-nice)
+ case nice == NiceFlash:
+ return "F"
+ case NiceFlash < nice && nice <= (NiceFlash+32):
+ return fmt.Sprintf("F+%d", nice-NiceFlash)
+
+ case NicePriority-31 < nice && nice < NicePriority:
+ return fmt.Sprintf("P-%d", NicePriority-nice)
+ case nice == NicePriority:
+ return "P"
+ case NicePriority < nice && nice <= (NicePriority+32):
+ return fmt.Sprintf("P+%d", nice-NicePriority)
+
+ case NiceNormal-31 < nice && nice < NiceNormal:
+ return fmt.Sprintf("N-%d", NiceNormal-nice)
+ case nice == NiceNormal:
+ return "N"
+ case NiceNormal < nice && nice <= (NiceNormal+32):
+ return fmt.Sprintf("N+%d", nice-NiceNormal)
+
+ case NiceBulk-31 < nice && nice < NiceBulk:
+ return fmt.Sprintf("B-%d", NiceBulk-nice)
+ case nice == NiceBulk:
+ return "B"
+ case NiceBulk < nice && nice <= (NiceBulk+30):
+ return fmt.Sprintf("B+%d", nice-NiceBulk)
+ }
+ return strconv.Itoa(int(nice))
+}
--- /dev/null
+package nncp
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestNiceSymmetric(t *testing.T) {
+ var nice uint8
+ for nice = 1; nice > 0; nice++ {
+ s := NicenessFmt(nice)
+ parsed, err := NicenessParse(s)
+ if err != nil || parsed != nice {
+ t.Error(err)
+ }
+ parsed, err = NicenessParse(strings.ToLower(s))
+ if err != nil || parsed != nice {
+ t.Error(err)
+ }
+ }
+}
MaxPathSize = 1<<8 - 1
- DefaultNiceExec = 64
- DefaultNiceFreq = 64
- DefaultNiceFile = 196
-
NNCPBundlePrefix = "NNCP"
)