From 561313b1994a8fadac5152bbdc7a980881fd93e0 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 23 Jan 2021 17:57:25 +0300 Subject: [PATCH] On demand calling --- bin/cmd.list | 1 + doc/call.texi | 124 +++------------------------------- doc/cmds.texi | 10 +++ doc/cronexpr.texi | 117 ++++++++++++++++++++++++++++++++ doc/news.ru.texi | 10 +++ doc/news.texi | 9 +++ ports/nncp/Makefile | 2 +- ports/nncp/pkg-plist | 1 + src/call.go | 1 + src/cfg.go | 4 ++ src/cmd/nncp-caller/main.go | 19 ++++++ src/cmd/nncp-cfgnew/main.go | 1 + src/cmd/nncp-cronexpr/main.go | 66 ++++++++++++++++++ 13 files changed, 248 insertions(+), 117 deletions(-) create mode 100644 doc/cronexpr.texi create mode 100644 src/cmd/nncp-cronexpr/main.go diff --git a/bin/cmd.list b/bin/cmd.list index 6c4cf72..7797d4f 100644 --- a/bin/cmd.list +++ b/bin/cmd.list @@ -5,6 +5,7 @@ nncp-cfgenc nncp-cfgmin nncp-cfgnew nncp-check +nncp-cronexpr nncp-daemon nncp-exec nncp-file diff --git a/doc/call.texi b/doc/call.texi index ac24b2a..81ee9ba 100644 --- a/doc/call.texi +++ b/doc/call.texi @@ -28,6 +28,10 @@ calls: [ xx: rx addr: lan }, + { + cron: "*/5 * * * * * *" + when-tx-exists: true + }, ] @end verbatim @@ -46,122 +50,7 @@ It contains the following fields (only @emph{cron} is required): @table @emph @item cron -This is copy-pasted documentation from -@code{github.com/gorhill/cronexpr} library used there. - -@multitable @columnfractions .2 .1 .2 .5 -@headitem Field name @tab Mandatory? @tab Allowed values @tab Allowed special characters - -@item Seconds @tab No @tab 0-59 @tab @verb{|* / , -|} -@item Minutes @tab Yes @tab 0-59 @tab @verb{|* / , -|} -@item Hours @tab Yes @tab 0-23 @tab @verb{|* / , -|} -@item Day of month @tab Yes @tab 1-31 @tab @verb{|* / , - L W|} -@item Month @tab Yes @tab 1-12 or JAN-DEC @tab @verb{|* / , -|} -@item Day of week @tab Yes @tab 0-6 or SUN-SAT @tab @verb{|* / , - L #|} -@item Year @tab No @tab 1970–2099 @tab @verb{|* / , -|} - -@end multitable - -@table @asis - -@item Asterisk (@verb{|*|}) - -The asterisk indicates that the cron expression matches for all values -of the field. E.g., using an asterisk in the 4th field (month) indicates -every month. - -@item Slash (@verb{|/|}) - -Slashes describe increments of ranges. For example @verb{|3-59/15|} in -the minute field indicate the third minute of the hour and every 15 -minutes thereafter. The form @verb{|*/...|} is equivalent to the form -"first-last/...", that is, an increment over the largest possible range -of the field. - -@item Comma (@verb{|,|}) - -Commas are used to separate items of a list. For example, using -@verb{|MON,WED,FRI|} in the 5th field (day of week) means Mondays, -Wednesdays and Fridays. - -@item Hyphen (@verb{|-|}) - -Hyphens define ranges. For example, 2000-2010 indicates every year -between 2000 and 2010 AD, inclusive. - -@item L - -@verb{|L|} stands for "last". When used in the day-of-week field, it -allows you to specify constructs such as "the last Friday" (@verb{|5L|}) -of a given month. In the day-of-month field, it specifies the last day -of the month. - -@item W - -The @verb{|W|} character is allowed for the day-of-month field. This -character is used to specify the business day (Monday-Friday) nearest -the given day. As an example, if you were to specify @verb{|15W|} as the -value for the day-of-month field, the meaning is: "the nearest business -day to the 15th of the month." - -So, if the 15th is a Saturday, the trigger fires on Friday the 14th. If -the 15th is a Sunday, the trigger fires on Monday the 16th. If the 15th -is a Tuesday, then it fires on Tuesday the 15th. However if you specify -@verb{|1W|} as the value for day-of-month, and the 1st is a Saturday, -the trigger fires on Monday the 3rd, as it does not 'jump' over the -boundary of a month's days. - -The @verb{|W|} character can be specified only when the day-of-month is -a single day, not a range or list of days. - -The @verb{|W|} character can also be combined with @verb{|L|}, i.e. -@verb{|LW|} to mean "the last business day of the month." - -@item Hash (@verb{|#|}) - -@verb{|#|} is allowed for the day-of-week field, and must be followed by -a number between one and five. It allows you to specify constructs such -as "the second Friday" of a given month. - -@end table - -Predefined cron expressions: - -@multitable @columnfractions .1 .75 .15 -@headitem Entry @tab Description @tab Equivalent to -@item @verb{|@annually|} @tab - Run once a year at midnight in the morning of January 1 @tab - @verb{|0 0 0 1 1 * *|} -@item @verb{|@yearly|} @tab - Run once a year at midnight in the morning of January 1 @tab - @verb{|0 0 0 1 1 * *|} -@item @verb{|@monthly|} @tab - Run once a month at midnight in the morning of the first of the month @tab - @verb{|0 0 0 1 * * *|} -@item @verb{|@weekly|} @tab - Run once a week at midnight in the morning of Sunday @tab - @verb{|0 0 0 * * 0 *|} -@item @verb{|@daily|} @tab - Run once a day at midnight @tab - @verb{|0 0 0 * * * *|} -@item @verb{|@hourly|} @tab - Run once an hour at the beginning of the hour @tab - @verb{|0 0 * * * * *|} -@end multitable - -@itemize -@item -If only six fields are present, a @verb{|0|} second field is prepended, -that is, @verb{|* * * * * 2013|} internally become -@verb{|0 * * * * * 2013|}. -@item -If only five fields are present, a @verb{|0|} second field is prepended -and a wildcard year field is appended, that is, @verb{|* * * * Mon|} -internally become @verb{|0 * * * * Mon *|}. -@item -Domain for day-of-week field is [0-7] instead of [0-6], 7 being Sunday -(like 0). This to comply with @url{https://linux.die.net/man/5/crontab}. -@end itemize +@include cronexpr.texi @item nice Optional. Use that @ref{Niceness, niceness} during the call (255 is used @@ -193,4 +82,7 @@ Optionally enable auto tossing: run tosser on node's spool every second during the call. You can control either are @file{.seen} files must be created, or skip any kind of packet processing. +@item when-tx-exists +Call only if packets for sending exists. + @end table diff --git a/doc/cmds.texi b/doc/cmds.texi index ae7bd52..e7e21ea 100644 --- a/doc/cmds.texi +++ b/doc/cmds.texi @@ -238,6 +238,16 @@ that has Base32-encoded filenames and compare it with recalculated BLAKE2b hash output of their contents. That supplementary command is not used often in practice, if ever. +@node nncp-cronexpr +@section nncp-cronexpr + +@example +$ nncp-cronexpr -num 12 "*/1 * * * * SAT,SUN 2021" +@end example + +Check validity of specified @ref{CronExpr, cron expression} and print 12 +next time entities. + @node nncp-daemon @section nncp-daemon diff --git a/doc/cronexpr.texi b/doc/cronexpr.texi new file mode 100644 index 0000000..3331b12 --- /dev/null +++ b/doc/cronexpr.texi @@ -0,0 +1,117 @@ +@anchor{CronExpr} +This is copy-pasted documentation from +@code{github.com/gorhill/cronexpr} library used there. + +@multitable @columnfractions .2 .1 .2 .5 +@headitem Field name @tab Mandatory? @tab Allowed values @tab Allowed special characters + +@item Seconds @tab No @tab 0-59 @tab @verb{|* / , -|} +@item Minutes @tab Yes @tab 0-59 @tab @verb{|* / , -|} +@item Hours @tab Yes @tab 0-23 @tab @verb{|* / , -|} +@item Day of month @tab Yes @tab 1-31 @tab @verb{|* / , - L W|} +@item Month @tab Yes @tab 1-12 or JAN-DEC @tab @verb{|* / , -|} +@item Day of week @tab Yes @tab 0-6 or SUN-SAT @tab @verb{|* / , - L #|} +@item Year @tab No @tab 1970–2099 @tab @verb{|* / , -|} + +@end multitable + +@table @asis + +@item Asterisk (@verb{|*|}) + +The asterisk indicates that the cron expression matches for all values +of the field. E.g., using an asterisk in the 4th field (month) indicates +every month. + +@item Slash (@verb{|/|}) + +Slashes describe increments of ranges. For example @verb{|3-59/15|} in +the minute field indicate the third minute of the hour and every 15 +minutes thereafter. The form @verb{|*/...|} is equivalent to the form +"first-last/...", that is, an increment over the largest possible range +of the field. + +@item Comma (@verb{|,|}) + +Commas are used to separate items of a list. For example, using +@verb{|MON,WED,FRI|} in the 5th field (day of week) means Mondays, +Wednesdays and Fridays. + +@item Hyphen (@verb{|-|}) + +Hyphens define ranges. For example, 2000-2010 indicates every year +between 2000 and 2010 AD, inclusive. + +@item L + +@verb{|L|} stands for "last". When used in the day-of-week field, it +allows you to specify constructs such as "the last Friday" (@verb{|5L|}) +of a given month. In the day-of-month field, it specifies the last day +of the month. + +@item W + +The @verb{|W|} character is allowed for the day-of-month field. This +character is used to specify the business day (Monday-Friday) nearest +the given day. As an example, if you were to specify @verb{|15W|} as the +value for the day-of-month field, the meaning is: "the nearest business +day to the 15th of the month." + +So, if the 15th is a Saturday, the trigger fires on Friday the 14th. If +the 15th is a Sunday, the trigger fires on Monday the 16th. If the 15th +is a Tuesday, then it fires on Tuesday the 15th. However if you specify +@verb{|1W|} as the value for day-of-month, and the 1st is a Saturday, +the trigger fires on Monday the 3rd, as it does not 'jump' over the +boundary of a month's days. + +The @verb{|W|} character can be specified only when the day-of-month is +a single day, not a range or list of days. + +The @verb{|W|} character can also be combined with @verb{|L|}, i.e. +@verb{|LW|} to mean "the last business day of the month." + +@item Hash (@verb{|#|}) + +@verb{|#|} is allowed for the day-of-week field, and must be followed by +a number between one and five. It allows you to specify constructs such +as "the second Friday" of a given month. + +@end table + +Predefined cron expressions: + +@multitable @columnfractions .1 .75 .15 +@headitem Entry @tab Description @tab Equivalent to +@item @verb{|@annually|} @tab + Run once a year at midnight in the morning of January 1 @tab + @verb{|0 0 0 1 1 * *|} +@item @verb{|@yearly|} @tab + Run once a year at midnight in the morning of January 1 @tab + @verb{|0 0 0 1 1 * *|} +@item @verb{|@monthly|} @tab + Run once a month at midnight in the morning of the first of the month @tab + @verb{|0 0 0 1 * * *|} +@item @verb{|@weekly|} @tab + Run once a week at midnight in the morning of Sunday @tab + @verb{|0 0 0 * * 0 *|} +@item @verb{|@daily|} @tab + Run once a day at midnight @tab + @verb{|0 0 0 * * * *|} +@item @verb{|@hourly|} @tab + Run once an hour at the beginning of the hour @tab + @verb{|0 0 * * * * *|} +@end multitable + +@itemize +@item +If only six fields are present, a @verb{|0|} second field is prepended, +that is, @verb{|* * * * * 2013|} internally become +@verb{|0 * * * * * 2013|}. +@item +If only five fields are present, a @verb{|0|} second field is prepended +and a wildcard year field is appended, that is, @verb{|* * * * Mon|} +internally become @verb{|0 * * * * Mon *|}. +@item +Domain for day-of-week field is [0-7] instead of [0-6], 7 being Sunday +(like 0). This to comply with @url{https://linux.die.net/man/5/crontab}. +@end itemize diff --git a/doc/news.ru.texi b/doc/news.ru.texi index 1a65a50..6c42a2a 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -9,6 +9,16 @@ Работоспособность @option{-autotoss*} опции с @option{-inetd} режимом @command{nncp-daemon}. +@item +@option{when-tx-exists} опция вызова в конфигурационном файле позволяет +делать вызов только если имеются исходящие сообщения. Совмещённая с cron +выражением содержащим секунды, это можно использовать как возможность +вызова только при появлении исходящих пакетов. + +@item +@command{nncp-cronexpr} команда позволяет проверить корректность и +ожидаемый результат от указанного cron выражения. + @end itemize @node Релиз 5.6.0 diff --git a/doc/news.texi b/doc/news.texi index 1bd2f44..ebd48da 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -11,6 +11,15 @@ See also this page @ref{Новости, on russian}. @option{-autotoss*} option workability with @command{nncp-daemon}'s @option{-inetd} mode. +@item +Call's @option{when-tx-exists} allows to make a call only when outbound +packets exists. Combined with seconds-aware cron expression that can be +used as some kind of auto dialler. + +@item +@command{nncp-cronexpr} command allows you to check validity and +expectations of specified cron expression. + @end itemize @node Release 5.6.0 diff --git a/ports/nncp/Makefile b/ports/nncp/Makefile index b846f49..0ced51b 100644 --- a/ports/nncp/Makefile +++ b/ports/nncp/Makefile @@ -1,7 +1,7 @@ # $FreeBSD: $ PORTNAME= nncp -DISTVERSION= 5.5.1 +DISTVERSION= 5.7.0 CATEGORIES= net MASTER_SITES= http://www.nncpgo.org/download/ diff --git a/ports/nncp/pkg-plist b/ports/nncp/pkg-plist index e7d9c87..4a58402 100644 --- a/ports/nncp/pkg-plist +++ b/ports/nncp/pkg-plist @@ -5,6 +5,7 @@ bin/nncp-cfgenc bin/nncp-cfgmin bin/nncp-cfgnew bin/nncp-check +bin/nncp-cronexpr bin/nncp-daemon bin/nncp-exec bin/nncp-file diff --git a/src/call.go b/src/call.go index 87fb5ae..1635b30 100644 --- a/src/call.go +++ b/src/call.go @@ -33,6 +33,7 @@ type Call struct { Addr *string OnlineDeadline time.Duration MaxOnlineTime time.Duration + WhenTxExists bool AutoToss bool AutoTossDoSeen bool diff --git a/src/cfg.go b/src/cfg.go index a72d371..9462433 100644 --- a/src/cfg.go +++ b/src/cfg.go @@ -81,6 +81,7 @@ type CallJSON struct { Addr *string `json:"addr,omitempty"` OnlineDeadline *uint `json:"onlinedeadline,omitempty"` MaxOnlineTime *uint `json:"maxonlinetime,omitempty"` + WhenTxExists *bool `json:"when-tx-exists,omitempty"` AutoToss *bool `json:"autotoss,omitempty"` AutoTossDoSeen *bool `json:"autotoss-doseen,omitempty"` @@ -280,6 +281,9 @@ func NewNode(name string, cfg NodeJSON) (*Node, error) { if callCfg.MaxOnlineTime != nil { call.MaxOnlineTime = time.Duration(*callCfg.MaxOnlineTime) * time.Second } + if callCfg.WhenTxExists != nil { + call.WhenTxExists = *callCfg.WhenTxExists + } if callCfg.AutoToss != nil { call.AutoToss = *callCfg.AutoToss } diff --git a/src/cmd/nncp-caller/main.go b/src/cmd/nncp-caller/main.go index 826033c..f7ab13c 100644 --- a/src/cmd/nncp-caller/main.go +++ b/src/cmd/nncp-caller/main.go @@ -134,6 +134,25 @@ func main() { node.Busy = true node.Unlock() + if call.WhenTxExists && call.Xx != "TRx" { + ctx.LogD("caller", sds, "checking tx existence") + txExists := false + for job := range ctx.Jobs(node.Id, nncp.TTx) { + job.Fd.Close() + if job.PktEnc.Nice > call.Nice { + continue + } + txExists = true + } + if !txExists { + ctx.LogD("caller", sds, "no tx") + node.Lock() + node.Busy = false + node.Unlock() + continue + } + } + var autoTossFinish chan struct{} var autoTossBadCode chan bool if call.AutoToss { diff --git a/src/cmd/nncp-cfgnew/main.go b/src/cmd/nncp-cfgnew/main.go index 93f3749..798f31c 100644 --- a/src/cmd/nncp-cfgnew/main.go +++ b/src/cmd/nncp-cfgnew/main.go @@ -210,6 +210,7 @@ func main() { # # txrate: 20 # # xx: rx # # addr: lan + # # when-tx-exists: true # # # # autotoss: false # # autotoss-doseen: true diff --git a/src/cmd/nncp-cronexpr/main.go b/src/cmd/nncp-cronexpr/main.go new file mode 100644 index 0000000..c9b4010 --- /dev/null +++ b/src/cmd/nncp-cronexpr/main.go @@ -0,0 +1,66 @@ +/* +NNCP -- Node to Node copy, utilities for store-and-forward data exchange +Copyright (C) 2016-2021 Sergey Matveev + +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, version 3 of the License. + +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 . +*/ + +// NNCP cron expression checker. +package main + +import ( + "flag" + "fmt" + "log" + "os" + "strings" + "time" + + "github.com/gorhill/cronexpr" + "go.cypherpunks.ru/nncp/v5" +) + +func usage() { + fmt.Fprintf(os.Stderr, nncp.UsageHeader()) + fmt.Fprintf(os.Stderr, "nncp-cronexpr -- cron expression checker\n\n") + fmt.Fprintf(os.Stderr, "Usage: %s [-num XXX] CRON-EXPRESSION\n", os.Args[0]) + flag.PrintDefaults() +} + +func main() { + var ( + num = flag.Uint("num", 10, "Number of future entries to print") + version = flag.Bool("version", false, "Print version information") + warranty = flag.Bool("warranty", false, "Print warranty information") + ) + flag.Usage = usage + flag.Parse() + if *warranty { + fmt.Println(nncp.Warranty) + return + } + if *version { + fmt.Println(nncp.VersionGet()) + return + } + + expr, err := cronexpr.Parse(strings.Join(flag.Args(), " ")) + if err != nil { + log.Fatalln(err) + } + now := time.Now() + fmt.Printf("Now:\t%s\n", now.UTC().Format(time.RFC3339Nano)) + for n, t := range expr.NextN(now, *num) { + fmt.Printf("%d:\t%s\n", n, t.UTC().Format(time.RFC3339Nano)) + } +} -- 2.44.0