Git Product home page Git Product logo

chattervox's Introduction

Chattervox

Travis CI Build Image Coverage Status

An AX.25 packet radio chat protocol with support for digital signatures and binary compression. Like IRC over radio waves ๐Ÿ“ก.

Chattervox implements a minimal packet radio protocol on top of AX.25 that can be used with a terminal node controller (TNC) like Direwolf to transmit and receive digitally signed messages using audio frequency shift keying modulation (AFSK). In the United States, it's illegal to broadcast encrypted messages on amateur radio frequencies. Chattervox respects this law, while using elliptic curve cryptography and digital signatures to protect against message spoofing.

With amateur packet radio anyone can pretend to be anyone else. With Chattervox, you can be sure you're chatting with the person you intend to. For more information, check out the FAQ or the discussion about chattervox on hackernews.

UPDATE (March 6, 2019): Check out my slides from the Chattervox workshop at WOPR Summit.

UPDATE (February 25, 2019): I've created a collection of example applications and use cases for the Chattervox protocol here. One example uses Chattervox to access a remote BASH shell on another machine and another shows how you can play Zork I over packet radio. PRs welcome!

UPDATE (October 11, 2018): We've setup a public key registry at chattervox-keys. Once you've generated your public key you can post it there!

Baofeng UV-5R Linux setup

Prerequisites

Chattervox requires a linux computer and a network or serial connection to a TNC to send and receive AX.25 packets. I recommend using Direwolf, a popular software TNC which can be run on the same computer hosting the chattervox application.

You'll also need a radio and a cable to connect the microphone and speaker from the radio to your linux machine. I recommend the following equipment, especially if you're on a budget:

  • $24 Baofeng UV-5R 4-watt radio. This is the absolute best radio you can buy for that price.
  • $18 BTech APRS cable (3.5mm TRRS to 3.5mm and 2.5mm audio cable, usually for sale on Amazon)

You can also make the cable yourself if you prefer. Check out this zine for instructions.

Finally, to operate legally on amateur radio frequencies, you'll need an amateur radio license.

Install Direwolf

Linux

Installing Direwolf on a Linux machine is easy! Just clone the repo, build the software, and install it on your system.

# clone, build, and install the Direwolf TNC
git clone https://github.com/wb2osz/direwolf
cd direwolf
make
sudo make install
make install-conf

MacOS

If you are using MacOS, you can install Direwolf with Homebrew by following the instructions in this Gist (thanks for the edits @danc256).

Windows

Windows isn't currently supported, but will be soon!

Download

Binary downloads are available for Linux x64 and x86 architectures on the releases page.

If you have npm, that is the preferred method of install as it allows for the easiest upgrade to the latest version. If you prefer to "build" it from Typescript source and run it as a Node.js app, you can do that as well.

NPM

npm install --cli -g chattervox@latest 

Installing a node package globally may require sudo. If you get a permission denied error, try running the install command again with sudo npm ....

Source

# clone the repo
git clone https://github.com/brannondorsey/chattervox
cd chattervox

# download dependencies
npm install

# transpile the src/*.ts typescript files to build/*.js
npm run build

# run chattervox from source to opening the chat room
node build/main.js chat

Binary Downloads

Binary downloads are packaged via Pkg. Chattervox uses a native Node.js addon for serial port communication but Pkg does not yet support bundling .node bindings in their binaries. Therefore, the serialport.node file that comes with the download must live in the same folder as the chattervox binary. If you want to install chattervox globally on your machine you can maintain this relationship by placing chattervox in your PATH using a symlink, or copying both chattervox and serialport.node to /usr/local/bin or wherever your OS looks for programs.

Usage

# open the chat room
chattervox chat

# send a packet from the command-line
chattervox send "this is a chattervox packet sent from the command-line."

# receive *all* packets and print them to stdout
chattervox receive --allow-all

# generate a new public/private key pair, and use it as your default signing key
chattervox genkey --make-signing

# add a friend's public key to your keyring, so that chattervox can verify their messages
chattervox addkey KC3LZO 0489a1d94d700d6e45508d12a4eb9be93386b5b30feb2b4aa07836398781e3d444e04b54a6e01cf752e54ef423770c00a6

# remove a friend's public key if it has become compromised 
chattervox removekey KC3LZO 0489a1d94d700d6e45508d12a4eb9be93386b5b30feb2b4aa07836398781e3d444e04b54a6e01cf752e54ef423770c00a6

# print all keys in your keyring
chattervox showkey
usage: chattervox [-h] [-v] [--config CONFIG]
                  {chat,send,receive,showkey,addkey,removekey,genkey} ...

An AX.25 packet radio chat protocol with support for digital signatures and 
binary compression. Like IRC over radio waves ๐Ÿ“กใ€ฐ.

Optional arguments:
  -h, --help            Show this help message and exit.
  -v, --version         Show program's version number and exit.
  --config CONFIG, -c CONFIG
                        Path to config file (default: /home/braxxox/.
                        chattervox/config.json)

subcommands:
  {chat,send,receive,showkey,addkey,removekey,genkey}

The Protocol

The chattervox packet is primitive and straightforward. It contains a simple header, an optional ECDSA digital signature, and a message payload that can be in plaintext or compressed. As of packet version 1, the protocol is connectionless. There is only one type of packet and there is no mechanism for delivery confirmation (think of it like UDP). It is expected to be transported via AX.25 Unnumbered Information (UI) packets, which the chattervox program relies on for sender and recipient information, as no such fields exists in the packet itself to conserve space.

The protocol may be amended in the future to add new features, however, its simplicity should not be seen as a weakness. The goal of chattervox is singular: Add cryptographic verifiability to text-based radio communication.

For proposed changes to the protocol view the open RFCs.

Chattervox Protocol v1 Packet

Byte Offset # of Bits Name Value Description
0x0000 16 Magic Header 0x7a39 A constant two-byte value used to identify chattervox packets.
0x0002 8 Version Byte Number A protocol version number between 1-255.
0x0003 6 Unused Flag Bits Null Reserved for future use.
0x0003 1 Digital Signature Flag Bit A value of 1 indicates that the message contains a ECDSA digital signature.
0x0003 1 Compression Flag Bit A value of 1 indicates that the message payload is compressed.
[0x0004] [8] [Signature Length] Number The length in bytes of the digital signature. This field is only included if the Digital Signature Flag is set.
[0x0004 or 0x0005] [0-2048] [Digital Signature] Bytes The ECDSA digital signature created using a SHA256 hash of the message contents and the sender's private key.
0x0004-0x104 0-โˆž Message Bytes The packet's UTF-8 message payload. If the Compression Flag is set the contents of this buffer is a raw DEFLATE buffer containing the UTF-8 message.

[] indicates an optional field.

TypeScript chattervox client

This repository serves as the first implementation of the protocol. The chattervox command-line tool acts as a client to send and receive chattervox packets in combination with a TNC. This implementation creates a new ECDSA keypair the first time it's run and includes a digital signature for each message (so long as there remains a signingKey in ~/.chattervox/config.json). Each message is temporarily compressed by the client before it's sent in an attempt to measure the efficiency of the DEFLATE compression algorithm. If the compressed version is smaller than the uncompressed version, the compressed buffer is used as the message payload and the compression bit is set in the chattervox packet. If the plaintext version is smaller, no compression is used and the original message text is used as the payload.

Beta Software

Please understand that this software is in beta and I ask for your patience until development stabilizes. While I'm very excited to see that interest in the project is high, It's quite unexpected and I have spent very little time testing the software (aside from automated tests). If you have a problem, please submit a detailed issue and I'll have a look. I'll be writing a tutorial explaining how to get up and running with chattervox very soon.

The protocol is subject to change, and there are several RFCs that indicate the direction it may take in the near future. Currently, there is no protection from replay attacks, so that's something we hope to fix soon!

chattervox's People

Contributors

brannondorsey avatar brycied00d avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chattervox's Issues

Key discovery

Can the protocol be used to discover keys of other participants? Can a revoke be announced? Can keys automatically rotate?

I suspect not today, and thatโ€™s fine. Neat project!

Add demo gif to README

Disclaimer: This is a bot

It looks like your repo is trending. The github_trending_videos Instgram account automatically shows the demo gifs of trending repos in Github.

Your README doesn't seem to have any demo gifs. Add one and the next time the parser runs it will pick it up and post it on its Instagram feed. If you don't want to just close this issue we won't bother you again.

Add send and receive subcommands

Add functionality to send and receive messages without the chattervox chat subcommand. This will be especially useful for scripting purposes or adding chattervox as a component in a larger software pipeline.

# send
chattervox send "This is a message sent from the command line"
echo "This is a message sent from the command line" | chattervox send

# receive
chattervox receive
chattervox receive | some-command

Encryption support for "Non US Users"

From the readme: "In the United States, it's illegal to broadcast encrypted messages on amateur radio frequencies.".

Would it be possible to perhaps add a config option to enable encryption support, for users in countries with less restrictive laws on amateur radio use?

Or perhaps could you provide some pointers as to how this could be implemented? I guess it could be put in the same bit as the message signing / verification, but still getting familiar with the codebase...

Multi-line messages cause UI glitches

screenshot from 2018-09-24 20-31-14

When a message is sent terminal-kit is used to clear the message buffer from the user's screen. It does this by removing one line, however if the message is longer than one line, only the bottom line is cleared.

Public key not found but is installed in keystore.json

Get (KEY NOT FOUND) on one station but works on another. It appears
the KF7FIT station can not find the public key for N7NIX even though
it is in the keystore.json file.

When using chat (~/dev/github/chattervox $ node build/main.js chat)
sending a message from N7NIX to KF7FIT, the KF7FIT station reports
(KEY NOT FOUND) when displaying the message. When sending a message
from KF7FIT, N7NIX has no problem, no error is reported.

When using receive on KF7FIT (~/dev/github/chattervox $ node
build/main.js receive) a message sent from n7nix is NOT displayed.
Changing command to 'receive --allow-all' allows message sent from
N7NIX to KF7FIT to be displayed.

Using 2 Raspberry Pi's (arch=armv7l) with chattervox installed from source on github
Installation script used on both stations:
https://github.com/nwdigitalradio/n7nix/blob/master/keyb2keyb/cv_install.sh

Public keys from both stations
On N7NIX:
cat ~/.chattervox/keystore.json | jq -r '.N7NIX[0].public'
04c4ba4bd163be7a0468731593ad887897adcd6e5d7da2f7f7965fb2ba2add119758522731403f1a96119ceffd2c8b6b41
cat ~/.chattervox/keystore.json | jq -r '.KF7FIT[0].public'
049962aedae34deba50a980ff6a943002c93008f665ab7691e9533219f07023e527311fed9262367ad467d6258e36f29fc

udr0: EAX25: fm KF7FIT-4 to CQ ctl UI pid=F0(Text) [DAMA] len 79 09:33:41.809792 
0000  7A 39 01 02 38 30 36 02 19 00 B3 EE B5 19 16 43  | z9..806...๏ฟฝ๏ฟฝ๏ฟฝ..C
0010  8B 34 CA F1 F3 60 7A 5D F8 D1 3F 46 C3 E7 B5 8A  | .4๏ฟฝ๏ฟฝ๏ฟฝ`z]๏ฟฝ๏ฟฝ?F๏ฟฝ๏ฟฝ๏ฟฝ.
0020  BC F7 02 19 00 BC F6 38 27 BE B8 5E A8 BF 03 B9  | ๏ฟฝ๏ฟฝ...๏ฟฝ๏ฟฝ8'๏ฟฝ๏ฟฝ^๏ฟฝ๏ฟฝ.๏ฟฝ
0030  59 76 AE DD 64 EA 2A 41 1B D3 41 08 7C 74 65 73  | Yv๏ฟฝ๏ฟฝd๏ฟฝ*A.๏ฟฝA.|tes
0040  74 20 66 72 6F 6D 20 6B 66 37 66 69 74 2D 34     | t from kf7fit-4

On KF7FIT:
cat ~/.chattervox/keystore.json | jq -r '.N7NIX[0].public'
04c4ba4bd163be7a0468731593ad887897adcd6e5d7da2f7f7965fb2ba2add119758522731403f1a96119ceffd2c8b6b41
cat ~/.chattervox/keystore.json | jq -r '.KF7FIT[0].public'
049962aedae34deba50a980ff6a943002c93008f665ab7691e9533219f07023e527311fed9262367ad467d6258e36f29fc

udr0: EAX25: fm N7NIX-4 to CQ ctl UI pid=F0(Text) [DAMA] len 84 09:44:32.667128 
0000  7A 39 01 02 38 30 36 02 19 00 B3 F4 26 E5 D2 A0  | z9..806...๏ฟฝ๏ฟฝ&๏ฟฝา 
0010  EB 62 C6 F0 F4 84 AE C5 FC 58 41 83 AF DD 51 BC  | ๏ฟฝb๏ฟฝ๏ฟฝ๏ฟฝ.๏ฟฝ๏ฟฝ๏ฟฝXA.๏ฟฝ๏ฟฝQ๏ฟฝ
0020  21 5A 02 19 00 87 78 C6 6E 5C 1C C3 3E CF 89 47  | !Z....x๏ฟฝn\.๏ฟฝ>๏ฟฝ.G
0030  BD 18 E8 31 E4 C0 D6 76 E5 9D 68 F7 35 54 65 73  | ๏ฟฝ.๏ฟฝ1๏ฟฝ๏ฟฝ๏ฟฝv๏ฟฝ.h๏ฟฝ5Tes
0040  74 20 6D 65 73 73 61 67 65 20 66 72 6F 6D 20 6E  | t message from n
0050  37 6E 69 78                                      | 7nix

Both stations are running same versions of software
node --version
v10.21.0
npm --version
6.14.10
uname -a
Linux test218010620 5.4.79-v7l+ #1373 SMP Mon Nov 23 13:27:40 GMT 2020 armv7l GNU/Linux

Need iOS & Mac apps please

I understand this software is in beta but I wanted to put in a request for an eventual iOS & Mac app when possible.

73!

Jim - KH2SR

Unhandled promise rejection. Error: Unknown point format

I need to look into this more, but I believe this occurs in an invalid digital signature.

(node:19671) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:19671) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:19671) UnhandledPromiseRejectionWarning: Error: Unknown point format
    at ShortCurve.decodePoint (/home/braxxox/Documents/code/chattervox/node_modules/elliptic/lib/elliptic/curve/base.js:285:9)
    at KeyPair._importPublic (/home/braxxox/Documents/code/chattervox/node_modules/elliptic/lib/elliptic/ec/key.js:99:28)
    at new KeyPair (/home/braxxox/Documents/code/chattervox/node_modules/elliptic/lib/elliptic/ec/key.js:17:10)
    at Function.fromPublic (/home/braxxox/Documents/code/chattervox/node_modules/elliptic/lib/elliptic/ec/key.js:25:10)
    at EC.keyFromPublic (/home/braxxox/Documents/code/chattervox/node_modules/elliptic/lib/elliptic/ec/index.js:50:18)
    at Keystore.verify (/home/braxxox/Documents/code/chattervox/build/Keystore.js:121:28)
    at Messenger.<anonymous> (/home/braxxox/Documents/code/chattervox/build/Messenger.js:111:46)
    at Generator.next (<anonymous>)
    at fulfilled (/home/braxxox/Documents/code/chattervox/build/Messenger.js:4:58)
    at <anonymous>
(node:19671) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

Issues building in 2024 (npm 20)

Hello from the future.

This is a cool project, thank you.

The binary is working fine but I wanted to try to build it myself and ran into issues.

Can you provide any pointers or suggestions? I'm happy to help here any way I can, although I'm more familiar with python.

I did try to update some of the deps in package.json but was only able to create a different set of errors. :)

LMK how I can help.

Here is a recreate Containerfile

FROM fedora:39


RUN dnf install -y \
    python3 \
    python3-pip \
    python3-devel \
    gcc-c++ \
    git \
    npm \
    && dnf clean all

RUN git clone https://github.com/brannondorsey/chattervox && \
    cd chattervox && \
    npm install && \
    npm run build

CMD /bin/bash
STEP 3/4: RUN git clone https://github.com/brannondorsey/chattervox &&     cd chattervox &&     npm install &&     npm run build
Cloning into 'chattervox'...
npm WARN old lockfile 
npm WARN old lockfile The package-lock.json file was created with an old version of npm,
npm WARN old lockfile so supplemental metadata must be fetched from the registry.
npm WARN old lockfile 
npm WARN old lockfile This is a one-time fix-up, please be patient...
npm WARN old lockfile 
npm WARN deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated [email protected]: This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.
npm WARN deprecated [email protected]: Please upgrade to v1.0.1
npm WARN deprecated [email protected]: Critical bug fixed in v2.0.1, please upgrade to the latest version.
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: Please update to ini >=1.3.6 to avoid a prototype pollution issue
npm WARN deprecated [email protected]: Please upgrade to v1.0.1
npm WARN deprecated [email protected]: Critical bug fixed in v3.0.1, please upgrade to the latest version.
npm WARN deprecated [email protected]: Please upgrade to v0.1.5
npm WARN deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated [email protected]: Please upgrade to v0.1.7
npm WARN deprecated [email protected]: Critical bug fixed in v3.0.1, please upgrade to the latest version.
npm WARN deprecated [email protected]: this library is no longer supported
npm WARN deprecated [email protected]: Critical bug fixed in v3.0.1, please upgrade to the latest version.
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: Please upgrade to v0.1.5
npm WARN deprecated [email protected]: Please upgrade to v0.1.5
npm WARN deprecated [email protected]: Please upgrade to v0.1.5
npm WARN deprecated [email protected]: Please upgrade to v0.1.7
npm WARN deprecated [email protected]: Please upgrade to v0.1.7
npm WARN deprecated [email protected]: Please upgrade to v0.1.7
npm WARN deprecated [email protected]: Please upgrade to v0.1.7
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: See https://github.com/lydell/source-map-url#deprecated
npm WARN deprecated [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
npm WARN deprecated [email protected]: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated [email protected]: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated [email protected]: See https://github.com/lydell/source-map-resolve#deprecated
npm WARN deprecated [email protected]: This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.
npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated [email protected]: This module is no longer maintained, try this instead:
npm WARN deprecated   npm i nyc
npm WARN deprecated Visit https://istanbul.js.org/integrations for other alternatives.
npm WARN deprecated [email protected]: Please upgrade to v0.1.5
npm WARN deprecated [email protected]: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
npm notice 
npm notice New minor version of npm available! 10.2.3 -> 10.3.0
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v10.3.0>
npm notice Run `npm install -g [email protected]` to update!
npm notice 
npm ERR! code 1
npm ERR! path /chattervox/node_modules/serialport
npm ERR! command failed
npm ERR! command sh -c prebuild-install || node-gyp rebuild
npm ERR! make: Entering directory '/chattervox/node_modules/serialport/build'
npm ERR!   CXX(target) Release/obj.target/serialport/src/serialport.o
npm ERR! make: Leaving directory '/chattervox/node_modules/serialport/build'
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp info using [email protected]
npm ERR! gyp info using [email protected] | linux | x64
npm ERR! gyp info find Python using Python version 3.12.0 found at "/usr/bin/python3"
npm ERR! gyp http GET https://nodejs.org/download/release/v20.10.0/node-v20.10.0-headers.tar.gz
npm ERR! gyp http 200 https://nodejs.org/download/release/v20.10.0/node-v20.10.0-headers.tar.gz
npm ERR! gyp http GET https://nodejs.org/download/release/v20.10.0/SHASUMS256.txt
npm ERR! gyp http 200 https://nodejs.org/download/release/v20.10.0/SHASUMS256.txt
npm ERR! gyp info spawn /usr/bin/python3
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args '/usr/lib/node_modules_20/npm/node_modules/node-gyp/gyp/gyp_main.py',
npm ERR! gyp info spawn args 'binding.gyp',
npm ERR! gyp info spawn args '-f',
npm ERR! gyp info spawn args 'make',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/chattervox/node_modules/serialport/build/config.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/usr/lib/node_modules_20/npm/node_modules/node-gyp/addon.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/root/.cache/node-gyp/20.10.0/include/node/common.gypi',
npm ERR! gyp info spawn args '-Dlibrary=shared_library',
npm ERR! gyp info spawn args '-Dvisibility=default',
npm ERR! gyp info spawn args '-Dnode_root_dir=/root/.cache/node-gyp/20.10.0',
npm ERR! gyp info spawn args '-Dnode_gyp_dir=/usr/lib/node_modules_20/npm/node_modules/node-gyp',
npm ERR! gyp info spawn args '-Dnode_lib_file=/root/.cache/node-gyp/20.10.0/<(target_arch)/node.lib',
npm ERR! gyp info spawn args '-Dmodule_root_dir=/chattervox/node_modules/serialport',
npm ERR! gyp info spawn args '-Dnode_engine=v8',
npm ERR! gyp info spawn args '--depth=.',
npm ERR! gyp info spawn args '--no-parallel',
npm ERR! gyp info spawn args '--generator-output',
npm ERR! gyp info spawn args 'build',
npm ERR! gyp info spawn args '-Goutput_dir=.'
npm ERR! gyp info spawn args ]
npm ERR! gyp info spawn make
npm ERR! gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
npm ERR! In file included from ../../nan/nan.h:173,
npm ERR!                  from ../src/./serialport.h:6,
npm ERR!                  from ../src/serialport.cpp:1:
npm ERR! ../../nan/nan_callbacks.h:55:23: error: 'AccessorSignature' is not a member of 'v8'
npm ERR!    55 | typedef v8::Local<v8::AccessorSignature> Sig;
npm ERR!       |                       ^~~~~~~~~~~~~~~~~
npm ERR! ../../nan/nan_callbacks.h:55:40: error: template argument 1 is invalid
npm ERR!    55 | typedef v8::Local<v8::AccessorSignature> Sig;
npm ERR!       |                                        ^
npm ERR! ../../nan/nan.h: In function 'bool Nan::IdleNotification(int)':
npm ERR! ../../nan/nan.h:615:63: warning: 'bool v8::Isolate::IdleNotificationDeadline(double)' is deprecated: Use MemoryPressureNotification() to influence the GC schedule. [-Wdeprecated-declarations]
npm ERR!   615 |     return v8::Isolate::GetCurrent()->IdleNotificationDeadline(
npm ERR!       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
npm ERR!   616 |         idle_time_in_ms * 0.001);
npm ERR!       |         ~~~~~~~~~~~~~~~~~~~~~~~~                               
npm ERR! In file included from /root/.cache/node-gyp/20.10.0/include/node/v8-initialization.h:13,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/v8.h:34,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/node.h:73,
npm ERR!                  from ../../nan/nan.h:53:
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-isolate.h:1293:8: note: declared here
npm ERR!  1293 |   bool IdleNotificationDeadline(double deadline_in_seconds);
npm ERR!       |        ^~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../../nan/nan.h: In function 'void Nan::AsyncQueueWorker(AsyncWorker*)':
npm ERR! ../../nan/nan.h:2232:7: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!  2232 |     , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
npm ERR!       |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../../nan/nan.h: In function 'void Nan::SetAccessor(v8::Local<v8::ObjectTemplate>, v8::Local<v8::String>, GetterCallback, SetterCallback, v8::Local<v8::Value>, v8::AccessControl, v8::PropertyAttribute, imp::Sig)':
npm ERR! ../../nan/nan.h:2470:19: error: no matching function for call to 'v8::ObjectTemplate::SetAccessor(v8::Local<v8::String>&, void (*&)(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&), void (*&)(v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&), v8::Local<v8::Object>&, v8::AccessControl&, v8::PropertyAttribute&, Nan::imp::Sig&)'
npm ERR!  2470 |   tpl->SetAccessor(
npm ERR!       |   ~~~~~~~~~~~~~~~~^
npm ERR!  2471 |       name
npm ERR!       |       ~~~~         
npm ERR!  2472 |     , getter_
npm ERR!       |     ~~~~~~~~~      
npm ERR!  2473 |     , setter_
npm ERR!       |     ~~~~~~~~~      
npm ERR!  2474 |     , obj
npm ERR!       |     ~~~~~          
npm ERR!  2475 |     , settings
npm ERR!       |     ~~~~~~~~~~     
npm ERR!  2476 |     , attribute
npm ERR!       |     ~~~~~~~~~~~    
npm ERR!  2477 |     , signature);
npm ERR!       |     ~~~~~~~~~~~~   
npm ERR! In file included from /root/.cache/node-gyp/20.10.0/include/node/v8-function.h:15,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/v8.h:33:
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-template.h:809:8: note: candidate: 'void v8::ObjectTemplate::SetAccessor(v8::Local<v8::String>, v8::AccessorGetterCallback, v8::AccessorSetterCallback, v8::Local<v8::Value>, v8::AccessControl, v8::PropertyAttribute, v8::SideEffectType, v8::SideEffectType)'
npm ERR!   809 |   void SetAccessor(
npm ERR!       |        ^~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-template.h:814:22: note:   no known conversion for argument 7 from 'Nan::imp::Sig' {aka 'int'} to 'v8::SideEffectType'
npm ERR!   814 |       SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
npm ERR!       |       ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-template.h:816:8: note: candidate: 'void v8::ObjectTemplate::SetAccessor(v8::Local<v8::Name>, v8::AccessorNameGetterCallback, v8::AccessorNameSetterCallback, v8::Local<v8::Value>, v8::AccessControl, v8::PropertyAttribute, v8::SideEffectType, v8::SideEffectType)'
npm ERR!   816 |   void SetAccessor(
npm ERR!       |        ^~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-template.h:821:22: note:   no known conversion for argument 7 from 'Nan::imp::Sig' {aka 'int'} to 'v8::SideEffectType'
npm ERR!   821 |       SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
npm ERR!       |       ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! In file included from /usr/include/c++/13/cassert:44,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/node_object_wrap.h:26,
npm ERR!                  from ../../nan/nan.h:55:
npm ERR! ../../nan/nan_object_wrap.h: In destructor 'virtual Nan::ObjectWrap::~ObjectWrap()':
npm ERR! ../../nan/nan_object_wrap.h:24:25: error: 'class Nan::Persistent<v8::Object>' has no member named 'IsNearDeath'
npm ERR!    24 |     assert(persistent().IsNearDeath());
npm ERR!       |                         ^~~~~~~~~~~
npm ERR! ../../nan/nan_object_wrap.h: In static member function 'static void Nan::ObjectWrap::WeakCallback(const v8::WeakCallbackInfo<Nan::ObjectWrap>&)':
npm ERR! ../../nan/nan_object_wrap.h:127:26: error: 'class Nan::Persistent<v8::Object>' has no member named 'IsNearDeath'
npm ERR!   127 |     assert(wrap->handle_.IsNearDeath());
npm ERR!       |                          ^~~~~~~~~~~
npm ERR! In file included from ../../nan/nan.h:2818:
npm ERR! ../../nan/nan_typedarray_contents.h: In constructor 'Nan::TypedArrayContents<T>::TypedArrayContents(v8::Local<v8::Value>)':
npm ERR! ../../nan/nan_typedarray_contents.h:34:43: error: 'class v8::ArrayBuffer' has no member named 'GetContents'
npm ERR!    34 |       data   = static_cast<char*>(buffer->GetContents().Data()) + byte_offset;
npm ERR!       |                                           ^~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Open(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:41:47: error: no matching function for call to 'v8::Value::ToString()'
npm ERR!    41 |   v8::String::Utf8Value path(info[0]->ToString());
npm ERR!       |                              ~~~~~~~~~~~~~~~~~^~
npm ERR! In file included from /root/.cache/node-gyp/20.10.0/include/node/v8-primitive.h:11,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:11,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/v8-array-buffer.h:13,
npm ERR!                  from /root/.cache/node-gyp/20.10.0/include/node/v8.h:24:
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:370:44: note: candidate: 'v8::MaybeLocal<v8::String> v8::Value::ToString(v8::Local<v8::Context>) const'
npm ERR!   370 |   V8_WARN_UNUSED_RESULT MaybeLocal<String> ToString(
npm ERR!       |                                            ^~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:370:44: note:   candidate expects 1 argument, 0 provided
npm ERR! ../src/serialport.cpp:48:52: error: no matching function for call to 'v8::Value::ToObject()'
npm ERR!    48 |   v8::Local<v8::Object> options = info[1]->ToObject();
npm ERR!       |                                   ~~~~~~~~~~~~~~~~~^~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note: candidate: 'v8::MaybeLocal<v8::Object> v8::Value::ToObject(v8::Local<v8::Context>) const'
npm ERR!   382 |   V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
npm ERR!       |                                            ^~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note:   candidate expects 1 argument, 0 provided
npm ERR! ../src/serialport.cpp:78:51: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!    78 |   uv_queue_work(uv_default_loop(), req, EIO_Open, (uv_after_work_cb)EIO_AfterOpen);
npm ERR!       |                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterOpen(uv_work_t*)':
npm ERR! ../src/serialport.cpp:95:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!    95 |   data->callback.Call(2, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Update(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:113:52: error: no matching function for call to 'v8::Value::ToObject()'
npm ERR!   113 |   v8::Local<v8::Object> options = info[1]->ToObject();
npm ERR!       |                                   ~~~~~~~~~~~~~~~~~^~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note: candidate: 'v8::MaybeLocal<v8::Object> v8::Value::ToObject(v8::Local<v8::Context>) const'
npm ERR!   382 |   V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
npm ERR!       |                                            ^~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note:   candidate expects 1 argument, 0 provided
npm ERR! ../src/serialport.cpp:135:53: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   135 |   uv_queue_work(uv_default_loop(), req, EIO_Update, (uv_after_work_cb)EIO_AfterUpdate);
npm ERR!       |                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterUpdate(uv_work_t*)':
npm ERR! ../src/serialport.cpp:150:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   150 |   data->callback.Call(1, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Close(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:175:52: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   175 |   uv_queue_work(uv_default_loop(), req, EIO_Close, (uv_after_work_cb)EIO_AfterClose);
npm ERR!       |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterClose(uv_work_t*)':
npm ERR! ../src/serialport.cpp:188:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   188 |   data->callback.Call(1, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Flush(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:215:52: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   215 |   uv_queue_work(uv_default_loop(), req, EIO_Flush, (uv_after_work_cb)EIO_AfterFlush);
npm ERR!       |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterFlush(uv_work_t*)':
npm ERR! ../src/serialport.cpp:231:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   231 |   data->callback.Call(1, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Set(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:250:52: error: no matching function for call to 'v8::Value::ToObject()'
npm ERR!   250 |   v8::Local<v8::Object> options = info[1]->ToObject();
npm ERR!       |                                   ~~~~~~~~~~~~~~~~~^~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note: candidate: 'v8::MaybeLocal<v8::Object> v8::Value::ToObject(v8::Local<v8::Context>) const'
npm ERR!   382 |   V8_WARN_UNUSED_RESULT MaybeLocal<Object> ToObject(
npm ERR!       |                                            ^~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-value.h:382:44: note:   candidate expects 1 argument, 0 provided
npm ERR! ../src/serialport.cpp:270:50: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   270 |   uv_queue_work(uv_default_loop(), req, EIO_Set, (uv_after_work_cb)EIO_AfterSet);
npm ERR!       |                                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterSet(uv_work_t*)':
npm ERR! ../src/serialport.cpp:285:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   285 |   data->callback.Call(1, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Get(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:314:50: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   314 |   uv_queue_work(uv_default_loop(), req, EIO_Get, (uv_after_work_cb)EIO_AfterGet);
npm ERR!       |                                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterGet(uv_work_t*)':
npm ERR! ../src/serialport.cpp:329:17: error: no matching function for call to 'v8::Object::Set(v8::Local<v8::String>, Nan::imp::FactoryBase<v8::Boolean>::return_t)'
npm ERR!   329 |     results->Set(Nan::New<v8::String>("cts").ToLocalChecked(), Nan::New<v8::Boolean>(data->cts));
npm ERR!       |     ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)'
npm ERR!   246 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, uint32_t, v8::Local<v8::Value>)'
npm ERR!   249 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! ../src/serialport.cpp:330:17: error: no matching function for call to 'v8::Object::Set(v8::Local<v8::String>, Nan::imp::FactoryBase<v8::Boolean>::return_t)'
npm ERR!   330 |     results->Set(Nan::New<v8::String>("dsr").ToLocalChecked(), Nan::New<v8::Boolean>(data->dsr));
npm ERR!       |     ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)'
npm ERR!   246 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, uint32_t, v8::Local<v8::Value>)'
npm ERR!   249 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! ../src/serialport.cpp:331:17: error: no matching function for call to 'v8::Object::Set(v8::Local<v8::String>, Nan::imp::FactoryBase<v8::Boolean>::return_t)'
npm ERR!   331 |     results->Set(Nan::New<v8::String>("dcd").ToLocalChecked(), Nan::New<v8::Boolean>(data->dcd));
npm ERR!       |     ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)'
npm ERR!   246 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:246:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note: candidate: 'v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, uint32_t, v8::Local<v8::Value>)'
npm ERR!   249 |   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
npm ERR!       |                                     ^~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/v8-object.h:249:37: note:   candidate expects 3 arguments, 2 provided
npm ERR! ../src/serialport.cpp:336:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   336 |   data->callback.Call(2, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE Drain(Nan::NAN_METHOD_ARGS_TYPE)':
npm ERR! ../src/serialport.cpp:362:52: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type]
npm ERR!   362 |   uv_queue_work(uv_default_loop(), req, EIO_Drain, (uv_after_work_cb)EIO_AfterDrain);
npm ERR!       |                                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp: In function 'void EIO_AfterDrain(uv_work_t*)':
npm ERR! ../src/serialport.cpp:377:22: warning: 'v8::Local<v8::Value> Nan::Callback::Call(int, v8::Local<v8::Value>*) const' is deprecated [-Wdeprecated-declarations]
npm ERR!   377 |   data->callback.Call(1, argv);
npm ERR!       |   ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
npm ERR! ../../nan/nan.h:1674:3: note: declared here
npm ERR!  1674 |   Call(int argc, v8::Local<v8::Value> argv[]) const {
npm ERR!       |   ^~~~
npm ERR! ../src/serialport.cpp: At global scope:
npm ERR! ../src/serialport.cpp:383:28: warning: unnecessary parentheses in declaration of 'ToParityEnum' [-Wparentheses]
npm ERR!   383 | SerialPortParity NAN_INLINE(ToParityEnum(const v8::Local<v8::String>& v8str)) {
npm ERR!       |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp:383:28: note: remove parentheses
npm ERR!   383 | SerialPortParity NAN_INLINE(ToParityEnum(const v8::Local<v8::String>& v8str)) {
npm ERR!       |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR!       |                            -                                                -
npm ERR! ../src/serialport.cpp:402:30: warning: unnecessary parentheses in declaration of 'ToStopBitEnum' [-Wparentheses]
npm ERR!   402 | SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) {
npm ERR!       |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/serialport.cpp:402:30: note: remove parentheses
npm ERR!   402 | SerialPortStopBits NAN_INLINE(ToStopBitEnum(double stopBits)) {
npm ERR!       |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR!       |                              -                              -
npm ERR! ../src/serialport.cpp:413:8: error: variable or field 'init' declared void
npm ERR!   413 |   void init(v8::Handle<v8::Object> target) {
npm ERR!       |        ^~~~
npm ERR! ../src/serialport.cpp:413:17: error: 'Handle' is not a member of 'v8'; did you mean 'JobHandle'?
npm ERR!   413 |   void init(v8::Handle<v8::Object> target) {
npm ERR!       |                 ^~~~~~
npm ERR!       |                 JobHandle
npm ERR! ../src/serialport.cpp:413:34: error: expected primary-expression before '>' token
npm ERR!   413 |   void init(v8::Handle<v8::Object> target) {
npm ERR!       |                                  ^
npm ERR! ../src/serialport.cpp:413:36: error: 'target' was not declared in this scope
npm ERR!   413 |   void init(v8::Handle<v8::Object> target) {
npm ERR!       |                                    ^~~~~~
npm ERR! ../src/serialport.cpp:437:25: error: 'init' was not declared in this scope; did you mean 'int'?
npm ERR!   437 | NODE_MODULE(serialport, init);
npm ERR!       |                         ^~~~
npm ERR! /root/.cache/node-gyp/20.10.0/include/node/node.h:1172:36: note: in definition of macro 'NODE_MODULE_X'
npm ERR!  1172 |       (node::addon_register_func) (regfunc),                          \
npm ERR!       |                                    ^~~~~~~
npm ERR! ../src/serialport.cpp:437:1: note: in expansion of macro 'NODE_MODULE'
npm ERR!   437 | NODE_MODULE(serialport, init);
npm ERR!       | ^~~~~~~~~~~
npm ERR! make: *** [serialport.target.mk:114: Release/obj.target/serialport/src/serialport.o] Error 1
npm ERR! gyp ERR! build error 
npm ERR! gyp ERR! stack Error: `make` failed with exit code: 2
npm ERR! gyp ERR! stack at ChildProcess.<anonymous> (/usr/lib/node_modules_20/npm/node_modules/node-gyp/lib/build.js:209:23)
npm ERR! gyp ERR! System Linux 6.6.7-200.fc39.x86_64
npm ERR! gyp ERR! command "/usr/bin/node-20" "/usr/lib/node_modules_20/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
npm ERR! gyp ERR! cwd /chattervox/node_modules/serialport
npm ERR! gyp ERR! node -v v20.10.0
npm ERR! gyp ERR! node-gyp -v v10.0.1
npm ERR! gyp ERR! not ok

npm ERR! A complete log of this run can be found in: /root/.npm/_logs/2024-01-22T13_27_00_145Z-debug-0.log
Error: building at STEP "RUN git clone https://github.com/brannondorsey/chattervox &&     cd chattervox &&     npm install &&     npm run build": while running runtime: exit status 1

Screenshot on readme

I see your htop picture ;)

Having a screenshot that's proudly shown on the ReadMe would make the project look a tad more proud of itself

RFC #2: Message Sequence Field

Proposal

Add an optional message sequence field to the chattervox packet. Initially proposed here.

Details

This functionality can be useful in determining if messages have been lost in transmission. It can also be used to protect against replay attacks in the event that clock synchronization is not possible or no timestamp field is included in the packet (see RFC #1).

This RFC proposes protocol-level support for message sequence numbers, however, it is up to the chattervox client software to choose how use them.

Considerations

  • The sequence field should be optional. Applications can opt out of sequence field inclusion in their chattervox packets to reduce packet size overhead.
  • Client software that supports the sequence field could alert users to message sequence gaps and aid in identifying lossy transmissions.
  • The sequence field is compatible with he timestamp field RFC #1. Either, both, or neither could be used.
  • Used to mitigate replay attacks, message sequence numbers are not as effective as timestamps as users are vulnerable to replay attacks that include message sequence numbers created since they last made contact with the real station. E.g. Alice and Bob are communicating in a round-table discussion in the CQ "chat room". The last message Alice hears from Bob before logging off contains sequence number 43. Once Alice has logged off, Bob continues to chat in the group and sends 100 messages, which Eve records. The next day, Alice joins the CQ while Bob is not present. She is vulnerable to replay attacks by Eve for 100 different messages that Eve heard but Alice did not. Because Bob is no longer in the room, he can not inform her that his next sequence number is 144.
  • Global sequence numbers don't play nice when a station uses two different computers, each with their own message sequence counters. Support for SSIDs (e.g. KC3LZO-1, KC3LZO-2, ...) mitigates this problem to some degree. This wouldn't be a problem if the client chooses to reset the sequence number each session, but then session numbers are no longer useful to prevent replay attacks.
  • The sequence number format should be large enough that messages won't rollover too frequently (or at all if used for replay attack protection) but small enough that they don't cause too much packet overhead.

Protocol Changes

Byte Offset # of Bits Name Value Description
0x0000 16 Magic Header 0x7a39 A constant two-byte value used to identify chattervox packets.
0x0002 8 Version Byte Number A protocol version number between 1-255.
0x0003 5 Unused Flag Bits Null Reserved for future use.
0x0003 1 Sequence Number Flag Bit A value of 1 indicates that the message contains a message sequence number.
0x0003 1 Digital Signature Flag Bit A value of 1 indicates that the message contains a ECDSA digital signature.
0x0003 1 Compression Flag Bit A value of 1 indicates that the message payload is compressed.
[0x0004] [8] [Signature Length] Number The length in bytes of the digital signature. This field is only included if the Digital Signature Flag is set.
[0x0004 or 0x0005] [0-2048] [Digital Signature] Bytes The ECDSA digital signature created using a SHA256 hash of the message contents and the sender's private key.
[0x0004-0x104] 8 or 24 [Sequence Number]* Unsigned Integer A message sequence number. This number should increase by one each time a new message is sent by a chattervox client.
0x0004-0x11C 0-โˆž Message* Bytes The packet's UTF-8 message payload. If the Compression Flag is set the contents of this buffer is a raw DEFLATE buffer containing the UTF-8 message.
bold values indicate proposed changes.
[] indicates an optional field.
* indicates a member of the signed message if a digital signature is present.

Open Questions

  • Should this method really be used for replay attack prevention? I don't think it is a very effective method of prevention.
  • If we don't intend to use sequence numbers to defend against replay attacks, we can make the bit-length of the field much smaller. If sequence numbers are used only to indicate message gaps, an 8-bit field would probably suffice. In this case the field would be used simply to count the relative distance between received messages and not the absolute message number. Sequence number rollovers would be fine as it is unlikely that a station would miss > 255 messages before hearing a new message.
  • Does adding a sequence number overstep the keep-it-simple-stupid ethos of the protocol? Does the usefulness of this feature outweigh the complexity it introduces?
  • Is this something that client software should roll itself on top of the protocol instead?

Raspbian NPM issue.

NPM fails to install.

(node:1185) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
npm ERR! Error: Method Not Allowed
npm ERR! at errorResponse (/usr/share/npm/lib/cache/add-named.js:260:10)
npm ERR! at /usr/share/npm/lib/cache/add-named.js:203:12
npm ERR! at saved (/usr/share/npm/node_modules/npm-registry-client/lib/get.js:167:7)
npm ERR! at FSReqWrap.oncomplete (fs.js:135:15)
npm ERR! If you need help, you may report this entire log,
npm ERR! including the npm and node versions, at:
npm ERR! http://github.com/npm/npm/issues

npm ERR! System Linux 4.14.62-v7+
npm ERR! command "/usr/bin/node" "/usr/bin/npm" "install"
npm ERR! cwd /home/pi/chattervox
npm ERR! node -v v8.11.1
npm ERR! npm -v 1.4.21
npm ERR! code E405
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/pi/chattervox/npm-debug.log
npm ERR! not ok code 0

Include a coarse timestamp to prevent replay of old messages

ysleepy on Hacker News said:

Maybe messages should include a coarse timestamp to prevent replay of old messages by some adversary.

Someone could resend a month old "yes" with your valid signature to a question someone asks now.

Also it might be beneficial to include sequence numbers or message IDs and for example echo the last 4 ids in following messages so recipients can detect holes. - The chat could insert some placeholder to notify recipients of missing previous messages.

Off-by-one in header structure description in readme

Currently, you show the 2-byte magic number at header offset 0x0000 (zero-based, obviously), but the version byte at offset 0x0003, and the flags bitfield at offset 0x0004. What is at offset 0x0002 is not stated.
Reviewing the code seems to indicate that everything other than the magic number should be reduced by one. Perhaps you started using 1-based counting, changed to 0-based to match the code, but didn't finish your updates?

RFC #1: Timestamp Field

Proposal

Add a timestamp field to the chattervox packet to protect against replay attacks. Initially proposed here.

Details

Protocol v1 supports cryptographic message signatures but provides no mechanism to protect against the replay of signed messages by parties other than the original sender/signer of a message.

From #10:

Someone could resend a month old "yes" with your valid signature to a question someone asks now.

The goal of this RFC is to add protocol-level protection from replay attacks using timestamps. Timestamps will be included in packets, however, it is up to the chattervox client software to choose how use them.

Considerations

  • The timestamp field should be optional. Applications that don't require replay protection can opt out of timestamp inclusion in their chattervox packets to reduce packet size overhead.
  • Communicating clients/stations must agree on the current time (using UTC time etc.) within some degree of accuracy in order to make use of the timestamp field. The method of clock synchronization is beyond the scope of this RFC and should be determined independent of the chattervox protocol.
  • Timestamp format...
    • Should be high enough precision that clients can choose strict "no replay after" windows. Ideally 1 second or less.
    • Can be unsigned as messages don't need to represent time before some epoch.
    • Should be Stored in a format that won't rollover for a long time (i.e. not a Unix timestamp due to the Year 2038 problem).
      • Unsigned 32-bit integers last 136 years before a rollover.
      • Unsigned 40-bit integers last 34,865 years before a rollover.
    • Can use a custom epoch.
      • 00:00:00 January 1, 2000 (A millineum epoch)
      • Tue Sep 11 17:46:35 2018 -0400 (The moment of the first chattervox commit)
    • Should be as small as possible to reduce packet size and overhead.

Protocol Changes

Byte Offset # of Bits Name Value Description
0x0000 16 Magic Header 0x7a39 A constant two-byte value used to identify chattervox packets.
0x0002 8 Version Byte Number A protocol version number between 1-255.
0x0003 5 Unused Flag Bits Null Reserved for future use.
0x0003 1 Timestamp Flag Bit A value of 1 indicates that the message contains a timestamp.
0x0003 1 Digital Signature Flag Bit A value of 1 indicates that the message contains a ECDSA digital signature.
0x0003 1 Compression Flag Bit A value of 1 indicates that the message payload is compressed.
[0x0004] [8] [Signature Length] Number The length in bytes of the digital signature. This field is only included if the Digital Signature Flag is set.
[0x0004 or 0x0005] [0-2048] [Digital Signature] Bytes The ECDSA digital signature created using a SHA256 hash of the message contents and the sender's private key.
[0x0004-0x104] 32 [Timestamp]* Unsigned Integer A time value representing seconds since Midnight Jan 1, 2000.
0x0004-0x125 0-โˆž Message* Bytes The packet's UTF-8 message payload. If the Compression Flag is set the contents of this buffer is a raw DEFLATE buffer containing the UTF-8 message.
bold values indicate proposed changes.
[] indicates an optional field.
* indicates a member of the signed message if a digital signature is present.

Implementation Notes

The addition of a timestamp field in the chatttervox protocol doesn't itself protect against replay attacks but it provides a mechanism for client software to do so. It's up to the chattervox client to use a computer's clock to compare the timestamp value in a packet to the time a message was received. If the distance between these two values is greater than some threshold then the message is likely being replayed and should be ignored by the client or alert the user of the attack. It is up to the client software to implement this comparison check as well as to define an appropriate threshold. A threshold should be large enough that it allows messages to be digipeated over a busy channel or across several digipeater hops but small enough that it doesn't leave the receiver vulnerable to replay attacks for a prolonged period of time. A threshold value of 5 minutes would allow the replay of messages within a 5 minute window. Transmission time should also be factored into the threshold value as a message may take a second or longer to transmit via 300 or 1200 baud. The chattervox typescript client will likely set this threshold at 30 seconds for initial testing.

Open Questions

  • Would a 32-bit timestamp value be large enough? An epoch starting at Jan 1 2000 would rollover in 2136. That seems long enough to me, especially considering that these timestamps, at least used to protect against replay attacks, can represent relative time, not absolute time. We need them only to measure the distance in time between when a message was sent and the current time, not the absolute moment when the message was sent. In this way, rollovers aren't necessarily a problem. The likelyhood that a message would be replayed > 136 years after it was sent is highly unlikely. And even then, depending on the behavior of the client software, an attacker would only have a very short window to replay a message every 136 years.
  • Is there a cheaper way to encode the time?

Updates

  • UPDATE (October 7, 2018): Change timestamp value from 40 bits to 32 bits. Fix incorrect message offset value.

Uncaught TypeError: Invalid magic bytes in packet header.

KC3LZO-4: test test
KC3LZO-4: do you copy?
KC3LZO-4: (node:8064) UnhandledPromiseRejectionWarning: TypeError: Invalid magic bytes in packet header
. This is not a CV Packet.
    at Packet.<anonymous> (/home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Packet
.js:96:23)
    at Generator.next (<anonymous>)
    at /home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Packet.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Packet.js:3:12)
    at Packet.disassemble (/home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Packet
.js:88:16)
    at Function.<anonymous> (/home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Pack
et.js:162:26)
    at Generator.next (<anonymous>)
    at /home/pi/.nvm/versions/node/v8.15.0/lib/node_modules/chattervox/build/Packet.js:7:71
    at new Promise (<anonymous>)
(node:8064) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either
 by throwing inside of an async function without a catch block, or by rejecting a promise which was not
 handled with .catch(). (rejection id: 4)
(node:8064) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, p
romise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Either handle config loading from cli nicely, or remove it.

chattervox --config ~/Documents/code/pw/README.md chat
SyntaxError: Unexpected token # in JSON at position 0
    at JSON.parse (<anonymous>)
    at Object.load (/home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/config.js:43:17)
    at /home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/main.js:104:29
    at Generator.next (<anonymous>)
    at /home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/main.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/main.js:4:12)
    at main (/home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/main.js:90:12)
    at Object.<anonymous> (/home/braxxox/.nvm/versions/node/v8.12.0/lib/node_modules/chattervox/build/main.js:127:1)
    at Module._compile (module.js:653:30)

Add direct messages

Messages with a to address of "CQ" appear in the regular chat. Messages with "@KC3LZO" at the beginning should only appear to KC3LZO.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.