Squashed 'external/toxcore/c-toxcore/' content from commit 67badf69
git-subtree-dir: external/toxcore/c-toxcore git-subtree-split: 67badf69416a74e74f6d7eb51dd96f37282b8455
This commit is contained in:
26
other/bootstrap_daemon/BUILD.bazel
Normal file
26
other/bootstrap_daemon/BUILD.bazel
Normal file
@ -0,0 +1,26 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary")
|
||||
|
||||
package(features = ["layering_check"])
|
||||
|
||||
cc_binary(
|
||||
name = "bootstrap_daemon",
|
||||
srcs = glob([
|
||||
"src/*.c",
|
||||
"src/*.h",
|
||||
]),
|
||||
deps = [
|
||||
"//c-toxcore/other:bootstrap_node_packets",
|
||||
"//c-toxcore/toxcore:DHT",
|
||||
"//c-toxcore/toxcore:LAN_discovery",
|
||||
"//c-toxcore/toxcore:TCP_server",
|
||||
"//c-toxcore/toxcore:announce",
|
||||
"//c-toxcore/toxcore:ccompat",
|
||||
"//c-toxcore/toxcore:group_onion_announce",
|
||||
"//c-toxcore/toxcore:logger",
|
||||
"//c-toxcore/toxcore:mono_time",
|
||||
"//c-toxcore/toxcore:onion_announce",
|
||||
"//c-toxcore/toxcore:tox",
|
||||
"//c-toxcore/toxcore:util",
|
||||
"@libconfig",
|
||||
],
|
||||
)
|
24
other/bootstrap_daemon/CMakeLists.txt
Normal file
24
other/bootstrap_daemon/CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Unity build broken because of _XOPEN_SOURCE macro
|
||||
set_source_files_properties(
|
||||
src/tox-bootstrapd.c
|
||||
PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE)
|
||||
|
||||
add_executable(tox-bootstrapd
|
||||
src/command_line_arguments.c
|
||||
src/command_line_arguments.h
|
||||
src/config.c
|
||||
src/config.h
|
||||
src/config_defaults.h
|
||||
src/global.h
|
||||
src/log.c
|
||||
src/log.h
|
||||
src/log_backend_stdout.c
|
||||
src/log_backend_stdout.h
|
||||
src/log_backend_syslog.c
|
||||
src/log_backend_syslog.h
|
||||
src/tox-bootstrapd.c
|
||||
../bootstrap_node_packets.c
|
||||
../bootstrap_node_packets.h)
|
||||
target_link_modules(tox-bootstrapd toxcore ${LIBCONFIG_LIBRARIES})
|
||||
install(TARGETS tox-bootstrapd RUNTIME DESTINATION bin)
|
||||
install(FILES bash-completion/completions/tox-bootstrapd DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions")
|
308
other/bootstrap_daemon/README.md
Normal file
308
other/bootstrap_daemon/README.md
Normal file
@ -0,0 +1,308 @@
|
||||
# Instructions
|
||||
|
||||
- [For `systemd` users](#for-systemd-users)
|
||||
- [Setting up](#setting-up)
|
||||
- [Updating](#updating)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [For `SysVinit` users](#for-sysvinit-users)
|
||||
- [Setting up](#setting-up-1)
|
||||
- [Updating](#updating-1)
|
||||
- [Troubleshooting](#troubleshooting-1)
|
||||
- [For `Docker` users](#for-docker-users)
|
||||
- [Setting up](#setting-up-2)
|
||||
- [Updating](#updating-2)
|
||||
- [Troubleshooting](#troubleshooting-2)
|
||||
|
||||
|
||||
These instructions are primarily tested on Debian Linux, Wheezy for SysVinit and Jessie for systemd, but they should work on other POSIX-compliant systems too.
|
||||
|
||||
|
||||
## For `systemd` users
|
||||
|
||||
### Setting up
|
||||
|
||||
For security reasons we run the daemon under its own user.
|
||||
|
||||
Create a new user by executing the following:
|
||||
```sh
|
||||
sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd
|
||||
```
|
||||
|
||||
Restrict access to home directory:
|
||||
```sh
|
||||
sudo chmod 700 /var/lib/tox-bootstrapd
|
||||
```
|
||||
|
||||
Copy `tox-bootstrapd.conf` file to where `ExecStart=` from `tox-bootstrapd.service` points to. By default it's `/etc/tox-bootstrapd.conf`.
|
||||
```sh
|
||||
sudo cp tox-bootstrapd.conf /etc/tox-bootstrapd.conf
|
||||
```
|
||||
|
||||
Go over everything in the copied `tox-bootstrapd.conf` file. Set options you want and add actual working nodes to the `bootstrap_nodes` list, instead of the example ones, if you want your node to connect to the Tox network. Make sure `pid_file_path` matches `PIDFile=` from `tox-bootstrapd.service`.
|
||||
|
||||
Copy `tox-bootstrapd.service` to `/etc/systemd/system/`:
|
||||
```sh
|
||||
sudo cp tox-bootstrapd.service /etc/systemd/system/
|
||||
```
|
||||
|
||||
You must uncomment the next line in tox-bootstrapd.service, if you want to use port number < 1024:
|
||||
|
||||
```
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
```
|
||||
|
||||
and, possibly, install `libcap2-bin` or `libcap2` package, depending of your distribution.
|
||||
|
||||
Reload systemd units definitions, enable service for automatic start (if needed), start it and verify it's running:
|
||||
```sh
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable tox-bootstrapd.service
|
||||
sudo systemctl start tox-bootstrapd.service
|
||||
sudo systemctl status tox-bootstrapd.service
|
||||
```
|
||||
|
||||
Get your public key and check that the daemon initialized correctly:
|
||||
```sh
|
||||
sudo grep "tox-bootstrapd" /var/log/syslog
|
||||
```
|
||||
|
||||
### Updating
|
||||
|
||||
You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month.
|
||||
|
||||
To update the daemon first stop it:
|
||||
|
||||
```sh
|
||||
sudo systemctl stop tox-bootstrapd.service
|
||||
```
|
||||
|
||||
Then update your toxcore git repository, rebuild the toxcore and the daemon and make sure to install them.
|
||||
|
||||
Check if `tox-bootstrapd.service` in toxcore git repository was modified since the last time you copied it, as you might need to update it too.
|
||||
|
||||
Reload `tox-bootstrapd.service` if you have updated modified it:
|
||||
|
||||
```sh
|
||||
sudo systemctl daemon-reload
|
||||
```
|
||||
|
||||
After all of this is done, simply start the daemon back again:
|
||||
|
||||
```sh
|
||||
sudo systemctl start tox-bootstrapd.service
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- Check daemon's status:
|
||||
```sh
|
||||
sudo systemctl status tox-bootstrapd.service
|
||||
```
|
||||
|
||||
- Check the log for errors:
|
||||
```sh
|
||||
sudo grep "tox-bootstrapd" /var/log/syslog
|
||||
# or
|
||||
sudo journalctl --pager-end
|
||||
# or
|
||||
sudo journalctl -f _SYSTEMD_UNIT=tox-bootstrapd.service
|
||||
```
|
||||
|
||||
- Make sure tox-bootstrapd user has write permission for keys and pid files.
|
||||
|
||||
- Make sure tox-bootstrapd has read permission for the config file.
|
||||
|
||||
- Make sure tox-bootstrapd location matches its path in tox-bootstrapd.service file.
|
||||
|
||||
|
||||
|
||||
## For `SysVinit` users
|
||||
|
||||
|
||||
### Setting up
|
||||
|
||||
For security reasons we run the daemon under its own user.
|
||||
|
||||
Create a new user by executing the following:
|
||||
```sh
|
||||
sudo useradd --home-dir /var/lib/tox-bootstrapd --create-home --system --shell /sbin/nologin --comment "Account to run Tox's DHT bootstrap daemon" --user-group tox-bootstrapd
|
||||
```
|
||||
|
||||
Restrict access to home directory:
|
||||
```sh
|
||||
sudo chmod 700 /var/lib/tox-bootstrapd
|
||||
```
|
||||
|
||||
Copy `tox-bootstrapd.conf` file to where `CFGFILE` variable from `tox-bootstrapd.sh` points to. By default it's `/etc/tox-bootstrapd.conf`.
|
||||
```sh
|
||||
sudo cp tox-bootstrapd.conf /etc/tox-bootstrapd.conf
|
||||
```
|
||||
|
||||
Go over everything in the copied `tox-bootstrapd.conf` file. Set options you want and add actual working nodes to the `bootstrap_nodes` list, instead of the example ones, if you want your node to connect to the Tox network. Make sure `pid_file_path` matches `PIDFILE` from `tox-bootstrapd.sh`.
|
||||
|
||||
Look at the variable declarations in the beginning of `tox-bootstrapd.sh` init script to see if you need to change anything for it to work on your system. The default values must be fine for most users and we assume that you use those next.
|
||||
|
||||
If you have configured the daemon to use any port numbers that are lower than 1024, you need to execute the command below, as by default non-privileged users cannot open ports <1024. The change persists through reboot:
|
||||
|
||||
```sh
|
||||
sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/tox-bootstrapd
|
||||
```
|
||||
|
||||
Copy `tox-bootstrapd.sh` init script to `/etc/init.d/tox-bootstrapd` (note the disappearance of ".sh" ending):
|
||||
```sh
|
||||
sudo cp tox-bootstrapd.sh /etc/init.d/tox-bootstrapd
|
||||
```
|
||||
|
||||
Set permissions for the init system to run the script:
|
||||
```sh
|
||||
sudo chmod 755 /etc/init.d/tox-bootstrapd
|
||||
```
|
||||
|
||||
Make the init system aware of the script, start the daemon and verify it's running:
|
||||
```sh
|
||||
sudo update-rc.d tox-bootstrapd defaults
|
||||
sudo service tox-bootstrapd start
|
||||
sudo service tox-bootstrapd status
|
||||
```
|
||||
|
||||
Get your public key and check that the daemon initialized correctly:
|
||||
```sh
|
||||
sudo grep "tox-bootstrapd" /var/log/syslog
|
||||
```
|
||||
|
||||
|
||||
### Updating
|
||||
|
||||
You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month.
|
||||
|
||||
To update the daemon first stop it:
|
||||
|
||||
```sh
|
||||
sudo service tox-bootstrapd stop
|
||||
```
|
||||
|
||||
Then update your toxcore git repository, rebuild the toxcore and the daemon and make sure to install them.
|
||||
|
||||
Check if `tox-bootstrapd.sh` in toxcore git repository was modified since the last time you copied it, as you might need to update it too.
|
||||
|
||||
After all of this is done, simply start the daemon back again:
|
||||
|
||||
```sh
|
||||
sudo service tox-bootstrapd start
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- Check daemon's status:
|
||||
```sh
|
||||
sudo service tox-bootstrapd status
|
||||
```
|
||||
|
||||
- Check the log for errors:
|
||||
```sh
|
||||
sudo grep "tox-bootstrapd" /var/log/syslog
|
||||
```
|
||||
|
||||
- Check that variables in the beginning of `/etc/init.d/tox-bootstrapd` are valid.
|
||||
|
||||
- Make sure tox-bootstrapd user has write permission for keys and pid files.
|
||||
|
||||
- Make sure tox-bootstrapd has read permission for the config file.
|
||||
|
||||
- Make sure tox-bootstrapd location matches its path in the `/etc/init.d/tox-bootstrapd` init script.
|
||||
|
||||
|
||||
## For `Docker` users:
|
||||
|
||||
### Setting up
|
||||
|
||||
If you are familiar with Docker and would rather run the daemon in a Docker container, you may download the latest official docker image. To download the latest image run:
|
||||
|
||||
```sh
|
||||
docker pull toxchat/bootstrap-node:latest
|
||||
docker run --rm -it --entrypoint=sha256sum toxchat/bootstrap-node:latest /usr/local/bin/tox-bootstrapd
|
||||
```
|
||||
|
||||
This will print the SHA256 checksum of the latest binary, which should agree with the SHA256 checksum in the Dockerfile.
|
||||
|
||||
If you want to build the bootstrap node from source, check out the latest release:
|
||||
|
||||
```sh
|
||||
git checkout $(git tag --list | grep -P '^v(\d+).(\d+).(\d+)$' | \
|
||||
sed 's/v/v /g' | sed 's/\./ /g' | \
|
||||
sort -snk4,4 | sort -snk3,3 | sort -snk2,2 | tail -n 1 | \
|
||||
sed 's/v /v/g' | sed 's/ /\./g')
|
||||
```
|
||||
|
||||
and run the following from the top level c-toxcore directory:
|
||||
|
||||
```sh
|
||||
tar c $(git ls-files) | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node -
|
||||
|
||||
sudo useradd \
|
||||
--home-dir /var/lib/tox-bootstrapd \
|
||||
--create-home \
|
||||
--system \
|
||||
--shell /sbin/nologin \
|
||||
--comment "Account to run Tox's DHT bootstrap daemon" \
|
||||
--user-group tox-bootstrapd
|
||||
sudo chmod 700 /var/lib/tox-bootstrapd
|
||||
|
||||
docker run -d --name tox-bootstrapd --restart always \
|
||||
--user "$(id -u tox-bootstrapd):$(id -g tox-bootstrapd)" \
|
||||
-v /var/lib/tox-bootstrapd/:/var/lib/tox-bootstrapd/ \
|
||||
--ulimit nofile=32768:32768 \
|
||||
-p 443:443 \
|
||||
-p 3389:3389 \
|
||||
-p 33445:33445 \
|
||||
-p 33445:33445/udp \
|
||||
toxchat/bootstrap-node
|
||||
```
|
||||
|
||||
We create a new user and protect its home directory in order to mount it in the Docker image, so that the kyepair the daemon uses would be stored on the host system, which makes it less likely that you would loose the keypair while playing with or updating the Docker container.
|
||||
|
||||
You can check logs for your public key or any errors:
|
||||
```sh
|
||||
docker logs tox-bootstrapd
|
||||
```
|
||||
|
||||
Note that the Docker container runs a script which pulls a list of bootstrap nodes off https://nodes.tox.chat/ and adds them in the config file.
|
||||
|
||||
### Updating
|
||||
|
||||
You want to make sure that the daemon uses the newest toxcore, as there might have been some changes done to the DHT, so it's advised to update the daemon at least once every month.
|
||||
|
||||
To update the daemon, all you need is to erase current container with its image:
|
||||
|
||||
```sh
|
||||
docker stop tox-bootstrapd
|
||||
docker rm tox-bootstrapd
|
||||
docker rmi toxchat/bootstrap-node
|
||||
```
|
||||
|
||||
Then rebuild and run the image again:
|
||||
|
||||
```sh
|
||||
tar c $(git ls-files) | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node -
|
||||
docker run -d --name tox-bootstrapd --restart always \
|
||||
--user "$(id -u tox-bootstrapd):$(id -g tox-bootstrapd)" \
|
||||
-v /var/lib/tox-bootstrapd/:/var/lib/tox-bootstrapd/ \
|
||||
--ulimit nofile=32768:32768 \
|
||||
-p 443:443 \
|
||||
-p 3389:3389 \
|
||||
-p 33445:33445 \
|
||||
-p 33445:33445/udp \
|
||||
toxchat/bootstrap-node
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- Check if the container is running:
|
||||
```sh
|
||||
docker ps -a
|
||||
```
|
||||
|
||||
- Check the log for errors:
|
||||
```sh
|
||||
docker logs tox-bootstrapd
|
||||
```
|
@ -0,0 +1,27 @@
|
||||
# tox-bootstrapd completion -*- shell-script -*-
|
||||
|
||||
_tox_bootstrapd()
|
||||
{
|
||||
local cur prev words cword split
|
||||
_init_completion -s || return
|
||||
|
||||
case $prev in
|
||||
--config)
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
--log-backend)
|
||||
COMPREPLY=($(compgen -W 'stdout syslog' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
$split && return
|
||||
|
||||
if type _bashcomp_try_faketty &>/dev/null; then
|
||||
COMPREPLY=($(compgen -W '$(_parse_help _bashcomp_try_faketty "$1" --help)' -- "$cur"))
|
||||
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace
|
||||
fi
|
||||
} && complete -F _tox_bootstrapd tox-bootstrapd
|
||||
|
||||
# ex: filetype=sh
|
90
other/bootstrap_daemon/docker/Dockerfile
Normal file
90
other/bootstrap_daemon/docker/Dockerfile
Normal file
@ -0,0 +1,90 @@
|
||||
###########################################################
|
||||
# Builder image: we compile the code here (static build)
|
||||
FROM alpine:3.15.0 AS build
|
||||
|
||||
RUN ["apk", "--no-cache", "add",\
|
||||
"build-base",\
|
||||
"cmake",\
|
||||
"linux-headers",\
|
||||
"libconfig-dev",\
|
||||
"libconfig-static",\
|
||||
"libsodium-dev",\
|
||||
"libsodium-static",\
|
||||
"ninja",\
|
||||
"python3"\
|
||||
]
|
||||
|
||||
WORKDIR /src/c-toxcore
|
||||
|
||||
# Very selectively add files to the image, because we may have random stuff
|
||||
# lying around. In particular, we don't need to rebuild the docker image when
|
||||
# toxav changes or the Dockerfile changes down from the build.
|
||||
COPY cmake cmake
|
||||
COPY other/bootstrap_daemon/bash-completion other/bootstrap_daemon/bash-completion
|
||||
COPY other/bootstrap_daemon/src other/bootstrap_daemon/src
|
||||
COPY other/bootstrap_node_packets.[ch] other/
|
||||
COPY other/DHT_bootstrap.c other/
|
||||
COPY other/pkgconfig other/pkgconfig
|
||||
COPY other/rpm other/rpm
|
||||
COPY testing/misc_tools.[ch] testing/
|
||||
COPY toxcore toxcore
|
||||
COPY toxencryptsave toxencryptsave
|
||||
COPY third_party third_party
|
||||
COPY CMakeLists.txt so.version ./
|
||||
COPY other/bootstrap_daemon/CMakeLists.txt other/bootstrap_daemon/CMakeLists.txt
|
||||
COPY testing/CMakeLists.txt testing/CMakeLists.txt
|
||||
|
||||
RUN cmake -B_build -H. \
|
||||
-GNinja \
|
||||
-DCMAKE_C_FLAGS="-DTCP_SERVER_USE_EPOLL -fstack-protector-all -fisolate-erroneous-paths-attribute" \
|
||||
-DCMAKE_UNITY_BUILD=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DFULLY_STATIC=ON \
|
||||
-DMIN_LOGGER_LEVEL=DEBUG \
|
||||
-DBUILD_TOXAV=OFF \
|
||||
-DBOOTSTRAP_DAEMON=ON && \
|
||||
cmake --build _build --target install
|
||||
|
||||
# Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't
|
||||
# mess with your binaries.
|
||||
COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/
|
||||
RUN sha256sum /usr/local/bin/tox-bootstrapd && \
|
||||
sha256sum -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256
|
||||
|
||||
# Remove all the example bootstrap nodes from the config file.
|
||||
COPY other/bootstrap_daemon/tox-bootstrapd.conf other/bootstrap_daemon/
|
||||
# hadolint ignore=SC2086,SC2154
|
||||
RUN ["sed", "-i", "/^bootstrap_nodes = /,$d", "other/bootstrap_daemon/tox-bootstrapd.conf"]
|
||||
|
||||
# Add bootstrap nodes from https://nodes.tox.chat/.
|
||||
COPY other/bootstrap_daemon/docker/get-nodes.py other/bootstrap_daemon/docker/
|
||||
RUN ["other/bootstrap_daemon/docker/get-nodes.py", "other/bootstrap_daemon/tox-bootstrapd.conf"]
|
||||
|
||||
###########################################################
|
||||
# Final image build: this is what runs the bootstrap node
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
COPY --from=build /usr/local/bin/tox-bootstrapd /usr/local/bin/
|
||||
COPY --from=build /src/c-toxcore/other/bootstrap_daemon/tox-bootstrapd.conf /etc/tox-bootstrapd.conf
|
||||
RUN useradd --home-dir /var/lib/tox-bootstrapd --create-home \
|
||||
--system --shell /sbin/nologin \
|
||||
--comment "Account to run the Tox DHT bootstrap daemon" \
|
||||
--user-group tox-bootstrapd && \
|
||||
chmod 644 /etc/tox-bootstrapd.conf && \
|
||||
chmod 700 /var/lib/tox-bootstrapd
|
||||
|
||||
WORKDIR /var/lib/tox-bootstrapd
|
||||
|
||||
USER tox-bootstrapd
|
||||
|
||||
# Smoke-test: make sure the binary actually starts up.
|
||||
# hadolint ignore=DL4006
|
||||
RUN script /usr/local/bin/tox-bootstrapd --help | grep "Usage"
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/tox-bootstrapd",\
|
||||
"--config", "/etc/tox-bootstrapd.conf",\
|
||||
"--log-backend", "stdout",\
|
||||
"--foreground"\
|
||||
]
|
||||
|
||||
EXPOSE 443/tcp 3389/tcp 33445/tcp 33445/udp
|
55
other/bootstrap_daemon/docker/get-nodes.py
Executable file
55
other/bootstrap_daemon/docker/get-nodes.py
Executable file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Copyright (c) 2016 by nurupo <nurupo.contributions@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
# Gets a list of nodes from https://nodes.tox.chat/json and prints them out
|
||||
# in the format of tox-bootstrapd config file.
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
from typing import Dict
|
||||
|
||||
response = urllib.request.urlopen("https://nodes.tox.chat/json")
|
||||
raw_json = response.read().decode("ascii", "ignore")
|
||||
nodes = json.loads(raw_json)["nodes"]
|
||||
|
||||
|
||||
def node_to_string(node: Dict[str, str]) -> str:
|
||||
node_output = " { // " + node["maintainer"] + "\n"
|
||||
node_output += ' public_key = "' + node["public_key"] + '"\n'
|
||||
node_output += " port = " + str(node["port"]) + "\n"
|
||||
node_output += ' address = "'
|
||||
if len(node["ipv4"]) > 4:
|
||||
return node_output + node["ipv4"] + '"\n }'
|
||||
if len(node["ipv6"]) > 4:
|
||||
return node_output + node["ipv6"] + '"\n }'
|
||||
raise Exception("no IP address found for node " + json.dumps(node))
|
||||
|
||||
|
||||
output = "bootstrap_nodes = (\n" + ",\n".join(map(node_to_string,
|
||||
nodes)) + "\n)"
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
with open(sys.argv[1], "a") as fh:
|
||||
fh.write(output + "\n")
|
||||
print("Wrote %d nodes to %s" % (len(nodes), sys.argv[1]))
|
||||
else:
|
||||
print(output)
|
1
other/bootstrap_daemon/docker/tox-bootstrapd.sha256
Normal file
1
other/bootstrap_daemon/docker/tox-bootstrapd.sha256
Normal file
@ -0,0 +1 @@
|
||||
4f5b47978dc26aed78719526f862a44693f821db12f5ff6d70b338d67fb6f784 /usr/local/bin/tox-bootstrapd
|
24
other/bootstrap_daemon/docker/update-sha256
Executable file
24
other/bootstrap_daemon/docker/update-sha256
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eux
|
||||
|
||||
docker_build() {
|
||||
docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node .
|
||||
}
|
||||
|
||||
# Run Docker build once. If it succeeds, we're good.
|
||||
if docker_build; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# We're not good. Run it again, but now capture the output.
|
||||
OUTPUT=$(docker_build || true 2>&1)
|
||||
|
||||
if echo "$OUTPUT" | grep '/usr/local/bin/tox-bootstrapd: FAILED'; then
|
||||
# This is a checksum warning, so we need to update it.
|
||||
IMAGE=$(echo "$OUTPUT" | grep '^ ---> [0-9a-f]*$' | grep -o '[0-9a-f]*$' | tail -n1)
|
||||
docker run --rm "$IMAGE" sha256sum /usr/local/bin/tox-bootstrapd >other/bootstrap_daemon/docker/tox-bootstrapd.sha256
|
||||
fi
|
||||
|
||||
# Run once last time to complete the build.
|
||||
docker_build
|
47
other/bootstrap_daemon/src/Makefile.inc
Normal file
47
other/bootstrap_daemon/src/Makefile.inc
Normal file
@ -0,0 +1,47 @@
|
||||
if BUILD_DHT_BOOTSTRAP_DAEMON
|
||||
|
||||
bin_PROGRAMS += tox-bootstrapd
|
||||
|
||||
tox_bootstrapd_SOURCES = \
|
||||
../other/bootstrap_daemon/src/command_line_arguments.c \
|
||||
../other/bootstrap_daemon/src/command_line_arguments.h \
|
||||
../other/bootstrap_daemon/src/config.c \
|
||||
../other/bootstrap_daemon/src/config.h \
|
||||
../other/bootstrap_daemon/src/config_defaults.h \
|
||||
../other/bootstrap_daemon/src/global.h \
|
||||
../other/bootstrap_daemon/src/log.c \
|
||||
../other/bootstrap_daemon/src/log.h \
|
||||
../other/bootstrap_daemon/src/log_backend_stdout.c \
|
||||
../other/bootstrap_daemon/src/log_backend_stdout.h \
|
||||
../other/bootstrap_daemon/src/log_backend_syslog.c \
|
||||
../other/bootstrap_daemon/src/log_backend_syslog.h \
|
||||
../other/bootstrap_daemon/src/tox-bootstrapd.c \
|
||||
../other/bootstrap_daemon/src/global.h \
|
||||
../other/bootstrap_node_packets.c \
|
||||
../other/bootstrap_node_packets.h
|
||||
|
||||
|
||||
tox_bootstrapd_CFLAGS = \
|
||||
-I$(top_srcdir)/other/bootstrap_daemon \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(LIBCONFIG_CFLAGS)
|
||||
|
||||
tox_bootstrapd_LDADD = \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBCONFIG_LIBS) \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_OBJECTS) \
|
||||
$(NACL_LIBS)
|
||||
|
||||
bashcompdir = $(datarootdir)/bash-completion/completions
|
||||
dist_bashcomp_DATA = $(top_builddir)/other/bootstrap_daemon/bash-completion/completions/tox-bootstrapd
|
||||
|
||||
EXTRA_DIST += \
|
||||
$(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.conf \
|
||||
$(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.service \
|
||||
$(top_srcdir)/other/bootstrap_daemon/tox-bootstrapd.sh
|
||||
|
||||
endif
|
134
other/bootstrap_daemon/src/command_line_arguments.c
Normal file
134
other/bootstrap_daemon/src/command_line_arguments.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Command line argument handling.
|
||||
*/
|
||||
#include "command_line_arguments.h"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Prints --help message
|
||||
*/
|
||||
static void print_help(void)
|
||||
{
|
||||
// 2 space ident
|
||||
// make sure all lines fit into 80 columns
|
||||
// make sure options are listed in alphabetical order
|
||||
log_write(LOG_LEVEL_INFO,
|
||||
"Usage: tox-bootstrapd [OPTION]... --config=FILE_PATH\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" --config=FILE_PATH Specify path to the config file.\n"
|
||||
" This is a required option.\n"
|
||||
" Set FILE_PATH to a path to an empty file in order to\n"
|
||||
" use default settings.\n"
|
||||
" --foreground Run the daemon in foreground. The daemon won't fork\n"
|
||||
" (detach from the terminal) and won't use the PID file.\n"
|
||||
" --help Print this help message.\n"
|
||||
" --log-backend=BACKEND Specify which logging backend to use.\n"
|
||||
" Valid BACKEND values (case sensetive):\n"
|
||||
" syslog Writes log messages to syslog.\n"
|
||||
" Default option when no --log-backend is\n"
|
||||
" specified.\n"
|
||||
" stdout Writes log messages to stdout/stderr.\n"
|
||||
" --version Print version information.\n");
|
||||
}
|
||||
|
||||
void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend,
|
||||
bool *run_in_foreground)
|
||||
{
|
||||
if (argc < 2) {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: No arguments provided.\n\n");
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opterr = 0;
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"config", required_argument, nullptr, 'c'}, // required option
|
||||
{"foreground", no_argument, nullptr, 'f'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"log-backend", required_argument, nullptr, 'l'}, // optional, defaults to syslog
|
||||
{"version", no_argument, nullptr, 'v'},
|
||||
{nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
bool cfg_file_path_set = false;
|
||||
bool log_backend_set = false;
|
||||
|
||||
*run_in_foreground = false;
|
||||
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, ":", long_options, nullptr)) != -1) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'c':
|
||||
*cfg_file_path = optarg;
|
||||
cfg_file_path_set = true;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
*run_in_foreground = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
|
||||
case 'l':
|
||||
if (strcmp(optarg, "syslog") == 0) {
|
||||
*log_backend = LOG_BACKEND_SYSLOG;
|
||||
log_backend_set = true;
|
||||
} else if (strcmp(optarg, "stdout") == 0) {
|
||||
*log_backend = LOG_BACKEND_STDOUT;
|
||||
log_backend_set = true;
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: Invalid BACKEND value for --log-backend option passed: %s\n\n", optarg);
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
log_write(LOG_LEVEL_INFO, "Version: %lu\n", DAEMON_VERSION_NUMBER);
|
||||
exit(0);
|
||||
|
||||
case '?':
|
||||
log_write(LOG_LEVEL_ERROR, "Error: Unrecognized option %s\n\n", argv[optind - 1]);
|
||||
print_help();
|
||||
exit(1);
|
||||
|
||||
case ':':
|
||||
log_write(LOG_LEVEL_ERROR, "Error: No argument provided for option %s\n\n", argv[optind - 1]);
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!log_backend_set) {
|
||||
*log_backend = LOG_BACKEND_SYSLOG;
|
||||
}
|
||||
|
||||
if (!cfg_file_path_set) {
|
||||
log_write(LOG_LEVEL_ERROR, "Error: The required --config option wasn't specified\n\n");
|
||||
print_help();
|
||||
exit(1);
|
||||
}
|
||||
}
|
28
other/bootstrap_daemon/src/command_line_arguments.h
Normal file
28
other/bootstrap_daemon/src/command_line_arguments.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Command line argument handling.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* Handles command line arguments, setting cfg_file_path and log_backend.
|
||||
* Terminates the application if incorrect arguments are specified.
|
||||
*
|
||||
* @param argc Argc passed into main().
|
||||
* @param argv Argv passed into main().
|
||||
* @param cfg_file_path Sets to the provided by the user config file path.
|
||||
* @param log_backend Sets to the provided by the user log backend option.
|
||||
* @param run_in_foreground Sets to the provided by the user foreground option.
|
||||
*/
|
||||
void handle_command_line_arguments(int argc, char *argv[], char **cfg_file_path, LOG_BACKEND *log_backend,
|
||||
bool *run_in_foreground);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_COMMAND_LINE_ARGUMENTS_H
|
414
other/bootstrap_daemon/src/config.c
Normal file
414
other/bootstrap_daemon/src/config.c
Normal file
@ -0,0 +1,414 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Functionality related to dealing with the config file.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "config_defaults.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libconfig.h>
|
||||
|
||||
#include "../../bootstrap_node_packets.h"
|
||||
|
||||
/**
|
||||
* Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array.
|
||||
*
|
||||
* Supposed to be called from get_general_config only.
|
||||
*
|
||||
* Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports`.
|
||||
*/
|
||||
static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count)
|
||||
{
|
||||
const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports";
|
||||
|
||||
*tcp_relay_port_count = 0;
|
||||
|
||||
config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS);
|
||||
|
||||
if (ports_array == nullptr) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS);
|
||||
|
||||
uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS};
|
||||
|
||||
for (int i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; ++i) {
|
||||
log_write(LOG_LEVEL_INFO, "Port #%d: %u\n", i, default_ports[i]);
|
||||
}
|
||||
|
||||
// similar procedure to the one of reading config file below
|
||||
*tcp_relay_ports = (uint16_t *)malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; ++i) {
|
||||
|
||||
(*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i];
|
||||
|
||||
if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
|
||||
|| (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
|
||||
log_write(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
|
||||
(*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
|
||||
continue;
|
||||
}
|
||||
|
||||
++*tcp_relay_port_count;
|
||||
}
|
||||
|
||||
// the loop above skips invalid ports, so we adjust the allocated memory size
|
||||
if ((*tcp_relay_port_count) > 0) {
|
||||
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
|
||||
} else {
|
||||
free(*tcp_relay_ports);
|
||||
*tcp_relay_ports = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (config_setting_is_array(ports_array) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_ERROR, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n",
|
||||
NAME_TCP_RELAY_PORTS);
|
||||
return;
|
||||
}
|
||||
|
||||
int config_port_count = config_setting_length(ports_array);
|
||||
|
||||
if (config_port_count == 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS);
|
||||
return;
|
||||
}
|
||||
|
||||
*tcp_relay_ports = (uint16_t *)malloc(config_port_count * sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i < config_port_count; ++i) {
|
||||
config_setting_t *elem = config_setting_get_elem(ports_array, i);
|
||||
|
||||
if (elem == nullptr) {
|
||||
// it's NULL if `ports_array` is not an array (we have that check earlier) or if `i` is out of range, which should not be
|
||||
log_write(LOG_LEVEL_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (config_setting_is_number(elem) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "Port #%d: Not a number. Skipping.\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
(*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem);
|
||||
|
||||
if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT
|
||||
|| (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) {
|
||||
log_write(LOG_LEVEL_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i,
|
||||
(*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
|
||||
continue;
|
||||
}
|
||||
|
||||
++*tcp_relay_port_count;
|
||||
}
|
||||
|
||||
// the loop above skips invalid ports, so we adjust the allocated memory size
|
||||
if ((*tcp_relay_port_count) > 0) {
|
||||
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
|
||||
} else {
|
||||
free(*tcp_relay_ports);
|
||||
*tcp_relay_ports = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port,
|
||||
int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay,
|
||||
uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd)
|
||||
{
|
||||
config_t cfg;
|
||||
|
||||
const char *NAME_PORT = "port";
|
||||
const char *NAME_PID_FILE_PATH = "pid_file_path";
|
||||
const char *NAME_KEYS_FILE_PATH = "keys_file_path";
|
||||
const char *NAME_ENABLE_IPV6 = "enable_ipv6";
|
||||
const char *NAME_ENABLE_IPV4_FALLBACK = "enable_ipv4_fallback";
|
||||
const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery";
|
||||
const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay";
|
||||
const char *NAME_ENABLE_MOTD = "enable_motd";
|
||||
const char *NAME_MOTD = "motd";
|
||||
|
||||
config_init(&cfg);
|
||||
|
||||
// Read the file. If there is an error, report it and exit.
|
||||
if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
|
||||
config_destroy(&cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get port
|
||||
if (config_lookup_int(&cfg, NAME_PORT, port) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PORT);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %d\n", NAME_PORT, DEFAULT_PORT);
|
||||
*port = DEFAULT_PORT;
|
||||
}
|
||||
|
||||
// Get PID file location
|
||||
const char *tmp_pid_file;
|
||||
|
||||
if (config_lookup_string(&cfg, NAME_PID_FILE_PATH, &tmp_pid_file) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_PID_FILE_PATH);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_PID_FILE_PATH, DEFAULT_PID_FILE_PATH);
|
||||
tmp_pid_file = DEFAULT_PID_FILE_PATH;
|
||||
}
|
||||
|
||||
const size_t pid_file_path_len = strlen(tmp_pid_file) + 1;
|
||||
*pid_file_path = (char *)malloc(pid_file_path_len);
|
||||
memcpy(*pid_file_path, tmp_pid_file, pid_file_path_len);
|
||||
|
||||
// Get keys file location
|
||||
const char *tmp_keys_file;
|
||||
|
||||
if (config_lookup_string(&cfg, NAME_KEYS_FILE_PATH, &tmp_keys_file) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_KEYS_FILE_PATH);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_KEYS_FILE_PATH, DEFAULT_KEYS_FILE_PATH);
|
||||
tmp_keys_file = DEFAULT_KEYS_FILE_PATH;
|
||||
}
|
||||
|
||||
const size_t keys_file_path_len = strlen(tmp_keys_file) + 1;
|
||||
*keys_file_path = (char *)malloc(keys_file_path_len);
|
||||
memcpy(*keys_file_path, tmp_keys_file, keys_file_path_len);
|
||||
|
||||
// Get IPv6 option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_IPV6, enable_ipv6) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV6);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV6, DEFAULT_ENABLE_IPV6 ? "true" : "false");
|
||||
*enable_ipv6 = DEFAULT_ENABLE_IPV6;
|
||||
}
|
||||
|
||||
// Get IPv4 fallback option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_IPV4_FALLBACK, enable_ipv4_fallback) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_IPV4_FALLBACK);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_IPV4_FALLBACK,
|
||||
DEFAULT_ENABLE_IPV4_FALLBACK ? "true" : "false");
|
||||
*enable_ipv4_fallback = DEFAULT_ENABLE_IPV4_FALLBACK;
|
||||
}
|
||||
|
||||
// Get LAN discovery option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_LAN_DISCOVERY, enable_lan_discovery) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_LAN_DISCOVERY);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_LAN_DISCOVERY,
|
||||
DEFAULT_ENABLE_LAN_DISCOVERY ? "true" : "false");
|
||||
*enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY;
|
||||
}
|
||||
|
||||
// Get TCP relay option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY,
|
||||
DEFAULT_ENABLE_TCP_RELAY ? "true" : "false");
|
||||
*enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY;
|
||||
}
|
||||
|
||||
if (*enable_tcp_relay) {
|
||||
parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count);
|
||||
} else {
|
||||
*tcp_relay_port_count = 0;
|
||||
}
|
||||
|
||||
// Get MOTD option
|
||||
if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD,
|
||||
DEFAULT_ENABLE_MOTD ? "true" : "false");
|
||||
*enable_motd = DEFAULT_ENABLE_MOTD;
|
||||
}
|
||||
|
||||
if (*enable_motd) {
|
||||
// Get MOTD
|
||||
const char *tmp_motd;
|
||||
|
||||
if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD);
|
||||
log_write(LOG_LEVEL_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD);
|
||||
tmp_motd = DEFAULT_MOTD;
|
||||
}
|
||||
|
||||
size_t tmp_motd_length = strlen(tmp_motd) + 1;
|
||||
size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length;
|
||||
*motd = (char *)malloc(motd_length);
|
||||
snprintf(*motd, motd_length, "%s", tmp_motd);
|
||||
}
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Successfully read:\n");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port);
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false");
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false");
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false");
|
||||
|
||||
// show info about tcp ports only if tcp relay is enabled
|
||||
if (*enable_tcp_relay) {
|
||||
if (*tcp_relay_port_count == 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_INFO, "Read %d TCP ports:\n", *tcp_relay_port_count);
|
||||
|
||||
for (int i = 0; i < *tcp_relay_port_count; ++i) {
|
||||
log_write(LOG_LEVEL_INFO, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false");
|
||||
|
||||
if (*enable_motd) {
|
||||
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Converts a hex string with even number of characters into binary.
|
||||
*
|
||||
* Important: You are responsible for freeing the return value.
|
||||
*
|
||||
* @return binary on success,
|
||||
* NULL on failure.
|
||||
*/
|
||||
static uint8_t *bootstrap_hex_string_to_bin(const char *hex_string)
|
||||
{
|
||||
if (strlen(hex_string) % 2 != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t len = strlen(hex_string) / 2;
|
||||
uint8_t *ret = (uint8_t *)malloc(len);
|
||||
|
||||
const char *pos = hex_string;
|
||||
|
||||
for (size_t i = 0; i < len; ++i, pos += 2) {
|
||||
unsigned int val;
|
||||
sscanf(pos, "%02x", &val);
|
||||
ret[i] = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
|
||||
{
|
||||
const char *NAME_BOOTSTRAP_NODES = "bootstrap_nodes";
|
||||
|
||||
const char *NAME_PUBLIC_KEY = "public_key";
|
||||
const char *NAME_PORT = "port";
|
||||
const char *NAME_ADDRESS = "address";
|
||||
|
||||
config_t cfg;
|
||||
|
||||
config_init(&cfg);
|
||||
|
||||
if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
|
||||
config_destroy(&cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES);
|
||||
|
||||
if (node_list == nullptr) {
|
||||
log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n",
|
||||
NAME_BOOTSTRAP_NODES);
|
||||
config_destroy(&cfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config_setting_length(node_list) == 0) {
|
||||
log_write(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n");
|
||||
config_destroy(&cfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bs_port;
|
||||
const char *bs_address;
|
||||
const char *bs_public_key;
|
||||
|
||||
config_setting_t *node;
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (config_setting_length(node_list)) {
|
||||
int address_resolved;
|
||||
uint8_t *bs_public_key_bin;
|
||||
|
||||
node = config_setting_get_elem(node_list, 0);
|
||||
|
||||
if (node == nullptr) {
|
||||
config_destroy(&cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check that all settings are present
|
||||
if (config_setting_lookup_string(node, NAME_PUBLIC_KEY, &bs_public_key) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i,
|
||||
NAME_PUBLIC_KEY);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_int(node, NAME_PORT, &bs_port) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_PORT);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (config_setting_lookup_string(node, NAME_ADDRESS, &bs_address) == CONFIG_FALSE) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Couldn't find '%s' setting. Skipping the node.\n", i, NAME_ADDRESS);
|
||||
goto next;
|
||||
}
|
||||
|
||||
// Process settings
|
||||
if (strlen(bs_public_key) != CRYPTO_PUBLIC_KEY_SIZE * 2) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY,
|
||||
bs_public_key);
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i,
|
||||
NAME_PORT,
|
||||
bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT);
|
||||
goto next;
|
||||
}
|
||||
|
||||
bs_public_key_bin = bootstrap_hex_string_to_bin(bs_public_key);
|
||||
address_resolved = dht_bootstrap_from_address(dht, bs_address, enable_ipv6, net_htons(bs_port),
|
||||
bs_public_key_bin);
|
||||
free(bs_public_key_bin);
|
||||
|
||||
if (!address_resolved) {
|
||||
log_write(LOG_LEVEL_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_ADDRESS, bs_address);
|
||||
goto next;
|
||||
}
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key);
|
||||
|
||||
next:
|
||||
// config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly
|
||||
// though it's freed when the element is removed, so we free it right away in order to keep memory
|
||||
// consumption minimal
|
||||
config_setting_remove_elem(node_list, 0);
|
||||
++i;
|
||||
}
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
return 1;
|
||||
}
|
37
other/bootstrap_daemon/src/config.h
Normal file
37
other/bootstrap_daemon/src/config.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Functionality related to dealing with the config file.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
||||
|
||||
#include "../../../toxcore/DHT.h"
|
||||
|
||||
/**
|
||||
* Gets general config options from the config file.
|
||||
*
|
||||
* Important: You are responsible for freeing `pid_file_path` and `keys_file_path`
|
||||
* also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports`
|
||||
* and also `motd` iff `enable_motd` is set.
|
||||
*
|
||||
* @return 1 on success,
|
||||
* 0 on failure, doesn't modify any data pointed by arguments.
|
||||
*/
|
||||
int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port,
|
||||
int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay,
|
||||
uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd);
|
||||
|
||||
/**
|
||||
* Bootstraps off nodes listed in the config file.
|
||||
*
|
||||
* @return 1 on success, some or no bootstrap nodes were added
|
||||
* 0 on failure, a error accured while parsing config file.
|
||||
*/
|
||||
int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H
|
27
other/bootstrap_daemon/src/config_defaults.h
Normal file
27
other/bootstrap_daemon/src/config_defaults.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Default config options for when they are missing in the config file.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_DEFAULTS_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_DEFAULTS_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#define DEFAULT_PID_FILE_PATH "tox-bootstrapd.pid"
|
||||
#define DEFAULT_KEYS_FILE_PATH "tox-bootstrapd.keys"
|
||||
#define DEFAULT_PORT 33445
|
||||
#define DEFAULT_ENABLE_IPV6 1 // 1 - true, 0 - false
|
||||
#define DEFAULT_ENABLE_IPV4_FALLBACK 1 // 1 - true, 0 - false
|
||||
#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false
|
||||
#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false
|
||||
#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly
|
||||
#define DEFAULT_TCP_RELAY_PORTS_COUNT 3
|
||||
#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false
|
||||
#define DEFAULT_MOTD DAEMON_NAME
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_DEFAULTS_H
|
44
other/bootstrap_daemon/src/global.h
Normal file
44
other/bootstrap_daemon/src/global.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Globally used defines.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
||||
|
||||
#include "../../../toxcore/tox.h"
|
||||
|
||||
#define DAEMON_NAME "tox-bootstrapd"
|
||||
|
||||
#define DAEMON_VERSION_MAJOR TOX_VERSION_MAJOR
|
||||
#define DAEMON_VERSION_MINOR TOX_VERSION_MINOR
|
||||
#define DAEMON_VERSION_PATCH TOX_VERSION_PATCH
|
||||
|
||||
// Make sure versions are within the limit
|
||||
#define VERSION_IS_OK(NUM) ( NUM >= 0 && NUM <= 999 )
|
||||
#if !VERSION_IS_OK(DAEMON_VERSION_MAJOR) || !VERSION_IS_OK(DAEMON_VERSION_MINOR) || !VERSION_IS_OK(DAEMON_VERSION_PATCH)
|
||||
#error "At least one of major, minor or patch parts of the version is out of bounds of [0, 999]. Current version: " DAEMON_VERSION_MAJOR "." DAEMON_VERSION_MINOR "." DAEMON_VERSION_PATCH
|
||||
#endif
|
||||
#undef VERSION_IS_OK
|
||||
|
||||
// New version scheme of 1AAABBBCCC, where A B and C are major, minor and patch
|
||||
// versions of toxcore. The leading 1 is there just to keep the leading zeros,
|
||||
// so that it would be easier to read the version when printed as a number.
|
||||
// The version is in a visual decimal format rather than in any other format,
|
||||
// because the original version was using a similar format, it was using
|
||||
// YYYYMMDDVV date-based format for the version, with VV being an incremental
|
||||
// counter in case more than one version was released at that day. Due to this
|
||||
// some tools started showing the version to users as a plain number, rather
|
||||
// than some binary format that needs to be parsed before being shown to users
|
||||
// so we decided to keep this display format compatibility and adopted this
|
||||
// weird scheme with a leading 1.
|
||||
#define DAEMON_VERSION_NUMBER (1000000000UL + DAEMON_VERSION_MAJOR*1000000UL + DAEMON_VERSION_MINOR*1000UL + DAEMON_VERSION_PATCH*1UL)
|
||||
|
||||
#define MIN_ALLOWED_PORT 1
|
||||
#define MAX_ALLOWED_PORT 65535
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_GLOBAL_H
|
82
other/bootstrap_daemon/src/log.c
Normal file
82
other/bootstrap_daemon/src/log.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Logging utility with support of multiple logging backends.
|
||||
*/
|
||||
#include "log.h"
|
||||
#include "log_backend_stdout.h"
|
||||
#include "log_backend_syslog.h"
|
||||
|
||||
#define INVALID_BACKEND ((LOG_BACKEND)-1u)
|
||||
static LOG_BACKEND current_backend = INVALID_BACKEND;
|
||||
|
||||
bool log_open(LOG_BACKEND backend)
|
||||
{
|
||||
if (current_backend != INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_backend = backend;
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
// nothing to do here
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_open();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool log_close(void)
|
||||
{
|
||||
if (current_backend == INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
// nothing to do here
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_close();
|
||||
break;
|
||||
}
|
||||
|
||||
current_backend = INVALID_BACKEND;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool log_write(LOG_LEVEL level, const char *format, ...)
|
||||
{
|
||||
if (current_backend == INVALID_BACKEND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
switch (current_backend) {
|
||||
case LOG_BACKEND_STDOUT:
|
||||
log_backend_stdout_write(level, format, args);
|
||||
break;
|
||||
|
||||
case LOG_BACKEND_SYSLOG:
|
||||
log_backend_syslog_write(level, format, args);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return true;
|
||||
}
|
51
other/bootstrap_daemon/src/log.h
Normal file
51
other/bootstrap_daemon/src/log.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Logging utility with support of multiple logging backends.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
typedef enum LOG_BACKEND {
|
||||
LOG_BACKEND_STDOUT,
|
||||
LOG_BACKEND_SYSLOG
|
||||
} LOG_BACKEND;
|
||||
|
||||
typedef enum LOG_LEVEL {
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_WARNING,
|
||||
LOG_LEVEL_ERROR
|
||||
} LOG_LEVEL;
|
||||
|
||||
/**
|
||||
* Initializes logger.
|
||||
* @param backend Specifies which backend to use.
|
||||
* @return true on success, false if log is already opened.
|
||||
*/
|
||||
bool log_open(LOG_BACKEND backend);
|
||||
|
||||
/**
|
||||
* Releases all used resources by the logger.
|
||||
* @return true on success, false if log is already closed.
|
||||
*/
|
||||
bool log_close(void);
|
||||
|
||||
/**
|
||||
* Writes a message to the log.
|
||||
* @param level Log level to use.
|
||||
* @param format printf-like format string.
|
||||
* @param ... Zero or more arguments, similar to printf function.
|
||||
* @return true on success, false if log is closed.
|
||||
*/
|
||||
bool log_write(LOG_LEVEL level, const char *format, ...) GNU_PRINTF(2, 3);
|
||||
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H
|
32
other/bootstrap_daemon/src/log_backend_stdout.c
Normal file
32
other/bootstrap_daemon/src/log_backend_stdout.c
Normal file
@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Stdout logging backend.
|
||||
*/
|
||||
#include "log_backend_stdout.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static FILE *log_backend_stdout_level(LOG_LEVEL level)
|
||||
{
|
||||
switch (level) {
|
||||
case LOG_LEVEL_INFO:
|
||||
return stdout;
|
||||
|
||||
case LOG_LEVEL_WARNING: // intentional fallthrough
|
||||
case LOG_LEVEL_ERROR:
|
||||
return stderr;
|
||||
}
|
||||
|
||||
return stdout;
|
||||
}
|
||||
|
||||
void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args)
|
||||
{
|
||||
vfprintf(log_backend_stdout_level(level), format, args);
|
||||
fflush(log_backend_stdout_level(level));
|
||||
}
|
19
other/bootstrap_daemon/src/log_backend_stdout.h
Normal file
19
other/bootstrap_daemon/src/log_backend_stdout.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Stdout logging backend.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
|
66
other/bootstrap_daemon/src/log_backend_syslog.c
Normal file
66
other/bootstrap_daemon/src/log_backend_syslog.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Syslog logging backend.
|
||||
*/
|
||||
#include "log_backend_syslog.h"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "../../../toxcore/ccompat.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
void log_backend_syslog_open(void)
|
||||
{
|
||||
openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON);
|
||||
}
|
||||
|
||||
void log_backend_syslog_close(void)
|
||||
{
|
||||
closelog();
|
||||
}
|
||||
|
||||
static int log_backend_syslog_level(LOG_LEVEL level)
|
||||
{
|
||||
switch (level) {
|
||||
case LOG_LEVEL_INFO:
|
||||
return LOG_INFO;
|
||||
|
||||
case LOG_LEVEL_WARNING:
|
||||
return LOG_WARNING;
|
||||
|
||||
case LOG_LEVEL_ERROR:
|
||||
return LOG_ERR;
|
||||
}
|
||||
|
||||
return LOG_INFO;
|
||||
}
|
||||
|
||||
void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args)
|
||||
{
|
||||
va_list args2;
|
||||
|
||||
va_copy(args2, args);
|
||||
int size = vsnprintf(nullptr, 0, format, args2);
|
||||
va_end(args2);
|
||||
|
||||
assert(size >= 0);
|
||||
|
||||
if (size < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf = (char *)malloc(size + 1);
|
||||
vsnprintf(buf, size + 1, format, args);
|
||||
|
||||
syslog(log_backend_syslog_level(level), "%s", buf);
|
||||
free(buf);
|
||||
}
|
21
other/bootstrap_daemon/src/log_backend_syslog.h
Normal file
21
other/bootstrap_daemon/src/log_backend_syslog.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2015-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Syslog logging backend.
|
||||
*/
|
||||
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
||||
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void log_backend_syslog_open(void);
|
||||
void log_backend_syslog_close(void);
|
||||
void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);
|
||||
|
||||
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
|
624
other/bootstrap_daemon/src/tox-bootstrapd.c
Normal file
624
other/bootstrap_daemon/src/tox-bootstrapd.c
Normal file
@ -0,0 +1,624 @@
|
||||
/* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* Copyright © 2016-2018 The TokTok team.
|
||||
* Copyright © 2014-2016 Tox project.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Tox DHT bootstrap daemon.
|
||||
* Main file.
|
||||
*/
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
// system provided
|
||||
#include <signal.h> // system header, rather than C, because we need it for POSIX sigaction(2)
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// C
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// toxcore
|
||||
#include "../../../toxcore/tox.h"
|
||||
#include "../../../toxcore/LAN_discovery.h"
|
||||
#include "../../../toxcore/TCP_server.h"
|
||||
#include "../../../toxcore/announce.h"
|
||||
#include "../../../toxcore/group_onion_announce.h"
|
||||
#include "../../../toxcore/logger.h"
|
||||
#include "../../../toxcore/mono_time.h"
|
||||
#include "../../../toxcore/onion_announce.h"
|
||||
#include "../../../toxcore/util.h"
|
||||
|
||||
// misc
|
||||
#include "../../bootstrap_node_packets.h"
|
||||
|
||||
#include "command_line_arguments.h"
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
static void sleep_milliseconds(uint32_t ms)
|
||||
{
|
||||
struct timespec req;
|
||||
req.tv_sec = ms / 1000;
|
||||
req.tv_nsec = (long)ms % 1000 * 1000 * 1000;
|
||||
nanosleep(&req, nullptr);
|
||||
}
|
||||
|
||||
// Uses the already existing key or creates one if it didn't exist
|
||||
//
|
||||
// returns 1 on success
|
||||
// 0 on failure - no keys were read or stored
|
||||
|
||||
static int manage_keys(DHT *dht, char *keys_file_path)
|
||||
{
|
||||
enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
|
||||
uint8_t keys[KEYS_SIZE];
|
||||
FILE *keys_file;
|
||||
|
||||
// Check if file exits, proceed to open and load keys
|
||||
keys_file = fopen(keys_file_path, "rb");
|
||||
|
||||
if (keys_file != nullptr) {
|
||||
const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
|
||||
|
||||
if (read_size != KEYS_SIZE) {
|
||||
fclose(keys_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dht_set_self_public_key(dht, keys);
|
||||
dht_set_self_secret_key(dht, keys + CRYPTO_PUBLIC_KEY_SIZE);
|
||||
} else {
|
||||
// Otherwise save new keys
|
||||
memcpy(keys, dht_get_self_public_key(dht), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, dht_get_self_secret_key(dht), CRYPTO_SECRET_KEY_SIZE);
|
||||
|
||||
keys_file = fopen(keys_file_path, "wb");
|
||||
|
||||
if (!keys_file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
|
||||
|
||||
if (write_size != KEYS_SIZE) {
|
||||
fclose(keys_file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(keys_file);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Prints public key
|
||||
|
||||
static void print_public_key(const uint8_t *public_key)
|
||||
{
|
||||
char buffer[2 * CRYPTO_PUBLIC_KEY_SIZE + 1];
|
||||
int index = 0;
|
||||
|
||||
for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
|
||||
index += snprintf(buffer + index, sizeof(buffer) - index, "%02X", public_key[i]);
|
||||
}
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Public Key: %s\n", buffer);
|
||||
}
|
||||
|
||||
// Demonizes the process, appending PID to the PID file and closing file descriptors based on log backend
|
||||
// Terminates the application if the daemonization fails.
|
||||
|
||||
static void daemonize(LOG_BACKEND log_backend, char *pid_file_path)
|
||||
{
|
||||
// Check if the PID file exists
|
||||
FILE *pid_file;
|
||||
|
||||
if ((pid_file = fopen(pid_file_path, "r"))) {
|
||||
log_write(LOG_LEVEL_WARNING, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path);
|
||||
fclose(pid_file);
|
||||
}
|
||||
|
||||
// Open the PID file for writing
|
||||
pid_file = fopen(pid_file_path, "a+");
|
||||
|
||||
if (pid_file == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Fork off from the parent process
|
||||
const pid_t pid = fork();
|
||||
|
||||
if (pid > 0) {
|
||||
fprintf(pid_file, "%d", pid);
|
||||
fclose(pid_file);
|
||||
log_write(LOG_LEVEL_INFO, "Forked successfully: PID: %d.\n", pid);
|
||||
exit(0);
|
||||
} else {
|
||||
fclose(pid_file);
|
||||
}
|
||||
|
||||
if (pid < 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "Forking failed. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Create a new SID for the child process
|
||||
if (setsid() < 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "SID creation failure. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// Change the current working directory
|
||||
if ((chdir("/")) < 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Go quiet
|
||||
if (log_backend != LOG_BACKEND_STDOUT) {
|
||||
close(STDOUT_FILENO);
|
||||
close(STDIN_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
}
|
||||
|
||||
// Logs toxcore logger message using our logger facility
|
||||
|
||||
static void toxcore_logger_callback(void *context, Logger_Level level, const char *file, int line,
|
||||
const char *func, const char *message, void *userdata)
|
||||
{
|
||||
LOG_LEVEL log_level;
|
||||
|
||||
switch (level) {
|
||||
case LOGGER_LEVEL_TRACE:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_DEBUG:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_INFO:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_WARNING:
|
||||
log_level = LOG_LEVEL_WARNING;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_ERROR:
|
||||
log_level = LOG_LEVEL_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
log_write(log_level, "%s:%d(%s) %s\n", file, line, func, message);
|
||||
}
|
||||
|
||||
static volatile sig_atomic_t caught_signal = 0;
|
||||
|
||||
static void handle_signal(int signum)
|
||||
{
|
||||
caught_signal = signum;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
umask(077);
|
||||
char *cfg_file_path = nullptr;
|
||||
LOG_BACKEND log_backend;
|
||||
bool run_in_foreground;
|
||||
|
||||
// choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal
|
||||
log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG;
|
||||
|
||||
log_open(log_backend);
|
||||
handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground);
|
||||
log_close();
|
||||
|
||||
log_open(log_backend);
|
||||
|
||||
log_write(LOG_LEVEL_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER);
|
||||
|
||||
char *pid_file_path = nullptr;
|
||||
char *keys_file_path = nullptr;
|
||||
int start_port;
|
||||
int enable_ipv6;
|
||||
int enable_ipv4_fallback;
|
||||
int enable_lan_discovery;
|
||||
int enable_tcp_relay;
|
||||
uint16_t *tcp_relay_ports = nullptr;
|
||||
int tcp_relay_port_count;
|
||||
int enable_motd;
|
||||
char *motd = nullptr;
|
||||
|
||||
if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &start_port, &enable_ipv6, &enable_ipv4_fallback,
|
||||
&enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) {
|
||||
log_write(LOG_LEVEL_INFO, "General config read successfully\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (start_port < MIN_ALLOWED_PORT || start_port > MAX_ALLOWED_PORT) {
|
||||
log_write(LOG_LEVEL_ERROR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", start_port, MIN_ALLOWED_PORT,
|
||||
MAX_ALLOWED_PORT);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
free(pid_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!run_in_foreground) {
|
||||
daemonize(log_backend, pid_file_path);
|
||||
}
|
||||
|
||||
free(pid_file_path);
|
||||
|
||||
IP ip;
|
||||
ip_init(&ip, enable_ipv6);
|
||||
|
||||
Logger *logger = logger_new();
|
||||
|
||||
if (MIN_LOGGER_LEVEL == LOGGER_LEVEL_TRACE || MIN_LOGGER_LEVEL == LOGGER_LEVEL_DEBUG) {
|
||||
logger_callback_log(logger, toxcore_logger_callback, nullptr, nullptr);
|
||||
}
|
||||
|
||||
const uint16_t end_port = start_port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM);
|
||||
const Network *ns = system_network();
|
||||
Networking_Core *net = new_networking_ex(logger, ns, &ip, start_port, end_port, nullptr);
|
||||
|
||||
if (net == nullptr) {
|
||||
if (enable_ipv6 && enable_ipv4_fallback) {
|
||||
log_write(LOG_LEVEL_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n");
|
||||
enable_ipv6 = 0;
|
||||
ip_init(&ip, enable_ipv6);
|
||||
net = new_networking_ex(logger, ns, &ip, start_port, end_port, nullptr);
|
||||
|
||||
if (net == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't fallback to IPv4. Exiting.\n");
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize networking. Exiting.\n");
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Mono_Time *const mono_time = mono_time_new(nullptr, nullptr);
|
||||
|
||||
if (mono_time == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize monotonic timer. Exiting.\n");
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_time_update(mono_time);
|
||||
|
||||
const Random *rng = system_random();
|
||||
DHT *const dht = new_dht(logger, rng, ns, mono_time, net, true, enable_lan_discovery);
|
||||
|
||||
if (dht == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n");
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Forwarding *forwarding = new_forwarding(logger, rng, mono_time, dht);
|
||||
|
||||
if (forwarding == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize forwarding. Exiting.\n");
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Announcements *announce = new_announcements(logger, rng, mono_time, forwarding);
|
||||
|
||||
if (announce == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize DHT announcements. Exiting.\n");
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
GC_Announces_List *group_announce = new_gca_list();
|
||||
|
||||
if (group_announce == nullptr) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize group announces. Exiting.\n");
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Onion *onion = new_onion(logger, mono_time, rng, dht);
|
||||
|
||||
if (!onion) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n");
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Onion_Announce *onion_a = new_onion_announce(logger, rng, mono_time, dht);
|
||||
|
||||
if (!onion_a) {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion Announce. Exiting.\n");
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gca_onion_init(group_announce, onion_a);
|
||||
|
||||
if (enable_motd) {
|
||||
if (bootstrap_set_callbacks(dht_get_net(dht), DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) {
|
||||
log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n");
|
||||
free(motd);
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't set MOTD: %s. Exiting.\n", motd);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(motd);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (manage_keys(dht, keys_file_path)) {
|
||||
log_write(LOG_LEVEL_INFO, "Keys are managed successfully.\n");
|
||||
free(keys_file_path);
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read/write: %s. Exiting.\n", keys_file_path);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(tcp_relay_ports);
|
||||
free(keys_file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
TCP_Server *tcp_server = nullptr;
|
||||
|
||||
if (enable_tcp_relay) {
|
||||
if (tcp_relay_port_count == 0) {
|
||||
log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n");
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_onion(onion);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
free(tcp_relay_ports);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tcp_server = new_TCP_server(logger, rng, ns, enable_ipv6, tcp_relay_port_count, tcp_relay_ports,
|
||||
dht_get_self_secret_key(dht), onion, forwarding);
|
||||
|
||||
free(tcp_relay_ports);
|
||||
|
||||
if (tcp_server != nullptr) {
|
||||
log_write(LOG_LEVEL_INFO, "Initialized Tox TCP server successfully.\n");
|
||||
|
||||
struct rlimit limit;
|
||||
|
||||
const rlim_t rlim_suggested = 32768;
|
||||
const rlim_t rlim_min = 4096;
|
||||
|
||||
assert(rlim_suggested >= rlim_min);
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &limit)) {
|
||||
if (limit.rlim_cur < limit.rlim_max) {
|
||||
// Some systems have a hard limit of over 1000000 open file descriptors, so let's cap it at something reasonable
|
||||
// so that we don't set it to an unreasonably high number.
|
||||
limit.rlim_cur = limit.rlim_max > rlim_suggested ? rlim_suggested : limit.rlim_max;
|
||||
setrlimit(RLIMIT_NOFILE, &limit);
|
||||
}
|
||||
}
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &limit) && limit.rlim_cur < rlim_min) {
|
||||
log_write(LOG_LEVEL_WARNING,
|
||||
"Current limit on the number of files this process can open (%ju) is rather low for the proper functioning of the TCP server. "
|
||||
"Consider raising the limit to at least %ju or the recommended %ju. "
|
||||
"Continuing using the current limit (%ju).\n",
|
||||
(uintmax_t)limit.rlim_cur, (uintmax_t)rlim_min, (uintmax_t)rlim_suggested, (uintmax_t)limit.rlim_cur);
|
||||
}
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox TCP server. Exiting.\n");
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) {
|
||||
log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n");
|
||||
} else {
|
||||
log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path);
|
||||
kill_TCP_server(tcp_server);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_public_key(dht_get_self_public_key(dht));
|
||||
|
||||
uint64_t last_LANdiscovery = 0;
|
||||
const uint16_t net_htons_port = net_htons(start_port);
|
||||
|
||||
int waiting_for_dht_connection = 1;
|
||||
|
||||
Broadcast_Info *broadcast = nullptr;
|
||||
|
||||
if (enable_lan_discovery) {
|
||||
broadcast = lan_discovery_init(ns);
|
||||
log_write(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n");
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_handler = handle_signal;
|
||||
|
||||
// Try to restart interrupted system calls if they are restartable
|
||||
sa.sa_flags = SA_RESTART;
|
||||
|
||||
// Prevent the signal handler from being called again before it returns
|
||||
sigfillset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(SIGINT, &sa, nullptr)) {
|
||||
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGINT. Continuing without the signal handler set.\n");
|
||||
}
|
||||
|
||||
if (sigaction(SIGTERM, &sa, nullptr)) {
|
||||
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGTERM. Continuing without the signal handler set.\n");
|
||||
}
|
||||
|
||||
while (!caught_signal) {
|
||||
mono_time_update(mono_time);
|
||||
|
||||
do_dht(dht);
|
||||
|
||||
if (enable_lan_discovery && mono_time_is_timeout(mono_time, last_LANdiscovery, LAN_DISCOVERY_INTERVAL)) {
|
||||
lan_discovery_send(dht_get_net(dht), broadcast, dht_get_self_public_key(dht), net_htons_port);
|
||||
last_LANdiscovery = mono_time_get(mono_time);
|
||||
}
|
||||
|
||||
if (enable_tcp_relay) {
|
||||
do_TCP_server(tcp_server, mono_time);
|
||||
}
|
||||
|
||||
networking_poll(dht_get_net(dht), nullptr);
|
||||
|
||||
if (waiting_for_dht_connection && dht_isconnected(dht)) {
|
||||
log_write(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n");
|
||||
waiting_for_dht_connection = 0;
|
||||
}
|
||||
|
||||
sleep_milliseconds(30);
|
||||
}
|
||||
|
||||
switch (caught_signal) {
|
||||
case SIGINT:
|
||||
log_write(LOG_LEVEL_INFO, "Received SIGINT (%d) signal. Exiting.\n", SIGINT);
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
log_write(LOG_LEVEL_INFO, "Received SIGTERM (%d) signal. Exiting.\n", SIGTERM);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_write(LOG_LEVEL_INFO, "Received (%d) signal. Exiting.\n", caught_signal);
|
||||
}
|
||||
|
||||
lan_discovery_kill(broadcast);
|
||||
kill_TCP_server(tcp_server);
|
||||
kill_onion_announce(onion_a);
|
||||
kill_gca(group_announce);
|
||||
kill_onion(onion);
|
||||
kill_announcements(announce);
|
||||
kill_forwarding(forwarding);
|
||||
kill_dht(dht);
|
||||
mono_time_free(mono_time);
|
||||
kill_networking(net);
|
||||
logger_kill(logger);
|
||||
|
||||
return 0;
|
||||
}
|
65
other/bootstrap_daemon/tox-bootstrapd.conf
Normal file
65
other/bootstrap_daemon/tox-bootstrapd.conf
Normal file
@ -0,0 +1,65 @@
|
||||
// Tox DHT bootstrap daemon configuration file.
|
||||
|
||||
// Listening port (UDP).
|
||||
port = 33445
|
||||
|
||||
// A key file is like a password, so keep it where no one can read it.
|
||||
// If there is no key file, a new one will be generated.
|
||||
// The daemon should have permission to read/write it.
|
||||
keys_file_path = "/var/lib/tox-bootstrapd/keys"
|
||||
|
||||
// The PID file written to by the daemon.
|
||||
// Make sure that the user that daemon runs as has permissions to write to the
|
||||
// PID file.
|
||||
pid_file_path = "/var/run/tox-bootstrapd/tox-bootstrapd.pid"
|
||||
|
||||
// Enable IPv6.
|
||||
enable_ipv6 = true
|
||||
|
||||
// Fallback to IPv4 in case IPv6 fails.
|
||||
enable_ipv4_fallback = true
|
||||
|
||||
// Automatically bootstrap with nodes on local area network.
|
||||
enable_lan_discovery = true
|
||||
|
||||
enable_tcp_relay = true
|
||||
|
||||
// While Tox uses 33445 port by default, 443 (https) and 3389 (rdp) ports are very
|
||||
// common among nodes, so it's encouraged to keep them in place.
|
||||
tcp_relay_ports = [443, 3389, 33445]
|
||||
|
||||
// Reply to MOTD (Message Of The Day) requests.
|
||||
enable_motd = true
|
||||
|
||||
// Just a message that is sent when someone requests MOTD.
|
||||
// Put anything you want, but note that it will be trimmed to fit into 255 bytes.
|
||||
motd = "tox-bootstrapd"
|
||||
|
||||
// Any number of nodes the daemon will bootstrap itself off.
|
||||
//
|
||||
// Remember to replace the provided example with your own node list.
|
||||
// There is a maintained list of bootstrap nodes on Tox's wiki, if you need it
|
||||
// (https://wiki.tox.chat/doku.php?id=users:nodes).
|
||||
//
|
||||
// You may leave the list empty or remove "bootstrap_nodes" completely,
|
||||
// in both cases this will be interpreted as if you don't want to bootstrap
|
||||
// from anyone.
|
||||
//
|
||||
// address = any IPv4 or IPv6 address and also any US-ASCII domain name.
|
||||
bootstrap_nodes = (
|
||||
{ // Example Node 1 (IPv4)
|
||||
address = "127.0.0.1"
|
||||
port = 33445
|
||||
public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854"
|
||||
},
|
||||
{ // Example Node 2 (IPv6)
|
||||
address = "::1/128"
|
||||
port = 33445
|
||||
public_key = "3E78BACF0F84235B30054B54898F56793E1DEF8BD46B1038B9D822E8460FAB67"
|
||||
},
|
||||
{ // Example Node 3 (US-ASCII domain name)
|
||||
address = "example.org"
|
||||
port = 33445
|
||||
public_key = "8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858"
|
||||
}
|
||||
)
|
20
other/bootstrap_daemon/tox-bootstrapd.service
Normal file
20
other/bootstrap_daemon/tox-bootstrapd.service
Normal file
@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Description=Tox DHT Bootstrap Daemon
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
RuntimeDirectory=tox-bootstrapd
|
||||
RuntimeDirectoryMode=750
|
||||
PIDFile=/var/run/tox-bootstrapd/tox-bootstrapd.pid
|
||||
WorkingDirectory=/var/lib/tox-bootstrapd
|
||||
ExecStart=/usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf
|
||||
User=tox-bootstrapd
|
||||
Group=tox-bootstrapd
|
||||
# TCP Server needs to be able to have lots of TCP sockets open.
|
||||
LimitNOFILE=32768
|
||||
# Uncomment to allow binding to ports < 1024, e.g. 443 (HTTPS) for TCP Server
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
147
other/bootstrap_daemon/tox-bootstrapd.sh
Normal file
147
other/bootstrap_daemon/tox-bootstrapd.sh
Normal file
@ -0,0 +1,147 @@
|
||||
#! /bin/bash
|
||||
### BEGIN INIT INFO
|
||||
# Provides: tox-bootstrapd
|
||||
# Required-Start: $remote_fs $syslog
|
||||
# Required-Stop: $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Starts the Tox DHT bootstrapping server daemon
|
||||
# Description: Starts the Tox DHT bootstrapping server daemon
|
||||
### END INIT INFO
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="Tox DHT bootstrap daemon"
|
||||
NAME=tox-bootstrapd
|
||||
DAEMON=/usr/local/bin/$NAME
|
||||
CFGFILE=/etc/$NAME.conf
|
||||
DAEMON_ARGS="--config $CFGFILE"
|
||||
PIDDIR=/var/run/$NAME
|
||||
PIDFILE=$PIDDIR/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
USER=tox-bootstrapd
|
||||
GROUP=tox-bootstrapd
|
||||
|
||||
# Set ulimit -n based on number of fds available.
|
||||
# This check is borrowed from Debian's tor package, with a few modifications.
|
||||
if [ -r /proc/sys/fs/file-max ]; then
|
||||
system_max=$(cat /proc/sys/fs/file-max)
|
||||
if [ "$system_max" -gt "80000" ] ; then
|
||||
MAX_FILEDESCRIPTORS=32768
|
||||
elif [ "$system_max" -gt "40000" ] ; then
|
||||
MAX_FILEDESCRIPTORS=16384
|
||||
elif [ "$system_max" -gt "20000" ] ; then
|
||||
MAX_FILEDESCRIPTORS=8192
|
||||
elif [ "$system_max" -gt "10000" ] ; then
|
||||
MAX_FILEDESCRIPTORS=4096
|
||||
else
|
||||
MAX_FILEDESCRIPTORS=1024
|
||||
cat << EOF
|
||||
|
||||
Warning: Your system has very few file descriptors available in total.
|
||||
|
||||
Maybe you should try raising that by adding 'fs.file-max=100000' to your
|
||||
/etc/sysctl.conf file. Feel free to pick any number that you deem appropriate.
|
||||
Then run 'sysctl -p'. See /proc/sys/fs/file-max for the current value, and
|
||||
file-nr in the same directory for how many of those are used at the moment.
|
||||
|
||||
EOF
|
||||
fi
|
||||
else
|
||||
MAX_FILEDESCRIPTORS=32768
|
||||
fi
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
if [ ! -d $PIDDIR ]
|
||||
then
|
||||
mkdir $PIDDIR
|
||||
fi
|
||||
chown $USER:$GROUP $PIDDIR
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test --chuid $USER > /dev/null || return 1
|
||||
# TCP Server needs to be able to have lots of TCP sockets open.
|
||||
ulimit -n $MAX_FILEDESCRIPTORS
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid $USER -- $DAEMON_ARGS || return 2
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry 5 --pidfile $PIDFILE --name $NAME --chuid $USER
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc -p $PIDFILE "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
|
||||
restart)
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
exit 0
|
29
other/bootstrap_daemon/websocket/Dockerfile
Normal file
29
other/bootstrap_daemon/websocket/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
||||
# Stage 1 - Compile websockify.
|
||||
FROM toxchat/bootstrap-node:latest AS tox
|
||||
FROM golang:1.17-alpine AS websockify
|
||||
|
||||
COPY websockify /work/websockify
|
||||
RUN cd /work/websockify && go mod download github.com/gorilla/websocket && go install
|
||||
|
||||
# Stage 2 - Create the run-time image with bootstrap daemon and websockify.
|
||||
FROM alpine:latest
|
||||
|
||||
RUN addgroup -S tox && adduser -SDH -G tox tox
|
||||
|
||||
COPY --from=websockify /go/bin/websockify /usr/local/bin/
|
||||
COPY --from=tox /usr/local /usr/local/
|
||||
COPY --from=tox /etc/tox-bootstrapd.conf /etc/
|
||||
COPY entrypoint.sh /
|
||||
|
||||
RUN mkdir -p /var/lib/tox-bootstrapd/ /var/run/tox-bootstrapd/ \
|
||||
&& chown tox:tox /var/lib/tox-bootstrapd/ /var/run/tox-bootstrapd/
|
||||
# Public Key: 122837CCDD474DD1183A83152164D51427044B3EAAA52ED683F6BA602568673B
|
||||
COPY keys /var/lib/tox-bootstrapd/
|
||||
USER tox
|
||||
|
||||
# Use this to generate a keys file:
|
||||
#RUN /usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf --log-backend stdout \
|
||||
# && sleep 1
|
||||
|
||||
WORKDIR /web
|
||||
CMD ["/entrypoint.sh"]
|
6
other/bootstrap_daemon/websocket/entrypoint.sh
Executable file
6
other/bootstrap_daemon/websocket/entrypoint.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eux
|
||||
|
||||
/usr/local/bin/tox-bootstrapd --config /etc/tox-bootstrapd.conf --log-backend stdout
|
||||
/usr/local/bin/websockify -l "0.0.0.0:$PORT" -t 127.0.0.1:33445
|
1
other/bootstrap_daemon/websocket/keys
Normal file
1
other/bootstrap_daemon/websocket/keys
Normal file
@ -0,0 +1 @@
|
||||
(7<><37>GM<47>:<3A>!d<>'K><3E><>.փ<><D683>`%hg;<3B>G<EFBFBD><47>Y<>:<3A>Zy5<79><35>S<EFBFBD>$<24>|Cڠ<43>Ǹ<EFBFBD>2<10> <09>t
|
17
other/bootstrap_daemon/websocket/websockify/BUILD.bazel
Normal file
17
other/bootstrap_daemon/websocket/websockify/BUILD.bazel
Normal file
@ -0,0 +1,17 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
|
||||
package(features = ["-layering_check"])
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["websockify.go"],
|
||||
importpath = "github.com/TokTok/c-toxcore/other/bootstrap_daemon/websocket/websockify",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["@com_github_gorilla_websocket//:go_default_library"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "websockify",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
7
other/bootstrap_daemon/websocket/websockify/go.mod
Normal file
7
other/bootstrap_daemon/websocket/websockify/go.mod
Normal file
@ -0,0 +1,7 @@
|
||||
module github.com/TokTok/c-toxcore/other/bootstrap_daemon/websocket/websockify
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket master
|
||||
)
|
111
other/bootstrap_daemon/websocket/websockify/websockify.go
Normal file
111
other/bootstrap_daemon/websocket/websockify/websockify.go
Normal file
@ -0,0 +1,111 @@
|
||||
// A Go version WebSocket to TCP socket proxy
|
||||
//
|
||||
// This is a heavily modified version of this file:
|
||||
// https://github.com/novnc/websockify-other/blob/master/golang/websockify.go
|
||||
//
|
||||
// Changes include:
|
||||
// - Fix infinite loop on error.
|
||||
// - Proper logging.
|
||||
// - Proper error handling in general.
|
||||
// - Support both websocket and regular GET requests on /.
|
||||
//
|
||||
// Copyright 2022 The TokTok team.
|
||||
// Copyright 2021 Michael.liu.
|
||||
// See LICENSE for licensing conditions.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
sourceAddr = flag.String("l", "127.0.0.1:8080", "http service address")
|
||||
targetAddr = flag.String("t", "127.0.0.1:5900", "tcp service address")
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
// Should be enough to fit any Tox TCP packets.
|
||||
ReadBufferSize: 2048,
|
||||
WriteBufferSize: 2048,
|
||||
Subprotocols: []string{"binary"},
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
func forwardTCP(wsconn *websocket.Conn, conn net.Conn) {
|
||||
var tcpbuffer [2048]byte
|
||||
defer wsconn.Close()
|
||||
defer conn.Close()
|
||||
for {
|
||||
n, err := conn.Read(tcpbuffer[0:])
|
||||
if err != nil {
|
||||
log.Println("TCP READ :", err)
|
||||
break
|
||||
}
|
||||
log.Println("TCP READ :", n, hex.EncodeToString(tcpbuffer[0:n]))
|
||||
|
||||
if err := wsconn.WriteMessage(websocket.BinaryMessage, tcpbuffer[0:n]); err != nil {
|
||||
log.Println("WS WRITE :", err)
|
||||
break
|
||||
}
|
||||
log.Println("WS WRITE :", n)
|
||||
}
|
||||
}
|
||||
|
||||
func forwardWeb(wsconn *websocket.Conn, conn net.Conn) {
|
||||
defer wsconn.Close()
|
||||
defer conn.Close()
|
||||
for {
|
||||
_, buffer, err := wsconn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("WS READ :", err)
|
||||
break
|
||||
}
|
||||
log.Println("WS READ :", len(buffer), hex.EncodeToString(buffer))
|
||||
|
||||
m, err := conn.Write(buffer)
|
||||
if err != nil {
|
||||
log.Println("TCP WRITE:", err)
|
||||
break
|
||||
}
|
||||
log.Println("TCP WRITE:", m)
|
||||
}
|
||||
}
|
||||
|
||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println("upgrade:", err)
|
||||
return
|
||||
}
|
||||
vnc, err := net.Dial("tcp", *targetAddr)
|
||||
if err != nil {
|
||||
log.Println("dial:", err)
|
||||
return
|
||||
}
|
||||
go forwardTCP(ws, vnc)
|
||||
go forwardWeb(ws, vnc)
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.Println("Starting up websockify endpoint")
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Upgrade") == "websocket" {
|
||||
serveWs(w, r)
|
||||
} else {
|
||||
http.ServeFile(w, r, r.URL.Path[1:])
|
||||
}
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(*sourceAddr, nil))
|
||||
}
|
Reference in New Issue
Block a user