@node Multicast @cindex multicast area @unnumbered Multicast areas NNCP has ability to multicast packets: send single packet to multiple recipients, which also can send it further to others. It can also be called echomail (like in FidoNet networks) or newsgroup (like in Usenet networks). @anchor{Area} Each multicast group is identified by so-called @strong{area}. Area consists of private/public Curve25519 keypairs for @ref{Encrypted area, packets encryption}, identity (BLAKE2b-256 hash of the public key) and possible subscribers. Areas are created with @command{@ref{nncp-cfgnew}} command. You can make either file or exec transmissions to the areas. Those ordinary file/exec packets are double wrapped in: @itemize @item encrypted packet, securing the actual packet contents from participants not having area's keypairs (but still being able to relay that encrypted packet to the others) @item area packet, containing area's identity, telling that tossing node can should it to the subscribers further @end itemize @vindex MsgHash Area's message identity (@code{MsgHash}) is the hash of the encrypted packet header. Because the area packet, containing the encrypted packet, is relayed as-is without any modifications, that area message's hash will be the same on each node it reaches. @ref{nncp-toss, Tosser}'s algorithm of processing the area packet is following: @itemize @item check is it known area's identity (@code{AREA}). Fail/skip if it is unknown @item hash encrypted packet's header, getting the @code{MsgHash} @item for each area's subscribers: @itemize @item check if that message was already seen (sent or received from) before by the destination node: check existence of @file{SPOOL/NODE/area/AREA/MsgHash} file. Skip that node if it exists @item if subscriber's node is not the one we received the packet from, then create outgoing encrypted packet to it, with that area packet inside @item create corresponding @file{MsgHash} file @item "rewind" the outer encrypted file to the beginning and repeat the whole cycle again, while all of subscribers will "seen" that area's message. Expensive signature verification and shared key computation procedures are skipped in the following cycles -- only symmetric cryptography will be in use, having negligible CPU resource consumption. @end itemize @item check if we have seen that area's message before by looking at @file{SPOOL/SELF/area/AREA/MsgHash}. If so, remove the packet, because it is just a ordinary possible duplicate, finish its processing @item check if we have got corresponding area's private key. If no key exists, then remove the packet, finish its processing -- we just relay it further without being able to read it @item look if area's encrypted packet's sender is known to us. If neither it is known, nor we have @code{allow-unknown} configuration option set for that area, then fail @item otherwise start decryption procedure, possibly ignoring the sender's signature verification if it is unknown @item fed the decrypted contents to the toss-procedure as an ordinary plain packet, receiving files or exec calls @item mark area's message as the seen one, remove the packet, finish processing @end itemize Because outgoing packets creation for each subscriber can be time and (disk) resource consuming, we can suddenly fail. It would be bad if we will loose the possibility to retry the multicasting process again. So we have got to save somehow outgoing area's message in permanent storage, while outgoing copies are created. That is why the initial (not relaying) message to the area is sent to the @strong{self} and processed by the @ref{nncp-toss, tosser} to create necessary outgoing message copies. Because message to myself is also encrypted, area's message is encrypted and secured and noone sees plaintext @code{MsgHash}, knowing that you either originated or have that message on the disk. For example we have got 4 nodes participating in the single area and let's send file to that area from the @code{nodeA}: @example nodeA -> subs: ["nodeB", "nodeD"] nodeB -> subs: ["nodeC", "nodeD", "nodeA"], no keys nodeC -> subs: ["nodeB"] nodeD -> subs: ["nodeA", "nodeB"] @end example @example A -- B -- C \ / \ / D @end example @example $ nncp-file nodelist-20210704.rec.zst area:nodelist-updates: $ nncp-toss -node self @end example @enumerate @item @command{@ref{nncp-file}} creates an encrypted packet with area packet and encrypted packet inside it, with our own @code{self} node as a recipient (in the @file{SPOOL/SELF/tx} directory). It also creates the @file{SPOOL/SELF/area/AREA/MsgHash} file. @item @command{@ref{nncp-toss}} sees @file{tx/} file and "opens" it, applying the area message tossing procedure as described above. That will create outgoing packets in @file{SPOOL/nodeB/tx} and @file{SPOOL/nodeD/tx} directories with @file{SPOOL/nodeB/area/AREA/MsgHash} @file{SPOOL/nodeD/area/AREA/MsgHash} files. Because we already have @file{SPOOL/SELF/area/AREA/MsgHash}, that packet is removed then. @item When @code{nodeB} receives the encrypted packet, it sees the area one inside. It copies/relays it to the @code{nodeC} and @code{nodeD}. It can not read area's message because it lacks the keys. @item @code{nodeC} does not relay it to anyone. Just stores @file{nodelist-20210704.rec.zst} in the incoming directory. @item @code{nodeD} receives packets from both @code{nodeA} and @code{nodeB}. Only one of them processed, and other is ignored because corresponding @file{MsgHash} file will exist. If @code{nodeD} will receive packet from the @code{nodeB} first, it will relay it to the @code{nodeA} also, that will silently remove it when tossing, because it was already seen. @item When @code{nodeC} sends message to the area, then @code{nodeA} will receive it twice from @code{nodeB} and @code{nodeD}, ignoring one of them during tossing. @end enumerate