]> Cypherpunks.ru repositories - nncp.git/commitdiff
Documentation updates
authorSergey Matveev <stargrave@stargrave.org>
Mon, 9 Jan 2017 08:44:02 +0000 (11:44 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Mon, 9 Jan 2017 20:56:40 +0000 (23:56 +0300)
20 files changed:
doc/cfg.texi
doc/cmds.texi
doc/index.texi
doc/log.texi [new file with mode: 0644]
doc/pkt.texi
doc/sp.texi
doc/spool.texi [new file with mode: 0644]
doc/usecases.texi
doc/workflow.texi [new file with mode: 0644]
src/cypherpunks.ru/nncp/cmd/nncp-call/main.go
src/cypherpunks.ru/nncp/cmd/nncp-check/main.go
src/cypherpunks.ru/nncp/cmd/nncp-daemon/main.go
src/cypherpunks.ru/nncp/cmd/nncp-file/main.go
src/cypherpunks.ru/nncp/cmd/nncp-freq/main.go
src/cypherpunks.ru/nncp/cmd/nncp-log/main.go
src/cypherpunks.ru/nncp/cmd/nncp-mail/main.go
src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go
src/cypherpunks.ru/nncp/cmd/nncp-stat/main.go
src/cypherpunks.ru/nncp/cmd/nncp-toss/main.go
src/cypherpunks.ru/nncp/cmd/nncp-xfer/main.go

index 3f114c52bbc520719402139a3586db81d021847e..369ce78a3c594ddcf8a59cf643550dc19a66e6ed 100644 (file)
@@ -1,4 +1,104 @@
 @node Configuration
 @unnumbered Configuration file
 
-TODO.
+Example YAML configuration file:
+
+@verbatim
+spool: /var/spool/nncp
+log: /var/spool/nncp/log
+notify:
+  file:
+    from: nncp@localhost
+    to: user+file@example.com
+  freq:
+    from: nncp@localhost
+    to: user+freq@example.com
+self:
+  id: TIJQL...2NGIA
+  exchpub: CYVGQ...PSEWQ
+  exchprv: 65PUY...MPZ3Q
+  signpub: 2NMVC...CMH5Q
+  signprv: 555JD...RGD6Y
+  noiseprv: D62XU...NKYPA
+  noisepub: KIBKK...ESM7Q
+neigh:
+  self:
+    id: TIJQL...2NGIA
+    exchpub: CYVGQ...PSEWQ
+    signpub: 2NMVC...CMH5Q
+    noisepub: KIBKK...ESM7Q
+    sendmail: [/usr/sbin/sendmail]
+  alice:
+    id: XJZBK...65IJQ
+    exchpub: MJACJ...FAI6A
+    signpub: T4AFC...N2FRQ
+    noisepub: UBM5K...VI42A
+    sendmail: [/bin/sh, -c, false]
+    incoming: /home/alice/incoming
+    addrs:
+      lan: "[fe80::1234%igb0]:5400"
+      internet: alice.com:3389
+  bob:
+    id: 2IZNP...UYGYA
+    exchpub: WFLMZ...B7NHA
+    signpub: GTGXG...IE3OA
+    noisepub: EQAZM...J3NBA
+    sendmail: [/usr/sbin/sendmail]
+    freq: /home/bob/pub
+    via: [alice]
+@end verbatim
+
+@strong{spool} field contains an absolute path to @ref{Spool, spool}
+directory. @strong{log} field contains an absolute path to @ref{Log,
+log} file.
+
+@strong{notify} section contains notification settings for successfully
+tossed file and file request packets. Corresponding @strong{from} and
+@strong{to} fields will substituted in notification email message.
+@emph{neigh/self/sendmail} will be used as a local mailer. If
+either of @emph{from}/@emph{to} fields are omitted, then no notification
+will be sent.
+
+@strong{self} section contains our node's private keypairs.
+@strong{exch*} and @strong{sign*} are used during @ref{Encrypted,
+encrypted} packet creation. @strong{noise*} are used during @ref{Sync,
+sync protocol} working in @ref{nncp-call}/@ref{nncp-daemon}.
+
+@strong{neigh} section contains all known neighbours information. It
+always has @strong{self} neighbour that is copy of our node's public
+data (public keys). It is useful for copy-paste sharing with your
+friends. Each section's key is a human-readable name of the neighbour.
+
+Except for @emph{id}, @emph{exchpub} and @emph{signpub} each node has
+the following fields:
+
+@table @strong
+@item noisepub
+Must be present, but can be dummy (only zeros) if no online
+communication using @ref{Sync, sync protocol} will be used.
+
+@item sendmail
+An array containing path to executable and its command line arguments
+that is called for mail sending.
+
+@item incoming
+Full path to directory where all file uploads will be saved. May be
+omitted to forbid file uploading on that node.
+
+@item freq
+Full path to directory from where file requests will queue files for
+transmission. May be omitted to forbid freqing from that node.
+
+@item via
+An array of node identifiers that will be used as a relay to that node.
+For example @code{[foo,bar]} means that packet can reach current node by
+transitioning through @code{foo} and then @code{bar} nodes. May be
+omitted if direct connection exists and no relaying is required.
+
+@item addrs
+Dictionary containing known network addresses of the node. Each key is
+human-readable name of the link/address. Values are @code{addr:port}
+pairs pointing to @ref{nncp-daemon}'s listening instance. May be omitted
+if either no direct connection exists, or @ref{nncp-call} is used with
+forced address specifying.
+@end table
index af9369a593763b1e127b7433d4151bbaa58880ff..38849a0d01d41289931eb9bce9cc2e20fc84db73 100644 (file)
 @node Commands
 @unnumbered Commands
 
+Nearly all commands have the following common options:
+
+@table @code
+@item -debug
+    Print debug messages. Normally this option should not be used.
+@item -nice
+    Set desired outgoing packet niceness level. 1-255 values are
+    allowed. Higher value means lower priority. In some commands that
+    means processing of packets that have equal or lower nice value.
+    That is used for controlling network QoS.
+@item -node
+    Process only single specified node.
+@item -quiet
+    Print only errors, omit simple informational messages. In any case
+    those messages are logged, so you can reread them using
+    @ref{nncp-log} command.
+@item -version
+    Print version information.
+@item -warranty
+    Print warranty information (no warranty).
+@end table
+
 @node nncp-call
 @section nncp-call
 
-TODO.
+@verbatim
+% nncp-call [options] [-rx|-tx] NODE[:ADDR] [FORCEADDR]
+@end verbatim
+
+Call (connect to) specified @code{NODE} and run @ref{Sync,
+synchronization} protocol with the @ref{nncp-daemon, daemon} on the
+remote side. Normally this command could be run any time you wish to
+either check for incoming packets, or to send out queued ones.
+Synchronization protocol allows resuming and bidirectional packets
+transfer.
+
+If @code{-rx} option is specified then only inbound packets transmission
+is performed. If @code{-tx} option is specified, then only outbound
+transmission is performed.
+
+Each @code{NODE} can contain several uniquely identified
+@code{ADDR}esses in @ref{Configuration, configuration} file. If you do
+not specify the exact one, then all will be tried until the first
+success. Optionally you can force @code{FORCEADDR} address usage,
+instead of addresses taken from configuration file.
+
+Pay attention that this command run integrity check for each completely
+received packet in the background. This can be time consuming and
+connection could be lost during that check time and remote node won't be
+notified that file is done. But after successful integrity check that
+file will be renamed from @code{.part} one and when you rerun
+@code{nncp-call} again, remote node will receive completion at once.
 
 @node nncp-check
 @section nncp-check
 
-TODO.
+@verbatim
+% nncp-check [options]
+@end verbatim
+
+Perform @ref{Spool, spool} directory integrity check. Read all files
+that has Base32-encoded filenames and compare it with recalculated
+BLAKE2b hash output of their contents. This supplementary command should
+not be used often in practice, if ever.
 
 @node nncp-daemon
 @section nncp-daemon
 
-TODO.
+@verbatim
+% nncp-daemon [options] [-maxconn INT] [-bind ADDR]
+@end verbatim
+
+Start listening TCP daemon, wait for incoming connections and run
+@ref{Sync, sync protocol} with each of them. You can run @ref{nncp-toss}
+utility in background to process inbound packets from time to time.
+
+@code{-maxconn} option specifies how many simultaneous clients daemon
+can handle. @code{-bind} option specifies @code{addr:port} it must bind
+to and listen.
 
 @node nncp-file
 @section nncp-file
 
-TODO.
+@verbatim
+% nncp-file [options] SRC NODE:[DST]
+@end verbatim
+
+Send @code{SRC} file to remote @code{NODE}. @code{DST} specifies
+destination file name in remote's @ref{Configuration, incoming}
+directory. If this file already exists there, then counter will be
+appended to it.
+
+This command queues file in @ref{Spool, spool} directory immediately
+(through the temporary file of course) -- so pay attention that sending
+2 GiB file will create 2 GiB outbound encrypted packet.
+
+If @ref{Configuration, notification} is enabled on the remote side for
+file transmissions, then it will sent simple letter after successful
+file receiving.
 
 @node nncp-freq
 @section nncp-freq
 
-TODO.
+@verbatim
+% nncp-freq [options] NODE:SRC DST
+@end verbatim
+
+Send file request to @code{NODE}, asking it to send its @code{SRC} file
+from @ref{Configuration, freq} directory to our node under @code{DST}
+filename in our @ref{Configuration, incoming} one.
+
+If @ref{Configuration, notification} is enabled on the remote side for
+file request, then it will sent simple letter after successful file
+queuing.
 
 @node nncp-log
 @section nncp-log
 
-TODO.
+@verbatim
+% nncp-log [options]
+@end verbatim
+
+Parse @ref{Log, log} file and print out its records in human-readable form.
 
 @node nncp-mail
 @section nncp-mail
 
-TODO.
+@verbatim
+% nncp-mail [options] NODE USER ...
+@end verbatim
+
+Send mail, that is read from stdin, to @code{NODE} and specified
+@code{USER}s. Mail message will be compressed. After receiving, remote
+side will execute specified @ref{Configuration, sendmail} command with
+@code{USER}s appended as a command line argument and feed decompressed
+mail body to that command's stdin.
 
 @node nncp-newnode
 @section nncp-newnode
 
-TODO.
+@verbatim
+% nncp-newnode [options] > mynewnode.yaml
+@end verbatim
+
+Generate new node: private keys, example configuration file and print it
+to stdout. You must use this command when you setup the new node.
+
+Pay attention that private keys generation consumes an entropy from your
+operating system.
 
 @node nncp-pkt
 @section nncp-pkt
 
-TODO.
+@verbatim
+% nncp-pkt [options] < pkt
+% nncp-pkt [options] -dump < pkt > payload
+@end verbatim
+
+Low level packet parser. Normally it should not be used, but can help in
+debugging.
+
+By default it will print packet's type, for example:
+@verbatim
+Packet type: encrypted
+Niceness: 64
+Sender: 2WHBV3TPZHDOZGUJEH563ZEK7M33J4UESRFO4PDKWD5KZNPROABQ
+Payload size: 4.0 MiB (4162852 bytes)
+@end verbatim
+
+If you specify @code{-dump} option and provide an @ref{Encrypted,
+encrypted} packet, then it will verify and decrypt it to stdout.
+Encrypted packets contain @ref{Plain, plain} ones, that also can be fed
+to @code{nncp-pkt}:
+
+@verbatim
+Packet type: plain
+Payload type: transitional
+Path: VHMTRWDOXPLK7BR55ICZ5N32ZJUMRKZEMFNGGCEAXV66GG43PEBQ
+
+Packet type: plain
+Payload type: mail
+Path: stargrave@stargrave.org
+@end verbatim
+
+And with the @code{-dump} option it will give you the actual payload
+(the whole file, mail message, and so on).
 
 @node nncp-stat
 @section nncp-stat
 
-TODO.
+@verbatim
+% nncp-stat [options]
+@end verbatim
+
+Print current @ref{Spool, spool} statistics about unsent and unprocessed
+packets. For each node and each niceness level there will be printed how
+many packets (with the total size) are in inbound (Rx) and outbound (Tx)
+queues.
 
 @node nncp-toss
 @section nncp-toss
 
-TODO.
+@verbatim
+% nncp-toss [options] [-dryrun]
+@end verbatim
+
+Perform "tossing" operation on all inbound packets. This is the tool
+that decrypts all packets and processes all payload packets in them:
+copies files, sends mails, sends out file requests and relays transition
+packets. It should be run after each online/offline exchange.
+
+@code{-dryrun} option does not perform any writing and sending, just
+tells what it will do.
 
 @node nncp-xfer
 @section nncp-xfer
 
-TODO.
+@verbatim
+% nncp-xfer [options] [-force] [-keep] [-rx|-tx] DIR
+@end verbatim
+
+Search for directory in @code{DIR} containing inbound packets for us and
+move them to local @ref{Spool, spool} directory. Also search for known
+neighbours directories and move locally queued outbound packets to them.
+This command is used for offline packets transmission.
+
+If @code{-force} option is specified, then outbound neighbour(s)
+directories will be created. This is useful for the first time usage,
+when storage device does not have any directories tree.
+
+If @code{-keep} option is specified, then keep copied files, do not
+remove them.
+
+@code{-rx} option tells only to move inbound packets addressed to us.
+@code{-tx} option tells exactly the opposite: move only outbound packets.
+
+@code{DIR} directory has the following structure:
+@code{RECIPIENT/SENDER/PACKET}, where @code{RECIPIENT} is Base32 encoded
+destination node, @code{SENDER} is Base32 encoded sender node.
index 1307c0f7d0daac4bce2d4078de5e1f9b0faa0bd6..681472386334b31b0c68aadd43344b4bf8eaad12 100644 (file)
@@ -52,21 +52,27 @@ POSIX}-compatible systems. Easy integration with existing
 @menu
 * Comparison with existing solutions: Comparison.
 * Use cases::
-* Commands::
+* Workflow::
 * Configuration file: Configuration.
+* Commands::
+* Spool directory: Spool.
+* Log format: Log.
 * Packet format: Packet.
 * Sync protocol: Sync.
-* Copying conditions::
+* Copying conditions: Copying.
 @end menu
 
 @include comparison.texi
 @include usecases.texi
-@include cmds.texi
+@include workflow.texi
 @include cfg.texi
+@include cmds.texi
+@include spool.texi
+@include log.texi
 @include pkt.texi
 @include sp.texi
 
-@node Copying conditions
+@node Copying
 @unnumbered Copying conditions
 
 @insertcopying
diff --git a/doc/log.texi b/doc/log.texi
new file mode 100644 (file)
index 0000000..3b567a0
--- /dev/null
@@ -0,0 +1,31 @@
+@node Log
+@unnumbered Log format
+
+Log is a plaintext file with single log entry per line. Lines are "\n"
+separated. Each line has the following format:
+
+@verbatim
+LEVEL | DATETIME | SD | MSG
+@end verbatim
+
+Example log records:
+
+@verbatim
+I 2017-01-09T08:41:54.751732131Z [nncp-xfer node="VHMTRWDOXPLK7BR55ICZ5N32ZJUMRKZEMFNGGCEAXV66GG43PEBQ" pkt="KMG6FO5UNEK7HWVFJPWQYC7MOZ76KEZ4FWCGM62PWA2QE5755NPA" size="4162548" xx="tx"]
+I 2017-01-09T08:42:18.990005394Z [sp-infos node="BYRRQUULEHINPKEFN7CHMSHR5I5CK7PMX5HQNCYERTBAR4BOCG6Q" pkts="0" size="0" xx="tx"]
+I 2017-01-09T08:48:59.264847401Z [call-finish duration="10" node="BYRRQUULEHINPKEFN7CHMSHR5I5CK7PMX5HQNCYERTBAR4BOCG6Q" rxbytes="60" rxspeed="60" txbytes="108" txspeed="108"]
+@end verbatim
+
+@table @code
+@item |
+    Space character.
+@item LEVEL
+    Is single character log level. As a rule is is either @code{I}
+    (informational message), or @code{E} (error message).
+@item DATETIME
+    UTC datetime in RFC 3339 @code{2006-01-02T15:04:05.999999999Z} format.
+@item SD
+    Structured data as in RFC 5424.
+@item MSG
+    Arbitrary UTF-8 encoded text data.
+@end table
index 87484a107a82e99be1f86d7321dec20a44472acb..492871b7fafc3a2e7c7f9f7e210098a1d948aaf4 100644 (file)
@@ -18,8 +18,6 @@ transition packet or email message. It is called "plain", because it
 contains plaintext, but plain packets would never be stored on your hard
 drive.
 
-Each packet has the following header:
-
 @verbatim
             HEADER
 +-------------------------------+--...---+
@@ -29,34 +27,31 @@ Each packet has the following header:
 
 @multitable @columnfractions 0.2 0.3 0.5
 @headitem  @tab XDR type @tab Value
-
 @item Magic number @tab
-  8-byte, fixed length opaque data @tab
-  @code{NNCPP0x10x00x00}
-
+    8-byte, fixed length opaque data @tab
+    @code{NNCPP0x10x00x00}
 @item Payload type @tab
-  unsigned integer @tab
-  0 (file), 1 (freq), 2 (mail), 3 (transition)
-
+    unsigned integer @tab
+    0 (file), 1 (freq), 2 (mail), 3 (transition)
 @item Path length @tab
-  unsigned integer @tab
-  actual length of following field's payload
-
+    unsigned integer @tab
+    actual length of following field's payload
 @item Path @tab
-  255 byte, fixed length opaque data @tab
-  @itemize
-  @item UTF-8 encoded destination path for file transfer
-  @item UTF-8 encoded source path for file request
-  @item UTF-8 encoded, space separated, email recipients list
-  @item Node id the transition packet must be relayed on
-  @end itemize
-
+    255 byte, fixed length opaque data @tab
+    @itemize
+    @item UTF-8 encoded destination path for file transfer
+    @item UTF-8 encoded source path for file request
+    @item UTF-8 encoded, space separated, email recipients list
+    @item Node id the transition packet must be relayed on
+    @end itemize
 @end multitable
 
 Path has fixed size because of hiding its actual length -- it is
-valuable metadata.
+valuable metadata. Payload is appended to the header -- it is not stored
+as XDR field, because most XDR libraries will store all that data in the
+memory.
 
-Actual payload comes after that header to the very end:
+Depending on the packet's type, payload could store:
 
 @itemize
 @item File contents
@@ -86,32 +81,25 @@ Each encrypted packet has the following header:
 
 @multitable @columnfractions 0.2 0.3 0.5
 @headitem  @tab XDR type @tab Value
-
 @item Magic number @tab
-  8-byte, fixed length opaque data @tab
-  @code{NNCPE0x10x00x00}
-
+    8-byte, fixed length opaque data @tab
+    @code{NNCPE0x10x00x00}
 @item Niceness @tab
-  unsigned integer @tab
-  1-255, packet niceness level, its priority.
-  Lower value means higher precedence
-
+    unsigned integer @tab
+    1-255, packet niceness level, its priority.
+    Lower value means higher precedence
 @item Sender @tab
-  32-byte, fixed length opaque data @tab
-  Sender node's id
-
+    32-byte, fixed length opaque data @tab
+    Sender node's id
 @item Exchange public key @tab
-  32-byte, fixed length opaque data @tab
-  Ephemeral curve25519 public key
-
+    32-byte, fixed length opaque data @tab
+    Ephemeral curve25519 public key
 @item Signature @tab
-  64-byte, fixed length opaque data @tab
-  ed25519 signature for that encrypted packet
-
+    64-byte, fixed length opaque data @tab
+    ed25519 signature for that encrypted packet
 @item Size @tab
-  unsigned hyper integer @tab
-  Encrypted payload size
-
+    unsigned hyper integer @tab
+    Encrypted payload size
 @end multitable
 
 Signature is calculated over the following structure:
index ff080901303d1cef07dcd122cb5cb97cc3ae29bc..b111988367312de51809402c087693661fd18eaa 100644 (file)
 @node Sync
 @unnumbered Sync protocol
 
-So-called sync protocol is used in current TCP daemon's implementation.
-It is aimed to be very simple and effective. It is used over reliable
-transport like TCP connections.
+So-called sync protocol (SP) is used in current TCP daemon's
+implementation. It is used for synchronizing @ref{Spool, spool}
+directory contents between two nodes.
 
-It must be effective both on single-duplex and full-duplex links (for
-example satellites have very high throughput, but high-delay links).
-Acknowledging of each received packet, like
+It is aimed to be very simple and effective. It uses reliable transport
+like TCP connections. It must be effective both on single-duplex and
+full-duplex links: for example satellites have very high throughput and
+high-delay links, so acknowledging of each received packet, like
 @url{https://en.wikipedia.org/wiki/XMODEM, XMODEM} does, causes
 unacceptable performance degradation.
 
-TODO
+SP works on top of
+@url{http://noiseprotocol.org/noise.html#interactive-patterns,
+@code{Noise_IK_25519_ChaChaPoly_BLAKE2b}} protocol. Each Noise packet
+are sent inside XDR envelope:
 
-http://noiseprotocol.org/noise.html#interactive-patterns
+@verbatim
++-----------------+
+| MAGIC | PAYLOAD |
++-----------------+
+@end verbatim
+
+@multitable @columnfractions 0.2 0.3 0.5
+@headitem  @tab XDR type @tab Value
+@item Magic number @tab
+    8-byte, fixed length opaque data @tab
+    @code{NNCPS0x10x00x00}
+@item Payload @tab
+    variable length opaque data @tab
+    Noise packet itself
+@end multitable
+
+Peers static keys are specified as @ref{Configuration, @code{noisepub}}
+configuration entry.
+
+Payload inside Noise packets has maximum size of @code{65 KiB - 256 B =
+65280 B}. It is sent immediately in the first message by each side. The
+very first payload (that is carried inside handshake messages) is always
+padded to the maximum size with @code{HALT} packets (read below), for
+hiding actual number of @code{INFO} packets (number of files available
+for transmission).
+
+Each SP payload is a concatenation of various SP packets. Each packet
+has XDR-encoded header and then corresponding XDR-encoded body. Header
+is just an unsigned integer telling what body structure follows.
+
+@table @code
+
+@item HALT
+    Stop file transmission, empty sending queue on the remote side.
+    Actually @code{HALT} packet does not have any body, only the header
+    with the type. It is also used in the first payload for padding to
+    the maximum size.
+
+@item INFO
+    Information about the file we have for transmission.
+@verbatim
++--------------------+
+| NICE | SIZE | HASH |
++--------------------+
+@end verbatim
+    @multitable @columnfractions 0.2 0.3 0.5
+    @headitem  @tab XDR type @tab Value
+    @item Niceness @tab
+        unsigned integer @tab
+        1-255, file niceness level, its priority
+    @item Size @tab
+        unsigned hyper integer @tab
+        File size
+    @item Hash @tab
+        32-byte, fixed length opaque data @tab
+        Unique file identifier, its checksum
+    @end multitable
+
+@item FREQ
+    File transmission request. Ask remote side to queue the file for
+    transmission.
+@verbatim
++---------------+
+| HASH | OFFSET |
++---------------+
+@end verbatim
+    @multitable @columnfractions 0.2 0.3 0.5
+    @headitem  @tab XDR type @tab Value
+    @item Hash @tab
+        32-byte, fixed length opaque data @tab
+        Unique file identifier, its checksum
+    @item Offset @tab
+        unsigned hyper integer @tab
+        Offset from which remote side must transmit the file
+    @end multitable
+
+@item FILE
+    Chunk of file.
+@verbatim
++-------------------------+
+| HASH | OFFSET | PAYLOAD |
++-------------------------+
+@end verbatim
+    @multitable @columnfractions 0.2 0.3 0.5
+    @headitem  @tab XDR type @tab Value
+    @item Hash @tab
+        32-byte, fixed length opaque data @tab
+        Unique file identifier, its checksum
+    @item Offset @tab
+        unsigned hyper integer @tab
+        Offset from which transmission goes
+    @item Payload @tab
+        variable length opaque data @tab
+        Chunk of file itself
+    @end multitable
+
+@item DONE
+    Signal remote side that we have successfully downloaded the file.
+@verbatim
++------+
+| HASH |
++------+
+@end verbatim
+    @multitable @columnfractions 0.2 0.3 0.5
+    @headitem  @tab XDR type @tab Value
+    @item Hash @tab
+        32-byte, fixed length opaque data @tab
+        Unique file identifier, its checksum
+    @end multitable
+
+@end table
diff --git a/doc/spool.texi b/doc/spool.texi
new file mode 100644 (file)
index 0000000..097b180
--- /dev/null
@@ -0,0 +1,34 @@
+@node Spool
+@unnumbered Spool directory
+
+Spool directory holds @ref{Encrypted, encrypted packets} received from
+remote nodes and queued for sending to them. It has the following
+example structure:
+
+@verbatim
+spool/tmp/
+spool/2WHB...OABQ/rx.lock
+spool/2WHB...OABQ/rx/5ZIB...UMKW.part
+spool/2WHB...OABQ/tx.lock
+spool/BYRR...CG6Q/rx.lock
+spool/BYRR...CG6Q/rx/
+spool/BYRR...CG6Q/tx.lock
+spool/BYRR...CG6Q/tx/NSYY...ZUU6
+spool/BYRR...CG6Q/tx/ZI5U...5RRQ
+@end verbatim
+
+Except for @code{tmp}, all other directories are Base32-encoded node
+identifiers (@code{2WHB...OABQ}, @code{BYRR...CG6Q} in our example).
+Each node subdirectory has @code{rx} (received, partly received and
+currently unprocessed packets) and @code{tx} (for outbound packets)
+directories.
+
+Each @code{rx}/@code{tx} directory contains one file per encrypted
+packet. Its filename is Base32 encoded BLAKE2b hash of the contents. So
+it can be integrity checked at any time. @code{5ZIB...UMKW.part} is
+partly received file from @code{2WHB...OABQ} node. @code{tx} directory
+can not contain partly written files -- they are moved atomically from
+@code{tmp}.
+
+Only one process can work with @code{rx}/@code{tx} directories at once,
+so there are corresponding lock files.
index e498eb005c5f1284caa4c87af775be8e8283da98..1af384e62aea47253805213bc3591c7cb31879b4 100644 (file)
@@ -1,9 +1,19 @@
 @node Use cases
 @unnumbered Use cases
 
-@table @strong
-
-@item Occasional connection to mail server
+@menu
+* Occasional connection to mail server: UsecaseMail.
+* Unreliable/expensive communication link: UsecaseUnreliable.
+* Slow/expensive link for high-volume data, bad QoS: UsecaseQoS.
+* Extreme terrestrial environments, no link: UsecaseNoLink.
+* Private, isolated MitM-resistant networks: UsecaseF2F.
+* Highly secure isolated air-gap computers: UsecaseAirgap.
+* Network censorship bypassing: UsecaseCensor.
+* Reconnaissance, spying, intelligence, covert agents: UsecaseSpy.
+@end menu
+
+@node UsecaseMail
+@section Occasional connection to mail server
 
 Assume that you have got your own @url{http://www.postfix.org/, Postfix}
 SMTP server connected to the Internet. But you read and write emails on
@@ -16,22 +26,35 @@ receive notification emails that his messages still are not delivered
 yet. Also you must have secure link (SSH, VPN, etc).
 
 Another possibility is to use POP3/IMAP4 servers, but this is too
-overcomplicated and bloated for the simple task. Not an option.
+overcomplicated and bloated for the simple task. Not an option. KISS!
+
+@anchor{Postfix}
 
 Just tell both of your Postfixes (on the server and notebook) to drop
-email as a mail via NNCP to specified node. Search for @code{uucp}
-related strings in @code{master.cf} and replace command to NNCP ones:
+email as a mail via NNCP to specified node. This is done similarly as
+with UUCP and as written in Postfix
+@url{http://www.postfix.org/UUCP_README.html, documentation}.
+
+Search for @code{uucp} related strings in @code{master.cf} and replace
+command to NNCP ones:
+
+@verbatim
+nncp unix - n n - - pipe flags=Fqhu user=nncp argv=nncp-mail -quiet $nexthop $recipient
+@end verbatim
+
+then add transport map, telling that mail for example.com domain can be
+reached through NNCP transport to node @code{bob}:
 
 @verbatim
-nncp      unix  -       n       n       -       -       pipe
-  flags=Fqhu user=nncp argv=nncp-mail -quiet $nexthop $recipient
+example.com nncp:bob
 @end verbatim
 
 Now, all mail will be stored in NNCP spool, that after exchanging and
 tossing will call local @code{sendmail} command to deliver them just
 that was happened on the same machine.
 
-@item Unreliable/expensive communication link
+@node UsecaseUnreliable
+@section Unreliable/expensive communication link
 
 Assume that you have got slow modem/radio/cellular link that frequently
 disconnects and causes TCP timeouts. Not all HTTP servers support file
@@ -54,16 +77,29 @@ will queue two files for sending to @code{bob} node. Fire and forget!
 Now this is daemon's job (or offline transfer) to send this file part by
 part to remote system when it is available.
 
-@item Slow/expensive link for high-volume data
+@node UsecaseQoS
+@section Slow/expensive link for high-volume data, bad QoS
 
 Assume that you can give your relatively cheap 2 TiB removable hard
 drive to someone each day at the morning (and take it back at the
 evening). This equals to 185 Mbps good quality (without any speed
 degradation) link in single direction. What about more and bigger hard
-drives? This type of data transferring is called
+drives? This type of data exchange is called
 @url{https://en.wikipedia.org/wiki/Sneakernet, sneakernet}/floppynet.
 
-@item Extreme terrestrial environments, no link
+NNCP allows traffic prioritizing: each packet has niceness level,
+that will guarantee that it will be processed earlier or later than the
+other ones. Nearly all commands has corresponding option:
+
+@verbatim
+% nncp-file -nice 32 myfile node:dst
+% nncp-xfer -nice 192 /mnt/shared
+% nncp-call -nice 224 bob
+[...]
+@end verbatim
+
+@node UsecaseNoLink
+@section Extreme terrestrial environments, no link
 
 This is some kind of too slow link. Offline delivery methods is the only
 choice. Just send files as shown above, but use removable media for
@@ -100,7 +136,8 @@ to find all packets related to their node and copy them locally for
 further processing. @code{nncp-xfer} is the only command used with
 removable devices.
 
-@item Private, isolated MitM-resistant networks
+@node UsecaseF2F
+@section Private, isolated MitM-resistant networks
 
 All Internet connections can be eavesdropped and forged. You
 @strong{have to} to use encryption and authentication for securing them.
@@ -141,7 +178,8 @@ configuration file) and send all related outbound packets and retrieve
 those the Bob has. All interrupted transfers will be automatically
 resumed.
 
-@item Highly secure isolated air-gap computers
+@node UsecaseAirgap
+@section Highly secure isolated air-gap computers
 
 If you worry much about security, then air-gapped computer could be the
 only choice you can afford. Computer without any modems, wired and
@@ -181,7 +219,26 @@ Pay attention that relaying node knows nothing about the packet inside,
 but just its size and priority. Transition packets are encrypted too.
 @code{bob} can not read @code{bob-airgap}'s packets.
 
-@item Reconnaissance, spying, intelligence, covert agents
+@node UsecaseCensor
+@section Network censorship bypassing
+
+This is some kind of bad link too. Some governments tend to forbid
+@strong{any} kind of private communication between people, allowing only
+entertainment content delivering and popular social networks access
+(that are already bloated with advertisements, local proprietary
+JavaScript code execution (for spying on user activities, collect data
+on them), shamelessly exploiting of very basic interhuman need of
+communication).
+
+This is their natural right and wish. Nobody forces you to obey huge
+corporations like Apple, Google or Microsoft. It is your choice to
+create isolated friend-to-friend network with piles of harmless content
+and private messaging. Only predators silently watch for their victims
+in mammals world -- it harms your health being watched and feeling that
+you are the victim that has already done something wrong.
+
+@node UsecaseSpy
+@section Reconnaissance, spying, intelligence, covert agents
 
 Those guys know how Internet is a dangerous place incompatible with
 privacy. They require quick, fast dropping and picking of data. No
@@ -196,8 +253,8 @@ be pretty fast, allowing to quickly fire chunks of queued packets.
 Very important property is that compromising of those dead drops and
 storages must not be fatal and even dangerous. Packets sent through the
 network and exchanged via those devices are end-to-end encrypted (but
-unfortunately without forward secrecy property). No filenames, mail
-recipients are seen.
+unfortunately lacking forward secrecy). No filenames, mail recipients
+are seen.
 
 All communications are done with so-called spool area: directory
 containing only those unprocessed encrypted packets. After packet
@@ -206,9 +263,6 @@ another stage: tossing. Only that stage involves your private
 cryptographic keys. So even if your loose your computer, storage devices
 and so on -- it is not so bad, because you are not carrying private keys
 with it, you do not "toss" those packets immediately on the same device.
-
 Tossing (reading those encrypted packets and extracting transferred
 files and mail messages) could and should be done on a separate
 computer.
-
-@end table
diff --git a/doc/workflow.texi b/doc/workflow.texi
new file mode 100644 (file)
index 0000000..dc4a3e4
--- /dev/null
@@ -0,0 +1,31 @@
+@node Workflow
+@unnumbered Workflow
+
+NNCP consists of several utilities. As a rule you will have the
+following workflow with them.
+
+@enumerate
+@item Run @ref{nncp-newnode} on each node to create an initial
+@ref{Configuration, configuration} file.
+@item Tune it up and set at least @ref{Spool, spool} and log paths.
+@item Share your public keys and reachability addressees with your
+neighbours. Add their keys to your configuration file and do any other
+required configuration about their reachability, allowance of file or
+freq transmissions.
+@item Use @ref{nncp-file}, @ref{nncp-freq}, @ref{nncp-mail}
+(@ref{Postfix, look how} Postfix SMTP server could be configured for its
+usage) commands to queue file, freq and mail transmissions. Repeat as
+many times any time as you wish.
+@item Depending on connection methods, either:
+    @itemize
+    @item run @ref{nncp-daemon} to accept remotely initiated connections
+    to your node
+    @item run @ref{nncp-call} to initiate connection to required nodes
+    @item use @ref{nncp-xfer} with removable storage devices for copying
+    packets for/from other nodes
+    @end itemize
+@item After successful packet exchanging (or just simply from time to
+time), run @ref{nncp-toss} for tossing (decrypting and processing) all
+inbound queues to receive mail messages, files, file requests and relay
+transition packets to other nodes.
+@end enumerate
index aeabb961c911e4770309f90a7c91a57585be8ab4..36f3ff713da856c87197ddeeba5b24748999b6d9 100644 (file)
@@ -47,7 +47,7 @@ func main() {
                rxOnly   = flag.Bool("rx", false, "Only receive packets")
                txOnly   = flag.Bool("tx", false, "Only transfer packets")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index d1d2d045e55a43f6eda24b483396182bf0dceb72..cd8268ee7cb33b98700af5c4638c671b11e4bde2 100644 (file)
@@ -32,7 +32,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-check -- verify Rx/Tx packets checksum\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -41,7 +41,7 @@ func main() {
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                nodeRaw  = flag.String("node", "", "Process only that node")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index 176c935a11aa90268264c4f475717f01e020111e..c14f4bac7ec2c124a7f9d46ce0e83f959725940b 100644 (file)
@@ -35,7 +35,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-daemon -- TCP daemon\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -46,7 +46,7 @@ func main() {
                bind     = flag.String("bind", "[::]:5400", "Address to bind to")
                maxConn  = flag.Int("maxconn", 128, "Maximal number of simultaneous connections")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index 6f37a96a904146e0a0dc63513b8000653e715dbb..46728ea26c1d4a60bb0d5ac968971b9206e182a7 100644 (file)
@@ -33,7 +33,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-file -- send file\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:DST\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options] SRC NODE:[DST]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -42,7 +42,7 @@ func main() {
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                niceRaw  = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index 7360f50743ebd76d1fe8cf489cb6abc25da9a2c5..260c599bb2e95e4e6a28cc92538e8beac1041bdc 100644 (file)
@@ -33,7 +33,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-freq -- send file request\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC DST\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE:SRC DST\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -42,7 +42,7 @@ func main() {
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                niceRaw  = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index d49b7f7e062d1e5ef5de10d8cddef0e63f9b3b21..9a4f5307e33eee9c999549eb173b0919564324ad 100644 (file)
@@ -33,14 +33,14 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-log -- read logs\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
 func main() {
        var (
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index 8b01b8cbc6b4313da655cff17912db4730bba5b4..f23877ba91b24e53a5e6e65be7ed7a3eaae43f99 100644 (file)
@@ -34,7 +34,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-mail -- send email\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options] NODE USER ...\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
        fmt.Fprintln(os.Stderr, "Email body is read from stdin.")
 }
@@ -44,7 +44,7 @@ func main() {
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                niceRaw  = flag.Int("nice", nncp.DefaultNiceMail, "Outbound packet niceness")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index d6a597f99c432da2b5a2d66931bd7a2b324dc405..674381e222c43a67da6bab638b00e6c7f8741c91 100644 (file)
@@ -38,7 +38,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-pkt -- parse raw packet\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
        fmt.Fprintln(os.Stderr, "Packet is read from stdin.")
 }
index 9791b98468676aad4b68c1f0336695292793a3f0..36cc1cb29262d0a43c8134d0e846755648e73571 100644 (file)
@@ -33,7 +33,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-stat -- show queued Rx/Tx stats\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -41,7 +41,7 @@ func main() {
        var (
                cfgPath  = flag.String("cfg", nncp.DefaultCfgPath, "Path to configuration file")
                nodeRaw  = flag.String("node", "", "Process only that node")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index e12e9015d975cb0a168af7374a6cea0985f391c9..9b50866e8198cc78330a459835fc6fc3751f781b 100644 (file)
@@ -32,7 +32,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-toss -- process inbound packets\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options]\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -43,7 +43,7 @@ func main() {
                niceRaw  = flag.Int("nice", 255, "Minimal required niceness")
                dryRun   = flag.Bool("dryrun", false, "Do not actually write any tossed data")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )
index f12fa5f02f09f612417625bb6dcb9e9329b9bd01..669eadc7a1e52cedc543448f9114b4b9a7bda1aa 100644 (file)
@@ -37,7 +37,7 @@ import (
 func usage() {
        fmt.Fprintf(os.Stderr, nncp.UsageHeader())
        fmt.Fprintln(os.Stderr, "nncp-xfer -- copy inbound and outbounds packets\n")
-       fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:", os.Args[0])
+       fmt.Fprintf(os.Stderr, "Usage: %s [options] DIR\nOptions:\n", os.Args[0])
        flag.PrintDefaults()
 }
 
@@ -51,7 +51,7 @@ func main() {
                force    = flag.Bool("force", false, "Force outbound directories creation")
                keep     = flag.Bool("keep", false, "Do not delete transferred packets")
                quiet    = flag.Bool("quiet", false, "Print only errors")
-               debug    = flag.Bool("debug", false, "Enable debugging information")
+               debug    = flag.Bool("debug", false, "Print debug messages")
                version  = flag.Bool("version", false, "Print version information")
                warranty = flag.Bool("warranty", false, "Print warranty information")
        )