summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2017-12-20 23:44:35 +0300
committeraunsane <aunsane@gmail.com>2017-12-20 23:46:11 +0300
commite6cb2c87dc119268a75ac6f41645b96400abdd7c (patch)
treef97e4ba7da8715358f13b7189769597bf6d2e75e /libs
parentc8548c468436fc3a2fccc00be9f48e6b7f0a1df2 (diff)
libtox moved to tox folder instead of libs
Diffstat (limited to 'libs')
-rw-r--r--libs/libtox/docs/CHANGELOG.md450
-rw-r--r--libs/libtox/docs/COPYING674
-rw-r--r--libs/libtox/docs/DONATORS7
-rw-r--r--libs/libtox/docs/README.md174
-rw-r--r--libs/libtox/libtox.vcxproj55
-rw-r--r--libs/libtox/libtox.vcxproj.filters293
-rw-r--r--libs/libtox/src/libtox.def155
-rw-r--r--libs/libtox/src/stdafx.cxx2
-rw-r--r--libs/libtox/src/stdafx.h0
-rw-r--r--libs/libtox/src/toxcore/DHT.c2853
-rw-r--r--libs/libtox/src/toxcore/DHT.h448
-rw-r--r--libs/libtox/src/toxcore/LAN_discovery.c410
-rw-r--r--libs/libtox/src/toxcore/LAN_discovery.h52
-rw-r--r--libs/libtox/src/toxcore/Messenger.c3155
-rw-r--r--libs/libtox/src/toxcore/Messenger.h777
-rw-r--r--libs/libtox/src/toxcore/TCP_client.c991
-rw-r--r--libs/libtox/src/toxcore/TCP_client.h167
-rw-r--r--libs/libtox/src/toxcore/TCP_connection.c1491
-rw-r--r--libs/libtox/src/toxcore/TCP_connection.h223
-rw-r--r--libs/libtox/src/toxcore/TCP_server.c1417
-rw-r--r--libs/libtox/src/toxcore/TCP_server.h167
-rw-r--r--libs/libtox/src/toxcore/ccompat.h43
-rw-r--r--libs/libtox/src/toxcore/crypto_core.api.h246
-rw-r--r--libs/libtox/src/toxcore/crypto_core.c287
-rw-r--r--libs/libtox/src/toxcore/crypto_core.h234
-rw-r--r--libs/libtox/src/toxcore/crypto_core_mem.c87
-rw-r--r--libs/libtox/src/toxcore/friend_connection.c937
-rw-r--r--libs/libtox/src/toxcore/friend_connection.h210
-rw-r--r--libs/libtox/src/toxcore/friend_requests.c152
-rw-r--r--libs/libtox/src/toxcore/friend_requests.h76
-rw-r--r--libs/libtox/src/toxcore/group.c2544
-rw-r--r--libs/libtox/src/toxcore/group.h395
-rw-r--r--libs/libtox/src/toxcore/list.c266
-rw-r--r--libs/libtox/src/toxcore/list.h85
-rw-r--r--libs/libtox/src/toxcore/logger.c77
-rw-r--r--libs/libtox/src/toxcore/logger.h80
-rw-r--r--libs/libtox/src/toxcore/net_crypto.c2908
-rw-r--r--libs/libtox/src/toxcore/net_crypto.h428
-rw-r--r--libs/libtox/src/toxcore/network.c1446
-rw-r--r--libs/libtox/src/toxcore/network.h424
-rw-r--r--libs/libtox/src/toxcore/onion.c679
-rw-r--r--libs/libtox/src/toxcore/onion.h165
-rw-r--r--libs/libtox/src/toxcore/onion_announce.c497
-rw-r--r--libs/libtox/src/toxcore/onion_announce.h140
-rw-r--r--libs/libtox/src/toxcore/onion_client.c1771
-rw-r--r--libs/libtox/src/toxcore/onion_client.h302
-rw-r--r--libs/libtox/src/toxcore/ping.c381
-rw-r--r--libs/libtox/src/toxcore/ping.h54
-rw-r--r--libs/libtox/src/toxcore/ping_array.c172
-rw-r--r--libs/libtox/src/toxcore/ping_array.h76
-rw-r--r--libs/libtox/src/toxcore/tox.api.h2583
-rw-r--r--libs/libtox/src/toxcore/tox.c1551
-rw-r--r--libs/libtox/src/toxcore/tox.h2947
-rw-r--r--libs/libtox/src/toxcore/tox_api.c97
-rw-r--r--libs/libtox/src/toxcore/util.c194
-rw-r--r--libs/libtox/src/toxcore/util.h64
-rw-r--r--libs/libtox/src/toxdns/Makefile.inc35
-rw-r--r--libs/libtox/src/toxdns/toxdns.c243
-rw-r--r--libs/libtox/src/toxdns/toxdns.h96
-rw-r--r--libs/libtox/src/toxencryptsave/Makefile.inc55
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h92
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c257
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h93
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h38
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c309
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt14
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c97
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h52
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c211
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c140
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h33
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c107
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c398
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h153
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c78
-rw-r--r--libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h40
-rw-r--r--libs/libtox/src/toxencryptsave/defines.h2
-rw-r--r--libs/libtox/src/toxencryptsave/toxencryptsave.api.h327
-rw-r--r--libs/libtox/src/toxencryptsave/toxencryptsave.c338
-rw-r--r--libs/libtox/src/toxencryptsave/toxencryptsave.h388
80 files changed, 0 insertions, 40155 deletions
diff --git a/libs/libtox/docs/CHANGELOG.md b/libs/libtox/docs/CHANGELOG.md
deleted file mode 100644
index e3275a16df..0000000000
--- a/libs/libtox/docs/CHANGELOG.md
+++ /dev/null
@@ -1,450 +0,0 @@
-
-
-## v0.1.10
-
-### Merged PRs:
-
-- [#564](https://github.com/TokTok/c-toxcore/pull/564) Fix Windows build
-- [#542](https://github.com/TokTok/c-toxcore/pull/542) Save bandwidth by moderating onion pinging
-
-## v0.1.9
-
-### Merged PRs:
-
-- [#563](https://github.com/TokTok/c-toxcore/pull/563) Release v0.1.9
-- [#561](https://github.com/TokTok/c-toxcore/pull/561) Remove unused variable
-- [#560](https://github.com/TokTok/c-toxcore/pull/560) Fix non-portable zeroing out of doubles
-- [#559](https://github.com/TokTok/c-toxcore/pull/559) Fix theoretical memory leaks
-- [#557](https://github.com/TokTok/c-toxcore/pull/557) Document inverted mutex lock/unlock.
-- [#556](https://github.com/TokTok/c-toxcore/pull/556) Build tests on appveyor, the MSVC build, but don't run them yet.
-- [#555](https://github.com/TokTok/c-toxcore/pull/555) Fold hstox tests into the general linux test.
-- [#554](https://github.com/TokTok/c-toxcore/pull/554) Add a monolith_test that includes all toxcore sources.
-- [#553](https://github.com/TokTok/c-toxcore/pull/553) Factor out strict_abi cmake code into a separate module.
-- [#552](https://github.com/TokTok/c-toxcore/pull/552) Fix formatting and spelling in version-sync script.
-- [#551](https://github.com/TokTok/c-toxcore/pull/551) Forbid undefined symbols in shared libraries.
-- [#546](https://github.com/TokTok/c-toxcore/pull/546) Make variable names in file saving test less cryptic
-- [#539](https://github.com/TokTok/c-toxcore/pull/539) Make OSX test failures fail the Travis CI build.
-- [#537](https://github.com/TokTok/c-toxcore/pull/537) Fix TokTok/c-toxcore#535
-- [#534](https://github.com/TokTok/c-toxcore/pull/534) Fix markdown formatting
-- [#530](https://github.com/TokTok/c-toxcore/pull/530) Implement missing TES constant functions.
-- [#511](https://github.com/TokTok/c-toxcore/pull/511) Save bandwidth by avoiding superfluous Nodes Requests to peers already on the Close List
-- [#506](https://github.com/TokTok/c-toxcore/pull/506) Add test case for title change
-- [#498](https://github.com/TokTok/c-toxcore/pull/498) DHT refactoring
-- [#487](https://github.com/TokTok/c-toxcore/pull/487) Split daemon's logging backends in separate modules
-- [#468](https://github.com/TokTok/c-toxcore/pull/468) Test for memberlist not changing after changing own name
-- [#449](https://github.com/TokTok/c-toxcore/pull/449) Use new encoding of `Maybe` in msgpack results.
-
-### Closed issues:
-
-- [#482](https://github.com/TokTok/c-toxcore/issues/482) CMake can't detect and compile ToxAV on OSX
-
-## v0.1.8
-
-### Merged PRs:
-
-- [#538](https://github.com/TokTok/c-toxcore/pull/538) Reverting tox_loop PR changes
-- [#536](https://github.com/TokTok/c-toxcore/pull/536) Release v0.1.8
-- [#526](https://github.com/TokTok/c-toxcore/pull/526) Add TOX_NOSPAM_SIZE to the public API.
-- [#525](https://github.com/TokTok/c-toxcore/pull/525) Retry autotools tests the same way as cmake tests.
-- [#524](https://github.com/TokTok/c-toxcore/pull/524) Reduce ctest timeout to 2 minutes from 5 minutes.
-- [#512](https://github.com/TokTok/c-toxcore/pull/512) Add test for DHT pack_nodes and unpack_nodes
-- [#504](https://github.com/TokTok/c-toxcore/pull/504) CMake: install bootstrapd if it is built
-- [#488](https://github.com/TokTok/c-toxcore/pull/488) Save compiled Android artifacts after CircleCI builds.
-- [#473](https://github.com/TokTok/c-toxcore/pull/473) Added missing includes: <netinet/in.h> and <sys/socket.h>
-- [#335](https://github.com/TokTok/c-toxcore/pull/335) Implement tox_loop
-
-### Closed issues:
-
-- [#535](https://github.com/TokTok/c-toxcore/issues/535) OS X tests failing
-- [#503](https://github.com/TokTok/c-toxcore/issues/503) Undefined functions: tox_pass_salt_length, tox_pass_key_length, tox_pass_encryption_extra_length
-- [#456](https://github.com/TokTok/c-toxcore/issues/456) Tox.h doesn't expose the size of the nospam.
-- [#411](https://github.com/TokTok/c-toxcore/issues/411) Reduce CTest timeout to 2 minutes
-
-## v0.1.7
-
-### Merged PRs:
-
-- [#523](https://github.com/TokTok/c-toxcore/pull/523) Release v0.1.7
-- [#521](https://github.com/TokTok/c-toxcore/pull/521) Fix appveyor script: install curl from chocolatey.
-- [#510](https://github.com/TokTok/c-toxcore/pull/510) Fix list malloc(0) bug
-- [#509](https://github.com/TokTok/c-toxcore/pull/509) Fix network malloc(0) bug
-- [#497](https://github.com/TokTok/c-toxcore/pull/497) Fix network
-- [#496](https://github.com/TokTok/c-toxcore/pull/496) Fix Travis always succeeding despite tests failing
-- [#491](https://github.com/TokTok/c-toxcore/pull/491) Add crypto_memzero for temp buffer
-- [#490](https://github.com/TokTok/c-toxcore/pull/490) Move c_sleep to helpers.h and misc_tools.h
-- [#486](https://github.com/TokTok/c-toxcore/pull/486) Remove empty line in Messenger.c
-- [#483](https://github.com/TokTok/c-toxcore/pull/483) Make BUILD_TOXAV an option and fail if dependencies are missing
-- [#481](https://github.com/TokTok/c-toxcore/pull/481) Remove dependency on strings.h
-- [#480](https://github.com/TokTok/c-toxcore/pull/480) Use VLA macro
-- [#479](https://github.com/TokTok/c-toxcore/pull/479) Fix pthreads in AppVeyor build
-- [#471](https://github.com/TokTok/c-toxcore/pull/471) Remove statics used in onion comparison functions.
-- [#461](https://github.com/TokTok/c-toxcore/pull/461) Replace part of network functions on platform-independent implementation
-- [#452](https://github.com/TokTok/c-toxcore/pull/452) Add VLA compatibility macro for C89-ish compilers.
-
-### Closed issues:
-
-- [#474](https://github.com/TokTok/c-toxcore/issues/474) TOX_VERSION_PATCH isn't in sync with the version
-
-## v0.1.6
-
-### Merged PRs:
-
-- [#460](https://github.com/TokTok/c-toxcore/pull/460) Release v0.1.6.
-- [#459](https://github.com/TokTok/c-toxcore/pull/459) Add Android build to CI.
-- [#454](https://github.com/TokTok/c-toxcore/pull/454) Add appveyor build for native windows tests.
-- [#448](https://github.com/TokTok/c-toxcore/pull/448) Only retry failed tests on Circle CI instead of all.
-- [#434](https://github.com/TokTok/c-toxcore/pull/434) Replace redundant packet type check in handler with assert.
-- [#432](https://github.com/TokTok/c-toxcore/pull/432) Remove some static variables
-- [#385](https://github.com/TokTok/c-toxcore/pull/385) Add platform-independent Socket and IP implementation
-
-### Closed issues:
-
-- [#415](https://github.com/TokTok/c-toxcore/issues/415) Set up a native windows build on appveyor
-
-## v0.1.5
-
-### Merged PRs:
-
-- [#447](https://github.com/TokTok/c-toxcore/pull/447) Release v0.1.5.
-- [#446](https://github.com/TokTok/c-toxcore/pull/446) Limit number of retries to 3.
-- [#445](https://github.com/TokTok/c-toxcore/pull/445) Make Travis tests slightly more robust by re-running them.
-- [#443](https://github.com/TokTok/c-toxcore/pull/443) Make building `DHT_bootstrap` in cmake optional.
-- [#433](https://github.com/TokTok/c-toxcore/pull/433) Add tutorial and "danger: experimental" banner to README.
-- [#431](https://github.com/TokTok/c-toxcore/pull/431) Update license headers and remove redundant file name comment.
-- [#424](https://github.com/TokTok/c-toxcore/pull/424) Fixed the FreeBSD build failure due to the undefined MSG_NOSIGNAL.
-- [#420](https://github.com/TokTok/c-toxcore/pull/420) Setup autotools to read .so version info from a separate file
-- [#418](https://github.com/TokTok/c-toxcore/pull/418) Clarify how the autotools build is done on Travis.
-- [#414](https://github.com/TokTok/c-toxcore/pull/414) Explicitly check if compiler supports C99
-
-## v0.1.4
-
-### Merged PRs:
-
-- [#422](https://github.com/TokTok/c-toxcore/pull/422) Release v0.1.4.
-- [#410](https://github.com/TokTok/c-toxcore/pull/410) Fix NaCl build: tar was called incorrectly.
-- [#409](https://github.com/TokTok/c-toxcore/pull/409) Clarify that the pass key `new` function can fail.
-- [#407](https://github.com/TokTok/c-toxcore/pull/407) Don't use `git.depth=1` anymore.
-- [#404](https://github.com/TokTok/c-toxcore/pull/404) Issue 404: semicolon not found
-- [#403](https://github.com/TokTok/c-toxcore/pull/403) Warn on -pedantic, don't error yet.
-- [#401](https://github.com/TokTok/c-toxcore/pull/401) Add logging callback to messenger_test.
-- [#400](https://github.com/TokTok/c-toxcore/pull/400) Run windows tests but ignore their failures.
-- [#398](https://github.com/TokTok/c-toxcore/pull/398) Portability Fixes
-- [#397](https://github.com/TokTok/c-toxcore/pull/397) Replace make_quick_sort with qsort
-- [#396](https://github.com/TokTok/c-toxcore/pull/396) Add an OSX build that doesn't run tests.
-- [#394](https://github.com/TokTok/c-toxcore/pull/394) CMake: Add soversion to library files to generate proper symlinks
-- [#393](https://github.com/TokTok/c-toxcore/pull/393) Set up autotools build to build against vanilla NaCl.
-- [#392](https://github.com/TokTok/c-toxcore/pull/392) Check that TCP connections aren't dropped in callbacks.
-- [#391](https://github.com/TokTok/c-toxcore/pull/391) Minor simplification in `file_seek` code.
-- [#390](https://github.com/TokTok/c-toxcore/pull/390) Always kill invalid file transfers when receiving file controls.
-- [#388](https://github.com/TokTok/c-toxcore/pull/388) Fix logging condition for IPv6 client timestamp updates.
-- [#387](https://github.com/TokTok/c-toxcore/pull/387) Eliminate dead return statement.
-- [#386](https://github.com/TokTok/c-toxcore/pull/386) Avoid accessing uninitialised memory in `net_crypto`.
-- [#381](https://github.com/TokTok/c-toxcore/pull/381) Remove `TOX_DEBUG` and have asserts always enabled.
-
-### Closed issues:
-
-- [#378](https://github.com/TokTok/c-toxcore/issues/378) Replace all uses of `make_quick_sort` with `qsort`
-- [#364](https://github.com/TokTok/c-toxcore/issues/364) Delete misc_tools.h after replacing its use by qsort.
-- [#363](https://github.com/TokTok/c-toxcore/issues/363) Test against NaCl in addition to libsodium on Travis.
-
-## v0.1.3
-
-### Merged PRs:
-
-- [#395](https://github.com/TokTok/c-toxcore/pull/395) Revert "Portability fixes"
-- [#380](https://github.com/TokTok/c-toxcore/pull/380) Test a few cmake option combinations before the build.
-- [#377](https://github.com/TokTok/c-toxcore/pull/377) Fix SSL verification in coveralls.
-- [#376](https://github.com/TokTok/c-toxcore/pull/376) Bring back autotools instructions
-- [#373](https://github.com/TokTok/c-toxcore/pull/373) Only fetch 1 revision from git during Travis builds.
-- [#369](https://github.com/TokTok/c-toxcore/pull/369) Integrate with CircleCI to build artifacts in the future
-- [#366](https://github.com/TokTok/c-toxcore/pull/366) Release v0.1.3.
-- [#362](https://github.com/TokTok/c-toxcore/pull/362) Remove .cabal-sandbox option from tox-spectest find line.
-- [#361](https://github.com/TokTok/c-toxcore/pull/361) Simplify integration as a third-party lib in cmake projects
-- [#354](https://github.com/TokTok/c-toxcore/pull/354) Add secure memcmp and memzero implementation.
-- [#324](https://github.com/TokTok/c-toxcore/pull/324) Do not compile and install DHT_bootstrap if it was disabled in configure
-- [#297](https://github.com/TokTok/c-toxcore/pull/297) Portability fixes
-
-### Closed issues:
-
-- [#347](https://github.com/TokTok/c-toxcore/issues/347) Implement our own secure `memcmp` and `memzero` if libsodium isn't available
-- [#319](https://github.com/TokTok/c-toxcore/issues/319) toxcore installs `DHT_bootstrap` even though `--disable-daemon` is passed to `./configure`
-
-## v0.1.2
-
-### Merged PRs:
-
-- [#355](https://github.com/TokTok/c-toxcore/pull/355) Release v0.1.2
-- [#353](https://github.com/TokTok/c-toxcore/pull/353) Fix toxav use after free caused by premature MSI destruction
-- [#346](https://github.com/TokTok/c-toxcore/pull/346) Avoid array out of bounds read in friend saving.
-- [#344](https://github.com/TokTok/c-toxcore/pull/344) Remove unused get/set salt/key functions from toxencryptsave.
-- [#343](https://github.com/TokTok/c-toxcore/pull/343) Wrap all sodium/nacl functions in crypto_core.c.
-- [#341](https://github.com/TokTok/c-toxcore/pull/341) Add test to check if tox_new/tox_kill leaks.
-- [#336](https://github.com/TokTok/c-toxcore/pull/336) Correct TES docs to reflect how many bytes functions actually require.
-- [#333](https://github.com/TokTok/c-toxcore/pull/333) Use `tox_options_set_*` instead of direct member access.
-
-### Closed issues:
-
-- [#345](https://github.com/TokTok/c-toxcore/issues/345) Array out of bounds read in "save" function
-- [#342](https://github.com/TokTok/c-toxcore/issues/342) Wrap all libsodium functions we use in toxcore in `crypto_core`.
-- [#278](https://github.com/TokTok/c-toxcore/issues/278) ToxAV use-after-free bug
-
-## v0.1.1
-
-### Merged PRs:
-
-- [#337](https://github.com/TokTok/c-toxcore/pull/337) Release v0.1.1
-- [#332](https://github.com/TokTok/c-toxcore/pull/332) Add test for encrypted savedata.
-- [#330](https://github.com/TokTok/c-toxcore/pull/330) Strengthen the note about ABI compatibility in tox.h.
-- [#328](https://github.com/TokTok/c-toxcore/pull/328) Drop the broken `TOX_VERSION_REQUIRE` macro.
-- [#326](https://github.com/TokTok/c-toxcore/pull/326) Fix unresolved reference in toxencryptsave API docs.
-- [#309](https://github.com/TokTok/c-toxcore/pull/309) Fixed attempt to join detached threads (fixes toxav test crash)
-- [#306](https://github.com/TokTok/c-toxcore/pull/306) Add option to disable local peer discovery
-
-### Closed issues:
-
-- [#327](https://github.com/TokTok/c-toxcore/issues/327) The `TOX_VERSION_REQUIRE` macro is broken.
-- [#221](https://github.com/TokTok/c-toxcore/issues/221) Option to disable local peer detection
-
-## v0.1.0
-
-### Merged PRs:
-
-- [#325](https://github.com/TokTok/c-toxcore/pull/325) Fix Libs line in toxcore.pc pkg-config file.
-- [#322](https://github.com/TokTok/c-toxcore/pull/322) Add compatibility pkg-config modules: libtoxcore, libtoxav.
-- [#318](https://github.com/TokTok/c-toxcore/pull/318) Fix `--enable-logging` flag in autotools configure script.
-- [#316](https://github.com/TokTok/c-toxcore/pull/316) Release 0.1.0.
-- [#315](https://github.com/TokTok/c-toxcore/pull/315) Fix version compatibility test.
-- [#314](https://github.com/TokTok/c-toxcore/pull/314) Fix off by one error in saving our own status message.
-- [#313](https://github.com/TokTok/c-toxcore/pull/313) Fix padding being in the wrong place in `SAVED_FRIEND` struct
-- [#312](https://github.com/TokTok/c-toxcore/pull/312) Conditionally enable non-portable assert on LP64.
-- [#310](https://github.com/TokTok/c-toxcore/pull/310) Add apidsl file for toxencryptsave.
-- [#307](https://github.com/TokTok/c-toxcore/pull/307) Clarify toxencryptsave documentation regarding buffer sizes
-- [#305](https://github.com/TokTok/c-toxcore/pull/305) Fix static builds
-- [#303](https://github.com/TokTok/c-toxcore/pull/303) Don't build nTox by default.
-- [#301](https://github.com/TokTok/c-toxcore/pull/301) Renamed messenger functions, prepend `m_`.
-- [#299](https://github.com/TokTok/c-toxcore/pull/299) net_crypto give handle_data_packet_helper a better name
-- [#294](https://github.com/TokTok/c-toxcore/pull/294) Don't error on warnings by default
-
-### Closed issues:
-
-- [#317](https://github.com/TokTok/c-toxcore/issues/317) toxcore fails to build with autotools and debugging level enabled
-- [#311](https://github.com/TokTok/c-toxcore/issues/311) Incorrect padding
-- [#308](https://github.com/TokTok/c-toxcore/issues/308) Review TES and port it to APIDSL
-- [#293](https://github.com/TokTok/c-toxcore/issues/293) error building on ubuntu 14.04
-- [#292](https://github.com/TokTok/c-toxcore/issues/292) Don't build nTox by default with CMake
-- [#290](https://github.com/TokTok/c-toxcore/issues/290) User Feed
-- [#266](https://github.com/TokTok/c-toxcore/issues/266) Support all levels listed in TOX_DHT_NAT_LEVEL
-- [#216](https://github.com/TokTok/c-toxcore/issues/216) When v0.1 release?
-
-## v0.0.5
-
-### Merged PRs:
-
-- [#289](https://github.com/TokTok/c-toxcore/pull/289) Version Patch v0.0.4 => v0.0.5
-- [#287](https://github.com/TokTok/c-toxcore/pull/287) Add CMake knobs to suppress building tests
-- [#286](https://github.com/TokTok/c-toxcore/pull/286) Support float32 and float64 in msgpack type printer.
-- [#285](https://github.com/TokTok/c-toxcore/pull/285) Mark `Tox_Options` struct as deprecated.
-- [#284](https://github.com/TokTok/c-toxcore/pull/284) Add NONE enumerator to bit mask.
-- [#281](https://github.com/TokTok/c-toxcore/pull/281) Made save format platform-independent
-- [#277](https://github.com/TokTok/c-toxcore/pull/277) Fix a memory leak in hstox interface
-- [#276](https://github.com/TokTok/c-toxcore/pull/276) Fix NULL pointer dereference in log calls
-- [#275](https://github.com/TokTok/c-toxcore/pull/275) Fix a memory leak in GroupAV
-- [#274](https://github.com/TokTok/c-toxcore/pull/274) Options in `new_messenger()` must never be null.
-- [#271](https://github.com/TokTok/c-toxcore/pull/271) Convert to and from network byte order in set/get nospam.
-- [#262](https://github.com/TokTok/c-toxcore/pull/262) Add ability to disable UDP hole punching
-
-### Closed issues:
-
-- [#254](https://github.com/TokTok/c-toxcore/issues/254) Add option to disable UDP hole punching
-- [#215](https://github.com/TokTok/c-toxcore/issues/215) The current tox save format is non-portable
-- [#205](https://github.com/TokTok/c-toxcore/issues/205) nospam value is reversed in array returned by `tox_self_get_address()`
-
-## v0.0.4
-
-### Merged PRs:
-
-- [#272](https://github.com/TokTok/c-toxcore/pull/272) v0.0.4
-- [#265](https://github.com/TokTok/c-toxcore/pull/265) Disable -Wunused-but-set-variable compiler warning flag.
-- [#261](https://github.com/TokTok/c-toxcore/pull/261) Work around Travis issue that causes build failures.
-- [#260](https://github.com/TokTok/c-toxcore/pull/260) Support arbitrary video resolutions in av_test
-- [#257](https://github.com/TokTok/c-toxcore/pull/257) Add decode/encode PlainText test support.
-- [#256](https://github.com/TokTok/c-toxcore/pull/256) Add spectest to the cmake test suite.
-- [#255](https://github.com/TokTok/c-toxcore/pull/255) Disable some gcc-specific warnings.
-- [#249](https://github.com/TokTok/c-toxcore/pull/249) Use apidsl for the crypto_core API.
-- [#248](https://github.com/TokTok/c-toxcore/pull/248) Remove new_nonce function in favour of random_nonce.
-- [#224](https://github.com/TokTok/c-toxcore/pull/224) Add DHT_create_packet, an abstraction for DHT RPC packets
-
-## v0.0.3
-
-### Merged PRs:
-
-- [#251](https://github.com/TokTok/c-toxcore/pull/251) Rename log levels to remove the extra "LOG" prefix.
-- [#250](https://github.com/TokTok/c-toxcore/pull/250) Release v0.0.3.
-- [#245](https://github.com/TokTok/c-toxcore/pull/245) Change packet kind enum to use hex constants.
-- [#243](https://github.com/TokTok/c-toxcore/pull/243) Enable address sanitizer on the cmake build.
-- [#242](https://github.com/TokTok/c-toxcore/pull/242) Remove assoc
-- [#241](https://github.com/TokTok/c-toxcore/pull/241) Move log callback to options.
-- [#233](https://github.com/TokTok/c-toxcore/pull/233) Enable all possible C compiler warning flags.
-- [#230](https://github.com/TokTok/c-toxcore/pull/230) Move packing and unpacking DHT request packets to DHT module.
-- [#228](https://github.com/TokTok/c-toxcore/pull/228) Remove unimplemented "time delta" parameter.
-- [#227](https://github.com/TokTok/c-toxcore/pull/227) Compile as C++ for windows builds.
-- [#223](https://github.com/TokTok/c-toxcore/pull/223) TravisCI shorten IRC message
-- [#220](https://github.com/TokTok/c-toxcore/pull/220) toxav renaming: group.{h,c} -> groupav.{h,c}
-- [#218](https://github.com/TokTok/c-toxcore/pull/218) Rename some internal "group chat" thing to "conference".
-- [#212](https://github.com/TokTok/c-toxcore/pull/212) Convert series of `NET_PACKET_*` defines into a typedef enum
-- [#196](https://github.com/TokTok/c-toxcore/pull/196) Update readme, moved the roadmap to a higher position
-- [#193](https://github.com/TokTok/c-toxcore/pull/193) Remove duplicate tests: split tests part 2.
-
-### Closed issues:
-
-- [#40](https://github.com/TokTok/c-toxcore/issues/40) Stateless callbacks in toxcore's public API
-
-## v0.0.2
-
-### Merged PRs:
-
-- [#207](https://github.com/TokTok/c-toxcore/pull/207) docs: correct instructions for cloning & harden agains repo name changes
-- [#206](https://github.com/TokTok/c-toxcore/pull/206) Corrected libsodium tag
-- [#204](https://github.com/TokTok/c-toxcore/pull/204) Error if format_test can't be executed.
-- [#202](https://github.com/TokTok/c-toxcore/pull/202) Version Patch v0.0.2
-- [#190](https://github.com/TokTok/c-toxcore/pull/190) Install libraries with RPATH.
-- [#189](https://github.com/TokTok/c-toxcore/pull/189) Use `socklen_t` instead of `unsigned int` in call to `accept`.
-- [#188](https://github.com/TokTok/c-toxcore/pull/188) Add option to set test timeout
-- [#187](https://github.com/TokTok/c-toxcore/pull/187) Add option to build tox-bootstrapd
-- [#185](https://github.com/TokTok/c-toxcore/pull/185) Import the hstox SUT interface from hstox.
-- [#183](https://github.com/TokTok/c-toxcore/pull/183) Set log level for DEBUG=ON to LOG_DEBUG.
-- [#182](https://github.com/TokTok/c-toxcore/pull/182) Remove return after no-return situation.
-- [#181](https://github.com/TokTok/c-toxcore/pull/181) Minor documentation fixes.
-- [#180](https://github.com/TokTok/c-toxcore/pull/180) Add the 'Tox' context object to the logger.
-- [#179](https://github.com/TokTok/c-toxcore/pull/179) Remove the `_test` suffix in `auto_test` calls.
-- [#178](https://github.com/TokTok/c-toxcore/pull/178) Rebuild apidsl'd headers in cmake.
-- [#177](https://github.com/TokTok/c-toxcore/pull/177) docs(INSTALL): update compiling instructions for Linux
-- [#176](https://github.com/TokTok/c-toxcore/pull/176) Merge irungentoo/toxcore into TokTok/c-toxcore.
-- [#173](https://github.com/TokTok/c-toxcore/pull/173) Duplicate tox_test to 4 other files.
-
-### Closed issues:
-
-- [#201](https://github.com/TokTok/c-toxcore/issues/201) Logging callback was broken
-
-## v0.0.1
-
-### Merged PRs:
-
-- [#174](https://github.com/TokTok/c-toxcore/pull/174) Remove redundant callback objects.
-- [#171](https://github.com/TokTok/c-toxcore/pull/171) Simple Version tick to v0.0.1
-- [#170](https://github.com/TokTok/c-toxcore/pull/170) C++ the second round.
-- [#166](https://github.com/TokTok/c-toxcore/pull/166) Add version-sync script.
-- [#164](https://github.com/TokTok/c-toxcore/pull/164) Replace `void*` with `RingBuffer*` to avoid conversions.
-- [#163](https://github.com/TokTok/c-toxcore/pull/163) Move ring buffer out of toxcore/util into toxav.
-- [#162](https://github.com/TokTok/c-toxcore/pull/162) Allow the OSX build to fail on travis.
-- [#161](https://github.com/TokTok/c-toxcore/pull/161) Minor cleanups: unused vars, unreachable code, static globals.
-- [#160](https://github.com/TokTok/c-toxcore/pull/160) Work around bug in opencv3 headers.
-- [#157](https://github.com/TokTok/c-toxcore/pull/157) Make TCP_Connections module-private.
-- [#156](https://github.com/TokTok/c-toxcore/pull/156) Make TCP_Server opaque.
-- [#153](https://github.com/TokTok/c-toxcore/pull/153) Fix strict-ld grep expressions to include digits.
-- [#151](https://github.com/TokTok/c-toxcore/pull/151) Revert #130 "Make ToxAV stateless"
-- [#148](https://github.com/TokTok/c-toxcore/pull/148) Added UB comment r/t deleting a friend w/ active call
-- [#146](https://github.com/TokTok/c-toxcore/pull/146) Make group callbacks stateless
-- [#145](https://github.com/TokTok/c-toxcore/pull/145) Make internal chat list function take uint32_t* as well.
-- [#144](https://github.com/TokTok/c-toxcore/pull/144) Only build toxav if opus and vpx are found.
-- [#143](https://github.com/TokTok/c-toxcore/pull/143) Make toxcore code C++ compatible.
-- [#142](https://github.com/TokTok/c-toxcore/pull/142) Fix for windows dynamic libraries.
-- [#141](https://github.com/TokTok/c-toxcore/pull/141) const-correctness in windows code.
-- [#140](https://github.com/TokTok/c-toxcore/pull/140) Use C99 %zu format conversion in printf for size_t.
-- [#139](https://github.com/TokTok/c-toxcore/pull/139) Clean up Travis build a bit in preparation for osx/win.
-- [#138](https://github.com/TokTok/c-toxcore/pull/138) Remove format-source from travis script.
-- [#135](https://github.com/TokTok/c-toxcore/pull/135) Convert old groupchats to new API format
-- [#134](https://github.com/TokTok/c-toxcore/pull/134) Add some astyle options to make it do more.
-- [#133](https://github.com/TokTok/c-toxcore/pull/133) Ensure that all TODOs have an owner.
-- [#132](https://github.com/TokTok/c-toxcore/pull/132) Remove `else` directly after `return`.
-- [#130](https://github.com/TokTok/c-toxcore/pull/130) Make ToxAV stateless
-- [#129](https://github.com/TokTok/c-toxcore/pull/129) Use TokTok's apidsl instead of the iphydf one.
-- [#127](https://github.com/TokTok/c-toxcore/pull/127) Use "phase" script for travis build phases.
-- [#126](https://github.com/TokTok/c-toxcore/pull/126) Add option to build static libraries.
-- [#125](https://github.com/TokTok/c-toxcore/pull/125) Group #include directives in 3-4 groups.
-- [#123](https://github.com/TokTok/c-toxcore/pull/123) Use correct logical operator for tox_test
-- [#120](https://github.com/TokTok/c-toxcore/pull/120) make the majority of the callbacks stateless and add some status to a testcase
-- [#118](https://github.com/TokTok/c-toxcore/pull/118) Use `const` for version numbers.
-- [#117](https://github.com/TokTok/c-toxcore/pull/117) Add STRICT_ABI cmake flag to generate export lists.
-- [#116](https://github.com/TokTok/c-toxcore/pull/116) Fix potential null pointer dereference.
-- [#115](https://github.com/TokTok/c-toxcore/pull/115) Fix memory leak on error paths in tox_new.
-- [#114](https://github.com/TokTok/c-toxcore/pull/114) Fix compilation for Windows.
-- [#111](https://github.com/TokTok/c-toxcore/pull/111) Add debugging option to autotools configuration
-- [#110](https://github.com/TokTok/c-toxcore/pull/110) Comment intentional switch fallthroughs
-- [#109](https://github.com/TokTok/c-toxcore/pull/109) Separate ip_port packing from pack_nodes() and unpack_nodes()
-- [#108](https://github.com/TokTok/c-toxcore/pull/108) Prevent `<winsock.h>` inclusion by `<windows.h>`.
-- [#107](https://github.com/TokTok/c-toxcore/pull/107) Print a message about missing astyle in format-source.
-- [#104](https://github.com/TokTok/c-toxcore/pull/104) Merge with irungentoo/master
-- [#103](https://github.com/TokTok/c-toxcore/pull/103) Allocate `sizeof(IP_ADAPTER_INFO)` bytes instead of `sizeof(T*)`.
-- [#101](https://github.com/TokTok/c-toxcore/pull/101) Add TODO for @mannol.
-- [#100](https://github.com/TokTok/c-toxcore/pull/100) Remove the packet mutation in toxav's bwcontroller.
-- [#99](https://github.com/TokTok/c-toxcore/pull/99) Make packet data a ptr-to-const.
-- [#97](https://github.com/TokTok/c-toxcore/pull/97) Improve static and const correctness.
-- [#96](https://github.com/TokTok/c-toxcore/pull/96) Improve C standard compliance.
-- [#94](https://github.com/TokTok/c-toxcore/pull/94) Rearrange fields to decrease size of structure
-- [#84](https://github.com/TokTok/c-toxcore/pull/84) Remove useless casts.
-- [#82](https://github.com/TokTok/c-toxcore/pull/82) Add missing #include <pthread.h> to av_test.c.
-- [#81](https://github.com/TokTok/c-toxcore/pull/81) Match parameter names in declarations with their definitions.
-- [#80](https://github.com/TokTok/c-toxcore/pull/80) Sort #includes in all source files.
-- [#79](https://github.com/TokTok/c-toxcore/pull/79) Remove redundant `return` statements.
-- [#78](https://github.com/TokTok/c-toxcore/pull/78) Do not use `else` after `return`.
-- [#77](https://github.com/TokTok/c-toxcore/pull/77) Add OSX and Windows build to travis config.
-- [#76](https://github.com/TokTok/c-toxcore/pull/76) Remove unused and bit-rotten friends_test.
-- [#75](https://github.com/TokTok/c-toxcore/pull/75) Enable build of av_test.
-- [#74](https://github.com/TokTok/c-toxcore/pull/74) Add missing #includes to headers and rename tox_old to tox_group.
-- [#73](https://github.com/TokTok/c-toxcore/pull/73) Add braces to all if statements.
-- [#72](https://github.com/TokTok/c-toxcore/pull/72) Add getters/setters for options.
-- [#70](https://github.com/TokTok/c-toxcore/pull/70) Expose constants as functions.
-- [#68](https://github.com/TokTok/c-toxcore/pull/68) Add address sanitizer option to cmake file.
-- [#66](https://github.com/TokTok/c-toxcore/pull/66) Fix plane size calculation in test
-- [#65](https://github.com/TokTok/c-toxcore/pull/65) Avoid large stack allocations on thread stacks.
-- [#64](https://github.com/TokTok/c-toxcore/pull/64) Comment out useless TODO'd if block.
-- [#63](https://github.com/TokTok/c-toxcore/pull/63) Initialise the id in assoc_test.
-- [#62](https://github.com/TokTok/c-toxcore/pull/62) Reduce the timeout on travis to something much more reasonable
-- [#60](https://github.com/TokTok/c-toxcore/pull/60) Make friend requests stateless
-- [#59](https://github.com/TokTok/c-toxcore/pull/59) Replace uint with unsigned int in assoc.c.
-- [#58](https://github.com/TokTok/c-toxcore/pull/58) Make Message received receipts stateless
-- [#57](https://github.com/TokTok/c-toxcore/pull/57) Make Friend User Status stateless
-- [#55](https://github.com/TokTok/c-toxcore/pull/55) docs(INSTALL.md): update instructions for Gentoo
-- [#54](https://github.com/TokTok/c-toxcore/pull/54) Make typing change callback stateless
-- [#53](https://github.com/TokTok/c-toxcore/pull/53) Add format-source script.
-- [#52](https://github.com/TokTok/c-toxcore/pull/52) Build assoc DHT code on travis.
-- [#51](https://github.com/TokTok/c-toxcore/pull/51) Fix operation sequencing in TCP_test.
-- [#49](https://github.com/TokTok/c-toxcore/pull/49) Apidsl test
-- [#48](https://github.com/TokTok/c-toxcore/pull/48) Make friend message callback stateless
-- [#46](https://github.com/TokTok/c-toxcore/pull/46) Move logging to a callback.
-- [#45](https://github.com/TokTok/c-toxcore/pull/45) Stateless friend status message
-- [#43](https://github.com/TokTok/c-toxcore/pull/43) Allow NULL as argument to tox_kill.
-- [#41](https://github.com/TokTok/c-toxcore/pull/41) Fix warnings
-- [#39](https://github.com/TokTok/c-toxcore/pull/39) Merge irungentoo/toxcore into TokTok/c-toxcore.
-- [#38](https://github.com/TokTok/c-toxcore/pull/38) Try searching for libsodium with pkg-config in ./configure.
-- [#37](https://github.com/TokTok/c-toxcore/pull/37) Add missing DHT_bootstrap to CMakeLists.txt.
-- [#36](https://github.com/TokTok/c-toxcore/pull/36) Make tox_callback_friend_name stateless.
-- [#33](https://github.com/TokTok/c-toxcore/pull/33) Update readme with tentative roadmap, removed old todo.md
-- [#32](https://github.com/TokTok/c-toxcore/pull/32) Fix a bug I introduced that would make toxcore fail to initialise a second time
-- [#31](https://github.com/TokTok/c-toxcore/pull/31) 7. Travis envs
-- [#30](https://github.com/TokTok/c-toxcore/pull/30) 2. Hstox test
-- [#29](https://github.com/TokTok/c-toxcore/pull/29) 1. Move toxcore travis build scripts out of .travis.yml.
-- [#27](https://github.com/TokTok/c-toxcore/pull/27) 8. Stateless
-- [#26](https://github.com/TokTok/c-toxcore/pull/26) 6. Cmake bootstrapd
-- [#25](https://github.com/TokTok/c-toxcore/pull/25) 5. Coverage clang
-- [#24](https://github.com/TokTok/c-toxcore/pull/24) Silence/fix some compiler warnings.
-- [#23](https://github.com/TokTok/c-toxcore/pull/23) 4. Cmake
-- [#20](https://github.com/TokTok/c-toxcore/pull/20) 3. Travis astyle
-- [#13](https://github.com/TokTok/c-toxcore/pull/13) Enable, and report test status
-- [#12](https://github.com/TokTok/c-toxcore/pull/12) Fix readme for TokTok
-- [#11](https://github.com/TokTok/c-toxcore/pull/11) Documentation: SysVInit workaround for <1024 ports
-- [#2](https://github.com/TokTok/c-toxcore/pull/2) Enable toxcore logging when building on Travis.
-- [#1](https://github.com/TokTok/c-toxcore/pull/1) Apidsl fixes and start tracking test coverage
-
-### Closed issues:
-
-- [#158](https://github.com/TokTok/c-toxcore/issues/158) Error while build with OpenCV 3.1
-- [#147](https://github.com/TokTok/c-toxcore/issues/147) Add comment to m_delfriend about the NULL passing to the internal conn status cb
-- [#136](https://github.com/TokTok/c-toxcore/issues/136) Replace astyle by clang-format
-- [#113](https://github.com/TokTok/c-toxcore/issues/113) Toxcore tests fail
-- [#83](https://github.com/TokTok/c-toxcore/issues/83) Travis tests are hard to quickly parse from their output.
-- [#22](https://github.com/TokTok/c-toxcore/issues/22) Make the current tests exercise both ipv4 and ipv6.
-- [#9](https://github.com/TokTok/c-toxcore/issues/9) Fix the failing test
-- [#8](https://github.com/TokTok/c-toxcore/issues/8) Toxcore should make more liberal use of assertions
-- [#4](https://github.com/TokTok/c-toxcore/issues/4) Integrate hstox tests with toxcore Travis build
diff --git a/libs/libtox/docs/COPYING b/libs/libtox/docs/COPYING
deleted file mode 100644
index 94a9ed024d..0000000000
--- a/libs/libtox/docs/COPYING
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/libs/libtox/docs/DONATORS b/libs/libtox/docs/DONATORS
deleted file mode 100644
index dcce32c869..0000000000
--- a/libs/libtox/docs/DONATORS
+++ /dev/null
@@ -1,7 +0,0 @@
-Minnesota > Florida
-vdo <vdo@greyfaze.net>
-Spitfire is best technicolor horse.
-if bad people don't hate you, you're doing something wrong
-Pinkie Pie is best pony.
-JRS was here
-qTox is so bloated it doesn't even fit in a 64-bit address space
diff --git a/libs/libtox/docs/README.md b/libs/libtox/docs/README.md
deleted file mode 100644
index 7a1ffe7ffa..0000000000
--- a/libs/libtox/docs/README.md
+++ /dev/null
@@ -1,174 +0,0 @@
-# ![Project Tox](https://raw.github.com/TokTok/toxcore/master/other/tox.png "Project Tox")
-
-**Current build status:** [![Build Status](https://travis-ci.org/TokTok/c-toxcore.svg?branch=master)](https://travis-ci.org/TokTok/c-toxcore)
-**Current Coverage:** [![Coverage Status](https://coveralls.io/repos/github/TokTok/toxcore/badge.svg?branch=master)](https://coveralls.io/github/TokTok/toxcore?branch=master)
-
-[**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|** [**Blog**](https://blog.tox.chat/) **|** [**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|** [**Binaries/Downloads**](https://wiki.tox.chat/Binaries) **|** [**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|** [**Compiling**](/INSTALL.md)
-
-**IRC Channels:** Users: [#tox@freenode](https://webchat.freenode.net/?channels=tox), Developers: [#toktok@freenode](https://webchat.freenode.net/?channels=toktok)
-
-## What is Tox
-
-Tox is a peer to peer (serverless) instant messenger aimed at making security
-and privacy easy to obtain for regular users. It uses
-[NaCl](https://nacl.cr.yp.to/) for its encryption and authentication.
-
-## IMPORTANT!
-
-### ![Danger: Experimental](other/tox-warning.png)
-
-This is an **experimental** cryptographic network library. It has not been
-formally audited by an independent third party that specializes in
-cryptography or cryptanalysis. **Use this library at your own risk.**
-
-The underlying crypto library [NaCl](https://nacl.cr.yp.to/install.html)
-provides reliable encryption, but the security model has not yet been fully
-specified. See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for
-a discussion on developing a threat model. See other issues for known
-weaknesses (e.g. [issue 426](https://github.com/TokTok/c-toxcore/issues/426)
-describes what can happen if your secret key is stolen).
-
-## Toxcore Development Roadmap
-
-The roadmap and changelog are generated from GitHub issues. You may view them
-on the website, where they are updated at least once every 24 hours:
-
-- Changelog: https://toktok.ltd/changelog/c-toxcore
-- Roadmap: https://toktok.ltd/roadmap/c-toxcore
-
-## Installing toxcore
-
-Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
-
-In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
-or [nacl](https://nacl.cr.yp.to/install.html) installed, run:
-
-```sh
-autoreconf -fi
-mkdir _build && cd _build
-../configure
-make
-sudo make install
-```
-
-If you have [libvpx](https://github.com/webmproject/libvpx) and
-[opus](https://github.com/xiph/opus) installed, the above will also build the
-A/V library for multimedia chats.
-
-## Using toxcore
-
-The simplest "hello world" example could be an echo bot. Here we will walk
-through the implementation of a simple bot.
-
-### Creating the tox instance
-
-All toxcore API functions work with error parameters. They are enums with one
-`OK` value and several error codes that describe the different situations in
-which the function might fail.
-
-```c
-TOX_ERR_NEW err_new;
-Tox *tox = tox_new(NULL, &err_new);
-if (err_new != TOX_ERR_NEW_OK) {
- fprintf(stderr, "tox_new failed with error code %d\n", err_new);
- exit(1);
-}
-```
-
-Here, we simply exit the program, but in a real client you will probably want
-to do some error handling and proper error reporting to the user. The `NULL`
-argument given to the first parameter of `tox_new` is the `Tox_Options`. It
-contains various write-once network settings and allows you to load a
-previously serialised instance. See [toxcore/tox.h](tox.h) for details.
-
-### Setting up callbacks
-
-Toxcore works with callbacks that you can register to listen for certain
-events. Examples of such events are "friend request received" or "friend sent
-a message". Search the API for `tox_callback_*` to find all of them.
-
-Here, we will set up callbacks for receiving friend requests and receiving
-messages. We will always accept any friend request (because we're a bot), and
-when we receive a message, we send it back to the sender.
-
-```c
-tox_callback_friend_request(tox, handle_friend_request);
-tox_callback_friend_message(tox, handle_friend_message);
-```
-
-These two function calls set up the callbacks. Now we also need to implement
-these "handle" functions.
-
-### Handle friend requests
-
-```c
-static void handle_friend_request(
- Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
- void *user_data) {
- // Accept the friend request:
- TOX_ERR_FRIEND_ADD err_friend_add;
- tox_friend_add_norequest(tox, public_key, &err_friend_add);
- if (err_friend_add != TOX_ERR_FRIEND_ADD_OK) {
- fprintf(stderr, "unable to add friend: %d\n", err_friend_add);
- }
-}
-```
-
-The `tox_friend_add_norequest` function adds the friend without sending them a
-friend request. Since we already got a friend request, this is the right thing
-to do. If you wanted to send a friend request yourself, you would use
-`tox_friend_add`, which has an extra parameter for the message.
-
-### Handle messages
-
-Now, when the friend sends us a message, we want to respond to them by sending
-them the same message back. This will be our "echo".
-
-```c
-static void handle_friend_message(
- Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type,
- const uint8_t *message, size_t length,
- void *user_data) {
- TOX_ERR_FRIEND_SEND_MESSAGE err_send;
- tox_friend_send_message(tox, friend_number, type, message, length,
- &err_send);
- if (err_send != TOX_ERR_FRIEND_SEND_MESSAGE_OK) {
- fprintf(stderr, "unable to send message back to friend %d: %d\n",
- friend_number, err_send);
- }
-}
-```
-
-That's it for the setup. Now we want to actually run the bot.
-
-### Main event loop
-
-Toxcore works with a main event loop function `tox_iterate` that you need to
-call at a certain frequency dictated by `tox_iteration_interval`. This is a
-polling function that receives new network messages and processes them.
-
-```c
-while (true) {
- usleep(1000 * tox_iteration_interval(tox));
- tox_iterate(tox, NULL);
-}
-```
-
-That's it! Now you have a working echo bot. The only problem is that since Tox
-works with public keys, and you can't really guess your bot's public key, you
-can't add it as a friend in your client. For this, we need to call another API
-function: `tox_self_get_address(tox, address)`. This will fill the 38 byte
-friend address into the `address` buffer. You can then display that binary
-string as hex and input it into your client. Writing a `bin2hex` function is
-left as exercise for the reader.
-
-We glossed over a lot of details, such as the user data which we passed to
-`tox_iterate` (passing `NULL`), bootstrapping into an actual network (this bot
-will work in the LAN, but not on an internet server) and the fact that we now
-have no clean way of stopping the bot (`while (true)`). If you want to write a
-real bot, you will probably want to read up on all the API functions. Consult
-the API documentation in [toxcore/tox.h](tox.h) for more information.
-
-### Other resources
-
-- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
diff --git a/libs/libtox/libtox.vcxproj b/libs/libtox/libtox.vcxproj
deleted file mode 100644
index b553c6194c..0000000000
--- a/libs/libtox/libtox.vcxproj
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{A21C50CD-28A6-481A-A12B-47189FE66641}</ProjectGuid>
- <ProjectName>libtox</ProjectName>
- </PropertyGroup>
- <Import Project="$(ProjectDir)..\..\build\vc.common\lib.props" />
- <ItemDefinitionGroup>
- <ClCompile>
- <AdditionalIncludeDirectories>$(ProjectDir)..\pthreads\src;$(ProjectDir)..\libsodium\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <ModuleDefinitionFile>src/libtox.def</ModuleDefinitionFile>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="src\toxcore\*.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="src\toxdns\*.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
- <ClCompile Include="src\toxencryptsave\*.c">
- <PrecompiledHeader>NotUsing</PrecompiledHeader>
- </ClCompile>
- <ClInclude Include="src\toxcore\*.h" />
- <ClInclude Include="src\toxencryptsave*.h" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\libsodium\libsodium.vcxproj">
- <Project>{a185b162-6cb6-4502-b03f-b56f7699a8d9}</Project>
- </ProjectReference>
- <ProjectReference Include="..\pthreads\pthreads.vcxproj">
- <Project>{e0ebb8a5-b577-414c-a5f9-9b4e2a0a66e9}</Project>
- </ProjectReference>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/libs/libtox/libtox.vcxproj.filters b/libs/libtox/libtox.vcxproj.filters
deleted file mode 100644
index 541f75ffb0..0000000000
--- a/libs/libtox/libtox.vcxproj.filters
+++ /dev/null
@@ -1,293 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
- <ItemGroup>
- <ClCompile Include="src\stdafx.cxx">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxcore\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="src\toxencryptsave\*.c">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="src\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="src\toxcore\*.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/libs/libtox/src/libtox.def b/libs/libtox/src/libtox.def
deleted file mode 100644
index e1706ad3ae..0000000000
--- a/libs/libtox/src/libtox.def
+++ /dev/null
@@ -1,155 +0,0 @@
-LIBRARY libtox.mir
-DESCRIPTION
-
-EXPORTS
-tox_add_tcp_relay
-tox_address_size
-tox_bootstrap
-tox_callback_conference_invite
-tox_callback_conference_message
-tox_callback_conference_namelist_change
-tox_callback_conference_title
-tox_callback_file_chunk_request
-tox_callback_file_recv
-tox_callback_file_recv_chunk
-tox_callback_file_recv_control
-tox_callback_friend_connection_status
-tox_callback_friend_lossless_packet
-tox_callback_friend_lossy_packet
-tox_callback_friend_message
-tox_callback_friend_name
-tox_callback_friend_read_receipt
-tox_callback_friend_request
-tox_callback_friend_status
-tox_callback_friend_status_message
-tox_callback_friend_typing
-tox_callback_self_connection_status
-tox_conference_delete
-tox_conference_get_chatlist
-tox_conference_get_chatlist_size
-tox_conference_get_title
-tox_conference_get_title_size
-tox_conference_get_type
-tox_conference_invite
-tox_conference_join
-tox_conference_new
-tox_conference_peer_count
-tox_conference_peer_get_name
-tox_conference_peer_get_name_size
-tox_conference_peer_get_public_key
-tox_conference_peer_number_is_ours
-tox_conference_send_message
-tox_conference_set_title
-tox_decrypt_dns3_TXT
-tox_dns3_kill
-tox_dns3_new
-tox_file_control
-tox_file_get_file_id
-tox_file_id_length
-tox_file_seek
-tox_file_send
-tox_file_send_chunk
-tox_friend_add
-tox_friend_add_norequest
-tox_friend_by_public_key
-tox_friend_delete
-tox_friend_exists
-tox_friend_get_connection_status
-tox_friend_get_last_online
-tox_friend_get_name
-tox_friend_get_name_size
-tox_friend_get_public_key
-tox_friend_get_status
-tox_friend_get_status_message
-tox_friend_get_status_message_size
-tox_friend_get_typing
-tox_friend_send_lossless_packet
-tox_friend_send_lossy_packet
-tox_friend_send_message
-tox_generate_dns3_string
-tox_get_salt
-tox_get_savedata
-tox_get_savedata_size
-tox_hash
-tox_hash_length
-tox_is_data_encrypted
-tox_iterate
-tox_iteration_interval
-tox_kill
-tox_max_custom_packet_size
-tox_max_filename_length
-tox_max_friend_request_length
-tox_max_message_length
-tox_max_name_length
-tox_max_status_message_length
-tox_new
-tox_options_default
-tox_options_free
-tox_options_get_end_port
-tox_options_get_hole_punching_enabled
-tox_options_get_ipv6_enabled
-tox_options_get_local_discovery_enabled
-tox_options_get_log_callback
-tox_options_get_log_user_data
-tox_options_get_proxy_host
-tox_options_get_proxy_port
-tox_options_get_proxy_type
-tox_options_get_savedata_data
-tox_options_get_savedata_length
-tox_options_get_savedata_type
-tox_options_get_start_port
-tox_options_get_tcp_port
-tox_options_get_udp_enabled
-tox_options_new
-tox_options_set_end_port
-tox_options_set_hole_punching_enabled
-tox_options_set_ipv6_enabled
-tox_options_set_local_discovery_enabled
-tox_options_set_log_callback
-tox_options_set_log_user_data
-tox_options_set_proxy_host
-tox_options_set_proxy_port
-tox_options_set_proxy_type
-tox_options_set_savedata_data
-tox_options_set_savedata_length
-tox_options_set_savedata_type
-tox_options_set_start_port
-tox_options_set_tcp_port
-tox_options_set_udp_enabled
-tox_pass_decrypt
-tox_pass_encrypt
-tox_pass_encryption_extra_length
-tox_pass_key_decrypt
-tox_pass_key_derive
-tox_pass_key_derive_with_salt
-tox_pass_key_encrypt
-tox_pass_key_free
-tox_pass_key_length
-tox_pass_key_new
-tox_pass_salt_length
-tox_public_key_size
-tox_secret_key_size
-tox_self_get_address
-tox_self_get_connection_status
-tox_self_get_dht_id
-tox_self_get_friend_list
-tox_self_get_friend_list_size
-tox_self_get_name
-tox_self_get_name_size
-tox_self_get_nospam
-tox_self_get_public_key
-tox_self_get_secret_key
-tox_self_get_status
-tox_self_get_status_message
-tox_self_get_status_message_size
-tox_self_get_tcp_port
-tox_self_get_udp_port
-tox_self_set_name
-tox_self_set_nospam
-tox_self_set_status
-tox_self_set_status_message
-tox_self_set_typing
-tox_version_is_compatible
-tox_version_major
-tox_version_minor
-tox_version_patch
diff --git a/libs/libtox/src/stdafx.cxx b/libs/libtox/src/stdafx.cxx
deleted file mode 100644
index 1647228cd0..0000000000
--- a/libs/libtox/src/stdafx.cxx
+++ /dev/null
@@ -1,2 +0,0 @@
-
-#include "stdafx.h" \ No newline at end of file
diff --git a/libs/libtox/src/stdafx.h b/libs/libtox/src/stdafx.h
deleted file mode 100644
index e69de29bb2..0000000000
--- a/libs/libtox/src/stdafx.h
+++ /dev/null
diff --git a/libs/libtox/src/toxcore/DHT.c b/libs/libtox/src/toxcore/DHT.c
deleted file mode 100644
index 4ebe7f3344..0000000000
--- a/libs/libtox/src/toxcore/DHT.c
+++ /dev/null
@@ -1,2853 +0,0 @@
-/*
- * An implementation of the DHT as seen in docs/updates/DHT.md
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "DHT.h"
-
-#include "LAN_discovery.h"
-#include "logger.h"
-#include "network.h"
-#include "ping.h"
-#include "util.h"
-
-#include <assert.h>
-
-/* The timeout after which a node is discarded completely. */
-#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
-
-/* Ping interval in seconds for each random sending of a get nodes request. */
-#define GET_NODE_INTERVAL 20
-
-#define MAX_PUNCHING_PORTS 48
-
-/* Interval in seconds between punching attempts*/
-#define PUNCH_INTERVAL 3
-
-/* Time in seconds after which punching parameters will be reset */
-#define PUNCH_RESET_TIME 40
-
-#define MAX_NORMAL_PUNCHING_TRIES 5
-
-#define NAT_PING_REQUEST 0
-#define NAT_PING_RESPONSE 1
-
-/* Number of get node requests to send to quickly find close nodes. */
-#define MAX_BOOTSTRAP_TIMES 5
-
-#define ASSOC_COUNT 2
-
-/* Compares pk1 and pk2 with pk.
- *
- * return 0 if both are same distance.
- * return 1 if pk1 is closer.
- * return 2 if pk2 is closer.
- */
-int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
-{
- for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
-
- uint8_t distance1 = pk[i] ^ pk1[i];
- uint8_t distance2 = pk[i] ^ pk2[i];
-
- if (distance1 < distance2) {
- return 1;
- }
-
- if (distance1 > distance2) {
- return 2;
- }
- }
-
- return 0;
-}
-
-/* Return index of first unequal bit number.
- */
-static unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
-{
- unsigned int i;
- unsigned int j = 0;
-
- for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
- if (pk1[i] == pk2[i]) {
- continue;
- }
-
- for (j = 0; j < 8; ++j) {
- uint8_t mask = 1 << (7 - j);
-
- if ((pk1[i] & mask) != (pk2[i] & mask)) {
- break;
- }
- }
-
- break;
- }
-
- return i * 8 + j;
-}
-
-/* Shared key generations are costly, it is therefor smart to store commonly used
- * ones so that they can re used later without being computed again.
- *
- * If shared key is already in shared_keys, copy it to shared_key.
- * else generate it into shared_key and copy it to shared_keys
- */
-void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key, const uint8_t *public_key)
-{
- uint32_t num = ~0;
- uint32_t curr = 0;
-
- for (uint32_t i = 0; i < MAX_KEYS_PER_SLOT; ++i) {
- int index = public_key[30] * MAX_KEYS_PER_SLOT + i;
- Shared_Key *key = &shared_keys->keys[index];
-
- if (key->stored) {
- if (id_equal(public_key, key->public_key)) {
- memcpy(shared_key, key->shared_key, CRYPTO_SHARED_KEY_SIZE);
- ++key->times_requested;
- key->time_last_requested = unix_time();
- return;
- }
-
- if (num != 0) {
- if (is_timeout(key->time_last_requested, KEYS_TIMEOUT)) {
- num = 0;
- curr = index;
- } else if (num > key->times_requested) {
- num = key->times_requested;
- curr = index;
- }
- }
- } else if (num != 0) {
- num = 0;
- curr = index;
- }
- }
-
- encrypt_precompute(public_key, secret_key, shared_key);
-
- if (num != (uint32_t)~0) {
- Shared_Key *key = &shared_keys->keys[curr];
- key->stored = 1;
- key->times_requested = 1;
- memcpy(key->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(key->shared_key, shared_key, CRYPTO_SHARED_KEY_SIZE);
- key->time_last_requested = unix_time();
- }
-}
-
-/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
- * for packets that we receive.
- */
-void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
-{
- get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, public_key);
-}
-
-/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
- * for packets that we send.
- */
-void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key)
-{
- get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, public_key);
-}
-
-#define CRYPTO_SIZE 1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE
-
-/* Create a request to peer.
- * send_public_key and send_secret_key are the pub/secret keys of the sender.
- * recv_public_key is public key of receiver.
- * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
- * Data represents the data we send with the request with length being the length of the data.
- * request_id is the id of the request (32 = friend request, 254 = ping request).
- *
- * return -1 on failure.
- * return the length of the created packet on success.
- */
-int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
- const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id)
-{
- if (!send_public_key || !packet || !recv_public_key || !data) {
- return -1;
- }
-
- if (MAX_CRYPTO_REQUEST_SIZE < length + CRYPTO_SIZE + 1 + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
- random_nonce(nonce);
- uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
- memcpy(temp + 1, data, length);
- temp[0] = request_id;
- int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
- CRYPTO_SIZE + packet);
-
- if (len == -1) {
- crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
- return -1;
- }
-
- packet[0] = NET_PACKET_CRYPTO;
- memcpy(packet + 1, recv_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, send_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
- return len + CRYPTO_SIZE;
-}
-
-/* Puts the senders public key in the request in public_key, the data from the request
- * in data if a friend or ping request was sent to us and returns the length of the data.
- * packet is the request packet and length is its length.
- *
- * return -1 if not valid request.
- */
-int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
- uint8_t *request_id, const uint8_t *packet, uint16_t length)
-{
- if (!self_public_key || !public_key || !data || !request_id || !packet) {
- return -1;
- }
-
- if (length <= CRYPTO_SIZE + CRYPTO_MAC_SIZE || length > MAX_CRYPTO_REQUEST_SIZE) {
- return -1;
- }
-
- if (!id_equal(packet + 1, self_public_key)) {
- return -1;
- }
-
- memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
- const uint8_t *nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
- uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
- int len1 = decrypt_data(public_key, self_secret_key, nonce,
- packet + CRYPTO_SIZE, length - CRYPTO_SIZE, temp);
-
- if (len1 == -1 || len1 == 0) {
- crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
- return -1;
- }
-
- request_id[0] = temp[0];
- --len1;
- memcpy(data, temp + 1, len1);
- crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
- return len1;
-}
-
-#define PACKED_NODE_SIZE_IP4 (1 + SIZE_IP4 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
-#define PACKED_NODE_SIZE_IP6 (1 + SIZE_IP6 + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE)
-
-/* Return packet size of packed node with ip_family on success.
- * Return -1 on failure.
- */
-int packed_node_size(uint8_t ip_family)
-{
- switch (ip_family) {
- case TOX_AF_INET:
- case TCP_INET:
- return PACKED_NODE_SIZE_IP4;
-
- case TOX_AF_INET6:
- case TCP_INET6:
- return PACKED_NODE_SIZE_IP6;
-
- default:
- return -1;
- }
-}
-
-
-/* Packs an IP_Port structure into data of max size length.
- *
- * Returns size of packed IP_Port data on success
- * Return -1 on failure.
- */
-static int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port)
-{
- if (data == NULL) {
- return -1;
- }
-
- bool is_ipv4;
- uint8_t net_family;
-
- if (ip_port->ip.family == TOX_AF_INET) {
- // TODO(irungentoo): use functions to convert endianness
- is_ipv4 = true;
- net_family = TOX_AF_INET;
- } else if (ip_port->ip.family == TCP_INET) {
- is_ipv4 = true;
- net_family = TOX_TCP_INET;
- } else if (ip_port->ip.family == TOX_AF_INET6) {
- is_ipv4 = false;
- net_family = TOX_AF_INET6;
- } else if (ip_port->ip.family == TCP_INET6) {
- is_ipv4 = false;
- net_family = TOX_TCP_INET6;
- } else {
- return -1;
- }
-
- if (is_ipv4) {
- uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- data[0] = net_family;
- memcpy(data + 1, &ip_port->ip.ip4, SIZE_IP4);
- memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t));
- return size;
- } else {
- uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- data[0] = net_family;
- memcpy(data + 1, &ip_port->ip.ip6, SIZE_IP6);
- memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t));
- return size;
- }
-}
-
-static int DHT_create_packet(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
- const uint8_t *shared_key, const uint8_t type, uint8_t *plain, size_t plain_length, uint8_t *packet)
-{
- VLA(uint8_t, encrypted, plain_length + CRYPTO_MAC_SIZE);
- uint8_t nonce[CRYPTO_NONCE_SIZE];
-
- random_nonce(nonce);
-
- int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted);
-
- if (encrypted_length == -1) {
- return -1;
- }
-
- packet[0] = type;
- memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
-
- return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
-}
-
-/* Unpack IP_Port structure from data of max size length into ip_port.
- *
- * Return size of unpacked ip_port on success.
- * Return -1 on failure.
- */
-static int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, uint8_t tcp_enabled)
-{
- if (data == NULL) {
- return -1;
- }
-
- bool is_ipv4;
- uint8_t host_family;
-
- if (data[0] == TOX_AF_INET) {
- is_ipv4 = true;
- host_family = TOX_AF_INET;
- } else if (data[0] == TOX_TCP_INET) {
- if (!tcp_enabled) {
- return -1;
- }
-
- is_ipv4 = true;
- host_family = TCP_INET;
- } else if (data[0] == TOX_AF_INET6) {
- is_ipv4 = false;
- host_family = TOX_AF_INET6;
- } else if (data[0] == TOX_TCP_INET6) {
- if (!tcp_enabled) {
- return -1;
- }
-
- is_ipv4 = false;
- host_family = TCP_INET6;
- } else {
- return -1;
- }
-
- if (is_ipv4) {
- uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- ip_port->ip.family = host_family;
- memcpy(&ip_port->ip.ip4, data + 1, SIZE_IP4);
- memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t));
- return size;
- } else {
- uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t);
-
- if (size > length) {
- return -1;
- }
-
- ip_port->ip.family = host_family;
- memcpy(&ip_port->ip.ip6, data + 1, SIZE_IP6);
- memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t));
- return size;
- }
-}
-
-/* Pack number of nodes into data of maxlength length.
- *
- * return length of packed nodes on success.
- * return -1 on failure.
- */
-int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
-{
- uint32_t packed_length = 0;
-
- for (uint32_t i = 0; i < number && packed_length < length; ++i) {
- int ipp_size = pack_ip_port(data + packed_length, length - packed_length, &nodes[i].ip_port);
-
- if (ipp_size == -1) {
- return -1;
- }
-
- packed_length += ipp_size;
-
- if (packed_length + CRYPTO_PUBLIC_KEY_SIZE > length) {
- return -1;
- }
-
- memcpy(data + packed_length, nodes[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- packed_length += CRYPTO_PUBLIC_KEY_SIZE;
-
- uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
- assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
- }
-
- return packed_length;
-}
-
-/* Unpack data of length into nodes of size max_num_nodes.
- * Put the length of the data processed in processed_data_len.
- * tcp_enabled sets if TCP nodes are expected (true) or not (false).
- *
- * return number of unpacked nodes on success.
- * return -1 on failure.
- */
-int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
- uint16_t length, uint8_t tcp_enabled)
-{
- uint32_t num = 0, len_processed = 0;
-
- while (num < max_num_nodes && len_processed < length) {
- int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
-
- if (ipp_size == -1) {
- return -1;
- }
-
- len_processed += ipp_size;
-
- if (len_processed + CRYPTO_PUBLIC_KEY_SIZE > length) {
- return -1;
- }
-
- memcpy(nodes[num].public_key, data + len_processed, CRYPTO_PUBLIC_KEY_SIZE);
- len_processed += CRYPTO_PUBLIC_KEY_SIZE;
- ++num;
-
- uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
- assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
- }
-
- if (processed_data_len) {
- *processed_data_len = len_processed;
- }
-
- return num;
-}
-
-/* Find index of ##type with public_key equal to pk.
- *
- * return index or UINT32_MAX if not found.
- */
-#define INDEX_OF_PK \
- for (uint32_t i = 0; i < size; i++) { \
- if (id_equal(array[i].public_key, pk)) { \
- return i; \
- } \
- } \
- \
- return UINT32_MAX;
-
-static uint32_t index_of_client_pk(const Client_data *array, uint32_t size, const uint8_t *pk)
-{
- INDEX_OF_PK
-}
-
-static uint32_t index_of_friend_pk(const DHT_Friend *array, uint32_t size, const uint8_t *pk)
-{
- INDEX_OF_PK
-}
-
-static uint32_t index_of_node_pk(const Node_format *array, uint32_t size, const uint8_t *pk)
-{
- INDEX_OF_PK
-}
-
-/* Find index of Client_data with ip_port equal to param ip_port.
- *
- * return index or UINT32_MAX if not found.
- */
-static uint32_t index_of_client_ip_port(const Client_data *array, uint32_t size, const IP_Port *ip_port)
-{
- for (uint32_t i = 0; i < size; ++i) {
- if (ip_port->ip.family == TOX_AF_INET && ipport_equal(&array[i].assoc4.ip_port, ip_port) ||
- ip_port->ip.family == TOX_AF_INET6 && ipport_equal(&array[i].assoc6.ip_port, ip_port)) {
- return i;
- }
- }
-
- return UINT32_MAX;
-}
-
-/* Update ip_port of client if it's needed.
- */
-static void update_client(Logger *log, int index, Client_data *client, IP_Port ip_port)
-{
- IPPTsPng *assoc;
- int ip_version;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- assoc = &client->assoc4;
- ip_version = 4;
- } else if (ip_port.ip.family == TOX_AF_INET6) {
- assoc = &client->assoc6;
- ip_version = 6;
- } else {
- return;
- }
-
- if (!ipport_equal(&assoc->ip_port, &ip_port)) {
- char ip_str[IP_NTOA_LEN];
- LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",
- index, ip_version,
- ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
- net_ntohs(assoc->ip_port.port),
- ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)),
- net_ntohs(ip_port.port));
- }
-
- if (LAN_ip(assoc->ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) {
- return;
- }
-
- assoc->ip_port = ip_port;
- assoc->timestamp = unix_time();
-}
-
-/* Check if client with public_key is already in list of length length.
- * If it is then set its corresponding timestamp to current time.
- * If the id is already in the list with a different ip_port, update it.
- * TODO(irungentoo): Maybe optimize this.
- *
- * return True(1) or False(0)
- */
-static int client_or_ip_port_in_list(Logger *log, Client_data *list, uint16_t length, const uint8_t *public_key,
- IP_Port ip_port)
-{
- uint64_t temp_time = unix_time();
- uint32_t index = index_of_client_pk(list, length, public_key);
-
- /* if public_key is in list, find it and maybe overwrite ip_port */
- if (index != UINT32_MAX) {
- update_client(log, index, &list[index], ip_port);
- return 1;
- }
-
- /* public_key not in list yet: see if we can find an identical ip_port, in
- * that case we kill the old public_key by overwriting it with the new one
- * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list
- * and the one who is the actual friend's public_key/address set?
- * MAYBE: check the other address, if valid, don't nuke? */
- index = index_of_client_ip_port(list, length, &ip_port);
-
- if (index == UINT32_MAX) {
- return 0;
- }
-
- IPPTsPng *assoc;
- int ip_version;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- assoc = &list[index].assoc4;
- ip_version = 4;
- } else {
- assoc = &list[index].assoc6;
- ip_version = 6;
- }
-
- /* Initialize client timestamp. */
- assoc->timestamp = temp_time;
- memcpy(list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
-
- /* kill the other address, if it was set */
- memset(assoc, 0, sizeof(IPPTsPng));
- return 1;
-}
-
-/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
- */
-bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
- const uint8_t *cmp_pk)
-{
- uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
- IP_Port ip_port_bak;
-
- for (size_t i = 0; i < length; ++i) {
- if (id_closest(cmp_pk, nodes_list[i].public_key, pk) == 2) {
- memcpy(pk_bak, nodes_list[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- ip_port_bak = nodes_list[i].ip_port;
- memcpy(nodes_list[i].public_key, pk, CRYPTO_PUBLIC_KEY_SIZE);
- nodes_list[i].ip_port = ip_port;
-
- if (i != (length - 1)) {
- add_to_list(nodes_list, length, pk_bak, ip_port_bak, cmp_pk);
- }
-
- return 1;
- }
- }
-
- return 0;
-}
-
-/* TODO(irungentoo): change this to 7 when done*/
-#define HARDENING_ALL_OK 2
-/* return 0 if not.
- * return 1 if route request are ok
- * return 2 if it responds to send node packets correctly
- * return 4 if it can test other nodes correctly
- * return HARDENING_ALL_OK if all ok.
- */
-static uint8_t hardening_correct(const Hardening *h)
-{
- return h->routes_requests_ok + (h->send_nodes_ok << 1) + (h->testing_requests << 2);
-}
-/*
- * helper for get_close_nodes(). argument list is a monster :D
- */
-static void get_close_nodes_inner(const uint8_t *public_key, Node_format *nodes_list,
- Family sa_family, const Client_data *client_list, uint32_t client_list_length,
- uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good)
-{
- if ((sa_family != TOX_AF_INET) && (sa_family != TOX_AF_INET6) && (sa_family != 0)) {
- return;
- }
-
- uint32_t num_nodes = *num_nodes_ptr;
-
- for (uint32_t i = 0; i < client_list_length; i++) {
- const Client_data *client = &client_list[i];
-
- /* node already in list? */
- if (index_of_node_pk(nodes_list, MAX_SENT_NODES, client->public_key) != UINT32_MAX) {
- continue;
- }
-
- const IPPTsPng *ipptp = NULL;
-
- if (sa_family == TOX_AF_INET) {
- ipptp = &client->assoc4;
- } else if (sa_family == TOX_AF_INET6) {
- ipptp = &client->assoc6;
- } else if (client->assoc4.timestamp >= client->assoc6.timestamp) {
- ipptp = &client->assoc4;
- } else {
- ipptp = &client->assoc6;
- }
-
- /* node not in a good condition? */
- if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) {
- continue;
- }
-
- /* don't send LAN ips to non LAN peers */
- if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) {
- continue;
- }
-
- if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK
- && !id_equal(public_key, client->public_key)) {
- continue;
- }
-
- if (num_nodes < MAX_SENT_NODES) {
- memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
- nodes_list[num_nodes].ip_port = ipptp->ip_port;
- num_nodes++;
- } else {
- add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, ipptp->ip_port, public_key);
- }
- }
-
- *num_nodes_ptr = num_nodes;
-}
-
-/* Find MAX_SENT_NODES nodes closest to the public_key for the send nodes request:
- * put them in the nodes_list and return how many were found.
- *
- * TODO(irungentoo): For the love of based <your favorite deity, in doubt use
- * "love"> make this function cleaner and much more efficient.
- *
- * want_good : do we want only good nodes as checked with the hardening returned or not?
- */
-static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list,
- Family sa_family, uint8_t is_LAN, uint8_t want_good)
-{
- uint32_t num_nodes = 0;
- get_close_nodes_inner(public_key, nodes_list, sa_family,
- dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, 0);
-
- /* TODO(irungentoo): uncomment this when hardening is added to close friend clients */
-#if 0
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- get_close_nodes_inner(dht, public_key, nodes_list, sa_family,
- dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
- &num_nodes, is_LAN, want_good);
- }
-
-#endif
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- get_close_nodes_inner(public_key, nodes_list, sa_family,
- dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
- &num_nodes, is_LAN, 0);
- }
-
- return num_nodes;
-}
-
-int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
- uint8_t is_LAN, uint8_t want_good)
-{
- memset(nodes_list, 0, MAX_SENT_NODES * sizeof(Node_format));
- return get_somewhat_close_nodes(dht, public_key, nodes_list, sa_family, is_LAN, want_good);
-}
-
-typedef struct {
- const uint8_t *base_public_key;
- Client_data entry;
-} DHT_Cmp_data;
-
-static int cmp_dht_entry(const void *a, const void *b)
-{
- DHT_Cmp_data cmp1, cmp2;
- memcpy(&cmp1, a, sizeof(DHT_Cmp_data));
- memcpy(&cmp2, b, sizeof(DHT_Cmp_data));
- Client_data entry1 = cmp1.entry;
- Client_data entry2 = cmp2.entry;
- const uint8_t *cmp_public_key = cmp1.base_public_key;
-
-#define ASSOC_TIMEOUT(assoc) is_timeout((assoc).timestamp, BAD_NODE_TIMEOUT)
-
- bool t1 = ASSOC_TIMEOUT(entry1.assoc4) && ASSOC_TIMEOUT(entry1.assoc6);
- bool t2 = ASSOC_TIMEOUT(entry2.assoc4) && ASSOC_TIMEOUT(entry2.assoc6);
-
- if (t1 && t2) {
- return 0;
- }
-
- if (t1) {
- return -1;
- }
-
- if (t2) {
- return 1;
- }
-
-#define INCORRECT_HARDENING(assoc) hardening_correct(&(assoc).hardening) != HARDENING_ALL_OK
-
- t1 = INCORRECT_HARDENING(entry1.assoc4) && INCORRECT_HARDENING(entry1.assoc6);
- t2 = INCORRECT_HARDENING(entry2.assoc4) && INCORRECT_HARDENING(entry2.assoc6);
-
- if (t1 && !t2) {
- return -1;
- }
-
- if (!t1 && t2) {
- return 1;
- }
-
- int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
-
- if (close == 1) {
- return 1;
- }
-
- if (close == 2) {
- return -1;
- }
-
- return 0;
-}
-
-/* Is it ok to store node with public_key in client.
- *
- * return 0 if node can't be stored.
- * return 1 if it can.
- */
-static unsigned int store_node_ok(const Client_data *client, const uint8_t *public_key, const uint8_t *comp_public_key)
-{
- return is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) &&
- is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) ||
- id_closest(comp_public_key, client->public_key, public_key) == 2;
-}
-
-static void sort_client_list(Client_data *list, unsigned int length, const uint8_t *comp_public_key)
-{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- VLA(DHT_Cmp_data, cmp_list, length);
-
- for (uint32_t i = 0; i < length; i++) {
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
- }
-
- qsort(cmp_list, length, sizeof(DHT_Cmp_data), cmp_dht_entry);
-
- for (uint32_t i = 0; i < length; i++) {
- list[i] = cmp_list[i].entry;
- }
-}
-
-static void update_client_with_reset(Client_data *client, const IP_Port *ip_port)
-{
- IPPTsPng *ipptp_write = NULL;
- IPPTsPng *ipptp_clear = NULL;
-
- if (ip_port->ip.family == TOX_AF_INET) {
- ipptp_write = &client->assoc4;
- ipptp_clear = &client->assoc6;
- } else {
- ipptp_write = &client->assoc6;
- ipptp_clear = &client->assoc4;
- }
-
- ipptp_write->ip_port = *ip_port;
- ipptp_write->timestamp = unix_time();
-
- ip_reset(&ipptp_write->ret_ip_port.ip);
- ipptp_write->ret_ip_port.port = 0;
- ipptp_write->ret_timestamp = 0;
-
- /* zero out other address */
- memset(ipptp_clear, 0, sizeof(*ipptp_clear));
-}
-
-/* Replace a first bad (or empty) node with this one
- * or replace a possibly bad node (tests failed or not done yet)
- * that is further than any other in the list
- * from the comp_public_key
- * or replace a good node that is further
- * than any other in the list from the comp_public_key
- * and further than public_key.
- *
- * Do not replace any node if the list has no bad or possibly bad nodes
- * and all nodes in the list are closer to comp_public_key
- * than public_key.
- *
- * returns True(1) when the item was stored, False(0) otherwise */
-static int replace_all(Client_data *list,
- uint16_t length,
- const uint8_t *public_key,
- IP_Port ip_port,
- const uint8_t *comp_public_key)
-{
- if ((ip_port.ip.family != TOX_AF_INET) && (ip_port.ip.family != TOX_AF_INET6)) {
- return 0;
- }
-
- if (!store_node_ok(&list[1], public_key, comp_public_key) &&
- !store_node_ok(&list[0], public_key, comp_public_key)) {
- return 0;
- }
-
- sort_client_list(list, length, comp_public_key);
-
- Client_data *client = &list[0];
- id_copy(client->public_key, public_key);
-
- update_client_with_reset(client, &ip_port);
- return 1;
-}
-
-/* Add node to close list.
- *
- * simulate is set to 1 if we want to check if a node can be added to the list without adding it.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int add_to_close(DHT *dht, const uint8_t *public_key, IP_Port ip_port, bool simulate)
-{
- unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
-
- if (index >= LCLIENT_LENGTH) {
- index = LCLIENT_LENGTH - 1;
- }
-
- for (uint32_t i = 0; i < LCLIENT_NODES; ++i) {
- /* TODO(iphydf): write bounds checking test to catch the case that
- * index is left as >= LCLIENT_LENGTH */
- Client_data *client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
-
- if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
- !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
- continue;
- }
-
- if (simulate) {
- return 0;
- }
-
- id_copy(client->public_key, public_key);
- update_client_with_reset(client, &ip_port);
- return 0;
- }
-
- return -1;
-}
-
-/* Return 1 if node can be added to close list, 0 if it can't.
- */
-bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
-{
- return add_to_close(dht, public_key, ip_port, 1) == 0;
-}
-
-static bool is_pk_in_client_list(Client_data *list, unsigned int client_list_length, const uint8_t *public_key,
- IP_Port ip_port)
-{
- uint32_t index = index_of_client_pk(list, client_list_length, public_key);
-
- if (index == UINT32_MAX) {
- return 0;
- }
-
- const IPPTsPng *assoc = ip_port.ip.family == TOX_AF_INET ?
- &list[index].assoc4 :
- &list[index].assoc6;
-
- return !is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT);
-}
-
-static bool is_pk_in_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
-{
- unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
-
- if (index >= LCLIENT_LENGTH) {
- index = LCLIENT_LENGTH - 1;
- }
-
- return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key, ip_port);
-}
-
-/* Check if the node obtained with a get_nodes with public_key should be pinged.
- * NOTE: for best results call it after addto_lists;
- *
- * return 0 if the node should not be pinged.
- * return 1 if it should.
- */
-static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_key, IP_Port ip_port)
-{
- bool ret = 0;
-
- if (add_to_close(dht, public_key, ip_port, 1) == 0) {
- ret = 1;
- }
-
- unsigned int *num = &dht->num_to_bootstrap;
- uint32_t index = index_of_node_pk(dht->to_bootstrap, *num, public_key);
- bool in_close_list = is_pk_in_close_list(dht, public_key, ip_port);
-
- if (ret && index == UINT32_MAX && !in_close_list) {
- if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
- memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- dht->to_bootstrap[*num].ip_port = ip_port;
- ++*num;
- } else {
- // TODO(irungentoo): ipv6 vs v4
- add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
- }
- }
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- bool store_ok = 0;
-
- DHT_Friend *dht_friend = &dht->friends_list[i];
-
- if (store_node_ok(&dht_friend->client_list[1], public_key, dht_friend->public_key)) {
- store_ok = 1;
- }
-
- if (store_node_ok(&dht_friend->client_list[0], public_key, dht_friend->public_key)) {
- store_ok = 1;
- }
-
- unsigned int *friend_num = &dht_friend->num_to_bootstrap;
- const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
- const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, public_key, ip_port);
-
- if (store_ok && index == UINT32_MAX && !pk_in_list) {
- if (*friend_num < MAX_SENT_NODES) {
- Node_format *format = &dht_friend->to_bootstrap[*friend_num];
- memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- format->ip_port = ip_port;
- ++*friend_num;
- } else {
- add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key);
- }
-
- ret = 1;
- }
- }
-
- return ret;
-}
-
-/* Attempt to add client with ip_port and public_key to the friends client list
- * and close_clientlist.
- *
- * returns 1+ if the item is used in any list, 0 else
- */
-uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
-{
- uint32_t used = 0;
-
- /* convert IPv4-in-IPv6 to IPv4 */
- if ((ip_port.ip.family == TOX_AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) {
- ip_port.ip.family = TOX_AF_INET;
- ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
- }
-
- /* NOTE: Current behavior if there are two clients with the same id is
- * to replace the first ip by the second.
- */
- const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->close_clientlist,
- LCLIENT_LIST, public_key, ip_port);
-
- /* add_to_close should be called only if !in_list (don't extract to variable) */
- if (in_close_list || add_to_close(dht, public_key, ip_port, 0)) {
- used++;
- }
-
- DHT_Friend *friend_foundip = 0;
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- const bool in_list = client_or_ip_port_in_list(dht->log, dht->friends_list[i].client_list,
- MAX_FRIEND_CLIENTS, public_key, ip_port);
-
- /* replace_all should be called only if !in_list (don't extract to variable) */
- if (in_list || replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key,
- ip_port, dht->friends_list[i].public_key)) {
- DHT_Friend *dht_friend = &dht->friends_list[i];
-
- if (id_equal(public_key, dht_friend->public_key)) {
- friend_foundip = dht_friend;
- }
-
- used++;
- }
- }
-
- if (!friend_foundip) {
- return used;
- }
-
- for (uint32_t i = 0; i < friend_foundip->lock_count; ++i) {
- if (friend_foundip->callbacks[i].ip_callback) {
- friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data,
- friend_foundip->callbacks[i].number, ip_port);
- }
- }
-
- return used;
-}
-
-static bool update_client_data(Client_data *array, size_t size, IP_Port ip_port, const uint8_t *pk)
-{
- uint64_t temp_time = unix_time();
- uint32_t index = index_of_client_pk(array, size, pk);
-
- if (index == UINT32_MAX) {
- return false;
- }
-
- Client_data *data = &array[index];
- IPPTsPng *assoc;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- assoc = &data->assoc4;
- } else if (ip_port.ip.family == TOX_AF_INET6) {
- assoc = &data->assoc6;
- } else {
- return true;
- }
-
- assoc->ret_ip_port = ip_port;
- assoc->ret_timestamp = temp_time;
- return true;
-}
-
-/* If public_key is a friend or us, update ret_ip_port
- * nodepublic_key is the id of the node that sent us this info.
- */
-static void returnedip_ports(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *nodepublic_key)
-{
- /* convert IPv4-in-IPv6 to IPv4 */
- if ((ip_port.ip.family == TOX_AF_INET6) && IPV6_IPV4_IN_V6(ip_port.ip.ip6)) {
- ip_port.ip.family = TOX_AF_INET;
- ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
- }
-
- if (id_equal(public_key, dht->self_public_key)) {
- update_client_data(dht->close_clientlist, LCLIENT_LIST, ip_port, nodepublic_key);
- return;
- }
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- if (id_equal(public_key, dht->friends_list[i].public_key)) {
- Client_data *client_list = dht->friends_list[i].client_list;
-
- if (update_client_data(client_list, MAX_FRIEND_CLIENTS, ip_port, nodepublic_key)) {
- return;
- }
- }
- }
-}
-
-/* Send a getnodes request.
- sendback_node is the node that it will send back the response to (set to NULL to disable this) */
-static int getnodes(DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id,
- const Node_format *sendback_node)
-{
- /* Check if packet is going to be sent to ourself. */
- if (id_equal(public_key, dht->self_public_key)) {
- return -1;
- }
-
- uint8_t plain_message[sizeof(Node_format) * 2] = {0};
-
- Node_format receiver;
- memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- receiver.ip_port = ip_port;
- memcpy(plain_message, &receiver, sizeof(receiver));
-
- uint64_t ping_id = 0;
-
- if (sendback_node != NULL) {
- memcpy(plain_message + sizeof(receiver), sendback_node, sizeof(Node_format));
- ping_id = ping_array_add(&dht->dht_harden_ping_array, plain_message, sizeof(plain_message));
- } else {
- ping_id = ping_array_add(&dht->dht_ping_array, plain_message, sizeof(receiver));
- }
-
- if (ping_id == 0) {
- return -1;
- }
-
- uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)];
- uint8_t data[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
-
- memcpy(plain, client_id, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
-
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- DHT_get_shared_key_sent(dht, shared_key, public_key);
-
- int len = DHT_create_packet(dht->self_public_key, shared_key, NET_PACKET_GET_NODES,
- plain, sizeof(plain), data);
-
- if (len != sizeof(data)) {
- return -1;
- }
-
- return sendpacket(dht->net, ip_port, data, len);
-}
-
-/* Send a send nodes response: message for IPv6 nodes */
-static int sendnodes_ipv6(const DHT *dht, IP_Port ip_port, const uint8_t *public_key, const uint8_t *client_id,
- const uint8_t *sendback_data, uint16_t length, const uint8_t *shared_encryption_key)
-{
- /* Check if packet is going to be sent to ourself. */
- if (id_equal(public_key, dht->self_public_key)) {
- return -1;
- }
-
- if (length != sizeof(uint64_t)) {
- return -1;
- }
-
- size_t Node_format_size = sizeof(Node_format);
-
- Node_format nodes_list[MAX_SENT_NODES];
- uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1);
-
- VLA(uint8_t, plain, 1 + Node_format_size * MAX_SENT_NODES + length);
-
- int nodes_length = 0;
-
- if (num_nodes) {
- nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
-
- if (nodes_length <= 0) {
- return -1;
- }
- }
-
- plain[0] = num_nodes;
- memcpy(plain + 1 + nodes_length, sendback_data, length);
-
- const uint32_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
- VLA(uint8_t, data, 1 + nodes_length + length + crypto_size);
-
- int len = DHT_create_packet(dht->self_public_key, shared_encryption_key, NET_PACKET_SEND_NODES_IPV6,
- plain, 1 + nodes_length + length, data);
-
- if (len != SIZEOF_VLA(data)) {
- return -1;
- }
-
- return sendpacket(dht->net, ip_port, data, len);
-}
-
-#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
-
-static int handle_getnodes(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
- return 1;
- }
-
- DHT *dht = (DHT *)object;
-
- /* Check if packet is from ourself. */
- if (id_equal(packet + 1, dht->self_public_key)) {
- return 1;
- }
-
- uint8_t plain[CRYPTO_NODE_SIZE];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
-
- DHT_get_shared_key_recv(dht, shared_key, packet + 1);
- int len = decrypt_data_symmetric(shared_key,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
- CRYPTO_NODE_SIZE + CRYPTO_MAC_SIZE,
- plain);
-
- if (len != CRYPTO_NODE_SIZE) {
- return 1;
- }
-
- sendnodes_ipv6(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
-
- add_to_ping(dht->ping, packet + 1, source);
-
- return 0;
-}
-/* return 0 if no
- return 1 if yes */
-static uint8_t sent_getnode_to_node(DHT *dht, const uint8_t *public_key, IP_Port node_ip_port, uint64_t ping_id,
- Node_format *sendback_node)
-{
- uint8_t data[sizeof(Node_format) * 2];
-
- if (ping_array_check(data, sizeof(data), &dht->dht_ping_array, ping_id) == sizeof(Node_format)) {
- memset(sendback_node, 0, sizeof(Node_format));
- } else if (ping_array_check(data, sizeof(data), &dht->dht_harden_ping_array, ping_id) == sizeof(data)) {
- memcpy(sendback_node, data + sizeof(Node_format), sizeof(Node_format));
- } else {
- return 0;
- }
-
- Node_format test;
- memcpy(&test, data, sizeof(Node_format));
-
- if (!ipport_equal(&test.ip_port, &node_ip_port) || !id_equal(test.public_key, public_key)) {
- return 0;
- }
-
- return 1;
-}
-
-/* Function is needed in following functions. */
-static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
- const uint8_t *nodes_data, uint16_t nodes_data_length);
-
-static int handle_sendnodes_core(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
- Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out)
-{
- DHT *dht = (DHT *)object;
- uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
-
- if (length < cid_size) { /* too short */
- return 1;
- }
-
- uint32_t data_size = length - cid_size;
-
- if (data_size == 0) {
- return 1;
- }
-
- if (data_size > sizeof(Node_format) * MAX_SENT_NODES) { /* invalid length */
- return 1;
- }
-
- VLA(uint8_t, plain, 1 + data_size + sizeof(uint64_t));
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- DHT_get_shared_key_sent(dht, shared_key, packet + 1);
- int len = decrypt_data_symmetric(
- shared_key,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
- 1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
- plain);
-
- if ((unsigned int)len != SIZEOF_VLA(plain)) {
- return 1;
- }
-
- if (plain[0] > size_plain_nodes) {
- return 1;
- }
-
- Node_format sendback_node;
-
- uint64_t ping_id;
- memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
-
- if (!sent_getnode_to_node(dht, packet + 1, source, ping_id, &sendback_node)) {
- return 1;
- }
-
- uint16_t length_nodes = 0;
- int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0);
-
- if (length_nodes != data_size) {
- return 1;
- }
-
- if (num_nodes != plain[0]) {
- return 1;
- }
-
- if (num_nodes < 0) {
- return 1;
- }
-
- /* store the address the *request* was sent to */
- addto_lists(dht, source, packet + 1);
-
- *num_nodes_out = num_nodes;
-
- send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size);
- return 0;
-}
-
-static int handle_sendnodes_ipv6(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
- Node_format plain_nodes[MAX_SENT_NODES];
- uint32_t num_nodes;
-
- if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
- return 1;
- }
-
- if (num_nodes == 0) {
- return 0;
- }
-
- for (uint32_t i = 0; i < num_nodes; i++) {
- if (ipport_isset(&plain_nodes[i].ip_port)) {
- ping_node_from_getnodes_ok(dht, plain_nodes[i].public_key, plain_nodes[i].ip_port);
- returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
- }
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------------*/
-/*------------------------END of packet handling functions--------------------------*/
-
-int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port),
- void *data, int32_t number, uint16_t *lock_count)
-{
- uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
-
- uint16_t lock_num;
-
- if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */
- DHT_Friend *dht_friend = &dht->friends_list[friend_num];
-
- if (dht_friend->lock_count == DHT_FRIEND_MAX_LOCKS) {
- return -1;
- }
-
- lock_num = dht_friend->lock_count;
- ++dht_friend->lock_count;
- dht_friend->callbacks[lock_num].ip_callback = ip_callback;
- dht_friend->callbacks[lock_num].data = data;
- dht_friend->callbacks[lock_num].number = number;
-
- if (lock_count) {
- *lock_count = lock_num + 1;
- }
-
- return 0;
- }
-
- DHT_Friend *temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
-
- if (temp == NULL) {
- return -1;
- }
-
- dht->friends_list = temp;
- DHT_Friend *dht_friend = &dht->friends_list[dht->num_friends];
- memset(dht_friend, 0, sizeof(DHT_Friend));
- memcpy(dht_friend->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- dht_friend->nat.NATping_id = random_64b();
- ++dht->num_friends;
-
- lock_num = dht_friend->lock_count;
- ++dht_friend->lock_count;
- dht_friend->callbacks[lock_num].ip_callback = ip_callback;
- dht_friend->callbacks[lock_num].data = data;
- dht_friend->callbacks[lock_num].number = number;
-
- if (lock_count) {
- *lock_count = lock_num + 1;
- }
-
- dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, 0, 1, 0);
-
- return 0;
-}
-
-int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count)
-{
- uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
-
- if (friend_num == UINT32_MAX) {
- return -1;
- }
-
- DHT_Friend *dht_friend = &dht->friends_list[friend_num];
- --dht_friend->lock_count;
-
- if (dht_friend->lock_count && lock_count) { /* DHT friend is still in use.*/
- --lock_count;
- dht_friend->callbacks[lock_count].ip_callback = NULL;
- dht_friend->callbacks[lock_count].data = NULL;
- dht_friend->callbacks[lock_count].number = 0;
- return 0;
- }
-
- --dht->num_friends;
-
- if (dht->num_friends != friend_num) {
- memcpy(&dht->friends_list[friend_num],
- &dht->friends_list[dht->num_friends],
- sizeof(DHT_Friend));
- }
-
- if (dht->num_friends == 0) {
- free(dht->friends_list);
- dht->friends_list = NULL;
- return 0;
- }
-
- DHT_Friend *temp = (DHT_Friend *)realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
-
- if (temp == NULL) {
- return -1;
- }
-
- dht->friends_list = temp;
- return 0;
-}
-
-/* TODO(irungentoo): Optimize this. */
-int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
-{
- ip_reset(&ip_port->ip);
- ip_port->port = 0;
-
- uint32_t friend_index = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
-
- if (friend_index == UINT32_MAX) {
- return -1;
- }
-
- DHT_Friend *frnd = &dht->friends_list[friend_index];
- uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);
-
- if (client_index == -1) {
- return 0;
- }
-
- Client_data *client = &frnd->client_list[client_index];
- IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
-
- for (size_t i = 0; i < ASSOC_COUNT; i++) {
- IPPTsPng *assoc = assocs[i];
-
- if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
- *ip_port = assoc->ip_port;
- return 1;
- }
- }
-
- return -1;
-}
-
-/* returns number of nodes not in kill-timeout */
-static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, const uint8_t *public_key,
- Client_data *list, uint32_t list_count, uint32_t *bootstrap_times, bool sortable)
-{
- uint8_t not_kill = 0;
- uint64_t temp_time = unix_time();
-
- uint32_t num_nodes = 0;
- VLA(Client_data *, client_list, list_count * 2);
- VLA(IPPTsPng *, assoc_list, list_count * 2);
- unsigned int sort = 0;
- bool sort_ok = 0;
-
- for (uint32_t i = 0; i < list_count; i++) {
- /* If node is not dead. */
- Client_data *client = &list[i];
-
- IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
-
- for (size_t i = 0; i < ASSOC_COUNT; i++) {
- IPPTsPng *assoc = assocs[i];
-
- if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) {
- sort = 0;
- not_kill++;
-
- if (is_timeout(assoc->last_pinged, PING_INTERVAL)) {
- getnodes(dht, assoc->ip_port, client->public_key, public_key, NULL);
- assoc->last_pinged = temp_time;
- }
-
- /* If node is good. */
- if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) {
- client_list[num_nodes] = client;
- assoc_list[num_nodes] = assoc;
- ++num_nodes;
- }
- } else {
- ++sort;
-
- /* Timed out should be at beginning, if they are not, sort the list. */
- if (sort > 1 && sort < (((i + 1) * 2) - 1)) {
- sort_ok = 1;
- }
- }
- }
- }
-
- if (sortable && sort_ok) {
- sort_client_list(list, list_count, public_key);
- }
-
- if ((num_nodes != 0) && (is_timeout(*lastgetnode, GET_NODE_INTERVAL) || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
- uint32_t rand_node = rand() % (num_nodes);
-
- if ((num_nodes - 1) != rand_node) {
- rand_node += rand() % (num_nodes - (rand_node + 1));
- }
-
- getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->public_key, public_key, NULL);
-
- *lastgetnode = temp_time;
- ++*bootstrap_times;
- }
-
- return not_kill;
-}
-
-/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
- * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
- */
-static void do_DHT_friends(DHT *dht)
-{
- for (size_t i = 0; i < dht->num_friends; ++i) {
- DHT_Friend *dht_friend = &dht->friends_list[i];
-
- for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
- getnodes(dht, dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key,
- NULL);
- }
-
- dht_friend->num_to_bootstrap = 0;
-
- do_ping_and_sendnode_requests(dht, &dht_friend->lastgetnode, dht_friend->public_key, dht_friend->client_list,
- MAX_FRIEND_CLIENTS,
- &dht_friend->bootstrap_times, 1);
- }
-}
-
-/* Ping each client in the close nodes list every PING_INTERVAL seconds.
- * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
- */
-static void do_Close(DHT *dht)
-{
- for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
- getnodes(dht, dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key, NULL);
- }
-
- dht->num_to_bootstrap = 0;
-
- uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key,
- dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times, 0);
-
- if (!not_killed) {
- /* all existing nodes are at least KILL_NODE_TIMEOUT,
- * which means we are mute, as we only send packets to
- * nodes NOT in KILL_NODE_TIMEOUT
- *
- * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
- * KILL_NODE_TIMEOUT, so we at least keep trying pings */
- uint64_t badonly = unix_time() - BAD_NODE_TIMEOUT;
-
- for (size_t i = 0; i < LCLIENT_LIST; i++) {
- Client_data *client = &dht->close_clientlist[i];
-
- IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
-
- for (size_t j = 0; j < ASSOC_COUNT; j++) {
- IPPTsPng *assoc = assocs[j];
-
- if (assoc->timestamp) {
- assoc->timestamp = badonly;
- }
- }
- }
- }
-}
-
-void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id)
-{
- getnodes(dht, *from_ipp, from_id, which_id, NULL);
-}
-
-void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
-{
- getnodes(dht, ip_port, public_key, dht->self_public_key, NULL);
-}
-int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
- uint16_t port, const uint8_t *public_key)
-{
- IP_Port ip_port_v64;
- IP *ip_extra = NULL;
- IP_Port ip_port_v4;
- ip_init(&ip_port_v64.ip, ipv6enabled);
-
- if (ipv6enabled) {
- /* setup for getting BOTH: an IPv6 AND an IPv4 address */
- ip_port_v64.ip.family = TOX_AF_UNSPEC;
- ip_reset(&ip_port_v4.ip);
- ip_extra = &ip_port_v4.ip;
- }
-
- if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
- ip_port_v64.port = port;
- DHT_bootstrap(dht, ip_port_v64, public_key);
-
- if ((ip_extra != NULL) && ip_isset(ip_extra)) {
- ip_port_v4.port = port;
- DHT_bootstrap(dht, ip_port_v4, public_key);
- }
-
- return 1;
- }
-
- return 0;
-}
-
-/* Send the given packet to node with public_key
- *
- * return -1 if failure.
- */
-int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
-{
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- if (id_equal(public_key, dht->close_clientlist[i].public_key)) {
- const Client_data *client = &dht->close_clientlist[i];
- const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc6, &client->assoc4 };
-
- for (size_t j = 0; j < ASSOC_COUNT; j++) {
- const IPPTsPng *assoc = assocs[j];
-
- if (ip_isset(&assoc->ip_port.ip)) {
- return sendpacket(dht->net, assoc->ip_port, packet, length);
- }
- }
-
- break;
- }
- }
-
- return -1;
-}
-
-/* Puts all the different ips returned by the nodes for a friend_num into array ip_portlist.
- * ip_portlist must be at least MAX_FRIEND_CLIENTS big.
- *
- * return the number of ips returned.
- * return 0 if we are connected to friend or if no ips were found.
- * return -1 if no such friend.
- */
-static int friend_iplist(const DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
-{
- if (friend_num >= dht->num_friends) {
- return -1;
- }
-
- DHT_Friend *dht_friend = &dht->friends_list[friend_num];
- Client_data *client;
- IP_Port ipv4s[MAX_FRIEND_CLIENTS];
- int num_ipv4s = 0;
- IP_Port ipv6s[MAX_FRIEND_CLIENTS];
- int num_ipv6s = 0;
-
- for (size_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
- client = &(dht_friend->client_list[i]);
-
- /* If ip is not zero and node is good. */
- if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
- ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
- ++num_ipv4s;
- }
-
- if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
- ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
- ++num_ipv6s;
- }
-
- if (id_equal(client->public_key, dht_friend->public_key)) {
- if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)
- || !is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT)) {
- return 0; /* direct connectivity */
- }
- }
- }
-
-#ifdef FRIEND_IPLIST_PAD
- memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
-
- if (num_ipv6s == MAX_FRIEND_CLIENTS) {
- return MAX_FRIEND_CLIENTS;
- }
-
- int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
-
- if (num_ipv4s_used > num_ipv4s) {
- num_ipv4s_used = num_ipv4s;
- }
-
- memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
- return num_ipv6s + num_ipv4s_used;
-
-#else /* !FRIEND_IPLIST_PAD */
-
- /* there must be some secret reason why we can't pad the longer list
- * with the shorter one...
- */
- if (num_ipv6s >= num_ipv4s) {
- memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
- return num_ipv6s;
- }
-
- memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
- return num_ipv4s;
-
-#endif /* !FRIEND_IPLIST_PAD */
-}
-
-
-/* Send the following packet to everyone who tells us they are connected to friend_id.
- *
- * return ip for friend.
- * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4).
- */
-int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
-{
- uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
-
- if (num == UINT32_MAX) {
- return 0;
- }
-
- uint32_t sent = 0;
- uint8_t friend_sent[MAX_FRIEND_CLIENTS] = {0};
-
- IP_Port ip_list[MAX_FRIEND_CLIENTS];
- int ip_num = friend_iplist(dht, ip_list, num);
-
- if (ip_num < (MAX_FRIEND_CLIENTS / 4)) {
- return 0; /* Reason for that? */
- }
-
- DHT_Friend *dht_friend = &dht->friends_list[num];
- Client_data *client;
-
- /* extra legwork, because having the outside allocating the space for us
- * is *usually* good(tm) (bites us in the behind in this case though) */
-
- for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
- if (friend_sent[i]) {/* Send one packet per client.*/
- continue;
- }
-
- client = &dht_friend->client_list[i];
-
- const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc4, &client->assoc6 };
-
- for (size_t j = 0; j < ASSOC_COUNT; j++) {
- const IPPTsPng *assoc = assocs[j];
-
- /* If ip is not zero and node is good. */
- if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
- int retval = sendpacket(dht->net, assoc->ip_port, packet, length);
-
- if ((unsigned int)retval == length) {
- ++sent;
- friend_sent[i] = 1;
- }
- }
- }
- }
-
- return sent;
-}
-
-/* Send the following packet to one random person who tells us they are connected to friend_id.
- *
- * return number of nodes the packet was sent to.
- */
-static int routeone_tofriend(DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length)
-{
- uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
-
- if (num == UINT32_MAX) {
- return 0;
- }
-
- DHT_Friend *dht_friend = &dht->friends_list[num];
- Client_data *client;
-
- IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
- int n = 0;
-
- /* extra legwork, because having the outside allocating the space for us
- * is *usually* good(tm) (bites us in the behind in this case though) */
-
- for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
- client = &dht_friend->client_list[i];
-
- const IPPTsPng *assocs[ASSOC_COUNT] = { &client->assoc4, &client->assoc6 };
-
- for (size_t j = 0; j < ASSOC_COUNT; j++) {
- const IPPTsPng *assoc = assocs[j];
-
- /* If ip is not zero and node is good. */
- if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
- ip_list[n] = assoc->ip_port;
- ++n;
- }
- }
- }
-
- if (n < 1) {
- return 0;
- }
-
- int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length);
-
- if ((unsigned int)retval == length) {
- return 1;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------------*/
-/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
-
-static int send_NATping(DHT *dht, const uint8_t *public_key, uint64_t ping_id, uint8_t type)
-{
- uint8_t data[sizeof(uint64_t) + 1];
- uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
-
- int num = 0;
-
- data[0] = type;
- memcpy(data + 1, &ping_id, sizeof(uint64_t));
- /* 254 is NAT ping request packet id */
- int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data,
- sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
-
- if (len == -1) {
- return -1;
- }
-
- if (type == 0) { /* If packet is request use many people to route it. */
- num = route_tofriend(dht, public_key, packet, len);
- } else if (type == 1) { /* If packet is response use only one person to route it */
- num = routeone_tofriend(dht, public_key, packet, len);
- }
-
- if (num == 0) {
- return -1;
- }
-
- return num;
-}
-
-/* Handle a received ping request for. */
-static int handle_NATping(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
- uint16_t length, void *userdata)
-{
- if (length != sizeof(uint64_t) + 1) {
- return 1;
- }
-
- DHT *dht = (DHT *)object;
- uint64_t ping_id;
- memcpy(&ping_id, packet + 1, sizeof(uint64_t));
-
- uint32_t friendnumber = index_of_friend_pk(dht->friends_list, dht->num_friends, source_pubkey);
-
- if (friendnumber == UINT32_MAX) {
- return 1;
- }
-
- DHT_Friend *dht_friend = &dht->friends_list[friendnumber];
-
- if (packet[0] == NAT_PING_REQUEST) {
- /* 1 is reply */
- send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
- dht_friend->nat.recvNATping_timestamp = unix_time();
- return 0;
- }
-
- if (packet[0] == NAT_PING_RESPONSE) {
- if (dht_friend->nat.NATping_id == ping_id) {
- dht_friend->nat.NATping_id = random_64b();
- dht_friend->nat.hole_punching = 1;
- return 0;
- }
- }
-
- return 1;
-}
-
-/* Get the most common ip in the ip_portlist.
- * Only return ip if it appears in list min_num or more.
- * len must not be bigger than MAX_FRIEND_CLIENTS.
- *
- * return ip of 0 if failure.
- */
-static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
-{
- IP zero;
- ip_reset(&zero);
-
- if (len > MAX_FRIEND_CLIENTS) {
- return zero;
- }
-
- uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
-
- for (uint32_t i = 0; i < len; ++i) {
- for (uint32_t j = 0; j < len; ++j) {
- if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) {
- ++numbers[i];
- }
- }
-
- if (numbers[i] >= min_num) {
- return ip_portlist[i].ip;
- }
- }
-
- return zero;
-}
-
-/* Return all the ports for one ip in a list.
- * portlist must be at least len long,
- * where len is the length of ip_portlist.
- *
- * return number of ports and puts the list of ports in portlist.
- */
-static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t len, IP ip)
-{
- uint16_t num = 0;
-
- for (uint32_t i = 0; i < len; ++i) {
- if (ip_equal(&ip_portlist[i].ip, &ip)) {
- portlist[num] = net_ntohs(ip_portlist[i].port);
- ++num;
- }
- }
-
- return num;
-}
-
-static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
-{
- if (!dht->hole_punching_enabled) {
- return;
- }
-
- if (numports > MAX_FRIEND_CLIENTS || numports == 0) {
- return;
- }
-
- uint16_t first_port = port_list[0];
- uint32_t i;
-
- for (i = 0; i < numports; ++i) {
- if (first_port != port_list[i]) {
- break;
- }
- }
-
- if (i == numports) { /* If all ports are the same, only try that one port. */
- IP_Port pinging;
- ip_copy(&pinging.ip, &ip);
- pinging.port = net_htons(first_port);
- send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
- } else {
- for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
- /* TODO(irungentoo): Improve port guessing algorithm. */
- uint32_t it = i + dht->friends_list[friend_num].nat.punching_index;
- int8_t sign = (it % 2) ? -1 : 1;
- uint32_t delta = sign * (it / (2 * numports));
- uint32_t index = (it / 2) % numports;
- uint16_t port = port_list[index] + delta;
- IP_Port pinging;
- ip_copy(&pinging.ip, &ip);
- pinging.port = net_htons(port);
- send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
- }
-
- dht->friends_list[friend_num].nat.punching_index += i;
- }
-
- if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {
- uint16_t port = 1024;
- IP_Port pinging;
- ip_copy(&pinging.ip, &ip);
-
- for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
- uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
- pinging.port = net_htons(port + it);
- send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].public_key);
- }
-
- dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2);
- }
-
- ++dht->friends_list[friend_num].nat.tries;
-}
-
-static void do_NAT(DHT *dht)
-{
- uint64_t temp_time = unix_time();
-
- for (uint32_t i = 0; i < dht->num_friends; ++i) {
- IP_Port ip_list[MAX_FRIEND_CLIENTS];
- int num = friend_iplist(dht, ip_list, i);
-
- /* If already connected or friend is not online don't try to hole punch. */
- if (num < MAX_FRIEND_CLIENTS / 2) {
- continue;
- }
-
- if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) {
- send_NATping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST);
- dht->friends_list[i].nat.NATping_timestamp = temp_time;
- }
-
- if (dht->friends_list[i].nat.hole_punching == 1 &&
- dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
- dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
-
- IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
-
- if (!ip_isset(&ip)) {
- continue;
- }
-
- if (dht->friends_list[i].nat.punching_timestamp + PUNCH_RESET_TIME < temp_time) {
- dht->friends_list[i].nat.tries = 0;
- dht->friends_list[i].nat.punching_index = 0;
- dht->friends_list[i].nat.punching_index2 = 0;
- }
-
- uint16_t port_list[MAX_FRIEND_CLIENTS];
- uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
- punch_holes(dht, ip, port_list, numports, i);
-
- dht->friends_list[i].nat.punching_timestamp = temp_time;
- dht->friends_list[i].nat.hole_punching = 0;
- }
- }
-}
-
-/*----------------------------------------------------------------------------------*/
-/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
-
-#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/
-
-#define CHECK_TYPE_ROUTE_REQ 0
-#define CHECK_TYPE_ROUTE_RES 1
-#define CHECK_TYPE_GETNODE_REQ 2
-#define CHECK_TYPE_GETNODE_RES 3
-#define CHECK_TYPE_TEST_REQ 4
-#define CHECK_TYPE_TEST_RES 5
-
-#if DHT_HARDENING
-static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8_t *contents, uint16_t length)
-{
- if (length > HARDREQ_DATA_SIZE - 1) {
- return -1;
- }
-
- uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
- uint8_t data[HARDREQ_DATA_SIZE] = {0};
- data[0] = type;
- memcpy(data + 1, contents, length);
- int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
- sizeof(data), CRYPTO_PACKET_HARDENING);
-
- if (len == -1) {
- return -1;
- }
-
- return sendpacket(dht->net, sendto->ip_port, packet, len);
-}
-
-/* Send a get node hardening request */
-static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format *node_totest, uint8_t *search_id)
-{
- uint8_t data[sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE];
- memcpy(data, node_totest, sizeof(Node_format));
- memcpy(data + sizeof(Node_format), search_id, CRYPTO_PUBLIC_KEY_SIZE);
- return send_hardening_req(dht, dest, CHECK_TYPE_GETNODE_REQ, data, sizeof(Node_format) + CRYPTO_PUBLIC_KEY_SIZE);
-}
-#endif
-
-/* Send a get node hardening response */
-static int send_hardening_getnode_res(const DHT *dht, const Node_format *sendto, const uint8_t *queried_client_id,
- const uint8_t *nodes_data, uint16_t nodes_data_length)
-{
- if (!ip_isset(&sendto->ip_port.ip)) {
- return -1;
- }
-
- uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
- VLA(uint8_t, data, 1 + CRYPTO_PUBLIC_KEY_SIZE + nodes_data_length);
- data[0] = CHECK_TYPE_GETNODE_RES;
- memcpy(data + 1, queried_client_id, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(data + 1 + CRYPTO_PUBLIC_KEY_SIZE, nodes_data, nodes_data_length);
- int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->public_key, data,
- SIZEOF_VLA(data), CRYPTO_PACKET_HARDENING);
-
- if (len == -1) {
- return -1;
- }
-
- return sendpacket(dht->net, sendto->ip_port, packet, len);
-}
-
-/* TODO(irungentoo): improve */
-static IPPTsPng *get_closelist_IPPTsPng(DHT *dht, const uint8_t *public_key, Family sa_family)
-{
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- if (!id_equal(dht->close_clientlist[i].public_key, public_key)) {
- continue;
- }
-
- if (sa_family == TOX_AF_INET) {
- return &dht->close_clientlist[i].assoc4;
- }
-
- if (sa_family == TOX_AF_INET6) {
- return &dht->close_clientlist[i].assoc6;
- }
- }
-
- return NULL;
-}
-
-/*
- * check how many nodes in nodes are also present in the closelist.
- * TODO(irungentoo): make this function better.
- */
-static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num)
-{
- uint32_t counter = 0;
-
- for (uint32_t i = 0; i < num; ++i) {
- if (id_equal(nodes[i].public_key, dht->self_public_key)) {
- ++counter;
- continue;
- }
-
- IPPTsPng *temp = get_closelist_IPPTsPng(dht, nodes[i].public_key, nodes[i].ip_port.ip.family);
-
- if (temp) {
- if (!is_timeout(temp->timestamp, BAD_NODE_TIMEOUT)) {
- ++counter;
- }
- }
- }
-
- return counter;
-}
-
-/* Interval in seconds between hardening checks */
-#define HARDENING_INTERVAL 120
-#define HARDEN_TIMEOUT 1200
-
-/* Handle a received hardening packet */
-static int handle_hardening(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
- uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
-
- if (length < 2) {
- return 1;
- }
-
- switch (packet[0]) {
- case CHECK_TYPE_GETNODE_REQ: {
- if (length != HARDREQ_DATA_SIZE) {
- return 1;
- }
-
- Node_format node, tocheck_node;
- node.ip_port = source;
- memcpy(node.public_key, source_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(&tocheck_node, packet + 1, sizeof(Node_format));
-
- if (getnodes(dht, tocheck_node.ip_port, tocheck_node.public_key, packet + 1 + sizeof(Node_format), &node) == -1) {
- return 1;
- }
-
- return 0;
- }
-
- case CHECK_TYPE_GETNODE_RES: {
- if (length <= CRYPTO_PUBLIC_KEY_SIZE + 1) {
- return 1;
- }
-
- if (length > 1 + CRYPTO_PUBLIC_KEY_SIZE + sizeof(Node_format) * MAX_SENT_NODES) {
- return 1;
- }
-
- uint16_t length_nodes = length - 1 - CRYPTO_PUBLIC_KEY_SIZE;
- Node_format nodes[MAX_SENT_NODES];
- int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length_nodes, 0);
-
- /* TODO(irungentoo): MAX_SENT_NODES nodes should be returned at all times
- (right now we have a small network size so it could cause problems for testing and etc..) */
- if (num_nodes <= 0) {
- return 1;
- }
-
- /* NOTE: This should work for now but should be changed to something better. */
- if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) {
- return 1;
- }
-
- IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family);
-
- if (temp == NULL) {
- return 1;
- }
-
- if (is_timeout(temp->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
- return 1;
- }
-
- if (!id_equal(temp->hardening.send_nodes_pingedid, source_pubkey)) {
- return 1;
- }
-
- /* If Nodes look good and the request checks out */
- temp->hardening.send_nodes_ok = 1;
- return 0;/* success*/
- }
- }
-
- return 1;
-}
-
-#if DHT_HARDENING
-/* Return a random node from all the nodes we are connected to.
- * TODO(irungentoo): improve this function.
- */
-static Node_format random_node(DHT *dht, Family sa_family)
-{
- uint8_t id[CRYPTO_PUBLIC_KEY_SIZE];
-
- for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE / 4; ++i) { /* populate the id with pseudorandom bytes.*/
- uint32_t t = rand();
- memcpy(id + i * sizeof(t), &t, sizeof(t));
- }
-
- Node_format nodes_list[MAX_SENT_NODES];
- memset(nodes_list, 0, sizeof(nodes_list));
- uint32_t num_nodes = get_close_nodes(dht, id, nodes_list, sa_family, 1, 0);
-
- if (num_nodes == 0) {
- return nodes_list[0];
- }
-
- return nodes_list[rand() % num_nodes];
-}
-#endif
-
-/* Put up to max_num nodes in nodes from the closelist.
- *
- * return the number of nodes.
- */
-static uint16_t list_nodes(Client_data *list, size_t length, Node_format *nodes, uint16_t max_num)
-{
- if (max_num == 0) {
- return 0;
- }
-
- uint16_t count = 0;
-
- for (size_t i = length; i != 0; --i) {
- IPPTsPng *assoc = NULL;
-
- if (!is_timeout(list[i - 1].assoc4.timestamp, BAD_NODE_TIMEOUT)) {
- assoc = &list[i - 1].assoc4;
- }
-
- if (!is_timeout(list[i - 1].assoc6.timestamp, BAD_NODE_TIMEOUT)) {
- if (assoc == NULL) {
- assoc = &list[i - 1].assoc6;
- } else if (rand() % 2) {
- assoc = &list[i - 1].assoc6;
- }
- }
-
- if (assoc != NULL) {
- memcpy(nodes[count].public_key, list[i - 1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- nodes[count].ip_port = assoc->ip_port;
- ++count;
-
- if (count >= max_num) {
- return count;
- }
- }
- }
-
- return count;
-}
-
-/* Put up to max_num nodes in nodes from the random friends.
- *
- * return the number of nodes.
- */
-uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
-{
- if (max_num == 0) {
- return 0;
- }
-
- uint16_t count = 0;
- unsigned int r = rand();
-
- for (size_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
- count += list_nodes(dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list, MAX_FRIEND_CLIENTS, nodes + count,
- max_num - count);
-
- if (count >= max_num) {
- break;
- }
- }
-
- return count;
-}
-
-/* Put up to max_num nodes in nodes from the closelist.
- *
- * return the number of nodes.
- */
-uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num)
-{
- return list_nodes(dht->close_clientlist, LCLIENT_LIST, nodes, max_num);
-}
-
-#if DHT_HARDENING
-static void do_hardening(DHT *dht)
-{
- for (uint32_t i = 0; i < LCLIENT_LIST * 2; ++i) {
- IPPTsPng *cur_iptspng;
- Family sa_family;
- uint8_t *public_key = dht->close_clientlist[i / 2].public_key;
-
- if (i % 2 == 0) {
- cur_iptspng = &dht->close_clientlist[i / 2].assoc4;
- sa_family = TOX_AF_INET;
- } else {
- cur_iptspng = &dht->close_clientlist[i / 2].assoc6;
- sa_family = TOX_AF_INET6;
- }
-
- if (is_timeout(cur_iptspng->timestamp, BAD_NODE_TIMEOUT)) {
- continue;
- }
-
- if (cur_iptspng->hardening.send_nodes_ok == 0) {
- if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDENING_INTERVAL)) {
- Node_format rand_node = random_node(dht, sa_family);
-
- if (!ipport_isset(&rand_node.ip_port)) {
- continue;
- }
-
- if (id_equal(public_key, rand_node.public_key)) {
- continue;
- }
-
- Node_format to_test;
- to_test.ip_port = cur_iptspng->ip_port;
- memcpy(to_test.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- // TODO(irungentoo): The search id should maybe not be ours?
- if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) {
- memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.public_key, CRYPTO_PUBLIC_KEY_SIZE);
- cur_iptspng->hardening.send_nodes_timestamp = unix_time();
- }
- }
- } else {
- if (is_timeout(cur_iptspng->hardening.send_nodes_timestamp, HARDEN_TIMEOUT)) {
- cur_iptspng->hardening.send_nodes_ok = 0;
- }
- }
-
- // TODO(irungentoo): add the 2 other testers.
- }
-}
-#endif
-
-/*----------------------------------------------------------------------------------*/
-
-void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object)
-{
- dht->cryptopackethandlers[byte].function = cb;
- dht->cryptopackethandlers[byte].object = object;
-}
-
-static int cryptopacket_handle(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
-
- assert(packet[0] == NET_PACKET_CRYPTO);
-
- if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE ||
- length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) {
- return 1;
- }
-
- // Check if request is for us.
- if (id_equal(packet + 1, dht->self_public_key)) {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
- uint8_t number;
- int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length);
-
- if (len == -1 || len == 0) {
- return 1;
- }
-
- if (!dht->cryptopackethandlers[number].function) {
- return 1;
- }
-
- return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key,
- data, len, userdata);
- }
-
- /* If request is not for us, try routing it. */
- int retval = route_packet(dht, packet + 1, packet, length);
-
- if ((unsigned int)retval == length) {
- return 0;
- }
-
- return 1;
-}
-
-/*----------------------------------------------------------------------------------*/
-
-DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled)
-{
- /* init time */
- unix_time_update();
-
- if (net == NULL) {
- return NULL;
- }
-
- DHT *dht = (DHT *)calloc(1, sizeof(DHT));
-
- if (dht == NULL) {
- return NULL;
- }
-
- dht->log = log;
- dht->net = net;
-
- dht->hole_punching_enabled = holepunching_enabled;
-
- dht->ping = new_ping(dht);
-
- if (dht->ping == NULL) {
- kill_DHT(dht);
- return NULL;
- }
-
- networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht);
- networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht);
- networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
- cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht);
- cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht);
-
- new_symmetric_key(dht->secret_symmetric_key);
- crypto_new_keypair(dht->self_public_key, dht->self_secret_key);
-
- ping_array_init(&dht->dht_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
- ping_array_init(&dht->dht_harden_ping_array, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
-
- for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
- uint8_t random_key_bytes[CRYPTO_PUBLIC_KEY_SIZE];
- random_bytes(random_key_bytes, sizeof(random_key_bytes));
-
- if (DHT_addfriend(dht, random_key_bytes, 0, 0, 0, 0) != 0) {
- kill_DHT(dht);
- return NULL;
- }
- }
-
- return dht;
-}
-
-void do_DHT(DHT *dht)
-{
- unix_time_update();
-
- if (dht->last_run == unix_time()) {
- return;
- }
-
- // Load friends/clients if first call to do_DHT
- if (dht->loaded_num_nodes) {
- DHT_connect_after_load(dht);
- }
-
- do_Close(dht);
- do_DHT_friends(dht);
- do_NAT(dht);
- do_to_ping(dht->ping);
-#if DHT_HARDENING
- do_hardening(dht);
-#endif
- dht->last_run = unix_time();
-}
-void kill_DHT(DHT *dht)
-{
- networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL);
- networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL);
- cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL);
- cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL);
- ping_array_free_all(&dht->dht_ping_array);
- ping_array_free_all(&dht->dht_harden_ping_array);
- kill_ping(dht->ping);
- free(dht->friends_list);
- free(dht->loaded_nodes_list);
- free(dht);
-}
-
-/* new DHT format for load/save, more robust and forward compatible */
-// TODO(irungentoo): Move this closer to Messenger.
-#define DHT_STATE_COOKIE_GLOBAL 0x159000d
-
-#define DHT_STATE_COOKIE_TYPE 0x11ce
-#define DHT_STATE_TYPE_NODES 4
-
-#define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2)
-
-/* Get the size of the DHT (for saving). */
-uint32_t DHT_size(const DHT *dht)
-{
- uint32_t numv4 = 0, numv6 = 0;
-
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- numv4 += (dht->close_clientlist[i].assoc4.timestamp != 0);
- numv6 += (dht->close_clientlist[i].assoc6.timestamp != 0);
- }
-
- for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
- DHT_Friend *fr = &dht->friends_list[i];
-
- for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
- numv4 += (fr->client_list[j].assoc4.timestamp != 0);
- numv6 += (fr->client_list[j].assoc6.timestamp != 0);
- }
- }
-
- uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
-
- return size32 + sizesubhead + (packed_node_size(TOX_AF_INET) * numv4) + (packed_node_size(TOX_AF_INET6) * numv6);
-}
-
-static uint8_t *DHT_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
-{
- host_to_lendian32(data, len);
- data += sizeof(uint32_t);
- host_to_lendian32(data, (host_tolendian16(DHT_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type));
- data += sizeof(uint32_t);
- return data;
-}
-
-
-/* Save the DHT in data where data is an array of size DHT_size(). */
-void DHT_save(DHT *dht, uint8_t *data)
-{
- host_to_lendian32(data, DHT_STATE_COOKIE_GLOBAL);
- data += sizeof(uint32_t);
-
- uint8_t *old_data = data;
-
- /* get right offset. we write the actual header later. */
- data = DHT_save_subheader(data, 0, 0);
-
- Node_format clients[MAX_SAVED_DHT_NODES];
-
- uint32_t num = 0;
-
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- if (dht->close_clientlist[i].assoc4.timestamp != 0) {
- memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
- ++num;
- }
-
- if (dht->close_clientlist[i].assoc6.timestamp != 0) {
- memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
- ++num;
- }
- }
-
- for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
- DHT_Friend *fr = &dht->friends_list[i];
-
- for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
- if (fr->client_list[j].assoc4.timestamp != 0) {
- memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
- ++num;
- }
-
- if (fr->client_list[j].assoc6.timestamp != 0) {
- memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
- ++num;
- }
- }
- }
-
- DHT_save_subheader(old_data, pack_nodes(data, sizeof(Node_format) * num, clients, num), DHT_STATE_TYPE_NODES);
-}
-
-/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */
-#define SAVE_BOOTSTAP_FREQUENCY 8
-
-/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
-int DHT_connect_after_load(DHT *dht)
-{
- if (dht == NULL) {
- return -1;
- }
-
- if (!dht->loaded_nodes_list) {
- return -1;
- }
-
- /* DHT is connected, stop. */
- if (DHT_non_lan_connected(dht)) {
- free(dht->loaded_nodes_list);
- dht->loaded_nodes_list = NULL;
- dht->loaded_num_nodes = 0;
- return 0;
- }
-
- for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
- unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
- DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
- ++dht->loaded_nodes_index;
- }
-
- return 0;
-}
-
-static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
-{
- DHT *dht = (DHT *)outer;
-
- switch (type) {
- case DHT_STATE_TYPE_NODES:
- if (length == 0) {
- break;
- }
-
- {
- free(dht->loaded_nodes_list);
- // Copy to loaded_clients_list
- dht->loaded_nodes_list = (Node_format *)calloc(MAX_SAVED_DHT_NODES, sizeof(Node_format));
-
- int num = unpack_nodes(dht->loaded_nodes_list, MAX_SAVED_DHT_NODES, NULL, data, length, 0);
-
- if (num > 0) {
- dht->loaded_num_nodes = num;
- } else {
- dht->loaded_num_nodes = 0;
- }
- } /* localize declarations */
-
- break;
-
- default:
- LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
- length, type);
- break;
- }
-
- return 0;
-}
-
-/* Load the DHT from data of size size.
- *
- * return -1 if failure.
- * return 0 if success.
- */
-int DHT_load(DHT *dht, const uint8_t *data, uint32_t length)
-{
- uint32_t cookie_len = sizeof(uint32_t);
-
- if (length > cookie_len) {
- uint32_t data32;
- lendian_to_host32(&data32, data);
-
- if (data32 == DHT_STATE_COOKIE_GLOBAL) {
- return load_state(dht_load_state_callback, dht->log, dht, data + cookie_len,
- length - cookie_len, DHT_STATE_COOKIE_TYPE);
- }
- }
-
- return -1;
-}
-
-/* return 0 if we are not connected to the DHT.
- * return 1 if we are.
- */
-int DHT_isconnected(const DHT *dht)
-{
- unix_time_update();
-
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- const Client_data *client = &dht->close_clientlist[i];
-
- if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) ||
- !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/* return 0 if we are not connected or only connected to lan peers with the DHT.
- * return 1 if we are.
- */
-int DHT_non_lan_connected(const DHT *dht)
-{
- unix_time_update();
-
- for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
- const Client_data *client = &dht->close_clientlist[i];
-
- if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc4.ip_port.ip) == -1) {
- return 1;
- }
-
- if (!is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT) && LAN_ip(client->assoc6.ip_port.ip) == -1) {
- return 1;
- }
- }
-
- return 0;
-}
diff --git a/libs/libtox/src/toxcore/DHT.h b/libs/libtox/src/toxcore/DHT.h
deleted file mode 100644
index 510b3c5c92..0000000000
--- a/libs/libtox/src/toxcore/DHT.h
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * An implementation of the DHT as seen in docs/updates/DHT.md
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef DHT_H
-#define DHT_H
-
-#include "crypto_core.h"
-#include "logger.h"
-#include "network.h"
-#include "ping_array.h"
-
-#include <stdbool.h>
-
-/* Maximum number of clients stored per friend. */
-#define MAX_FRIEND_CLIENTS 8
-
-#define LCLIENT_NODES (MAX_FRIEND_CLIENTS)
-#define LCLIENT_LENGTH 128
-
-/* A list of the clients mathematically closest to ours. */
-#define LCLIENT_LIST (LCLIENT_LENGTH * LCLIENT_NODES)
-
-#define MAX_CLOSE_TO_BOOTSTRAP_NODES 8
-
-/* The max number of nodes to send with send nodes. */
-#define MAX_SENT_NODES 4
-
-/* Ping timeout in seconds */
-#define PING_TIMEOUT 5
-
-/* size of DHT ping arrays. */
-#define DHT_PING_ARRAY_SIZE 512
-
-/* Ping interval in seconds for each node in our lists. */
-#define PING_INTERVAL 60
-
-/* The number of seconds for a non responsive node to become bad. */
-#define PINGS_MISSED_NODE_GOES_BAD 1
-#define PING_ROUNDTRIP 2
-#define BAD_NODE_TIMEOUT (PING_INTERVAL + PINGS_MISSED_NODE_GOES_BAD * (PING_INTERVAL + PING_ROUNDTRIP))
-
-/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
-#define DHT_FAKE_FRIEND_NUMBER 2
-
-#define MAX_CRYPTO_REQUEST_SIZE 1024
-
-#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
-#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
-#define CRYPTO_PACKET_DHTPK 156
-#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
-
-/* Create a request to peer.
- * send_public_key and send_secret_key are the pub/secret keys of the sender.
- * recv_public_key is public key of receiver.
- * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big.
- * Data represents the data we send with the request with length being the length of the data.
- * request_id is the id of the request (32 = friend request, 254 = ping request).
- *
- * return -1 on failure.
- * return the length of the created packet on success.
- */
-int create_request(const uint8_t *send_public_key, const uint8_t *send_secret_key, uint8_t *packet,
- const uint8_t *recv_public_key, const uint8_t *data, uint32_t length, uint8_t request_id);
-
-/* puts the senders public key in the request in public_key, the data from the request
- in data if a friend or ping request was sent to us and returns the length of the data.
- packet is the request packet and length is its length
- return -1 if not valid request. */
-int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
- uint8_t *request_id, const uint8_t *packet, uint16_t length);
-
-typedef struct {
- IP_Port ip_port;
- uint64_t timestamp;
-} IPPTs;
-
-typedef struct {
- /* Node routes request correctly (true (1) or false/didn't check (0)) */
- uint8_t routes_requests_ok;
- /* Time which we last checked this.*/
- uint64_t routes_requests_timestamp;
- uint8_t routes_requests_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
- /* Node sends correct send_node (true (1) or false/didn't check (0)) */
- uint8_t send_nodes_ok;
- /* Time which we last checked this.*/
- uint64_t send_nodes_timestamp;
- uint8_t send_nodes_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
- /* Node can be used to test other nodes (true (1) or false/didn't check (0)) */
- uint8_t testing_requests;
- /* Time which we last checked this.*/
- uint64_t testing_timestamp;
- uint8_t testing_pingedid[CRYPTO_PUBLIC_KEY_SIZE];
-} Hardening;
-
-typedef struct {
- IP_Port ip_port;
- uint64_t timestamp;
- uint64_t last_pinged;
-
- Hardening hardening;
- /* Returned by this node. Either our friend or us. */
- IP_Port ret_ip_port;
- uint64_t ret_timestamp;
-} IPPTsPng;
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- IPPTsPng assoc4;
- IPPTsPng assoc6;
-} Client_data;
-
-/*----------------------------------------------------------------------------------*/
-
-typedef struct {
- /* 1 if currently hole punching, otherwise 0 */
- uint8_t hole_punching;
- uint32_t punching_index;
- uint32_t tries;
- uint32_t punching_index2;
-
- uint64_t punching_timestamp;
- uint64_t recvNATping_timestamp;
- uint64_t NATping_id;
- uint64_t NATping_timestamp;
-} NAT;
-
-#define DHT_FRIEND_MAX_LOCKS 32
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- IP_Port ip_port;
-}
-Node_format;
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- Client_data client_list[MAX_FRIEND_CLIENTS];
-
- /* Time at which the last get_nodes request was sent. */
- uint64_t lastgetnode;
- /* number of times get_node packets were sent. */
- uint32_t bootstrap_times;
-
- /* Symetric NAT hole punching stuff. */
- NAT nat;
-
- uint16_t lock_count;
- struct {
- void (*ip_callback)(void *, int32_t, IP_Port);
- void *data;
- int32_t number;
- } callbacks[DHT_FRIEND_MAX_LOCKS];
-
- Node_format to_bootstrap[MAX_SENT_NODES];
- unsigned int num_to_bootstrap;
-} DHT_Friend;
-
-/* Return packet size of packed node with ip_family on success.
- * Return -1 on failure.
- */
-int packed_node_size(uint8_t ip_family);
-
-/* Pack number of nodes into data of maxlength length.
- *
- * return length of packed nodes on success.
- * return -1 on failure.
- */
-int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number);
-
-/* Unpack data of length into nodes of size max_num_nodes.
- * Put the length of the data processed in processed_data_len.
- * tcp_enabled sets if TCP nodes are expected (true) or not (false).
- *
- * return number of unpacked nodes on success.
- * return -1 on failure.
- */
-int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
- uint16_t length, uint8_t tcp_enabled);
-
-
-/*----------------------------------------------------------------------------------*/
-/* struct to store some shared keys so we don't have to regenerate them for each request. */
-#define MAX_KEYS_PER_SLOT 4
-#define KEYS_TIMEOUT 600
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint32_t times_requested;
- uint8_t stored; /* 0 if not, 1 if is */
- uint64_t time_last_requested;
-} Shared_Key;
-
-typedef struct {
- Shared_Key keys[256 * MAX_KEYS_PER_SLOT];
-} Shared_Keys;
-
-/*----------------------------------------------------------------------------------*/
-
-typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, const uint8_t *source_pubkey,
- const uint8_t *data, uint16_t len, void *userdata);
-
-typedef struct {
- cryptopacket_handler_callback function;
- void *object;
-} Cryptopacket_Handles;
-
-typedef struct {
- Logger *log;
- Networking_Core *net;
-
- bool hole_punching_enabled;
-
- Client_data close_clientlist[LCLIENT_LIST];
- uint64_t close_lastgetnodes;
- uint32_t close_bootstrap_times;
-
- /* Note: this key should not be/is not used to transmit any sensitive materials */
- uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
- /* DHT keypair */
- uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- DHT_Friend *friends_list;
- uint16_t num_friends;
-
- Node_format *loaded_nodes_list;
- uint32_t loaded_num_nodes;
- unsigned int loaded_nodes_index;
-
- Shared_Keys shared_keys_recv;
- Shared_Keys shared_keys_sent;
-
- struct PING *ping;
- Ping_Array dht_ping_array;
- Ping_Array dht_harden_ping_array;
- uint64_t last_run;
-
- Cryptopacket_Handles cryptopackethandlers[256];
-
- Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
- unsigned int num_to_bootstrap;
-} DHT;
-/*----------------------------------------------------------------------------------*/
-
-/* Shared key generations are costly, it is therefor smart to store commonly used
- * ones so that they can re used later without being computed again.
- *
- * If shared key is already in shared_keys, copy it to shared_key.
- * else generate it into shared_key and copy it to shared_keys
- */
-void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, const uint8_t *secret_key,
- const uint8_t *public_key);
-
-/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
- * for packets that we receive.
- */
-void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, const uint8_t *public_key);
-
-/* Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
- * for packets that we send.
- */
-void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, const uint8_t *public_key);
-
-void DHT_getnodes(DHT *dht, const IP_Port *from_ipp, const uint8_t *from_id, const uint8_t *which_id);
-
-/* Add a new friend to the friends list.
- * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
- *
- * ip_callback is the callback of a function that will be called when the ip address
- * is found along with arguments data and number.
- *
- * lock_count will be set to a non zero number that must be passed to DHT_delfriend()
- * to properly remove the callback.
- *
- * return 0 if success.
- * return -1 if failure (friends list is full).
- */
-int DHT_addfriend(DHT *dht, const uint8_t *public_key, void (*ip_callback)(void *data, int32_t number, IP_Port),
- void *data, int32_t number, uint16_t *lock_count);
-
-/* Delete a friend from the friends list.
- * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
- *
- * return 0 if success.
- * return -1 if failure (public_key not in friends list).
- */
-int DHT_delfriend(DHT *dht, const uint8_t *public_key, uint16_t lock_count);
-
-/* Get ip of friend.
- * public_key must be CRYPTO_PUBLIC_KEY_SIZE bytes long.
- * ip must be 4 bytes long.
- * port must be 2 bytes long.
- *
- * int DHT_getfriendip(DHT *dht, uint8_t *public_key, IP_Port *ip_port);
- *
- * return -1, -- if public_key does NOT refer to a friend
- * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
- * return 1, ip if public_key refers to a friend and we found him
- */
-int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port);
-
-/* Compares pk1 and pk2 with pk.
- *
- * return 0 if both are same distance.
- * return 1 if pk1 is closer.
- * return 2 if pk2 is closer.
- */
-int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2);
-
-/* Add node to the node list making sure only the nodes closest to cmp_pk are in the list.
- */
-bool add_to_list(Node_format *nodes_list, unsigned int length, const uint8_t *pk, IP_Port ip_port,
- const uint8_t *cmp_pk);
-
-/* Return 1 if node can be added to close list, 0 if it can't.
- */
-bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, IP_Port ip_port);
-
-/* Get the (maximum MAX_SENT_NODES) closest nodes to public_key we know
- * and put them in nodes_list (must be MAX_SENT_NODES big).
- *
- * sa_family = family (IPv4 or IPv6) (0 if we don't care)?
- * is_LAN = return some LAN ips (true or false)
- * want_good = do we want tested nodes or not? (TODO(irungentoo))
- *
- * return the number of nodes returned.
- *
- */
-int get_close_nodes(const DHT *dht, const uint8_t *public_key, Node_format *nodes_list, Family sa_family,
- uint8_t is_LAN, uint8_t want_good);
-
-
-/* Put up to max_num nodes in nodes from the random friends.
- *
- * return the number of nodes.
- */
-uint16_t randfriends_nodes(DHT *dht, Node_format *nodes, uint16_t max_num);
-
-/* Put up to max_num nodes in nodes from the closelist.
- *
- * return the number of nodes.
- */
-uint16_t closelist_nodes(DHT *dht, Node_format *nodes, uint16_t max_num);
-
-/* Run this function at least a couple times per second (It's the main loop). */
-void do_DHT(DHT *dht);
-
-/*
- * Use these two functions to bootstrap the client.
- */
-/* Sends a "get nodes" request to the given node with ip, port and public_key
- * to setup connections
- */
-void DHT_bootstrap(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
-/* Resolves address into an IP address. If successful, sends a "get nodes"
- * request to the given node with ip, port and public_key to setup connections
- *
- * address can be a hostname or an IP address (IPv4 or IPv6).
- * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses
- * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first,
- * then IPv4 addresses.
- *
- * returns 1 if the address could be converted into an IP address
- * returns 0 otherwise
- */
-int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
- uint16_t port, const uint8_t *public_key);
-
-/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.
- *
- * returns 0 if successful
- * returns -1 otherwise
- */
-int DHT_connect_after_load(DHT *dht);
-
-/* ROUTING FUNCTIONS */
-
-/* Send the given packet to node with public_key.
- *
- * return -1 if failure.
- */
-int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length);
-
-/* Send the following packet to everyone who tells us they are connected to friend_id.
- *
- * return number of nodes it sent the packet to.
- */
-int route_tofriend(const DHT *dht, const uint8_t *friend_id, const uint8_t *packet, uint16_t length);
-
-/* Function to handle crypto packets.
- */
-void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object);
-
-/* SAVE/LOAD functions */
-
-/* Get the size of the DHT (for saving). */
-uint32_t DHT_size(const DHT *dht);
-
-/* Save the DHT in data where data is an array of size DHT_size(). */
-void DHT_save(DHT *dht, uint8_t *data);
-
-/* Load the DHT from data of size size.
- *
- * return -1 if failure.
- * return 0 if success.
- */
-int DHT_load(DHT *dht, const uint8_t *data, uint32_t length);
-
-/* Initialize DHT. */
-DHT *new_DHT(Logger *log, Networking_Core *net, bool holepunching_enabled);
-
-void kill_DHT(DHT *dht);
-
-/* return 0 if we are not connected to the DHT.
- * return 1 if we are.
- */
-int DHT_isconnected(const DHT *dht);
-
-/* return 0 if we are not connected or only connected to lan peers with the DHT.
- * return 1 if we are.
- */
-int DHT_non_lan_connected(const DHT *dht);
-
-
-uint32_t addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key);
-
-#endif
diff --git a/libs/libtox/src/toxcore/LAN_discovery.c b/libs/libtox/src/toxcore/LAN_discovery.c
deleted file mode 100644
index b95e401d05..0000000000
--- a/libs/libtox/src/toxcore/LAN_discovery.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * LAN discovery implementation.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "LAN_discovery.h"
-
-#include "util.h"
-
-/* Used for get_broadcast(). */
-#ifdef __linux
-#include <linux/netdevice.h>
-#include <sys/ioctl.h>
-#endif
-
-#define MAX_INTERFACES 16
-
-
-/* TODO: multiple threads might concurrently try to set these, and it isn't clear that this couldn't lead to undesirable
- * behaviour. Consider storing the data in per-instance variables instead. */
-static int broadcast_count = -1;
-static IP_Port broadcast_ip_ports[MAX_INTERFACES];
-
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
-
-#include <iphlpapi.h>
-
-static void fetch_broadcast_info(uint16_t port)
-{
- IP_ADAPTER_INFO *pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
- unsigned long ulOutBufLen = sizeof(IP_ADAPTER_INFO);
-
- if (pAdapterInfo == NULL) {
- return;
- }
-
- if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
- free(pAdapterInfo);
- pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
-
- if (pAdapterInfo == NULL) {
- return;
- }
- }
-
- /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
- * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
- * interfaces will be set to be broadcast to.
- * */
- int count = 0;
- IP_Port ip_ports[MAX_INTERFACES];
-
- int ret;
-
- if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
- IP_ADAPTER_INFO *pAdapter = pAdapterInfo;
-
- while (pAdapter) {
- IP gateway = {0}, subnet_mask = {0};
-
- if (addr_parse_ip(pAdapter->IpAddressList.IpMask.String, &subnet_mask)
- && addr_parse_ip(pAdapter->GatewayList.IpAddress.String, &gateway)) {
- if (gateway.family == TOX_AF_INET && subnet_mask.family == TOX_AF_INET) {
- IP_Port *ip_port = &ip_ports[count];
- ip_port->ip.family = TOX_AF_INET;
- uint32_t gateway_ip = net_ntohl(gateway.ip4.uint32), subnet_ip = net_ntohl(subnet_mask.ip4.uint32);
- uint32_t broadcast_ip = gateway_ip + ~subnet_ip - 1;
- ip_port->ip.ip4.uint32 = net_htonl(broadcast_ip);
- ip_port->port = port;
- count++;
-
- if (count >= MAX_INTERFACES) {
- break;
- }
- }
- }
-
- pAdapter = pAdapter->Next;
- }
- }
-
- if (pAdapterInfo) {
- free(pAdapterInfo);
- }
-
- broadcast_count = count;
-
- for (uint32_t i = 0; i < count; i++) {
- broadcast_ip_ports[i] = ip_ports[i];
- }
-}
-
-#elif defined(__linux__)
-
-static void fetch_broadcast_info(uint16_t port)
-{
- /* Not sure how many platforms this will run on,
- * so it's wrapped in __linux for now.
- * Definitely won't work like this on Windows...
- */
- broadcast_count = 0;
- Socket sock = 0;
-
- if ((sock = net_socket(TOX_AF_INET, TOX_SOCK_STREAM, 0)) < 0) {
- return;
- }
-
- /* Configure ifconf for the ioctl call. */
- struct ifreq i_faces[MAX_INTERFACES];
- memset(i_faces, 0, sizeof(struct ifreq) * MAX_INTERFACES);
-
- struct ifconf ifconf;
- ifconf.ifc_buf = (char *)i_faces;
- ifconf.ifc_len = sizeof(i_faces);
-
- if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) {
- close(sock);
- return;
- }
-
- /* We copy these to the static variables broadcast_* only at the end of fetch_broadcast_info().
- * The intention is to ensure that even if multiple threads enter fetch_broadcast_info() concurrently, only valid
- * interfaces will be set to be broadcast to.
- * */
- int count = 0;
- IP_Port ip_ports[MAX_INTERFACES];
-
- /* ifconf.ifc_len is set by the ioctl() to the actual length used;
- * on usage of the complete array the call should be repeated with
- * a larger array, not done (640kB and 16 interfaces shall be
- * enough, for everybody!)
- */
- int i, n = ifconf.ifc_len / sizeof(struct ifreq);
-
- for (i = 0; i < n; i++) {
- /* there are interfaces with are incapable of broadcast */
- if (ioctl(sock, SIOCGIFBRDADDR, &i_faces[i]) < 0) {
- continue;
- }
-
- /* moot check: only TOX_AF_INET returned (backwards compat.) */
- if (i_faces[i].ifr_broadaddr.sa_family != TOX_AF_INET) {
- continue;
- }
-
- struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
-
- if (count >= MAX_INTERFACES) {
- break;
- }
-
- IP_Port *ip_port = &ip_ports[count];
- ip_port->ip.family = TOX_AF_INET;
- ip_port->ip.ip4.uint32 = sock4->sin_addr.s_addr;
-
- if (ip_port->ip.ip4.uint32 == 0) {
- continue;
- }
-
- ip_port->port = port;
- count++;
- }
-
- close(sock);
-
- broadcast_count = count;
-
- for (uint32_t i = 0; i < count; i++) {
- broadcast_ip_ports[i] = ip_ports[i];
- }
-}
-
-#else // TODO(irungentoo): Other platforms?
-
-static void fetch_broadcast_info(uint16_t port)
-{
- broadcast_count = 0;
-}
-
-#endif
-/* Send packet to all IPv4 broadcast addresses
- *
- * return 1 if sent to at least one broadcast target.
- * return 0 on failure to find any valid broadcast target.
- */
-static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, const uint8_t *data, uint16_t length)
-{
- /* fetch only once? on every packet? every X seconds?
- * old: every packet, new: once */
- if (broadcast_count < 0) {
- fetch_broadcast_info(port);
- }
-
- if (!broadcast_count) {
- return 0;
- }
-
- int i;
-
- for (i = 0; i < broadcast_count; i++) {
- sendpacket(net, broadcast_ip_ports[i], data, length);
- }
-
- return 1;
-}
-
-/* Return the broadcast ip. */
-static IP broadcast_ip(Family family_socket, Family family_broadcast)
-{
- IP ip;
- ip_reset(&ip);
-
- if (family_socket == TOX_AF_INET6) {
- if (family_broadcast == TOX_AF_INET6) {
- ip.family = TOX_AF_INET6;
- /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
- /* FE80::*: MUST be exact, for that we would need to look over all
- * interfaces and check in which status they are */
- ip.ip6.uint8[ 0] = 0xFF;
- ip.ip6.uint8[ 1] = 0x02;
- ip.ip6.uint8[15] = 0x01;
- } else if (family_broadcast == TOX_AF_INET) {
- ip.family = TOX_AF_INET6;
- ip.ip6 = IP6_BROADCAST;
- }
- } else if (family_socket == TOX_AF_INET) {
- if (family_broadcast == TOX_AF_INET) {
- ip.family = TOX_AF_INET;
- ip.ip4 = IP4_BROADCAST;
- }
- }
-
- return ip;
-}
-
-/* Is IP a local ip or not. */
-bool Local_ip(IP ip)
-{
- if (ip.family == TOX_AF_INET) {
- IP4 ip4 = ip.ip4;
-
- /* Loopback. */
- if (ip4.uint8[0] == 127) {
- return 1;
- }
- } else {
- /* embedded IPv4-in-IPv6 */
- if (IPV6_IPV4_IN_V6(ip.ip6)) {
- IP ip4;
- ip4.family = TOX_AF_INET;
- ip4.ip4.uint32 = ip.ip6.uint32[3];
- return Local_ip(ip4);
- }
-
- /* localhost in IPv6 (::1) */
- if (ip.ip6.uint64[0] == 0 && ip.ip6.uint32[2] == 0 && ip.ip6.uint32[3] == net_htonl(1)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/* return 0 if ip is a LAN ip.
- * return -1 if it is not.
- */
-int LAN_ip(IP ip)
-{
- if (Local_ip(ip)) {
- return 0;
- }
-
- if (ip.family == TOX_AF_INET) {
- IP4 ip4 = ip.ip4;
-
- /* 10.0.0.0 to 10.255.255.255 range. */
- if (ip4.uint8[0] == 10) {
- return 0;
- }
-
- /* 172.16.0.0 to 172.31.255.255 range. */
- if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31) {
- return 0;
- }
-
- /* 192.168.0.0 to 192.168.255.255 range. */
- if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168) {
- return 0;
- }
-
- /* 169.254.1.0 to 169.254.254.255 range. */
- if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
- && ip4.uint8[2] != 255) {
- return 0;
- }
-
- /* RFC 6598: 100.64.0.0 to 100.127.255.255 (100.64.0.0/10)
- * (shared address space to stack another layer of NAT) */
- if ((ip4.uint8[0] == 100) && ((ip4.uint8[1] & 0xC0) == 0x40)) {
- return 0;
- }
- } else if (ip.family == TOX_AF_INET6) {
-
- /* autogenerated for each interface: FE80::* (up to FEBF::*)
- FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
- if (((ip.ip6.uint8[0] == 0xFF) && (ip.ip6.uint8[1] < 3) && (ip.ip6.uint8[15] == 1)) ||
- ((ip.ip6.uint8[0] == 0xFE) && ((ip.ip6.uint8[1] & 0xC0) == 0x80))) {
- return 0;
- }
-
- /* embedded IPv4-in-IPv6 */
- if (IPV6_IPV4_IN_V6(ip.ip6)) {
- IP ip4;
- ip4.family = TOX_AF_INET;
- ip4.ip4.uint32 = ip.ip6.uint32[3];
- return LAN_ip(ip4);
- }
- }
-
- return -1;
-}
-
-static int handle_LANdiscovery(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
-
- if (LAN_ip(source.ip) == -1) {
- return 1;
- }
-
- if (length != CRYPTO_PUBLIC_KEY_SIZE + 1) {
- return 1;
- }
-
- char ip_str[IP_NTOA_LEN] = { 0 };
- ip_ntoa(&source.ip, ip_str, sizeof(ip_str));
- LOGGER_INFO(dht->log, "Found node in LAN: %s", ip_str);
-
- DHT_bootstrap(dht, source, packet + 1);
- return 0;
-}
-
-
-int send_LANdiscovery(uint16_t port, DHT *dht)
-{
- uint8_t data[CRYPTO_PUBLIC_KEY_SIZE + 1];
- data[0] = NET_PACKET_LAN_DISCOVERY;
- id_copy(data + 1, dht->self_public_key);
-
- send_broadcasts(dht->net, port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE);
-
- int res = -1;
- IP_Port ip_port;
- ip_port.port = port;
-
- /* IPv6 multicast */
- if (dht->net->family == TOX_AF_INET6) {
- ip_port.ip = broadcast_ip(TOX_AF_INET6, TOX_AF_INET6);
-
- if (ip_isset(&ip_port.ip)) {
- if (sendpacket(dht->net, ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE) > 0) {
- res = 1;
- }
- }
- }
-
- /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is TOX_AF_INET6 */
- ip_port.ip = broadcast_ip(dht->net->family, TOX_AF_INET);
-
- if (ip_isset(&ip_port.ip)) {
- if (sendpacket(dht->net, ip_port, data, 1 + CRYPTO_PUBLIC_KEY_SIZE)) {
- res = 1;
- }
- }
-
- return res;
-}
-
-
-void LANdiscovery_init(DHT *dht)
-{
- networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht);
-}
-
-void LANdiscovery_kill(DHT *dht)
-{
- networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, NULL, NULL);
-}
diff --git a/libs/libtox/src/toxcore/LAN_discovery.h b/libs/libtox/src/toxcore/LAN_discovery.h
deleted file mode 100644
index 753de5249f..0000000000
--- a/libs/libtox/src/toxcore/LAN_discovery.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * LAN discovery implementation.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef LAN_DISCOVERY_H
-#define LAN_DISCOVERY_H
-
-#include "DHT.h"
-
-/* Interval in seconds between LAN discovery packet sending. */
-#define LAN_DISCOVERY_INTERVAL 10
-
-/* Send a LAN discovery pcaket to the broadcast address with port port. */
-int send_LANdiscovery(uint16_t port, DHT *dht);
-
-/* Sets up packet handlers. */
-void LANdiscovery_init(DHT *dht);
-
-/* Clear packet handlers. */
-void LANdiscovery_kill(DHT *dht);
-
-/* Is IP a local ip or not. */
-bool Local_ip(IP ip);
-
-/* checks if a given IP isn't routable
- *
- * return 0 if ip is a LAN ip.
- * return -1 if it is not.
- */
-int LAN_ip(IP ip);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/Messenger.c b/libs/libtox/src/toxcore/Messenger.c
deleted file mode 100644
index 4dd7d0c4a4..0000000000
--- a/libs/libtox/src/toxcore/Messenger.c
+++ /dev/null
@@ -1,3155 +0,0 @@
-/*
- * An implementation of a simple text chat only messenger on the tox network core.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "Messenger.h"
-
-#include "logger.h"
-#include "network.h"
-#include "util.h"
-
-#include <assert.h>
-
-static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata);
-static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
- uint32_t length, uint8_t congestion_control);
-
-// friend_not_valid determines if the friendnumber passed is valid in the Messenger object
-static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
-{
- if ((unsigned int)friendnumber < m->numfriends) {
- if (m->friendlist[friendnumber].status != 0) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/* Set the size of the friend list to numfriends.
- *
- * return -1 if realloc fails.
- */
-static int realloc_friendlist(Messenger *m, uint32_t num)
-{
- if (num == 0) {
- free(m->friendlist);
- m->friendlist = NULL;
- return 0;
- }
-
- Friend *newfriendlist = (Friend *)realloc(m->friendlist, num * sizeof(Friend));
-
- if (newfriendlist == NULL) {
- return -1;
- }
-
- m->friendlist = newfriendlist;
- return 0;
-}
-
-/* return the friend id associated to that public key.
- * return -1 if no such friend.
- */
-int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk)
-{
- uint32_t i;
-
- for (i = 0; i < m->numfriends; ++i) {
- if (m->friendlist[i].status > 0) {
- if (id_equal(real_pk, m->friendlist[i].real_pk)) {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/* Copies the public key associated to that friend id into real_pk buffer.
- * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- memcpy(real_pk, m->friendlist[friendnumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- return 0;
-}
-
-/* return friend connection id on success.
- * return -1 if failure.
- */
-int getfriendcon_id(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- return m->friendlist[friendnumber].friendcon_id;
-}
-
-/*
- * return a uint16_t that represents the checksum of address of length len.
- */
-static uint16_t address_checksum(const uint8_t *address, uint32_t len)
-{
- uint8_t checksum[2] = {0};
- uint16_t check;
- uint32_t i;
-
- for (i = 0; i < len; ++i) {
- checksum[i % 2] ^= address[i];
- }
-
- memcpy(&check, checksum, sizeof(check));
- return check;
-}
-
-/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
- *
- * return FRIEND_ADDRESS_SIZE byte address to give to others.
- */
-void getaddress(const Messenger *m, uint8_t *address)
-{
- id_copy(address, m->net_crypto->self_public_key);
- uint32_t nospam = get_nospam(&(m->fr));
- memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &nospam, sizeof(nospam));
- uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
- memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(nospam), &checksum, sizeof(checksum));
-}
-
-static int send_online_packet(Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return 0;
- }
-
- uint8_t packet = PACKET_ID_ONLINE;
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), &packet, sizeof(packet), 0) != -1;
-}
-
-static int send_offline_packet(Messenger *m, int friendcon_id)
-{
- uint8_t packet = PACKET_ID_OFFLINE;
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, friendcon_id), &packet,
- sizeof(packet), 0) != -1;
-}
-
-static int m_handle_status(void *object, int i, uint8_t status, void *userdata);
-static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata);
-static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
- void *userdata);
-
-static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t status)
-{
- /* Resize the friend list if necessary. */
- if (realloc_friendlist(m, m->numfriends + 1) != 0) {
- return FAERR_NOMEM;
- }
-
- memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend));
-
- int friendcon_id = new_friend_connection(m->fr_c, real_pk);
-
- if (friendcon_id == -1) {
- return FAERR_NOMEM;
- }
-
- uint32_t i;
-
- for (i = 0; i <= m->numfriends; ++i) {
- if (m->friendlist[i].status == NOFRIEND) {
- m->friendlist[i].status = status;
- m->friendlist[i].friendcon_id = friendcon_id;
- m->friendlist[i].friendrequest_lastsent = 0;
- id_copy(m->friendlist[i].real_pk, real_pk);
- m->friendlist[i].statusmessage_length = 0;
- m->friendlist[i].userstatus = USERSTATUS_NONE;
- m->friendlist[i].is_typing = 0;
- m->friendlist[i].message_id = 0;
- friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &m_handle_status, &m_handle_packet,
- &m_handle_custom_lossy_packet, m, i);
-
- if (m->numfriends == i) {
- ++m->numfriends;
- }
-
- if (friend_con_connected(m->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
- send_online_packet(m, i);
- }
-
- return i;
- }
- }
-
- return FAERR_NOMEM;
-}
-
-/*
- * Add a friend.
- * Set the data that will be sent along with friend request.
- * Address is the address of the friend (returned by getaddress of the friend you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
- * data is the data and length is the length.
- *
- * return the friend number if success.
- * return FA_TOOLONG if message length is too long.
- * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte).
- * return FAERR_OWNKEY if user's own key.
- * return FAERR_ALREADYSENT if friend request already sent or already a friend.
- * return FAERR_BADCHECKSUM if bad checksum in address.
- * return FAERR_SETNEWNOSPAM if the friend was already there but the nospam was different.
- * (the nospam for that friend was set to the new one).
- * return FAERR_NOMEM if increasing the friend list size fails.
- */
-int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length)
-{
- if (length > MAX_FRIEND_REQUEST_DATA_SIZE) {
- return FAERR_TOOLONG;
- }
-
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- id_copy(real_pk, address);
-
- if (!public_key_valid(real_pk)) {
- return FAERR_BADCHECKSUM;
- }
-
- uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
- memcpy(&check, address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), sizeof(check));
-
- if (check != checksum) {
- return FAERR_BADCHECKSUM;
- }
-
- if (length < 1) {
- return FAERR_NOMESSAGE;
- }
-
- if (id_equal(real_pk, m->net_crypto->self_public_key)) {
- return FAERR_OWNKEY;
- }
-
- int32_t friend_id = getfriend_id(m, real_pk);
-
- if (friend_id != -1) {
- if (m->friendlist[friend_id].status >= FRIEND_CONFIRMED) {
- return FAERR_ALREADYSENT;
- }
-
- uint32_t nospam;
- memcpy(&nospam, address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(nospam));
-
- if (m->friendlist[friend_id].friendrequest_nospam == nospam) {
- return FAERR_ALREADYSENT;
- }
-
- m->friendlist[friend_id].friendrequest_nospam = nospam;
- return FAERR_SETNEWNOSPAM;
- }
-
- int32_t ret = init_new_friend(m, real_pk, FRIEND_ADDED);
-
- if (ret < 0) {
- return ret;
- }
-
- m->friendlist[ret].friendrequest_timeout = FRIENDREQUEST_TIMEOUT;
- memcpy(m->friendlist[ret].info, data, length);
- m->friendlist[ret].info_size = length;
- memcpy(&(m->friendlist[ret].friendrequest_nospam), address + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint32_t));
-
- return ret;
-}
-
-int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
-{
- if (getfriend_id(m, real_pk) != -1) {
- return FAERR_ALREADYSENT;
- }
-
- if (!public_key_valid(real_pk)) {
- return FAERR_BADCHECKSUM;
- }
-
- if (id_equal(real_pk, m->net_crypto->self_public_key)) {
- return FAERR_OWNKEY;
- }
-
- return init_new_friend(m, real_pk, FRIEND_CONFIRMED);
-}
-
-static int clear_receipts(Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
-
- while (receipts) {
- struct Receipts *temp_r = receipts->next;
- free(receipts);
- receipts = temp_r;
- }
-
- m->friendlist[friendnumber].receipts_start = NULL;
- m->friendlist[friendnumber].receipts_end = NULL;
- return 0;
-}
-
-static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- struct Receipts *new_receipts = (struct Receipts *)calloc(1, sizeof(struct Receipts));
-
- if (!new_receipts) {
- return -1;
- }
-
- new_receipts->packet_num = packet_num;
- new_receipts->msg_id = msg_id;
-
- if (!m->friendlist[friendnumber].receipts_start) {
- m->friendlist[friendnumber].receipts_start = new_receipts;
- } else {
- m->friendlist[friendnumber].receipts_end->next = new_receipts;
- }
-
- m->friendlist[friendnumber].receipts_end = new_receipts;
- new_receipts->next = NULL;
- return 0;
-}
-/*
- * return -1 on failure.
- * return 0 if packet was received.
- */
-static int friend_received_packet(const Messenger *m, int32_t friendnumber, uint32_t number)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- return cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), number);
-}
-
-static int do_receipts(Messenger *m, int32_t friendnumber, void *userdata)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
-
- while (receipts) {
- struct Receipts *temp_r = receipts->next;
-
- if (friend_received_packet(m, friendnumber, receipts->packet_num) == -1) {
- break;
- }
-
- if (m->read_receipt) {
- (*m->read_receipt)(m, friendnumber, receipts->msg_id, userdata);
- }
-
- free(receipts);
- m->friendlist[friendnumber].receipts_start = temp_r;
- receipts = temp_r;
- }
-
- if (!m->friendlist[friendnumber].receipts_start) {
- m->friendlist[friendnumber].receipts_end = NULL;
- }
-
- return 0;
-}
-
-/* Remove a friend.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int m_delfriend(Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friend_connectionstatuschange_internal) {
- m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata);
- }
-
- clear_receipts(m, friendnumber);
- remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
- friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
-
- if (friend_con_connected(m->fr_c, m->friendlist[friendnumber].friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
- send_offline_packet(m, m->friendlist[friendnumber].friendcon_id);
- }
-
- kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
- memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
- uint32_t i;
-
- for (i = m->numfriends; i != 0; --i) {
- if (m->friendlist[i - 1].status != NOFRIEND) {
- break;
- }
- }
-
- m->numfriends = i;
-
- if (realloc_friendlist(m, m->numfriends) != 0) {
- return FAERR_NOMEM;
- }
-
- return 0;
-}
-
-int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].status == FRIEND_ONLINE) {
- bool direct_connected = 0;
- unsigned int num_online_relays = 0;
- int crypt_conn_id = friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id);
- crypto_connection_status(m->net_crypto, crypt_conn_id, &direct_connected, &num_online_relays);
-
- if (direct_connected) {
- return CONNECTION_UDP;
- }
-
- if (num_online_relays) {
- return CONNECTION_TCP;
- }
-
- return CONNECTION_UNKNOWN;
- }
-
- return CONNECTION_NONE;
-}
-
-int m_friend_exists(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return 0;
- }
-
- return 1;
-}
-
-/* Send a message of type.
- *
- * return -1 if friend not valid.
- * return -2 if too large.
- * return -3 if friend not online.
- * return -4 if send failed (because queue is full).
- * return -5 if bad type.
- * return 0 if success.
- */
-int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
- uint32_t *message_id)
-{
- if (type > MESSAGE_ACTION) {
- return -5;
- }
-
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (length >= MAX_CRYPTO_DATA_SIZE) {
- return -2;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -3;
- }
-
- VLA(uint8_t, packet, length + 1);
- packet[0] = type + PACKET_ID_MESSAGE;
-
- if (length != 0) {
- memcpy(packet + 1, message, length);
- }
-
- int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);
-
- if (packet_num == -1) {
- return -4;
- }
-
- uint32_t msg_id = ++m->friendlist[friendnumber].message_id;
-
- add_receipt(m, friendnumber, packet_num, msg_id);
-
- if (message_id) {
- *message_id = msg_id;
- }
-
- return 0;
-}
-
-/* Send a name packet to friendnumber.
- * length is the length with the NULL terminator.
- */
-static int m_sendname(const Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
-{
- if (length > MAX_NAME_LENGTH) {
- return 0;
- }
-
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length, 0);
-}
-
-/* Set the name and name_length of a friend.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (length > MAX_NAME_LENGTH || length == 0) {
- return -1;
- }
-
- m->friendlist[friendnumber].name_length = length;
- memcpy(m->friendlist[friendnumber].name, name, length);
- return 0;
-}
-
-/* Set our nickname
- * name must be a string of maximum MAX_NAME_LENGTH length.
- * length must be at least 1 byte.
- * length is the length of name with the NULL terminator.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int setname(Messenger *m, const uint8_t *name, uint16_t length)
-{
- if (length > MAX_NAME_LENGTH) {
- return -1;
- }
-
- if (m->name_length == length && (length == 0 || memcmp(name, m->name, length) == 0)) {
- return 0;
- }
-
- if (length) {
- memcpy(m->name, name, length);
- }
-
- m->name_length = length;
- uint32_t i;
-
- for (i = 0; i < m->numfriends; ++i) {
- m->friendlist[i].name_sent = 0;
- }
-
- return 0;
-}
-
-/* Get our nickname and put it in name.
- * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
- *
- * return the length of the name.
- */
-uint16_t getself_name(const Messenger *m, uint8_t *name)
-{
- if (name == NULL) {
- return 0;
- }
-
- memcpy(name, m->name, m->name_length);
-
- return m->name_length;
-}
-
-/* Get name of friendnumber and put it in name.
- * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
- *
- * return length of name if success.
- * return -1 if failure.
- */
-int getname(const Messenger *m, int32_t friendnumber, uint8_t *name)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- memcpy(name, m->friendlist[friendnumber].name, m->friendlist[friendnumber].name_length);
- return m->friendlist[friendnumber].name_length;
-}
-
-int m_get_name_size(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- return m->friendlist[friendnumber].name_length;
-}
-
-int m_get_self_name_size(const Messenger *m)
-{
- return m->name_length;
-}
-
-int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length)
-{
- if (length > MAX_STATUSMESSAGE_LENGTH) {
- return -1;
- }
-
- if (m->statusmessage_length == length && (length == 0 || memcmp(m->statusmessage, status, length) == 0)) {
- return 0;
- }
-
- if (length) {
- memcpy(m->statusmessage, status, length);
- }
-
- m->statusmessage_length = length;
-
- uint32_t i;
-
- for (i = 0; i < m->numfriends; ++i) {
- m->friendlist[i].statusmessage_sent = 0;
- }
-
- return 0;
-}
-
-int m_set_userstatus(Messenger *m, uint8_t status)
-{
- if (status >= USERSTATUS_INVALID) {
- return -1;
- }
-
- if (m->userstatus == status) {
- return 0;
- }
-
- m->userstatus = (USERSTATUS)status;
- uint32_t i;
-
- for (i = 0; i < m->numfriends; ++i) {
- m->friendlist[i].userstatus_sent = 0;
- }
-
- return 0;
-}
-
-/* return the size of friendnumber's user status.
- * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
- */
-int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- return m->friendlist[friendnumber].statusmessage_length;
-}
-
-/* Copy the user status of friendnumber into buf, truncating if needed to maxlen
- * bytes, use m_get_statusmessage_size to find out how much you need to allocate.
- */
-int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- int msglen = MIN(maxlen, m->friendlist[friendnumber].statusmessage_length);
-
- memcpy(buf, m->friendlist[friendnumber].statusmessage, msglen);
- memset(buf + msglen, 0, maxlen - msglen);
- return msglen;
-}
-
-/* return the size of friendnumber's user status.
- * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
- */
-int m_get_self_statusmessage_size(const Messenger *m)
-{
- return m->statusmessage_length;
-}
-
-int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf)
-{
- memcpy(buf, m->statusmessage, m->statusmessage_length);
- return m->statusmessage_length;
-}
-
-uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return USERSTATUS_INVALID;
- }
-
- uint8_t status = m->friendlist[friendnumber].userstatus;
-
- if (status >= USERSTATUS_INVALID) {
- status = USERSTATUS_NONE;
- }
-
- return status;
-}
-
-uint8_t m_get_self_userstatus(const Messenger *m)
-{
- return m->userstatus;
-}
-
-uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return UINT64_MAX;
- }
-
- return m->friendlist[friendnumber].last_seen_time;
-}
-
-int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing)
-{
- if (is_typing != 0 && is_typing != 1) {
- return -1;
- }
-
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].user_istyping == is_typing) {
- return 0;
- }
-
- m->friendlist[friendnumber].user_istyping = is_typing;
- m->friendlist[friendnumber].user_istyping_sent = 0;
-
- return 0;
-}
-
-int m_get_istyping(const Messenger *m, int32_t friendnumber)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- return m->friendlist[friendnumber].is_typing;
-}
-
-static int send_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
-{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length, 0);
-}
-
-static int send_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
-{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &status, sizeof(status), 0);
-}
-
-static int send_user_istyping(const Messenger *m, int32_t friendnumber, uint8_t is_typing)
-{
- uint8_t typing = is_typing;
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_TYPING, &typing, sizeof(typing), 0);
-}
-
-static int set_friend_statusmessage(const Messenger *m, int32_t friendnumber, const uint8_t *status, uint16_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (length > MAX_STATUSMESSAGE_LENGTH) {
- return -1;
- }
-
- if (length) {
- memcpy(m->friendlist[friendnumber].statusmessage, status, length);
- }
-
- m->friendlist[friendnumber].statusmessage_length = length;
- return 0;
-}
-
-static void set_friend_userstatus(const Messenger *m, int32_t friendnumber, uint8_t status)
-{
- m->friendlist[friendnumber].userstatus = (USERSTATUS)status;
-}
-
-static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t is_typing)
-{
- m->friendlist[friendnumber].is_typing = is_typing;
-}
-
-void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata)
-{
- logger_callback_log(m->log, function, context, userdata);
-}
-
-/* Set the function that will be executed when a friend request is received. */
-void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
- void *))
-{
- callback_friendrequest(&(m->fr), (void (*)(void *, const uint8_t *, const uint8_t *, size_t, void *))function, m);
-}
-
-/* Set the function that will be executed when a message from a friend is received. */
-void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
- size_t, void *))
-{
- m->friend_message = function;
-}
-
-void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
-{
- m->friend_namechange = function;
-}
-
-void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *))
-{
- m->friend_statusmessagechange = function;
-}
-
-void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
-{
- m->friend_userstatuschange = function;
-}
-
-void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *))
-{
- m->friend_typingchange = function;
-}
-
-void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *))
-{
- m->read_receipt = function;
-}
-
-void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *))
-{
- m->friend_connectionstatuschange = function;
-}
-
-void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *))
-{
- m->core_connection_change = function;
-}
-
-void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
- void *userdata)
-{
- m->friend_connectionstatuschange_internal = function;
- m->friend_connectionstatuschange_internal_userdata = userdata;
-}
-
-static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata)
-{
- int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp;
-
- int ret = m_get_friend_connectionstatus(m, friendnumber);
-
- if (ret == -1) {
- return;
- }
-
- if (ret == CONNECTION_UNKNOWN) {
- if (last_connection_udp_tcp == CONNECTION_UDP) {
- return;
- }
-
- ret = CONNECTION_TCP;
- }
-
- if (last_connection_udp_tcp != ret) {
- if (m->friend_connectionstatuschange) {
- m->friend_connectionstatuschange(m, friendnumber, ret, userdata);
- }
- }
-
- m->friendlist[friendnumber].last_connection_udp_tcp = ret;
-}
-
-static void break_files(const Messenger *m, int32_t friendnumber);
-static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
-{
- if (status == NOFRIEND) {
- return;
- }
-
- const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
- const uint8_t is_online = status == FRIEND_ONLINE;
-
- if (is_online != was_online) {
- if (was_online) {
- break_files(m, friendnumber);
- clear_receipts(m, friendnumber);
- } else {
- m->friendlist[friendnumber].name_sent = 0;
- m->friendlist[friendnumber].userstatus_sent = 0;
- m->friendlist[friendnumber].statusmessage_sent = 0;
- m->friendlist[friendnumber].user_istyping_sent = 0;
- }
-
- m->friendlist[friendnumber].status = status;
-
- check_friend_tcp_udp(m, friendnumber, userdata);
-
- if (m->friend_connectionstatuschange_internal) {
- m->friend_connectionstatuschange_internal(m, friendnumber, is_online,
- m->friend_connectionstatuschange_internal_userdata);
- }
- }
-}
-
-void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata)
-{
- check_friend_connectionstatus(m, friendnumber, status, userdata);
- m->friendlist[friendnumber].status = status;
-}
-
-static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
- uint32_t length, uint8_t congestion_control)
-{
- if (friend_not_valid(m, friendnumber)) {
- return 0;
- }
-
- if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return 0;
- }
-
- VLA(uint8_t, packet, length + 1);
- packet[0] = packet_id;
-
- if (length != 0) {
- memcpy(packet + 1, data, length);
- }
-
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), packet, length + 1, congestion_control) != -1;
-}
-
-/**********CONFERENCES************/
-
-
-/* Set the callback for conference invites.
- *
- * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
- */
-void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
- void *))
-{
- m->conference_invite = function;
-}
-
-
-/* Send a conference invite packet.
- *
- * return 1 on success
- * return 0 on failure
- */
-int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
-{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_CONFERENCE, data, length, 0);
-}
-
-/****************FILE SENDING*****************/
-
-
-/* Set the callback for file send requests.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
- */
-void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
- const uint8_t *, size_t, void *))
-{
- m->file_sendrequest = function;
-}
-
-/* Set the callback for file control requests.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
- *
- */
-void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *))
-{
- m->file_filecontrol = function;
-}
-
-/* Set the callback for file data.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, uint8_t *data, size_t length, void *userdata)
- *
- */
-void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
- size_t, void *))
-{
- m->file_filedata = function;
-}
-
-/* Set the callback for file request chunk.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
- *
- */
-void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *))
-{
- m->file_reqchunk = function;
-}
-
-#define MAX_FILENAME_LENGTH 255
-
-/* Copy the file transfer file id to file_id
- *
- * return 0 on success.
- * return -1 if friend not valid.
- * return -2 if filenumber not valid
- */
-int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -2;
- }
-
- uint32_t temp_filenum;
- uint8_t send_receive, file_number;
-
- if (filenumber >= (1 << 16)) {
- send_receive = 1;
- temp_filenum = (filenumber >> 16) - 1;
- } else {
- send_receive = 0;
- temp_filenum = filenumber;
- }
-
- if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
- return -2;
- }
-
- file_number = temp_filenum;
-
- struct File_Transfers *ft;
-
- if (send_receive) {
- ft = &m->friendlist[friendnumber].file_receiving[file_number];
- } else {
- ft = &m->friendlist[friendnumber].file_sending[file_number];
- }
-
- if (ft->status == FILESTATUS_NONE) {
- return -2;
- }
-
- memcpy(file_id, ft->id, FILE_ID_LENGTH);
- return 0;
-}
-
-/* Send a file send request.
- * Maximum filename length is 255 bytes.
- * return 1 on success
- * return 0 on failure
- */
-static int file_sendrequest(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint32_t file_type,
- uint64_t filesize, const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return 0;
- }
-
- if (filename_length > MAX_FILENAME_LENGTH) {
- return 0;
- }
-
- VLA(uint8_t, packet, 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH + filename_length);
- packet[0] = filenumber;
- file_type = net_htonl(file_type);
- memcpy(packet + 1, &file_type, sizeof(file_type));
- host_to_net((uint8_t *)&filesize, sizeof(filesize));
- memcpy(packet + 1 + sizeof(file_type), &filesize, sizeof(filesize));
- memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize), file_id, FILE_ID_LENGTH);
-
- if (filename_length) {
- memcpy(packet + 1 + sizeof(file_type) + sizeof(filesize) + FILE_ID_LENGTH, filename, filename_length);
- }
-
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_SENDREQUEST, packet, SIZEOF_VLA(packet), 0);
-}
-
-/* Send a file send request.
- * Maximum filename length is 255 bytes.
- * return file number on success
- * return -1 if friend not found.
- * return -2 if filename length invalid.
- * return -3 if no more file sending slots left.
- * return -4 if could not send packet (friend offline).
- *
- */
-long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
- const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (filename_length > MAX_FILENAME_LENGTH) {
- return -2;
- }
-
- uint32_t i;
-
- for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
- if (m->friendlist[friendnumber].file_sending[i].status == FILESTATUS_NONE) {
- break;
- }
- }
-
- if (i == MAX_CONCURRENT_FILE_PIPES) {
- return -3;
- }
-
- if (file_sendrequest(m, friendnumber, i, file_type, filesize, file_id, filename, filename_length) == 0) {
- return -4;
- }
-
- struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i];
-
- ft->status = FILESTATUS_NOT_ACCEPTED;
-
- ft->size = filesize;
-
- ft->transferred = 0;
-
- ft->requested = 0;
-
- ft->slots_allocated = 0;
-
- ft->paused = FILE_PAUSE_NOT;
-
- memcpy(ft->id, file_id, FILE_ID_LENGTH);
-
- ++m->friendlist[friendnumber].num_sending_files;
-
- return i;
-}
-
-static int send_file_control_packet(const Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber,
- uint8_t control_type, uint8_t *data, uint16_t data_length)
-{
- if ((unsigned int)(1 + 3 + data_length) > MAX_CRYPTO_DATA_SIZE) {
- return -1;
- }
-
- VLA(uint8_t, packet, 3 + data_length);
-
- packet[0] = send_receive;
- packet[1] = filenumber;
- packet[2] = control_type;
-
- if (data_length) {
- memcpy(packet + 3, data, data_length);
- }
-
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_FILE_CONTROL, packet, SIZEOF_VLA(packet), 0);
-}
-
-/* Send a file control request.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if file number invalid.
- * return -4 if file control is bad.
- * return -5 if file already paused.
- * return -6 if resume file failed because it was only paused by the other.
- * return -7 if resume file failed because it wasn't paused.
- * return -8 if packet failed to send.
- */
-int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -2;
- }
-
- uint32_t temp_filenum;
- uint8_t send_receive, file_number;
-
- if (filenumber >= (1 << 16)) {
- send_receive = 1;
- temp_filenum = (filenumber >> 16) - 1;
- } else {
- send_receive = 0;
- temp_filenum = filenumber;
- }
-
- if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
- return -3;
- }
-
- file_number = temp_filenum;
-
- struct File_Transfers *ft;
-
- if (send_receive) {
- ft = &m->friendlist[friendnumber].file_receiving[file_number];
- } else {
- ft = &m->friendlist[friendnumber].file_sending[file_number];
- }
-
- if (ft->status == FILESTATUS_NONE) {
- return -3;
- }
-
- if (control > FILECONTROL_KILL) {
- return -4;
- }
-
- if (control == FILECONTROL_PAUSE && ((ft->paused & FILE_PAUSE_US) || ft->status != FILESTATUS_TRANSFERRING)) {
- return -5;
- }
-
- if (control == FILECONTROL_ACCEPT) {
- if (ft->status == FILESTATUS_TRANSFERRING) {
- if (!(ft->paused & FILE_PAUSE_US)) {
- if (ft->paused & FILE_PAUSE_OTHER) {
- return -6;
- }
-
- return -7;
- }
- } else {
- if (ft->status != FILESTATUS_NOT_ACCEPTED) {
- return -7;
- }
-
- if (!send_receive) {
- return -6;
- }
- }
- }
-
- if (send_file_control_packet(m, friendnumber, send_receive, file_number, control, 0, 0)) {
- if (control == FILECONTROL_KILL) {
- ft->status = FILESTATUS_NONE;
-
- if (send_receive == 0) {
- --m->friendlist[friendnumber].num_sending_files;
- }
- } else if (control == FILECONTROL_PAUSE) {
- ft->paused |= FILE_PAUSE_US;
- } else if (control == FILECONTROL_ACCEPT) {
- ft->status = FILESTATUS_TRANSFERRING;
-
- if (ft->paused & FILE_PAUSE_US) {
- ft->paused ^= FILE_PAUSE_US;
- }
- }
- } else {
- return -8;
- }
-
- return 0;
-}
-
-/* Send a seek file control request.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if file number invalid.
- * return -4 if not receiving file.
- * return -5 if file status wrong.
- * return -6 if position bad.
- * return -8 if packet failed to send.
- */
-int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -2;
- }
-
- if (filenumber < (1 << 16)) {
- // Not receiving.
- return -4;
- }
-
- uint32_t temp_filenum = (filenumber >> 16) - 1;
-
- if (temp_filenum >= MAX_CONCURRENT_FILE_PIPES) {
- return -3;
- }
-
- assert(temp_filenum <= UINT8_MAX);
- uint8_t file_number = temp_filenum;
-
- // We're always receiving at this point.
- struct File_Transfers *ft = &m->friendlist[friendnumber].file_receiving[file_number];
-
- if (ft->status == FILESTATUS_NONE) {
- return -3;
- }
-
- if (ft->status != FILESTATUS_NOT_ACCEPTED) {
- return -5;
- }
-
- if (position >= ft->size) {
- return -6;
- }
-
- uint64_t sending_pos = position;
- host_to_net((uint8_t *)&sending_pos, sizeof(sending_pos));
-
- if (send_file_control_packet(m, friendnumber, 1, file_number, FILECONTROL_SEEK, (uint8_t *)&sending_pos,
- sizeof(sending_pos))) {
- ft->transferred = position;
- } else {
- return -8;
- }
-
- return 0;
-}
-
-/* return packet number on success.
- * return -1 on failure.
- */
-static int64_t send_file_data_packet(const Messenger *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data,
- uint16_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- VLA(uint8_t, packet, 2 + length);
- packet[0] = PACKET_ID_FILE_DATA;
- packet[1] = filenumber;
-
- if (length) {
- memcpy(packet + 2, data, length);
- }
-
- return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), packet, SIZEOF_VLA(packet), 1);
-}
-
-#define MAX_FILE_DATA_SIZE (MAX_CRYPTO_DATA_SIZE - 2)
-#define MIN_SLOTS_FREE (CRYPTO_MIN_QUEUE_LENGTH / 4)
-/* Send file data.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if filenumber invalid.
- * return -4 if file transfer not transferring.
- * return -5 if bad data size.
- * return -6 if packet queue full.
- * return -7 if wrong position.
- */
-int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
- uint16_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -2;
- }
-
- if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
- return -3;
- }
-
- struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[filenumber];
-
- if (ft->status != FILESTATUS_TRANSFERRING) {
- return -4;
- }
-
- if (length > MAX_FILE_DATA_SIZE) {
- return -5;
- }
-
- if (ft->size - ft->transferred < length) {
- return -5;
- }
-
- if (ft->size != UINT64_MAX && length != MAX_FILE_DATA_SIZE && (ft->transferred + length) != ft->size) {
- return -5;
- }
-
- if (position != ft->transferred || (ft->requested <= position && ft->size != 0)) {
- return -7;
- }
-
- /* Prevent file sending from filling up the entire buffer preventing messages from being sent.
- * TODO(irungentoo): remove */
- if (crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id)) < MIN_SLOTS_FREE) {
- return -6;
- }
-
- int64_t ret = send_file_data_packet(m, friendnumber, filenumber, data, length);
-
- if (ret != -1) {
- // TODO(irungentoo): record packet ids to check if other received complete file.
- ft->transferred += length;
-
- if (ft->slots_allocated) {
- --ft->slots_allocated;
- }
-
- if (length != MAX_FILE_DATA_SIZE || ft->size == ft->transferred) {
- ft->status = FILESTATUS_FINISHED;
- ft->last_packet_number = ret;
- }
-
- return 0;
- }
-
- return -6;
-}
-
-/* Give the number of bytes left to be sent/received.
- *
- * send_receive is 0 if we want the sending files, 1 if we want the receiving.
- *
- * return number of bytes remaining to be sent/received on success
- * return 0 on failure
- */
-uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive)
-{
- if (friend_not_valid(m, friendnumber)) {
- return 0;
- }
-
- if (send_receive == 0) {
- if (m->friendlist[friendnumber].file_sending[filenumber].status == FILESTATUS_NONE) {
- return 0;
- }
-
- return m->friendlist[friendnumber].file_sending[filenumber].size -
- m->friendlist[friendnumber].file_sending[filenumber].transferred;
- }
-
- if (m->friendlist[friendnumber].file_receiving[filenumber].status == FILESTATUS_NONE) {
- return 0;
- }
-
- return m->friendlist[friendnumber].file_receiving[filenumber].size -
- m->friendlist[friendnumber].file_receiving[filenumber].transferred;
-}
-
-static void do_reqchunk_filecb(Messenger *m, int32_t friendnumber, void *userdata)
-{
- if (!m->friendlist[friendnumber].num_sending_files) {
- return;
- }
-
- int free_slots = crypto_num_free_sendqueue_slots(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id));
-
- if (free_slots < MIN_SLOTS_FREE) {
- free_slots = 0;
- } else {
- free_slots -= MIN_SLOTS_FREE;
- }
-
- unsigned int i, num = m->friendlist[friendnumber].num_sending_files;
-
- for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
- struct File_Transfers *ft = &m->friendlist[friendnumber].file_sending[i];
-
- if (ft->status != FILESTATUS_NONE) {
- --num;
-
- if (ft->status == FILESTATUS_FINISHED) {
- /* Check if file was entirely sent. */
- if (friend_received_packet(m, friendnumber, ft->last_packet_number) == 0) {
- if (m->file_reqchunk) {
- (*m->file_reqchunk)(m, friendnumber, i, ft->transferred, 0, userdata);
- }
-
- ft->status = FILESTATUS_NONE;
- --m->friendlist[friendnumber].num_sending_files;
- }
- }
-
- /* TODO(irungentoo): if file is too slow, switch to the next. */
- if (ft->slots_allocated > (unsigned int)free_slots) {
- free_slots = 0;
- } else {
- free_slots -= ft->slots_allocated;
- }
- }
-
- while (ft->status == FILESTATUS_TRANSFERRING && (ft->paused == FILE_PAUSE_NOT)) {
- if (max_speed_reached(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id))) {
- free_slots = 0;
- }
-
- if (free_slots == 0) {
- break;
- }
-
- uint16_t length = MAX_FILE_DATA_SIZE;
-
- if (ft->size == 0) {
- /* Send 0 data to friend if file is 0 length. */
- file_data(m, friendnumber, i, 0, 0, 0);
- break;
- }
-
- if (ft->size == ft->requested) {
- break;
- }
-
- if (ft->size - ft->requested < length) {
- length = ft->size - ft->requested;
- }
-
- ++ft->slots_allocated;
-
- uint64_t position = ft->requested;
- ft->requested += length;
-
- if (m->file_reqchunk) {
- (*m->file_reqchunk)(m, friendnumber, i, position, length, userdata);
- }
-
- --free_slots;
- }
-
- if (num == 0) {
- break;
- }
- }
-}
-
-/* Run this when the friend disconnects.
- * Kill all current file transfers.
- */
-static void break_files(const Messenger *m, int32_t friendnumber)
-{
- uint32_t i;
-
- // TODO(irungentoo): Inform the client which file transfers get killed with a callback?
- for (i = 0; i < MAX_CONCURRENT_FILE_PIPES; ++i) {
- if (m->friendlist[friendnumber].file_sending[i].status != FILESTATUS_NONE) {
- m->friendlist[friendnumber].file_sending[i].status = FILESTATUS_NONE;
- }
-
- if (m->friendlist[friendnumber].file_receiving[i].status != FILESTATUS_NONE) {
- m->friendlist[friendnumber].file_receiving[i].status = FILESTATUS_NONE;
- }
- }
-}
-
-static struct File_Transfers *get_file_transfer(uint8_t receive_send, uint8_t filenumber,
- uint32_t *real_filenumber, Friend *sender)
-{
- struct File_Transfers *ft;
-
- if (receive_send == 0) {
- *real_filenumber = (filenumber + 1) << 16;
- ft = &sender->file_receiving[filenumber];
- } else {
- *real_filenumber = filenumber;
- ft = &sender->file_sending[filenumber];
- }
-
- if (ft->status == FILESTATUS_NONE) {
- return NULL;
- }
-
- return ft;
-}
-
-/* return -1 on failure, 0 on success.
- */
-static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
- uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (receive_send > 1) {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): receive_send value is invalid (should be 0 or 1): %d",
- friendnumber, filenumber, receive_send);
- return -1;
- }
-
- uint32_t real_filenumber;
- struct File_Transfers *ft = get_file_transfer(receive_send, filenumber, &real_filenumber, &m->friendlist[friendnumber]);
-
- if (ft == NULL) {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): file transfer does not exist; telling the other to kill it",
- friendnumber, filenumber);
- send_file_control_packet(m, friendnumber, !receive_send, filenumber, FILECONTROL_KILL, 0, 0);
- return -1;
- }
-
- switch (control_type) {
- case FILECONTROL_ACCEPT: {
- if (receive_send && ft->status == FILESTATUS_NOT_ACCEPTED) {
- ft->status = FILESTATUS_TRANSFERRING;
- } else {
- if (ft->paused & FILE_PAUSE_OTHER) {
- ft->paused ^= FILE_PAUSE_OTHER;
- } else {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to resume file transfer that wasn't paused",
- friendnumber, filenumber);
- return -1;
- }
- }
-
- if (m->file_filecontrol) {
- m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
- }
-
- return 0;
- }
-
- case FILECONTROL_PAUSE: {
- if ((ft->paused & FILE_PAUSE_OTHER) || ft->status != FILESTATUS_TRANSFERRING) {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): friend told us to pause file transfer that is already paused",
- friendnumber, filenumber);
- return -1;
- }
-
- ft->paused |= FILE_PAUSE_OTHER;
-
- if (m->file_filecontrol) {
- m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
- }
-
- return 0;
- }
-
- case FILECONTROL_KILL: {
- if (m->file_filecontrol) {
- m->file_filecontrol(m, friendnumber, real_filenumber, control_type, userdata);
- }
-
- ft->status = FILESTATUS_NONE;
-
- if (receive_send) {
- --m->friendlist[friendnumber].num_sending_files;
- }
-
- return 0;
- }
-
- case FILECONTROL_SEEK: {
- uint64_t position;
-
- if (length != sizeof(position)) {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): expected payload of length %d, but got %d",
- friendnumber, filenumber, (uint32_t)sizeof(position), length);
- return -1;
- }
-
- /* seek can only be sent by the receiver to seek before resuming broken transfers. */
- if (ft->status != FILESTATUS_NOT_ACCEPTED || !receive_send) {
- LOGGER_DEBUG(m->log,
- "file control (friend %d, file %d): seek was either sent by a sender or by the receiver after accepting",
- friendnumber, filenumber);
- return -1;
- }
-
- memcpy(&position, data, sizeof(position));
- net_to_host((uint8_t *) &position, sizeof(position));
-
- if (position >= ft->size) {
- LOGGER_DEBUG(m->log,
- "file control (friend %d, file %d): seek position %lld exceeds file size %lld",
- friendnumber, filenumber, (unsigned long long)position, (unsigned long long)ft->size);
- return -1;
- }
-
- ft->transferred = ft->requested = position;
- return 0;
- }
-
- default: {
- LOGGER_DEBUG(m->log, "file control (friend %d, file %d): invalid file control: %d",
- friendnumber, filenumber, control_type);
- return -1;
- }
- }
-}
-
-/**************************************/
-
-/* Set the callback for msi packets.
- *
- * Function(Messenger *m, int friendnumber, uint8_t *data, uint16_t length, void *userdata)
- */
-void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t, void *),
- void *userdata)
-{
- m->msi_packet = function;
- m->msi_packet_userdata = userdata;
-}
-
-/* Send an msi packet.
- *
- * return 1 on success
- * return 0 on failure
- */
-int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length)
-{
- return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, 0);
-}
-
-static int m_handle_custom_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
- void *userdata)
-{
- Messenger *m = (Messenger *)object;
-
- if (friend_not_valid(m, friend_num)) {
- return 1;
- }
-
- if (packet[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
- if (m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function) {
- return m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_LOSSY_AV_RESERVED].function(
- m, friend_num, packet, length, m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] %
- PACKET_LOSSY_AV_RESERVED].object);
- }
-
- return 1;
- }
-
- if (m->lossy_packethandler) {
- m->lossy_packethandler(m, friend_num, packet, length, userdata);
- }
-
- return 1;
-}
-
-void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
-{
- m->lossy_packethandler = packet_handler_callback;
-}
-
-int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (byte < PACKET_ID_LOSSY_RANGE_START) {
- return -1;
- }
-
- if (byte >= (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
- return -1;
- }
-
- m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].function =
- packet_handler_callback;
- m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_LOSSY_AV_RESERVED].object = object;
- return 0;
-}
-
-
-int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
- return -2;
- }
-
- if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
- return -3;
- }
-
- if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
- return -3;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -4;
- }
-
- if (send_lossy_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), data, length) == -1) {
- return -5;
- }
-
- return 0;
-}
-
-static int handle_custom_lossless_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length,
- void *userdata)
-{
- Messenger *m = (Messenger *)object;
-
- if (friend_not_valid(m, friend_num)) {
- return -1;
- }
-
- if (packet[0] < PACKET_ID_LOSSLESS_RANGE_START) {
- return -1;
- }
-
- if (packet[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
- return -1;
- }
-
- if (m->lossless_packethandler) {
- m->lossless_packethandler(m, friend_num, packet, length, userdata);
- }
-
- return 1;
-}
-
-void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, size_t len, void *object))
-{
- m->lossless_packethandler = packet_handler_callback;
-}
-
-int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length)
-{
- if (friend_not_valid(m, friendnumber)) {
- return -1;
- }
-
- if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
- return -2;
- }
-
- if (data[0] < PACKET_ID_LOSSLESS_RANGE_START) {
- return -3;
- }
-
- if (data[0] >= (PACKET_ID_LOSSLESS_RANGE_START + PACKET_ID_LOSSLESS_RANGE_SIZE)) {
- return -3;
- }
-
- if (m->friendlist[friendnumber].status != FRIEND_ONLINE) {
- return -4;
- }
-
- if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
- m->friendlist[friendnumber].friendcon_id), data, length, 1) == -1) {
- return -5;
- }
-
- return 0;
-}
-
-/* Function to filter out some friend requests*/
-static int friend_already_added(const uint8_t *real_pk, void *data)
-{
- const Messenger *m = (const Messenger *)data;
-
- if (getfriend_id(m, real_pk) == -1) {
- return 0;
- }
-
- return -1;
-}
-
-/* Run this at startup. */
-Messenger *new_messenger(Messenger_Options *options, unsigned int *error)
-{
- if (!options) {
- return NULL;
- }
-
- Messenger *m = (Messenger *)calloc(1, sizeof(Messenger));
-
- if (error) {
- *error = MESSENGER_ERROR_OTHER;
- }
-
- if (!m) {
- return NULL;
- }
-
- Logger *log = NULL;
-
- if (options->log_callback) {
- log = logger_new();
-
- if (log != NULL) {
- logger_callback_log(log, options->log_callback, m, options->log_user_data);
- }
- }
-
- m->log = log;
-
- unsigned int net_err = 0;
-
- if (options->udp_disabled) {
- /* this is the easiest way to completely disable UDP without changing too much code. */
- m->net = (Networking_Core *)calloc(1, sizeof(Networking_Core));
- } else {
- IP ip;
- ip_init(&ip, options->ipv6enabled);
- m->net = new_networking_ex(log, ip, options->port_range[0], options->port_range[1], &net_err);
- }
-
- if (m->net == NULL) {
- free(m);
-
- if (error && net_err == 1) {
- *error = MESSENGER_ERROR_PORT;
- }
-
- return NULL;
- }
-
- m->dht = new_DHT(m->log, m->net, options->hole_punching_enabled);
-
- if (m->dht == NULL) {
- kill_networking(m->net);
- free(m);
- return NULL;
- }
-
- m->net_crypto = new_net_crypto(m->log, m->dht, &options->proxy_info);
-
- if (m->net_crypto == NULL) {
- kill_networking(m->net);
- kill_DHT(m->dht);
- free(m);
- return NULL;
- }
-
- m->onion = new_onion(m->dht);
- m->onion_a = new_onion_announce(m->dht);
- m->onion_c = new_onion_client(m->net_crypto);
- m->fr_c = new_friend_connections(m->onion_c, options->local_discovery_enabled);
-
- if (!(m->onion && m->onion_a && m->onion_c)) {
- kill_friend_connections(m->fr_c);
- kill_onion(m->onion);
- kill_onion_announce(m->onion_a);
- kill_onion_client(m->onion_c);
- kill_net_crypto(m->net_crypto);
- kill_DHT(m->dht);
- kill_networking(m->net);
- free(m);
- return NULL;
- }
-
- if (options->tcp_server_port) {
- m->tcp_server = new_TCP_server(options->ipv6enabled, 1, &options->tcp_server_port, m->dht->self_secret_key, m->onion);
-
- if (m->tcp_server == NULL) {
- kill_friend_connections(m->fr_c);
- kill_onion(m->onion);
- kill_onion_announce(m->onion_a);
- kill_onion_client(m->onion_c);
- kill_net_crypto(m->net_crypto);
- kill_DHT(m->dht);
- kill_networking(m->net);
- free(m);
-
- if (error) {
- *error = MESSENGER_ERROR_TCP_SERVER;
- }
-
- return NULL;
- }
- }
-
- m->options = *options;
- friendreq_init(&(m->fr), m->fr_c);
- set_nospam(&(m->fr), random_int());
- set_filter_function(&(m->fr), &friend_already_added, m);
-
- m->lastdump = 0;
-
- if (error) {
- *error = MESSENGER_ERROR_NONE;
- }
-
- return m;
-}
-
-/* Run this before closing shop. */
-void kill_messenger(Messenger *m)
-{
- if (!m) {
- return;
- }
-
- uint32_t i;
-
- if (m->tcp_server) {
- kill_TCP_server(m->tcp_server);
- }
-
- kill_friend_connections(m->fr_c);
- kill_onion(m->onion);
- kill_onion_announce(m->onion_a);
- kill_onion_client(m->onion_c);
- kill_net_crypto(m->net_crypto);
- kill_DHT(m->dht);
- kill_networking(m->net);
-
- for (i = 0; i < m->numfriends; ++i) {
- clear_receipts(m, i);
- }
-
- logger_kill(m->log);
- free(m->friendlist);
- free(m);
-}
-
-/* Check for and handle a timed-out friend request. If the request has
- * timed-out then the friend status is set back to FRIEND_ADDED.
- * i: friendlist index of the timed-out friend
- * t: time
- */
-static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t, void *userdata)
-{
- Friend *f = &m->friendlist[i];
-
- if (f->friendrequest_lastsent + f->friendrequest_timeout < t) {
- set_friend_status(m, i, FRIEND_ADDED, userdata);
- /* Double the default timeout every time if friendrequest is assumed
- * to have been sent unsuccessfully.
- */
- f->friendrequest_timeout *= 2;
- }
-}
-
-static int m_handle_status(void *object, int i, uint8_t status, void *userdata)
-{
- Messenger *m = (Messenger *)object;
-
- if (status) { /* Went online. */
- send_online_packet(m, i);
- } else { /* Went offline. */
- if (m->friendlist[i].status == FRIEND_ONLINE) {
- set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
- }
- }
-
- return 0;
-}
-
-static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata)
-{
- if (len == 0) {
- return -1;
- }
-
- Messenger *m = (Messenger *)object;
- uint8_t packet_id = temp[0];
- const uint8_t *data = temp + 1;
- uint32_t data_length = len - 1;
-
- if (m->friendlist[i].status != FRIEND_ONLINE) {
- if (packet_id == PACKET_ID_ONLINE && len == 1) {
- set_friend_status(m, i, FRIEND_ONLINE, userdata);
- send_online_packet(m, i);
- } else {
- return -1;
- }
- }
-
- switch (packet_id) {
- case PACKET_ID_OFFLINE: {
- if (data_length != 0) {
- break;
- }
-
- set_friend_status(m, i, FRIEND_CONFIRMED, userdata);
- break;
- }
-
- case PACKET_ID_NICKNAME: {
- if (data_length > MAX_NAME_LENGTH) {
- break;
- }
-
- /* Make sure the NULL terminator is present. */
- VLA(uint8_t, data_terminated, data_length + 1);
- memcpy(data_terminated, data, data_length);
- data_terminated[data_length] = 0;
-
- /* inform of namechange before we overwrite the old name */
- if (m->friend_namechange) {
- m->friend_namechange(m, i, data_terminated, data_length, userdata);
- }
-
- memcpy(m->friendlist[i].name, data_terminated, data_length);
- m->friendlist[i].name_length = data_length;
-
- break;
- }
-
- case PACKET_ID_STATUSMESSAGE: {
- if (data_length > MAX_STATUSMESSAGE_LENGTH) {
- break;
- }
-
- /* Make sure the NULL terminator is present. */
- VLA(uint8_t, data_terminated, data_length + 1);
- memcpy(data_terminated, data, data_length);
- data_terminated[data_length] = 0;
-
- if (m->friend_statusmessagechange) {
- m->friend_statusmessagechange(m, i, data_terminated, data_length, userdata);
- }
-
- set_friend_statusmessage(m, i, data_terminated, data_length);
- break;
- }
-
- case PACKET_ID_USERSTATUS: {
- if (data_length != 1) {
- break;
- }
-
- USERSTATUS status = (USERSTATUS)data[0];
-
- if (status >= USERSTATUS_INVALID) {
- break;
- }
-
- if (m->friend_userstatuschange) {
- m->friend_userstatuschange(m, i, status, userdata);
- }
-
- set_friend_userstatus(m, i, status);
- break;
- }
-
- case PACKET_ID_TYPING: {
- if (data_length != 1) {
- break;
- }
-
- bool typing = !!data[0];
-
- set_friend_typing(m, i, typing);
-
- if (m->friend_typingchange) {
- m->friend_typingchange(m, i, typing, userdata);
- }
-
- break;
- }
-
- case PACKET_ID_MESSAGE: // fall-through
- case PACKET_ID_ACTION: {
- if (data_length == 0) {
- break;
- }
-
- const uint8_t *message = data;
- uint16_t message_length = data_length;
-
- /* Make sure the NULL terminator is present. */
- VLA(uint8_t, message_terminated, message_length + 1);
- memcpy(message_terminated, message, message_length);
- message_terminated[message_length] = 0;
- uint8_t type = packet_id - PACKET_ID_MESSAGE;
-
- if (m->friend_message) {
- (*m->friend_message)(m, i, type, message_terminated, message_length, userdata);
- }
-
- break;
- }
-
- case PACKET_ID_INVITE_CONFERENCE: {
- if (data_length == 0) {
- break;
- }
-
- if (m->conference_invite) {
- (*m->conference_invite)(m, i, data, data_length, userdata);
- }
-
- break;
- }
-
- case PACKET_ID_FILE_SENDREQUEST: {
- const unsigned int head_length = 1 + sizeof(uint32_t) + sizeof(uint64_t) + FILE_ID_LENGTH;
-
- if (data_length < head_length) {
- break;
- }
-
- uint8_t filenumber = data[0];
-
- if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
- break;
- }
-
- uint64_t filesize;
- uint32_t file_type;
- uint16_t filename_length = data_length - head_length;
-
- if (filename_length > MAX_FILENAME_LENGTH) {
- break;
- }
-
- memcpy(&file_type, data + 1, sizeof(file_type));
- file_type = net_ntohl(file_type);
-
- memcpy(&filesize, data + 1 + sizeof(uint32_t), sizeof(filesize));
- net_to_host((uint8_t *) &filesize, sizeof(filesize));
- struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
-
- if (ft->status != FILESTATUS_NONE) {
- break;
- }
-
- ft->status = FILESTATUS_NOT_ACCEPTED;
- ft->size = filesize;
- ft->transferred = 0;
- ft->paused = FILE_PAUSE_NOT;
- memcpy(ft->id, data + 1 + sizeof(uint32_t) + sizeof(uint64_t), FILE_ID_LENGTH);
-
- VLA(uint8_t, filename_terminated, filename_length + 1);
- uint8_t *filename = NULL;
-
- if (filename_length) {
- /* Force NULL terminate file name. */
- memcpy(filename_terminated, data + head_length, filename_length);
- filename_terminated[filename_length] = 0;
- filename = filename_terminated;
- }
-
- uint32_t real_filenumber = filenumber;
- real_filenumber += 1;
- real_filenumber <<= 16;
-
- if (m->file_sendrequest) {
- (*m->file_sendrequest)(m, i, real_filenumber, file_type, filesize, filename, filename_length,
- userdata);
- }
-
- break;
- }
-
- case PACKET_ID_FILE_CONTROL: {
- if (data_length < 3) {
- break;
- }
-
- uint8_t send_receive = data[0];
- uint8_t filenumber = data[1];
- uint8_t control_type = data[2];
-
- if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
- break;
- }
-
- if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, userdata) == -1) {
- // TODO(iphydf): Do something different here? Right now, this
- // check is pointless.
- break;
- }
-
- break;
- }
-
- case PACKET_ID_FILE_DATA: {
- if (data_length < 1) {
- break;
- }
-
- uint8_t filenumber = data[0];
-
- if (filenumber >= MAX_CONCURRENT_FILE_PIPES) {
- break;
- }
-
- struct File_Transfers *ft = &m->friendlist[i].file_receiving[filenumber];
-
- if (ft->status != FILESTATUS_TRANSFERRING) {
- break;
- }
-
- uint64_t position = ft->transferred;
- uint32_t real_filenumber = filenumber;
- real_filenumber += 1;
- real_filenumber <<= 16;
- uint16_t file_data_length = (data_length - 1);
- const uint8_t *file_data;
-
- if (file_data_length == 0) {
- file_data = NULL;
- } else {
- file_data = data + 1;
- }
-
- /* Prevent more data than the filesize from being passed to clients. */
- if ((ft->transferred + file_data_length) > ft->size) {
- file_data_length = ft->size - ft->transferred;
- }
-
- if (m->file_filedata) {
- (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
- }
-
- ft->transferred += file_data_length;
-
- if (file_data_length && (ft->transferred >= ft->size || file_data_length != MAX_FILE_DATA_SIZE)) {
- file_data_length = 0;
- file_data = NULL;
- position = ft->transferred;
-
- /* Full file received. */
- if (m->file_filedata) {
- (*m->file_filedata)(m, i, real_filenumber, position, file_data, file_data_length, userdata);
- }
- }
-
- /* Data is zero, filetransfer is over. */
- if (file_data_length == 0) {
- ft->status = FILESTATUS_NONE;
- }
-
- break;
- }
-
- case PACKET_ID_MSI: {
- if (data_length == 0) {
- break;
- }
-
- if (m->msi_packet) {
- (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata);
- }
-
- break;
- }
-
- default: {
- handle_custom_lossless_packet(object, i, temp, len, userdata);
- break;
- }
- }
-
- return 0;
-}
-
-static void do_friends(Messenger *m, void *userdata)
-{
- uint32_t i;
- uint64_t temp_time = unix_time();
-
- for (i = 0; i < m->numfriends; ++i) {
- if (m->friendlist[i].status == FRIEND_ADDED) {
- int fr = send_friend_request_packet(m->fr_c, m->friendlist[i].friendcon_id, m->friendlist[i].friendrequest_nospam,
- m->friendlist[i].info,
- m->friendlist[i].info_size);
-
- if (fr >= 0) {
- set_friend_status(m, i, FRIEND_REQUESTED, userdata);
- m->friendlist[i].friendrequest_lastsent = temp_time;
- }
- }
-
- if (m->friendlist[i].status == FRIEND_REQUESTED
- || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */
- if (m->friendlist[i].status == FRIEND_REQUESTED) {
- /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
- * unsuccessful so we set the status back to FRIEND_ADDED and try again.
- */
- check_friend_request_timed_out(m, i, temp_time, userdata);
- }
- }
-
- if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */
- if (m->friendlist[i].name_sent == 0) {
- if (m_sendname(m, i, m->name, m->name_length)) {
- m->friendlist[i].name_sent = 1;
- }
- }
-
- if (m->friendlist[i].statusmessage_sent == 0) {
- if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length)) {
- m->friendlist[i].statusmessage_sent = 1;
- }
- }
-
- if (m->friendlist[i].userstatus_sent == 0) {
- if (send_userstatus(m, i, m->userstatus)) {
- m->friendlist[i].userstatus_sent = 1;
- }
- }
-
- if (m->friendlist[i].user_istyping_sent == 0) {
- if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) {
- m->friendlist[i].user_istyping_sent = 1;
- }
- }
-
- check_friend_tcp_udp(m, i, userdata);
- do_receipts(m, i, userdata);
- do_reqchunk_filecb(m, i, userdata);
-
- m->friendlist[i].last_seen_time = (uint64_t) time(NULL);
- }
- }
-}
-
-static void connection_status_cb(Messenger *m, void *userdata)
-{
- unsigned int conn_status = onion_connection_status(m->onion_c);
-
- if (conn_status != m->last_connection_status) {
- if (m->core_connection_change) {
- (*m->core_connection_change)(m, conn_status, userdata);
- }
-
- m->last_connection_status = conn_status;
- }
-}
-
-
-#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
-
-#define IDSTRING_LEN (CRYPTO_PUBLIC_KEY_SIZE * 2 + 1)
-/* id_str should be of length at least IDSTRING_LEN */
-static char *id_to_string(const uint8_t *pk, char *id_str, size_t length)
-{
- if (length < IDSTRING_LEN) {
- snprintf(id_str, length, "Bad buf length");
- return id_str;
- }
-
- for (uint32_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; i++) {
- sprintf(&id_str[i * 2], "%02X", pk[i]);
- }
-
- id_str[CRYPTO_PUBLIC_KEY_SIZE * 2] = 0;
- return id_str;
-}
-
-/* Minimum messenger run interval in ms
- TODO(mannol): A/V */
-#define MIN_RUN_INTERVAL 50
-
-/* Return the time in milliseconds before do_messenger() should be called again
- * for optimal performance.
- *
- * returns time (in ms) before the next do_messenger() needs to be run on success.
- */
-uint32_t messenger_run_interval(const Messenger *m)
-{
- uint32_t crypto_interval = crypto_run_interval(m->net_crypto);
-
- if (crypto_interval > MIN_RUN_INTERVAL) {
- return MIN_RUN_INTERVAL;
- }
-
- return crypto_interval;
-}
-
-/* The main loop that needs to be run at least 20 times per second. */
-void do_messenger(Messenger *m, void *userdata)
-{
- // Add the TCP relays, but only if this is the first time calling do_messenger
- if (m->has_added_relays == 0) {
- m->has_added_relays = 1;
-
- int i;
-
- for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) {
- add_tcp_relay(m->net_crypto, m->loaded_relays[i].ip_port, m->loaded_relays[i].public_key);
- }
-
- if (m->tcp_server) {
- /* Add self tcp server. */
- IP_Port local_ip_port;
- local_ip_port.port = m->options.tcp_server_port;
- local_ip_port.ip.family = TOX_AF_INET;
- local_ip_port.ip.ip4 = get_ip4_loopback();
- add_tcp_relay(m->net_crypto, local_ip_port,
- tcp_server_public_key(m->tcp_server));
- }
- }
-
- unix_time_update();
-
- if (!m->options.udp_disabled) {
- networking_poll(m->net, userdata);
- do_DHT(m->dht);
- }
-
- if (m->tcp_server) {
- do_TCP_server(m->tcp_server);
- }
-
- do_net_crypto(m->net_crypto, userdata);
- do_onion_client(m->onion_c);
- do_friend_connections(m->fr_c, userdata);
- do_friends(m, userdata);
- connection_status_cb(m, userdata);
-
- if (unix_time() > m->lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
- m->lastdump = unix_time();
- uint32_t client, last_pinged;
-
- for (client = 0; client < LCLIENT_LIST; client++) {
- Client_data *cptr = &m->dht->close_clientlist[client];
- IPPTsPng *assoc = NULL;
- uint32_t a;
-
- for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
- if (ip_isset(&assoc->ip_port.ip)) {
- last_pinged = m->lastdump - assoc->last_pinged;
-
- if (last_pinged > 999) {
- last_pinged = 999;
- }
-
- char ip_str[IP_NTOA_LEN];
- char id_str[IDSTRING_LEN];
- LOGGER_TRACE(m->log, "C[%2u] %s:%u [%3u] %s",
- client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
- net_ntohs(assoc->ip_port.port), last_pinged,
- id_to_string(cptr->public_key, id_str, sizeof(id_str)));
- }
- }
- }
-
-
- uint32_t friend_idx, dhtfriend;
-
- /* dht contains additional "friends" (requests) */
- uint32_t num_dhtfriends = m->dht->num_friends;
- VLA(int32_t, m2dht, num_dhtfriends);
- VLA(int32_t, dht2m, num_dhtfriends);
-
- for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
- m2dht[friend_idx] = -1;
- dht2m[friend_idx] = -1;
-
- if (friend_idx >= m->numfriends) {
- continue;
- }
-
- for (dhtfriend = 0; dhtfriend < m->dht->num_friends; dhtfriend++) {
- if (id_equal(m->friendlist[friend_idx].real_pk, m->dht->friends_list[dhtfriend].public_key)) {
- m2dht[friend_idx] = dhtfriend;
- break;
- }
- }
- }
-
- for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
- if (m2dht[friend_idx] >= 0) {
- dht2m[m2dht[friend_idx]] = friend_idx;
- }
- }
-
- if (m->numfriends != m->dht->num_friends) {
- LOGGER_TRACE(m->log, "Friend num in DHT %u != friend num in msger %u\n", m->dht->num_friends, m->numfriends);
- }
-
- Friend *msgfptr;
- DHT_Friend *dhtfptr;
-
- for (friend_idx = 0; friend_idx < num_dhtfriends; friend_idx++) {
- if (dht2m[friend_idx] >= 0) {
- msgfptr = &m->friendlist[dht2m[friend_idx]];
- } else {
- msgfptr = NULL;
- }
-
- dhtfptr = &m->dht->friends_list[friend_idx];
-
- if (msgfptr) {
- char id_str[IDSTRING_LEN];
- LOGGER_TRACE(m->log, "F[%2u:%2u] <%s> %s",
- dht2m[friend_idx], friend_idx, msgfptr->name,
- id_to_string(msgfptr->real_pk, id_str, sizeof(id_str)));
- } else {
- char id_str[IDSTRING_LEN];
- LOGGER_TRACE(m->log, "F[--:%2u] %s", friend_idx,
- id_to_string(dhtfptr->public_key, id_str, sizeof(id_str)));
- }
-
- for (client = 0; client < MAX_FRIEND_CLIENTS; client++) {
- Client_data *cptr = &dhtfptr->client_list[client];
- IPPTsPng *assoc = NULL;
- uint32_t a;
-
- for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) {
- if (ip_isset(&assoc->ip_port.ip)) {
- last_pinged = m->lastdump - assoc->last_pinged;
-
- if (last_pinged > 999) {
- last_pinged = 999;
- }
-
- char ip_str[IP_NTOA_LEN];
- char id_str[IDSTRING_LEN];
- LOGGER_TRACE(m->log, "F[%2u] => C[%2u] %s:%u [%3u] %s",
- friend_idx, client, ip_ntoa(&assoc->ip_port.ip, ip_str, sizeof(ip_str)),
- net_ntohs(assoc->ip_port.port), last_pinged,
- id_to_string(cptr->public_key, id_str, sizeof(id_str)));
- }
- }
- }
- }
- }
-}
-
-/* new messenger format for load/save, more robust and forward compatible */
-
-#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f
-
-#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
-#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1
-#define MESSENGER_STATE_TYPE_DHT 2
-#define MESSENGER_STATE_TYPE_FRIENDS 3
-#define MESSENGER_STATE_TYPE_NAME 4
-#define MESSENGER_STATE_TYPE_STATUSMESSAGE 5
-#define MESSENGER_STATE_TYPE_STATUS 6
-#define MESSENGER_STATE_TYPE_TCP_RELAY 10
-#define MESSENGER_STATE_TYPE_PATH_NODE 11
-#define MESSENGER_STATE_TYPE_END 255
-
-#define SAVED_FRIEND_REQUEST_SIZE 1024
-#define NUM_SAVED_PATH_NODES 8
-
-struct SAVED_FRIEND {
- uint8_t status;
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do.
- uint16_t info_size; // Length of the info.
- uint8_t name[MAX_NAME_LENGTH];
- uint16_t name_length;
- uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
- uint16_t statusmessage_length;
- uint8_t userstatus;
- uint32_t friendrequest_nospam;
- uint64_t last_seen_time;
-};
-
-static uint32_t friend_size()
-{
- uint32_t data = 0;
- const struct SAVED_FRIEND temp = { 0 };
-
-#define VALUE_MEMBER(NAME) data += sizeof(temp.NAME)
-#define ARRAY_MEMBER(NAME) data += sizeof(temp.NAME)
-
- // Exactly the same in friend_load, friend_save, and friend_size
- VALUE_MEMBER(status);
- ARRAY_MEMBER(real_pk);
- ARRAY_MEMBER(info);
- data++; // padding
- VALUE_MEMBER(info_size);
- ARRAY_MEMBER(name);
- VALUE_MEMBER(name_length);
- ARRAY_MEMBER(statusmessage);
- data++; // padding
- VALUE_MEMBER(statusmessage_length);
- VALUE_MEMBER(userstatus);
- data += 3; // padding
- VALUE_MEMBER(friendrequest_nospam);
- VALUE_MEMBER(last_seen_time);
-
-#undef VALUE_MEMBER
-#undef ARRAY_MEMBER
-
- return data;
-}
-
-static uint32_t saved_friendslist_size(const Messenger *m)
-{
- return count_friendlist(m) * friend_size();
-}
-
-static uint8_t *friend_save(const struct SAVED_FRIEND *temp, uint8_t *data)
-{
-#define VALUE_MEMBER(NAME) \
- memcpy(data, &temp->NAME, sizeof(temp->NAME)); \
- data += sizeof(temp->NAME)
-
-#define ARRAY_MEMBER(NAME) \
- memcpy(data, temp->NAME, sizeof(temp->NAME)); \
- data += sizeof(temp->NAME)
-
- // Exactly the same in friend_load, friend_save, and friend_size
- VALUE_MEMBER(status);
- ARRAY_MEMBER(real_pk);
- ARRAY_MEMBER(info);
- data++; // padding
- VALUE_MEMBER(info_size);
- ARRAY_MEMBER(name);
- VALUE_MEMBER(name_length);
- ARRAY_MEMBER(statusmessage);
- data++; // padding
- VALUE_MEMBER(statusmessage_length);
- VALUE_MEMBER(userstatus);
- data += 3; // padding
- VALUE_MEMBER(friendrequest_nospam);
- VALUE_MEMBER(last_seen_time);
-
-#undef VALUE_MEMBER
-#undef ARRAY_MEMBER
-
- return data;
-}
-
-static uint32_t friends_list_save(const Messenger *m, uint8_t *data)
-{
- uint32_t i;
- uint32_t num = 0;
- uint8_t *cur_data = data;
-
- for (i = 0; i < m->numfriends; i++) {
- if (m->friendlist[i].status > 0) {
- struct SAVED_FRIEND temp = { 0 };
- temp.status = m->friendlist[i].status;
- memcpy(temp.real_pk, m->friendlist[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
-
- if (temp.status < 3) {
- const size_t friendrequest_length =
- MIN(m->friendlist[i].info_size,
- MIN(SAVED_FRIEND_REQUEST_SIZE, MAX_FRIEND_REQUEST_DATA_SIZE));
- memcpy(temp.info, m->friendlist[i].info, friendrequest_length);
-
- temp.info_size = net_htons(m->friendlist[i].info_size);
- temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam;
- } else {
- memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length);
- temp.name_length = net_htons(m->friendlist[i].name_length);
- memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length);
- temp.statusmessage_length = net_htons(m->friendlist[i].statusmessage_length);
- temp.userstatus = m->friendlist[i].userstatus;
-
- uint8_t last_seen_time[sizeof(uint64_t)];
- memcpy(last_seen_time, &m->friendlist[i].last_seen_time, sizeof(uint64_t));
- host_to_net(last_seen_time, sizeof(uint64_t));
- memcpy(&temp.last_seen_time, last_seen_time, sizeof(uint64_t));
- }
-
- uint8_t *next_data = friend_save(&temp, cur_data);
- assert(next_data - cur_data == friend_size());
-#ifdef __LP64__
- assert(memcmp(cur_data, &temp, friend_size()) == 0);
-#endif
- cur_data = next_data;
- num++;
- }
- }
-
- assert(cur_data - data == num * friend_size());
- return cur_data - data;
-}
-
-static const uint8_t *friend_load(struct SAVED_FRIEND *temp, const uint8_t *data)
-{
-#define VALUE_MEMBER(NAME) \
- memcpy(&temp->NAME, data, sizeof(temp->NAME)); \
- data += sizeof(temp->NAME)
-
-#define ARRAY_MEMBER(NAME) \
- memcpy(temp->NAME, data, sizeof(temp->NAME)); \
- data += sizeof(temp->NAME)
-
- // Exactly the same in friend_load, friend_save, and friend_size
- VALUE_MEMBER(status);
- ARRAY_MEMBER(real_pk);
- ARRAY_MEMBER(info);
- data++; // padding
- VALUE_MEMBER(info_size);
- ARRAY_MEMBER(name);
- VALUE_MEMBER(name_length);
- ARRAY_MEMBER(statusmessage);
- data++; // padding
- VALUE_MEMBER(statusmessage_length);
- VALUE_MEMBER(userstatus);
- data += 3; // padding
- VALUE_MEMBER(friendrequest_nospam);
- VALUE_MEMBER(last_seen_time);
-
-#undef VALUE_MEMBER
-#undef ARRAY_MEMBER
-
- return data;
-}
-
-static int friends_list_load(Messenger *m, const uint8_t *data, uint32_t length)
-{
- if (length % friend_size() != 0) {
- return -1;
- }
-
- uint32_t num = length / friend_size();
- uint32_t i;
- const uint8_t *cur_data = data;
-
- for (i = 0; i < num; ++i) {
- struct SAVED_FRIEND temp = { 0 };
- const uint8_t *next_data = friend_load(&temp, cur_data);
- assert(next_data - cur_data == friend_size());
-#ifdef __LP64__
- assert(memcmp(&temp, cur_data, friend_size()) == 0);
-#endif
- cur_data = next_data;
-
- if (temp.status >= 3) {
- int fnum = m_addfriend_norequest(m, temp.real_pk);
-
- if (fnum < 0) {
- continue;
- }
-
- setfriendname(m, fnum, temp.name, net_ntohs(temp.name_length));
- set_friend_statusmessage(m, fnum, temp.statusmessage, net_ntohs(temp.statusmessage_length));
- set_friend_userstatus(m, fnum, temp.userstatus);
- uint8_t last_seen_time[sizeof(uint64_t)];
- memcpy(last_seen_time, &temp.last_seen_time, sizeof(uint64_t));
- net_to_host(last_seen_time, sizeof(uint64_t));
- memcpy(&m->friendlist[fnum].last_seen_time, last_seen_time, sizeof(uint64_t));
- } else if (temp.status != 0) {
- /* TODO(irungentoo): This is not a good way to do this. */
- uint8_t address[FRIEND_ADDRESS_SIZE];
- id_copy(address, temp.real_pk);
- memcpy(address + CRYPTO_PUBLIC_KEY_SIZE, &(temp.friendrequest_nospam), sizeof(uint32_t));
- uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
- memcpy(address + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t), &checksum, sizeof(checksum));
- m_addfriend(m, address, temp.info, net_ntohs(temp.info_size));
- }
- }
-
- return num;
-}
-
-/* return size of the messenger data (for saving) */
-uint32_t messenger_size(const Messenger *m)
-{
- uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
- return size32 * 2 // global cookie
- + sizesubhead + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE
- + sizesubhead + DHT_size(m->dht) // DHT
- + sizesubhead + saved_friendslist_size(m) // Friendlist itself.
- + sizesubhead + m->name_length // Own nickname.
- + sizesubhead + m->statusmessage_length // status message
- + sizesubhead + 1 // status
- + sizesubhead + NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6) //TCP relays
- + sizesubhead + NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6) //saved path nodes
- + sizesubhead;
-}
-
-static uint8_t *messenger_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
-{
- host_to_lendian32(data, len);
- data += sizeof(uint32_t);
- host_to_lendian32(data, (host_tolendian16(MESSENGER_STATE_COOKIE_TYPE) << 16) | host_tolendian16(type));
- data += sizeof(uint32_t);
- return data;
-}
-
-/* Save the messenger in data of size Messenger_size(). */
-void messenger_save(const Messenger *m, uint8_t *data)
-{
- memset(data, 0, messenger_size(m));
-
- uint32_t len;
- uint16_t type;
- uint32_t size32 = sizeof(uint32_t);
-
- memset(data, 0, size32);
- data += size32;
- host_to_lendian32(data, MESSENGER_STATE_COOKIE_GLOBAL);
- data += size32;
-
- assert(sizeof(get_nospam(&m->fr)) == sizeof(uint32_t));
- len = size32 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE;
- type = MESSENGER_STATE_TYPE_NOSPAMKEYS;
- data = messenger_save_subheader(data, len, type);
- *(uint32_t *)data = get_nospam(&(m->fr));
- save_keys(m->net_crypto, data + size32);
- data += len;
-
- len = saved_friendslist_size(m);
- type = MESSENGER_STATE_TYPE_FRIENDS;
- data = messenger_save_subheader(data, len, type);
- friends_list_save(m, data);
- data += len;
-
- len = m->name_length;
- type = MESSENGER_STATE_TYPE_NAME;
- data = messenger_save_subheader(data, len, type);
- memcpy(data, m->name, len);
- data += len;
-
- len = m->statusmessage_length;
- type = MESSENGER_STATE_TYPE_STATUSMESSAGE;
- data = messenger_save_subheader(data, len, type);
- memcpy(data, m->statusmessage, len);
- data += len;
-
- len = 1;
- type = MESSENGER_STATE_TYPE_STATUS;
- data = messenger_save_subheader(data, len, type);
- *data = m->userstatus;
- data += len;
-
- len = DHT_size(m->dht);
- type = MESSENGER_STATE_TYPE_DHT;
- data = messenger_save_subheader(data, len, type);
- DHT_save(m->dht, data);
- data += len;
-
- Node_format relays[NUM_SAVED_TCP_RELAYS];
- type = MESSENGER_STATE_TYPE_TCP_RELAY;
- uint8_t *temp_data = data;
- data = messenger_save_subheader(temp_data, 0, type);
- unsigned int num = copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS);
- int l = pack_nodes(data, NUM_SAVED_TCP_RELAYS * packed_node_size(TCP_INET6), relays, num);
-
- if (l > 0) {
- len = l;
- data = messenger_save_subheader(temp_data, len, type);
- data += len;
- }
-
- Node_format nodes[NUM_SAVED_PATH_NODES];
- type = MESSENGER_STATE_TYPE_PATH_NODE;
- temp_data = data;
- data = messenger_save_subheader(data, 0, type);
- memset(nodes, 0, sizeof(nodes));
- num = onion_backup_nodes(m->onion_c, nodes, NUM_SAVED_PATH_NODES);
- l = pack_nodes(data, NUM_SAVED_PATH_NODES * packed_node_size(TCP_INET6), nodes, num);
-
- if (l > 0) {
- len = l;
- data = messenger_save_subheader(temp_data, len, type);
- data += len;
- }
-
- messenger_save_subheader(data, 0, MESSENGER_STATE_TYPE_END);
-}
-
-static int messenger_load_state_callback(void *outer, const uint8_t *data, uint32_t length, uint16_t type)
-{
- Messenger *m = (Messenger *)outer;
-
- switch (type) {
- case MESSENGER_STATE_TYPE_NOSPAMKEYS:
- if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE + sizeof(uint32_t)) {
- set_nospam(&(m->fr), *(const uint32_t *)data);
- load_secret_key(m->net_crypto, (&data[sizeof(uint32_t)]) + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (public_key_cmp((&data[sizeof(uint32_t)]), m->net_crypto->self_public_key) != 0) {
- return -1;
- }
- } else {
- return -1; /* critical */
- }
-
- break;
-
- case MESSENGER_STATE_TYPE_DHT:
- DHT_load(m->dht, data, length);
- break;
-
- case MESSENGER_STATE_TYPE_FRIENDS:
- friends_list_load(m, data, length);
- break;
-
- case MESSENGER_STATE_TYPE_NAME:
- if ((length > 0) && (length <= MAX_NAME_LENGTH)) {
- setname(m, data, length);
- }
-
- break;
-
- case MESSENGER_STATE_TYPE_STATUSMESSAGE:
- if ((length > 0) && (length <= MAX_STATUSMESSAGE_LENGTH)) {
- m_set_statusmessage(m, data, length);
- }
-
- break;
-
- case MESSENGER_STATE_TYPE_STATUS:
- if (length == 1) {
- m_set_userstatus(m, *data);
- }
-
- break;
-
- case MESSENGER_STATE_TYPE_TCP_RELAY: {
- if (length == 0) {
- break;
- }
-
- unpack_nodes(m->loaded_relays, NUM_SAVED_TCP_RELAYS, 0, data, length, 1);
- m->has_added_relays = 0;
-
- break;
- }
-
- case MESSENGER_STATE_TYPE_PATH_NODE: {
- Node_format nodes[NUM_SAVED_PATH_NODES];
-
- if (length == 0) {
- break;
- }
-
- int i, num = unpack_nodes(nodes, NUM_SAVED_PATH_NODES, 0, data, length, 0);
-
- for (i = 0; i < num; ++i) {
- onion_add_bs_path_node(m->onion_c, nodes[i].ip_port, nodes[i].public_key);
- }
-
- break;
- }
-
- case MESSENGER_STATE_TYPE_END: {
- if (length != 0) {
- return -1;
- }
-
- return -2;
- }
-
- default:
- LOGGER_ERROR(m->log, "Load state: contains unrecognized part (len %u, type %u)\n",
- length, type);
- break;
- }
-
- return 0;
-}
-
-/* Load the messenger from data of size length. */
-int messenger_load(Messenger *m, const uint8_t *data, uint32_t length)
-{
- uint32_t data32[2];
- uint32_t cookie_len = sizeof(data32);
-
- if (length < cookie_len) {
- return -1;
- }
-
- memcpy(data32, data, sizeof(uint32_t));
- lendian_to_host32(data32 + 1, data + sizeof(uint32_t));
-
- if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) {
- return load_state(messenger_load_state_callback, m->log, m, data + cookie_len,
- length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
- }
-
- return -1;
-}
-
-/* Return the number of friends in the instance m.
- * You should use this to determine how much memory to allocate
- * for copy_friendlist. */
-uint32_t count_friendlist(const Messenger *m)
-{
- uint32_t ret = 0;
- uint32_t i;
-
- for (i = 0; i < m->numfriends; i++) {
- if (m->friendlist[i].status > 0) {
- ret++;
- }
- }
-
- return ret;
-}
-
-/* Copy a list of valid friend IDs into the array out_list.
- * If out_list is NULL, returns 0.
- * Otherwise, returns the number of elements copied.
- * If the array was too small, the contents
- * of out_list will be truncated to list_size. */
-uint32_t copy_friendlist(Messenger const *m, uint32_t *out_list, uint32_t list_size)
-{
- if (!out_list) {
- return 0;
- }
-
- if (m->numfriends == 0) {
- return 0;
- }
-
- uint32_t i;
- uint32_t ret = 0;
-
- for (i = 0; i < m->numfriends; i++) {
- if (ret >= list_size) {
- break; /* Abandon ship */
- }
-
- if (m->friendlist[i].status > 0) {
- out_list[ret] = i;
- ret++;
- }
- }
-
- return ret;
-}
diff --git a/libs/libtox/src/toxcore/Messenger.h b/libs/libtox/src/toxcore/Messenger.h
deleted file mode 100644
index e1dba69886..0000000000
--- a/libs/libtox/src/toxcore/Messenger.h
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- * An implementation of a simple text chat only messenger on the tox network
- * core.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef MESSENGER_H
-#define MESSENGER_H
-
-#include "friend_connection.h"
-#include "friend_requests.h"
-#include "logger.h"
-
-#define MAX_NAME_LENGTH 128
-/* TODO(irungentoo): this must depend on other variable. */
-#define MAX_STATUSMESSAGE_LENGTH 1007
-/* Used for TCP relays in Messenger struct (may need to be % 2 == 0)*/
-#define NUM_SAVED_TCP_RELAYS 8
-/* This cannot be bigger than 256 */
-#define MAX_CONCURRENT_FILE_PIPES 256
-
-
-#define FRIEND_ADDRESS_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
-
-enum {
- MESSAGE_NORMAL,
- MESSAGE_ACTION
-};
-
-/* NOTE: Packet ids below 24 must never be used. */
-#define PACKET_ID_ONLINE 24
-#define PACKET_ID_OFFLINE 25
-#define PACKET_ID_NICKNAME 48
-#define PACKET_ID_STATUSMESSAGE 49
-#define PACKET_ID_USERSTATUS 50
-#define PACKET_ID_TYPING 51
-#define PACKET_ID_MESSAGE 64
-#define PACKET_ID_ACTION (PACKET_ID_MESSAGE + MESSAGE_ACTION) /* 65 */
-#define PACKET_ID_MSI 69
-#define PACKET_ID_FILE_SENDREQUEST 80
-#define PACKET_ID_FILE_CONTROL 81
-#define PACKET_ID_FILE_DATA 82
-#define PACKET_ID_INVITE_CONFERENCE 96
-#define PACKET_ID_ONLINE_PACKET 97
-#define PACKET_ID_DIRECT_CONFERENCE 98
-#define PACKET_ID_MESSAGE_CONFERENCE 99
-#define PACKET_ID_LOSSY_CONFERENCE 199
-
-/* All packets starting with a byte in this range can be used for anything. */
-#define PACKET_ID_LOSSLESS_RANGE_START 160
-#define PACKET_ID_LOSSLESS_RANGE_SIZE 32
-#define PACKET_LOSSY_AV_RESERVED 8 /* Number of lossy packet types at start of range reserved for A/V. */
-
-typedef struct {
- uint8_t ipv6enabled;
- uint8_t udp_disabled;
- TCP_Proxy_Info proxy_info;
- uint16_t port_range[2];
- uint16_t tcp_server_port;
-
- uint8_t hole_punching_enabled;
- bool local_discovery_enabled;
-
- logger_cb *log_callback;
- void *log_user_data;
-} Messenger_Options;
-
-
-struct Receipts {
- uint32_t packet_num;
- uint32_t msg_id;
- struct Receipts *next;
-};
-
-/* Status definitions. */
-enum {
- NOFRIEND,
- FRIEND_ADDED,
- FRIEND_REQUESTED,
- FRIEND_CONFIRMED,
- FRIEND_ONLINE,
-};
-
-/* Errors for m_addfriend
- * FAERR - Friend Add Error
- */
-enum {
- FAERR_TOOLONG = -1,
- FAERR_NOMESSAGE = -2,
- FAERR_OWNKEY = -3,
- FAERR_ALREADYSENT = -4,
- FAERR_BADCHECKSUM = -6,
- FAERR_SETNEWNOSPAM = -7,
- FAERR_NOMEM = -8
-};
-
-
-/* Default start timeout in seconds between friend requests. */
-#define FRIENDREQUEST_TIMEOUT 5;
-
-enum {
- CONNECTION_NONE,
- CONNECTION_TCP,
- CONNECTION_UDP,
- CONNECTION_UNKNOWN
-};
-
-/* USERSTATUS -
- * Represents userstatuses someone can have.
- */
-
-typedef enum {
- USERSTATUS_NONE,
- USERSTATUS_AWAY,
- USERSTATUS_BUSY,
- USERSTATUS_INVALID
-}
-USERSTATUS;
-
-#define FILE_ID_LENGTH 32
-
-struct File_Transfers {
- uint64_t size;
- uint64_t transferred;
- uint8_t status; /* 0 == no transfer, 1 = not accepted, 3 = transferring, 4 = broken, 5 = finished */
- uint8_t paused; /* 0: not paused, 1 = paused by us, 2 = paused by other, 3 = paused by both. */
- uint32_t last_packet_number; /* number of the last packet sent. */
- uint64_t requested; /* total data requested by the request chunk callback */
- unsigned int slots_allocated; /* number of slots allocated to this transfer. */
- uint8_t id[FILE_ID_LENGTH];
-};
-enum {
- FILESTATUS_NONE,
- FILESTATUS_NOT_ACCEPTED,
- FILESTATUS_TRANSFERRING,
- //FILESTATUS_BROKEN,
- FILESTATUS_FINISHED
-};
-
-enum {
- FILE_PAUSE_NOT,
- FILE_PAUSE_US,
- FILE_PAUSE_OTHER,
- FILE_PAUSE_BOTH
-};
-
-enum {
- FILECONTROL_ACCEPT,
- FILECONTROL_PAUSE,
- FILECONTROL_KILL,
- FILECONTROL_SEEK
-};
-
-enum {
- FILEKIND_DATA,
- FILEKIND_AVATAR
-};
-
-
-typedef struct Messenger Messenger;
-
-typedef struct {
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- int friendcon_id;
-
- uint64_t friendrequest_lastsent; // Time at which the last friend request was sent.
- uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts.
- uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online.
- uint8_t info[MAX_FRIEND_REQUEST_DATA_SIZE]; // the data that is sent during the friend requests we do.
- uint8_t name[MAX_NAME_LENGTH];
- uint16_t name_length;
- uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have.
- uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
- uint16_t statusmessage_length;
- uint8_t statusmessage_sent;
- USERSTATUS userstatus;
- uint8_t userstatus_sent;
- uint8_t user_istyping;
- uint8_t user_istyping_sent;
- uint8_t is_typing;
- uint16_t info_size; // Length of the info.
- uint32_t message_id; // a semi-unique id used in read receipts.
- uint32_t friendrequest_nospam; // The nospam number used in the friend request.
- uint64_t last_seen_time;
- uint8_t last_connection_udp_tcp;
- struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
- unsigned int num_sending_files;
- struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
-
- struct {
- int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object);
- void *object;
- } lossy_rtp_packethandlers[PACKET_LOSSY_AV_RESERVED];
-
- struct Receipts *receipts_start;
- struct Receipts *receipts_end;
-} Friend;
-
-struct Messenger {
- Logger *log;
-
- Networking_Core *net;
- Net_Crypto *net_crypto;
- DHT *dht;
-
- Onion *onion;
- Onion_Announce *onion_a;
- Onion_Client *onion_c;
-
- Friend_Connections *fr_c;
-
- TCP_Server *tcp_server;
- Friend_Requests fr;
- uint8_t name[MAX_NAME_LENGTH];
- uint16_t name_length;
-
- uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
- uint16_t statusmessage_length;
-
- USERSTATUS userstatus;
-
- Friend *friendlist;
- uint32_t numfriends;
-
- time_t lastdump;
-
- uint8_t has_added_relays; // If the first connection has occurred in do_messenger
- Node_format loaded_relays[NUM_SAVED_TCP_RELAYS]; // Relays loaded from config
-
- void (*friend_message)(struct Messenger *m, uint32_t, unsigned int, const uint8_t *, size_t, void *);
- void (*friend_namechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
- void (*friend_statusmessagechange)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
- void (*friend_userstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
- void (*friend_typingchange)(struct Messenger *m, uint32_t, bool, void *);
- void (*read_receipt)(struct Messenger *m, uint32_t, uint32_t, void *);
- void (*friend_connectionstatuschange)(struct Messenger *m, uint32_t, unsigned int, void *);
- void (*friend_connectionstatuschange_internal)(struct Messenger *m, uint32_t, uint8_t, void *);
- void *friend_connectionstatuschange_internal_userdata;
-
- void *conferences_object; /* Set by new_groupchats()*/
- void (*conference_invite)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
-
- void (*file_sendrequest)(struct Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t,
- void *);
- void (*file_filecontrol)(struct Messenger *m, uint32_t, uint32_t, unsigned int, void *);
- void (*file_filedata)(struct Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *, size_t, void *);
- void (*file_reqchunk)(struct Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *);
-
- void (*msi_packet)(struct Messenger *m, uint32_t, const uint8_t *, uint16_t, void *);
- void *msi_packet_userdata;
-
- void (*lossy_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
- void (*lossless_packethandler)(struct Messenger *m, uint32_t, const uint8_t *, size_t, void *);
-
- void (*core_connection_change)(struct Messenger *m, unsigned int, void *);
- unsigned int last_connection_status;
-
- Messenger_Options options;
-};
-
-/* Format: [real_pk (32 bytes)][nospam number (4 bytes)][checksum (2 bytes)]
- *
- * return FRIEND_ADDRESS_SIZE byte address to give to others.
- */
-void getaddress(const Messenger *m, uint8_t *address);
-
-/* Add a friend.
- * Set the data that will be sent along with friend request.
- * address is the address of the friend (returned by getaddress of the friend
- * you wish to add) it must be FRIEND_ADDRESS_SIZE bytes.
- * TODO(irungentoo): add checksum.
- * data is the data and length is the length.
- *
- * return the friend number if success.
- * return -1 if message length is too long.
- * return -2 if no message (message length must be >= 1 byte).
- * return -3 if user's own key.
- * return -4 if friend request already sent or already a friend.
- * return -6 if bad checksum in address.
- * return -7 if the friend was already there but the nospam was different.
- * (the nospam for that friend was set to the new one).
- * return -8 if increasing the friend list size fails.
- */
-int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, uint16_t length);
-
-
-/* Add a friend without sending a friendrequest.
- * return the friend number if success.
- * return -3 if user's own key.
- * return -4 if friend request already sent or already a friend.
- * return -6 if bad checksum in address.
- * return -8 if increasing the friend list size fails.
- */
-int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk);
-
-/* return the friend number associated to that client id.
- * return -1 if no such friend.
- */
-int32_t getfriend_id(const Messenger *m, const uint8_t *real_pk);
-
-/* Copies the public key associated to that friend id into real_pk buffer.
- * Make sure that real_pk is of size CRYPTO_PUBLIC_KEY_SIZE.
- *
- * return 0 if success
- * return -1 if failure
- */
-int get_real_pk(const Messenger *m, int32_t friendnumber, uint8_t *real_pk);
-
-/* return friend connection id on success.
- * return -1 if failure.
- */
-int getfriendcon_id(const Messenger *m, int32_t friendnumber);
-
-/* Remove a friend.
- *
- * return 0 if success
- * return -1 if failure
- */
-int m_delfriend(Messenger *m, int32_t friendnumber);
-
-/* Checks friend's connecting status.
- *
- * return CONNECTION_UDP (2) if friend is directly connected to us (Online UDP).
- * return CONNECTION_TCP (1) if friend is connected to us (Online TCP).
- * return CONNECTION_NONE (0) if friend is not connected to us (Offline).
- * return -1 on failure.
- */
-int m_get_friend_connectionstatus(const Messenger *m, int32_t friendnumber);
-
-/* Checks if there exists a friend with given friendnumber.
- *
- * return 1 if friend exists.
- * return 0 if friend doesn't exist.
- */
-int m_friend_exists(const Messenger *m, int32_t friendnumber);
-
-/* Send a message of type to an online friend.
- *
- * return -1 if friend not valid.
- * return -2 if too large.
- * return -3 if friend not online.
- * return -4 if send failed (because queue is full).
- * return -5 if bad type.
- * return 0 if success.
- *
- * the value in message_id will be passed to your read_receipt callback when the other receives the message.
- */
-int m_send_message_generic(Messenger *m, int32_t friendnumber, uint8_t type, const uint8_t *message, uint32_t length,
- uint32_t *message_id);
-
-
-/* Set the name and name_length of a friend.
- * name must be a string of maximum MAX_NAME_LENGTH length.
- * length must be at least 1 byte.
- * length is the length of name with the NULL terminator.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int setfriendname(Messenger *m, int32_t friendnumber, const uint8_t *name, uint16_t length);
-
-/* Set our nickname.
- * name must be a string of maximum MAX_NAME_LENGTH length.
- * length must be at least 1 byte.
- * length is the length of name with the NULL terminator.
- *
- * return 0 if success.
- * return -1 if failure.
- */
-int setname(Messenger *m, const uint8_t *name, uint16_t length);
-
-/*
- * Get your nickname.
- * m - The messenger context to use.
- * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
- *
- * return length of the name.
- * return 0 on error.
- */
-uint16_t getself_name(const Messenger *m, uint8_t *name);
-
-/* Get name of friendnumber and put it in name.
- * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
- *
- * return length of name if success.
- * return -1 if failure.
- */
-int getname(const Messenger *m, int32_t friendnumber, uint8_t *name);
-
-/* return the length of name, including null on success.
- * return -1 on failure.
- */
-int m_get_name_size(const Messenger *m, int32_t friendnumber);
-int m_get_self_name_size(const Messenger *m);
-
-/* Set our user status.
- * You are responsible for freeing status after.
- *
- * returns 0 on success.
- * returns -1 on failure.
- */
-int m_set_statusmessage(Messenger *m, const uint8_t *status, uint16_t length);
-int m_set_userstatus(Messenger *m, uint8_t status);
-
-/* return the length of friendnumber's status message, including null on success.
- * return -1 on failure.
- */
-int m_get_statusmessage_size(const Messenger *m, int32_t friendnumber);
-int m_get_self_statusmessage_size(const Messenger *m);
-
-/* Copy friendnumber's status message into buf, truncating if size is over maxlen.
- * Get the size you need to allocate from m_get_statusmessage_size.
- * The self variant will copy our own status message.
- *
- * returns the length of the copied data on success
- * retruns -1 on failure.
- */
-int m_copy_statusmessage(const Messenger *m, int32_t friendnumber, uint8_t *buf, uint32_t maxlen);
-int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf);
-
-/* return one of USERSTATUS values.
- * Values unknown to your application should be represented as USERSTATUS_NONE.
- * As above, the self variant will return our own USERSTATUS.
- * If friendnumber is invalid, this shall return USERSTATUS_INVALID.
- */
-uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
-uint8_t m_get_self_userstatus(const Messenger *m);
-
-
-/* returns timestamp of last time friendnumber was seen online or 0 if never seen.
- * if friendnumber is invalid this function will return UINT64_MAX.
- */
-uint64_t m_get_last_online(const Messenger *m, int32_t friendnumber);
-
-/* Set our typing status for a friend.
- * You are responsible for turning it on or off.
- *
- * returns 0 on success.
- * returns -1 on failure.
- */
-int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing);
-
-/* Get the typing status of a friend.
- *
- * returns 0 if friend is not typing.
- * returns 1 if friend is typing.
- */
-int m_get_istyping(const Messenger *m, int32_t friendnumber);
-
-/* Set the logger callback.
- */
-void m_callback_log(Messenger *m, logger_cb *function, void *context, void *userdata);
-
-/* Set the function that will be executed when a friend request is received.
- * Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
- */
-void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
- void *));
-
-/* Set the function that will be executed when a message from a friend is received.
- * Function format is: function(uint32_t friendnumber, unsigned int type, uint8_t * message, uint32_t length)
- */
-void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, const uint8_t *,
- size_t, void *));
-
-/* Set the callback for name changes.
- * Function(uint32_t friendnumber, uint8_t *newname, size_t length)
- * You are not responsible for freeing newname.
- */
-void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
-
-/* Set the callback for status message changes.
- * Function(uint32_t friendnumber, uint8_t *newstatus, size_t length)
- *
- * You are not responsible for freeing newstatus
- */
-void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, size_t, void *));
-
-/* Set the callback for status type changes.
- * Function(uint32_t friendnumber, USERSTATUS kind)
- */
-void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
-
-/* Set the callback for typing changes.
- * Function(uint32_t friendnumber, uint8_t is_typing)
- */
-void m_callback_typingchange(Messenger *m, void(*function)(Messenger *m, uint32_t, bool, void *));
-
-/* Set the callback for read receipts.
- * Function(uint32_t friendnumber, uint32_t receipt)
- *
- * If you are keeping a record of returns from m_sendmessage,
- * receipt might be one of those values, meaning the message
- * has been received on the other side.
- * Since core doesn't track ids for you, receipt may not correspond to any message.
- * In that case, you should discard it.
- */
-void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, void *));
-
-/* Set the callback for connection status changes.
- * function(uint32_t friendnumber, uint8_t status)
- *
- * Status:
- * 0 -- friend went offline after being previously online.
- * 1 -- friend went online.
- *
- * Note that this callback is not called when adding friends, thus the "after
- * being previously online" part.
- * It's assumed that when adding friends, their connection status is offline.
- */
-void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, uint32_t, unsigned int, void *));
-
-/* Same as previous but for internal A/V core usage only */
-void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, uint32_t, uint8_t, void *),
- void *userdata);
-
-
-/* Set the callback for typing changes.
- * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP))
- */
-void m_callback_core_connection(Messenger *m, void (*function)(Messenger *m, unsigned int, void *));
-
-/**********CONFERENCES************/
-
-/* Set the callback for conference invites.
- *
- * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
- */
-void m_callback_conference_invite(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t,
- void *));
-
-/* Send a conference invite packet.
- *
- * return 1 on success
- * return 0 on failure
- */
-int send_conference_invite_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
-
-/****************FILE SENDING*****************/
-
-
-/* Set the callback for file send requests.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint32_t filetype, uint64_t filesize, uint8_t *filename, size_t filename_length, void *userdata)
- */
-void callback_file_sendrequest(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint32_t, uint64_t,
- const uint8_t *, size_t, void *));
-
-
-/* Set the callback for file control requests.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, unsigned int control_type, void *userdata)
- *
- */
-void callback_file_control(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, unsigned int, void *));
-
-/* Set the callback for file data.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, uint8_t *data, size_t length, void *userdata)
- *
- */
-void callback_file_data(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, const uint8_t *,
- size_t, void *));
-
-/* Set the callback for file request chunk.
- *
- * Function(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata)
- *
- */
-void callback_file_reqchunk(Messenger *m, void (*function)(Messenger *m, uint32_t, uint32_t, uint64_t, size_t, void *));
-
-
-/* Copy the file transfer file id to file_id
- *
- * return 0 on success.
- * return -1 if friend not valid.
- * return -2 if filenumber not valid
- */
-int file_get_id(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint8_t *file_id);
-
-/* Send a file send request.
- * Maximum filename length is 255 bytes.
- * return file number on success
- * return -1 if friend not found.
- * return -2 if filename length invalid.
- * return -3 if no more file sending slots left.
- * return -4 if could not send packet (friend offline).
- *
- */
-long int new_filesender(const Messenger *m, int32_t friendnumber, uint32_t file_type, uint64_t filesize,
- const uint8_t *file_id, const uint8_t *filename, uint16_t filename_length);
-
-/* Send a file control request.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if file number invalid.
- * return -4 if file control is bad.
- * return -5 if file already paused.
- * return -6 if resume file failed because it was only paused by the other.
- * return -7 if resume file failed because it wasn't paused.
- * return -8 if packet failed to send.
- */
-int file_control(const Messenger *m, int32_t friendnumber, uint32_t filenumber, unsigned int control);
-
-/* Send a seek file control request.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if file number invalid.
- * return -4 if not receiving file.
- * return -5 if file status wrong.
- * return -6 if position bad.
- * return -8 if packet failed to send.
- */
-int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position);
-
-/* Send file data.
- *
- * return 0 on success
- * return -1 if friend not valid.
- * return -2 if friend not online.
- * return -3 if filenumber invalid.
- * return -4 if file transfer not transferring.
- * return -5 if bad data size.
- * return -6 if packet queue full.
- * return -7 if wrong position.
- */
-int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
- uint16_t length);
-
-/* Give the number of bytes left to be sent/received.
- *
- * send_receive is 0 if we want the sending files, 1 if we want the receiving.
- *
- * return number of bytes remaining to be sent/received on success
- * return 0 on failure
- */
-uint64_t file_dataremaining(const Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t send_receive);
-
-/*************** A/V related ******************/
-
-/* Set the callback for msi packets.
- *
- * Function(Messenger *m, uint32_t friendnumber, uint8_t *data, uint16_t length, void *userdata)
- */
-void m_callback_msi_packet(Messenger *m, void (*function)(Messenger *m, uint32_t, const uint8_t *, uint16_t, void *),
- void *userdata);
-
-/* Send an msi packet.
- *
- * return 1 on success
- * return 0 on failure
- */
-int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length);
-
-/* Set handlers for lossy rtp packets.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, int (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object), void *object);
-
-/**********************************************/
-
-/* Set handlers for custom lossy packets.
- *
- */
-void custom_lossy_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
-
-/* High level function to send custom lossy packets.
- *
- * return -1 if friend invalid.
- * return -2 if length wrong.
- * return -3 if first byte invalid.
- * return -4 if friend offline.
- * return -5 if packet failed to send because of other error.
- * return 0 on success.
- */
-int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
-
-
-/* Set handlers for custom lossless packets.
- *
- */
-void custom_lossless_packet_registerhandler(Messenger *m, void (*packet_handler_callback)(Messenger *m,
- uint32_t friendnumber, const uint8_t *data, size_t len, void *object));
-
-/* High level function to send custom lossless packets.
- *
- * return -1 if friend invalid.
- * return -2 if length wrong.
- * return -3 if first byte invalid.
- * return -4 if friend offline.
- * return -5 if packet failed to send because of other error.
- * return 0 on success.
- */
-int send_custom_lossless_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length);
-
-/**********************************************/
-
-enum {
- MESSENGER_ERROR_NONE,
- MESSENGER_ERROR_PORT,
- MESSENGER_ERROR_TCP_SERVER,
- MESSENGER_ERROR_OTHER
-};
-
-/* Run this at startup.
- * return allocated instance of Messenger on success.
- * return 0 if there are problems.
- *
- * if error is not NULL it will be set to one of the values in the enum above.
- */
-Messenger *new_messenger(Messenger_Options *options, unsigned int *error);
-
-/* Run this before closing shop
- * Free all datastructures.
- */
-void kill_messenger(Messenger *m);
-
-/* The main loop that needs to be run at least 20 times per second. */
-void do_messenger(Messenger *m, void *userdata);
-
-/* Return the time in milliseconds before do_messenger() should be called again
- * for optimal performance.
- *
- * returns time (in ms) before the next do_messenger() needs to be run on success.
- */
-uint32_t messenger_run_interval(const Messenger *m);
-
-/* SAVING AND LOADING FUNCTIONS: */
-
-/* return size of the messenger data (for saving). */
-uint32_t messenger_size(const Messenger *m);
-
-/* Save the messenger in data (must be allocated memory of size Messenger_size()) */
-void messenger_save(const Messenger *m, uint8_t *data);
-
-/* Load the messenger from data of size length. */
-int messenger_load(Messenger *m, const uint8_t *data, uint32_t length);
-
-/* Return the number of friends in the instance m.
- * You should use this to determine how much memory to allocate
- * for copy_friendlist. */
-uint32_t count_friendlist(const Messenger *m);
-
-/* Copy a list of valid friend IDs into the array out_list.
- * If out_list is NULL, returns 0.
- * Otherwise, returns the number of elements copied.
- * If the array was too small, the contents
- * of out_list will be truncated to list_size. */
-uint32_t copy_friendlist(const Messenger *m, uint32_t *out_list, uint32_t list_size);
-
-#endif
diff --git a/libs/libtox/src/toxcore/TCP_client.c b/libs/libtox/src/toxcore/TCP_client.c
deleted file mode 100644
index 8a14c7cd70..0000000000
--- a/libs/libtox/src/toxcore/TCP_client.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/*
- * Implementation of the TCP relay client part of Tox.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "TCP_client.h"
-
-#include "util.h"
-
-#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
-#include <sys/ioctl.h>
-#endif
-
-/* return 1 on success
- * return 0 on failure
- */
-static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
-{
- if (proxy_info->proxy_type != TCP_PROXY_NONE) {
- ip_port = proxy_info->ip_port;
- }
-
- /* nonblocking socket, connect will never return success */
- net_connect(sock, ip_port);
- return 1;
-}
-
-/* return 1 on success.
- * return 0 on failure.
- */
-static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn)
-{
- char one[] = "CONNECT ";
- char two[] = " HTTP/1.1\nHost: ";
- char three[] = "\r\n\r\n";
-
- char ip[TOX_INET6_ADDRSTRLEN];
-
- if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
- return 0;
- }
-
- const uint16_t port = net_ntohs(TCP_conn->ip_port.port);
- const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two,
- ip, port, three);
-
- if (written < 0 || MAX_PACKET_SIZE < written) {
- return 0;
- }
-
- TCP_conn->last_packet_length = written;
- TCP_conn->last_packet_sent = 0;
-
- return 1;
-}
-
-/* return 1 on success.
- * return 0 if no data received.
- * return -1 on failure (connection refused).
- */
-static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
-{
- char success[] = "200";
- uint8_t data[16]; // draining works the best if the length is a power of 2
-
- int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1);
-
- if (ret == -1) {
- return 0;
- }
-
- data[sizeof(data) - 1] = 0;
-
- if (strstr((char *)data, success)) {
- // drain all data
- unsigned int data_left = TCP_socket_data_recv_buffer(TCP_conn->sock);
-
- if (data_left) {
- VLA(uint8_t, temp_data, data_left);
- read_TCP_packet(TCP_conn->sock, temp_data, data_left);
- }
-
- return 1;
- }
-
- return -1;
-}
-
-static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
-{
- TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
- TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */
- TCP_conn->last_packet[2] = 0; /* No authentication */
-
- TCP_conn->last_packet_length = 3;
- TCP_conn->last_packet_sent = 0;
-}
-
-/* return 1 on success.
- * return 0 if no data received.
- * return -1 on failure (connection refused).
- */
-static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
-{
- uint8_t data[2];
- int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
-
- if (ret == -1) {
- return 0;
- }
-
- if (data[0] == 5 && data[1] == 0) { // TODO(irungentoo): magic numbers
- return 1;
- }
-
- return -1;
-}
-
-static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
-{
- TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
- TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
- TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */
- uint16_t length = 3;
-
- if (TCP_conn->ip_port.ip.family == TOX_AF_INET) {
- TCP_conn->last_packet[3] = 1; /* IPv4 address */
- ++length;
- memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip4.uint8, sizeof(IP4));
- length += sizeof(IP4);
- } else {
- TCP_conn->last_packet[3] = 4; /* IPv6 address */
- ++length;
- memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip6.uint8, sizeof(IP6));
- length += sizeof(IP6);
- }
-
- memcpy(TCP_conn->last_packet + length, &TCP_conn->ip_port.port, sizeof(uint16_t));
- length += sizeof(uint16_t);
-
- TCP_conn->last_packet_length = length;
- TCP_conn->last_packet_sent = 0;
-}
-
-/* return 1 on success.
- * return 0 if no data received.
- * return -1 on failure (connection refused).
- */
-static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
-{
- if (TCP_conn->ip_port.ip.family == TOX_AF_INET) {
- uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
- int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
-
- if (ret == -1) {
- return 0;
- }
-
- if (data[0] == 5 && data[1] == 0) {
- return 1;
- }
- } else {
- uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
- int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data));
-
- if (ret == -1) {
- return 0;
- }
-
- if (data[0] == 5 && data[1] == 0) {
- return 1;
- }
- }
-
- return -1;
-}
-
-/* return 0 on success.
- * return -1 on failure.
- */
-static int generate_handshake(TCP_Client_Connection *TCP_conn)
-{
- uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
- crypto_new_keypair(plain, TCP_conn->temp_secret_key);
- random_nonce(TCP_conn->sent_nonce);
- memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, TCP_conn->sent_nonce, CRYPTO_NONCE_SIZE);
- memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- random_nonce(TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
- sizeof(plain), TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
-
- if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- TCP_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
- TCP_conn->last_packet_sent = 0;
- return 0;
-}
-
-/* data must be of length TCP_SERVER_HANDSHAKE_SIZE
- *
- * return 0 on success.
- * return -1 on failure.
- */
-static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data)
-{
- uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
- int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + CRYPTO_NONCE_SIZE,
- TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
-
- if (len != sizeof(plain)) {
- return -1;
- }
-
- memcpy(TCP_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
- encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
- crypto_memzero(TCP_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
- return 0;
-}
-
-/* return 0 if pending data was sent completely
- * return -1 if it wasn't
- */
-static int client_send_pending_data_nonpriority(TCP_Client_Connection *con)
-{
- if (con->last_packet_length == 0) {
- return 0;
- }
-
- uint16_t left = con->last_packet_length - con->last_packet_sent;
- const char *data = (const char *)(con->last_packet + con->last_packet_sent);
- int len = send(con->sock, data, left, MSG_NOSIGNAL);
-
- if (len <= 0) {
- return -1;
- }
-
- if (len == left) {
- con->last_packet_length = 0;
- con->last_packet_sent = 0;
- return 0;
- }
-
- con->last_packet_sent += len;
- return -1;
-}
-
-/* return 0 if pending data was sent completely
- * return -1 if it wasn't
- */
-static int client_send_pending_data(TCP_Client_Connection *con)
-{
- /* finish sending current non-priority packet */
- if (client_send_pending_data_nonpriority(con) == -1) {
- return -1;
- }
-
- TCP_Priority_List *p = con->priority_queue_start;
-
- while (p) {
- uint16_t left = p->size - p->sent;
- int len = send(con->sock, (const char *)(p->data + p->sent), left, MSG_NOSIGNAL);
-
- if (len != left) {
- if (len > 0) {
- p->sent += len;
- }
-
- break;
- }
-
- TCP_Priority_List *pp = p;
- p = p->next;
- free(pp);
- }
-
- con->priority_queue_start = p;
-
- if (!p) {
- con->priority_queue_end = NULL;
- return 0;
- }
-
- return -1;
-}
-
-/* return 0 on failure (only if malloc fails)
- * return 1 on success
- */
-static bool client_add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
-{
- TCP_Priority_List *p = con->priority_queue_end;
- TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
-
- if (!new_list) {
- return 0;
- }
-
- new_list->next = NULL;
- new_list->size = size;
- new_list->sent = sent;
- memcpy(new_list->data, packet, size);
-
- if (p) {
- p->next = new_list;
- } else {
- con->priority_queue_start = new_list;
- }
-
- con->priority_queue_end = new_list;
- return 1;
-}
-
-static void wipe_priority_list(TCP_Client_Connection *con)
-{
- TCP_Priority_List *p = con->priority_queue_start;
-
- while (p) {
- TCP_Priority_List *pp = p;
- p = p->next;
- free(pp);
- }
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int write_packet_TCP_client_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length,
- bool priority)
-{
- if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
- return -1;
- }
-
- bool sendpriority = 1;
-
- if (client_send_pending_data(con) == -1) {
- if (priority) {
- sendpriority = 0;
- } else {
- return 0;
- }
- }
-
- VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
-
- uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
- memcpy(packet, &c_length, sizeof(uint16_t));
- int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
-
- if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
- return -1;
- }
-
- if (priority) {
- len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0;
-
- if (len <= 0) {
- len = 0;
- }
-
- increment_nonce(con->sent_nonce);
-
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
- return 1;
- }
-
- return client_add_priority(con, packet, SIZEOF_VLA(packet), len);
- }
-
- len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL);
-
- if (len <= 0) {
- return 0;
- }
-
- increment_nonce(con->sent_nonce);
-
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
- return 1;
- }
-
- memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
- con->last_packet_length = SIZEOF_VLA(packet);
- con->last_packet_sent = len;
- return 1;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
-{
- uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];
- packet[0] = TCP_PACKET_ROUTING_REQUEST;
- memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
-}
-
-void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
- const uint8_t *public_key), void *object)
-{
- con->response_callback = response_callback;
- con->response_callback_object = object;
-}
-
-void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
- uint8_t connection_id, uint8_t status), void *object)
-{
- con->status_callback = status_callback;
- con->status_callback_object = object;
-}
-
-static int tcp_send_ping_response(TCP_Client_Connection *con);
-static int tcp_send_ping_request(TCP_Client_Connection *con);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure.
- */
-int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)
-{
- if (con_id >= NUM_CLIENT_CONNECTIONS) {
- return -1;
- }
-
- if (con->connections[con_id].status != 2) {
- return -1;
- }
-
- if (tcp_send_ping_response(con) == 0 || tcp_send_ping_request(con) == 0) {
- return 0;
- }
-
- VLA(uint8_t, packet, 1 + length);
- packet[0] = con_id + NUM_RESERVED_PORTS;
- memcpy(packet + 1, data, length);
- return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure.
- */
-int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length)
-{
- if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
- return -1;
- }
-
- VLA(uint8_t, packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
- packet[0] = TCP_PACKET_OOB_SEND;
- memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
- return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
-}
-
-
-/* Set the number that will be used as an argument in the callbacks related to con_id.
- *
- * When not set by this function, the number is ~0.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
-{
- if (con_id >= NUM_CLIENT_CONNECTIONS) {
- return -1;
- }
-
- if (con->connections[con_id].status == 0) {
- return -1;
- }
-
- con->connections[con_id].number = number;
- return 0;
-}
-
-void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
- uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object)
-{
- con->data_callback = data_callback;
- con->data_callback_object = object;
-}
-
-void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
- const uint8_t *data, uint16_t length, void *userdata), void *object)
-{
- con->oob_data_callback = oob_data_callback;
- con->oob_data_callback_object = object;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int client_send_disconnect_notification(TCP_Client_Connection *con, uint8_t id)
-{
- uint8_t packet[1 + 1];
- packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
- packet[1] = id;
- return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int tcp_send_ping_request(TCP_Client_Connection *con)
-{
- if (!con->ping_request_id) {
- return 1;
- }
-
- uint8_t packet[1 + sizeof(uint64_t)];
- packet[0] = TCP_PACKET_PING;
- memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
- int ret;
-
- if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
- con->ping_request_id = 0;
- }
-
- return ret;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int tcp_send_ping_response(TCP_Client_Connection *con)
-{
- if (!con->ping_response_id) {
- return 1;
- }
-
- uint8_t packet[1 + sizeof(uint64_t)];
- packet[0] = TCP_PACKET_PONG;
- memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
- int ret;
-
- if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) {
- con->ping_response_id = 0;
- }
-
- return ret;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id)
-{
- if (con_id >= NUM_CLIENT_CONNECTIONS) {
- return -1;
- }
-
- con->connections[con_id].status = 0;
- con->connections[con_id].number = 0;
- return client_send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS);
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
-{
- VLA(uint8_t, packet, 1 + length);
- packet[0] = TCP_PACKET_ONION_REQUEST;
- memcpy(packet + 1, data, length);
- return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
-}
-
-void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
- uint16_t length, void *userdata), void *object)
-{
- con->onion_callback = onion_callback;
- con->onion_callback_object = object;
-}
-
-/* Create new TCP connection to ip_port/public_key
- */
-TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
- const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info)
-{
- if (networking_at_startup() != 0) {
- return NULL;
- }
-
- if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
- return NULL;
- }
-
- TCP_Proxy_Info default_proxyinfo;
-
- if (proxy_info == NULL) {
- default_proxyinfo.proxy_type = TCP_PROXY_NONE;
- proxy_info = &default_proxyinfo;
- }
-
- uint8_t family = ip_port.ip.family;
-
- if (proxy_info->proxy_type != TCP_PROXY_NONE) {
- family = proxy_info->ip_port.ip.family;
- }
-
- Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
-
- if (!sock_valid(sock)) {
- return NULL;
- }
-
- if (!set_socket_nosigpipe(sock)) {
- kill_sock(sock);
- return 0;
- }
-
- if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) {
- kill_sock(sock);
- return NULL;
- }
-
- TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1);
-
- if (temp == NULL) {
- kill_sock(sock);
- return NULL;
- }
-
- temp->sock = sock;
- memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
- temp->ip_port = ip_port;
- temp->proxy_info = *proxy_info;
-
- switch (proxy_info->proxy_type) {
- case TCP_PROXY_HTTP:
- temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
- proxy_http_generate_connection_request(temp);
- break;
-
- case TCP_PROXY_SOCKS5:
- temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
- proxy_socks5_generate_handshake(temp);
- break;
-
- case TCP_PROXY_NONE:
- temp->status = TCP_CLIENT_CONNECTING;
-
- if (generate_handshake(temp) == -1) {
- kill_sock(sock);
- free(temp);
- return NULL;
- }
-
- break;
- }
-
- temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
-
- return temp;
-}
-
-/* return 0 on success
- * return -1 on failure
- */
-static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length <= 1) {
- return -1;
- }
-
- switch (data[0]) {
- case TCP_PACKET_ROUTING_RESPONSE: {
- if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) {
- return -1;
- }
-
- if (data[1] < NUM_RESERVED_PORTS) {
- return 0;
- }
-
- uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
-
- if (conn->connections[con_id].status != 0) {
- return 0;
- }
-
- conn->connections[con_id].status = 1;
- conn->connections[con_id].number = ~0;
- memcpy(conn->connections[con_id].public_key, data + 2, CRYPTO_PUBLIC_KEY_SIZE);
-
- if (conn->response_callback) {
- conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
- }
-
- return 0;
- }
-
- case TCP_PACKET_CONNECTION_NOTIFICATION: {
- if (length != 1 + 1) {
- return -1;
- }
-
- if (data[1] < NUM_RESERVED_PORTS) {
- return -1;
- }
-
- uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
-
- if (conn->connections[con_id].status != 1) {
- return 0;
- }
-
- conn->connections[con_id].status = 2;
-
- if (conn->status_callback) {
- conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
- conn->connections[con_id].status);
- }
-
- return 0;
- }
-
- case TCP_PACKET_DISCONNECT_NOTIFICATION: {
- if (length != 1 + 1) {
- return -1;
- }
-
- if (data[1] < NUM_RESERVED_PORTS) {
- return -1;
- }
-
- uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
-
- if (conn->connections[con_id].status == 0) {
- return 0;
- }
-
- if (conn->connections[con_id].status != 2) {
- return 0;
- }
-
- conn->connections[con_id].status = 1;
-
- if (conn->status_callback) {
- conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
- conn->connections[con_id].status);
- }
-
- return 0;
- }
-
- case TCP_PACKET_PING: {
- if (length != 1 + sizeof(uint64_t)) {
- return -1;
- }
-
- uint64_t ping_id;
- memcpy(&ping_id, data + 1, sizeof(uint64_t));
- conn->ping_response_id = ping_id;
- tcp_send_ping_response(conn);
- return 0;
- }
-
- case TCP_PACKET_PONG: {
- if (length != 1 + sizeof(uint64_t)) {
- return -1;
- }
-
- uint64_t ping_id;
- memcpy(&ping_id, data + 1, sizeof(uint64_t));
-
- if (ping_id) {
- if (ping_id == conn->ping_id) {
- conn->ping_id = 0;
- }
-
- return 0;
- }
-
- return -1;
- }
-
- case TCP_PACKET_OOB_RECV: {
- if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
- return -1;
- }
-
- if (conn->oob_data_callback) {
- conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata);
- }
-
- return 0;
- }
-
- case TCP_PACKET_ONION_RESPONSE: {
- conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata);
- return 0;
- }
-
- default: {
- if (data[0] < NUM_RESERVED_PORTS) {
- return -1;
- }
-
- uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
-
- if (conn->data_callback) {
- conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1,
- userdata);
- }
- }
- }
-
- return 0;
-}
-
-static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
-{
- client_send_pending_data(conn);
- tcp_send_ping_response(conn);
- tcp_send_ping_request(conn);
-
- uint8_t packet[MAX_PACKET_SIZE];
- int len;
-
- if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
- uint64_t ping_id = random_64b();
-
- if (!ping_id) {
- ++ping_id;
- }
-
- conn->ping_request_id = conn->ping_id = ping_id;
- tcp_send_ping_request(conn);
- conn->last_pinged = unix_time();
- }
-
- if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
- conn->status = TCP_CLIENT_DISCONNECTED;
- return 0;
- }
-
- while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
- conn->recv_nonce, packet, sizeof(packet)))) {
- if (len == -1) {
- conn->status = TCP_CLIENT_DISCONNECTED;
- break;
- }
-
- if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) {
- conn->status = TCP_CLIENT_DISCONNECTED;
- break;
- }
- }
-
- return 0;
-}
-
-/* Run the TCP connection
- */
-void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata)
-{
- unix_time_update();
-
- if (TCP_connection->status == TCP_CLIENT_DISCONNECTED) {
- return;
- }
-
- if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
- if (client_send_pending_data(TCP_connection) == 0) {
- int ret = proxy_http_read_connection_response(TCP_connection);
-
- if (ret == -1) {
- TCP_connection->kill_at = 0;
- TCP_connection->status = TCP_CLIENT_DISCONNECTED;
- }
-
- if (ret == 1) {
- generate_handshake(TCP_connection);
- TCP_connection->status = TCP_CLIENT_CONNECTING;
- }
- }
- }
-
- if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
- if (client_send_pending_data(TCP_connection) == 0) {
- int ret = socks5_read_handshake_response(TCP_connection);
-
- if (ret == -1) {
- TCP_connection->kill_at = 0;
- TCP_connection->status = TCP_CLIENT_DISCONNECTED;
- }
-
- if (ret == 1) {
- proxy_socks5_generate_connection_request(TCP_connection);
- TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
- }
- }
- }
-
- if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
- if (client_send_pending_data(TCP_connection) == 0) {
- int ret = proxy_socks5_read_connection_response(TCP_connection);
-
- if (ret == -1) {
- TCP_connection->kill_at = 0;
- TCP_connection->status = TCP_CLIENT_DISCONNECTED;
- }
-
- if (ret == 1) {
- generate_handshake(TCP_connection);
- TCP_connection->status = TCP_CLIENT_CONNECTING;
- }
- }
- }
-
- if (TCP_connection->status == TCP_CLIENT_CONNECTING) {
- if (client_send_pending_data(TCP_connection) == 0) {
- TCP_connection->status = TCP_CLIENT_UNCONFIRMED;
- }
- }
-
- if (TCP_connection->status == TCP_CLIENT_UNCONFIRMED) {
- uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
- int len = read_TCP_packet(TCP_connection->sock, data, sizeof(data));
-
- if (sizeof(data) == len) {
- if (handle_handshake(TCP_connection, data) == 0) {
- TCP_connection->kill_at = ~0;
- TCP_connection->status = TCP_CLIENT_CONFIRMED;
- } else {
- TCP_connection->kill_at = 0;
- TCP_connection->status = TCP_CLIENT_DISCONNECTED;
- }
- }
- }
-
- if (TCP_connection->status == TCP_CLIENT_CONFIRMED) {
- do_confirmed_TCP(TCP_connection, userdata);
- }
-
- if (TCP_connection->kill_at <= unix_time()) {
- TCP_connection->status = TCP_CLIENT_DISCONNECTED;
- }
-}
-
-/* Kill the TCP connection
- */
-void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
-{
- if (TCP_connection == NULL) {
- return;
- }
-
- wipe_priority_list(TCP_connection);
- kill_sock(TCP_connection->sock);
- crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection));
- free(TCP_connection);
-}
diff --git a/libs/libtox/src/toxcore/TCP_client.h b/libs/libtox/src/toxcore/TCP_client.h
deleted file mode 100644
index 212543147c..0000000000
--- a/libs/libtox/src/toxcore/TCP_client.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Implementation of the TCP relay client part of Tox.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TCP_CLIENT_H
-#define TCP_CLIENT_H
-
-#include "TCP_server.h"
-#include "crypto_core.h"
-
-#define TCP_CONNECTION_TIMEOUT 10
-
-typedef enum {
- TCP_PROXY_NONE,
- TCP_PROXY_HTTP,
- TCP_PROXY_SOCKS5
-} TCP_PROXY_TYPE;
-
-typedef struct {
- IP_Port ip_port;
- uint8_t proxy_type; // a value from TCP_PROXY_TYPE
-} TCP_Proxy_Info;
-
-enum {
- TCP_CLIENT_NO_STATUS,
- TCP_CLIENT_PROXY_HTTP_CONNECTING,
- TCP_CLIENT_PROXY_SOCKS5_CONNECTING,
- TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED,
- TCP_CLIENT_CONNECTING,
- TCP_CLIENT_UNCONFIRMED,
- TCP_CLIENT_CONFIRMED,
- TCP_CLIENT_DISCONNECTED,
-};
-typedef struct {
- uint8_t status;
- Socket sock;
- uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
- IP_Port ip_port; /* The ip and port of the server */
- TCP_Proxy_Info proxy_info;
- uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
- uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint16_t next_packet_length;
-
- uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- uint8_t last_packet[2 + MAX_PACKET_SIZE];
- uint16_t last_packet_length;
- uint16_t last_packet_sent;
-
- TCP_Priority_List *priority_queue_start, *priority_queue_end;
-
- uint64_t kill_at;
-
- uint64_t last_pinged;
- uint64_t ping_id;
-
- uint64_t ping_response_id;
- uint64_t ping_request_id;
-
- struct {
- uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint32_t number;
- } connections[NUM_CLIENT_CONNECTIONS];
- int (*response_callback)(void *object, uint8_t connection_id, const uint8_t *public_key);
- void *response_callback_object;
- int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status);
- void *status_callback_object;
- int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length,
- void *userdata);
- void *data_callback_object;
- int (*oob_data_callback)(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
- void *oob_data_callback_object;
-
- int (*onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
- void *onion_callback_object;
-
- /* Can be used by user. */
- void *custom_object;
- uint32_t custom_uint;
-} TCP_Client_Connection;
-
-/* Create new TCP connection to ip_port/public_key
- */
-TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key,
- const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info);
-
-/* Run the TCP connection
- */
-void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata);
-
-/* Kill the TCP connection
- */
-void kill_TCP_connection(TCP_Client_Connection *TCP_connection);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t length);
-void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data,
- uint16_t length, void *userdata), void *object);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key);
-void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id,
- const uint8_t *public_key), void *object);
-void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number,
- uint8_t connection_id, uint8_t status), void *object);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id);
-
-/* Set the number that will be used as an argument in the callbacks related to con_id.
- *
- * When not set by this function, the number is ~0.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure.
- */
-int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length);
-void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number,
- uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object);
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure.
- */
-int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data, uint16_t length);
-void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key,
- const uint8_t *data, uint16_t length, void *userdata), void *object);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/TCP_connection.c b/libs/libtox/src/toxcore/TCP_connection.c
deleted file mode 100644
index 251594912a..0000000000
--- a/libs/libtox/src/toxcore/TCP_connection.c
+++ /dev/null
@@ -1,1491 +0,0 @@
-/*
- * Handles TCP relay connections between two Tox clients.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2015 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "TCP_connection.h"
-
-#include "util.h"
-
-#include <assert.h>
-
-
-struct TCP_Connections {
- DHT *dht;
-
- uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- TCP_Connection_to *connections;
- uint32_t connections_length; /* Length of connections array. */
-
- TCP_con *tcp_connections;
- uint32_t tcp_connections_length; /* Length of tcp_connections array. */
-
- int (*tcp_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
- void *tcp_data_callback_object;
-
- int (*tcp_oob_callback)(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
- const uint8_t *data, uint16_t length, void *userdata);
- void *tcp_oob_callback_object;
-
- int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata);
- void *tcp_onion_callback_object;
-
- TCP_Proxy_Info proxy_info;
-
- bool onion_status;
- uint16_t onion_num_conns;
-};
-
-
-const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
-{
- return tcp_c->self_public_key;
-}
-
-
-/* Set the size of the array to num.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-#define realloc_tox_array(array, element_type, num, temp_pointer) \
- (num \
- ? (temp_pointer = (element_type *)realloc( \
- array, \
- (num) * sizeof(element_type)), \
- temp_pointer ? (array = temp_pointer, 0) : -1) \
- : (free(array), array = NULL, 0))
-
-
-/* return 1 if the connections_number is not valid.
- * return 0 if the connections_number is valid.
- */
-static bool connections_number_not_valid(const TCP_Connections *tcp_c, int connections_number)
-{
- if ((unsigned int)connections_number >= tcp_c->connections_length) {
- return 1;
- }
-
- if (tcp_c->connections == NULL) {
- return 1;
- }
-
- if (tcp_c->connections[connections_number].status == TCP_CONN_NONE) {
- return 1;
- }
-
- return 0;
-}
-
-/* return 1 if the tcp_connections_number is not valid.
- * return 0 if the tcp_connections_number is valid.
- */
-static bool tcp_connections_number_not_valid(const TCP_Connections *tcp_c, int tcp_connections_number)
-{
- if ((unsigned int)tcp_connections_number >= tcp_c->tcp_connections_length) {
- return 1;
- }
-
- if (tcp_c->tcp_connections == NULL) {
- return 1;
- }
-
- if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_NONE) {
- return 1;
- }
-
- return 0;
-}
-
-/* Create a new empty connection.
- *
- * return -1 on failure.
- * return connections_number on success.
- */
-static int create_connection(TCP_Connections *tcp_c)
-{
- uint32_t i;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- if (tcp_c->connections[i].status == TCP_CONN_NONE) {
- return i;
- }
- }
-
- int id = -1;
-
- TCP_Connection_to *temp_pointer;
-
- if (realloc_tox_array(tcp_c->connections, TCP_Connection_to, tcp_c->connections_length + 1,
- temp_pointer) == 0) {
- id = tcp_c->connections_length;
- ++tcp_c->connections_length;
- memset(&(tcp_c->connections[id]), 0, sizeof(TCP_Connection_to));
- }
-
- return id;
-}
-
-/* Create a new empty tcp connection.
- *
- * return -1 on failure.
- * return tcp_connections_number on success.
- */
-static int create_tcp_connection(TCP_Connections *tcp_c)
-{
- uint32_t i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) {
- return i;
- }
- }
-
- int id = -1;
-
- TCP_con *temp_pointer;
-
- if (realloc_tox_array(tcp_c->tcp_connections, TCP_con, tcp_c->tcp_connections_length + 1, temp_pointer) == 0) {
- id = tcp_c->tcp_connections_length;
- ++tcp_c->tcp_connections_length;
- memset(&(tcp_c->tcp_connections[id]), 0, sizeof(TCP_con));
- }
-
- return id;
-}
-
-/* Wipe a connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
-{
- if (connections_number_not_valid(tcp_c, connections_number)) {
- return -1;
- }
-
- uint32_t i;
- memset(&(tcp_c->connections[connections_number]), 0 , sizeof(TCP_Connection_to));
-
- for (i = tcp_c->connections_length; i != 0; --i) {
- if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) {
- break;
- }
- }
-
- if (tcp_c->connections_length != i) {
- tcp_c->connections_length = i;
- TCP_Connection_to *temp_pointer;
- realloc_tox_array(tcp_c->connections, TCP_Connection_to, tcp_c->connections_length, temp_pointer);
- }
-
- return 0;
-}
-
-/* Wipe a connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
- return -1;
- }
-
- uint32_t i;
- memset(&(tcp_c->tcp_connections[tcp_connections_number]), 0 , sizeof(TCP_con));
-
- for (i = tcp_c->tcp_connections_length; i != 0; --i) {
- if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) {
- break;
- }
- }
-
- if (tcp_c->tcp_connections_length != i) {
- tcp_c->tcp_connections_length = i;
- TCP_con *temp_pointer;
- realloc_tox_array(tcp_c->tcp_connections, TCP_con, tcp_c->tcp_connections_length, temp_pointer);
- }
-
- return 0;
-}
-
-static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number)
-{
- if (connections_number_not_valid(tcp_c, connections_number)) {
- return 0;
- }
-
- return &tcp_c->connections[connections_number];
-}
-
-static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number)
-{
- if (tcp_connections_number_not_valid(tcp_c, tcp_connections_number)) {
- return 0;
- }
-
- return &tcp_c->tcp_connections[tcp_connections_number];
-}
-
-/* Send a packet to the TCP connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return -1;
- }
-
- // TODO(irungentoo): detect and kill bad relays.
- // TODO(irungentoo): thread safety?
- unsigned int i;
- int ret = -1;
-
- bool limit_reached = 0;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
- uint8_t status = con_to->connections[i].status;
- uint8_t connection_id = con_to->connections[i].connection_id;
-
- if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_ONLINE) {
- tcp_con_num -= 1;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
-
- if (!tcp_con) {
- continue;
- }
-
- ret = send_data(tcp_con->connection, connection_id, packet, length);
-
- if (ret == 0) {
- limit_reached = 1;
- }
-
- if (ret == 1) {
- break;
- }
- }
- }
-
- if (ret == 1) {
- return 0;
- }
-
- if (!limit_reached) {
- ret = 0;
-
- /* Send oob packets to all relays tied to the connection. */
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
- uint8_t status = con_to->connections[i].status;
-
- if (tcp_con_num && status == TCP_CONNECTIONS_STATUS_REGISTERED) {
- tcp_con_num -= 1;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
-
- if (!tcp_con) {
- continue;
- }
-
- if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) {
- ret += 1;
- }
- }
- }
-
- if (ret >= 1) {
- return 0;
- }
-
- return -1;
- }
-
- return -1;
-}
-
-/* Return a random TCP connection number for use in send_tcp_onion_request.
- *
- * TODO(irungentoo): This number is just the index of an array that the elements
- * can change without warning.
- *
- * return TCP connection number on success.
- * return -1 on failure.
- */
-int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c)
-{
- unsigned int i, r = rand();
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- unsigned int index = ((i + r) % tcp_c->tcp_connections_length);
-
- if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {
- return index;
- }
- }
-
- return -1;
-}
-
-/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
- uint16_t length)
-{
- if (tcp_connections_number >= tcp_c->tcp_connections_length) {
- return -1;
- }
-
- if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) {
- int ret = send_onion_request(tcp_c->tcp_connections[tcp_connections_number].connection, data, length);
-
- if (ret == 1) {
- return 0;
- }
- }
-
- return -1;
-}
-
-/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,
- const uint8_t *packet, uint16_t length)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (tcp_con->status != TCP_CONN_CONNECTED) {
- return -1;
- }
-
- int ret = send_oob_packet(tcp_con->connection, public_key, packet, length);
-
- if (ret == 1) {
- return 0;
- }
-
- return -1;
-}
-
-/* Set the callback for TCP data packets.
- */
-void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
- const uint8_t *data, uint16_t length, void *userdata), void *object)
-{
- tcp_c->tcp_data_callback = tcp_data_callback;
- tcp_c->tcp_data_callback_object = object;
-}
-
-/* Set the callback for TCP onion packets.
- */
-void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
- const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
- void *object)
-{
- tcp_c->tcp_oob_callback = tcp_oob_callback;
- tcp_c->tcp_oob_callback_object = object;
-}
-
-/* Set the callback for TCP oob data packets.
- */
-void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
- const uint8_t *data, uint16_t length, void *userdata), void *object)
-{
- tcp_c->tcp_onion_callback = tcp_onion_callback;
- tcp_c->tcp_onion_callback_object = object;
-}
-
-
-/* Find the TCP connection with public_key.
- *
- * return connections_number on success.
- * return -1 on failure.
- */
-static int find_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key)
-{
- unsigned int i;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
-
- if (con_to) {
- if (public_key_cmp(con_to->public_key, public_key) == 0) {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/* Find the TCP connection to a relay with relay_pk.
- *
- * return connections_number on success.
- * return -1 on failure.
- */
-static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *relay_pk)
-{
- unsigned int i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->status == TCP_CONN_SLEEPING) {
- if (public_key_cmp(tcp_con->relay_pk, relay_pk) == 0) {
- return i;
- }
- } else {
- if (public_key_cmp(tcp_con->connection->public_key, relay_pk) == 0) {
- return i;
- }
- }
- }
- }
-
- return -1;
-}
-
-/* Create a new TCP connection to public_key.
- *
- * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().
- *
- * id is the id in the callbacks for that connection.
- *
- * return connections_number on success.
- * return -1 on failure.
- */
-int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id)
-{
- if (find_tcp_connection_to(tcp_c, public_key) != -1) {
- return -1;
- }
-
- int connections_number = create_connection(tcp_c);
-
- if (connections_number == -1) {
- return -1;
- }
-
- TCP_Connection_to *con_to = &tcp_c->connections[connections_number];
-
- con_to->status = TCP_CONN_VALID;
- memcpy(con_to->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- con_to->id = id;
-
- return connections_number;
-}
-
-/* return 0 on success.
- * return -1 on failure.
- */
-int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection) {
- unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- continue;
- }
-
- if (tcp_con->status == TCP_CONN_CONNECTED) {
- send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id);
- }
-
- if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
- --tcp_con->lock_count;
-
- if (con_to->status == TCP_CONN_SLEEPING) {
- --tcp_con->sleep_count;
- }
- }
- }
- }
-
- return wipe_connection(tcp_c, connections_number);
-}
-
-/* Set connection status.
- *
- * status of 1 means we are using the connection.
- * status of 0 means we are not using it.
- *
- * Unused tcp connections will be disconnected from but kept in case they are needed.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return -1;
- }
-
- if (status) {
- /* Connection is unsleeping. */
- if (con_to->status != TCP_CONN_SLEEPING) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection) {
- unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- continue;
- }
-
- if (tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
- }
- }
- }
-
- con_to->status = TCP_CONN_VALID;
- return 0;
- }
-
- /* Connection is going to sleep. */
- if (con_to->status != TCP_CONN_VALID) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection) {
- unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- continue;
- }
-
- if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
- ++tcp_con->sleep_count;
- }
- }
- }
-
- con_to->status = TCP_CONN_SLEEPING;
- return 0;
-}
-
-static bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/* return index on success.
- * return -1 on failure.
- */
-static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
-{
- unsigned int i;
-
- if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
- return -1;
- }
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection == 0) {
- con_to->connections[i].tcp_connection = tcp_connections_number + 1;
- con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
- con_to->connections[i].connection_id = 0;
- return i;
- }
- }
-
- return -1;
-}
-
-/* return index on success.
- * return -1 on failure.
- */
-static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
- con_to->connections[i].tcp_connection = 0;
- con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
- con_to->connections[i].connection_id = 0;
- return i;
- }
- }
-
- return -1;
-}
-
-/* return number of online connections on success.
- * return -1 on failure.
- */
-static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to)
-{
- unsigned int i, count = 0;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection) {
- if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
- ++count;
- }
- }
- }
-
- return count;
-}
-
-/* return index on success.
- * return -1 on failure.
- */
-static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number,
- unsigned int status, uint8_t connection_id)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
- if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
-
- if (con_to->connections[i].status == status) {
- return -1;
- }
-
- con_to->connections[i].status = status;
- con_to->connections[i].connection_id = connection_id;
- return i;
- }
- }
-
- return -1;
-}
-
-/* Kill a TCP relay connection.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
-
- if (con_to) {
- rm_tcp_connection_from_conn(con_to, tcp_connections_number);
- }
- }
-
- if (tcp_con->onion) {
- --tcp_c->onion_num_conns;
- }
-
- kill_TCP_connection(tcp_con->connection);
-
- return wipe_tcp_connection(tcp_c, tcp_connections_number);
-}
-
-static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (tcp_con->status == TCP_CONN_SLEEPING) {
- return -1;
- }
-
- IP_Port ip_port = tcp_con->connection->ip_port;
- uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
- memcpy(relay_pk, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
- kill_TCP_connection(tcp_con->connection);
- tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
- &tcp_c->proxy_info);
-
- if (!tcp_con->connection) {
- kill_tcp_relay_connection(tcp_c, tcp_connections_number);
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
-
- if (con_to) {
- set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
- }
- }
-
- if (tcp_con->onion) {
- --tcp_c->onion_num_conns;
- tcp_con->onion = 0;
- }
-
- tcp_con->lock_count = 0;
- tcp_con->sleep_count = 0;
- tcp_con->connected_time = 0;
- tcp_con->status = TCP_CONN_VALID;
- tcp_con->unsleep = 0;
-
- return 0;
-}
-
-static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (tcp_con->status != TCP_CONN_CONNECTED) {
- return -1;
- }
-
- if (tcp_con->lock_count != tcp_con->sleep_count) {
- return -1;
- }
-
- tcp_con->ip_port = tcp_con->connection->ip_port;
- memcpy(tcp_con->relay_pk, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- kill_TCP_connection(tcp_con->connection);
- tcp_con->connection = NULL;
-
- unsigned int i;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
-
- if (con_to) {
- set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
- }
- }
-
- if (tcp_con->onion) {
- --tcp_c->onion_num_conns;
- tcp_con->onion = 0;
- }
-
- tcp_con->lock_count = 0;
- tcp_con->sleep_count = 0;
- tcp_con->connected_time = 0;
- tcp_con->status = TCP_CONN_SLEEPING;
- tcp_con->unsleep = 0;
-
- return 0;
-}
-
-static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (tcp_con->status != TCP_CONN_SLEEPING) {
- return -1;
- }
-
- tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->self_public_key,
- tcp_c->self_secret_key, &tcp_c->proxy_info);
-
- if (!tcp_con->connection) {
- kill_tcp_relay_connection(tcp_c, tcp_connections_number);
- return -1;
- }
-
- tcp_con->lock_count = 0;
- tcp_con->sleep_count = 0;
- tcp_con->connected_time = 0;
- tcp_con->status = TCP_CONN_VALID;
- tcp_con->unsleep = 0;
- return 0;
-}
-
-/* Send a TCP routing request.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connections_number, uint8_t *public_key)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (tcp_con->status == TCP_CONN_SLEEPING) {
- return -1;
- }
-
- if (send_routing_request(tcp_con->connection, public_key) != 1) {
- return -1;
- }
-
- return 0;
-}
-
-static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)
-{
- TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
- TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
-
- unsigned int tcp_connections_number = TCP_client_con->custom_uint;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- int connections_number = find_tcp_connection_to(tcp_c, public_key);
-
- if (connections_number == -1) {
- return -1;
- }
-
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (con_to == NULL) {
- return -1;
- }
-
- if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
- return -1;
- }
-
- set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
-
- return 0;
-}
-
-static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status)
-{
- TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
- TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
-
- unsigned int tcp_connections_number = TCP_client_con->custom_uint;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
- TCP_Connection_to *con_to = get_connection(tcp_c, number);
-
- if (!con_to || !tcp_con) {
- return -1;
- }
-
- if (status == 1) {
- if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
- return -1;
- }
-
- --tcp_con->lock_count;
-
- if (con_to->status == TCP_CONN_SLEEPING) {
- --tcp_con->sleep_count;
- }
- } else if (status == 2) {
- if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) {
- return -1;
- }
-
- ++tcp_con->lock_count;
-
- if (con_to->status == TCP_CONN_SLEEPING) {
- ++tcp_con->sleep_count;
- }
- }
-
- return 0;
-}
-
-static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,
- uint16_t length, void *userdata)
-{
- if (length == 0) {
- return -1;
- }
-
- TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
- TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
-
- unsigned int tcp_connections_number = TCP_client_con->custom_uint;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- TCP_Connection_to *con_to = get_connection(tcp_c, number);
-
- if (!con_to) {
- return -1;
- }
-
- if (tcp_c->tcp_data_callback) {
- tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length, userdata);
- }
-
- return 0;
-}
-
-static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,
- void *userdata)
-{
- if (length == 0) {
- return -1;
- }
-
- TCP_Client_Connection *TCP_client_con = (TCP_Client_Connection *)object;
- TCP_Connections *tcp_c = (TCP_Connections *)TCP_client_con->custom_object;
-
- unsigned int tcp_connections_number = TCP_client_con->custom_uint;
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- /* TODO(irungentoo): optimize */
- int connections_number = find_tcp_connection_to(tcp_c, public_key);
-
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {
- return tcp_conn_data_callback(object, connections_number, 0, data, length, userdata);
- }
-
- if (tcp_c->tcp_oob_callback) {
- tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length, userdata);
- }
-
- return 0;
-}
-
-static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length, void *userdata)
-{
- TCP_Connections *tcp_c = (TCP_Connections *)object;
-
- if (tcp_c->tcp_onion_callback) {
- tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length, userdata);
- }
-
- return 0;
-}
-
-/* Set callbacks for the TCP relay connection.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-static int tcp_relay_set_callbacks(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- TCP_Client_Connection *con = tcp_con->connection;
-
- con->custom_object = tcp_c;
- con->custom_uint = tcp_connections_number;
- onion_response_handler(con, &tcp_onion_callback, tcp_c);
- routing_response_handler(con, &tcp_response_callback, con);
- routing_status_handler(con, &tcp_status_callback, con);
- routing_data_handler(con, &tcp_conn_data_callback, con);
- oob_data_handler(con, &tcp_conn_oob_callback, con);
-
- return 0;
-}
-
-static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_number)
-{
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- unsigned int i, sent = 0;
-
- for (i = 0; i < tcp_c->connections_length; ++i) {
- TCP_Connection_to *con_to = get_connection(tcp_c, i);
-
- if (con_to) {
- if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
- if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
- ++sent;
- }
- }
- }
- }
-
- tcp_relay_set_callbacks(tcp_c, tcp_connections_number);
- tcp_con->status = TCP_CONN_CONNECTED;
-
- /* If this connection isn't used by any connection, we don't need to wait for them to come online. */
- if (sent) {
- tcp_con->connected_time = unix_time();
- } else {
- tcp_con->connected_time = 0;
- }
-
- if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
- tcp_con->onion = 1;
- ++tcp_c->onion_num_conns;
- }
-
- return 0;
-}
-
-static int add_tcp_relay_instance(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk)
-{
- if (ip_port.ip.family == TCP_INET) {
- ip_port.ip.family = TOX_AF_INET;
- } else if (ip_port.ip.family == TCP_INET6) {
- ip_port.ip.family = TOX_AF_INET6;
- }
-
- if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
- return -1;
- }
-
- int tcp_connections_number = create_tcp_connection(tcp_c);
-
- if (tcp_connections_number == -1) {
- return -1;
- }
-
- TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
-
- tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key,
- &tcp_c->proxy_info);
-
- if (!tcp_con->connection) {
- return -1;
- }
-
- tcp_con->status = TCP_CONN_VALID;
-
- return tcp_connections_number;
-}
-
-/* Add a TCP relay to the TCP_Connections instance.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk)
-{
- int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
-
- if (tcp_connections_number != -1) {
- return -1;
- }
-
- if (add_tcp_relay_instance(tcp_c, ip_port, relay_pk) == -1) {
- return -1;
- }
-
- return 0;
-}
-
-/* Add a TCP relay tied to a connection.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number, unsigned int tcp_connections_number)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return -1;
- }
-
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
- }
-
- if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
- return -1;
- }
-
- if (tcp_con->status == TCP_CONN_CONNECTED) {
- if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
- tcp_con->connected_time = unix_time();
- }
- }
-
- return 0;
-}
-
-/* Add a TCP relay tied to a connection.
- *
- * This should be called with the same relay by two peers who want to create a TCP connection with each other.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return -1;
- }
-
- int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
-
- if (tcp_connections_number != -1) {
- return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
- }
-
- if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
- return -1;
- }
-
- tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk);
-
- TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
-
- if (!tcp_con) {
- return -1;
- }
-
- if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
- return -1;
- }
-
- return 0;
-}
-
-/* return number of online tcp relays tied to the connection on success.
- * return 0 on failure.
- */
-unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number)
-{
- TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
-
- if (!con_to) {
- return 0;
- }
-
- return online_tcp_connection_from_conn(con_to);
-}
-
-/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
- * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
- *
- * return number of relays copied to tcp_relays on success.
- * return 0 on failure.
- */
-unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)
-{
- unsigned int i, copied = 0, r = rand();
-
- for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length);
-
- if (!tcp_con) {
- continue;
- }
-
- if (tcp_con->status == TCP_CONN_CONNECTED) {
- memcpy(tcp_relays[copied].public_key, tcp_con->connection->public_key, CRYPTO_PUBLIC_KEY_SIZE);
- tcp_relays[copied].ip_port = tcp_con->connection->ip_port;
-
- if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET) {
- tcp_relays[copied].ip_port.ip.family = TCP_INET;
- } else if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET6) {
- tcp_relays[copied].ip_port.ip.family = TCP_INET6;
- }
-
- ++copied;
- }
- }
-
- return copied;
-}
-
-/* Set if we want TCP_connection to allocate some connection for onion use.
- *
- * If status is 1, allocate some connections. if status is 0, don't.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
-{
- if (tcp_c->onion_status == status) {
- return -1;
- }
-
- if (status) {
- unsigned int i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
- ++tcp_c->onion_num_conns;
- tcp_con->onion = 1;
- }
- }
-
- if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS) {
- break;
- }
- }
-
- if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
- unsigned int wakeup = NUM_ONION_TCP_CONNECTIONS - tcp_c->onion_num_conns;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->status == TCP_CONN_SLEEPING) {
- tcp_con->unsleep = 1;
- }
- }
-
- if (!wakeup) {
- break;
- }
- }
- }
-
- tcp_c->onion_status = 1;
- } else {
- unsigned int i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->onion) {
- --tcp_c->onion_num_conns;
- tcp_con->onion = 0;
- }
- }
- }
-
- tcp_c->onion_status = 0;
- }
-
- return 0;
-}
-
-/* Returns a new TCP_Connections object associated with the secret_key.
- *
- * In order for others to connect to this instance new_tcp_connection_to() must be called with the
- * public_key associated with secret_key.
- *
- * Returns NULL on failure.
- */
-TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info)
-{
- if (secret_key == NULL) {
- return NULL;
- }
-
- TCP_Connections *temp = (TCP_Connections *)calloc(1, sizeof(TCP_Connections));
-
- if (temp == NULL) {
- return NULL;
- }
-
- memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
- crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);
- temp->proxy_info = *proxy_info;
-
- return temp;
-}
-
-static void do_tcp_conns(TCP_Connections *tcp_c, void *userdata)
-{
- unsigned int i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->status != TCP_CONN_SLEEPING) {
- do_TCP_connection(tcp_con->connection, userdata);
-
- /* callbacks can change TCP connection address. */
- tcp_con = get_tcp_connection(tcp_c, i);
-
- // Make sure the TCP connection wasn't dropped in any of the callbacks.
- assert(tcp_con != NULL);
-
- if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) {
- if (tcp_con->status == TCP_CONN_CONNECTED) {
- reconnect_tcp_relay_connection(tcp_c, i);
- } else {
- kill_tcp_relay_connection(tcp_c, i);
- }
-
- continue;
- }
-
- if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) {
- tcp_relay_on_online(tcp_c, i);
- }
-
- if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count
- && tcp_con->lock_count == tcp_con->sleep_count
- && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
- sleep_tcp_relay_connection(tcp_c, i);
- }
- }
-
- if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) {
- unsleep_tcp_relay_connection(tcp_c, i);
- }
- }
- }
-}
-
-static void kill_nonused_tcp(TCP_Connections *tcp_c)
-{
- if (tcp_c->tcp_connections_length == 0) {
- return;
- }
-
- unsigned int i;
- unsigned int num_online = 0;
- unsigned int num_kill = 0;
- VLA(unsigned int, to_kill, tcp_c->tcp_connections_length);
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
-
- if (tcp_con) {
- if (tcp_con->status == TCP_CONN_CONNECTED) {
- if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
- to_kill[num_kill] = i;
- ++num_kill;
- }
-
- ++num_online;
- }
- }
- }
-
- if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
- return;
- }
-
- unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
-
- if (n < num_kill) {
- num_kill = n;
- }
-
- for (i = 0; i < num_kill; ++i) {
- kill_tcp_relay_connection(tcp_c, to_kill[i]);
- }
-}
-
-void do_tcp_connections(TCP_Connections *tcp_c, void *userdata)
-{
- do_tcp_conns(tcp_c, userdata);
- kill_nonused_tcp(tcp_c);
-}
-
-void kill_tcp_connections(TCP_Connections *tcp_c)
-{
- unsigned int i;
-
- for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
- kill_TCP_connection(tcp_c->tcp_connections[i].connection);
- }
-
- free(tcp_c->tcp_connections);
- free(tcp_c->connections);
- free(tcp_c);
-}
diff --git a/libs/libtox/src/toxcore/TCP_connection.h b/libs/libtox/src/toxcore/TCP_connection.h
deleted file mode 100644
index a45129a7e8..0000000000
--- a/libs/libtox/src/toxcore/TCP_connection.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Handles TCP relay connections between two Tox clients.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2015 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TCP_CONNECTION_H
-#define TCP_CONNECTION_H
-
-#include "TCP_client.h"
-
-#define TCP_CONN_NONE 0
-#define TCP_CONN_VALID 1
-
-/* NOTE: only used by TCP_con */
-#define TCP_CONN_CONNECTED 2
-
-/* Connection is not connected but can be quickly reconnected in case it is needed. */
-#define TCP_CONN_SLEEPING 3
-
-#define TCP_CONNECTIONS_STATUS_NONE 0
-#define TCP_CONNECTIONS_STATUS_REGISTERED 1
-#define TCP_CONNECTIONS_STATUS_ONLINE 2
-
-#define MAX_FRIEND_TCP_CONNECTIONS 6
-
-/* Time until connection to friend gets killed (if it doesn't get locked within that time) */
-#define TCP_CONNECTION_ANNOUNCE_TIMEOUT (TCP_CONNECTION_TIMEOUT)
-
-/* The amount of recommended connections for each friend
- NOTE: Must be at most (MAX_FRIEND_TCP_CONNECTIONS / 2) */
-#define RECOMMENDED_FRIEND_TCP_CONNECTIONS (MAX_FRIEND_TCP_CONNECTIONS / 2)
-
-/* Number of TCP connections used for onion purposes. */
-#define NUM_ONION_TCP_CONNECTIONS RECOMMENDED_FRIEND_TCP_CONNECTIONS
-
-typedef struct {
- uint8_t status;
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
-
- struct {
- uint32_t tcp_connection;
- unsigned int status;
- unsigned int connection_id;
- } connections[MAX_FRIEND_TCP_CONNECTIONS];
-
- int id; /* id used in callbacks. */
-} TCP_Connection_to;
-
-typedef struct {
- uint8_t status;
- TCP_Client_Connection *connection;
- uint64_t connected_time;
- uint32_t lock_count;
- uint32_t sleep_count;
- bool onion;
-
- /* Only used when connection is sleeping. */
- IP_Port ip_port;
- uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
- bool unsleep; /* set to 1 to unsleep connection. */
-} TCP_con;
-
-typedef struct TCP_Connections TCP_Connections;
-
-const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c);
-
-/* Send a packet to the TCP connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, const uint8_t *packet, uint16_t length);
-
-/* Return a random TCP connection number for use in send_tcp_onion_request.
- *
- * TODO(irungentoo): This number is just the index of an array that the elements
- * can change without warning.
- *
- * return TCP connection number on success.
- * return -1 on failure.
- */
-int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c);
-
-/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int tcp_send_onion_request(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *data,
- uint16_t length);
-
-/* Set if we want TCP_connection to allocate some connection for onion use.
- *
- * If status is 1, allocate some connections. if status is 0, don't.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_onion_status(TCP_Connections *tcp_c, bool status);
-
-/* Send an oob packet via the TCP relay corresponding to tcp_connections_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_number, const uint8_t *public_key,
- const uint8_t *packet, uint16_t length);
-
-/* Set the callback for TCP data packets.
- */
-void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_data_callback)(void *object, int id,
- const uint8_t *data, uint16_t length, void *userdata), void *object);
-
-/* Set the callback for TCP onion packets.
- */
-void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_onion_callback)(void *object,
- const uint8_t *data, uint16_t length, void *userdata), void *object);
-
-/* Set the callback for TCP oob data packets.
- */
-void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, int (*tcp_oob_callback)(void *object,
- const uint8_t *public_key, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length, void *userdata),
- void *object);
-
-/* Create a new TCP connection to public_key.
- *
- * public_key must be the counterpart to the secret key that the other peer used with new_tcp_connections().
- *
- * id is the id in the callbacks for that connection.
- *
- * return connections_number on success.
- * return -1 on failure.
- */
-int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id);
-
-/* return 0 on success.
- * return -1 on failure.
- */
-int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number);
-
-/* Set connection status.
- *
- * status of 1 means we are using the connection.
- * status of 0 means we are not using it.
- *
- * Unused tcp connections will be disconnected from but kept in case they are needed.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, bool status);
-
-/* return number of online tcp relays tied to the connection on success.
- * return 0 on failure.
- */
-unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number);
-
-/* Add a TCP relay tied to a connection.
- *
- * NOTE: This can only be used during the tcp_oob_callback.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_number,
- unsigned int tcp_connections_number);
-
-/* Add a TCP relay tied to a connection.
- *
- * This should be called with the same relay by two peers who want to create a TCP connection with each other.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_Port ip_port, const uint8_t *relay_pk);
-
-/* Add a TCP relay to the instance.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int add_tcp_relay_global(TCP_Connections *tcp_c, IP_Port ip_port, const uint8_t *relay_pk);
-
-/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
- * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
- *
- * return number of relays copied to tcp_relays on success.
- * return 0 on failure.
- */
-unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num);
-
-/* Returns a new TCP_Connections object associated with the secret_key.
- *
- * In order for others to connect to this instance new_tcp_connection_to() must be called with the
- * public_key associated with secret_key.
- *
- * Returns NULL on failure.
- */
-TCP_Connections *new_tcp_connections(const uint8_t *secret_key, TCP_Proxy_Info *proxy_info);
-
-void do_tcp_connections(TCP_Connections *tcp_c, void *userdata);
-void kill_tcp_connections(TCP_Connections *tcp_c);
-
-#endif
-
diff --git a/libs/libtox/src/toxcore/TCP_server.c b/libs/libtox/src/toxcore/TCP_server.c
deleted file mode 100644
index 9b94667aa1..0000000000
--- a/libs/libtox/src/toxcore/TCP_server.c
+++ /dev/null
@@ -1,1417 +0,0 @@
-/*
- * Implementation of the TCP relay server part of Tox.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "TCP_server.h"
-
-#include "util.h"
-
-#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
-#include <sys/ioctl.h>
-#endif
-
-struct TCP_Server {
- Onion *onion;
-
-#ifdef TCP_SERVER_USE_EPOLL
- int efd;
- uint64_t last_run_pinged;
-#endif
- Socket *socks_listening;
- unsigned int num_listening_socks;
-
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE];
- TCP_Secure_Connection incoming_connection_queue[MAX_INCOMING_CONNECTIONS];
- uint16_t incoming_connection_queue_index;
- TCP_Secure_Connection unconfirmed_connection_queue[MAX_INCOMING_CONNECTIONS];
- uint16_t unconfirmed_connection_queue_index;
-
- TCP_Secure_Connection *accepted_connection_array;
- uint32_t size_accepted_connections;
- uint32_t num_accepted_connections;
-
- uint64_t counter;
-
- BS_LIST accepted_key_list;
-};
-
-const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server)
-{
- return tcp_server->public_key;
-}
-
-size_t tcp_server_listen_count(const TCP_Server *tcp_server)
-{
- return tcp_server->num_listening_socks;
-}
-
-/* This is needed to compile on Android below API 21
- */
-#ifndef EPOLLRDHUP
-#define EPOLLRDHUP 0x2000
-#endif
-
-/* Set the size of the connection list to numfriends.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-static int realloc_connection(TCP_Server *TCP_server, uint32_t num)
-{
- if (num == 0) {
- free(TCP_server->accepted_connection_array);
- TCP_server->accepted_connection_array = NULL;
- TCP_server->size_accepted_connections = 0;
- return 0;
- }
-
- if (num == TCP_server->size_accepted_connections) {
- return 0;
- }
-
- TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc(
- TCP_server->accepted_connection_array,
- num * sizeof(TCP_Secure_Connection));
-
- if (new_connections == NULL) {
- return -1;
- }
-
- if (num > TCP_server->size_accepted_connections) {
- uint32_t old_size = TCP_server->size_accepted_connections;
- uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection);
- memset(new_connections + old_size, 0, size_new_entries);
- }
-
- TCP_server->accepted_connection_array = new_connections;
- TCP_server->size_accepted_connections = num;
- return 0;
-}
-
-/* return index corresponding to connection with peer on success
- * return -1 on failure.
- */
-static int get_TCP_connection_index(const TCP_Server *TCP_server, const uint8_t *public_key)
-{
- return bs_list_find(&TCP_server->accepted_key_list, public_key);
-}
-
-
-static int kill_accepted(TCP_Server *TCP_server, int index);
-
-/* Add accepted TCP connection to the list.
- *
- * return index on success
- * return -1 on failure
- */
-static int add_accepted(TCP_Server *TCP_server, const TCP_Secure_Connection *con)
-{
- int index = get_TCP_connection_index(TCP_server, con->public_key);
-
- if (index != -1) { /* If an old connection to the same public key exists, kill it. */
- kill_accepted(TCP_server, index);
- index = -1;
- }
-
- if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) {
- if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) {
- return -1;
- }
-
- index = TCP_server->num_accepted_connections;
- } else {
- uint32_t i;
-
- for (i = TCP_server->size_accepted_connections; i != 0; --i) {
- if (TCP_server->accepted_connection_array[i - 1].status == TCP_STATUS_NO_STATUS) {
- index = i - 1;
- break;
- }
- }
- }
-
- if (index == -1) {
- fprintf(stderr, "FAIL index is -1\n");
- return -1;
- }
-
- if (!bs_list_add(&TCP_server->accepted_key_list, con->public_key, index)) {
- return -1;
- }
-
- memcpy(&TCP_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection));
- TCP_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED;
- ++TCP_server->num_accepted_connections;
- TCP_server->accepted_connection_array[index].identifier = ++TCP_server->counter;
- TCP_server->accepted_connection_array[index].last_pinged = unix_time();
- TCP_server->accepted_connection_array[index].ping_id = 0;
-
- return index;
-}
-
-/* Delete accepted connection from list.
- *
- * return 0 on success
- * return -1 on failure
- */
-static int del_accepted(TCP_Server *TCP_server, int index)
-{
- if ((uint32_t)index >= TCP_server->size_accepted_connections) {
- return -1;
- }
-
- if (TCP_server->accepted_connection_array[index].status == TCP_STATUS_NO_STATUS) {
- return -1;
- }
-
- if (!bs_list_remove(&TCP_server->accepted_key_list, TCP_server->accepted_connection_array[index].public_key, index)) {
- return -1;
- }
-
- crypto_memzero(&TCP_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection));
- --TCP_server->num_accepted_connections;
-
- if (TCP_server->num_accepted_connections == 0) {
- realloc_connection(TCP_server, 0);
- }
-
- return 0;
-}
-
-/* return the amount of data in the tcp recv buffer.
- * return 0 on failure.
- */
-unsigned int TCP_socket_data_recv_buffer(Socket sock)
-{
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- unsigned long count = 0;
- ioctlsocket(sock, FIONREAD, &count);
-#else
- int count = 0;
- ioctl(sock, FIONREAD, &count);
-#endif
-
- return count;
-}
-
-/* Read the next two bytes in TCP stream then convert them to
- * length (host byte order).
- *
- * return length on success
- * return 0 if nothing has been read from socket.
- * return ~0 on failure.
- */
-uint16_t read_TCP_length(Socket sock)
-{
- unsigned int count = TCP_socket_data_recv_buffer(sock);
-
- if (count >= sizeof(uint16_t)) {
- uint16_t length;
- int len = recv(sock, (char *)&length, sizeof(uint16_t), MSG_NOSIGNAL);
-
- if (len != sizeof(uint16_t)) {
- fprintf(stderr, "FAIL recv packet\n");
- return 0;
- }
-
- length = net_ntohs(length);
-
- if (length > MAX_PACKET_SIZE) {
- return ~0;
- }
-
- return length;
- }
-
- return 0;
-}
-
-/* Read length bytes from socket.
- *
- * return length on success
- * return -1 on failure/no data in buffer.
- */
-int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length)
-{
- unsigned int count = TCP_socket_data_recv_buffer(sock);
-
- if (count >= length) {
- int len = recv(sock, (char *)data, length, MSG_NOSIGNAL);
-
- if (len != length) {
- fprintf(stderr, "FAIL recv packet\n");
- return -1;
- }
-
- return len;
- }
-
- return -1;
-}
-
-/* return length of received packet on success.
- * return 0 if could not read any packet.
- * return -1 on failure (connection must be killed).
- */
-int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
- uint8_t *recv_nonce, uint8_t *data, uint16_t max_len)
-{
- if (*next_packet_length == 0) {
- uint16_t len = read_TCP_length(sock);
-
- if (len == (uint16_t)~0) {
- return -1;
- }
-
- if (len == 0) {
- return 0;
- }
-
- *next_packet_length = len;
- }
-
- if (max_len + CRYPTO_MAC_SIZE < *next_packet_length) {
- return -1;
- }
-
- VLA(uint8_t, data_encrypted, *next_packet_length);
- int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length);
-
- if (len_packet != *next_packet_length) {
- return 0;
- }
-
- *next_packet_length = 0;
-
- int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data);
-
- if (len + CRYPTO_MAC_SIZE != len_packet) {
- return -1;
- }
-
- increment_nonce(recv_nonce);
-
- return len;
-}
-
-/* return 0 if pending data was sent completely
- * return -1 if it wasn't
- */
-static int send_pending_data_nonpriority(TCP_Secure_Connection *con)
-{
- if (con->last_packet_length == 0) {
- return 0;
- }
-
- uint16_t left = con->last_packet_length - con->last_packet_sent;
- int len = send(con->sock, (const char *)(con->last_packet + con->last_packet_sent), left, MSG_NOSIGNAL);
-
- if (len <= 0) {
- return -1;
- }
-
- if (len == left) {
- con->last_packet_length = 0;
- con->last_packet_sent = 0;
- return 0;
- }
-
- con->last_packet_sent += len;
- return -1;
-}
-
-/* return 0 if pending data was sent completely
- * return -1 if it wasn't
- */
-static int send_pending_data(TCP_Secure_Connection *con)
-{
- /* finish sending current non-priority packet */
- if (send_pending_data_nonpriority(con) == -1) {
- return -1;
- }
-
- TCP_Priority_List *p = con->priority_queue_start;
-
- while (p) {
- uint16_t left = p->size - p->sent;
- int len = send(con->sock, (const char *)(p->data + p->sent), left, MSG_NOSIGNAL);
-
- if (len != left) {
- if (len > 0) {
- p->sent += len;
- }
-
- break;
- }
-
- TCP_Priority_List *pp = p;
- p = p->next;
- free(pp);
- }
-
- con->priority_queue_start = p;
-
- if (!p) {
- con->priority_queue_end = NULL;
- return 0;
- }
-
- return -1;
-}
-
-/* return 0 on failure (only if malloc fails)
- * return 1 on success
- */
-static bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent)
-{
- TCP_Priority_List *p = con->priority_queue_end;
- TCP_Priority_List *new_list = (TCP_Priority_List *)malloc(sizeof(TCP_Priority_List) + size);
-
- if (!new_list) {
- return 0;
- }
-
- new_list->next = NULL;
- new_list->size = size;
- new_list->sent = sent;
- memcpy(new_list->data, packet, size);
-
- if (p) {
- p->next = new_list;
- } else {
- con->priority_queue_start = new_list;
- }
-
- con->priority_queue_end = new_list;
- return 1;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
- bool priority)
-{
- if (length + CRYPTO_MAC_SIZE > MAX_PACKET_SIZE) {
- return -1;
- }
-
- bool sendpriority = 1;
-
- if (send_pending_data(con) == -1) {
- if (priority) {
- sendpriority = 0;
- } else {
- return 0;
- }
- }
-
- VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
-
- uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
- memcpy(packet, &c_length, sizeof(uint16_t));
- int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
-
- if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) {
- return -1;
- }
-
- if (priority) {
- len = sendpriority ? send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL) : 0;
-
- if (len <= 0) {
- len = 0;
- }
-
- increment_nonce(con->sent_nonce);
-
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
- return 1;
- }
-
- return add_priority(con, packet, SIZEOF_VLA(packet), len);
- }
-
- len = send(con->sock, (const char *)packet, SIZEOF_VLA(packet), MSG_NOSIGNAL);
-
- if (len <= 0) {
- return 0;
- }
-
- increment_nonce(con->sent_nonce);
-
- if ((unsigned int)len == SIZEOF_VLA(packet)) {
- return 1;
- }
-
- memcpy(con->last_packet, packet, SIZEOF_VLA(packet));
- con->last_packet_length = SIZEOF_VLA(packet);
- con->last_packet_sent = len;
- return 1;
-}
-
-/* Kill a TCP_Secure_Connection
- */
-static void kill_TCP_secure_connection(TCP_Secure_Connection *con)
-{
- kill_sock(con->sock);
- crypto_memzero(con, sizeof(TCP_Secure_Connection));
-}
-
-static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number);
-
-/* Kill an accepted TCP_Secure_Connection
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int kill_accepted(TCP_Server *TCP_server, int index)
-{
- if ((uint32_t)index >= TCP_server->size_accepted_connections) {
- return -1;
- }
-
- uint32_t i;
-
- for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
- rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i);
- }
-
- Socket sock = TCP_server->accepted_connection_array[index].sock;
-
- if (del_accepted(TCP_server, index) != 0) {
- return -1;
- }
-
- kill_sock(sock);
- return 0;
-}
-
-/* return 1 if everything went well.
- * return -1 if the connection must be killed.
- */
-static int handle_TCP_handshake(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length,
- const uint8_t *self_secret_key)
-{
- if (length != TCP_CLIENT_HANDSHAKE_SIZE) {
- return -1;
- }
-
- if (con->status != TCP_STATUS_CONNECTED) {
- return -1;
- }
-
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- encrypt_precompute(data, self_secret_key, shared_key);
- uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
- int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
- data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);
-
- if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
- return -1;
- }
-
- memcpy(con->public_key, data, CRYPTO_PUBLIC_KEY_SIZE);
- uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
- uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE];
- crypto_new_keypair(resp_plain, temp_secret_key);
- random_nonce(con->sent_nonce);
- memcpy(resp_plain + CRYPTO_PUBLIC_KEY_SIZE, con->sent_nonce, CRYPTO_NONCE_SIZE);
- memcpy(con->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
-
- uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
- random_nonce(response);
-
- len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
- response + CRYPTO_NONCE_SIZE);
-
- if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, (const char *)response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL)) {
- return -1;
- }
-
- encrypt_precompute(plain, temp_secret_key, con->shared_key);
- con->status = TCP_STATUS_UNCONFIRMED;
- return 1;
-}
-
-/* return 1 if connection handshake was handled correctly.
- * return 0 if we didn't get it yet.
- * return -1 if the connection must be killed.
- */
-static int read_connection_handshake(TCP_Secure_Connection *con, const uint8_t *self_secret_key)
-{
- uint8_t data[TCP_CLIENT_HANDSHAKE_SIZE];
- int len = 0;
-
- if ((len = read_TCP_packet(con->sock, data, TCP_CLIENT_HANDSHAKE_SIZE)) != -1) {
- return handle_TCP_handshake(con, data, len, self_secret_key);
- }
-
- return 0;
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const uint8_t *public_key)
-{
- uint8_t data[1 + 1 + CRYPTO_PUBLIC_KEY_SIZE];
- data[0] = TCP_PACKET_ROUTING_RESPONSE;
- data[1] = rpid;
- memcpy(data + 2, public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id)
-{
- uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
- return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
-}
-
-/* return 1 on success.
- * return 0 if could not send packet.
- * return -1 on failure (connection must be killed).
- */
-static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id)
-{
- uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, (uint8_t)(id + NUM_RESERVED_PORTS)};
- return write_packet_TCP_secure_connection(con, data, sizeof(data), 1);
-}
-
-/* return 0 on success.
- * return -1 on failure (connection must be killed).
- */
-static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key)
-{
- uint32_t i;
- uint32_t index = ~0;
- TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
-
- /* If person tries to cennect to himself we deny the request*/
- if (public_key_cmp(con->public_key, public_key) == 0) {
- if (send_routing_response(con, 0, public_key) == -1) {
- return -1;
- }
-
- return 0;
- }
-
- for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
- if (con->connections[i].status != 0) {
- if (public_key_cmp(public_key, con->connections[i].public_key) == 0) {
- if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) {
- return -1;
- }
-
- return 0;
- }
- } else if (index == (uint32_t)~0) {
- index = i;
- }
- }
-
- if (index == (uint32_t)~0) {
- if (send_routing_response(con, 0, public_key) == -1) {
- return -1;
- }
-
- return 0;
- }
-
- int ret = send_routing_response(con, index + NUM_RESERVED_PORTS, public_key);
-
- if (ret == 0) {
- return 0;
- }
-
- if (ret == -1) {
- return -1;
- }
-
- con->connections[index].status = 1;
- memcpy(con->connections[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- int other_index = get_TCP_connection_index(TCP_server, public_key);
-
- if (other_index != -1) {
- uint32_t other_id = ~0;
- TCP_Secure_Connection *other_conn = &TCP_server->accepted_connection_array[other_index];
-
- for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) {
- if (other_conn->connections[i].status == 1
- && public_key_cmp(other_conn->connections[i].public_key, con->public_key) == 0) {
- other_id = i;
- break;
- }
- }
-
- if (other_id != (uint32_t)~0) {
- con->connections[index].status = 2;
- con->connections[index].index = other_index;
- con->connections[index].other_id = other_id;
- other_conn->connections[other_id].status = 2;
- other_conn->connections[other_id].index = con_id;
- other_conn->connections[other_id].other_id = index;
- // TODO(irungentoo): return values?
- send_connect_notification(con, index);
- send_connect_notification(other_conn, other_id);
- }
- }
-
- return 0;
-}
-
-/* return 0 on success.
- * return -1 on failure (connection must be killed).
- */
-static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *public_key, const uint8_t *data,
- uint16_t length)
-{
- if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
- return -1;
- }
-
- TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
-
- int other_index = get_TCP_connection_index(TCP_server, public_key);
-
- if (other_index != -1) {
- VLA(uint8_t, resp_packet, 1 + CRYPTO_PUBLIC_KEY_SIZE + length);
- resp_packet[0] = TCP_PACKET_OOB_RECV;
- memcpy(resp_packet + 1, con->public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(resp_packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
- write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet,
- SIZEOF_VLA(resp_packet), 0);
- }
-
- return 0;
-}
-
-/* Remove connection with con_number from the connections array of con.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number)
-{
- if (con_number >= NUM_CLIENT_CONNECTIONS) {
- return -1;
- }
-
- if (con->connections[con_number].status) {
- uint32_t index = con->connections[con_number].index;
- uint8_t other_id = con->connections[con_number].other_id;
-
- if (con->connections[con_number].status == 2) {
-
- if (index >= TCP_server->size_accepted_connections) {
- return -1;
- }
-
- TCP_server->accepted_connection_array[index].connections[other_id].other_id = 0;
- TCP_server->accepted_connection_array[index].connections[other_id].index = 0;
- TCP_server->accepted_connection_array[index].connections[other_id].status = 1;
- // TODO(irungentoo): return values?
- send_disconnect_notification(&TCP_server->accepted_connection_array[index], other_id);
- }
-
- con->connections[con_number].index = 0;
- con->connections[con_number].other_id = 0;
- con->connections[con_number].status = 0;
- return 0;
- }
-
- return -1;
-}
-
-static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, uint16_t length)
-{
- TCP_Server *TCP_server = (TCP_Server *)object;
- uint32_t index = dest.ip.ip6.uint32[0];
-
- if (index >= TCP_server->size_accepted_connections) {
- return 1;
- }
-
- TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[index];
-
- if (con->identifier != dest.ip.ip6.uint64[1]) {
- return 1;
- }
-
- VLA(uint8_t, packet, 1 + length);
- memcpy(packet + 1, data, length);
- packet[0] = TCP_PACKET_ONION_RESPONSE;
-
- if (write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0) != 1) {
- return 1;
- }
-
- return 0;
-}
-
-/* return 0 on success
- * return -1 on failure
- */
-static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length)
-{
- if (length == 0) {
- return -1;
- }
-
- TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id];
-
- switch (data[0]) {
- case TCP_PACKET_ROUTING_REQUEST: {
- if (length != 1 + CRYPTO_PUBLIC_KEY_SIZE) {
- return -1;
- }
-
- return handle_TCP_routing_req(TCP_server, con_id, data + 1);
- }
-
- case TCP_PACKET_CONNECTION_NOTIFICATION: {
- if (length != 2) {
- return -1;
- }
-
- break;
- }
-
- case TCP_PACKET_DISCONNECT_NOTIFICATION: {
- if (length != 2) {
- return -1;
- }
-
- return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS);
- }
-
- case TCP_PACKET_PING: {
- if (length != 1 + sizeof(uint64_t)) {
- return -1;
- }
-
- uint8_t response[1 + sizeof(uint64_t)];
- response[0] = TCP_PACKET_PONG;
- memcpy(response + 1, data + 1, sizeof(uint64_t));
- write_packet_TCP_secure_connection(con, response, sizeof(response), 1);
- return 0;
- }
-
- case TCP_PACKET_PONG: {
- if (length != 1 + sizeof(uint64_t)) {
- return -1;
- }
-
- uint64_t ping_id;
- memcpy(&ping_id, data + 1, sizeof(uint64_t));
-
- if (ping_id) {
- if (ping_id == con->ping_id) {
- con->ping_id = 0;
- }
-
- return 0;
- }
-
- return -1;
- }
-
- case TCP_PACKET_OOB_SEND: {
- if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
- return -1;
- }
-
- return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_PUBLIC_KEY_SIZE));
- }
-
- case TCP_PACKET_ONION_REQUEST: {
- if (TCP_server->onion) {
- if (length <= 1 + CRYPTO_NONCE_SIZE + ONION_SEND_BASE * 2) {
- return -1;
- }
-
- IP_Port source;
- source.port = 0; // dummy initialise
- source.ip.family = TCP_ONION_FAMILY;
- source.ip.ip6.uint32[0] = con_id;
- source.ip.ip6.uint32[1] = 0;
- source.ip.ip6.uint64[1] = con->identifier;
- onion_send_1(TCP_server->onion, data + 1 + CRYPTO_NONCE_SIZE, length - (1 + CRYPTO_NONCE_SIZE), source,
- data + 1);
- }
-
- return 0;
- }
-
- case TCP_PACKET_ONION_RESPONSE: {
- return -1;
- }
-
- default: {
- if (data[0] < NUM_RESERVED_PORTS) {
- return -1;
- }
-
- uint8_t c_id = data[0] - NUM_RESERVED_PORTS;
-
- if (c_id >= NUM_CLIENT_CONNECTIONS) {
- return -1;
- }
-
- if (con->connections[c_id].status == 0) {
- return -1;
- }
-
- if (con->connections[c_id].status != 2) {
- return 0;
- }
-
- uint32_t index = con->connections[c_id].index;
- uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS;
- VLA(uint8_t, new_data, length);
- memcpy(new_data, data, length);
- new_data[0] = other_c_id;
- int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0);
-
- if (ret == -1) {
- return -1;
- }
-
- return 0;
- }
- }
-
- return 0;
-}
-
-
-static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection *con, const uint8_t *data,
- uint16_t length)
-{
- int index = add_accepted(TCP_server, con);
-
- if (index == -1) {
- kill_TCP_secure_connection(con);
- return -1;
- }
-
- crypto_memzero(con, sizeof(TCP_Secure_Connection));
-
- if (handle_TCP_packet(TCP_server, index, data, length) == -1) {
- kill_accepted(TCP_server, index);
- return -1;
- }
-
- return index;
-}
-
-/* return index on success
- * return -1 on failure
- */
-static int accept_connection(TCP_Server *TCP_server, Socket sock)
-{
- if (!sock_valid(sock)) {
- return -1;
- }
-
- if (!set_socket_nonblock(sock)) {
- kill_sock(sock);
- return -1;
- }
-
- if (!set_socket_nosigpipe(sock)) {
- kill_sock(sock);
- return -1;
- }
-
- uint16_t index = TCP_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS;
-
- TCP_Secure_Connection *conn = &TCP_server->incoming_connection_queue[index];
-
- if (conn->status != TCP_STATUS_NO_STATUS) {
- kill_TCP_secure_connection(conn);
- }
-
- conn->status = TCP_STATUS_CONNECTED;
- conn->sock = sock;
- conn->next_packet_length = 0;
-
- ++TCP_server->incoming_connection_queue_index;
- return index;
-}
-
-static Socket new_listening_TCP_socket(int family, uint16_t port)
-{
- Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
-
- if (!sock_valid(sock)) {
- return ~0;
- }
-
- int ok = set_socket_nonblock(sock);
-
- if (ok && family == TOX_AF_INET6) {
- ok = set_socket_dualstack(sock);
- }
-
- if (ok) {
- ok = set_socket_reuseaddr(sock);
- }
-
- ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0);
-
- if (!ok) {
- kill_sock(sock);
- return ~0;
- }
-
- return sock;
-}
-
-TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
- Onion *onion)
-{
- if (num_sockets == 0 || ports == NULL) {
- return NULL;
- }
-
- if (networking_at_startup() != 0) {
- return NULL;
- }
-
- TCP_Server *temp = (TCP_Server *)calloc(1, sizeof(TCP_Server));
-
- if (temp == NULL) {
- return NULL;
- }
-
- temp->socks_listening = (Socket *)calloc(num_sockets, sizeof(Socket));
-
- if (temp->socks_listening == NULL) {
- free(temp);
- return NULL;
- }
-
-#ifdef TCP_SERVER_USE_EPOLL
- temp->efd = epoll_create(8);
-
- if (temp->efd == -1) {
- free(temp->socks_listening);
- free(temp);
- return NULL;
- }
-
-#endif
-
- uint8_t family;
-
- if (ipv6_enabled) {
- family = TOX_AF_INET6;
- } else {
- family = TOX_AF_INET;
- }
-
- uint32_t i;
-#ifdef TCP_SERVER_USE_EPOLL
- struct epoll_event ev;
-#endif
-
- for (i = 0; i < num_sockets; ++i) {
- Socket sock = new_listening_TCP_socket(family, ports[i]);
-
- if (sock_valid(sock)) {
-#ifdef TCP_SERVER_USE_EPOLL
- ev.events = EPOLLIN | EPOLLET;
- ev.data.u64 = sock | ((uint64_t)TCP_SOCKET_LISTENING << 32);
-
- if (epoll_ctl(temp->efd, EPOLL_CTL_ADD, sock, &ev) == -1) {
- continue;
- }
-
-#endif
-
- temp->socks_listening[temp->num_listening_socks] = sock;
- ++temp->num_listening_socks;
- }
- }
-
- if (temp->num_listening_socks == 0) {
- free(temp->socks_listening);
- free(temp);
- return NULL;
- }
-
- if (onion) {
- temp->onion = onion;
- set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp);
- }
-
- memcpy(temp->secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
- crypto_derive_public_key(temp->public_key, temp->secret_key);
-
- bs_list_init(&temp->accepted_key_list, CRYPTO_PUBLIC_KEY_SIZE, 8);
-
- return temp;
-}
-
-static void do_TCP_accept_new(TCP_Server *TCP_server)
-{
- uint32_t i;
-
- for (i = 0; i < TCP_server->num_listening_socks; ++i) {
- struct sockaddr_storage addr;
- socklen_t addrlen = sizeof(addr);
- Socket sock;
-
- do {
- sock = accept(TCP_server->socks_listening[i], (struct sockaddr *)&addr, &addrlen);
- } while (accept_connection(TCP_server, sock) != -1);
- }
-}
-
-static int do_incoming(TCP_Server *TCP_server, uint32_t i)
-{
- if (TCP_server->incoming_connection_queue[i].status != TCP_STATUS_CONNECTED) {
- return -1;
- }
-
- int ret = read_connection_handshake(&TCP_server->incoming_connection_queue[i], TCP_server->secret_key);
-
- if (ret == -1) {
- kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[i]);
- } else if (ret == 1) {
- int index_new = TCP_server->unconfirmed_connection_queue_index % MAX_INCOMING_CONNECTIONS;
- TCP_Secure_Connection *conn_old = &TCP_server->incoming_connection_queue[i];
- TCP_Secure_Connection *conn_new = &TCP_server->unconfirmed_connection_queue[index_new];
-
- if (conn_new->status != TCP_STATUS_NO_STATUS) {
- kill_TCP_secure_connection(conn_new);
- }
-
- memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection));
- crypto_memzero(conn_old, sizeof(TCP_Secure_Connection));
- ++TCP_server->unconfirmed_connection_queue_index;
-
- return index_new;
- }
-
- return -1;
-}
-
-static int do_unconfirmed(TCP_Server *TCP_server, uint32_t i)
-{
- TCP_Secure_Connection *conn = &TCP_server->unconfirmed_connection_queue[i];
-
- if (conn->status != TCP_STATUS_UNCONFIRMED) {
- return -1;
- }
-
- uint8_t packet[MAX_PACKET_SIZE];
- int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce,
- packet, sizeof(packet));
-
- if (len == 0) {
- return -1;
- }
-
- if (len == -1) {
- kill_TCP_secure_connection(conn);
- return -1;
- }
-
- return confirm_TCP_connection(TCP_server, conn, packet, len);
-}
-
-static void do_confirmed_recv(TCP_Server *TCP_server, uint32_t i)
-{
- TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];
-
- uint8_t packet[MAX_PACKET_SIZE];
- int len;
-
- while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
- conn->recv_nonce, packet, sizeof(packet)))) {
- if (len == -1) {
- kill_accepted(TCP_server, i);
- break;
- }
-
- if (handle_TCP_packet(TCP_server, i, packet, len) == -1) {
- kill_accepted(TCP_server, i);
- break;
- }
- }
-}
-
-static void do_TCP_incoming(TCP_Server *TCP_server)
-{
- uint32_t i;
-
- for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
- do_incoming(TCP_server, i);
- }
-}
-
-static void do_TCP_unconfirmed(TCP_Server *TCP_server)
-{
- uint32_t i;
-
- for (i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) {
- do_unconfirmed(TCP_server, i);
- }
-}
-
-static void do_TCP_confirmed(TCP_Server *TCP_server)
-{
-#ifdef TCP_SERVER_USE_EPOLL
-
- if (TCP_server->last_run_pinged == unix_time()) {
- return;
- }
-
- TCP_server->last_run_pinged = unix_time();
-#endif
- uint32_t i;
-
- for (i = 0; i < TCP_server->size_accepted_connections; ++i) {
- TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i];
-
- if (conn->status != TCP_STATUS_CONFIRMED) {
- continue;
- }
-
- if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
- uint8_t ping[1 + sizeof(uint64_t)];
- ping[0] = TCP_PACKET_PING;
- uint64_t ping_id = random_64b();
-
- if (!ping_id) {
- ++ping_id;
- }
-
- memcpy(ping + 1, &ping_id, sizeof(uint64_t));
- int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1);
-
- if (ret == 1) {
- conn->last_pinged = unix_time();
- conn->ping_id = ping_id;
- } else {
- if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) {
- kill_accepted(TCP_server, i);
- continue;
- }
- }
- }
-
- if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) {
- kill_accepted(TCP_server, i);
- continue;
- }
-
- send_pending_data(conn);
-
-#ifndef TCP_SERVER_USE_EPOLL
-
- do_confirmed_recv(TCP_server, i);
-
-#endif
- }
-}
-
-#ifdef TCP_SERVER_USE_EPOLL
-static void do_TCP_epoll(TCP_Server *TCP_server)
-{
-#define MAX_EVENTS 16
- struct epoll_event events[MAX_EVENTS];
- int nfds;
-
- while ((nfds = epoll_wait(TCP_server->efd, events, MAX_EVENTS, 0)) > 0) {
- int n;
-
- for (n = 0; n < nfds; ++n) {
- Socket sock = events[n].data.u64 & 0xFFFFFFFF;
- int status = (events[n].data.u64 >> 32) & 0xFF, index = (events[n].data.u64 >> 40);
-
- if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP) || (events[n].events & EPOLLRDHUP)) {
- switch (status) {
- case TCP_SOCKET_LISTENING: {
- //should never happen
- break;
- }
-
- case TCP_SOCKET_INCOMING: {
- kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index]);
- break;
- }
-
- case TCP_SOCKET_UNCONFIRMED: {
- kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index]);
- break;
- }
-
- case TCP_SOCKET_CONFIRMED: {
- kill_accepted(TCP_server, index);
- break;
- }
- }
-
- continue;
- }
-
-
- if (!(events[n].events & EPOLLIN)) {
- continue;
- }
-
- switch (status) {
- case TCP_SOCKET_LISTENING: {
- //socket is from socks_listening, accept connection
- struct sockaddr_storage addr;
- socklen_t addrlen = sizeof(addr);
-
- while (1) {
- Socket sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen);
-
- if (!sock_valid(sock_new)) {
- break;
- }
-
- int index_new = accept_connection(TCP_server, sock_new);
-
- if (index_new == -1) {
- continue;
- }
-
- struct epoll_event ev = {
- .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
- .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 40)
- };
-
- if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) {
- kill_TCP_secure_connection(&TCP_server->incoming_connection_queue[index_new]);
- continue;
- }
- }
-
- break;
- }
-
- case TCP_SOCKET_INCOMING: {
- int index_new;
-
- if ((index_new = do_incoming(TCP_server, index)) != -1) {
- events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
- events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 40);
-
- if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
- kill_TCP_secure_connection(&TCP_server->unconfirmed_connection_queue[index_new]);
- break;
- }
- }
-
- break;
- }
-
- case TCP_SOCKET_UNCONFIRMED: {
- int index_new;
-
- if ((index_new = do_unconfirmed(TCP_server, index)) != -1) {
- events[n].events = EPOLLIN | EPOLLET | EPOLLRDHUP;
- events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 40);
-
- if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
- //remove from confirmed connections
- kill_accepted(TCP_server, index_new);
- break;
- }
- }
-
- break;
- }
-
- case TCP_SOCKET_CONFIRMED: {
- do_confirmed_recv(TCP_server, index);
- break;
- }
- }
- }
- }
-
-#undef MAX_EVENTS
-}
-#endif
-
-void do_TCP_server(TCP_Server *TCP_server)
-{
- unix_time_update();
-
-#ifdef TCP_SERVER_USE_EPOLL
- do_TCP_epoll(TCP_server);
-
-#else
- do_TCP_accept_new(TCP_server);
- do_TCP_incoming(TCP_server);
- do_TCP_unconfirmed(TCP_server);
-#endif
-
- do_TCP_confirmed(TCP_server);
-}
-
-void kill_TCP_server(TCP_Server *TCP_server)
-{
- uint32_t i;
-
- for (i = 0; i < TCP_server->num_listening_socks; ++i) {
- kill_sock(TCP_server->socks_listening[i]);
- }
-
- if (TCP_server->onion) {
- set_callback_handle_recv_1(TCP_server->onion, NULL, NULL);
- }
-
- bs_list_free(&TCP_server->accepted_key_list);
-
-#ifdef TCP_SERVER_USE_EPOLL
- close(TCP_server->efd);
-#endif
-
- free(TCP_server->socks_listening);
- free(TCP_server->accepted_connection_array);
- free(TCP_server);
-}
diff --git a/libs/libtox/src/toxcore/TCP_server.h b/libs/libtox/src/toxcore/TCP_server.h
deleted file mode 100644
index f213c078e6..0000000000
--- a/libs/libtox/src/toxcore/TCP_server.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Implementation of the TCP relay server part of Tox.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TCP_SERVER_H
-#define TCP_SERVER_H
-
-#include "crypto_core.h"
-#include "list.h"
-#include "onion.h"
-
-#ifdef TCP_SERVER_USE_EPOLL
-#include <sys/epoll.h>
-#endif
-
-// Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD
-#if !defined(MSG_NOSIGNAL)
-#define MSG_NOSIGNAL 0
-#endif
-
-#define MAX_INCOMING_CONNECTIONS 256
-
-#define TCP_MAX_BACKLOG MAX_INCOMING_CONNECTIONS
-
-#define MAX_PACKET_SIZE 2048
-
-#define TCP_HANDSHAKE_PLAIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE)
-#define TCP_SERVER_HANDSHAKE_SIZE (CRYPTO_NONCE_SIZE + TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE)
-#define TCP_CLIENT_HANDSHAKE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + TCP_SERVER_HANDSHAKE_SIZE)
-#define TCP_MAX_OOB_DATA_LENGTH 1024
-
-#define NUM_RESERVED_PORTS 16
-#define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS)
-
-#define TCP_PACKET_ROUTING_REQUEST 0
-#define TCP_PACKET_ROUTING_RESPONSE 1
-#define TCP_PACKET_CONNECTION_NOTIFICATION 2
-#define TCP_PACKET_DISCONNECT_NOTIFICATION 3
-#define TCP_PACKET_PING 4
-#define TCP_PACKET_PONG 5
-#define TCP_PACKET_OOB_SEND 6
-#define TCP_PACKET_OOB_RECV 7
-#define TCP_PACKET_ONION_REQUEST 8
-#define TCP_PACKET_ONION_RESPONSE 9
-
-#define ARRAY_ENTRY_SIZE 6
-
-/* frequency to ping connected nodes and timeout in seconds */
-#define TCP_PING_FREQUENCY 30
-#define TCP_PING_TIMEOUT 10
-
-#ifdef TCP_SERVER_USE_EPOLL
-#define TCP_SOCKET_LISTENING 0
-#define TCP_SOCKET_INCOMING 1
-#define TCP_SOCKET_UNCONFIRMED 2
-#define TCP_SOCKET_CONFIRMED 3
-#endif
-
-enum {
- TCP_STATUS_NO_STATUS,
- TCP_STATUS_CONNECTED,
- TCP_STATUS_UNCONFIRMED,
- TCP_STATUS_CONFIRMED,
-};
-
-typedef struct TCP_Priority_List TCP_Priority_List;
-
-struct TCP_Priority_List {
- TCP_Priority_List *next;
- uint16_t size, sent;
- uint8_t data[];
-};
-
-typedef struct TCP_Secure_Connection {
- Socket sock;
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
- uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint16_t next_packet_length;
- struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint32_t index;
- uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
- uint8_t other_id;
- } connections[NUM_CLIENT_CONNECTIONS];
- uint8_t last_packet[2 + MAX_PACKET_SIZE];
- uint8_t status;
- uint16_t last_packet_length;
- uint16_t last_packet_sent;
-
- TCP_Priority_List *priority_queue_start, *priority_queue_end;
-
- uint64_t identifier;
-
- uint64_t last_pinged;
- uint64_t ping_id;
-} TCP_Secure_Connection;
-
-
-typedef struct TCP_Server TCP_Server;
-
-const uint8_t *tcp_server_public_key(const TCP_Server *tcp_server);
-size_t tcp_server_listen_count(const TCP_Server *tcp_server);
-
-/* Create new TCP server instance.
- */
-TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, const uint16_t *ports, const uint8_t *secret_key,
- Onion *onion);
-
-/* Run the TCP_server
- */
-void do_TCP_server(TCP_Server *TCP_server);
-
-/* Kill the TCP server
- */
-void kill_TCP_server(TCP_Server *TCP_server);
-
-/* return the amount of data in the tcp recv buffer.
- * return 0 on failure.
- */
-unsigned int TCP_socket_data_recv_buffer(Socket sock);
-
-/* Read the next two bytes in TCP stream then convert them to
- * length (host byte order).
- *
- * return length on success
- * return 0 if nothing has been read from socket.
- * return ~0 on failure.
- */
-uint16_t read_TCP_length(Socket sock);
-
-/* Read length bytes from socket.
- *
- * return length on success
- * return -1 on failure/no data in buffer.
- */
-int read_TCP_packet(Socket sock, uint8_t *data, uint16_t length);
-
-/* return length of received packet on success.
- * return 0 if could not read any packet.
- * return -1 on failure (connection must be killed).
- */
-int read_packet_TCP_secure_connection(Socket sock, uint16_t *next_packet_length, const uint8_t *shared_key,
- uint8_t *recv_nonce, uint8_t *data, uint16_t max_len);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/ccompat.h b/libs/libtox/src/toxcore/ccompat.h
deleted file mode 100644
index e72e66ae58..0000000000
--- a/libs/libtox/src/toxcore/ccompat.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * C language compatibility macros for varying compiler support.
- */
-#ifndef CCOMPAT_H
-#define CCOMPAT_H
-
-// Marking GNU extensions to avoid warnings.
-#if defined(__GNUC__)
-#define GNU_EXTENSION __extension__
-#else
-#define GNU_EXTENSION
-#endif
-
-// Variable length arrays.
-// VLA(type, name, size) allocates a variable length array with automatic
-// storage duration. VLA_SIZE(name) evaluates to the runtime size of that array
-// in bytes.
-//
-// If C99 VLAs are not available, an emulation using alloca (stack allocation
-// "function") is used. Note the semantic difference: alloca'd memory does not
-// get freed at the end of the declaration's scope. Do not use VLA() in loops or
-// you may run out of stack space.
-#if !defined(_MSC_VER) && __STDC_VERSION__ >= 199901L
-// C99 VLAs.
-#define VLA(type, name, size) type name[size]
-#define SIZEOF_VLA sizeof
-#else
-
-// Emulation using alloca.
-#ifdef _WIN32
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
-#define VLA(type, name, size) \
- const size_t name##_size = (size) * sizeof(type); \
- type *const name = (type *)alloca(name##_size)
-#define SIZEOF_VLA(name) name##_size
-
-#endif
-
-#endif /* CCOMPAT_H */
diff --git a/libs/libtox/src/toxcore/crypto_core.api.h b/libs/libtox/src/toxcore/crypto_core.api.h
deleted file mode 100644
index cef1a52c14..0000000000
--- a/libs/libtox/src/toxcore/crypto_core.api.h
+++ /dev/null
@@ -1,246 +0,0 @@
-%{
-/*
- * Functions for the core crypto.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef CRYPTO_CORE_H
-#define CRYPTO_CORE_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-%}
-
-/**
- * The number of bytes in a Tox public key.
- */
-const CRYPTO_PUBLIC_KEY_SIZE = 32;
-
-/**
- * The number of bytes in a Tox secret key.
- */
-const CRYPTO_SECRET_KEY_SIZE = 32;
-
-/**
- * The number of bytes in a shared key computed from public and secret keys.
- */
-const CRYPTO_SHARED_KEY_SIZE = 32;
-
-/**
- * The number of bytes in a symmetric key.
- */
-const CRYPTO_SYMMETRIC_KEY_SIZE = CRYPTO_SHARED_KEY_SIZE;
-
-/**
- * The number of bytes needed for the MAC (message authentication code) in an
- * encrypted message.
- */
-const CRYPTO_MAC_SIZE = 16;
-
-/**
- * The number of bytes in a nonce used for encryption/decryption.
- */
-const CRYPTO_NONCE_SIZE = 24;
-
-/**
- * The number of bytes in a SHA256 hash.
- */
-const CRYPTO_SHA256_SIZE = 32;
-
-/**
- * The number of bytes in a SHA512 hash.
- */
-const CRYPTO_SHA512_SIZE = 64;
-
-/**
- * A `memcmp`-like function whose running time does not depend on the input
- * bytes, only on the input length. Useful to compare sensitive data where
- * timing attacks could reveal that data.
- *
- * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
- * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
- * take 1 time, because it immediately knows that the two strings are not equal.
- */
-static int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
-
-/**
- * A `bzero`-like function which won't be optimised away by the compiler. Some
- * compilers will inline `bzero` or `memset` if they can prove that there will
- * be no reads to the written data. Use this function if you want to be sure the
- * memory is indeed zeroed.
- */
-static void crypto_memzero(void *data, size_t length);
-
-/**
- * Compute a SHA256 hash (32 bytes).
- */
-static void crypto_sha256(uint8_t[CRYPTO_SHA256_SIZE] hash, const uint8_t[length] data);
-
-/**
- * Compute a SHA512 hash (64 bytes).
- */
-static void crypto_sha512(uint8_t[CRYPTO_SHA512_SIZE] hash, const uint8_t[length] data);
-
-/**
- * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
- * timing attacks.
- *
- * @return 0 if both mem locations of length are equal, -1 if they are not.
- */
-static int32_t public_key_cmp(
- const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk1,
- const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] pk2);
-
-/**
- * Return a random 32 bit integer.
- */
-static uint32_t random_int();
-
-/**
- * Return a random 64 bit integer.
- */
-static uint64_t random_64b();
-
-/**
- * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
- * should only be used for input validation.
- *
- * @return false if it isn't, true if it is.
- */
-static bool public_key_valid(const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key);
-
-/**
- * Generate a new random keypair. Every call to this function is likely to
- * generate a different keypair.
- */
-static int32_t crypto_new_keypair(
- uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
- uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
-
-/**
- * Derive the public key from a given secret key.
- */
-static void crypto_derive_public_key(
- uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
- const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key);
-
-/**
- * Encrypt plain text of the given length to encrypted of length +
- * $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of the
- * receiver and the secret key of the sender and a $CRYPTO_NONCE_SIZE byte
- * nonce.
- *
- * @return -1 if there was a problem, length of encrypted data if everything
- * was fine.
- */
-static int32_t encrypt_data(
- const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
- const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
- const uint8_t[CRYPTO_NONCE_SIZE] nonce,
- const uint8_t[length] plain,
- uint8_t *encrypted);
-
-
-/**
- * Decrypt encrypted text of the given length to plain text of the given length
- * - $CRYPTO_MAC_SIZE using the public key ($CRYPTO_PUBLIC_KEY_SIZE bytes) of
- * the sender, the secret key of the receiver and a $CRYPTO_NONCE_SIZE byte
- * nonce.
- *
- * @return -1 if there was a problem (decryption failed), length of plain text
- * data if everything was fine.
- */
-static int32_t decrypt_data(
- const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
- const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
- const uint8_t[CRYPTO_NONCE_SIZE] nonce,
- const uint8_t[length] encrypted,
- uint8_t *plain);
-
-/**
- * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
- * $encrypt_precompute does the shared-key generation once so it does not have
- * to be preformed on every encrypt/decrypt.
- */
-static int32_t encrypt_precompute(
- const uint8_t[CRYPTO_PUBLIC_KEY_SIZE] public_key,
- const uint8_t[CRYPTO_SECRET_KEY_SIZE] secret_key,
- uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key);
-
-/**
- * Encrypts plain of length length to encrypted of length + $CRYPTO_MAC_SIZE
- * using a shared key $CRYPTO_SYMMETRIC_KEY_SIZE big and a $CRYPTO_NONCE_SIZE
- * byte nonce.
- *
- * @return -1 if there was a problem, length of encrypted data if everything
- * was fine.
- */
-static int32_t encrypt_data_symmetric(
- const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
- const uint8_t[CRYPTO_NONCE_SIZE] nonce,
- const uint8_t[length] plain,
- uint8_t *encrypted);
-
-/**
- * Decrypts encrypted of length length to plain of length length -
- * $CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
- * $CRYPTO_NONCE_SIZE byte nonce.
- *
- * @return -1 if there was a problem (decryption failed), length of plain data
- * if everything was fine.
- */
-static int32_t decrypt_data_symmetric(
- const uint8_t[CRYPTO_SHARED_KEY_SIZE] shared_key,
- const uint8_t[CRYPTO_NONCE_SIZE] nonce,
- const uint8_t[length] encrypted,
- uint8_t *plain);
-
-/**
- * Increment the given nonce by 1 in big endian (rightmost byte incremented
- * first).
- */
-static void increment_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
-
-/**
- * Increment the given nonce by a given number. The number should be in host
- * byte order.
- */
-static void increment_nonce_number(uint8_t[CRYPTO_NONCE_SIZE] nonce, uint32_t host_order_num);
-
-/**
- * Fill the given nonce with random bytes.
- */
-static void random_nonce(uint8_t[CRYPTO_NONCE_SIZE] nonce);
-
-/**
- * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
- */
-static void new_symmetric_key(uint8_t[CRYPTO_SYMMETRIC_KEY_SIZE] key);
-
-/**
- * Fill an array of bytes with random values.
- */
-static void random_bytes(uint8_t[length] bytes);
-
-%{
-#endif /* CRYPTO_CORE_H */
-%}
diff --git a/libs/libtox/src/toxcore/crypto_core.c b/libs/libtox/src/toxcore/crypto_core.c
deleted file mode 100644
index 8e34b5876a..0000000000
--- a/libs/libtox/src/toxcore/crypto_core.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Functions for the core crypto.
- *
- * NOTE: This code has to be perfect. We don't mess around with encryption.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ccompat.h"
-#include "crypto_core.h"
-
-#include <string.h>
-
-#ifndef VANILLA_NACL
-/* We use libsodium by default. */
-#include <sodium.h>
-#else
-#include <crypto_box.h>
-#include <crypto_hash_sha256.h>
-#include <crypto_hash_sha512.h>
-#include <crypto_scalarmult_curve25519.h>
-#include <crypto_verify_16.h>
-#include <crypto_verify_32.h>
-#include <randombytes.h>
-#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
-#endif
-
-#if CRYPTO_PUBLIC_KEY_SIZE != crypto_box_PUBLICKEYBYTES
-#error CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES
-#endif
-
-#if CRYPTO_SECRET_KEY_SIZE != crypto_box_SECRETKEYBYTES
-#error CRYPTO_SECRET_KEY_SIZE should be equal to crypto_box_SECRETKEYBYTES
-#endif
-
-#if CRYPTO_SHARED_KEY_SIZE != crypto_box_BEFORENMBYTES
-#error CRYPTO_SHARED_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
-#endif
-
-#if CRYPTO_SYMMETRIC_KEY_SIZE != crypto_box_BEFORENMBYTES
-#error CRYPTO_SYMMETRIC_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES
-#endif
-
-#if CRYPTO_MAC_SIZE != crypto_box_MACBYTES
-#error CRYPTO_MAC_SIZE should be equal to crypto_box_MACBYTES
-#endif
-
-#if CRYPTO_NONCE_SIZE != crypto_box_NONCEBYTES
-#error CRYPTO_NONCE_SIZE should be equal to crypto_box_NONCEBYTES
-#endif
-
-#if CRYPTO_SHA256_SIZE != crypto_hash_sha256_BYTES
-#error CRYPTO_SHA256_SIZE should be equal to crypto_hash_sha256_BYTES
-#endif
-
-#if CRYPTO_SHA512_SIZE != crypto_hash_sha512_BYTES
-#error CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES
-#endif
-
-int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2)
-{
-#if CRYPTO_PUBLIC_KEY_SIZE != 32
-#error CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for public_key_cmp to work,
-#endif
- return crypto_verify_32(pk1, pk2);
-}
-
-uint32_t random_int(void)
-{
- uint32_t randnum;
- randombytes((uint8_t *)&randnum , sizeof(randnum));
- return randnum;
-}
-
-uint64_t random_64b(void)
-{
- uint64_t randnum;
- randombytes((uint8_t *)&randnum, sizeof(randnum));
- return randnum;
-}
-
-bool public_key_valid(const uint8_t *public_key)
-{
- if (public_key[31] >= 128) { /* Last bit of key is always zero. */
- return 0;
- }
-
- return 1;
-}
-
-/* Precomputes the shared key from their public_key and our secret_key.
- * This way we can avoid an expensive elliptic curve scalar multiply for each
- * encrypt/decrypt operation.
- * shared_key has to be crypto_box_BEFORENMBYTES bytes long.
- */
-int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key)
-{
- return crypto_box_beforenm(shared_key, public_key, secret_key);
-}
-
-int32_t encrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
- uint8_t *encrypted)
-{
- if (length == 0 || !secret_key || !nonce || !plain || !encrypted) {
- return -1;
- }
-
- VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
- VLA(uint8_t, temp_encrypted, length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES);
-
- memset(temp_plain, 0, crypto_box_ZEROBYTES);
- memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes.
-
- if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) {
- return -1;
- }
-
- /* Unpad the encrypted message. */
- memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
- return length + crypto_box_MACBYTES;
-}
-
-int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
- uint8_t *plain)
-{
- if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) {
- return -1;
- }
-
- VLA(uint8_t, temp_plain, length + crypto_box_ZEROBYTES);
- VLA(uint8_t, temp_encrypted, length + crypto_box_BOXZEROBYTES);
-
- memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES);
- memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes.
-
- if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) {
- return -1;
- }
-
- memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
- return length - crypto_box_MACBYTES;
-}
-
-int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
- const uint8_t *plain, size_t length, uint8_t *encrypted)
-{
- if (!public_key || !secret_key) {
- return -1;
- }
-
- uint8_t k[crypto_box_BEFORENMBYTES];
- encrypt_precompute(public_key, secret_key, k);
- int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted);
- crypto_memzero(k, sizeof k);
- return ret;
-}
-
-int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
- const uint8_t *encrypted, size_t length, uint8_t *plain)
-{
- if (!public_key || !secret_key) {
- return -1;
- }
-
- uint8_t k[crypto_box_BEFORENMBYTES];
- encrypt_precompute(public_key, secret_key, k);
- int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain);
- crypto_memzero(k, sizeof k);
- return ret;
-}
-
-
-/* Increment the given nonce by 1. */
-void increment_nonce(uint8_t *nonce)
-{
- /* TODO(irungentoo): use increment_nonce_number(nonce, 1) or sodium_increment (change to little endian)
- * NOTE don't use breaks inside this loop
- * In particular, make sure, as far as possible,
- * that loop bounds and their potential underflow or overflow
- * are independent of user-controlled input (you may have heard of the Heartbleed bug).
- */
- uint32_t i = crypto_box_NONCEBYTES;
- uint_fast16_t carry = 1U;
-
- for (; i != 0; --i) {
- carry += (uint_fast16_t) nonce[i - 1];
- nonce[i - 1] = (uint8_t) carry;
- carry >>= 8;
- }
-}
-
-static uint32_t host_to_network(uint32_t x)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
- return
- ((x >> 24) & 0x000000FF) | // move byte 3 to byte 0
- ((x >> 8) & 0x0000FF00) | // move byte 2 to byte 1
- ((x << 8) & 0x00FF0000) | // move byte 1 to byte 2
- ((x << 24) & 0xFF000000); // move byte 0 to byte 3
-#else
- return x;
-#endif
-}
-
-/* increment the given nonce by num */
-void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num)
-{
- /* NOTE don't use breaks inside this loop
- * In particular, make sure, as far as possible,
- * that loop bounds and their potential underflow or overflow
- * are independent of user-controlled input (you may have heard of the Heartbleed bug).
- */
- const uint32_t big_endian_num = host_to_network(host_order_num);
- const uint8_t *const num_vec = (const uint8_t *) &big_endian_num;
- uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0};
- num_as_nonce[crypto_box_NONCEBYTES - 4] = num_vec[0];
- num_as_nonce[crypto_box_NONCEBYTES - 3] = num_vec[1];
- num_as_nonce[crypto_box_NONCEBYTES - 2] = num_vec[2];
- num_as_nonce[crypto_box_NONCEBYTES - 1] = num_vec[3];
-
- uint32_t i = crypto_box_NONCEBYTES;
- uint_fast16_t carry = 0U;
-
- for (; i != 0; --i) {
- carry += (uint_fast16_t) nonce[i - 1] + (uint_fast16_t) num_as_nonce[i - 1];
- nonce[i - 1] = (unsigned char) carry;
- carry >>= 8;
- }
-}
-
-/* Fill the given nonce with random bytes. */
-void random_nonce(uint8_t *nonce)
-{
- randombytes(nonce, crypto_box_NONCEBYTES);
-}
-
-/* Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes */
-void new_symmetric_key(uint8_t *key)
-{
- randombytes(key, CRYPTO_SYMMETRIC_KEY_SIZE);
-}
-
-int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key)
-{
- return crypto_box_keypair(public_key, secret_key);
-}
-
-void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key)
-{
- crypto_scalarmult_curve25519_base(public_key, secret_key);
-}
-
-void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length)
-{
- crypto_hash_sha256(hash, data, length);
-}
-
-void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length)
-{
- crypto_hash_sha512(hash, data, length);
-}
-
-void random_bytes(uint8_t *data, size_t length)
-{
- randombytes(data, length);
-}
diff --git a/libs/libtox/src/toxcore/crypto_core.h b/libs/libtox/src/toxcore/crypto_core.h
deleted file mode 100644
index fc5756c1d2..0000000000
--- a/libs/libtox/src/toxcore/crypto_core.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Functions for the core crypto.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef CRYPTO_CORE_H
-#define CRYPTO_CORE_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-/**
- * The number of bytes in a Tox public key.
- */
-#define CRYPTO_PUBLIC_KEY_SIZE 32
-
-uint32_t crypto_public_key_size(void);
-
-/**
- * The number of bytes in a Tox secret key.
- */
-#define CRYPTO_SECRET_KEY_SIZE 32
-
-uint32_t crypto_secret_key_size(void);
-
-/**
- * The number of bytes in a shared key computed from public and secret keys.
- */
-#define CRYPTO_SHARED_KEY_SIZE 32
-
-uint32_t crypto_shared_key_size(void);
-
-/**
- * The number of bytes in a symmetric key.
- */
-#define CRYPTO_SYMMETRIC_KEY_SIZE CRYPTO_SHARED_KEY_SIZE
-
-uint32_t crypto_symmetric_key_size(void);
-
-/**
- * The number of bytes needed for the MAC (message authentication code) in an
- * encrypted message.
- */
-#define CRYPTO_MAC_SIZE 16
-
-uint32_t crypto_mac_size(void);
-
-/**
- * The number of bytes in a nonce used for encryption/decryption.
- */
-#define CRYPTO_NONCE_SIZE 24
-
-uint32_t crypto_nonce_size(void);
-
-/**
- * The number of bytes in a SHA256 hash.
- */
-#define CRYPTO_SHA256_SIZE 32
-
-uint32_t crypto_sha256_size(void);
-
-/**
- * The number of bytes in a SHA512 hash.
- */
-#define CRYPTO_SHA512_SIZE 64
-
-uint32_t crypto_sha512_size(void);
-
-/**
- * A `memcmp`-like function whose running time does not depend on the input
- * bytes, only on the input length. Useful to compare sensitive data where
- * timing attacks could reveal that data.
- *
- * This means for instance that comparing "aaaa" and "aaaa" takes 4 time, and
- * "aaaa" and "baaa" also takes 4 time. With a regular `memcmp`, the latter may
- * take 1 time, because it immediately knows that the two strings are not equal.
- */
-int32_t crypto_memcmp(const void *p1, const void *p2, size_t length);
-
-/**
- * A `bzero`-like function which won't be optimised away by the compiler. Some
- * compilers will inline `bzero` or `memset` if they can prove that there will
- * be no reads to the written data. Use this function if you want to be sure the
- * memory is indeed zeroed.
- */
-void crypto_memzero(void *data, size_t length);
-
-/**
- * Compute a SHA256 hash (32 bytes).
- */
-void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length);
-
-/**
- * Compute a SHA512 hash (64 bytes).
- */
-void crypto_sha512(uint8_t *hash, const uint8_t *data, size_t length);
-
-/**
- * Compare 2 public keys of length CRYPTO_PUBLIC_KEY_SIZE, not vulnerable to
- * timing attacks.
- *
- * @return 0 if both mem locations of length are equal, -1 if they are not.
- */
-int32_t public_key_cmp(const uint8_t *pk1, const uint8_t *pk2);
-
-/**
- * Return a random 32 bit integer.
- */
-uint32_t random_int(void);
-
-/**
- * Return a random 64 bit integer.
- */
-uint64_t random_64b(void);
-
-/**
- * Check if a Tox public key CRYPTO_PUBLIC_KEY_SIZE is valid or not. This
- * should only be used for input validation.
- *
- * @return false if it isn't, true if it is.
- */
-bool public_key_valid(const uint8_t *public_key);
-
-/**
- * Generate a new random keypair. Every call to this function is likely to
- * generate a different keypair.
- */
-int32_t crypto_new_keypair(uint8_t *public_key, uint8_t *secret_key);
-
-/**
- * Derive the public key from a given secret key.
- */
-void crypto_derive_public_key(uint8_t *public_key, const uint8_t *secret_key);
-
-/**
- * Encrypt plain text of the given length to encrypted of length +
- * CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of the
- * receiver and the secret key of the sender and a CRYPTO_NONCE_SIZE byte
- * nonce.
- *
- * @return -1 if there was a problem, length of encrypted data if everything
- * was fine.
- */
-int32_t encrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *plain,
- size_t length, uint8_t *encrypted);
-
-/**
- * Decrypt encrypted text of the given length to plain text of the given length
- * - CRYPTO_MAC_SIZE using the public key (CRYPTO_PUBLIC_KEY_SIZE bytes) of
- * the sender, the secret key of the receiver and a CRYPTO_NONCE_SIZE byte
- * nonce.
- *
- * @return -1 if there was a problem (decryption failed), length of plain text
- * data if everything was fine.
- */
-int32_t decrypt_data(const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *nonce,
- const uint8_t *encrypted, size_t length, uint8_t *plain);
-
-/**
- * Fast encrypt/decrypt operations. Use if this is not a one-time communication.
- * encrypt_precompute does the shared-key generation once so it does not have
- * to be preformed on every encrypt/decrypt.
- */
-int32_t encrypt_precompute(const uint8_t *public_key, const uint8_t *secret_key, uint8_t *shared_key);
-
-/**
- * Encrypts plain of length length to encrypted of length + CRYPTO_MAC_SIZE
- * using a shared key CRYPTO_SYMMETRIC_KEY_SIZE big and a CRYPTO_NONCE_SIZE
- * byte nonce.
- *
- * @return -1 if there was a problem, length of encrypted data if everything
- * was fine.
- */
-int32_t encrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *plain, size_t length,
- uint8_t *encrypted);
-
-/**
- * Decrypts encrypted of length length to plain of length length -
- * CRYPTO_MAC_SIZE using a shared key CRYPTO_SHARED_KEY_SIZE big and a
- * CRYPTO_NONCE_SIZE byte nonce.
- *
- * @return -1 if there was a problem (decryption failed), length of plain data
- * if everything was fine.
- */
-int32_t decrypt_data_symmetric(const uint8_t *shared_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length,
- uint8_t *plain);
-
-/**
- * Increment the given nonce by 1 in big endian (rightmost byte incremented
- * first).
- */
-void increment_nonce(uint8_t *nonce);
-
-/**
- * Increment the given nonce by a given number. The number should be in host
- * byte order.
- */
-void increment_nonce_number(uint8_t *nonce, uint32_t host_order_num);
-
-/**
- * Fill the given nonce with random bytes.
- */
-void random_nonce(uint8_t *nonce);
-
-/**
- * Fill a key CRYPTO_SYMMETRIC_KEY_SIZE big with random bytes.
- */
-void new_symmetric_key(uint8_t *key);
-
-/**
- * Fill an array of bytes with random values.
- */
-void random_bytes(uint8_t *bytes, size_t length);
-
-#endif /* CRYPTO_CORE_H */
diff --git a/libs/libtox/src/toxcore/crypto_core_mem.c b/libs/libtox/src/toxcore/crypto_core_mem.c
deleted file mode 100644
index b8f4223e65..0000000000
--- a/libs/libtox/src/toxcore/crypto_core_mem.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * ISC License
- *
- * Copyright (c) 2013-2016
- * Frank Denis <j at pureftpd dot org>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "crypto_core.h"
-
-#ifndef VANILLA_NACL
-/* We use libsodium by default. */
-#include <sodium.h>
-#else
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-#include <windows.h>
-#include <wincrypt.h>
-#endif
-#endif
-
-
-void crypto_memzero(void *data, size_t length)
-{
-#ifndef VANILLA_NACL
- sodium_memzero(data, length);
-#else
-#ifdef _WIN32
- SecureZeroMemory(data, length);
-#elif defined(HAVE_MEMSET_S)
-
- if (length > 0U) {
- errno_t code = memset_s(data, (rsize_t) length, 0, (rsize_t) length);
-
- if (code != 0) {
- abort(); /* LCOV_EXCL_LINE */
- }
- }
-
-#elif defined(HAVE_EXPLICIT_BZERO)
- explicit_bzero(data, length);
-#else
- volatile unsigned char *volatile pnt =
- (volatile unsigned char *volatile) data;
- size_t i = (size_t) 0U;
-
- while (i < length) {
- pnt[i++] = 0U;
- }
-
-#endif
-#endif
-}
-
-int32_t crypto_memcmp(const void *p1, const void *p2, size_t length)
-{
-#ifndef VANILLA_NACL
- return sodium_memcmp(p1, p2, length);
-#else
- const volatile unsigned char *volatile b1 =
- (const volatile unsigned char *volatile) p1;
- const volatile unsigned char *volatile b2 =
- (const volatile unsigned char *volatile) p2;
-
- size_t i;
- unsigned char d = (unsigned char) 0U;
-
- for (i = 0U; i < length; i++) {
- d |= b1[i] ^ b2[i];
- }
-
- return (1 & ((d - 1) >> 8)) - 1;
-#endif
-}
diff --git a/libs/libtox/src/toxcore/friend_connection.c b/libs/libtox/src/toxcore/friend_connection.c
deleted file mode 100644
index 9f0677b109..0000000000
--- a/libs/libtox/src/toxcore/friend_connection.c
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
- * Connection to friends.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "friend_connection.h"
-
-#include "util.h"
-
-#define PORTS_PER_DISCOVERY 10
-
-/* return 1 if the friendcon_id is not valid.
- * return 0 if the friendcon_id is valid.
- */
-static uint8_t friendconn_id_not_valid(const Friend_Connections *fr_c, int friendcon_id)
-{
- if ((unsigned int)friendcon_id >= fr_c->num_cons) {
- return 1;
- }
-
- if (fr_c->conns == NULL) {
- return 1;
- }
-
- if (fr_c->conns[friendcon_id].status == FRIENDCONN_STATUS_NONE) {
- return 1;
- }
-
- return 0;
-}
-
-
-/* Set the size of the friend connections list to num.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-static int realloc_friendconns(Friend_Connections *fr_c, uint32_t num)
-{
- if (num == 0) {
- free(fr_c->conns);
- fr_c->conns = NULL;
- return 0;
- }
-
- Friend_Conn *newgroup_cons = (Friend_Conn *)realloc(fr_c->conns, num * sizeof(Friend_Conn));
-
- if (newgroup_cons == NULL) {
- return -1;
- }
-
- fr_c->conns = newgroup_cons;
- return 0;
-}
-
-/* Create a new empty friend connection.
- *
- * return -1 on failure.
- * return friendcon_id on success.
- */
-static int create_friend_conn(Friend_Connections *fr_c)
-{
- uint32_t i;
-
- for (i = 0; i < fr_c->num_cons; ++i) {
- if (fr_c->conns[i].status == FRIENDCONN_STATUS_NONE) {
- return i;
- }
- }
-
- int id = -1;
-
- if (realloc_friendconns(fr_c, fr_c->num_cons + 1) == 0) {
- id = fr_c->num_cons;
- ++fr_c->num_cons;
- memset(&(fr_c->conns[id]), 0, sizeof(Friend_Conn));
- }
-
- return id;
-}
-
-/* Wipe a friend connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int wipe_friend_conn(Friend_Connections *fr_c, int friendcon_id)
-{
- if (friendconn_id_not_valid(fr_c, friendcon_id)) {
- return -1;
- }
-
- uint32_t i;
- memset(&(fr_c->conns[friendcon_id]), 0 , sizeof(Friend_Conn));
-
- for (i = fr_c->num_cons; i != 0; --i) {
- if (fr_c->conns[i - 1].status != FRIENDCONN_STATUS_NONE) {
- break;
- }
- }
-
- if (fr_c->num_cons != i) {
- fr_c->num_cons = i;
- realloc_friendconns(fr_c, fr_c->num_cons);
- }
-
- return 0;
-}
-
-static Friend_Conn *get_conn(const Friend_Connections *fr_c, int friendcon_id)
-{
- if (friendconn_id_not_valid(fr_c, friendcon_id)) {
- return 0;
- }
-
- return &fr_c->conns[friendcon_id];
-}
-
-/* return friendcon_id corresponding to the real public key on success.
- * return -1 on failure.
- */
-int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk)
-{
- uint32_t i;
-
- for (i = 0; i < fr_c->num_cons; ++i) {
- Friend_Conn *friend_con = get_conn(fr_c, i);
-
- if (friend_con) {
- if (public_key_cmp(friend_con->real_public_key, real_pk) == 0) {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/* Add a TCP relay associated to the friend.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- /* Local ip and same pk means that they are hosting a TCP relay. */
- if (Local_ip(ip_port.ip) && public_key_cmp(friend_con->dht_temp_pk, public_key) == 0) {
- if (friend_con->dht_ip_port.ip.family != 0) {
- ip_port.ip = friend_con->dht_ip_port.ip;
- } else {
- friend_con->hosting_tcp_relay = 0;
- }
- }
-
- unsigned int i;
-
- uint16_t index = friend_con->tcp_relay_counter % FRIEND_MAX_STORED_TCP_RELAYS;
-
- for (i = 0; i < FRIEND_MAX_STORED_TCP_RELAYS; ++i) {
- if (friend_con->tcp_relays[i].ip_port.ip.family != 0
- && public_key_cmp(friend_con->tcp_relays[i].public_key, public_key) == 0) {
- memset(&friend_con->tcp_relays[i], 0, sizeof(Node_format));
- }
- }
-
- friend_con->tcp_relays[index].ip_port = ip_port;
- memcpy(friend_con->tcp_relays[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- ++friend_con->tcp_relay_counter;
-
- return add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, public_key);
-}
-
-/* Connect to number saved relays for friend. */
-static void connect_to_saved_tcp_relays(Friend_Connections *fr_c, int friendcon_id, unsigned int number)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return;
- }
-
- unsigned int i;
-
- for (i = 0; (i < FRIEND_MAX_STORED_TCP_RELAYS) && (number != 0); ++i) {
- uint16_t index = (friend_con->tcp_relay_counter - (i + 1)) % FRIEND_MAX_STORED_TCP_RELAYS;
-
- if (friend_con->tcp_relays[index].ip_port.ip.family) {
- if (add_tcp_relay_peer(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->tcp_relays[index].ip_port,
- friend_con->tcp_relays[index].public_key) == 0) {
- --number;
- }
- }
- }
-}
-
-static unsigned int send_relays(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return 0;
- }
-
- Node_format nodes[MAX_SHARED_RELAYS];
- uint8_t data[1024];
- int n, length;
-
- n = copy_connected_tcp_relays(fr_c->net_crypto, nodes, MAX_SHARED_RELAYS);
-
- int i;
-
- for (i = 0; i < n; ++i) {
- /* Associated the relays being sent with this connection.
- On receiving the peer will do the same which will establish the connection. */
- friend_add_tcp_relay(fr_c, friendcon_id, nodes[i].ip_port, nodes[i].public_key);
- }
-
- length = pack_nodes(data + 1, sizeof(data) - 1, nodes, n);
-
- if (length <= 0) {
- return 0;
- }
-
- data[0] = PACKET_ID_SHARE_RELAYS;
- ++length;
-
- if (write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, data, length, 0) != -1) {
- friend_con->share_relays_lastsent = unix_time();
- return 1;
- }
-
- return 0;
-}
-
-/* callback for recv TCP relay nodes. */
-static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key)
-{
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
-
- if (friend_con->crypt_connection_id != -1) {
- return friend_add_tcp_relay(fr_c, number, ip_port, public_key);
- }
-
- return add_tcp_relay(fr_c->net_crypto, ip_port, public_key);
-}
-
-static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id);
-/* Callback for DHT ip_port changes. */
-static void dht_ip_callback(void *object, int32_t number, IP_Port ip_port)
-{
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return;
- }
-
- if (friend_con->crypt_connection_id == -1) {
- friend_new_connection(fr_c, number);
- }
-
- set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, ip_port, 1);
- friend_con->dht_ip_port = ip_port;
- friend_con->dht_ip_port_lastrecv = unix_time();
-
- if (friend_con->hosting_tcp_relay) {
- friend_add_tcp_relay(fr_c, number, ip_port, friend_con->dht_temp_pk);
- friend_con->hosting_tcp_relay = 0;
- }
-}
-
-static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return;
- }
-
- friend_con->dht_pk_lastrecv = unix_time();
-
- if (friend_con->dht_lock) {
- if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
- printf("a. Could not delete dht peer. Please report this.\n");
- return;
- }
-
- friend_con->dht_lock = 0;
- }
-
- DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock);
- memcpy(friend_con->dht_temp_pk, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-}
-
-static int handle_status(void *object, int number, uint8_t status, void *userdata)
-{
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
-
- bool call_cb = 0;
-
- if (status) { /* Went online. */
- call_cb = 1;
- friend_con->status = FRIENDCONN_STATUS_CONNECTED;
- friend_con->ping_lastrecv = unix_time();
- friend_con->share_relays_lastsent = 0;
- onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
- } else { /* Went offline. */
- if (friend_con->status != FRIENDCONN_STATUS_CONNECTING) {
- call_cb = 1;
- friend_con->dht_pk_lastrecv = unix_time();
- onion_set_friend_online(fr_c->onion_c, friend_con->onion_friendnum, status);
- }
-
- friend_con->status = FRIENDCONN_STATUS_CONNECTING;
- friend_con->crypt_connection_id = -1;
- friend_con->hosting_tcp_relay = 0;
- }
-
- if (call_cb) {
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
- if (friend_con->callbacks[i].status_callback) {
- friend_con->callbacks[i].status_callback(
- friend_con->callbacks[i].callback_object,
- friend_con->callbacks[i].callback_id, status, userdata);
- }
- }
- }
-
- return 0;
-}
-
-/* Callback for dht public key changes. */
-static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)
-{
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return;
- }
-
- if (public_key_cmp(friend_con->dht_temp_pk, dht_public_key) == 0) {
- return;
- }
-
- change_dht_pk(fr_c, number, dht_public_key);
-
- /* if pk changed, create a new connection.*/
- if (friend_con->crypt_connection_id != -1) {
- crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
- friend_con->crypt_connection_id = -1;
- handle_status(object, number, 0, userdata); /* Going offline. */
- }
-
- friend_new_connection(fr_c, number);
- onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
-}
-
-static int handle_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0) {
- return -1;
- }
-
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
-
- if (data[0] == PACKET_ID_FRIEND_REQUESTS) {
- if (fr_c->fr_request_callback) {
- fr_c->fr_request_callback(fr_c->fr_request_object, friend_con->real_public_key, data, length, userdata);
- }
-
- return 0;
- }
-
- if (data[0] == PACKET_ID_ALIVE) {
- friend_con->ping_lastrecv = unix_time();
- return 0;
- }
-
- if (data[0] == PACKET_ID_SHARE_RELAYS) {
- Node_format nodes[MAX_SHARED_RELAYS];
- int n;
-
- if ((n = unpack_nodes(nodes, MAX_SHARED_RELAYS, NULL, data + 1, length - 1, 1)) == -1) {
- return -1;
- }
-
- int j;
-
- for (j = 0; j < n; j++) {
- friend_add_tcp_relay(fr_c, number, nodes[j].ip_port, nodes[j].public_key);
- }
-
- return 0;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
- if (friend_con->callbacks[i].data_callback) {
- friend_con->callbacks[i].data_callback(
- friend_con->callbacks[i].callback_object,
- friend_con->callbacks[i].callback_id, data, length, userdata);
- }
-
- friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
- }
-
- return 0;
-}
-
-static int handle_lossy_packet(void *object, int number, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0) {
- return -1;
- }
-
- Friend_Connections *fr_c = (Friend_Connections *)object;
- Friend_Conn *friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_FRIEND_CONNECTION_CALLBACKS; ++i) {
- if (friend_con->callbacks[i].lossy_data_callback) {
- friend_con->callbacks[i].lossy_data_callback(
- friend_con->callbacks[i].callback_object,
- friend_con->callbacks[i].callback_id, data, length, userdata);
- }
-
- friend_con = get_conn(fr_c, number);
-
- if (!friend_con) {
- return -1;
- }
- }
-
- return 0;
-}
-
-static int handle_new_connections(void *object, New_Connection *n_c)
-{
- Friend_Connections *fr_c = (Friend_Connections *)object;
- int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key);
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (friend_con) {
-
- if (friend_con->crypt_connection_id != -1) {
- return -1;
- }
-
- int id = accept_crypto_connection(fr_c->net_crypto, n_c);
-
- if (id == -1) {
- return -1;
- }
-
- connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
- connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
- connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
- friend_con->crypt_connection_id = id;
-
- if (n_c->source.ip.family != TOX_AF_INET && n_c->source.ip.family != TOX_AF_INET6) {
- set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
- } else {
- friend_con->dht_ip_port = n_c->source;
- friend_con->dht_ip_port_lastrecv = unix_time();
- }
-
- if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) {
- change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key);
- }
-
- nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
- return 0;
- }
-
- return -1;
-}
-
-static int friend_new_connection(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- if (friend_con->crypt_connection_id != -1) {
- return -1;
- }
-
- /* If dht_temp_pk does not contains a pk. */
- if (!friend_con->dht_lock) {
- return -1;
- }
-
- int id = new_crypto_connection(fr_c->net_crypto, friend_con->real_public_key, friend_con->dht_temp_pk);
-
- if (id == -1) {
- return -1;
- }
-
- friend_con->crypt_connection_id = id;
- connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id);
- connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id);
- connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id);
- nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id);
-
- return 0;
-}
-
-static int send_ping(const Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- uint8_t ping = PACKET_ID_ALIVE;
- int64_t ret = write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, &ping, sizeof(ping), 0);
-
- if (ret != -1) {
- friend_con->ping_lastsent = unix_time();
- return 0;
- }
-
- return -1;
-}
-
-/* Increases lock_count for the connection with friendcon_id by 1.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- ++friend_con->lock_count;
- return 0;
-}
-
-/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected.
- * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.
- * return FRIENDCONN_STATUS_NONE on failure.
- */
-unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return 0;
- }
-
- return friend_con->status;
-}
-
-/* Copy public keys associated to friendcon_id.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- if (real_pk) {
- memcpy(real_pk, friend_con->real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- }
-
- if (dht_temp_pk) {
- memcpy(dht_temp_pk, friend_con->dht_temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
- }
-
- return 0;
-}
-
-/* Set temp dht key for connection.
- */
-void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata)
-{
- dht_pk_callback(fr_c, friendcon_id, dht_temp_pk, userdata);
-}
-
-/* Set the callbacks for the friend connection.
- * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
- int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
- int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
- int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
- void *object, int number)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- if (index >= MAX_FRIEND_CONNECTION_CALLBACKS) {
- return -1;
- }
-
- friend_con->callbacks[index].status_callback = status_callback;
- friend_con->callbacks[index].data_callback = data_callback;
- friend_con->callbacks[index].lossy_data_callback = lossy_data_callback;
-
- friend_con->callbacks[index].callback_object = object;
- friend_con->callbacks[index].callback_id = number;
-
- return 0;
-}
-
-/* return the crypt_connection_id for the connection.
- *
- * return crypt_connection_id on success.
- * return -1 on failure.
- */
-int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- return friend_con->crypt_connection_id;
-}
-
-/* Create a new friend connection.
- * If one to that real public key already exists, increase lock count and return it.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key)
-{
- int friendcon_id = getfriend_conn_id_pk(fr_c, real_public_key);
-
- if (friendcon_id != -1) {
- ++fr_c->conns[friendcon_id].lock_count;
- return friendcon_id;
- }
-
- friendcon_id = create_friend_conn(fr_c);
-
- if (friendcon_id == -1) {
- return -1;
- }
-
- int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key);
-
- if (onion_friendnum == -1) {
- return -1;
- }
-
- Friend_Conn *friend_con = &fr_c->conns[friendcon_id];
-
- friend_con->crypt_connection_id = -1;
- friend_con->status = FRIENDCONN_STATUS_CONNECTING;
- memcpy(friend_con->real_public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- friend_con->onion_friendnum = onion_friendnum;
-
- recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id);
- onion_dht_pk_callback(fr_c->onion_c, onion_friendnum, &dht_pk_callback, fr_c, friendcon_id);
-
- return friendcon_id;
-}
-
-/* Kill a friend connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
-{
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- if (friend_con->lock_count) {
- --friend_con->lock_count;
- return 0;
- }
-
- onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum);
- crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
-
- if (friend_con->dht_lock) {
- DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
- }
-
- return wipe_friend_conn(fr_c, friendcon_id);
-}
-
-
-/* Set friend request callback.
- *
- * This function will be called every time a friend request packet is received.
- */
-void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
- const uint8_t *, uint16_t, void *), void *object)
-{
- fr_c->fr_request_callback = fr_request_callback;
- fr_c->fr_request_object = object;
- oniondata_registerhandler(fr_c->onion_c, CRYPTO_PACKET_FRIEND_REQ, fr_request_callback, object);
-}
-
-/* Send a Friend request packet.
- *
- * return -1 if failure.
- * return 0 if it sent the friend request directly to the friend.
- * return the number of peers it was routed through if it did not send it directly.
- */
-int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
- uint16_t length)
-{
- if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) {
- return -1;
- }
-
- Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);
-
- if (!friend_con) {
- return -1;
- }
-
- VLA(uint8_t, packet, 1 + sizeof(nospam_num) + length);
- memcpy(packet + 1, &nospam_num, sizeof(nospam_num));
- memcpy(packet + 1 + sizeof(nospam_num), data, length);
-
- if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
- packet[0] = PACKET_ID_FRIEND_REQUESTS;
- return write_cryptpacket(fr_c->net_crypto, friend_con->crypt_connection_id, packet, SIZEOF_VLA(packet), 0) != -1;
- }
-
- packet[0] = CRYPTO_PACKET_FRIEND_REQ;
- int num = send_onion_data(fr_c->onion_c, friend_con->onion_friendnum, packet, SIZEOF_VLA(packet));
-
- if (num <= 0) {
- return -1;
- }
-
- return num;
-}
-
-/* Create new friend_connections instance. */
-Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled)
-{
- if (!onion_c) {
- return NULL;
- }
-
- Friend_Connections *temp = (Friend_Connections *)calloc(1, sizeof(Friend_Connections));
-
- if (temp == NULL) {
- return NULL;
- }
-
- temp->dht = onion_c->dht;
- temp->net_crypto = onion_c->c;
- temp->onion_c = onion_c;
- temp->local_discovery_enabled = local_discovery_enabled;
- // Don't include default port in port range
- temp->next_LANport = TOX_PORTRANGE_FROM + 1;
-
- new_connection_handler(temp->net_crypto, &handle_new_connections, temp);
-
- if (temp->local_discovery_enabled) {
- LANdiscovery_init(temp->dht);
- }
-
- return temp;
-}
-
-/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
-static void LANdiscovery(Friend_Connections *fr_c)
-{
- if (fr_c->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
- const uint16_t first = fr_c->next_LANport;
- uint16_t last = first + PORTS_PER_DISCOVERY;
- last = last > TOX_PORTRANGE_TO ? TOX_PORTRANGE_TO : last;
-
- // Always send to default port
- send_LANdiscovery(net_htons(TOX_PORT_DEFAULT), fr_c->dht);
-
- // And check some extra ports
- for (uint16_t port = first; port < last; port++) {
- send_LANdiscovery(net_htons(port), fr_c->dht);
- }
-
- // Don't include default port in port range
- fr_c->next_LANport = last != TOX_PORTRANGE_TO ? last : TOX_PORTRANGE_FROM + 1;
- fr_c->last_LANdiscovery = unix_time();
- }
-}
-
-/* main friend_connections loop. */
-void do_friend_connections(Friend_Connections *fr_c, void *userdata)
-{
- uint32_t i;
- uint64_t temp_time = unix_time();
-
- for (i = 0; i < fr_c->num_cons; ++i) {
- Friend_Conn *friend_con = get_conn(fr_c, i);
-
- if (friend_con) {
- if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
- if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
- if (friend_con->dht_lock) {
- DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
- friend_con->dht_lock = 0;
- memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
- }
- }
-
- if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
- friend_con->dht_ip_port.ip.family = 0;
- }
-
- if (friend_con->dht_lock) {
- if (friend_new_connection(fr_c, i) == 0) {
- set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
- connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
- }
- }
- } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
- if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
- send_ping(fr_c, i);
- }
-
- if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
- send_relays(fr_c, i);
- }
-
- if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
- /* If we stopped receiving ping packets, kill it. */
- crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
- friend_con->crypt_connection_id = -1;
- handle_status(fr_c, i, 0, userdata); /* Going offline. */
- }
- }
- }
- }
-
- if (fr_c->local_discovery_enabled) {
- LANdiscovery(fr_c);
- }
-}
-
-/* Free everything related with friend_connections. */
-void kill_friend_connections(Friend_Connections *fr_c)
-{
- if (!fr_c) {
- return;
- }
-
- uint32_t i;
-
- for (i = 0; i < fr_c->num_cons; ++i) {
- kill_friend_connection(fr_c, i);
- }
-
- if (fr_c->local_discovery_enabled) {
- LANdiscovery_kill(fr_c->dht);
- }
-
- free(fr_c);
-}
diff --git a/libs/libtox/src/toxcore/friend_connection.h b/libs/libtox/src/toxcore/friend_connection.h
deleted file mode 100644
index e993a103d3..0000000000
--- a/libs/libtox/src/toxcore/friend_connection.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Connection to friends.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef FRIEND_CONNECTION_H
-#define FRIEND_CONNECTION_H
-
-#include "DHT.h"
-#include "LAN_discovery.h"
-#include "net_crypto.h"
-#include "onion_client.h"
-
-#define MAX_FRIEND_CONNECTION_CALLBACKS 2
-#define MESSENGER_CALLBACK_INDEX 0
-#define GROUPCHAT_CALLBACK_INDEX 1
-
-#define PACKET_ID_ALIVE 16
-#define PACKET_ID_SHARE_RELAYS 17
-#define PACKET_ID_FRIEND_REQUESTS 18
-
-/* Interval between the sending of ping packets. */
-#define FRIEND_PING_INTERVAL 8
-
-/* If no packets are received from friend in this time interval, kill the connection. */
-#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 4)
-
-/* Time before friend is removed from the DHT after last hearing about him. */
-#define FRIEND_DHT_TIMEOUT BAD_NODE_TIMEOUT
-
-#define FRIEND_MAX_STORED_TCP_RELAYS (MAX_FRIEND_TCP_CONNECTIONS * 4)
-
-/* Max number of tcp relays sent to friends */
-#define MAX_SHARED_RELAYS (RECOMMENDED_FRIEND_TCP_CONNECTIONS)
-
-/* Interval between the sending of tcp relay information */
-#define SHARE_RELAYS_INTERVAL (5 * 60)
-
-
-enum {
- FRIENDCONN_STATUS_NONE,
- FRIENDCONN_STATUS_CONNECTING,
- FRIENDCONN_STATUS_CONNECTED
-};
-
-typedef struct {
- uint8_t status;
-
- uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint16_t dht_lock;
- IP_Port dht_ip_port;
- uint64_t dht_pk_lastrecv, dht_ip_port_lastrecv;
-
- int onion_friendnum;
- int crypt_connection_id;
-
- uint64_t ping_lastrecv, ping_lastsent;
- uint64_t share_relays_lastsent;
-
- struct {
- int (*status_callback)(void *object, int id, uint8_t status, void *userdata);
- int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
- int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
-
- void *callback_object;
- int callback_id;
- } callbacks[MAX_FRIEND_CONNECTION_CALLBACKS];
-
- uint16_t lock_count;
-
- Node_format tcp_relays[FRIEND_MAX_STORED_TCP_RELAYS];
- uint16_t tcp_relay_counter;
-
- bool hosting_tcp_relay;
-} Friend_Conn;
-
-
-typedef struct {
- Net_Crypto *net_crypto;
- DHT *dht;
- Onion_Client *onion_c;
-
- Friend_Conn *conns;
- uint32_t num_cons;
-
- int (*fr_request_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t len,
- void *userdata);
- void *fr_request_object;
-
- uint64_t last_LANdiscovery;
- uint16_t next_LANport;
-
- bool local_discovery_enabled;
-} Friend_Connections;
-
-/* return friendcon_id corresponding to the real public key on success.
- * return -1 on failure.
- */
-int getfriend_conn_id_pk(Friend_Connections *fr_c, const uint8_t *real_pk);
-
-/* Increases lock_count for the connection with friendcon_id by 1.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int friend_connection_lock(Friend_Connections *fr_c, int friendcon_id);
-
-/* return FRIENDCONN_STATUS_CONNECTED if the friend is connected.
- * return FRIENDCONN_STATUS_CONNECTING if the friend isn't connected.
- * return FRIENDCONN_STATUS_NONE on failure.
- */
-unsigned int friend_con_connected(Friend_Connections *fr_c, int friendcon_id);
-
-/* Copy public keys associated to friendcon_id.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int get_friendcon_public_keys(uint8_t *real_pk, uint8_t *dht_temp_pk, Friend_Connections *fr_c, int friendcon_id);
-
-/* Set temp dht key for connection.
- */
-void set_dht_temp_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_temp_pk, void *userdata);
-
-/* Add a TCP relay associated to the friend.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int friend_add_tcp_relay(Friend_Connections *fr_c, int friendcon_id, IP_Port ip_port, const uint8_t *public_key);
-
-/* Set the callbacks for the friend connection.
- * index is the index (0 to (MAX_FRIEND_CONNECTION_CALLBACKS - 1)) we want the callback to set in the array.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int friend_connection_callbacks(Friend_Connections *fr_c, int friendcon_id, unsigned int index,
- int (*status_callback)(void *object, int id, uint8_t status, void *userdata),
- int (*data_callback)(void *object, int id, const uint8_t *data, uint16_t len, void *userdata),
- int (*lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
- void *object, int number);
-
-/* return the crypt_connection_id for the connection.
- *
- * return crypt_connection_id on success.
- * return -1 on failure.
- */
-int friend_connection_crypt_connection_id(Friend_Connections *fr_c, int friendcon_id);
-
-/* Create a new friend connection.
- * If one to that real public key already exists, increase lock count and return it.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key);
-
-/* Kill a friend connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id);
-
-/* Send a Friend request packet.
- *
- * return -1 if failure.
- * return 0 if it sent the friend request directly to the friend.
- * return the number of peers it was routed through if it did not send it directly.
- */
-int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
- uint16_t length);
-
-/* Set friend request callback.
- *
- * This function will be called every time a friend request is received.
- */
-void set_friend_request_callback(Friend_Connections *fr_c, int (*fr_request_callback)(void *, const uint8_t *,
- const uint8_t *, uint16_t, void *), void *object);
-
-/* Create new friend_connections instance. */
-Friend_Connections *new_friend_connections(Onion_Client *onion_c, bool local_discovery_enabled);
-
-/* main friend_connections loop. */
-void do_friend_connections(Friend_Connections *fr_c, void *userdata);
-
-/* Free everything related with friend_connections. */
-void kill_friend_connections(Friend_Connections *fr_c);
-
-#endif
diff --git a/libs/libtox/src/toxcore/friend_requests.c b/libs/libtox/src/toxcore/friend_requests.c
deleted file mode 100644
index ba782e2b01..0000000000
--- a/libs/libtox/src/toxcore/friend_requests.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Handle friend requests.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "friend_requests.h"
-
-#include "util.h"
-
-/* Set and get the nospam variable used to prevent one type of friend request spam. */
-void set_nospam(Friend_Requests *fr, uint32_t num)
-{
- fr->nospam = num;
-}
-
-uint32_t get_nospam(const Friend_Requests *fr)
-{
- return fr->nospam;
-}
-
-
-/* Set the function that will be executed when a friend request is received. */
-void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
- void *), void *object)
-{
- fr->handle_friendrequest = function;
- fr->handle_friendrequest_isset = 1;
- fr->handle_friendrequest_object = object;
-}
-/* Set the function used to check if a friend request should be displayed to the user or not. */
-void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata)
-{
- fr->filter_function = function;
- fr->filter_function_userdata = userdata;
-}
-
-/* Add to list of received friend requests. */
-static void addto_receivedlist(Friend_Requests *fr, const uint8_t *real_pk)
-{
- if (fr->received_requests_index >= MAX_RECEIVED_STORED) {
- fr->received_requests_index = 0;
- }
-
- id_copy(fr->received_requests[fr->received_requests_index], real_pk);
- ++fr->received_requests_index;
-}
-
-/* Check if a friend request was already received.
- *
- * return 0 if it did not.
- * return 1 if it did.
- */
-static int request_received(Friend_Requests *fr, const uint8_t *real_pk)
-{
- uint32_t i;
-
- for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
- if (id_equal(fr->received_requests[i], real_pk)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Remove real pk from received_requests list.
- *
- * return 0 if it removed it successfully.
- * return -1 if it didn't find it.
- */
-int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk)
-{
- uint32_t i;
-
- for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
- if (id_equal(fr->received_requests[i], real_pk)) {
- crypto_memzero(fr->received_requests[i], CRYPTO_PUBLIC_KEY_SIZE);
- return 0;
- }
- }
-
- return -1;
-}
-
-
-static int friendreq_handlepacket(void *object, const uint8_t *source_pubkey, const uint8_t *packet, uint16_t length,
- void *userdata)
-{
- Friend_Requests *fr = (Friend_Requests *)object;
-
- if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) {
- return 1;
- }
-
- ++packet;
- --length;
-
- if (fr->handle_friendrequest_isset == 0) {
- return 1;
- }
-
- if (request_received(fr, source_pubkey)) {
- return 1;
- }
-
- if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0) {
- return 1;
- }
-
- if (fr->filter_function) {
- if ((*fr->filter_function)(source_pubkey, fr->filter_function_userdata) != 0) {
- return 1;
- }
- }
-
- addto_receivedlist(fr, source_pubkey);
-
- uint32_t message_len = length - sizeof(fr->nospam);
- VLA(uint8_t, message, message_len + 1);
- memcpy(message, packet + sizeof(fr->nospam), message_len);
- message[SIZEOF_VLA(message) - 1] = 0; /* Be sure the message is null terminated. */
-
- (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len, userdata);
- return 0;
-}
-
-void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c)
-{
- set_friend_request_callback(fr_c, &friendreq_handlepacket, fr);
-}
diff --git a/libs/libtox/src/toxcore/friend_requests.h b/libs/libtox/src/toxcore/friend_requests.h
deleted file mode 100644
index 316e1c671f..0000000000
--- a/libs/libtox/src/toxcore/friend_requests.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Handle friend requests.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef FRIEND_REQUESTS_H
-#define FRIEND_REQUESTS_H
-
-#include "friend_connection.h"
-
-#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t)))
-
-typedef struct {
- uint32_t nospam;
- void (*handle_friendrequest)(void *, const uint8_t *, const uint8_t *, size_t, void *);
- uint8_t handle_friendrequest_isset;
- void *handle_friendrequest_object;
-
- int (*filter_function)(const uint8_t *, void *);
- void *filter_function_userdata;
- /* NOTE: The following is just a temporary fix for the multiple friend requests received at the same time problem.
- * TODO(irungentoo): Make this better (This will most likely tie in with the way we will handle spam.)
- */
-
-#define MAX_RECEIVED_STORED 32
-
- uint8_t received_requests[MAX_RECEIVED_STORED][CRYPTO_PUBLIC_KEY_SIZE];
- uint16_t received_requests_index;
-} Friend_Requests;
-
-/* Set and get the nospam variable used to prevent one type of friend request spam. */
-void set_nospam(Friend_Requests *fr, uint32_t num);
-uint32_t get_nospam(const Friend_Requests *fr);
-
-/* Remove real_pk from received_requests list.
- *
- * return 0 if it removed it successfully.
- * return -1 if it didn't find it.
- */
-int remove_request_received(Friend_Requests *fr, const uint8_t *real_pk);
-
-/* Set the function that will be executed when a friend request for us is received.
- * Function format is function(uint8_t * public_key, uint8_t * data, size_t length, void * userdata)
- */
-void callback_friendrequest(Friend_Requests *fr, void (*function)(void *, const uint8_t *, const uint8_t *, size_t,
- void *), void *object);
-
-/* Set the function used to check if a friend request should be displayed to the user or not.
- * Function format is int function(uint8_t * public_key, void * userdata)
- * It must return 0 if the request is ok (anything else if it is bad.)
- */
-void set_filter_function(Friend_Requests *fr, int (*function)(const uint8_t *, void *), void *userdata);
-
-/* Sets up friendreq packet handlers. */
-void friendreq_init(Friend_Requests *fr, Friend_Connections *fr_c);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/group.c b/libs/libtox/src/toxcore/group.c
deleted file mode 100644
index d3f068dfce..0000000000
--- a/libs/libtox/src/toxcore/group.c
+++ /dev/null
@@ -1,2544 +0,0 @@
-/*
- * Slightly better groupchats implementation.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "group.h"
-
-#include "util.h"
-
-/* return 1 if the groupnumber is not valid.
- * return 0 if the groupnumber is valid.
- */
-static uint8_t groupnumber_not_valid(const Group_Chats *g_c, int groupnumber)
-{
- if ((unsigned int)groupnumber >= g_c->num_chats) {
- return 1;
- }
-
- if (g_c->chats == NULL) {
- return 1;
- }
-
- if (g_c->chats[groupnumber].status == GROUPCHAT_STATUS_NONE) {
- return 1;
- }
-
- return 0;
-}
-
-
-/* Set the size of the groupchat list to num.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-static int realloc_groupchats(Group_Chats *g_c, uint32_t num)
-{
- if (num == 0) {
- free(g_c->chats);
- g_c->chats = NULL;
- return 0;
- }
-
- Group_c *newgroup_chats = (Group_c *)realloc(g_c->chats, num * sizeof(Group_c));
-
- if (newgroup_chats == NULL) {
- return -1;
- }
-
- g_c->chats = newgroup_chats;
- return 0;
-}
-
-
-/* Create a new empty groupchat connection.
- *
- * return -1 on failure.
- * return groupnumber on success.
- */
-static int create_group_chat(Group_Chats *g_c)
-{
- uint32_t i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- if (g_c->chats[i].status == GROUPCHAT_STATUS_NONE) {
- return i;
- }
- }
-
- int id = -1;
-
- if (realloc_groupchats(g_c, g_c->num_chats + 1) == 0) {
- id = g_c->num_chats;
- ++g_c->num_chats;
- memset(&(g_c->chats[id]), 0, sizeof(Group_c));
- }
-
- return id;
-}
-
-
-/* Wipe a groupchat.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int wipe_group_chat(Group_Chats *g_c, int groupnumber)
-{
- if (groupnumber_not_valid(g_c, groupnumber)) {
- return -1;
- }
-
- uint32_t i;
- crypto_memzero(&(g_c->chats[groupnumber]), sizeof(Group_c));
-
- for (i = g_c->num_chats; i != 0; --i) {
- if (g_c->chats[i - 1].status != GROUPCHAT_STATUS_NONE) {
- break;
- }
- }
-
- if (g_c->num_chats != i) {
- g_c->num_chats = i;
- realloc_groupchats(g_c, g_c->num_chats);
- }
-
- return 0;
-}
-
-static Group_c *get_group_c(const Group_Chats *g_c, int groupnumber)
-{
- if (groupnumber_not_valid(g_c, groupnumber)) {
- return 0;
- }
-
- return &g_c->chats[groupnumber];
-}
-
-/*
- * check if peer with real_pk is in peer array.
- *
- * return peer index if peer is in chat.
- * return -1 if peer is not in chat.
- *
- * TODO(irungentoo): make this more efficient.
- */
-
-static int peer_in_chat(const Group_c *chat, const uint8_t *real_pk)
-{
- uint32_t i;
-
- for (i = 0; i < chat->numpeers; ++i) {
- if (id_equal(chat->group[i].real_pk, real_pk)) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * check if group with identifier is in group array.
- *
- * return group number if peer is in list.
- * return -1 if group is not in list.
- *
- * TODO(irungentoo): make this more efficient and maybe use constant time comparisons?
- */
-static int get_group_num(const Group_Chats *g_c, const uint8_t *identifier)
-{
- uint32_t i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- if (crypto_memcmp(g_c->chats[i].identifier, identifier, GROUP_IDENTIFIER_LENGTH) == 0) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * check if peer with peer_number is in peer array.
- *
- * return peer number if peer is in chat.
- * return -1 if peer is not in chat.
- *
- * TODO(irungentoo): make this more efficient.
- */
-static int get_peer_index(Group_c *g, uint16_t peer_number)
-{
- uint32_t i;
-
- for (i = 0; i < g->numpeers; ++i) {
- if (g->group[i].peer_number == peer_number) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-static uint64_t calculate_comp_value(const uint8_t *pk1, const uint8_t *pk2)
-{
- uint64_t cmp1 = 0, cmp2 = 0;
-
- unsigned int i;
-
- for (i = 0; i < sizeof(uint64_t); ++i) {
- cmp1 = (cmp1 << 8) + (uint64_t)pk1[i];
- cmp2 = (cmp2 << 8) + (uint64_t)pk2[i];
- }
-
- return (cmp1 - cmp2);
-}
-
-enum {
- GROUPCHAT_CLOSEST_NONE,
- GROUPCHAT_CLOSEST_ADDED,
- GROUPCHAT_CLOSEST_REMOVED
-};
-
-static int friend_in_close(Group_c *g, int friendcon_id);
-static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock);
-
-static int add_to_closest(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (public_key_cmp(g->real_pk, real_pk) == 0) {
- return -1;
- }
-
- unsigned int i;
- unsigned int index = DESIRED_CLOSE_CONNECTIONS;
-
- for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
- if (g->closest_peers[i].entry && public_key_cmp(real_pk, g->closest_peers[i].real_pk) == 0) {
- return 0;
- }
- }
-
- for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
- if (g->closest_peers[i].entry == 0) {
- index = i;
- break;
- }
- }
-
- if (index == DESIRED_CLOSE_CONNECTIONS) {
- uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);
- uint64_t comp_d = 0;
-
- for (i = 0; i < (DESIRED_CLOSE_CONNECTIONS / 2); ++i) {
- uint64_t comp;
- comp = calculate_comp_value(g->real_pk, g->closest_peers[i].real_pk);
-
- if (comp > comp_val && comp > comp_d) {
- index = i;
- comp_d = comp;
- }
- }
-
- comp_val = calculate_comp_value(real_pk, g->real_pk);
-
- for (i = (DESIRED_CLOSE_CONNECTIONS / 2); i < DESIRED_CLOSE_CONNECTIONS; ++i) {
- uint64_t comp = calculate_comp_value(g->closest_peers[i].real_pk, g->real_pk);
-
- if (comp > comp_val && comp > comp_d) {
- index = i;
- comp_d = comp;
- }
- }
- }
-
- if (index == DESIRED_CLOSE_CONNECTIONS) {
- return -1;
- }
-
- uint8_t old_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t old_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t old = 0;
-
- if (g->closest_peers[index].entry) {
- memcpy(old_real_pk, g->closest_peers[index].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(old_temp_pk, g->closest_peers[index].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
- old = 1;
- }
-
- g->closest_peers[index].entry = 1;
- memcpy(g->closest_peers[index].real_pk, real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(g->closest_peers[index].temp_pk, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
-
- if (old) {
- add_to_closest(g_c, groupnumber, old_real_pk, old_temp_pk);
- }
-
- if (!g->changed) {
- g->changed = GROUPCHAT_CLOSEST_ADDED;
- }
-
- return 0;
-}
-
-static unsigned int pk_in_closest_peers(Group_c *g, uint8_t *real_pk)
-{
- unsigned int i;
-
- for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
- if (!g->closest_peers[i].entry) {
- continue;
- }
-
- if (public_key_cmp(g->closest_peers[i].real_pk, real_pk) == 0) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier);
-
-static int connect_to_closest(Group_Chats *g_c, int groupnumber, void *userdata)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (!g->changed) {
- return 0;
- }
-
- unsigned int i;
-
- if (g->changed == GROUPCHAT_CLOSEST_REMOVED) {
- for (i = 0; i < g->numpeers; ++i) {
- add_to_closest(g_c, groupnumber, g->group[i].real_pk, g->group[i].temp_pk);
- }
- }
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- continue;
- }
-
- if (!g->close[i].closest) {
- continue;
- }
-
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number);
-
- if (!pk_in_closest_peers(g, real_pk)) {
- g->close[i].type = GROUPCHAT_CLOSE_NONE;
- kill_friend_connection(g_c->fr_c, g->close[i].number);
- }
- }
-
- for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) {
- if (!g->closest_peers[i].entry) {
- continue;
- }
-
- int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk);
-
- uint8_t lock = 1;
-
- if (friendcon_id == -1) {
- friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk);
- lock = 0;
-
- if (friendcon_id == -1) {
- continue;
- }
-
- set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk, userdata);
- }
-
- add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1, lock);
-
- if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) {
- send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
- }
- }
-
- g->changed = GROUPCHAT_CLOSEST_NONE;
-
- return 0;
-}
-
-/* Add a peer to the group chat.
- *
- * do_gc_callback indicates whether we want to trigger callbacks set by the client
- * via the public API. This should be set to false if this function is called
- * from outside of the tox_iterate() loop.
- *
- * return peer_index if success or peer already in chat.
- * return -1 if error.
- */
-static int addpeer(Group_Chats *g_c, int groupnumber, const uint8_t *real_pk, const uint8_t *temp_pk,
- uint16_t peer_number, void *userdata, bool do_gc_callback)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- // TODO(irungentoo):
- int peer_index = peer_in_chat(g, real_pk);
-
- if (peer_index != -1) {
- id_copy(g->group[peer_index].temp_pk, temp_pk);
-
- if (g->group[peer_index].peer_number != peer_number) {
- return -1;
- }
-
- return peer_index;
- }
-
- peer_index = get_peer_index(g, peer_number);
-
- if (peer_index != -1) {
- return -1;
- }
-
- Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers + 1));
-
- if (temp == NULL) {
- return -1;
- }
-
- memset(&(temp[g->numpeers]), 0, sizeof(Group_Peer));
- g->group = temp;
-
- id_copy(g->group[g->numpeers].real_pk, real_pk);
- id_copy(g->group[g->numpeers].temp_pk, temp_pk);
- g->group[g->numpeers].peer_number = peer_number;
-
- g->group[g->numpeers].last_recv = unix_time();
- ++g->numpeers;
-
- add_to_closest(g_c, groupnumber, real_pk, temp_pk);
-
- if (do_gc_callback && g_c->group_namelistchange) {
- g_c->group_namelistchange(g_c->m, groupnumber, g->numpeers - 1, CHAT_CHANGE_PEER_ADD, userdata);
- }
-
- if (g->peer_on_join) {
- g->peer_on_join(g->object, groupnumber, g->numpeers - 1);
- }
-
- return (g->numpeers - 1);
-}
-
-static int remove_close_conn(Group_Chats *g_c, int groupnumber, int friendcon_id)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint32_t i;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- continue;
- }
-
- if (g->close[i].number == (unsigned int)friendcon_id) {
- g->close[i].type = GROUPCHAT_CLOSE_NONE;
- kill_friend_connection(g_c->fr_c, friendcon_id);
- return 0;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Delete a peer from the group chat.
- *
- * return 0 if success
- * return -1 if error.
- */
-static int delpeer(Group_Chats *g_c, int groupnumber, int peer_index, void *userdata)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint32_t i;
-
- for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { /* If peer is in closest_peers list, remove it. */
- if (g->closest_peers[i].entry && id_equal(g->closest_peers[i].real_pk, g->group[peer_index].real_pk)) {
- g->closest_peers[i].entry = 0;
- g->changed = GROUPCHAT_CLOSEST_REMOVED;
- break;
- }
- }
-
- int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->group[peer_index].real_pk);
-
- if (friendcon_id != -1) {
- remove_close_conn(g_c, groupnumber, friendcon_id);
- }
-
- --g->numpeers;
-
- void *peer_object = g->group[peer_index].object;
-
- if (g->numpeers == 0) {
- free(g->group);
- g->group = NULL;
- } else {
- if (g->numpeers != (uint32_t)peer_index) {
- memcpy(&g->group[peer_index], &g->group[g->numpeers], sizeof(Group_Peer));
- }
-
- Group_Peer *temp = (Group_Peer *)realloc(g->group, sizeof(Group_Peer) * (g->numpeers));
-
- if (temp == NULL) {
- return -1;
- }
-
- g->group = temp;
- }
-
- if (g_c->group_namelistchange) {
- g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_DEL, userdata);
- }
-
- if (g->peer_on_leave) {
- g->peer_on_leave(g->object, groupnumber, peer_index, peer_object);
- }
-
- return 0;
-}
-
-/* Set the nick for a peer.
- *
- * do_gc_callback indicates whether we want to trigger callbacks set by the client
- * via the public API. This should be set to false if this function is called
- * from outside of the tox_iterate() loop.
- *
- * return 0 on success.
- * return -1 if error.
- */
-static int setnick(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *nick, uint16_t nick_len,
- void *userdata, bool do_gc_callback)
-{
- if (nick_len > MAX_NAME_LENGTH) {
- return -1;
- }
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- /* same name as already stored? */
- if (g->group[peer_index].nick_len == nick_len) {
- if (nick_len == 0 || !memcmp(g->group[peer_index].nick, nick, nick_len)) {
- return 0;
- }
- }
-
- if (nick_len) {
- memcpy(g->group[peer_index].nick, nick, nick_len);
- }
-
- g->group[peer_index].nick_len = nick_len;
-
- if (do_gc_callback && g_c->group_namelistchange) {
- g_c->group_namelistchange(g_c->m, groupnumber, peer_index, CHAT_CHANGE_PEER_NAME, userdata);
- }
-
- return 0;
-}
-
-static int settitle(Group_Chats *g_c, int groupnumber, int peer_index, const uint8_t *title, uint8_t title_len,
- void *userdata)
-{
- if (title_len > MAX_NAME_LENGTH || title_len == 0) {
- return -1;
- }
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- /* same as already set? */
- if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
- return 0;
- }
-
- memcpy(g->title, title, title_len);
- g->title_len = title_len;
-
- if (g_c->title_callback) {
- g_c->title_callback(g_c->m, groupnumber, peer_index, title, title_len, userdata);
- }
-
- return 0;
-}
-
-static void set_conns_type_close(Group_Chats *g_c, int groupnumber, int friendcon_id, uint8_t type)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return;
- }
-
- uint32_t i;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- continue;
- }
-
- if (g->close[i].number != (unsigned int)friendcon_id) {
- continue;
- }
-
- if (type == GROUPCHAT_CLOSE_ONLINE) {
- send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
- } else {
- g->close[i].type = type;
- }
- }
-}
-/* Set the type for all close connections with friendcon_id */
-static void set_conns_status_groups(Group_Chats *g_c, int friendcon_id, uint8_t type)
-{
- uint32_t i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- set_conns_type_close(g_c, i, friendcon_id, type);
- }
-}
-
-static int g_handle_status(void *object, int friendcon_id, uint8_t status, void *userdata)
-{
- Group_Chats *g_c = (Group_Chats *)object;
-
- if (status) { /* Went online */
- set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_ONLINE);
- } else { /* Went offline */
- set_conns_status_groups(g_c, friendcon_id, GROUPCHAT_CLOSE_CONNECTION);
- // TODO(irungentoo): remove timedout connections?
- }
-
- return 0;
-}
-
-static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
-static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata);
-
-/* Add friend to group chat.
- *
- * return close index on success
- * return -1 on failure.
- */
-static int add_conn_to_groupchat(Group_Chats *g_c, int friendcon_id, int groupnumber, uint8_t closest, uint8_t lock)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint16_t i, ind = MAX_GROUP_CONNECTIONS;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- ind = i;
- continue;
- }
-
- if (g->close[i].number == (uint32_t)friendcon_id) {
- g->close[i].closest = closest;
- return i; /* Already in list. */
- }
- }
-
- if (ind == MAX_GROUP_CONNECTIONS) {
- return -1;
- }
-
- if (lock) {
- friend_connection_lock(g_c->fr_c, friendcon_id);
- }
-
- g->close[ind].type = GROUPCHAT_CLOSE_CONNECTION;
- g->close[ind].number = friendcon_id;
- g->close[ind].closest = closest;
- // TODO(irungentoo):
- friend_connection_callbacks(g_c->m->fr_c, friendcon_id, GROUPCHAT_CALLBACK_INDEX, &g_handle_status, &g_handle_packet,
- &handle_lossy, g_c, friendcon_id);
-
- return ind;
-}
-
-/* Creates a new groupchat and puts it in the chats array.
- *
- * type is one of GROUPCHAT_TYPE_*
- *
- * return group number on success.
- * return -1 on failure.
- */
-int add_groupchat(Group_Chats *g_c, uint8_t type)
-{
- int groupnumber = create_group_chat(g_c);
-
- if (groupnumber == -1) {
- return -1;
- }
-
- Group_c *g = &g_c->chats[groupnumber];
-
- g->status = GROUPCHAT_STATUS_CONNECTED;
- g->number_joined = -1;
- new_symmetric_key(g->identifier + 1);
- g->identifier[0] = type;
- g->peer_number = 0; /* Founder is peer 0. */
- memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- int peer_index = addpeer(g_c, groupnumber, g->real_pk, g_c->m->dht->self_public_key, 0, NULL, false);
-
- if (peer_index == -1) {
- return -1;
- }
-
- setnick(g_c, groupnumber, peer_index, g_c->m->name, g_c->m->name_length, NULL, false);
-
- return groupnumber;
-}
-
-static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num);
-/* Delete a groupchat from the chats array.
- *
- * return 0 on success.
- * return -1 if groupnumber is invalid.
- */
-int del_groupchat(Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- group_kill_peer_send(g_c, groupnumber, g->peer_number);
-
- unsigned int i;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- continue;
- }
-
- g->close[i].type = GROUPCHAT_CLOSE_NONE;
- kill_friend_connection(g_c->fr_c, g->close[i].number);
- }
-
- for (i = 0; i < g->numpeers; ++i) {
- if (g->peer_on_leave) {
- g->peer_on_leave(g->object, groupnumber, i, g->group[i].object);
- }
- }
-
- free(g->group);
-
- if (g->group_on_delete) {
- g->group_on_delete(g->object, groupnumber);
- }
-
- return wipe_group_chat(g_c, groupnumber);
-}
-
-/* Copy the public key of peernumber who is in groupnumber to pk.
- * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
- *
- * return 0 on success
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return -2;
- }
-
- memcpy(pk, g->group[peernumber].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- return 0;
-}
-
-/*
- * Return the size of peernumber's name.
- *
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return -2;
- }
-
- if (g->group[peernumber].nick_len == 0) {
- return 8;
- }
-
- return g->group[peernumber].nick_len;
-}
-
-/* Copy the name of peernumber who is in groupnumber to name.
- * name must be at least MAX_NAME_LENGTH long.
- *
- * return length of name if success
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return -2;
- }
-
- if (g->group[peernumber].nick_len == 0) {
- memcpy(name, "Tox User", 8);
- return 8;
- }
-
- memcpy(name, g->group[peernumber].nick, g->group[peernumber].nick_len);
- return g->group[peernumber].nick_len;
-}
-
-/* List all the peers in the group chat.
- *
- * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array.
- *
- * Copies the lengths of the names to lengths[length]
- *
- * returns the number of peers on success.
- *
- * return -1 on failure.
- */
-int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
- uint16_t length)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < g->numpeers && i < length; ++i) {
- lengths[i] = group_peername(g_c, groupnumber, i, names[i]);
- }
-
- return i;
-}
-
-/* Return the number of peers in the group chat on success.
- * return -1 if groupnumber is invalid.
- */
-int group_number_peers(const Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- return g->numpeers;
-}
-
-/* return 1 if the peernumber corresponds to ours.
- * return 0 if the peernumber is not ours.
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- * return -3 if we are not connected to the group chat.
- */
-int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return -2;
- }
-
- if (g->status != GROUPCHAT_STATUS_CONNECTED) {
- return -3;
- }
-
- return g->peer_number == g->group[peernumber].peer_number;
-}
-
-/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.
- *
- * return -1 on failure.
- * return type on success.
- */
-int group_get_type(const Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- return g->identifier[0];
-}
-
-/* Send a group packet to friendcon_id.
- *
- * return 1 on success
- * return 0 on failure
- */
-static unsigned int send_packet_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
- uint16_t group_num, const uint8_t *data, uint16_t length)
-{
- if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
- return 0;
- }
-
- group_num = net_htons(group_num);
- VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
- packet[0] = packet_id;
- memcpy(packet + 1, &group_num, sizeof(uint16_t));
- memcpy(packet + 1 + sizeof(uint16_t), data, length);
- return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
- SIZEOF_VLA(packet), 0) != -1;
-}
-
-/* Send a group lossy packet to friendcon_id.
- *
- * return 1 on success
- * return 0 on failure
- */
-static unsigned int send_lossy_group_peer(Friend_Connections *fr_c, int friendcon_id, uint8_t packet_id,
- uint16_t group_num, const uint8_t *data, uint16_t length)
-{
- if (1 + sizeof(uint16_t) + length > MAX_CRYPTO_DATA_SIZE) {
- return 0;
- }
-
- group_num = net_htons(group_num);
- VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length);
- packet[0] = packet_id;
- memcpy(packet + 1, &group_num, sizeof(uint16_t));
- memcpy(packet + 1 + sizeof(uint16_t), data, length);
- return send_lossy_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
- SIZEOF_VLA(packet)) != -1;
-}
-
-#define INVITE_PACKET_SIZE (1 + sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
-#define INVITE_ID 0
-
-#define INVITE_RESPONSE_PACKET_SIZE (1 + sizeof(uint16_t) * 2 + GROUP_IDENTIFIER_LENGTH)
-#define INVITE_RESPONSE_ID 1
-
-/* invite friendnumber to groupnumber.
- *
- * return 0 on success.
- * return -1 if groupnumber is invalid.
- * return -2 if invite packet failed to send.
- */
-int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint8_t invite[INVITE_PACKET_SIZE];
- invite[0] = INVITE_ID;
- uint16_t groupchat_num = net_htons((uint16_t)groupnumber);
- memcpy(invite + 1, &groupchat_num, sizeof(groupchat_num));
- memcpy(invite + 1 + sizeof(groupchat_num), g->identifier, GROUP_IDENTIFIER_LENGTH);
-
- if (send_conference_invite_packet(g_c->m, friendnumber, invite, sizeof(invite))) {
- return 0;
- }
-
- wipe_group_chat(g_c, groupnumber);
- return -2;
-}
-
-static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
-
-/* Join a group (you need to have been invited first.)
- *
- * expected_type is the groupchat type we expect the chat we are joining is.
- *
- * return group number on success.
- * return -1 if data length is invalid.
- * return -2 if group is not the expected type.
- * return -3 if friendnumber is invalid.
- * return -4 if client is already in this group.
- * return -5 if group instance failed to initialize.
- * return -6 if join packet fails to send.
- */
-int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length)
-{
- if (length != sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH) {
- return -1;
- }
-
- if (data[sizeof(uint16_t)] != expected_type) {
- return -2;
- }
-
- int friendcon_id = getfriendcon_id(g_c->m, friendnumber);
-
- if (friendcon_id == -1) {
- return -3;
- }
-
- if (get_group_num(g_c, data + sizeof(uint16_t)) != -1) {
- return -4;
- }
-
- int groupnumber = create_group_chat(g_c);
-
- if (groupnumber == -1) {
- return -5;
- }
-
- Group_c *g = &g_c->chats[groupnumber];
-
- uint16_t group_num = net_htons(groupnumber);
- g->status = GROUPCHAT_STATUS_VALID;
- g->number_joined = -1;
- memcpy(g->real_pk, g_c->m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- uint8_t response[INVITE_RESPONSE_PACKET_SIZE];
- response[0] = INVITE_RESPONSE_ID;
- memcpy(response + 1, &group_num, sizeof(uint16_t));
- memcpy(response + 1 + sizeof(uint16_t), data, sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH);
-
- if (send_conference_invite_packet(g_c->m, friendnumber, response, sizeof(response))) {
- uint16_t other_groupnum;
- memcpy(&other_groupnum, data, sizeof(other_groupnum));
- other_groupnum = net_ntohs(other_groupnum);
- memcpy(g->identifier, data + sizeof(uint16_t), GROUP_IDENTIFIER_LENGTH);
- int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 0, 1);
-
- if (close_index != -1) {
- g->close[close_index].group_number = other_groupnum;
- g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
- g->number_joined = friendcon_id;
- }
-
- send_peer_query(g_c, friendcon_id, other_groupnum);
- return groupnumber;
- }
-
- g->status = GROUPCHAT_STATUS_NONE;
- return -6;
-}
-
-/* Set handlers for custom lossy packets.
- *
- * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
- */
-void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
- const uint8_t *, uint16_t))
-{
- g_c->lossy_packethandlers[byte].function = function;
-}
-
-/* Set the callback for group invites.
- *
- * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
- *
- * data of length is what needs to be passed to join_groupchat().
- */
-void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
- size_t, void *))
-{
- g_c->invite_callback = function;
-}
-
-/* Set the callback for group messages.
- *
- * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
- */
-void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
- size_t, void *))
-{
- g_c->message_callback = function;
-}
-
-/* Set callback function for peer name list changes.
- *
- * It gets called every time the name list changes(new peer/name, deleted peer)
- * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
- */
-void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *))
-{
- g_c->group_namelistchange = function;
-}
-
-/* Set callback function for title changes.
- *
- * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
- * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
- */
-void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
- size_t, void *))
-{
- g_c->title_callback = function;
-}
-
-/* Set a function to be called when a new peer joins a group chat.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber)
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int))
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- g->peer_on_join = function;
- return 0;
-}
-
-/* Set a function to be called when a peer leaves a group chat.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object))
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *))
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- g->peer_on_leave = function;
- return 0;
-}
-
-/* Set a function to be called when the group chat is deleted.
- *
- * Function(void *group object (set with group_set_object), int groupnumber)
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int))
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- g->group_on_delete = function;
- return 0;
-}
-
-static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
- uint16_t len);
-
-#define GROUP_MESSAGE_PING_ID 0
-static int group_ping_send(const Group_Chats *g_c, int groupnumber)
-{
- if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_PING_ID, 0, 0) > 0) {
- return 0;
- }
-
- return -1;
-}
-
-#define GROUP_MESSAGE_NEW_PEER_ID 16
-#define GROUP_MESSAGE_NEW_PEER_LENGTH (sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2)
-/* send a new_peer message
- * return 0 on success
- * return -1 on failure
- */
-static int group_new_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num, const uint8_t *real_pk,
- uint8_t *temp_pk)
-{
- uint8_t packet[GROUP_MESSAGE_NEW_PEER_LENGTH];
-
- peer_num = net_htons(peer_num);
- memcpy(packet, &peer_num, sizeof(uint16_t));
- memcpy(packet + sizeof(uint16_t), real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE, temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
-
- if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NEW_PEER_ID, packet, sizeof(packet)) > 0) {
- return 0;
- }
-
- return -1;
-}
-
-#define GROUP_MESSAGE_KILL_PEER_ID 17
-#define GROUP_MESSAGE_KILL_PEER_LENGTH (sizeof(uint16_t))
-
-/* send a kill_peer message
- * return 0 on success
- * return -1 on failure
- */
-static int group_kill_peer_send(const Group_Chats *g_c, int groupnumber, uint16_t peer_num)
-{
- uint8_t packet[GROUP_MESSAGE_KILL_PEER_LENGTH];
-
- peer_num = net_htons(peer_num);
- memcpy(packet, &peer_num, sizeof(uint16_t));
-
- if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_KILL_PEER_ID, packet, sizeof(packet)) > 0) {
- return 0;
- }
-
- return -1;
-}
-
-#define GROUP_MESSAGE_NAME_ID 48
-
-/* send a name message
- * return 0 on success
- * return -1 on failure
- */
-static int group_name_send(const Group_Chats *g_c, int groupnumber, const uint8_t *nick, uint16_t nick_len)
-{
- if (nick_len > MAX_NAME_LENGTH) {
- return -1;
- }
-
- if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_NAME_ID, nick, nick_len) > 0) {
- return 0;
- }
-
- return -1;
-}
-
-#define GROUP_MESSAGE_TITLE_ID 49
-
-/* set the group's title, limited to MAX_NAME_LENGTH
- * return 0 on success
- * return -1 if groupnumber is invalid.
- * return -2 if title is too long or empty.
- * return -3 if packet fails to send.
- */
-int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (title_len > MAX_NAME_LENGTH || title_len == 0) {
- return -2;
- }
-
- /* same as already set? */
- if (g->title_len == title_len && !memcmp(g->title, title, title_len)) {
- return 0;
- }
-
- memcpy(g->title, title, title_len);
- g->title_len = title_len;
-
- if (g->numpeers == 1) {
- return 0;
- }
-
- if (send_message_group(g_c, groupnumber, GROUP_MESSAGE_TITLE_ID, title, title_len) > 0) {
- return 0;
- }
-
- return -3;
-}
-
-/* return the group's title size.
- * return -1 of groupnumber is invalid.
- * return -2 if title is too long or empty.
- */
-int group_title_get_size(const Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
- return -2;
- }
-
- return g->title_len;
-}
-
-/* Get group title from groupnumber and put it in title.
- * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
- *
- * return length of copied title if success.
- * return -1 if groupnumber is invalid.
- * return -2 if title is too long or empty.
- */
-int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (g->title_len == 0 || g->title_len > MAX_NAME_LENGTH) {
- return -2;
- }
-
- memcpy(title, g->title, g->title_len);
- return g->title_len;
-}
-
-static void handle_friend_invite_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length,
- void *userdata)
-{
- Group_Chats *g_c = (Group_Chats *)m->conferences_object;
-
- if (length <= 1) {
- return;
- }
-
- const uint8_t *invite_data = data + 1;
- uint16_t invite_length = length - 1;
-
- switch (data[0]) {
- case INVITE_ID: {
- if (length != INVITE_PACKET_SIZE) {
- return;
- }
-
- int groupnumber = get_group_num(g_c, data + 1 + sizeof(uint16_t));
-
- if (groupnumber == -1) {
- if (g_c->invite_callback) {
- g_c->invite_callback(m, friendnumber, *(invite_data + sizeof(uint16_t)), invite_data, invite_length, userdata);
- }
-
- return;
- }
-
- break;
- }
-
- case INVITE_RESPONSE_ID: {
- if (length != INVITE_RESPONSE_PACKET_SIZE) {
- return;
- }
-
- uint16_t other_groupnum, groupnum;
- memcpy(&groupnum, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
- groupnum = net_ntohs(groupnum);
-
- Group_c *g = get_group_c(g_c, groupnum);
-
- if (!g) {
- return;
- }
-
- if (crypto_memcmp(data + 1 + sizeof(uint16_t) * 2, g->identifier, GROUP_IDENTIFIER_LENGTH) != 0) {
- return;
- }
-
- /* TODO(irungentoo): what if two people enter the group at the same time and
- are given the same peer_number by different nodes? */
- uint16_t peer_number = rand();
-
- unsigned int tries = 0;
-
- while (get_peer_index(g, peer_number) != -1) {
- peer_number = rand();
- ++tries;
-
- if (tries > 32) {
- return;
- }
- }
-
- memcpy(&other_groupnum, data + 1, sizeof(uint16_t));
- other_groupnum = net_ntohs(other_groupnum);
-
- int friendcon_id = getfriendcon_id(m, friendnumber);
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE], temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- get_friendcon_public_keys(real_pk, temp_pk, g_c->fr_c, friendcon_id);
-
- addpeer(g_c, groupnum, real_pk, temp_pk, peer_number, userdata, true);
- int close_index = add_conn_to_groupchat(g_c, friendcon_id, groupnum, 0, 1);
-
- if (close_index != -1) {
- g->close[close_index].group_number = other_groupnum;
- g->close[close_index].type = GROUPCHAT_CLOSE_ONLINE;
- }
-
- group_new_peer_send(g_c, groupnum, peer_number, real_pk, temp_pk);
- break;
- }
-
- default:
- return;
- }
-}
-
-/* Find index of friend in the close list;
- *
- * returns index on success
- * returns -1 on failure.
- */
-static int friend_in_close(Group_c *g, int friendcon_id)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_NONE) {
- continue;
- }
-
- if (g->close[i].number != (uint32_t)friendcon_id) {
- continue;
- }
-
- return i;
- }
-
- return -1;
-}
-
-/* return number of connected close connections.
- */
-static unsigned int count_close_connected(Group_c *g)
-{
- unsigned int i, count = 0;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type == GROUPCHAT_CLOSE_ONLINE) {
- ++count;
- }
- }
-
- return count;
-}
-
-#define ONLINE_PACKET_DATA_SIZE (sizeof(uint16_t) + GROUP_IDENTIFIER_LENGTH)
-
-static int send_packet_online(Friend_Connections *fr_c, int friendcon_id, uint16_t group_num, uint8_t *identifier)
-{
- uint8_t packet[1 + ONLINE_PACKET_DATA_SIZE];
- group_num = net_htons(group_num);
- packet[0] = PACKET_ID_ONLINE_PACKET;
- memcpy(packet + 1, &group_num, sizeof(uint16_t));
- memcpy(packet + 1 + sizeof(uint16_t), identifier, GROUP_IDENTIFIER_LENGTH);
- return write_cryptpacket(fr_c->net_crypto, friend_connection_crypt_connection_id(fr_c, friendcon_id), packet,
- sizeof(packet), 0) != -1;
-}
-
-static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num);
-
-static int handle_packet_online(Group_Chats *g_c, int friendcon_id, const uint8_t *data, uint16_t length)
-{
- if (length != ONLINE_PACKET_DATA_SIZE) {
- return -1;
- }
-
- int groupnumber = get_group_num(g_c, data + sizeof(uint16_t));
- uint16_t other_groupnum;
- memcpy(&other_groupnum, data, sizeof(uint16_t));
- other_groupnum = net_ntohs(other_groupnum);
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- int index = friend_in_close(g, friendcon_id);
-
- if (index == -1) {
- return -1;
- }
-
- if (g->close[index].type == GROUPCHAT_CLOSE_ONLINE) {
- return -1;
- }
-
- if (count_close_connected(g) == 0) {
- send_peer_query(g_c, friendcon_id, other_groupnum);
- }
-
- g->close[index].group_number = other_groupnum;
- g->close[index].type = GROUPCHAT_CLOSE_ONLINE;
- send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier);
-
- if (g->number_joined != -1 && count_close_connected(g) >= DESIRED_CLOSE_CONNECTIONS) {
- int fr_close_index = friend_in_close(g, g->number_joined);
-
- if (fr_close_index == -1) {
- return -1;
- }
-
- if (!g->close[fr_close_index].closest) {
- g->close[fr_close_index].type = GROUPCHAT_CLOSE_NONE;
- send_peer_kill(g_c, g->close[fr_close_index].number, g->close[fr_close_index].group_number);
- kill_friend_connection(g_c->fr_c, g->close[fr_close_index].number);
- g->number_joined = -1;
- }
- }
-
- return 0;
-}
-
-#define PEER_KILL_ID 1
-#define PEER_QUERY_ID 8
-#define PEER_RESPONSE_ID 9
-#define PEER_TITLE_ID 10
-// we could send title with invite, but then if it changes between sending and accepting inv, joinee won't see it
-
-/* return 1 on success.
- * return 0 on failure
- */
-static unsigned int send_peer_kill(Group_Chats *g_c, int friendcon_id, uint16_t group_num)
-{
- uint8_t packet[1];
- packet[0] = PEER_KILL_ID;
- return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
-}
-
-
-/* return 1 on success.
- * return 0 on failure
- */
-static unsigned int send_peer_query(Group_Chats *g_c, int friendcon_id, uint16_t group_num)
-{
- uint8_t packet[1];
- packet[0] = PEER_QUERY_ID;
- return send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, sizeof(packet));
-}
-
-/* return number of peers sent on success.
- * return 0 on failure.
- */
-static unsigned int send_peers(Group_Chats *g_c, int groupnumber, int friendcon_id, uint16_t group_num)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint8_t packet[MAX_CRYPTO_DATA_SIZE - (1 + sizeof(uint16_t))];
- packet[0] = PEER_RESPONSE_ID;
- uint8_t *p = packet + 1;
-
- uint16_t sent = 0;
- unsigned int i;
-
- for (i = 0; i < g->numpeers; ++i) {
- if ((p - packet) + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1 + g->group[i].nick_len > sizeof(packet)) {
- if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
- sent = i;
- } else {
- return sent;
- }
-
- p = packet + 1;
- }
-
- uint16_t peer_num = net_htons(g->group[i].peer_number);
- memcpy(p, &peer_num, sizeof(peer_num));
- p += sizeof(peer_num);
- memcpy(p, g->group[i].real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- p += CRYPTO_PUBLIC_KEY_SIZE;
- memcpy(p, g->group[i].temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
- p += CRYPTO_PUBLIC_KEY_SIZE;
- *p = g->group[i].nick_len;
- p += 1;
- memcpy(p, g->group[i].nick, g->group[i].nick_len);
- p += g->group[i].nick_len;
- }
-
- if (sent != i) {
- if (send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, packet, (p - packet))) {
- sent = i;
- }
- }
-
- if (g->title_len) {
- VLA(uint8_t, Packet, 1 + g->title_len);
- Packet[0] = PEER_TITLE_ID;
- memcpy(Packet + 1, g->title, g->title_len);
- send_packet_group_peer(g_c->fr_c, friendcon_id, PACKET_ID_DIRECT_CONFERENCE, group_num, Packet, SIZEOF_VLA(Packet));
- }
-
- return sent;
-}
-
-static int handle_send_peers(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0) {
- return -1;
- }
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- const uint8_t *d = data;
-
- while ((unsigned int)(length - (d - data)) >= sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE * 2 + 1) {
- uint16_t peer_num;
- memcpy(&peer_num, d, sizeof(peer_num));
- peer_num = net_ntohs(peer_num);
- d += sizeof(uint16_t);
- int peer_index = addpeer(g_c, groupnumber, d, d + CRYPTO_PUBLIC_KEY_SIZE, peer_num, userdata, true);
-
- if (peer_index == -1) {
- return -1;
- }
-
- if (g->status == GROUPCHAT_STATUS_VALID
- && public_key_cmp(d, g_c->m->net_crypto->self_public_key) == 0) {
- g->peer_number = peer_num;
- g->status = GROUPCHAT_STATUS_CONNECTED;
- group_name_send(g_c, groupnumber, g_c->m->name, g_c->m->name_length);
- }
-
- d += CRYPTO_PUBLIC_KEY_SIZE * 2;
- uint8_t name_length = *d;
- d += 1;
-
- if (name_length > (length - (d - data)) || name_length > MAX_NAME_LENGTH) {
- return -1;
- }
-
- setnick(g_c, groupnumber, peer_index, d, name_length, userdata, true);
- d += name_length;
- }
-
- return 0;
-}
-
-static void handle_direct_packet(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
- int close_index, void *userdata)
-{
- if (length == 0) {
- return;
- }
-
- switch (data[0]) {
- case PEER_KILL_ID: {
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return;
- }
-
- if (!g->close[close_index].closest) {
- g->close[close_index].type = GROUPCHAT_CLOSE_NONE;
- kill_friend_connection(g_c->fr_c, g->close[close_index].number);
- }
- }
-
- break;
-
- case PEER_QUERY_ID: {
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return;
- }
-
- send_peers(g_c, groupnumber, g->close[close_index].number, g->close[close_index].group_number);
- }
-
- break;
-
- case PEER_RESPONSE_ID: {
- handle_send_peers(g_c, groupnumber, data + 1, length - 1, userdata);
- }
-
- break;
-
- case PEER_TITLE_ID: {
- settitle(g_c, groupnumber, -1, data + 1, length - 1, userdata);
- }
-
- break;
- }
-}
-
-#define MIN_MESSAGE_PACKET_LEN (sizeof(uint16_t) * 2 + sizeof(uint32_t) + 1)
-
-/* Send message to all close except receiver (if receiver isn't -1)
- * NOTE: this function appends the group chat number to the data passed to it.
- *
- * return number of messages sent.
- */
-static unsigned int send_message_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data,
- uint16_t length, int receiver)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return 0;
- }
-
- uint16_t i, sent = 0;
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
- continue;
- }
-
- if ((int)i == receiver) {
- continue;
- }
-
- if (send_packet_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_MESSAGE_CONFERENCE, g->close[i].group_number, data,
- length)) {
- ++sent;
- }
- }
-
- return sent;
-}
-
-/* Send lossy message to all close except receiver (if receiver isn't -1)
- * NOTE: this function appends the group chat number to the data passed to it.
- *
- * return number of messages sent.
- */
-static unsigned int send_lossy_all_close(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
- int receiver)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return 0;
- }
-
- unsigned int i, sent = 0, num_connected_closest = 0, connected_closest[DESIRED_CLOSE_CONNECTIONS];
-
- for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) {
- if (g->close[i].type != GROUPCHAT_CLOSE_ONLINE) {
- continue;
- }
-
- if ((int)i == receiver) {
- continue;
- }
-
- if (g->close[i].closest) {
- connected_closest[num_connected_closest] = i;
- ++num_connected_closest;
- continue;
- }
-
- if (send_lossy_group_peer(g_c->fr_c, g->close[i].number, PACKET_ID_LOSSY_CONFERENCE, g->close[i].group_number, data,
- length)) {
- ++sent;
- }
- }
-
- if (!num_connected_closest) {
- return sent;
- }
-
- unsigned int to_send = 0;
- uint64_t comp_val_old = ~0;
-
- for (i = 0; i < num_connected_closest; ++i) {
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
- uint64_t comp_val = calculate_comp_value(g->real_pk, real_pk);
-
- if (comp_val < comp_val_old) {
- to_send = connected_closest[i];
- comp_val_old = comp_val;
- }
- }
-
- if (send_lossy_group_peer(g_c->fr_c, g->close[to_send].number, PACKET_ID_LOSSY_CONFERENCE,
- g->close[to_send].group_number, data, length)) {
- ++sent;
- }
-
- unsigned int to_send_other = 0;
- comp_val_old = ~0;
-
- for (i = 0; i < num_connected_closest; ++i) {
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t dht_temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[connected_closest[i]].number);
- uint64_t comp_val = calculate_comp_value(real_pk, g->real_pk);
-
- if (comp_val < comp_val_old) {
- to_send_other = connected_closest[i];
- comp_val_old = comp_val;
- }
- }
-
- if (to_send_other == to_send) {
- return sent;
- }
-
- if (send_lossy_group_peer(g_c->fr_c, g->close[to_send_other].number, PACKET_ID_LOSSY_CONFERENCE,
- g->close[to_send_other].group_number, data, length)) {
- ++sent;
- }
-
- return sent;
-}
-
-#define MAX_GROUP_MESSAGE_DATA_LEN (MAX_CRYPTO_DATA_SIZE - (1 + MIN_MESSAGE_PACKET_LEN))
-
-/* Send data of len with message_id to groupnumber.
- *
- * return number of peers it was sent to on success.
- * return -1 if groupnumber is invalid.
- * return -2 if message is too long.
- * return -3 if we are not connected to the group.
- * reutrn -4 if message failed to send.
- */
-static int send_message_group(const Group_Chats *g_c, int groupnumber, uint8_t message_id, const uint8_t *data,
- uint16_t len)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (len > MAX_GROUP_MESSAGE_DATA_LEN) {
- return -2;
- }
-
- if (g->status != GROUPCHAT_STATUS_CONNECTED) {
- return -3;
- }
-
- VLA(uint8_t, packet, sizeof(uint16_t) + sizeof(uint32_t) + 1 + len);
- uint16_t peer_num = net_htons(g->peer_number);
- memcpy(packet, &peer_num, sizeof(peer_num));
-
- ++g->message_number;
-
- if (!g->message_number) {
- ++g->message_number;
- }
-
- uint32_t message_num = net_htonl(g->message_number);
- memcpy(packet + sizeof(uint16_t), &message_num, sizeof(message_num));
-
- packet[sizeof(uint16_t) + sizeof(uint32_t)] = message_id;
-
- if (len) {
- memcpy(packet + sizeof(uint16_t) + sizeof(uint32_t) + 1, data, len);
- }
-
- unsigned int ret = send_message_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1);
-
- return (ret == 0) ? -4 : ret;
-}
-
-/* send a group message
- * return 0 on success
- * see: send_message_group() for error codes.
- */
-int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length)
-{
- int ret = send_message_group(g_c, groupnumber, PACKET_ID_MESSAGE, message, length);
-
- if (ret > 0) {
- return 0;
- }
-
- return ret;
-}
-
-/* send a group action
- * return 0 on success
- * see: send_message_group() for error codes.
- */
-int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length)
-{
- int ret = send_message_group(g_c, groupnumber, PACKET_ID_ACTION, action, length);
-
- if (ret > 0) {
- return 0;
- }
-
- return ret;
-}
-
-/* High level function to send custom lossy packets.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length)
-{
- // TODO(irungentoo): length check here?
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- VLA(uint8_t, packet, sizeof(uint16_t) * 2 + length);
- uint16_t peer_number = net_htons(g->peer_number);
- memcpy(packet, &peer_number, sizeof(uint16_t));
- uint16_t message_num = net_htons(g->lossy_message_number);
- memcpy(packet + sizeof(uint16_t), &message_num, sizeof(uint16_t));
- memcpy(packet + sizeof(uint16_t) * 2, data, length);
-
- if (send_lossy_all_close(g_c, groupnumber, packet, SIZEOF_VLA(packet), -1) == 0) {
- return -1;
- }
-
- ++g->lossy_message_number;
- return 0;
-}
-
-static void handle_message_packet_group(Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length,
- int close_index, void *userdata)
-{
- if (length < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
- return;
- }
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return;
- }
-
- uint16_t peer_number;
- memcpy(&peer_number, data, sizeof(uint16_t));
- peer_number = net_ntohs(peer_number);
-
- int index = get_peer_index(g, peer_number);
-
- if (index == -1) {
- /* We don't know the peer this packet came from so we query the list of peers from that peer.
- (They would not have relayed it if they didn't know the peer.) */
- send_peer_query(g_c, g->close[close_index].number, g->close[close_index].group_number);
- return;
- }
-
- uint32_t message_number;
- memcpy(&message_number, data + sizeof(uint16_t), sizeof(message_number));
- message_number = net_ntohl(message_number);
-
- if (g->group[index].last_message_number == 0) {
- g->group[index].last_message_number = message_number;
- } else if (message_number - g->group[index].last_message_number > 64 ||
- message_number == g->group[index].last_message_number) {
- return;
- }
-
- g->group[index].last_message_number = message_number;
-
- uint8_t message_id = data[sizeof(uint16_t) + sizeof(message_number)];
- const uint8_t *msg_data = data + sizeof(uint16_t) + sizeof(message_number) + 1;
- uint16_t msg_data_len = length - (sizeof(uint16_t) + sizeof(message_number) + 1);
-
- switch (message_id) {
- case GROUP_MESSAGE_PING_ID: {
- if (msg_data_len != 0) {
- return;
- }
-
- g->group[index].last_recv = unix_time();
- }
- break;
-
- case GROUP_MESSAGE_NEW_PEER_ID: {
- if (msg_data_len != GROUP_MESSAGE_NEW_PEER_LENGTH) {
- return;
- }
-
- uint16_t new_peer_number;
- memcpy(&new_peer_number, msg_data, sizeof(uint16_t));
- new_peer_number = net_ntohs(new_peer_number);
- addpeer(g_c, groupnumber, msg_data + sizeof(uint16_t), msg_data + sizeof(uint16_t) + CRYPTO_PUBLIC_KEY_SIZE,
- new_peer_number, userdata, true);
- }
- break;
-
- case GROUP_MESSAGE_KILL_PEER_ID: {
- if (msg_data_len != GROUP_MESSAGE_KILL_PEER_LENGTH) {
- return;
- }
-
- uint16_t kill_peer_number;
- memcpy(&kill_peer_number, msg_data, sizeof(uint16_t));
- kill_peer_number = net_ntohs(kill_peer_number);
-
- if (peer_number == kill_peer_number) {
- delpeer(g_c, groupnumber, index, userdata);
- } else {
- return;
- // TODO(irungentoo):
- }
- }
- break;
-
- case GROUP_MESSAGE_NAME_ID: {
- if (setnick(g_c, groupnumber, index, msg_data, msg_data_len, userdata, true) == -1) {
- return;
- }
- }
- break;
-
- case GROUP_MESSAGE_TITLE_ID: {
- if (settitle(g_c, groupnumber, index, msg_data, msg_data_len, userdata) == -1) {
- return;
- }
- }
- break;
-
- case PACKET_ID_MESSAGE: {
- if (msg_data_len == 0) {
- return;
- }
-
- VLA(uint8_t, newmsg, msg_data_len + 1);
- memcpy(newmsg, msg_data, msg_data_len);
- newmsg[msg_data_len] = 0;
-
- // TODO(irungentoo):
- if (g_c->message_callback) {
- g_c->message_callback(g_c->m, groupnumber, index, 0, newmsg, msg_data_len, userdata);
- }
-
- break;
- }
-
- case PACKET_ID_ACTION: {
- if (msg_data_len == 0) {
- return;
- }
-
- VLA(uint8_t, newmsg, msg_data_len + 1);
- memcpy(newmsg, msg_data, msg_data_len);
- newmsg[msg_data_len] = 0;
-
- // TODO(irungentoo):
- if (g_c->message_callback) {
- g_c->message_callback(g_c->m, groupnumber, index, 1, newmsg, msg_data_len, userdata);
- }
-
- break;
- }
-
- default:
- return;
- }
-
- send_message_all_close(g_c, groupnumber, data, length, -1/* TODO(irungentoo) close_index */);
-}
-
-static int g_handle_packet(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
-{
- Group_Chats *g_c = (Group_Chats *)object;
-
- if (length < 1 + sizeof(uint16_t) + 1) {
- return -1;
- }
-
- if (data[0] == PACKET_ID_ONLINE_PACKET) {
- return handle_packet_online(g_c, friendcon_id, data + 1, length - 1);
- }
-
- if (data[0] != PACKET_ID_DIRECT_CONFERENCE && data[0] != PACKET_ID_MESSAGE_CONFERENCE) {
- return -1;
- }
-
- uint16_t groupnumber;
- memcpy(&groupnumber, data + 1, sizeof(uint16_t));
- groupnumber = net_ntohs(groupnumber);
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- int index = friend_in_close(g, friendcon_id);
-
- if (index == -1) {
- return -1;
- }
-
- switch (data[0]) {
- case PACKET_ID_DIRECT_CONFERENCE: {
- handle_direct_packet(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index, userdata);
- break;
- }
-
- case PACKET_ID_MESSAGE_CONFERENCE: {
- handle_message_packet_group(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index,
- userdata);
- break;
- }
-
- default: {
- return 0;
- }
- }
-
- return 0;
-}
-
-/* Did we already receive the lossy packet or not.
- *
- * return -1 on failure.
- * return 0 if packet was not received.
- * return 1 if packet was received.
- *
- * TODO(irungentoo): test this
- */
-static unsigned int lossy_packet_not_received(Group_c *g, int peer_index, uint16_t message_number)
-{
- if (peer_index == -1) {
- return -1;
- }
-
- if (g->group[peer_index].bottom_lossy_number == g->group[peer_index].top_lossy_number) {
- g->group[peer_index].top_lossy_number = message_number;
- g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
- g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
- return 0;
- }
-
- if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) < MAX_LOSSY_COUNT) {
- if (g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT]) {
- return 1;
- }
-
- g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
- return 0;
- }
-
- if ((uint16_t)(message_number - g->group[peer_index].bottom_lossy_number) > (1 << 15)) {
- return -1;
- }
-
- uint16_t top_distance = message_number - g->group[peer_index].top_lossy_number;
-
- if (top_distance >= MAX_LOSSY_COUNT) {
- crypto_memzero(g->group[peer_index].recv_lossy, sizeof(g->group[peer_index].recv_lossy));
- g->group[peer_index].top_lossy_number = message_number;
- g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
- g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
- return 0;
- }
-
- if (top_distance < MAX_LOSSY_COUNT) {
- unsigned int i;
-
- for (i = g->group[peer_index].bottom_lossy_number; i != (g->group[peer_index].bottom_lossy_number + top_distance);
- ++i) {
- g->group[peer_index].recv_lossy[i % MAX_LOSSY_COUNT] = 0;
- }
-
- g->group[peer_index].top_lossy_number = message_number;
- g->group[peer_index].bottom_lossy_number = (message_number - MAX_LOSSY_COUNT) + 1;
- g->group[peer_index].recv_lossy[message_number % MAX_LOSSY_COUNT] = 1;
- return 0;
- }
-
- return -1;
-}
-
-static int handle_lossy(void *object, int friendcon_id, const uint8_t *data, uint16_t length, void *userdata)
-{
- Group_Chats *g_c = (Group_Chats *)object;
-
- if (length < 1 + sizeof(uint16_t) * 3 + 1) {
- return -1;
- }
-
- if (data[0] != PACKET_ID_LOSSY_CONFERENCE) {
- return -1;
- }
-
- uint16_t groupnumber, peer_number, message_number;
- memcpy(&groupnumber, data + 1, sizeof(uint16_t));
- memcpy(&peer_number, data + 1 + sizeof(uint16_t), sizeof(uint16_t));
- memcpy(&message_number, data + 1 + sizeof(uint16_t) * 2, sizeof(uint16_t));
- groupnumber = net_ntohs(groupnumber);
- peer_number = net_ntohs(peer_number);
- message_number = net_ntohs(message_number);
-
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- int index = friend_in_close(g, friendcon_id);
-
- if (index == -1) {
- return -1;
- }
-
- if (peer_number == g->peer_number) {
- return -1;
- }
-
- int peer_index = get_peer_index(g, peer_number);
-
- if (peer_index == -1) {
- return -1;
- }
-
- if (lossy_packet_not_received(g, peer_index, message_number)) {
- return -1;
- }
-
- const uint8_t *lossy_data = data + 1 + sizeof(uint16_t) * 3;
- uint16_t lossy_length = length - (1 + sizeof(uint16_t) * 3);
- uint8_t message_id = lossy_data[0];
- ++lossy_data;
- --lossy_length;
-
- if (g_c->lossy_packethandlers[message_id].function) {
- if (g_c->lossy_packethandlers[message_id].function(g->object, groupnumber, peer_index, g->group[peer_index].object,
- lossy_data, lossy_length) == -1) {
- return -1;
- }
- } else {
- return -1;
- }
-
- send_lossy_all_close(g_c, groupnumber, data + 1 + sizeof(uint16_t), length - (1 + sizeof(uint16_t)), index);
- return 0;
-}
-
-/* Set the object that is tied to the group chat.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int group_set_object(const Group_Chats *g_c, int groupnumber, void *object)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- g->object = object;
- return 0;
-}
-
-/* Set the object that is tied to the group peer.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return -1;
- }
-
- g->group[peernumber].object = object;
- return 0;
-}
-
-/* Return the object tide to the group chat previously set by group_set_object.
- *
- * return NULL on failure.
- * return object on success.
- */
-void *group_get_object(const Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return NULL;
- }
-
- return g->object;
-}
-
-/* Return the object tide to the group chat peer previously set by group_peer_set_object.
- *
- * return NULL on failure.
- * return object on success.
- */
-void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return NULL;
- }
-
- if ((uint32_t)peernumber >= g->numpeers) {
- return NULL;
- }
-
- return g->group[peernumber].object;
-}
-
-/* Interval in seconds to send ping messages */
-#define GROUP_PING_INTERVAL 20
-
-static int ping_groupchat(Group_Chats *g_c, int groupnumber)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- if (is_timeout(g->last_sent_ping, GROUP_PING_INTERVAL)) {
- if (group_ping_send(g_c, groupnumber) != -1) { /* Ping */
- g->last_sent_ping = unix_time();
- }
- }
-
- return 0;
-}
-
-static int groupchat_clear_timedout(Group_Chats *g_c, int groupnumber, void *userdata)
-{
- Group_c *g = get_group_c(g_c, groupnumber);
-
- if (!g) {
- return -1;
- }
-
- uint32_t i;
-
- for (i = 0; i < g->numpeers; ++i) {
- if (g->peer_number != g->group[i].peer_number && is_timeout(g->group[i].last_recv, GROUP_PING_INTERVAL * 3)) {
- delpeer(g_c, groupnumber, i, userdata);
- }
-
- if (g->group == NULL || i >= g->numpeers) {
- break;
- }
- }
-
- return 0;
-}
-
-/* Send current name (set in messenger) to all online groups.
- */
-void send_name_all_groups(Group_Chats *g_c)
-{
- unsigned int i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- Group_c *g = get_group_c(g_c, i);
-
- if (!g) {
- continue;
- }
-
- if (g->status == GROUPCHAT_STATUS_CONNECTED) {
- group_name_send(g_c, i, g_c->m->name, g_c->m->name_length);
- }
- }
-}
-
-/* Create new groupchat instance. */
-Group_Chats *new_groupchats(Messenger *m)
-{
- if (!m) {
- return NULL;
- }
-
- Group_Chats *temp = (Group_Chats *)calloc(1, sizeof(Group_Chats));
-
- if (temp == NULL) {
- return NULL;
- }
-
- temp->m = m;
- temp->fr_c = m->fr_c;
- m->conferences_object = temp;
- m_callback_conference_invite(m, &handle_friend_invite_packet);
-
- return temp;
-}
-
-/* main groupchats loop. */
-void do_groupchats(Group_Chats *g_c, void *userdata)
-{
- unsigned int i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- Group_c *g = get_group_c(g_c, i);
-
- if (!g) {
- continue;
- }
-
- if (g->status == GROUPCHAT_STATUS_CONNECTED) {
- connect_to_closest(g_c, i, userdata);
- ping_groupchat(g_c, i);
- groupchat_clear_timedout(g_c, i, userdata);
- }
- }
-
- // TODO(irungentoo):
-}
-
-/* Free everything related with group chats. */
-void kill_groupchats(Group_Chats *g_c)
-{
- unsigned int i;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- del_groupchat(g_c, i);
- }
-
- m_callback_conference_invite(g_c->m, NULL);
- g_c->m->conferences_object = NULL;
- free(g_c);
-}
-
-/* Return the number of chats in the instance m.
- * You should use this to determine how much memory to allocate
- * for copy_chatlist.
- */
-uint32_t count_chatlist(Group_Chats *g_c)
-{
- uint32_t ret = 0;
- uint32_t i;
-
- for (i = 0; i < g_c->num_chats; i++) {
- if (g_c->chats[i].status != GROUPCHAT_STATUS_NONE) {
- ret++;
- }
- }
-
- return ret;
-}
-
-/* Copy a list of valid chat IDs into the array out_list.
- * If out_list is NULL, returns 0.
- * Otherwise, returns the number of elements copied.
- * If the array was too small, the contents
- * of out_list will be truncated to list_size. */
-uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size)
-{
- if (!out_list) {
- return 0;
- }
-
- if (g_c->num_chats == 0) {
- return 0;
- }
-
- uint32_t i, ret = 0;
-
- for (i = 0; i < g_c->num_chats; ++i) {
- if (ret >= list_size) {
- break; /* Abandon ship */
- }
-
- if (g_c->chats[i].status > GROUPCHAT_STATUS_NONE) {
- out_list[ret] = i;
- ret++;
- }
- }
-
- return ret;
-}
diff --git a/libs/libtox/src/toxcore/group.h b/libs/libtox/src/toxcore/group.h
deleted file mode 100644
index 2e014da36d..0000000000
--- a/libs/libtox/src/toxcore/group.h
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Slightly better groupchats implementation.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef GROUP_H
-#define GROUP_H
-
-#include "Messenger.h"
-
-enum {
- GROUPCHAT_STATUS_NONE,
- GROUPCHAT_STATUS_VALID,
- GROUPCHAT_STATUS_CONNECTED
-};
-
-enum {
- GROUPCHAT_TYPE_TEXT,
- GROUPCHAT_TYPE_AV
-};
-
-#define MAX_LOSSY_COUNT 256
-
-typedef struct {
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
-
- uint64_t last_recv;
- uint32_t last_message_number;
-
- uint8_t nick[MAX_NAME_LENGTH];
- uint8_t nick_len;
-
- uint16_t peer_number;
-
- uint8_t recv_lossy[MAX_LOSSY_COUNT];
- uint16_t bottom_lossy_number, top_lossy_number;
-
- void *object;
-} Group_Peer;
-
-#define DESIRED_CLOSE_CONNECTIONS 4
-#define MAX_GROUP_CONNECTIONS 16
-#define GROUP_IDENTIFIER_LENGTH (1 + CRYPTO_SYMMETRIC_KEY_SIZE) /* type + CRYPTO_SYMMETRIC_KEY_SIZE so we can use new_symmetric_key(...) to fill it */
-
-enum {
- GROUPCHAT_CLOSE_NONE,
- GROUPCHAT_CLOSE_CONNECTION,
- GROUPCHAT_CLOSE_ONLINE
-};
-
-typedef struct {
- uint8_t status;
-
- Group_Peer *group;
- uint32_t numpeers;
-
- struct {
- uint8_t type; /* GROUPCHAT_CLOSE_* */
- uint8_t closest;
- uint32_t number;
- uint16_t group_number;
- } close[MAX_GROUP_CONNECTIONS];
-
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- struct {
- uint8_t entry;
- uint8_t real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- } closest_peers[DESIRED_CLOSE_CONNECTIONS];
- uint8_t changed;
-
- uint8_t identifier[GROUP_IDENTIFIER_LENGTH];
-
- uint8_t title[MAX_NAME_LENGTH];
- uint8_t title_len;
-
- uint32_t message_number;
- uint16_t lossy_message_number;
- uint16_t peer_number;
-
- uint64_t last_sent_ping;
-
- int number_joined; /* friendcon_id of person that invited us to the chat. (-1 means none) */
-
- void *object;
-
- void (*peer_on_join)(void *, int, int);
- void (*peer_on_leave)(void *, int, int, void *);
- void (*group_on_delete)(void *, int);
-} Group_c;
-
-typedef struct {
- Messenger *m;
- Friend_Connections *fr_c;
-
- Group_c *chats;
- uint32_t num_chats;
-
- void (*invite_callback)(Messenger *m, uint32_t, int, const uint8_t *, size_t, void *);
- void (*message_callback)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *, size_t, void *);
- void (*group_namelistchange)(Messenger *m, int, int, uint8_t, void *);
- void (*title_callback)(Messenger *m, uint32_t, uint32_t, const uint8_t *, size_t, void *);
-
- struct {
- int (*function)(void *, int, int, void *, const uint8_t *, uint16_t);
- } lossy_packethandlers[256];
-} Group_Chats;
-
-/* Set the callback for group invites.
- *
- * Function(Group_Chats *g_c, int32_t friendnumber, uint8_t type, uint8_t *data, uint16_t length, void *userdata)
- *
- * data of length is what needs to be passed to join_groupchat().
- */
-void g_callback_group_invite(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, int, const uint8_t *,
- size_t, void *));
-
-/* Set the callback for group messages.
- *
- * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * message, uint16_t length, void *userdata)
- */
-void g_callback_group_message(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, int, const uint8_t *,
- size_t, void *));
-
-
-/* Set callback function for title changes.
- *
- * Function(Group_Chats *g_c, int groupnumber, int friendgroupnumber, uint8_t * title, uint8_t length, void *userdata)
- * if friendgroupnumber == -1, then author is unknown (e.g. initial joining the group)
- */
-void g_callback_group_title(Group_Chats *g_c, void (*function)(Messenger *m, uint32_t, uint32_t, const uint8_t *,
- size_t, void *));
-
-/* Set callback function for peer name list changes.
- *
- * It gets called every time the name list changes(new peer/name, deleted peer)
- * Function(Group_Chats *g_c, int groupnumber, int peernumber, TOX_CHAT_CHANGE change, void *userdata)
- */
-enum {
- CHAT_CHANGE_PEER_ADD,
- CHAT_CHANGE_PEER_DEL,
- CHAT_CHANGE_PEER_NAME,
-};
-void g_callback_group_namelistchange(Group_Chats *g_c, void (*function)(Messenger *m, int, int, uint8_t, void *));
-
-/* Creates a new groupchat and puts it in the chats array.
- *
- * type is one of GROUPCHAT_TYPE_*
- *
- * return group number on success.
- * return -1 on failure.
- */
-int add_groupchat(Group_Chats *g_c, uint8_t type);
-
-/* Delete a groupchat from the chats array.
- *
- * return 0 on success.
- * return -1 if groupnumber is invalid.
- */
-int del_groupchat(Group_Chats *g_c, int groupnumber);
-
-/* Copy the public key of peernumber who is in groupnumber to pk.
- * pk must be CRYPTO_PUBLIC_KEY_SIZE long.
- *
- * return 0 on success
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peer_pubkey(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *pk);
-
-/*
- * Return the size of peernumber's name.
- *
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peername_size(const Group_Chats *g_c, int groupnumber, int peernumber);
-
-/* Copy the name of peernumber who is in groupnumber to name.
- * name must be at least MAX_NAME_LENGTH long.
- *
- * return length of name if success
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- */
-int group_peername(const Group_Chats *g_c, int groupnumber, int peernumber, uint8_t *name);
-
-/* invite friendnumber to groupnumber
- *
- * return 0 on success.
- * return -1 if groupnumber is invalid.
- * return -2 if invite packet failed to send.
- */
-int invite_friend(Group_Chats *g_c, int32_t friendnumber, int groupnumber);
-
-/* Join a group (you need to have been invited first.)
- *
- * expected_type is the groupchat type we expect the chat we are joining is.
- *
- * return group number on success.
- * return -1 if data length is invalid.
- * return -2 if group is not the expected type.
- * return -3 if friendnumber is invalid.
- * return -4 if client is already in this group.
- * return -5 if group instance failed to initialize.
- * return -6 if join packet fails to send.
- */
-int join_groupchat(Group_Chats *g_c, int32_t friendnumber, uint8_t expected_type, const uint8_t *data, uint16_t length);
-
-/* send a group message
- * return 0 on success
- * see: send_message_group() for error codes.
- */
-int group_message_send(const Group_Chats *g_c, int groupnumber, const uint8_t *message, uint16_t length);
-
-/* send a group action
- * return 0 on success
- * see: send_message_group() for error codes.
- */
-int group_action_send(const Group_Chats *g_c, int groupnumber, const uint8_t *action, uint16_t length);
-
-/* set the group's title, limited to MAX_NAME_LENGTH
- * return 0 on success
- * return -1 if groupnumber is invalid.
- * return -2 if title is too long or empty.
- * return -3 if packet fails to send.
- */
-int group_title_send(const Group_Chats *g_c, int groupnumber, const uint8_t *title, uint8_t title_len);
-
-
-/* return the group's title size.
- * return -1 of groupnumber is invalid.
- * return -2 if title is too long or empty.
- */
-int group_title_get_size(const Group_Chats *g_c, int groupnumber);
-
-/* Get group title from groupnumber and put it in title.
- * Title needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes.
- *
- * return length of copied title if success.
- * return -1 if groupnumber is invalid.
- * return -2 if title is too long or empty.
- */
-int group_title_get(const Group_Chats *g_c, int groupnumber, uint8_t *title);
-
-/* Return the number of peers in the group chat on success.
- * return -1 if groupnumber is invalid.
- */
-int group_number_peers(const Group_Chats *g_c, int groupnumber);
-
-/* return 1 if the peernumber corresponds to ours.
- * return 0 if the peernumber is not ours.
- * return -1 if groupnumber is invalid.
- * return -2 if peernumber is invalid.
- * return -3 if we are not connected to the group chat.
- */
-int group_peernumber_is_ours(const Group_Chats *g_c, int groupnumber, int peernumber);
-
-/* List all the peers in the group chat.
- *
- * Copies the names of the peers to the name[length][MAX_NAME_LENGTH] array.
- *
- * Copies the lengths of the names to lengths[length]
- *
- * returns the number of peers on success.
- *
- * return -1 on failure.
- */
-int group_names(const Group_Chats *g_c, int groupnumber, uint8_t names[][MAX_NAME_LENGTH], uint16_t lengths[],
- uint16_t length);
-
-/* Set handlers for custom lossy packets.
- *
- * NOTE: Handler must return 0 if packet is to be relayed, -1 if the packet should not be relayed.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object), const uint8_t *packet, uint16_t length)
- */
-void group_lossy_packet_registerhandler(Group_Chats *g_c, uint8_t byte, int (*function)(void *, int, int, void *,
- const uint8_t *, uint16_t));
-
-/* High level function to send custom lossy packets.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_group_lossy_packet(const Group_Chats *g_c, int groupnumber, const uint8_t *data, uint16_t length);
-
-/* Return the number of chats in the instance m.
- * You should use this to determine how much memory to allocate
- * for copy_chatlist.
- */
-uint32_t count_chatlist(Group_Chats *g_c);
-
-/* Copy a list of valid chat IDs into the array out_list.
- * If out_list is NULL, returns 0.
- * Otherwise, returns the number of elements copied.
- * If the array was too small, the contents
- * of out_list will be truncated to list_size. */
-uint32_t copy_chatlist(Group_Chats *g_c, uint32_t *out_list, uint32_t list_size);
-
-/* return the type of groupchat (GROUPCHAT_TYPE_) that groupnumber is.
- *
- * return -1 on failure.
- * return type on success.
- */
-int group_get_type(const Group_Chats *g_c, int groupnumber);
-
-/* Send current name (set in messenger) to all online groups.
- */
-void send_name_all_groups(Group_Chats *g_c);
-
-/* Set the object that is tied to the group chat.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int group_set_object(const Group_Chats *g_c, int groupnumber, void *object);
-
-/* Set the object that is tied to the group peer.
- *
- * return 0 on success.
- * return -1 on failure
- */
-int group_peer_set_object(const Group_Chats *g_c, int groupnumber, int peernumber, void *object);
-
-/* Return the object tide to the group chat previously set by group_set_object.
- *
- * return NULL on failure.
- * return object on success.
- */
-void *group_get_object(const Group_Chats *g_c, int groupnumber);
-
-/* Return the object tide to the group chat peer previously set by group_peer_set_object.
- *
- * return NULL on failure.
- * return object on success.
- */
-void *group_peer_get_object(const Group_Chats *g_c, int groupnumber, int peernumber);
-
-/* Set a function to be called when a new peer joins a group chat.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber)
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_peer_new(const Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int));
-
-/* Set a function to be called when a peer leaves a group chat.
- *
- * Function(void *group object (set with group_set_object), int groupnumber, int friendgroupnumber, void *group peer object (set with group_peer_set_object))
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_peer_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int, int, void *));
-
-/* Set a function to be called when the group chat is deleted.
- *
- * Function(void *group object (set with group_set_object), int groupnumber)
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int callback_groupchat_delete(Group_Chats *g_c, int groupnumber, void (*function)(void *, int));
-
-/* Create new groupchat instance. */
-Group_Chats *new_groupchats(Messenger *m);
-
-/* main groupchats loop. */
-void do_groupchats(Group_Chats *g_c, void *userdata);
-
-/* Free everything related with group chats. */
-void kill_groupchats(Group_Chats *g_c);
-
-#endif
diff --git a/libs/libtox/src/toxcore/list.c b/libs/libtox/src/toxcore/list.c
deleted file mode 100644
index 36d609fbd1..0000000000
--- a/libs/libtox/src/toxcore/list.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Simple struct with functions to create a list which associates ids with data
- * -Allows for finding ids associated with data such as IPs or public keys in a short time
- * -Should only be used if there are relatively few add/remove calls to the list
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "list.h"
-
-/* Basically, the elements in the list are placed in order so that they can be searched for easily
- * -each element is seen as a big-endian integer when ordering them
- * -the ids array is maintained so that each id always matches
- * -the search algorithm cuts down the time to find the id associated with a piece of data
- * at the cost of slow add/remove functions for large lists
- * -Starts at 1/2 of the array, compares the element in the array with the data,
- * then moves +/- 1/4 of the array depending on whether the value is greater or lower,
- * then +- 1/8, etc, until the value is matched or its position where it should be in the array is found
- * -some considerations since the array size is never perfect
- */
-
-#define INDEX(i) (~i)
-
-/* Find data in list
- *
- * return value:
- * >= 0 : index of data in array
- * < 0 : no match, returns index (return value is INDEX(index)) where
- * the data should be inserted
- */
-static int find(const BS_LIST *list, const uint8_t *data)
-{
- //should work well, but could be improved
- if (list->n == 0) {
- return INDEX(0);
- }
-
- uint32_t i = list->n / 2; //current position in the array
- uint32_t delta = i / 2; //how much we move in the array
-
- if (!delta) {
- delta = 1;
- }
-
- int d = -1; //used to determine if closest match is found
- //closest match is found if we move back to where we have already been
-
- while (1) {
- int r = memcmp(data, list->data + list->element_size * i, list->element_size);
-
- if (r == 0) {
- return i;
- }
-
- if (r > 0) {
- //data is greater
- //move down
- i += delta;
-
- if (d == 0 || i == list->n) {
- //reached bottom of list, or closest match
- return INDEX(i);
- }
-
- delta = (delta) / 2;
-
- if (delta == 0) {
- delta = 1;
- d = 1;
- }
- } else {
- //data is smaller
- if (d == 1 || i == 0) {
- //reached top or list or closest match
- return INDEX(i);
- }
-
- //move up
- i -= delta;
-
- delta = (delta) / 2;
-
- if (delta == 0) {
- delta = 1;
- d = 0;
- }
- }
- }
-}
-
-/* Resized the list list
- *
- * return value:
- * 1 : success
- * 0 : failure
- */
-static int resize(BS_LIST *list, uint32_t new_size)
-{
- if (new_size == 0) {
- bs_list_free(list);
- return 1;
- }
-
- uint8_t *data = (uint8_t *)realloc(list->data, list->element_size * new_size);
-
- if (!data) {
- return 0;
- }
-
- list->data = data;
-
- int *ids = (int *)realloc(list->ids, sizeof(int) * new_size);
-
- if (!ids) {
- return 0;
- }
-
- list->ids = ids;
-
- return 1;
-}
-
-
-int bs_list_init(BS_LIST *list, uint32_t element_size, uint32_t initial_capacity)
-{
- //set initial values
- list->n = 0;
- list->element_size = element_size;
- list->capacity = 0;
- list->data = NULL;
- list->ids = NULL;
-
- if (initial_capacity != 0) {
- if (!resize(list, initial_capacity)) {
- return 0;
- }
- }
-
- list->capacity = initial_capacity;
-
- return 1;
-}
-
-void bs_list_free(BS_LIST *list)
-{
- //free both arrays
- free(list->data);
- list->data = NULL;
-
- free(list->ids);
- list->ids = NULL;
-}
-
-int bs_list_find(const BS_LIST *list, const uint8_t *data)
-{
- int r = find(list, data);
-
- //return only -1 and positive values
- if (r < 0) {
- return -1;
- }
-
- return list->ids[r];
-}
-
-int bs_list_add(BS_LIST *list, const uint8_t *data, int id)
-{
- //find where the new element should be inserted
- //see: return value of find()
- int i = find(list, data);
-
- if (i >= 0) {
- //already in list
- return 0;
- }
-
- i = ~i;
-
- //increase the size of the arrays if needed
- if (list->n == list->capacity) {
- // 1.5 * n + 1
- const uint32_t new_capacity = list->n + list->n / 2 + 1;
-
- if (!resize(list, new_capacity)) {
- return 0;
- }
-
- list->capacity = new_capacity;
- }
-
- //insert data to element array
- memmove(list->data + (i + 1) * list->element_size, list->data + i * list->element_size,
- (list->n - i) * list->element_size);
- memcpy(list->data + i * list->element_size, data, list->element_size);
-
- //insert id to id array
- memmove(&list->ids[i + 1], &list->ids[i], (list->n - i) * sizeof(int));
- list->ids[i] = id;
-
- //increase n
- list->n++;
-
- return 1;
-}
-
-int bs_list_remove(BS_LIST *list, const uint8_t *data, int id)
-{
- int i = find(list, data);
-
- if (i < 0) {
- return 0;
- }
-
- if (list->ids[i] != id) {
- //this should never happen
- return 0;
- }
-
- //decrease the size of the arrays if needed
- if (list->n < list->capacity / 2) {
- const uint32_t new_capacity = list->capacity / 2;
-
- if (resize(list, new_capacity)) {
- list->capacity = new_capacity;
- }
- }
-
- list->n--;
-
- memmove(list->data + i * list->element_size, list->data + (i + 1) * list->element_size,
- (list->n - i) * list->element_size);
- memmove(&list->ids[i], &list->ids[i + 1], (list->n - i) * sizeof(int));
-
- return 1;
-}
-
-int bs_list_trim(BS_LIST *list)
-{
- if (!resize(list, list->n)) {
- return 0;
- }
-
- list->capacity = list->n;
- return 1;
-}
diff --git a/libs/libtox/src/toxcore/list.h b/libs/libtox/src/toxcore/list.h
deleted file mode 100644
index cb3b328c5a..0000000000
--- a/libs/libtox/src/toxcore/list.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Simple struct with functions to create a list which associates ids with data
- * -Allows for finding ids associated with data such as IPs or public keys in a short time
- * -Should only be used if there are relatively few add/remove calls to the list
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef LIST_H
-#define LIST_H
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-typedef struct {
- uint32_t n; //number of elements
- uint32_t capacity; //number of elements memory is allocated for
- uint32_t element_size; //size of the elements
- uint8_t *data; //array of elements
- int *ids; //array of element ids
-} BS_LIST;
-
-/* Initialize a list, element_size is the size of the elements in the list and
- * initial_capacity is the number of elements the memory will be initially allocated for
- *
- * return value:
- * 1 : success
- * 0 : failure
- */
-int bs_list_init(BS_LIST *list, uint32_t element_size, uint32_t initial_capacity);
-
-/* Free a list initiated with list_init */
-void bs_list_free(BS_LIST *list);
-
-/* Retrieve the id of an element in the list
- *
- * return value:
- * >= 0 : id associated with data
- * -1 : failure
- */
-int bs_list_find(const BS_LIST *list, const uint8_t *data);
-
-/* Add an element with associated id to the list
- *
- * return value:
- * 1 : success
- * 0 : failure (data already in list)
- */
-int bs_list_add(BS_LIST *list, const uint8_t *data, int id);
-
-/* Remove element from the list
- *
- * return value:
- * 1 : success
- * 0 : failure (element not found or id does not match)
- */
-int bs_list_remove(BS_LIST *list, const uint8_t *data, int id);
-
-/* Removes the memory overhead
- *
- * return value:
- * 1 : success
- * 0 : failure
- */
-int bs_list_trim(BS_LIST *list);
-
-#endif
diff --git a/libs/libtox/src/toxcore/logger.c b/libs/libtox/src/toxcore/logger.c
deleted file mode 100644
index 18b765a385..0000000000
--- a/libs/libtox/src/toxcore/logger.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Text logging abstraction.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013,2015 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "logger.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-struct Logger {
- logger_cb *callback;
- void *context;
- void *userdata;
-};
-
-
-/**
- * Public Functions
- */
-Logger *logger_new(void)
-{
- return (Logger *)calloc(1, sizeof(Logger));
-}
-
-void logger_kill(Logger *log)
-{
- free(log);
-}
-
-void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
-{
- log->callback = function;
- log->context = context;
- log->userdata = userdata;
-}
-
-void logger_write(Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func, const char *format,
- ...)
-{
- if (!log || !log->callback) {
- return;
- }
-
- /* Format message */
- char msg[1024];
- va_list args;
- va_start(args, format);
- vsnprintf(msg, sizeof msg, format, args);
- va_end(args);
-
- log->callback(log->context, level, file, line, func, msg, log->userdata);
-}
diff --git a/libs/libtox/src/toxcore/logger.h b/libs/libtox/src/toxcore/logger.h
deleted file mode 100644
index 8c8a639bec..0000000000
--- a/libs/libtox/src/toxcore/logger.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Logger abstraction backed by callbacks for writing.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOXLOGGER_H
-#define TOXLOGGER_H
-
-#include <stdint.h>
-
-#ifndef MIN_LOGGER_LEVEL
-#define MIN_LOGGER_LEVEL LOG_INFO
-#endif
-
-typedef enum {
- LOG_TRACE,
- LOG_DEBUG,
- LOG_INFO,
- LOG_WARNING,
- LOG_ERROR
-} LOGGER_LEVEL;
-
-typedef struct Logger Logger;
-
-typedef void logger_cb(void *context, LOGGER_LEVEL level, const char *file, int line,
- const char *func, const char *message, void *userdata);
-
-/**
- * Creates a new logger with logging disabled (callback is NULL) by default.
- */
-Logger *logger_new(void);
-
-void logger_kill(Logger *log);
-
-/**
- * Sets the logger callback. Disables logging if set to NULL.
- * The context parameter is passed to the callback as first argument.
- */
-void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata);
-
-/**
- * Main write function. If logging disabled does nothing.
- */
-void logger_write(Logger *log, LOGGER_LEVEL level, const char *file, int line, const char *func, const char *format,
- ...);
-
-
-#define LOGGER_WRITE(log, level, ...) \
- do { \
- if (level >= MIN_LOGGER_LEVEL) { \
- logger_write(log, level, __FILE__, __LINE__, __func__, __VA_ARGS__); \
- } \
- } while (0)
-
-/* To log with an logger */
-#define LOGGER_TRACE(log, ...) LOGGER_WRITE(log, LOG_TRACE , __VA_ARGS__)
-#define LOGGER_DEBUG(log, ...) LOGGER_WRITE(log, LOG_DEBUG , __VA_ARGS__)
-#define LOGGER_INFO(log, ...) LOGGER_WRITE(log, LOG_INFO , __VA_ARGS__)
-#define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOG_WARNING, __VA_ARGS__)
-#define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOG_ERROR , __VA_ARGS__)
-
-#endif /* TOXLOGGER_H */
diff --git a/libs/libtox/src/toxcore/net_crypto.c b/libs/libtox/src/toxcore/net_crypto.c
deleted file mode 100644
index 37cbab188f..0000000000
--- a/libs/libtox/src/toxcore/net_crypto.c
+++ /dev/null
@@ -1,2908 +0,0 @@
-/*
- * Functions for the core network crypto.
- *
- * NOTE: This code has to be perfect. We don't mess around with encryption.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "net_crypto.h"
-
-#include "util.h"
-
-#include <math.h>
-
-
-static uint8_t crypt_connection_id_not_valid(const Net_Crypto *c, int crypt_connection_id)
-{
- if ((uint32_t)crypt_connection_id >= c->crypto_connections_length) {
- return 1;
- }
-
- if (c->crypto_connections == NULL) {
- return 1;
- }
-
- if (c->crypto_connections[crypt_connection_id].status == CRYPTO_CONN_NO_CONNECTION) {
- return 1;
- }
-
- return 0;
-}
-
-/* cookie timeout in seconds */
-#define COOKIE_TIMEOUT 15
-#define COOKIE_DATA_LENGTH (CRYPTO_PUBLIC_KEY_SIZE * 2)
-#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH)
-#define COOKIE_LENGTH (CRYPTO_NONCE_SIZE + COOKIE_CONTENTS_LENGTH + CRYPTO_MAC_SIZE)
-
-#define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t))
-#define COOKIE_REQUEST_LENGTH (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE)
-#define COOKIE_RESPONSE_LENGTH (1 + CRYPTO_NONCE_SIZE + COOKIE_LENGTH + sizeof(uint64_t) + CRYPTO_MAC_SIZE)
-
-/* Create a cookie request packet and put it in packet.
- * dht_public_key is the dht public key of the other
- *
- * packet must be of size COOKIE_REQUEST_LENGTH or bigger.
- *
- * return -1 on failure.
- * return COOKIE_REQUEST_LENGTH on success.
- */
-static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint64_t number,
- uint8_t *shared_key)
-{
- uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH];
- uint8_t padding[CRYPTO_PUBLIC_KEY_SIZE] = {0};
-
- memcpy(plain, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, padding, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + (CRYPTO_PUBLIC_KEY_SIZE * 2), &number, sizeof(uint64_t));
-
- DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
- packet[0] = NET_PACKET_COOKIE_REQUEST;
- memcpy(packet + 1, c->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
- int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain),
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
-
- if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- return (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + len);
-}
-
-/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int create_cookie(uint8_t *cookie, const uint8_t *bytes, const uint8_t *encryption_key)
-{
- uint8_t contents[COOKIE_CONTENTS_LENGTH];
- uint64_t temp_time = unix_time();
- memcpy(contents, &temp_time, sizeof(temp_time));
- memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
- random_nonce(cookie);
- int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
-
- if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) {
- return -1;
- }
-
- return 0;
-}
-
-/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int open_cookie(uint8_t *bytes, const uint8_t *cookie, const uint8_t *encryption_key)
-{
- uint8_t contents[COOKIE_CONTENTS_LENGTH];
- int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
- COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents);
-
- if (len != sizeof(contents)) {
- return -1;
- }
-
- uint64_t cookie_time;
- memcpy(&cookie_time, contents, sizeof(cookie_time));
- uint64_t temp_time = unix_time();
-
- if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) {
- return -1;
- }
-
- memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH);
- return 0;
-}
-
-
-/* Create a cookie response packet and put it in packet.
- * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes.
- * packet must be of size COOKIE_RESPONSE_LENGTH or bigger.
- *
- * return -1 on failure.
- * return COOKIE_RESPONSE_LENGTH on success.
- */
-static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const uint8_t *request_plain,
- const uint8_t *shared_key, const uint8_t *dht_public_key)
-{
- uint8_t cookie_plain[COOKIE_DATA_LENGTH];
- memcpy(cookie_plain, request_plain, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
-
- if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) {
- return -1;
- }
-
- memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t));
- packet[0] = NET_PACKET_COOKIE_RESPONSE;
- random_nonce(packet + 1);
- int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
-
- if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) {
- return -1;
- }
-
- return COOKIE_RESPONSE_LENGTH;
-}
-
-/* Handle the cookie request packet of length length.
- * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH)
- * Put the key used to decrypt the request into shared_key (of size CRYPTO_SHARED_KEY_SIZE) for use in the response.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key,
- uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
-{
- if (length != COOKIE_REQUEST_LENGTH) {
- return -1;
- }
-
- memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE);
- DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key);
- int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE,
- request_plain);
-
- if (len != COOKIE_REQUEST_PLAIN_LENGTH) {
- return -1;
- }
-
- return 0;
-}
-
-/* Handle the cookie request packet (for raw UDP)
- */
-static int udp_handle_cookie_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
- void *userdata)
-{
- Net_Crypto *c = (Net_Crypto *)object;
- uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
-
- if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
- return 1;
- }
-
- uint8_t data[COOKIE_RESPONSE_LENGTH];
-
- if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
- return 1;
- }
-
- if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) {
- return 1;
- }
-
- return 0;
-}
-
-/* Handle the cookie request packet (for TCP)
- */
-static int tcp_handle_cookie_request(Net_Crypto *c, int connections_number, const uint8_t *packet, uint16_t length)
-{
- uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
-
- if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) {
- return -1;
- }
-
- uint8_t data[COOKIE_RESPONSE_LENGTH];
-
- if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
- return -1;
- }
-
- int ret = send_packet_tcp_connection(c->tcp_c, connections_number, data, sizeof(data));
- return ret;
-}
-
-/* Handle the cookie request packet (for TCP oob packets)
- */
-static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_connections_number,
- const uint8_t *dht_public_key, const uint8_t *packet, uint16_t length)
-{
- uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- uint8_t dht_public_key_temp[CRYPTO_PUBLIC_KEY_SIZE];
-
- if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) {
- return -1;
- }
-
- if (public_key_cmp(dht_public_key, dht_public_key_temp) != 0) {
- return -1;
- }
-
- uint8_t data[COOKIE_RESPONSE_LENGTH];
-
- if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) {
- return -1;
- }
-
- int ret = tcp_send_oob_packet(c->tcp_c, tcp_connections_number, dht_public_key, data, sizeof(data));
- return ret;
-}
-
-/* Handle a cookie response packet of length encrypted with shared_key.
- * put the cookie in the response in cookie
- *
- * cookie must be of length COOKIE_LENGTH.
- *
- * return -1 on failure.
- * return COOKIE_LENGTH on success.
- */
-static int handle_cookie_response(uint8_t *cookie, uint64_t *number, const uint8_t *packet, uint16_t length,
- const uint8_t *shared_key)
-{
- if (length != COOKIE_RESPONSE_LENGTH) {
- return -1;
- }
-
- uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- length - (1 + CRYPTO_NONCE_SIZE), plain);
-
- if (len != sizeof(plain)) {
- return -1;
- }
-
- memcpy(cookie, plain, COOKIE_LENGTH);
- memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t));
- return COOKIE_LENGTH;
-}
-
-#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH + CRYPTO_MAC_SIZE)
-
-/* Create a handshake packet and put it in packet.
- * cookie must be COOKIE_LENGTH bytes.
- * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger.
- *
- * return -1 on failure.
- * return HANDSHAKE_PACKET_LENGTH on success.
- */
-static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const uint8_t *cookie, const uint8_t *nonce,
- const uint8_t *session_pk, const uint8_t *peer_real_pk, const uint8_t *peer_dht_pubkey)
-{
- uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
- memcpy(plain, nonce, CRYPTO_NONCE_SIZE);
- memcpy(plain + CRYPTO_NONCE_SIZE, session_pk, CRYPTO_PUBLIC_KEY_SIZE);
- crypto_sha512(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, cookie, COOKIE_LENGTH);
- uint8_t cookie_plain[COOKIE_DATA_LENGTH];
- memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
-
- if (create_cookie(plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, cookie_plain,
- c->secret_symmetric_key) != 0) {
- return -1;
- }
-
- random_nonce(packet + 1 + COOKIE_LENGTH);
- int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
- packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE);
-
- if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) {
- return -1;
- }
-
- packet[0] = NET_PACKET_CRYPTO_HS;
- memcpy(packet + 1, cookie, COOKIE_LENGTH);
-
- return HANDSHAKE_PACKET_LENGTH;
-}
-
-/* Handle a crypto handshake packet of length.
- * put the nonce contained in the packet in nonce,
- * the session public key in session_pk
- * the real public key of the peer in peer_real_pk
- * the dht public key of the peer in dht_public_key and
- * the cookie inside the encrypted part of the packet in cookie.
- *
- * if expected_real_pk isn't NULL it denotes the real public key
- * the packet should be from.
- *
- * nonce must be at least CRYPTO_NONCE_SIZE
- * session_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
- * peer_real_pk must be at least CRYPTO_PUBLIC_KEY_SIZE
- * cookie must be at least COOKIE_LENGTH
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk,
- uint8_t *dht_public_key, uint8_t *cookie, const uint8_t *packet, uint16_t length, const uint8_t *expected_real_pk)
-{
- if (length != HANDSHAKE_PACKET_LENGTH) {
- return -1;
- }
-
- uint8_t cookie_plain[COOKIE_DATA_LENGTH];
-
- if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
- return -1;
- }
-
- if (expected_real_pk) {
- if (public_key_cmp(cookie_plain, expected_real_pk) != 0) {
- return -1;
- }
- }
-
- uint8_t cookie_hash[CRYPTO_SHA512_SIZE];
- crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH);
-
- uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
- int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
- packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE,
- HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain);
-
- if (len != sizeof(plain)) {
- return -1;
- }
-
- if (crypto_memcmp(cookie_hash, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- CRYPTO_SHA512_SIZE) != 0) {
- return -1;
- }
-
- memcpy(nonce, plain, CRYPTO_NONCE_SIZE);
- memcpy(session_pk, plain + CRYPTO_NONCE_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(cookie, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, COOKIE_LENGTH);
- memcpy(peer_real_pk, cookie_plain, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(dht_public_key, cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
- return 0;
-}
-
-
-static Crypto_Connection *get_crypto_connection(const Net_Crypto *c, int crypt_connection_id)
-{
- if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
- return 0;
- }
-
- return &c->crypto_connections[crypt_connection_id];
-}
-
-
-/* Associate an ip_port to a connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int add_ip_port_connection(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (ip_port.ip.family == TOX_AF_INET) {
- if (!ipport_equal(&ip_port, &conn->ip_portv4) && LAN_ip(conn->ip_portv4.ip) != 0) {
- if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
- return -1;
- }
-
- bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
- conn->ip_portv4 = ip_port;
- return 0;
- }
- } else if (ip_port.ip.family == TOX_AF_INET6) {
- if (!ipport_equal(&ip_port, &conn->ip_portv6)) {
- if (!bs_list_add(&c->ip_port_list, (uint8_t *)&ip_port, crypt_connection_id)) {
- return -1;
- }
-
- bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
- conn->ip_portv6 = ip_port;
- return 0;
- }
- }
-
- return -1;
-}
-
-/* Return the IP_Port that should be used to send packets to the other peer.
- *
- * return IP_Port with family 0 on failure.
- * return IP_Port on success.
- */
-static IP_Port return_ip_port_connection(Net_Crypto *c, int crypt_connection_id)
-{
- const IP_Port empty = {{0}};
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return empty;
- }
-
- uint64_t current_time = unix_time();
- bool v6 = 0, v4 = 0;
-
- if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
- v4 = 1;
- }
-
- if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
- v6 = 1;
- }
-
- if (v4 && LAN_ip(conn->ip_portv4.ip) == 0) {
- return conn->ip_portv4;
- }
-
- if (v6 && conn->ip_portv6.ip.family == TOX_AF_INET6) {
- return conn->ip_portv6;
- }
-
- if (conn->ip_portv4.ip.family == TOX_AF_INET) {
- return conn->ip_portv4;
- }
-
- return empty;
-}
-
-/* Sends a packet to the peer using the fastest route.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
-{
-// TODO(irungentoo): TCP, etc...
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- int direct_send_attempt = 0;
-
- pthread_mutex_lock(&conn->mutex);
- IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id);
-
- // TODO(irungentoo): on bad networks, direct connections might not last indefinitely.
- if (ip_port.ip.family != 0) {
- bool direct_connected = 0;
- crypto_connection_status(c, crypt_connection_id, &direct_connected, NULL);
-
- if (direct_connected) {
- if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) {
- pthread_mutex_unlock(&conn->mutex);
- return 0;
- }
-
- pthread_mutex_unlock(&conn->mutex);
- return -1;
- }
-
- // TODO(irungentoo): a better way of sending packets directly to confirm the others ip.
- uint64_t current_time = unix_time();
-
- if ((((UDP_DIRECT_TIMEOUT / 2) + conn->direct_send_attempt_time) > current_time && length < 96)
- || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) {
- if ((uint32_t)sendpacket(c->dht->net, ip_port, data, length) == length) {
- direct_send_attempt = 1;
- conn->direct_send_attempt_time = unix_time();
- }
- }
- }
-
- pthread_mutex_unlock(&conn->mutex);
- pthread_mutex_lock(&c->tcp_mutex);
- int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- pthread_mutex_lock(&conn->mutex);
-
- if (ret == 0) {
- conn->last_tcp_sent = current_time_monotonic();
- }
-
- pthread_mutex_unlock(&conn->mutex);
-
- if (ret == 0 || direct_send_attempt) {
- return 0;
- }
-
- return -1;
-}
-
-/** START: Array Related functions **/
-
-
-/* Return number of packets in array
- * Note that holes are counted too.
- */
-static uint32_t num_packets_array(const Packets_Array *array)
-{
- return array->buffer_end - array->buffer_start;
-}
-
-/* Add data with packet number to array.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int add_data_to_buffer(Packets_Array *array, uint32_t number, const Packet_Data *data)
-{
- if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) {
- return -1;
- }
-
- uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (array->buffer[num]) {
- return -1;
- }
-
- Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
-
- if (new_d == NULL) {
- return -1;
- }
-
- memcpy(new_d, data, sizeof(Packet_Data));
- array->buffer[num] = new_d;
-
- if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) {
- array->buffer_end = number + 1;
- }
-
- return 0;
-}
-
-/* Get pointer of data with packet number.
- *
- * return -1 on failure.
- * return 0 if data at number is empty.
- * return 1 if data pointer was put in data.
- */
-static int get_data_pointer(const Packets_Array *array, Packet_Data **data, uint32_t number)
-{
- uint32_t num_spots = array->buffer_end - array->buffer_start;
-
- if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) {
- return -1;
- }
-
- uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (!array->buffer[num]) {
- return 0;
- }
-
- *data = array->buffer[num];
- return 1;
-}
-
-/* Add data to end of array.
- *
- * return -1 on failure.
- * return packet number on success.
- */
-static int64_t add_data_end_of_buffer(Packets_Array *array, const Packet_Data *data)
-{
- if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) {
- return -1;
- }
-
- Packet_Data *new_d = (Packet_Data *)malloc(sizeof(Packet_Data));
-
- if (new_d == NULL) {
- return -1;
- }
-
- memcpy(new_d, data, sizeof(Packet_Data));
- uint32_t id = array->buffer_end;
- array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d;
- ++array->buffer_end;
- return id;
-}
-
-/* Read data from begginning of array.
- *
- * return -1 on failure.
- * return packet number on success.
- */
-static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data)
-{
- if (array->buffer_end == array->buffer_start) {
- return -1;
- }
-
- uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (!array->buffer[num]) {
- return -1;
- }
-
- memcpy(data, array->buffer[num], sizeof(Packet_Data));
- uint32_t id = array->buffer_start;
- ++array->buffer_start;
- free(array->buffer[num]);
- array->buffer[num] = NULL;
- return id;
-}
-
-/* Delete all packets in array before number (but not number)
- *
- * return -1 on failure.
- * return 0 on success
- */
-static int clear_buffer_until(Packets_Array *array, uint32_t number)
-{
- uint32_t num_spots = array->buffer_end - array->buffer_start;
-
- if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) {
- return -1;
- }
-
- uint32_t i;
-
- for (i = array->buffer_start; i != number; ++i) {
- uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (array->buffer[num]) {
- free(array->buffer[num]);
- array->buffer[num] = NULL;
- }
- }
-
- array->buffer_start = i;
- return 0;
-}
-
-static int clear_buffer(Packets_Array *array)
-{
- uint32_t i;
-
- for (i = array->buffer_start; i != array->buffer_end; ++i) {
- uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (array->buffer[num]) {
- free(array->buffer[num]);
- array->buffer[num] = NULL;
- }
- }
-
- array->buffer_start = i;
- return 0;
-}
-
-/* Set array buffer end to number.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int set_buffer_end(Packets_Array *array, uint32_t number)
-{
- if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) {
- return -1;
- }
-
- if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) {
- return -1;
- }
-
- array->buffer_end = number;
- return 0;
-}
-
-/* Create a packet request packet from recv_array and send_buffer_end into
- * data of length.
- *
- * return -1 on failure.
- * return length of packet on success.
- */
-static int generate_request_packet(uint8_t *data, uint16_t length, const Packets_Array *recv_array)
-{
- if (length == 0) {
- return -1;
- }
-
- data[0] = PACKET_ID_REQUEST;
-
- uint16_t cur_len = 1;
-
- if (recv_array->buffer_start == recv_array->buffer_end) {
- return cur_len;
- }
-
- if (length <= cur_len) {
- return cur_len;
- }
-
- uint32_t i, n = 1;
-
- for (i = recv_array->buffer_start; i != recv_array->buffer_end; ++i) {
- uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (!recv_array->buffer[num]) {
- data[cur_len] = n;
- n = 0;
- ++cur_len;
-
- if (length <= cur_len) {
- return cur_len;
- }
- } else if (n == 255) {
- data[cur_len] = 0;
- n = 0;
- ++cur_len;
-
- if (length <= cur_len) {
- return cur_len;
- }
- }
-
- ++n;
- }
-
- return cur_len;
-}
-
-/* Handle a request data packet.
- * Remove all the packets the other received from the array.
- *
- * return -1 on failure.
- * return number of requested packets on success.
- */
-static int handle_request_packet(Packets_Array *send_array, const uint8_t *data, uint16_t length,
- uint64_t *latest_send_time, uint64_t rtt_time)
-{
- if (length < 1) {
- return -1;
- }
-
- if (data[0] != PACKET_ID_REQUEST) {
- return -1;
- }
-
- if (length == 1) {
- return 0;
- }
-
- ++data;
- --length;
-
- uint32_t i, n = 1;
- uint32_t requested = 0;
-
- uint64_t temp_time = current_time_monotonic();
- uint64_t l_sent_time = ~0;
-
- for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) {
- if (length == 0) {
- break;
- }
-
- uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE;
-
- if (n == data[0]) {
- if (send_array->buffer[num]) {
- uint64_t sent_time = send_array->buffer[num]->sent_time;
-
- if ((sent_time + rtt_time) < temp_time) {
- send_array->buffer[num]->sent_time = 0;
- }
- }
-
- ++data;
- --length;
- n = 0;
- ++requested;
- } else {
- if (send_array->buffer[num]) {
- uint64_t sent_time = send_array->buffer[num]->sent_time;
-
- if (l_sent_time < sent_time) {
- l_sent_time = sent_time;
- }
-
- free(send_array->buffer[num]);
- send_array->buffer[num] = NULL;
- }
- }
-
- if (n == 255) {
- n = 1;
-
- if (data[0] != 0) {
- return -1;
- }
-
- ++data;
- --length;
- } else {
- ++n;
- }
- }
-
- if (*latest_send_time < l_sent_time) {
- *latest_send_time = l_sent_time;
- }
-
- return requested;
-}
-
-/** END: Array Related functions **/
-
-#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE))
-
-/* Creates and sends a data packet to the peer using the fastest route.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
-{
- if (length == 0 || length + (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- pthread_mutex_lock(&conn->mutex);
- VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
- packet[0] = NET_PACKET_CRYPTO_DATA;
- memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
- int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
-
- if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) {
- pthread_mutex_unlock(&conn->mutex);
- return -1;
- }
-
- increment_nonce(conn->sent_nonce);
- pthread_mutex_unlock(&conn->mutex);
-
- return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
-}
-
-/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num,
- const uint8_t *data, uint16_t length)
-{
- if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
- return -1;
- }
-
- num = net_htonl(num);
- buffer_start = net_htonl(buffer_start);
- uint16_t padding_length = (MAX_CRYPTO_DATA_SIZE - length) % CRYPTO_MAX_PADDING;
- VLA(uint8_t, packet, sizeof(uint32_t) + sizeof(uint32_t) + padding_length + length);
- memcpy(packet, &buffer_start, sizeof(uint32_t));
- memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t));
- memset(packet + (sizeof(uint32_t) * 2), PACKET_ID_PADDING, padding_length);
- memcpy(packet + (sizeof(uint32_t) * 2) + padding_length, data, length);
-
- return send_data_packet(c, crypt_connection_id, packet, SIZEOF_VLA(packet));
-}
-
-static int reset_max_speed_reached(Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- /* If last packet send failed, try to send packet again.
- If sending it fails we won't be able to send the new packet. */
- if (conn->maximum_speed_reached) {
- Packet_Data *dt = NULL;
- uint32_t packet_num = conn->send_array.buffer_end - 1;
- int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
-
- uint8_t send_failed = 0;
-
- if (ret == 1) {
- if (!dt->sent_time) {
- if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
- dt->length) != 0) {
- send_failed = 1;
- } else {
- dt->sent_time = current_time_monotonic();
- }
- }
- }
-
- if (!send_failed) {
- conn->maximum_speed_reached = 0;
- } else {
- return -1;
- }
- }
-
- return 0;
-}
-
-/* return -1 if data could not be put in packet queue.
- * return positive packet number if data was put into the queue.
- */
-static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
- uint8_t congestion_control)
-{
- if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- /* If last packet send failed, try to send packet again.
- If sending it fails we won't be able to send the new packet. */
- reset_max_speed_reached(c, crypt_connection_id);
-
- if (conn->maximum_speed_reached && congestion_control) {
- return -1;
- }
-
- Packet_Data dt;
- dt.sent_time = 0;
- dt.length = length;
- memcpy(dt.data, data, length);
- pthread_mutex_lock(&conn->mutex);
- int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt);
- pthread_mutex_unlock(&conn->mutex);
-
- if (packet_num == -1) {
- return -1;
- }
-
- if (!congestion_control && conn->maximum_speed_reached) {
- return packet_num;
- }
-
- if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) == 0) {
- Packet_Data *dt1 = NULL;
-
- if (get_data_pointer(&conn->send_array, &dt1, packet_num) == 1) {
- dt1->sent_time = current_time_monotonic();
- }
- } else {
- conn->maximum_speed_reached = 1;
- LOGGER_ERROR(c->log, "send_data_packet failed\n");
- }
-
- return packet_num;
-}
-
-/* Get the lowest 2 bytes from the nonce and convert
- * them to host byte format before returning them.
- */
-static uint16_t get_nonce_uint16(const uint8_t *nonce)
-{
- uint16_t num;
- memcpy(&num, nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
- return net_ntohs(num);
-}
-
-#define DATA_NUM_THRESHOLD 21845
-
-/* Handle a data packet.
- * Decrypt packet of length and put it into data.
- * data must be at least MAX_DATA_DATA_PACKET_SIZE big.
- *
- * return -1 on failure.
- * return length of data on success.
- */
-static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint8_t *data, const uint8_t *packet,
- uint16_t length)
-{
- if (length <= (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE) || length > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- memcpy(nonce, conn->recv_nonce, CRYPTO_NONCE_SIZE);
- uint16_t num_cur_nonce = get_nonce_uint16(nonce);
- uint16_t num;
- memcpy(&num, packet + 1, sizeof(uint16_t));
- num = net_ntohs(num);
- uint16_t diff = num - num_cur_nonce;
- increment_nonce_number(nonce, diff);
- int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
- length - (1 + sizeof(uint16_t)), data);
-
- if ((unsigned int)len != length - (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)) {
- return -1;
- }
-
- if (diff > DATA_NUM_THRESHOLD * 2) {
- increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD);
- }
-
- return len;
-}
-
-/* Send a request packet.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_request_packet(Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t data[MAX_CRYPTO_DATA_SIZE];
- int len = generate_request_packet(data, sizeof(data), &conn->recv_array);
-
- if (len == -1) {
- return -1;
- }
-
- return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, data,
- len);
-}
-
-/* Send up to max num previously requested data packets.
- *
- * return -1 on failure.
- * return number of packets sent on success.
- */
-static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint32_t max_num)
-{
- if (max_num == 0) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint64_t temp_time = current_time_monotonic();
- uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array);
-
- for (i = 0; i < array_size; ++i) {
- Packet_Data *dt;
- uint32_t packet_num = (i + conn->send_array.buffer_start);
- int ret = get_data_pointer(&conn->send_array, &dt, packet_num);
-
- if (ret == -1) {
- return -1;
- }
-
- if (ret == 0) {
- continue;
- }
-
- if (dt->sent_time) {
- continue;
- }
-
- if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data,
- dt->length) == 0) {
- dt->sent_time = temp_time;
- ++num_sent;
- }
-
- if (num_sent >= max_num) {
- break;
- }
- }
-
- return num_sent;
-}
-
-
-/* Add a new temp packet to send repeatedly.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int new_temp_packet(const Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length)
-{
- if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t *temp_packet = (uint8_t *)malloc(length);
-
- if (temp_packet == 0) {
- return -1;
- }
-
- if (conn->temp_packet) {
- free(conn->temp_packet);
- }
-
- memcpy(temp_packet, packet, length);
- conn->temp_packet = temp_packet;
- conn->temp_packet_length = length;
- conn->temp_packet_sent_time = 0;
- conn->temp_packet_num_sent = 0;
- return 0;
-}
-
-/* Clear the temp packet.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int clear_temp_packet(const Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (conn->temp_packet) {
- free(conn->temp_packet);
- }
-
- conn->temp_packet = 0;
- conn->temp_packet_length = 0;
- conn->temp_packet_sent_time = 0;
- conn->temp_packet_num_sent = 0;
- return 0;
-}
-
-
-/* Send the temp packet.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_temp_packet(Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (!conn->temp_packet) {
- return -1;
- }
-
- if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) {
- return -1;
- }
-
- conn->temp_packet_sent_time = current_time_monotonic();
- ++conn->temp_packet_num_sent;
- return 0;
-}
-
-/* Create a handshake packet and set it as a temp packet.
- * cookie must be COOKIE_LENGTH.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, const uint8_t *cookie,
- const uint8_t *dht_public_key)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH];
-
- if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key,
- conn->public_key, dht_public_key) != sizeof(handshake_packet)) {
- return -1;
- }
-
- if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) {
- return -1;
- }
-
- send_temp_packet(c, crypt_connection_id);
- return 0;
-}
-
-/* Send a kill packet.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_kill_packet(Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t kill_packet = PACKET_ID_KILL;
- return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end,
- &kill_packet, sizeof(kill_packet));
-}
-
-static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userdata)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return;
- }
-
- if (conn->connection_status_callback) {
- conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0,
- userdata);
- }
-
- crypto_kill(c, crypt_connection_id);
-}
-
-/* Handle a received data packet.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
- bool udp, void *userdata)
-{
- if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint8_t data[MAX_DATA_DATA_PACKET_SIZE];
- int len = handle_data_packet(c, crypt_connection_id, data, packet, length);
-
- if (len <= (int)(sizeof(uint32_t) * 2)) {
- return -1;
- }
-
- uint32_t buffer_start, num;
- memcpy(&buffer_start, data, sizeof(uint32_t));
- memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t));
- buffer_start = net_ntohl(buffer_start);
- num = net_ntohl(num);
-
- uint64_t rtt_calc_time = 0;
-
- if (buffer_start != conn->send_array.buffer_start) {
- Packet_Data *packet_time;
-
- if (get_data_pointer(&conn->send_array, &packet_time, conn->send_array.buffer_start) == 1) {
- rtt_calc_time = packet_time->sent_time;
- }
-
- if (clear_buffer_until(&conn->send_array, buffer_start) != 0) {
- return -1;
- }
- }
-
- uint8_t *real_data = data + (sizeof(uint32_t) * 2);
- uint16_t real_length = len - (sizeof(uint32_t) * 2);
-
- while (real_data[0] == PACKET_ID_PADDING) { /* Remove Padding */
- ++real_data;
- --real_length;
-
- if (real_length == 0) {
- return -1;
- }
- }
-
- if (real_data[0] == PACKET_ID_KILL) {
- connection_kill(c, crypt_connection_id, userdata);
- return 0;
- }
-
- if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
- clear_temp_packet(c, crypt_connection_id);
- conn->status = CRYPTO_CONN_ESTABLISHED;
-
- if (conn->connection_status_callback) {
- conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1,
- userdata);
- }
- }
-
- if (real_data[0] == PACKET_ID_REQUEST) {
- uint64_t rtt_time;
-
- if (udp) {
- rtt_time = conn->rtt_time;
- } else {
- rtt_time = DEFAULT_TCP_PING_CONNECTION;
- }
-
- int requested = handle_request_packet(&conn->send_array, real_data, real_length, &rtt_calc_time, rtt_time);
-
- if (requested == -1) {
- return -1;
- }
-
- // else { /* TODO(irungentoo): ? */ }
-
- set_buffer_end(&conn->recv_array, num);
- } else if (real_data[0] >= CRYPTO_RESERVED_PACKETS && real_data[0] < PACKET_ID_LOSSY_RANGE_START) {
- Packet_Data dt;
- dt.length = real_length;
- memcpy(dt.data, real_data, real_length);
-
- if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) {
- return -1;
- }
-
- while (1) {
- pthread_mutex_lock(&conn->mutex);
- int ret = read_data_beg_buffer(&conn->recv_array, &dt);
- pthread_mutex_unlock(&conn->mutex);
-
- if (ret == -1) {
- break;
- }
-
- if (conn->connection_data_callback) {
- conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data,
- dt.length, userdata);
- }
-
- /* conn might get killed in callback. */
- conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
- }
-
- /* Packet counter. */
- ++conn->packet_counter;
- } else if (real_data[0] >= PACKET_ID_LOSSY_RANGE_START &&
- real_data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
-
- set_buffer_end(&conn->recv_array, num);
-
- if (conn->connection_lossy_data_callback) {
- conn->connection_lossy_data_callback(conn->connection_lossy_data_callback_object,
- conn->connection_lossy_data_callback_id, real_data, real_length, userdata);
- }
- } else {
- return -1;
- }
-
- if (rtt_calc_time != 0) {
- uint64_t rtt_time = current_time_monotonic() - rtt_calc_time;
-
- if (rtt_time < conn->rtt_time) {
- conn->rtt_time = rtt_time;
- }
- }
-
- return 0;
-}
-
-/* Handle a packet that was received for the connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, const uint8_t *packet, uint16_t length,
- bool udp, void *userdata)
-{
- if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- switch (packet[0]) {
- case NET_PACKET_COOKIE_RESPONSE: {
- if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) {
- return -1;
- }
-
- uint8_t cookie[COOKIE_LENGTH];
- uint64_t number;
-
- if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
- return -1;
- }
-
- if (number != conn->cookie_request_number) {
- return -1;
- }
-
- if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) {
- return -1;
- }
-
- conn->status = CRYPTO_CONN_HANDSHAKE_SENT;
- return 0;
- }
-
- case NET_PACKET_CRYPTO_HS: {
- if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
- || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
- uint8_t peer_real_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t cookie[COOKIE_LENGTH];
-
- if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie,
- packet, length, conn->public_key) != 0) {
- return -1;
- }
-
- if (public_key_cmp(dht_public_key, conn->dht_public_key) == 0) {
- encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
-
- if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) {
- if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) {
- return -1;
- }
- }
-
- conn->status = CRYPTO_CONN_NOT_CONFIRMED;
- } else {
- if (conn->dht_pk_callback) {
- conn->dht_pk_callback(conn->dht_pk_callback_object, conn->dht_pk_callback_number, dht_public_key, userdata);
- }
- }
- } else {
- return -1;
- }
-
- return 0;
- }
-
- case NET_PACKET_CRYPTO_DATA: {
- if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) {
- return handle_data_packet_core(c, crypt_connection_id, packet, length, udp, userdata);
- }
-
- return -1;
- }
-
- default: {
- return -1;
- }
- }
-}
-
-/* Set the size of the friend list to numfriends.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
-{
- if (num == 0) {
- free(c->crypto_connections);
- c->crypto_connections = NULL;
- return 0;
- }
-
- Crypto_Connection *newcrypto_connections = (Crypto_Connection *)realloc(c->crypto_connections,
- num * sizeof(Crypto_Connection));
-
- if (newcrypto_connections == NULL) {
- return -1;
- }
-
- c->crypto_connections = newcrypto_connections;
- return 0;
-}
-
-
-/* Create a new empty crypto connection.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-static int create_crypto_connection(Net_Crypto *c)
-{
- uint32_t i;
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
- return i;
- }
- }
-
- while (1) { /* TODO(irungentoo): is this really the best way to do this? */
- pthread_mutex_lock(&c->connections_mutex);
-
- if (!c->connection_use_counter) {
- break;
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
- }
-
- int id = -1;
-
- if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == 0) {
- id = c->crypto_connections_length;
- ++c->crypto_connections_length;
- memset(&(c->crypto_connections[id]), 0, sizeof(Crypto_Connection));
- // Memsetting float/double to 0 is non-portable, so we explicitly set them to 0
- c->crypto_connections[id].packet_recv_rate = 0;
- c->crypto_connections[id].packet_send_rate = 0;
- c->crypto_connections[id].last_packets_left_rem = 0;
- c->crypto_connections[id].packet_send_rate_requested = 0;
- c->crypto_connections[id].last_packets_left_requested_rem = 0;
-
- if (pthread_mutex_init(&c->crypto_connections[id].mutex, NULL) != 0) {
- pthread_mutex_unlock(&c->connections_mutex);
- return -1;
- }
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
- return id;
-}
-
-/* Wipe a crypto connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id)
-{
- if (crypt_connection_id_not_valid(c, crypt_connection_id)) {
- return -1;
- }
-
- uint32_t i;
-
- /* Keep mutex, only destroy it when connection is realloced out. */
- pthread_mutex_t mutex = c->crypto_connections[crypt_connection_id].mutex;
- crypto_memzero(&(c->crypto_connections[crypt_connection_id]), sizeof(Crypto_Connection));
- c->crypto_connections[crypt_connection_id].mutex = mutex;
-
- for (i = c->crypto_connections_length; i != 0; --i) {
- if (c->crypto_connections[i - 1].status == CRYPTO_CONN_NO_CONNECTION) {
- pthread_mutex_destroy(&c->crypto_connections[i - 1].mutex);
- } else {
- break;
- }
- }
-
- if (c->crypto_connections_length != i) {
- c->crypto_connections_length = i;
- realloc_cryptoconnection(c, c->crypto_connections_length);
- }
-
- return 0;
-}
-
-/* Get crypto connection id from public key of peer.
- *
- * return -1 if there are no connections like we are looking for.
- * return id if it found it.
- */
-static int getcryptconnection_id(const Net_Crypto *c, const uint8_t *public_key)
-{
- uint32_t i;
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) {
- if (public_key_cmp(public_key, c->crypto_connections[i].public_key) == 0) {
- return i;
- }
- }
- }
-
- return -1;
-}
-
-/* Add a source to the crypto connection.
- * This is to be used only when we have received a packet from that source.
- *
- * return -1 on failure.
- * return positive number on success.
- * 0 if source was a direct UDP connection.
- */
-static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (source.ip.family == TOX_AF_INET || source.ip.family == TOX_AF_INET6) {
- if (add_ip_port_connection(c, crypt_connection_id, source) != 0) {
- return -1;
- }
-
- if (source.ip.family == TOX_AF_INET) {
- conn->direct_lastrecv_timev4 = unix_time();
- } else {
- conn->direct_lastrecv_timev6 = unix_time();
- }
-
- return 0;
- }
-
- if (source.ip.family == TCP_FAMILY) {
- if (add_tcp_number_relay_connection(c->tcp_c, conn->connection_number_tcp, source.ip.ip6.uint32[0]) == 0) {
- return 1;
- }
- }
-
- return -1;
-}
-
-
-/* Set function to be called when someone requests a new connection to us.
- *
- * The set function should return -1 on failure and 0 on success.
- *
- * n_c is only valid for the duration of the function call.
- */
-void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
- void *object)
-{
- c->new_connection_callback = new_connection_callback;
- c->new_connection_callback_object = object;
-}
-
-/* Handle a handshake packet by someone who wants to initiate a new connection with us.
- * This calls the callback set by new_connection_handler() if the handshake is ok.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, const uint8_t *data, uint16_t length,
- void *userdata)
-{
- New_Connection n_c;
- n_c.cookie = (uint8_t *)malloc(COOKIE_LENGTH);
-
- if (n_c.cookie == NULL) {
- return -1;
- }
-
- n_c.source = source;
- n_c.cookie_length = COOKIE_LENGTH;
-
- if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key,
- n_c.cookie, data, length, 0) != 0) {
- free(n_c.cookie);
- return -1;
- }
-
- int crypt_connection_id = getcryptconnection_id(c, n_c.public_key);
-
- if (crypt_connection_id != -1) {
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (public_key_cmp(n_c.dht_public_key, conn->dht_public_key) != 0) {
- connection_kill(c, crypt_connection_id, userdata);
- } else {
- int ret = -1;
-
- if (conn && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) {
- memcpy(conn->recv_nonce, n_c.recv_nonce, CRYPTO_NONCE_SIZE);
- memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
- encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
-
- crypto_connection_add_source(c, crypt_connection_id, source);
-
- if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) {
- conn->status = CRYPTO_CONN_NOT_CONFIRMED;
- ret = 0;
- }
- }
-
- free(n_c.cookie);
- return ret;
- }
- }
-
- int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c);
- free(n_c.cookie);
- return ret;
-}
-
-/* Accept a crypto connection.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c)
-{
- if (getcryptconnection_id(c, n_c->public_key) != -1) {
- return -1;
- }
-
- int crypt_connection_id = create_crypto_connection(c);
-
- if (crypt_connection_id == -1) {
- return -1;
- }
-
- Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
-
- if (n_c->cookie_length != COOKIE_LENGTH) {
- return -1;
- }
-
- pthread_mutex_lock(&c->tcp_mutex);
- int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- if (connection_number_tcp == -1) {
- return -1;
- }
-
- conn->connection_number_tcp = connection_number_tcp;
- memcpy(conn->public_key, n_c->public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(conn->recv_nonce, n_c->recv_nonce, CRYPTO_NONCE_SIZE);
- memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, CRYPTO_PUBLIC_KEY_SIZE);
- random_nonce(conn->sent_nonce);
- crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
- encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key);
- conn->status = CRYPTO_CONN_NOT_CONFIRMED;
-
- if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) {
- pthread_mutex_lock(&c->tcp_mutex);
- kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
- conn->status = CRYPTO_CONN_NO_CONNECTION;
- return -1;
- }
-
- memcpy(conn->dht_public_key, n_c->dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
- conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
- conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
- conn->rtt_time = DEFAULT_PING_CONNECTION;
- crypto_connection_add_source(c, crypt_connection_id, n_c->source);
- return crypt_connection_id;
-}
-
-/* Create a crypto connection.
- * If one to that real public key already exists, return it.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key)
-{
- int crypt_connection_id = getcryptconnection_id(c, real_public_key);
-
- if (crypt_connection_id != -1) {
- return crypt_connection_id;
- }
-
- crypt_connection_id = create_crypto_connection(c);
-
- if (crypt_connection_id == -1) {
- return -1;
- }
-
- Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id];
-
- if (conn == 0) {
- return -1;
- }
-
- pthread_mutex_lock(&c->tcp_mutex);
- int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- if (connection_number_tcp == -1) {
- return -1;
- }
-
- conn->connection_number_tcp = connection_number_tcp;
- memcpy(conn->public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- random_nonce(conn->sent_nonce);
- crypto_new_keypair(conn->sessionpublic_key, conn->sessionsecret_key);
- conn->status = CRYPTO_CONN_COOKIE_REQUESTING;
- conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
- conn->packet_send_rate_requested = CRYPTO_PACKET_MIN_RATE;
- conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
- conn->rtt_time = DEFAULT_PING_CONNECTION;
- memcpy(conn->dht_public_key, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- conn->cookie_request_number = random_64b();
- uint8_t cookie_request[COOKIE_REQUEST_LENGTH];
-
- if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number,
- conn->shared_key) != sizeof(cookie_request)
- || new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) {
- pthread_mutex_lock(&c->tcp_mutex);
- kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
- conn->status = CRYPTO_CONN_NO_CONNECTION;
- return -1;
- }
-
- return crypt_connection_id;
-}
-
-/* Set the direct ip of the crypto connection.
- *
- * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (add_ip_port_connection(c, crypt_connection_id, ip_port) == 0) {
- if (connected) {
- if (ip_port.ip.family == TOX_AF_INET) {
- conn->direct_lastrecv_timev4 = unix_time();
- } else {
- conn->direct_lastrecv_timev6 = unix_time();
- }
- } else {
- if (ip_port.ip.family == TOX_AF_INET) {
- conn->direct_lastrecv_timev4 = 0;
- } else {
- conn->direct_lastrecv_timev6 = 0;
- }
- }
-
- return 0;
- }
-
- return -1;
-}
-
-
-static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Net_Crypto *c = (Net_Crypto *)object;
-
- Crypto_Connection *conn = get_crypto_connection(c, id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (data[0] == NET_PACKET_COOKIE_REQUEST) {
- return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length);
- }
-
- // This unlocks the mutex that at this point is locked by do_tcp before
- // calling do_tcp_connections.
- pthread_mutex_unlock(&c->tcp_mutex);
- int ret = handle_packet_connection(c, id, data, length, 0, userdata);
- pthread_mutex_lock(&c->tcp_mutex);
-
- if (ret != 0) {
- return -1;
- }
-
- // TODO(irungentoo): detect and kill bad TCP connections.
- return 0;
-}
-
-static int tcp_oob_callback(void *object, const uint8_t *public_key, unsigned int tcp_connections_number,
- const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) {
- return -1;
- }
-
- Net_Crypto *c = (Net_Crypto *)object;
-
- if (data[0] == NET_PACKET_COOKIE_REQUEST) {
- return tcp_oob_handle_cookie_request(c, tcp_connections_number, public_key, data, length);
- }
-
- if (data[0] == NET_PACKET_CRYPTO_HS) {
- IP_Port source;
- source.port = 0;
- source.ip.family = TCP_FAMILY;
- source.ip.ip6.uint32[0] = tcp_connections_number;
-
- if (handle_new_connection_handshake(c, source, data, length, userdata) != 0) {
- return -1;
- }
-
- return 0;
- }
-
- return -1;
-}
-
-/* Add a tcp relay, associating it to a crypt_connection_id.
- *
- * return 0 if it was added.
- * return -1 if it wasn't.
- */
-int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- pthread_mutex_lock(&c->tcp_mutex);
- int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key);
- pthread_mutex_unlock(&c->tcp_mutex);
- return ret;
-}
-
-/* Add a tcp relay to the array.
- *
- * return 0 if it was added.
- * return -1 if it wasn't.
- */
-int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)
-{
- pthread_mutex_lock(&c->tcp_mutex);
- int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key);
- pthread_mutex_unlock(&c->tcp_mutex);
- return ret;
-}
-
-/* Return a random TCP connection number for use in send_tcp_onion_request.
- *
- * TODO(irungentoo): This number is just the index of an array that the elements can
- * change without warning.
- *
- * return TCP connection number on success.
- * return -1 on failure.
- */
-int get_random_tcp_con_number(Net_Crypto *c)
-{
- pthread_mutex_lock(&c->tcp_mutex);
- int ret = get_random_tcp_onion_conn_number(c->tcp_c);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
-}
-
-/* Send an onion packet via the TCP relay corresponding to tcp_connections_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length)
-{
- pthread_mutex_lock(&c->tcp_mutex);
- int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
-}
-
-/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
- * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
- *
- * return number of relays copied to tcp_relays on success.
- * return 0 on failure.
- */
-unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num)
-{
- if (num == 0) {
- return 0;
- }
-
- pthread_mutex_lock(&c->tcp_mutex);
- unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- return ret;
-}
-
-static void do_tcp(Net_Crypto *c, void *userdata)
-{
- pthread_mutex_lock(&c->tcp_mutex);
- do_tcp_connections(c->tcp_c, userdata);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- uint32_t i;
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- Crypto_Connection *conn = get_crypto_connection(c, i);
-
- if (conn == 0) {
- return;
- }
-
- if (conn->status == CRYPTO_CONN_ESTABLISHED) {
- bool direct_connected = 0;
- crypto_connection_status(c, i, &direct_connected, NULL);
-
- if (direct_connected) {
- pthread_mutex_lock(&c->tcp_mutex);
- set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 0);
- pthread_mutex_unlock(&c->tcp_mutex);
- } else {
- pthread_mutex_lock(&c->tcp_mutex);
- set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 1);
- pthread_mutex_unlock(&c->tcp_mutex);
- }
- }
- }
-}
-
-/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
- *
- * The set function should return -1 on failure and 0 on success.
- * Note that if this function is set, the connection will clear itself on disconnect.
- * Object and id will be passed to this function untouched.
- * status is 1 if the connection is going online, 0 if it is going offline.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
- int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- conn->connection_status_callback = connection_status_callback;
- conn->connection_status_callback_object = object;
- conn->connection_status_callback_id = id;
- return 0;
-}
-
-/* Set function to be called when connection with crypt_connection_id receives a data packet of length.
- *
- * The set function should return -1 on failure and 0 on success.
- * Object and id will be passed to this function untouched.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
- int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- conn->connection_data_callback = connection_data_callback;
- conn->connection_data_callback_object = object;
- conn->connection_data_callback_id = id;
- return 0;
-}
-
-/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
- *
- * The set function should return -1 on failure and 0 on success.
- * Object and id will be passed to this function untouched.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
- int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
- void *object, int id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- conn->connection_lossy_data_callback = connection_lossy_data_callback;
- conn->connection_lossy_data_callback_object = object;
- conn->connection_lossy_data_callback_id = id;
- return 0;
-}
-
-
-/* Set the function for this friend that will be callbacked with object and number if
- * the friend sends us a different dht public key than we have associated to him.
- *
- * If this function is called, the connection should be recreated with the new public key.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
- const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- conn->dht_pk_callback = function;
- conn->dht_pk_callback_object = object;
- conn->dht_pk_callback_number = number;
- return 0;
-}
-
-/* Get the crypto connection id from the ip_port.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-static int crypto_id_ip_port(const Net_Crypto *c, IP_Port ip_port)
-{
- return bs_list_find(&c->ip_port_list, (uint8_t *)&ip_port);
-}
-
-#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + CRYPTO_MAC_SIZE)
-
-/* Handle raw UDP packets coming directly from the socket.
- *
- * Handles:
- * Cookie response packets.
- * Crypto handshake packets.
- * Crypto data packets.
- *
- */
-static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) {
- return 1;
- }
-
- Net_Crypto *c = (Net_Crypto *)object;
- int crypt_connection_id = crypto_id_ip_port(c, source);
-
- if (crypt_connection_id == -1) {
- if (packet[0] != NET_PACKET_CRYPTO_HS) {
- return 1;
- }
-
- if (handle_new_connection_handshake(c, source, packet, length, userdata) != 0) {
- return 1;
- }
-
- return 0;
- }
-
- if (handle_packet_connection(c, crypt_connection_id, packet, length, 1, userdata) != 0) {
- return 1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- pthread_mutex_lock(&conn->mutex);
-
- if (source.ip.family == TOX_AF_INET) {
- conn->direct_lastrecv_timev4 = unix_time();
- } else {
- conn->direct_lastrecv_timev6 = unix_time();
- }
-
- pthread_mutex_unlock(&conn->mutex);
- return 0;
-}
-
-/* The dT for the average packet receiving rate calculations.
- Also used as the */
-#define PACKET_COUNTER_AVERAGE_INTERVAL 50
-
-/* Ratio of recv queue size / recv packet rate (in seconds) times
- * the number of ms between request packets to send at that ratio
- */
-#define REQUEST_PACKETS_COMPARE_CONSTANT (0.125 * 100.0)
-
-/* Timeout for increasing speed after congestion event (in ms). */
-#define CONGESTION_EVENT_TIMEOUT 1000
-
-/* If the send queue is SEND_QUEUE_RATIO times larger than the
- * calculated link speed the packet send speed will be reduced
- * by a value depending on this number.
- */
-#define SEND_QUEUE_RATIO 2.0
-
-static void send_crypto_packets(Net_Crypto *c)
-{
- uint32_t i;
- uint64_t temp_time = current_time_monotonic();
- double total_send_rate = 0;
- uint32_t peak_request_packet_interval = ~0;
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- Crypto_Connection *conn = get_crypto_connection(c, i);
-
- if (conn == 0) {
- return;
- }
-
- if (CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time < temp_time) {
- send_temp_packet(c, i);
- }
-
- if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED)
- && ((CRYPTO_SEND_PACKET_INTERVAL) + conn->last_request_packet_sent) < temp_time) {
- if (send_request_packet(c, i) == 0) {
- conn->last_request_packet_sent = temp_time;
- }
- }
-
- if (conn->status == CRYPTO_CONN_ESTABLISHED) {
- if (conn->packet_recv_rate > CRYPTO_PACKET_MIN_RATE) {
- double request_packet_interval = (REQUEST_PACKETS_COMPARE_CONSTANT / ((num_packets_array(
- &conn->recv_array) + 1.0) / (conn->packet_recv_rate + 1.0)));
-
- double request_packet_interval2 = ((CRYPTO_PACKET_MIN_RATE / conn->packet_recv_rate) *
- (double)CRYPTO_SEND_PACKET_INTERVAL) + (double)PACKET_COUNTER_AVERAGE_INTERVAL;
-
- if (request_packet_interval2 < request_packet_interval) {
- request_packet_interval = request_packet_interval2;
- }
-
- if (request_packet_interval < PACKET_COUNTER_AVERAGE_INTERVAL) {
- request_packet_interval = PACKET_COUNTER_AVERAGE_INTERVAL;
- }
-
- if (request_packet_interval > CRYPTO_SEND_PACKET_INTERVAL) {
- request_packet_interval = CRYPTO_SEND_PACKET_INTERVAL;
- }
-
- if (temp_time - conn->last_request_packet_sent > (uint64_t)request_packet_interval) {
- if (send_request_packet(c, i) == 0) {
- conn->last_request_packet_sent = temp_time;
- }
- }
-
- if (request_packet_interval < peak_request_packet_interval) {
- peak_request_packet_interval = request_packet_interval;
- }
- }
-
- if ((PACKET_COUNTER_AVERAGE_INTERVAL + conn->packet_counter_set) < temp_time) {
-
- double dt = temp_time - conn->packet_counter_set;
-
- conn->packet_recv_rate = (double)conn->packet_counter / (dt / 1000.0);
- conn->packet_counter = 0;
- conn->packet_counter_set = temp_time;
-
- uint32_t packets_sent = conn->packets_sent;
- conn->packets_sent = 0;
-
- uint32_t packets_resent = conn->packets_resent;
- conn->packets_resent = 0;
-
- /* conjestion control
- calculate a new value of conn->packet_send_rate based on some data
- */
-
- unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE;
- conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array);
- ++conn->last_sendqueue_counter;
-
- unsigned int j;
- long signed int sum = 0;
- sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] -
- (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE];
-
- unsigned int n_p_pos = conn->last_sendqueue_counter % CONGESTION_LAST_SENT_ARRAY_SIZE;
- conn->last_num_packets_sent[n_p_pos] = packets_sent;
- conn->last_num_packets_resent[n_p_pos] = packets_resent;
-
- bool direct_connected = 0;
- crypto_connection_status(c, i, &direct_connected, NULL);
-
- if (direct_connected && conn->last_tcp_sent + CONGESTION_EVENT_TIMEOUT > temp_time) {
- /* When switching from TCP to UDP, don't change the packet send rate for CONGESTION_EVENT_TIMEOUT ms. */
- } else {
- long signed int total_sent = 0, total_resent = 0;
-
- // TODO(irungentoo): use real delay
- unsigned int delay = (unsigned int)((conn->rtt_time / PACKET_COUNTER_AVERAGE_INTERVAL) + 0.5);
- unsigned int packets_set_rem_array = (CONGESTION_LAST_SENT_ARRAY_SIZE - CONGESTION_QUEUE_ARRAY_SIZE);
-
- if (delay > packets_set_rem_array) {
- delay = packets_set_rem_array;
- }
-
- for (j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) {
- unsigned int ind = (j + (packets_set_rem_array - delay) + n_p_pos) % CONGESTION_LAST_SENT_ARRAY_SIZE;
- total_sent += conn->last_num_packets_sent[ind];
- total_resent += conn->last_num_packets_resent[ind];
- }
-
- if (sum > 0) {
- total_sent -= sum;
- } else {
- if (total_resent > -sum) {
- total_resent = -sum;
- }
- }
-
- /* if queue is too big only allow resending packets. */
- uint32_t npackets = num_packets_array(&conn->send_array);
- double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) *
- PACKET_COUNTER_AVERAGE_INTERVAL));
-
- double min_speed_request = 1000.0 * (((double)(total_sent + total_resent)) / ((double)(
- CONGESTION_QUEUE_ARRAY_SIZE) * PACKET_COUNTER_AVERAGE_INTERVAL));
-
- if (min_speed < CRYPTO_PACKET_MIN_RATE) {
- min_speed = CRYPTO_PACKET_MIN_RATE;
- }
-
- double send_array_ratio = (((double)npackets) / min_speed);
-
- // TODO(irungentoo): Improve formula?
- if (send_array_ratio > SEND_QUEUE_RATIO && CRYPTO_MIN_QUEUE_LENGTH < npackets) {
- conn->packet_send_rate = min_speed * (1.0 / (send_array_ratio / SEND_QUEUE_RATIO));
- } else if (conn->last_congestion_event + CONGESTION_EVENT_TIMEOUT < temp_time) {
- conn->packet_send_rate = min_speed * 1.2;
- } else {
- conn->packet_send_rate = min_speed * 0.9;
- }
-
- conn->packet_send_rate_requested = min_speed_request * 1.2;
-
- if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) {
- conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE;
- }
-
- if (conn->packet_send_rate_requested < conn->packet_send_rate) {
- conn->packet_send_rate_requested = conn->packet_send_rate;
- }
- }
- }
-
- if (conn->last_packets_left_set == 0 || conn->last_packets_left_requested_set == 0) {
- conn->last_packets_left_requested_set = conn->last_packets_left_set = temp_time;
- conn->packets_left_requested = conn->packets_left = CRYPTO_MIN_QUEUE_LENGTH;
- } else {
- if (((uint64_t)((1000.0 / conn->packet_send_rate) + 0.5) + conn->last_packets_left_set) <= temp_time) {
- double n_packets = conn->packet_send_rate * (((double)(temp_time - conn->last_packets_left_set)) / 1000.0);
- n_packets += conn->last_packets_left_rem;
-
- uint32_t num_packets = n_packets;
- double rem = n_packets - (double)num_packets;
-
- if (conn->packets_left > num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH) {
- conn->packets_left = num_packets * 4 + CRYPTO_MIN_QUEUE_LENGTH;
- } else {
- conn->packets_left += num_packets;
- }
-
- conn->last_packets_left_set = temp_time;
- conn->last_packets_left_rem = rem;
- }
-
- if (((uint64_t)((1000.0 / conn->packet_send_rate_requested) + 0.5) + conn->last_packets_left_requested_set) <=
- temp_time) {
- double n_packets = conn->packet_send_rate_requested * (((double)(temp_time - conn->last_packets_left_requested_set)) /
- 1000.0);
- n_packets += conn->last_packets_left_requested_rem;
-
- uint32_t num_packets = n_packets;
- double rem = n_packets - (double)num_packets;
- conn->packets_left_requested = num_packets;
-
- conn->last_packets_left_requested_set = temp_time;
- conn->last_packets_left_requested_rem = rem;
- }
-
- if (conn->packets_left > conn->packets_left_requested) {
- conn->packets_left_requested = conn->packets_left;
- }
- }
-
- int ret = send_requested_packets(c, i, conn->packets_left_requested);
-
- if (ret != -1) {
- conn->packets_left_requested -= ret;
- conn->packets_resent += ret;
-
- if ((unsigned int)ret < conn->packets_left) {
- conn->packets_left -= ret;
- } else {
- conn->last_congestion_event = temp_time;
- conn->packets_left = 0;
- }
- }
-
- if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) {
- total_send_rate += conn->packet_send_rate;
- }
- }
- }
-
- c->current_sleep_time = ~0;
- uint32_t sleep_time = peak_request_packet_interval;
-
- if (c->current_sleep_time > sleep_time) {
- c->current_sleep_time = sleep_time;
- }
-
- if (total_send_rate > CRYPTO_PACKET_MIN_RATE) {
- sleep_time = (1000.0 / total_send_rate);
-
- if (c->current_sleep_time > sleep_time) {
- c->current_sleep_time = sleep_time + 1;
- }
- }
-
- sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
-
- if (c->current_sleep_time > sleep_time) {
- c->current_sleep_time = sleep_time;
- }
-}
-
-/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
- * Return 0 if it wasn't reached.
- */
-bool max_speed_reached(Net_Crypto *c, int crypt_connection_id)
-{
- return reset_max_speed_reached(c, crypt_connection_id) != 0;
-}
-
-/* returns the number of packet slots left in the sendbuffer.
- * return 0 if failure.
- */
-uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return 0;
- }
-
- uint32_t max_packets = CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array);
-
- if (conn->packets_left < max_packets) {
- return conn->packets_left;
- }
-
- return max_packets;
-}
-
-/* Sends a lossless cryptopacket.
- *
- * return -1 if data could not be put in packet queue.
- * return positive packet number if data was put into the queue.
- *
- * congestion_control: should congestion control apply to this packet?
- */
-int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
- uint8_t congestion_control)
-{
- if (length == 0) {
- return -1;
- }
-
- if (data[0] < CRYPTO_RESERVED_PACKETS) {
- return -1;
- }
-
- if (data[0] >= PACKET_ID_LOSSY_RANGE_START) {
- return -1;
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- if (conn->status != CRYPTO_CONN_ESTABLISHED) {
- return -1;
- }
-
- if (congestion_control && conn->packets_left == 0) {
- return -1;
- }
-
- int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length, congestion_control);
-
- if (ret == -1) {
- return -1;
- }
-
- if (congestion_control) {
- --conn->packets_left;
- --conn->packets_left_requested;
- conn->packets_sent++;
- }
-
- return ret;
-}
-
-/* Check if packet_number was received by the other side.
- *
- * packet_number must be a valid packet number of a packet sent on this connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return -1;
- }
-
- uint32_t num = conn->send_array.buffer_end - conn->send_array.buffer_start;
- uint32_t num1 = packet_number - conn->send_array.buffer_start;
-
- if (num < num1) {
- return 0;
- }
-
- return -1;
-}
-
-/* return -1 on failure.
- * return 0 on success.
- *
- * Sends a lossy cryptopacket. (first byte must in the PACKET_ID_LOSSY_RANGE_*)
- */
-int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length)
-{
- if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) {
- return -1;
- }
-
- if (data[0] < PACKET_ID_LOSSY_RANGE_START) {
- return -1;
- }
-
- if (data[0] >= (PACKET_ID_LOSSY_RANGE_START + PACKET_ID_LOSSY_RANGE_SIZE)) {
- return -1;
- }
-
- pthread_mutex_lock(&c->connections_mutex);
- ++c->connection_use_counter;
- pthread_mutex_unlock(&c->connections_mutex);
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- int ret = -1;
-
- if (conn) {
- pthread_mutex_lock(&conn->mutex);
- uint32_t buffer_start = conn->recv_array.buffer_start;
- uint32_t buffer_end = conn->send_array.buffer_end;
- pthread_mutex_unlock(&conn->mutex);
- ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length);
- }
-
- pthread_mutex_lock(&c->connections_mutex);
- --c->connection_use_counter;
- pthread_mutex_unlock(&c->connections_mutex);
-
- return ret;
-}
-
-/* Kill a crypto connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int crypto_kill(Net_Crypto *c, int crypt_connection_id)
-{
- while (1) { /* TODO(irungentoo): is this really the best way to do this? */
- pthread_mutex_lock(&c->connections_mutex);
-
- if (!c->connection_use_counter) {
- break;
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
- }
-
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- int ret = -1;
-
- if (conn) {
- if (conn->status == CRYPTO_CONN_ESTABLISHED) {
- send_kill_packet(c, crypt_connection_id);
- }
-
- pthread_mutex_lock(&c->tcp_mutex);
- kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp);
- pthread_mutex_unlock(&c->tcp_mutex);
-
- bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id);
- bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id);
- clear_temp_packet(c, crypt_connection_id);
- clear_buffer(&conn->send_array);
- clear_buffer(&conn->recv_array);
- ret = wipe_crypto_connection(c, crypt_connection_id);
- }
-
- pthread_mutex_unlock(&c->connections_mutex);
-
- return ret;
-}
-
-/* return one of CRYPTO_CONN_* values indicating the state of the connection.
- *
- * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
- * sets online_tcp_relays to the number of connected tcp relays this connection has.
- */
-unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
- unsigned int *online_tcp_relays)
-{
- Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id);
-
- if (conn == 0) {
- return CRYPTO_CONN_NO_CONNECTION;
- }
-
- if (direct_connected) {
- *direct_connected = 0;
-
- uint64_t current_time = unix_time();
-
- if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev4) > current_time) {
- *direct_connected = 1;
- }
-
- if ((UDP_DIRECT_TIMEOUT + conn->direct_lastrecv_timev6) > current_time) {
- *direct_connected = 1;
- }
- }
-
- if (online_tcp_relays) {
- *online_tcp_relays = tcp_connection_to_online_tcp_relays(c->tcp_c, conn->connection_number_tcp);
- }
-
- return conn->status;
-}
-
-void new_keys(Net_Crypto *c)
-{
- crypto_new_keypair(c->self_public_key, c->self_secret_key);
-}
-
-/* Save the public and private keys to the keys array.
- * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
- *
- * TODO(irungentoo): Save only secret key.
- */
-void save_keys(const Net_Crypto *c, uint8_t *keys)
-{
- memcpy(keys, c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(keys + CRYPTO_PUBLIC_KEY_SIZE, c->self_secret_key, CRYPTO_SECRET_KEY_SIZE);
-}
-
-/* Load the secret key.
- * Length must be CRYPTO_SECRET_KEY_SIZE.
- */
-void load_secret_key(Net_Crypto *c, const uint8_t *sk)
-{
- memcpy(c->self_secret_key, sk, CRYPTO_SECRET_KEY_SIZE);
- crypto_derive_public_key(c->self_public_key, c->self_secret_key);
-}
-
-/* Run this to (re)initialize net_crypto.
- * Sets all the global connection variables to their default values.
- */
-Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info)
-{
- unix_time_update();
-
- if (dht == NULL) {
- return NULL;
- }
-
- Net_Crypto *temp = (Net_Crypto *)calloc(1, sizeof(Net_Crypto));
-
- if (temp == NULL) {
- return NULL;
- }
-
- temp->log = log;
-
- temp->tcp_c = new_tcp_connections(dht->self_secret_key, proxy_info);
-
- if (temp->tcp_c == NULL) {
- free(temp);
- return NULL;
- }
-
- set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp);
- set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp);
-
- /*if (create_recursive_mutex(&temp->tcp_mutex) != 0 ||
- pthread_mutex_init(&temp->connections_mutex, NULL) != 0) {
- kill_tcp_connections(temp->tcp_c);
- free(temp);
- return NULL;
- }*/
-
- temp->dht = dht;
-
- new_keys(temp);
- new_symmetric_key(temp->secret_symmetric_key);
-
- temp->current_sleep_time = CRYPTO_SEND_PACKET_INTERVAL;
-
- networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp);
- networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp);
- networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp);
- networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp);
-
- bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8);
-
- return temp;
-}
-
-static void kill_timedout(Net_Crypto *c, void *userdata)
-{
- uint32_t i;
- //uint64_t temp_time = current_time_monotonic();
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- Crypto_Connection *conn = get_crypto_connection(c, i);
-
- if (conn == 0) {
- return;
- }
-
- if (conn->status == CRYPTO_CONN_NO_CONNECTION) {
- continue;
- }
-
- if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT
- || conn->status == CRYPTO_CONN_NOT_CONFIRMED) {
- if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) {
- continue;
- }
-
- connection_kill(c, i, userdata);
- }
-
-#if 0
-
- if (conn->status == CRYPTO_CONN_ESTABLISHED) {
- // TODO(irungentoo): add a timeout here?
- }
-
-#endif
- }
-}
-
-/* return the optimal interval in ms for running do_net_crypto.
- */
-uint32_t crypto_run_interval(const Net_Crypto *c)
-{
- return c->current_sleep_time;
-}
-
-/* Main loop. */
-void do_net_crypto(Net_Crypto *c, void *userdata)
-{
- unix_time_update();
- kill_timedout(c, userdata);
- do_tcp(c, userdata);
- send_crypto_packets(c);
-}
-
-void kill_net_crypto(Net_Crypto *c)
-{
- uint32_t i;
-
- for (i = 0; i < c->crypto_connections_length; ++i) {
- crypto_kill(c, i);
- }
-
- pthread_mutex_destroy(&c->tcp_mutex);
- pthread_mutex_destroy(&c->connections_mutex);
-
- kill_tcp_connections(c->tcp_c);
- bs_list_free(&c->ip_port_list);
- networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL);
- networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL);
- networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL);
- networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL);
- crypto_memzero(c, sizeof(Net_Crypto));
- free(c);
-}
diff --git a/libs/libtox/src/toxcore/net_crypto.h b/libs/libtox/src/toxcore/net_crypto.h
deleted file mode 100644
index 5ec5ca94fb..0000000000
--- a/libs/libtox/src/toxcore/net_crypto.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Functions for the core network crypto.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef NET_CRYPTO_H
-#define NET_CRYPTO_H
-
-#include "DHT.h"
-#include "LAN_discovery.h"
-#include "TCP_connection.h"
-#include "logger.h"
-
-#include <pthread.h>
-
-#define CRYPTO_CONN_NO_CONNECTION 0
-#define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets
-#define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets
-#define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets, we have received one from the other
-#define CRYPTO_CONN_ESTABLISHED 4
-
-/* Maximum size of receiving and sending packet buffers. */
-#define CRYPTO_PACKET_BUFFER_SIZE 32768 /* Must be a power of 2 */
-
-/* Minimum packet rate per second. */
-#define CRYPTO_PACKET_MIN_RATE 4.0
-
-/* Minimum packet queue max length. */
-#define CRYPTO_MIN_QUEUE_LENGTH 64
-
-/* Maximum total size of packets that net_crypto sends. */
-#define MAX_CRYPTO_PACKET_SIZE 1400
-
-#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + CRYPTO_MAC_SIZE)
-
-/* Max size of data in packets */
-#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE)
-
-/* Interval in ms between sending cookie request/handshake packets. */
-#define CRYPTO_SEND_PACKET_INTERVAL 1000
-
-/* The maximum number of times we try to send the cookie request and handshake
- before giving up. */
-#define MAX_NUM_SENDPACKET_TRIES 8
-
-/* The timeout of no received UDP packets before the direct UDP connection is considered dead. */
-#define UDP_DIRECT_TIMEOUT ((MAX_NUM_SENDPACKET_TRIES * CRYPTO_SEND_PACKET_INTERVAL) / 1000)
-
-#define PACKET_ID_PADDING 0 /* Denotes padding */
-#define PACKET_ID_REQUEST 1 /* Used to request unreceived packets */
-#define PACKET_ID_KILL 2 /* Used to kill connection */
-
-/* Packet ids 0 to CRYPTO_RESERVED_PACKETS - 1 are reserved for use by net_crypto. */
-#define CRYPTO_RESERVED_PACKETS 16
-
-#define MAX_TCP_CONNECTIONS 64
-#define MAX_TCP_RELAYS_PEER 4
-
-/* All packets starting with a byte in this range are considered lossy packets. */
-#define PACKET_ID_LOSSY_RANGE_START 192
-#define PACKET_ID_LOSSY_RANGE_SIZE 63
-
-#define CRYPTO_MAX_PADDING 8 /* All packets will be padded a number of bytes based on this number. */
-
-/* Base current transfer speed on last CONGESTION_QUEUE_ARRAY_SIZE number of points taken
- at the dT defined in net_crypto.c */
-#define CONGESTION_QUEUE_ARRAY_SIZE 12
-#define CONGESTION_LAST_SENT_ARRAY_SIZE (CONGESTION_QUEUE_ARRAY_SIZE * 2)
-
-/* Default connection ping in ms. */
-#define DEFAULT_PING_CONNECTION 1000
-#define DEFAULT_TCP_PING_CONNECTION 500
-
-typedef struct {
- uint64_t sent_time;
- uint16_t length;
- uint8_t data[MAX_CRYPTO_DATA_SIZE];
-} Packet_Data;
-
-typedef struct {
- Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE];
- uint32_t buffer_start;
- uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */
-} Packets_Array;
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
- uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
- uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of sent packets. */
- uint8_t sessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* Our public key for this session. */
- uint8_t sessionsecret_key[CRYPTO_SECRET_KEY_SIZE]; /* Our private key for this session. */
- uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; /* The precomputed shared key from encrypt_precompute. */
- uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets,
- * 2 if we are sending handshake packets
- * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet),
- * 4 if the connection is established.
- */
- uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer */
-
- uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */
- uint16_t temp_packet_length;
- uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */
- uint32_t temp_packet_num_sent;
-
- IP_Port ip_portv4; /* The ip and port to contact this guy directly.*/
- IP_Port ip_portv6;
- uint64_t direct_lastrecv_timev4; /* The Time at which we last received a direct packet in ms. */
- uint64_t direct_lastrecv_timev6;
-
- uint64_t last_tcp_sent; /* Time the last TCP packet was sent. */
-
- Packets_Array send_array;
- Packets_Array recv_array;
-
- int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata);
- void *connection_status_callback_object;
- int connection_status_callback_id;
-
- int (*connection_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
- void *connection_data_callback_object;
- int connection_data_callback_id;
-
- int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata);
- void *connection_lossy_data_callback_object;
- int connection_lossy_data_callback_id;
-
- uint64_t last_request_packet_sent;
- uint64_t direct_send_attempt_time;
-
- uint32_t packet_counter;
- double packet_recv_rate;
- uint64_t packet_counter_set;
-
- double packet_send_rate;
- uint32_t packets_left;
- uint64_t last_packets_left_set;
- double last_packets_left_rem;
-
- double packet_send_rate_requested;
- uint32_t packets_left_requested;
- uint64_t last_packets_left_requested_set;
- double last_packets_left_requested_rem;
-
- uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter;
- long signed int last_num_packets_sent[CONGESTION_LAST_SENT_ARRAY_SIZE],
- last_num_packets_resent[CONGESTION_LAST_SENT_ARRAY_SIZE];
- uint32_t packets_sent, packets_resent;
- uint64_t last_congestion_event;
- uint64_t rtt_time;
-
- /* TCP_connection connection_number */
- unsigned int connection_number_tcp;
-
- uint8_t maximum_speed_reached;
-
- pthread_mutex_t mutex;
-
- void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
- void *dht_pk_callback_object;
- uint32_t dht_pk_callback_number;
-} Crypto_Connection;
-
-typedef struct {
- IP_Port source;
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The real public key of the peer. */
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The dht public key of the peer. */
- uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
- uint8_t peersessionpublic_key[CRYPTO_PUBLIC_KEY_SIZE]; /* The public key of the peer. */
- uint8_t *cookie;
- uint8_t cookie_length;
-} New_Connection;
-
-typedef struct {
- Logger *log;
-
- DHT *dht;
- TCP_Connections *tcp_c;
-
- Crypto_Connection *crypto_connections;
- pthread_mutex_t tcp_mutex;
-
- pthread_mutex_t connections_mutex;
- unsigned int connection_use_counter;
-
- uint32_t crypto_connections_length; /* Length of connections array. */
-
- /* Our public and secret keys. */
- uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- /* The secret key used for cookies */
- uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
-
- int (*new_connection_callback)(void *object, New_Connection *n_c);
- void *new_connection_callback_object;
-
- /* The current optimal sleep time */
- uint32_t current_sleep_time;
-
- BS_LIST ip_port_list;
-} Net_Crypto;
-
-
-/* Set function to be called when someone requests a new connection to us.
- *
- * The set function should return -1 on failure and 0 on success.
- *
- * n_c is only valid for the duration of the function call.
- */
-void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
- void *object);
-
-/* Accept a crypto connection.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
-
-/* Create a crypto connection.
- * If one to that real public key already exists, return it.
- *
- * return -1 on failure.
- * return connection id on success.
- */
-int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const uint8_t *dht_public_key);
-
-/* Set the direct ip of the crypto connection.
- *
- * Connected is 0 if we are not sure we are connected to that person, 1 if we are sure.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, bool connected);
-
-/* Set function to be called when connection with crypt_connection_id goes connects/disconnects.
- *
- * The set function should return -1 on failure and 0 on success.
- * Note that if this function is set, the connection will clear itself on disconnect.
- * Object and id will be passed to this function untouched.
- * status is 1 if the connection is going online, 0 if it is going offline.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_status_handler(const Net_Crypto *c, int crypt_connection_id,
- int (*connection_status_callback)(void *object, int id, uint8_t status, void *userdata), void *object, int id);
-
-/* Set function to be called when connection with crypt_connection_id receives a lossless data packet of length.
- *
- * The set function should return -1 on failure and 0 on success.
- * Object and id will be passed to this function untouched.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_data_handler(const Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object,
- int id, const uint8_t *data, uint16_t length, void *userdata), void *object, int id);
-
-
-/* Set function to be called when connection with crypt_connection_id receives a lossy data packet of length.
- *
- * The set function should return -1 on failure and 0 on success.
- * Object and id will be passed to this function untouched.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int connection_lossy_data_handler(Net_Crypto *c, int crypt_connection_id,
- int (*connection_lossy_data_callback)(void *object, int id, const uint8_t *data, uint16_t length, void *userdata),
- void *object,
- int id);
-
-/* Set the function for this friend that will be callbacked with object and number if
- * the friend sends us a different dht public key than we have associated to him.
- *
- * If this function is called, the connection should be recreated with the new public key.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int nc_dht_pk_callback(Net_Crypto *c, int crypt_connection_id, void (*function)(void *data, int32_t number,
- const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
-
-/* returns the number of packet slots left in the sendbuffer.
- * return 0 if failure.
- */
-uint32_t crypto_num_free_sendqueue_slots(const Net_Crypto *c, int crypt_connection_id);
-
-/* Return 1 if max speed was reached for this connection (no more data can be physically through the pipe).
- * Return 0 if it wasn't reached.
- */
-bool max_speed_reached(Net_Crypto *c, int crypt_connection_id);
-
-/* Sends a lossless cryptopacket.
- *
- * return -1 if data could not be put in packet queue.
- * return positive packet number if data was put into the queue.
- *
- * The first byte of data must be in the CRYPTO_RESERVED_PACKETS to PACKET_ID_LOSSY_RANGE_START range.
- *
- * congestion_control: should congestion control apply to this packet?
- */
-int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length,
- uint8_t congestion_control);
-
-/* Check if packet_number was received by the other side.
- *
- * packet_number must be a valid packet number of a packet sent on this connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int cryptpacket_received(Net_Crypto *c, int crypt_connection_id, uint32_t packet_number);
-
-/* return -1 on failure.
- * return 0 on success.
- *
- * Sends a lossy cryptopacket. (first byte must in the PACKET_ID_LOSSY_RANGE_*)
- */
-int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t *data, uint16_t length);
-
-/* Add a tcp relay, associating it to a crypt_connection_id.
- *
- * return 0 if it was added.
- * return -1 if it wasn't.
- */
-int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, const uint8_t *public_key);
-
-/* Add a tcp relay to the array.
- *
- * return 0 if it was added.
- * return -1 if it wasn't.
- */
-int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key);
-
-/* Return a random TCP connection number for use in send_tcp_onion_request.
- *
- * return TCP connection number on success.
- * return -1 on failure.
- */
-int get_random_tcp_con_number(Net_Crypto *c);
-
-/* Send an onion packet via the TCP relay corresponding to TCP_conn_number.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length);
-
-/* Copy a maximum of num TCP relays we are connected to to tcp_relays.
- * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
- *
- * return number of relays copied to tcp_relays on success.
- * return 0 on failure.
- */
-unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num);
-
-/* Kill a crypto connection.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int crypto_kill(Net_Crypto *c, int crypt_connection_id);
-
-/* return one of CRYPTO_CONN_* values indicating the state of the connection.
- *
- * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't.
- * sets online_tcp_relays to the number of connected tcp relays this connection has.
- */
-unsigned int crypto_connection_status(const Net_Crypto *c, int crypt_connection_id, bool *direct_connected,
- unsigned int *online_tcp_relays);
-
-/* Generate our public and private keys.
- * Only call this function the first time the program starts.
- */
-void new_keys(Net_Crypto *c);
-
-/* Save the public and private keys to the keys array.
- * Length must be CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE.
- */
-void save_keys(const Net_Crypto *c, uint8_t *keys);
-
-/* Load the secret key.
- * Length must be CRYPTO_SECRET_KEY_SIZE.
- */
-void load_secret_key(Net_Crypto *c, const uint8_t *sk);
-
-/* Create new instance of Net_Crypto.
- * Sets all the global connection variables to their default values.
- */
-Net_Crypto *new_net_crypto(Logger *log, DHT *dht, TCP_Proxy_Info *proxy_info);
-
-/* return the optimal interval in ms for running do_net_crypto.
- */
-uint32_t crypto_run_interval(const Net_Crypto *c);
-
-/* Main loop. */
-void do_net_crypto(Net_Crypto *c, void *userdata);
-
-void kill_net_crypto(Net_Crypto *c);
-
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/network.c b/libs/libtox/src/toxcore/network.c
deleted file mode 100644
index 5c43bf5779..0000000000
--- a/libs/libtox/src/toxcore/network.c
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*
- * Functions for the core networking.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _DARWIN_C_SOURCE
-#define _XOPEN_SOURCE 600
-
-#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_WINXP
-#define _WIN32_WINNT 0x501
-#endif
-
-#include "network.h"
-
-#include "logger.h"
-#include "util.h"
-
-#include <assert.h>
-#ifdef __APPLE__
-#include <mach/clock.h>
-#include <mach/mach.h>
-#endif
-
-#ifndef IPV6_ADD_MEMBERSHIP
-#ifdef IPV6_JOIN_GROUP
-#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
-#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
-#endif
-#endif
-
-#if !(defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
-
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#else
-
-#ifndef IPV6_V6ONLY
-#define IPV6_V6ONLY 27
-#endif
-
-#ifndef EWOULDBLOCK
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-
-static const char *inet_ntop(Family family, const void *addr, char *buf, size_t bufsize)
-{
- if (family == TOX_AF_INET) {
- struct sockaddr_in saddr;
- memset(&saddr, 0, sizeof(saddr));
-
- saddr.sin_family = AF_INET;
- saddr.sin_addr = *(const struct in_addr *)addr;
-
- DWORD len = bufsize;
-
- if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) {
- return NULL;
- }
-
- return buf;
- } else if (family == TOX_AF_INET6) {
- struct sockaddr_in6 saddr;
- memset(&saddr, 0, sizeof(saddr));
-
- saddr.sin6_family = AF_INET6;
- saddr.sin6_addr = *(const struct in6_addr *)addr;
-
- DWORD len = bufsize;
-
- if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len)) {
- return NULL;
- }
-
- return buf;
- }
-
- return NULL;
-}
-
-static int inet_pton(Family family, const char *addrString, void *addrbuf)
-{
- if (family == TOX_AF_INET) {
- struct sockaddr_in saddr;
- memset(&saddr, 0, sizeof(saddr));
-
- INT len = sizeof(saddr);
-
- if (WSAStringToAddress((LPTSTR)addrString, AF_INET, NULL, (LPSOCKADDR)&saddr, &len)) {
- return 0;
- }
-
- *(struct in_addr *)addrbuf = saddr.sin_addr;
-
- return 1;
- } else if (family == TOX_AF_INET6) {
- struct sockaddr_in6 saddr;
- memset(&saddr, 0, sizeof(saddr));
-
- INT len = sizeof(saddr);
-
- if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, NULL, (LPSOCKADDR)&saddr, &len)) {
- return 0;
- }
-
- *(struct in6_addr *)addrbuf = saddr.sin6_addr;
-
- return 1;
- }
-
- return 0;
-}
-
-#endif
-
-#if TOX_INET6_ADDRSTRLEN < INET6_ADDRSTRLEN
-#error TOX_INET6_ADDRSTRLEN should be greater or equal to INET6_ADDRSTRLEN (#INET6_ADDRSTRLEN)
-#endif
-
-#if TOX_INET_ADDRSTRLEN < INET_ADDRSTRLEN
-#error TOX_INET_ADDRSTRLEN should be greater or equal to INET_ADDRSTRLEN (#INET_ADDRSTRLEN)
-#endif
-
-static int make_proto(int proto);
-static int make_socktype(int type);
-static int make_family(int tox_family);
-static int make_tox_family(int family);
-
-static void get_ip4(IP4 *result, const struct in_addr *addr)
-{
- result->uint32 = addr->s_addr;
-}
-
-static void get_ip6(IP6 *result, const struct in6_addr *addr)
-{
- assert(sizeof(result->uint8) == sizeof(addr->s6_addr));
- memcpy(result->uint8, addr->s6_addr, sizeof(result->uint8));
-}
-
-static void fill_addr4(IP4 ip, struct in_addr *addr)
-{
- addr->s_addr = ip.uint32;
-}
-
-static void fill_addr6(IP6 ip, struct in6_addr *addr)
-{
- assert(sizeof(ip.uint8) == sizeof(addr->s6_addr));
- memcpy(addr->s6_addr, ip.uint8, sizeof(ip.uint8));
-}
-
-#if !defined(INADDR_LOOPBACK)
-#define INADDR_LOOPBACK 0x7f000001
-#endif
-
-const IP4 IP4_BROADCAST = { INADDR_BROADCAST };
-const IP6 IP6_BROADCAST = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
-};
-
-IP4 get_ip4_loopback()
-{
- IP4 loopback;
- loopback.uint32 = htonl(INADDR_LOOPBACK);
- return loopback;
-}
-
-IP6 get_ip6_loopback()
-{
- IP6 loopback;
- get_ip6(&loopback, &in6addr_loopback);
- return loopback;
-}
-
-/* Check if socket is valid.
- *
- * return 1 if valid
- * return 0 if not valid
- */
-int sock_valid(Socket sock)
-{
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
-
- if (sock == INVALID_SOCKET) {
-#else
-
- if (sock < 0) {
-#endif
- return 0;
- }
-
- return 1;
-}
-
-/* Close the socket.
- */
-void kill_sock(Socket sock)
-{
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- closesocket(sock);
-#else
- close(sock);
-#endif
-}
-
-/* Set socket as nonblocking
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_nonblock(Socket sock)
-{
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- u_long mode = 1;
- return (ioctlsocket(sock, FIONBIO, &mode) == 0);
-#else
- return (fcntl(sock, F_SETFL, O_NONBLOCK, 1) == 0);
-#endif
-}
-
-/* Set socket to not emit SIGPIPE
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_nosigpipe(Socket sock)
-{
-#if defined(__MACH__)
- int set = 1;
- return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set, sizeof(int)) == 0);
-#else
- return 1;
-#endif
-}
-
-/* Enable SO_REUSEADDR on socket.
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_reuseaddr(Socket sock)
-{
- int set = 1;
- return (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&set, sizeof(set)) == 0);
-}
-
-/* Set socket to dual (IPv4 + IPv6 socket)
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_dualstack(Socket sock)
-{
- int ipv6only = 0;
- socklen_t optsize = sizeof(ipv6only);
- int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, &optsize);
-
- if ((res == 0) && (ipv6only == 0)) {
- return 1;
- }
-
- ipv6only = 0;
- return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) == 0);
-}
-
-
-/* return current UNIX time in microseconds (us). */
-static uint64_t current_time_actual(void)
-{
- uint64_t time;
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- /* This probably works fine */
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- time = ft.dwHighDateTime;
- time <<= 32;
- time |= ft.dwLowDateTime;
- time -= 116444736000000000ULL;
- return time / 10;
-#else
- struct timeval a;
- gettimeofday(&a, NULL);
- time = 1000000ULL * a.tv_sec + a.tv_usec;
- return time;
-#endif
-}
-
-
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
-static uint64_t last_monotime;
-static uint64_t add_monotime;
-#endif
-
-/* return current monotonic time in milliseconds (ms). */
-uint64_t current_time_monotonic(void)
-{
- uint64_t time;
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- uint64_t old_add_monotime = add_monotime;
- time = (uint64_t)GetTickCount() + add_monotime;
-
- /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
- * conditions when multiple threads call this function at once */
- if (time + 0x10000 < last_monotime) {
- uint32_t add = ~0;
- /* use old_add_monotime rather than simply incrementing add_monotime, to handle the case that many threads
- * simultaneously detect an overflow */
- add_monotime = old_add_monotime + add;
- time += add;
- }
-
- last_monotime = time;
-#else
- struct timespec monotime;
-#if defined(__linux__) && defined(CLOCK_MONOTONIC_RAW)
- clock_gettime(CLOCK_MONOTONIC_RAW, &monotime);
-#elif defined(__APPLE__)
- clock_serv_t muhclock;
- mach_timespec_t machtime;
-
- host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
- clock_get_time(muhclock, &machtime);
- mach_port_deallocate(mach_task_self(), muhclock);
-
- monotime.tv_sec = machtime.tv_sec;
- monotime.tv_nsec = machtime.tv_nsec;
-#else
- clock_gettime(CLOCK_MONOTONIC, &monotime);
-#endif
- time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL);
-#endif
- return time;
-}
-
-static uint32_t data_0(uint16_t buflen, const uint8_t *buffer)
-{
- return buflen > 4 ? net_ntohl(*(const uint32_t *)&buffer[1]) : 0;
-}
-static uint32_t data_1(uint16_t buflen, const uint8_t *buffer)
-{
- return buflen > 7 ? net_ntohl(*(const uint32_t *)&buffer[5]) : 0;
-}
-
-static void loglogdata(Logger *log, const char *message, const uint8_t *buffer,
- uint16_t buflen, IP_Port ip_port, int res)
-{
- char ip_str[IP_NTOA_LEN];
-
- if (res < 0) { /* Windows doesn't necessarily know %zu */
- LOGGER_TRACE(log, "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x",
- buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E',
- ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), errno,
- strerror(errno), data_0(buflen, buffer), data_1(buflen, buffer));
- } else if ((res > 0) && ((size_t)res <= buflen)) {
- LOGGER_TRACE(log, "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x",
- buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='),
- ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
- data_0(buflen, buffer), data_1(buflen, buffer));
- } else { /* empty or overwrite */
- LOGGER_TRACE(log, "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x",
- buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen,
- ip_ntoa(&ip_port.ip, ip_str, sizeof(ip_str)), net_ntohs(ip_port.port), 0, "OK",
- data_0(buflen, buffer), data_1(buflen, buffer));
- }
-}
-
-/* Basic network functions:
- * Function to send packet(data) of length length to ip_port.
- */
-int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length)
-{
- if (net->family == 0) { /* Socket not initialized */
- return -1;
- }
-
- /* socket TOX_AF_INET, but target IP NOT: can't send */
- if ((net->family == TOX_AF_INET) && (ip_port.ip.family != TOX_AF_INET)) {
- return -1;
- }
-
- struct sockaddr_storage addr;
-
- size_t addrsize = 0;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- if (net->family == TOX_AF_INET6) {
- /* must convert to IPV4-in-IPV6 address */
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
-
- addrsize = sizeof(struct sockaddr_in6);
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = ip_port.port;
-
- /* there should be a macro for this in a standards compliant
- * environment, not found */
- IP6 ip6;
-
- ip6.uint32[0] = 0;
- ip6.uint32[1] = 0;
- ip6.uint32[2] = net_htonl(0xFFFF);
- ip6.uint32[3] = ip_port.ip.ip4.uint32;
- fill_addr6(ip6, &addr6->sin6_addr);
-
- addr6->sin6_flowinfo = 0;
- addr6->sin6_scope_id = 0;
- } else {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
-
- addrsize = sizeof(struct sockaddr_in);
- addr4->sin_family = AF_INET;
- fill_addr4(ip_port.ip.ip4, &addr4->sin_addr);
- addr4->sin_port = ip_port.port;
- }
- } else if (ip_port.ip.family == TOX_AF_INET6) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
-
- addrsize = sizeof(struct sockaddr_in6);
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = ip_port.port;
- fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr);
-
- addr6->sin6_flowinfo = 0;
- addr6->sin6_scope_id = 0;
- } else {
- /* unknown address type*/
- return -1;
- }
-
- int res = sendto(net->sock, (const char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
-
- loglogdata(net->log, "O=>", data, length, ip_port, res);
-
- return res;
-}
-
-/* Function to receive data
- * ip and port of sender is put into ip_port.
- * Packet data is put into data.
- * Packet length is put into length.
- */
-static int receivepacket(Logger *log, Socket sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
-{
- memset(ip_port, 0, sizeof(IP_Port));
- struct sockaddr_storage addr;
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- int addrlen = sizeof(addr);
-#else
- socklen_t addrlen = sizeof(addr);
-#endif
- *length = 0;
- int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
-
- if (fail_or_len < 0) {
-
- if (fail_or_len < 0 && errno != EWOULDBLOCK) {
- LOGGER_ERROR(log, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
- }
-
- return -1; /* Nothing received. */
- }
-
- *length = (uint32_t)fail_or_len;
-
- if (addr.ss_family == AF_INET) {
- struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
-
- ip_port->ip.family = make_tox_family(addr_in->sin_family);
- get_ip4(&ip_port->ip.ip4, &addr_in->sin_addr);
- ip_port->port = addr_in->sin_port;
- } else if (addr.ss_family == AF_INET6) {
- struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
- ip_port->ip.family = make_tox_family(addr_in6->sin6_family);
- get_ip6(&ip_port->ip.ip6, &addr_in6->sin6_addr);
- ip_port->port = addr_in6->sin6_port;
-
- if (IPV6_IPV4_IN_V6(ip_port->ip.ip6)) {
- ip_port->ip.family = TOX_AF_INET;
- ip_port->ip.ip4.uint32 = ip_port->ip.ip6.uint32[3];
- }
- } else {
- return -1;
- }
-
- loglogdata(log, "=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length);
-
- return 0;
-}
-
-void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object)
-{
- net->packethandlers[byte].function = cb;
- net->packethandlers[byte].object = object;
-}
-
-void networking_poll(Networking_Core *net, void *userdata)
-{
- if (net->family == 0) { /* Socket not initialized */
- return;
- }
-
- unix_time_update();
-
- IP_Port ip_port;
- uint8_t data[MAX_UDP_PACKET_SIZE];
- uint32_t length;
-
- while (receivepacket(net->log, net->sock, &ip_port, data, &length) != -1) {
- if (length < 1) {
- continue;
- }
-
- if (!(net->packethandlers[data[0]].function)) {
- LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]);
- continue;
- }
-
- net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length, userdata);
- }
-}
-
-#ifndef VANILLA_NACL
-/* Used for sodium_init() */
-#include <sodium.h>
-#endif
-
-static uint8_t at_startup_ran = 0;
-int networking_at_startup(void)
-{
- if (at_startup_ran != 0) {
- return 0;
- }
-
-#ifndef VANILLA_NACL
-
-#ifdef USE_RANDOMBYTES_STIR
- randombytes_stir();
-#else
-
- if (sodium_init() == -1) {
- return -1;
- }
-
-#endif /*USE_RANDOMBYTES_STIR*/
-
-#endif/*VANILLA_NACL*/
-
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- WSADATA wsaData;
-
- if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
- return -1;
- }
-
-#endif
- srand((uint32_t)current_time_actual());
- at_startup_ran = 1;
- return 0;
-}
-
-/* TODO(irungentoo): Put this somewhere */
-#if 0
-static void at_shutdown(void)
-{
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
- WSACleanup();
-#endif
-}
-#endif
-
-/* Initialize networking.
- * Added for reverse compatibility with old new_networking calls.
- */
-Networking_Core *new_networking(Logger *log, IP ip, uint16_t port)
-{
- return new_networking_ex(log, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), 0);
-}
-
-/* Initialize networking.
- * Bind to ip and port.
- * ip must be in network order EX: 127.0.0.1 = (7F000001).
- * port is in host byte order (this means don't worry about it).
- *
- * return Networking_Core object if no problems
- * return NULL if there are problems.
- *
- * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
- */
-Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error)
-{
- /* If both from and to are 0, use default port range
- * If one is 0 and the other is non-0, use the non-0 value as only port
- * If from > to, swap
- */
- if (port_from == 0 && port_to == 0) {
- port_from = TOX_PORTRANGE_FROM;
- port_to = TOX_PORTRANGE_TO;
- } else if (port_from == 0 && port_to != 0) {
- port_from = port_to;
- } else if (port_from != 0 && port_to == 0) {
- port_to = port_from;
- } else if (port_from > port_to) {
- uint16_t temp = port_from;
- port_from = port_to;
- port_to = temp;
- }
-
- if (error) {
- *error = 2;
- }
-
- /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
- if (ip.family != TOX_AF_INET && ip.family != TOX_AF_INET6) {
- LOGGER_ERROR(log, "Invalid address family: %u\n", ip.family);
- return NULL;
- }
-
- if (networking_at_startup() != 0) {
- return NULL;
- }
-
- Networking_Core *temp = (Networking_Core *)calloc(1, sizeof(Networking_Core));
-
- if (temp == NULL) {
- return NULL;
- }
-
- temp->log = log;
- temp->family = ip.family;
- temp->port = 0;
-
- /* Initialize our socket. */
- /* add log message what we're creating */
- temp->sock = net_socket(temp->family, TOX_SOCK_DGRAM, TOX_PROTO_UDP);
-
- /* Check for socket error. */
- if (!sock_valid(temp->sock)) {
- LOGGER_ERROR(log, "Failed to get a socket?! %u, %s\n", errno, strerror(errno));
- free(temp);
-
- if (error) {
- *error = 1;
- }
-
- return NULL;
- }
-
- /* Functions to increase the size of the send and receive UDP buffers.
- */
- int n = 1024 * 1024 * 2;
- setsockopt(temp->sock, SOL_SOCKET, SO_RCVBUF, (const char *)&n, sizeof(n));
- setsockopt(temp->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&n, sizeof(n));
-
- /* Enable broadcast on socket */
- int broadcast = 1;
- setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast));
-
- /* iOS UDP sockets are weird and apparently can SIGPIPE */
- if (!set_socket_nosigpipe(temp->sock)) {
- kill_networking(temp);
-
- if (error) {
- *error = 1;
- }
-
- return NULL;
- }
-
- /* Set socket nonblocking. */
- if (!set_socket_nonblock(temp->sock)) {
- kill_networking(temp);
-
- if (error) {
- *error = 1;
- }
-
- return NULL;
- }
-
- /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
- uint16_t *portptr = NULL;
- struct sockaddr_storage addr;
- size_t addrsize;
-
- memset(&addr, 0, sizeof(struct sockaddr_storage));
-
- if (temp->family == TOX_AF_INET) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
-
- addrsize = sizeof(struct sockaddr_in);
- addr4->sin_family = AF_INET;
- addr4->sin_port = 0;
- fill_addr4(ip.ip4, &addr4->sin_addr);
-
- portptr = &addr4->sin_port;
- } else if (temp->family == TOX_AF_INET6) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
-
- addrsize = sizeof(struct sockaddr_in6);
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = 0;
- fill_addr6(ip.ip6, &addr6->sin6_addr);
-
- addr6->sin6_flowinfo = 0;
- addr6->sin6_scope_id = 0;
-
- portptr = &addr6->sin6_port;
- } else {
- free(temp);
- return NULL;
- }
-
- if (ip.family == TOX_AF_INET6) {
- int is_dualstack = set_socket_dualstack(temp->sock);
- LOGGER_DEBUG(log, "Dual-stack socket: %s",
- is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses");
- /* multicast local nodes */
- struct ipv6_mreq mreq;
- memset(&mreq, 0, sizeof(mreq));
- mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
- mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
- mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
- mreq.ipv6mr_interface = 0;
- int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char *)&mreq, sizeof(mreq));
-
- LOGGER_DEBUG(log, res < 0 ? "Failed to activate local multicast membership. (%u, %s)" :
- "Local multicast group FF02::1 joined successfully", errno, strerror(errno));
- }
-
- /* a hanging program or a different user might block the standard port;
- * as long as it isn't a parameter coming from the commandline,
- * try a few ports after it, to see if we can find a "free" one
- *
- * if we go on without binding, the first sendto() automatically binds to
- * a free port chosen by the system (i.e. anything from 1024 to 65535)
- *
- * returning NULL after bind fails has both advantages and disadvantages:
- * advantage:
- * we can rely on getting the port in the range 33445..33450, which
- * enables us to tell joe user to open their firewall to a small range
- *
- * disadvantage:
- * some clients might not test return of tox_new(), blindly assuming that
- * it worked ok (which it did previously without a successful bind)
- */
- uint16_t port_to_try = port_from;
- *portptr = net_htons(port_to_try);
- int tries;
-
- for (tries = port_from; tries <= port_to; tries++) {
- int res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
-
- if (!res) {
- temp->port = *portptr;
-
- char ip_str[IP_NTOA_LEN];
- LOGGER_DEBUG(log, "Bound successfully to %s:%u", ip_ntoa(&ip, ip_str, sizeof(ip_str)),
- net_ntohs(temp->port));
-
- /* errno isn't reset on success, only set on failure, the failed
- * binds with parallel clients yield a -EPERM to the outside if
- * errno isn't cleared here */
- if (tries > 0) {
- errno = 0;
- }
-
- if (error) {
- *error = 0;
- }
-
- return temp;
- }
-
- port_to_try++;
-
- if (port_to_try > port_to) {
- port_to_try = port_from;
- }
-
- *portptr = net_htons(port_to_try);
- }
-
- char ip_str[IP_NTOA_LEN];
- LOGGER_ERROR(log, "Failed to bind socket: %u, %s IP: %s port_from: %u port_to: %u", errno, strerror(errno),
- ip_ntoa(&ip, ip_str, sizeof(ip_str)), port_from, port_to);
-
- kill_networking(temp);
-
- if (error) {
- *error = 1;
- }
-
- return NULL;
-}
-
-/* Function to cleanup networking stuff. */
-void kill_networking(Networking_Core *net)
-{
- if (!net) {
- return;
- }
-
- if (net->family != 0) { /* Socket not initialized */
- kill_sock(net->sock);
- }
-
- free(net);
-}
-
-
-/* ip_equal
- * compares two IPAny structures
- * unset means unequal
- *
- * returns 0 when not equal or when uninitialized
- */
-int ip_equal(const IP *a, const IP *b)
-{
- if (!a || !b) {
- return 0;
- }
-
- /* same family */
- if (a->family == b->family) {
- if (a->family == TOX_AF_INET || a->family == TCP_INET) {
- struct in_addr addr_a;
- struct in_addr addr_b;
- fill_addr4(a->ip4, &addr_a);
- fill_addr4(b->ip4, &addr_b);
- return addr_a.s_addr == addr_b.s_addr;
- }
-
- if (a->family == TOX_AF_INET6 || a->family == TCP_INET6) {
- return a->ip6.uint64[0] == b->ip6.uint64[0] &&
- a->ip6.uint64[1] == b->ip6.uint64[1];
- }
-
- return 0;
- }
-
- /* different family: check on the IPv6 one if it is the IPv4 one embedded */
- if ((a->family == TOX_AF_INET) && (b->family == TOX_AF_INET6)) {
- if (IPV6_IPV4_IN_V6(b->ip6)) {
- struct in_addr addr_a;
- fill_addr4(a->ip4, &addr_a);
- return addr_a.s_addr == b->ip6.uint32[3];
- }
- } else if ((a->family == TOX_AF_INET6) && (b->family == TOX_AF_INET)) {
- if (IPV6_IPV4_IN_V6(a->ip6)) {
- struct in_addr addr_b;
- fill_addr4(b->ip4, &addr_b);
- return a->ip6.uint32[3] == addr_b.s_addr;
- }
- }
-
- return 0;
-}
-
-/* ipport_equal
- * compares two IPAny_Port structures
- * unset means unequal
- *
- * returns 0 when not equal or when uninitialized
- */
-int ipport_equal(const IP_Port *a, const IP_Port *b)
-{
- if (!a || !b) {
- return 0;
- }
-
- if (!a->port || (a->port != b->port)) {
- return 0;
- }
-
- return ip_equal(&a->ip, &b->ip);
-}
-
-/* nulls out ip */
-void ip_reset(IP *ip)
-{
- if (!ip) {
- return;
- }
-
- memset(ip, 0, sizeof(IP));
-}
-
-/* nulls out ip, sets family according to flag */
-void ip_init(IP *ip, uint8_t ipv6enabled)
-{
- if (!ip) {
- return;
- }
-
- memset(ip, 0, sizeof(IP));
- ip->family = ipv6enabled ? TOX_AF_INET6 : TOX_AF_INET;
-}
-
-/* checks if ip is valid */
-int ip_isset(const IP *ip)
-{
- if (!ip) {
- return 0;
- }
-
- return (ip->family != 0);
-}
-
-/* checks if ip is valid */
-int ipport_isset(const IP_Port *ipport)
-{
- if (!ipport) {
- return 0;
- }
-
- if (!ipport->port) {
- return 0;
- }
-
- return ip_isset(&ipport->ip);
-}
-
-/* copies an ip structure (careful about direction!) */
-void ip_copy(IP *target, const IP *source)
-{
- if (!source || !target) {
- return;
- }
-
- memcpy(target, source, sizeof(IP));
-}
-
-/* copies an ip_port structure (careful about direction!) */
-void ipport_copy(IP_Port *target, const IP_Port *source)
-{
- if (!source || !target) {
- return;
- }
-
- memcpy(target, source, sizeof(IP_Port));
-}
-
-/* ip_ntoa
- * converts ip into a string
- * ip_str must be of length at least IP_NTOA_LEN
- *
- * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
- * writes error message into the buffer on error
- *
- * returns ip_str
- */
-const char *ip_ntoa(const IP *ip, char *ip_str, size_t length)
-{
- if (length < IP_NTOA_LEN) {
- snprintf(ip_str, length, "Bad buf length");
- return ip_str;
- }
-
- if (ip) {
- const int family = make_family(ip->family);
-
- if (ip->family == TOX_AF_INET) {
- /* returns standard quad-dotted notation */
- struct in_addr addr;
- fill_addr4(ip->ip4, &addr);
-
- ip_str[0] = 0;
- inet_ntop(family, &addr, ip_str, length);
- } else if (ip->family == TOX_AF_INET6) {
- /* returns hex-groups enclosed into square brackets */
- struct in6_addr addr;
- fill_addr6(ip->ip6, &addr);
-
- ip_str[0] = '[';
- inet_ntop(family, &addr, &ip_str[1], length - 3);
- size_t len = strlen(ip_str);
- ip_str[len] = ']';
- ip_str[len + 1] = 0;
- } else {
- snprintf(ip_str, length, "(IP invalid, family %u)", ip->family);
- }
- } else {
- snprintf(ip_str, length, "(IP invalid: NULL)");
- }
-
- /* brute force protection against lacking termination */
- ip_str[length - 1] = 0;
- return ip_str;
-}
-
-/*
- * ip_parse_addr
- * parses IP structure into an address string
- *
- * input
- * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
- * length: length of the address buffer
- * Must be at least INET_ADDRSTRLEN for TOX_AF_INET
- * and INET6_ADDRSTRLEN for TOX_AF_INET6
- *
- * output
- * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
- *
- * returns 1 on success, 0 on failure
- */
-int ip_parse_addr(const IP *ip, char *address, size_t length)
-{
- if (!address || !ip) {
- return 0;
- }
-
- if (ip->family == TOX_AF_INET) {
- const struct in_addr *addr = (const struct in_addr *)&ip->ip4;
- return inet_ntop(ip->family, addr, address, length) != NULL;
- }
-
- if (ip->family == TOX_AF_INET6) {
- const struct in6_addr *addr = (const struct in6_addr *)&ip->ip6;
- return inet_ntop(ip->family, addr, address, length) != NULL;
- }
-
- return 0;
-}
-
-/*
- * addr_parse_ip
- * directly parses the input into an IP structure
- * tries IPv4 first, then IPv6
- *
- * input
- * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
- *
- * output
- * IP: family and the value is set on success
- *
- * returns 1 on success, 0 on failure
- */
-int addr_parse_ip(const char *address, IP *to)
-{
- if (!address || !to) {
- return 0;
- }
-
- struct in_addr addr4;
-
- if (inet_pton(AF_INET, address, &addr4) == 1) {
- to->family = TOX_AF_INET;
- get_ip4(&to->ip4, &addr4);
- return 1;
- }
-
- struct in6_addr addr6;
-
- if (inet_pton(AF_INET6, address, &addr6) == 1) {
- to->family = TOX_AF_INET6;
- get_ip6(&to->ip6, &addr6);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * addr_resolve():
- * uses getaddrinfo to resolve an address into an IP address
- * uses the first IPv4/IPv6 addresses returned by getaddrinfo
- *
- * input
- * address: a hostname (or something parseable to an IP address)
- * to: to.family MUST be initialized, either set to a specific IP version
- * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
- * IP versions are acceptable
- * extra can be NULL and is only set in special circumstances, see returns
- *
- * returns in *to a valid IPAny (v4/v6),
- * prefers v6 if ip.family was AF_UNSPEC and both available
- * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is TOX_AF_INET6
- * returns 0 on failure, TOX_ADDR_RESOLVE_* on success.
- */
-int addr_resolve(const char *address, IP *to, IP *extra)
-{
- if (!address || !to) {
- return 0;
- }
-
- Family tox_family = to->family;
- Family family = make_family(tox_family);
-
- struct addrinfo *server = NULL;
- struct addrinfo *walker = NULL;
- struct addrinfo hints;
- int rc;
- int result = 0;
- int done = 0;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
-
- if (networking_at_startup() != 0) {
- return 0;
- }
-
- rc = getaddrinfo(address, NULL, &hints, &server);
-
- // Lookup failed.
- if (rc != 0) {
- return 0;
- }
-
- IP ip4;
- ip_init(&ip4, 0); // ipv6enabled = 0
- IP ip6;
- ip_init(&ip6, 1); // ipv6enabled = 1
-
- for (walker = server; (walker != NULL) && !done; walker = walker->ai_next) {
- switch (walker->ai_family) {
- case AF_INET:
- if (walker->ai_family == family) { /* AF_INET requested, done */
- struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
- get_ip4(&to->ip4, &addr->sin_addr);
- result = TOX_ADDR_RESOLVE_INET;
- done = 1;
- } else if (!(result & TOX_ADDR_RESOLVE_INET)) { /* AF_UNSPEC requested, store away */
- struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
- get_ip4(&ip4.ip4, &addr->sin_addr);
- result |= TOX_ADDR_RESOLVE_INET;
- }
-
- break; /* switch */
-
- case AF_INET6:
- if (walker->ai_family == family) { /* AF_INET6 requested, done */
- if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
- struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
- get_ip6(&to->ip6, &addr->sin6_addr);
- result = TOX_ADDR_RESOLVE_INET6;
- done = 1;
- }
- } else if (!(result & TOX_ADDR_RESOLVE_INET6)) { /* AF_UNSPEC requested, store away */
- if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
- struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
- get_ip6(&ip6.ip6, &addr->sin6_addr);
- result |= TOX_ADDR_RESOLVE_INET6;
- }
- }
-
- break; /* switch */
- }
- }
-
- if (family == AF_UNSPEC) {
- if (result & TOX_ADDR_RESOLVE_INET6) {
- ip_copy(to, &ip6);
-
- if ((result & TOX_ADDR_RESOLVE_INET) && (extra != NULL)) {
- ip_copy(extra, &ip4);
- }
- } else if (result & TOX_ADDR_RESOLVE_INET) {
- ip_copy(to, &ip4);
- } else {
- result = 0;
- }
- }
-
- freeaddrinfo(server);
- return result;
-}
-
-/*
- * addr_resolve_or_parse_ip
- * resolves string into an IP address
- *
- * address: a hostname (or something parseable to an IP address)
- * to: to.family MUST be initialized, either set to a specific IP version
- * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
- * IP versions are acceptable
- * extra can be NULL and is only set in special circumstances, see returns
- *
- * returns in *tro a matching address (IPv6 or IPv4)
- * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
- * returns 1 on success
- * returns 0 on failure
- */
-int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
-{
- if (!addr_resolve(address, to, extra)) {
- if (!addr_parse_ip(address, to)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-int net_connect(Socket sock, IP_Port ip_port)
-{
- struct sockaddr_storage addr = {0};
- size_t addrsize;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
-
- addrsize = sizeof(struct sockaddr_in);
- addr4->sin_family = AF_INET;
- fill_addr4(ip_port.ip.ip4, &addr4->sin_addr);
- addr4->sin_port = ip_port.port;
- } else if (ip_port.ip.family == TOX_AF_INET6) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
-
- addrsize = sizeof(struct sockaddr_in6);
- addr6->sin6_family = AF_INET6;
- fill_addr6(ip_port.ip.ip6, &addr6->sin6_addr);
- addr6->sin6_port = ip_port.port;
- } else {
- return 0;
- }
-
- return connect(sock, (struct sockaddr *)&addr, addrsize);
-}
-
-int32_t net_getipport(const char *node, IP_Port **res, int tox_type)
-{
- struct addrinfo *infos;
- int ret = getaddrinfo(node, NULL, NULL, &infos);
- *res = NULL;
-
- if (ret != 0) {
- return -1;
- }
-
- // Used to avoid malloc parameter overflow
- const size_t MAX_COUNT = MIN(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
- int type = make_socktype(tox_type);
- struct addrinfo *cur;
- int32_t count = 0;
-
- for (cur = infos; count < MAX_COUNT && cur != NULL; cur = cur->ai_next) {
- if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
- continue;
- }
-
- if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
- continue;
- }
-
- count++;
- }
-
- assert(count <= MAX_COUNT);
-
- if (count == 0) {
- return 0;
- }
-
- *res = (IP_Port *)malloc(sizeof(IP_Port) * count);
-
- if (*res == NULL) {
- return -1;
- }
-
- IP_Port *ip_port = *res;
-
- for (cur = infos; cur != NULL; cur = cur->ai_next) {
- if (cur->ai_socktype && type > 0 && cur->ai_socktype != type) {
- continue;
- }
-
- if (cur->ai_family == AF_INET) {
- struct sockaddr_in *addr = (struct sockaddr_in *)cur->ai_addr;
- memcpy(&ip_port->ip.ip4, &addr->sin_addr, sizeof(IP4));
- } else if (cur->ai_family == AF_INET6) {
- struct sockaddr_in6 *addr = (struct sockaddr_in6 *)cur->ai_addr;
- memcpy(&ip_port->ip.ip6, &addr->sin6_addr, sizeof(IP6));
- } else {
- continue;
- }
-
- ip_port->ip.family = make_tox_family(cur->ai_family);
-
- ip_port++;
- }
-
- freeaddrinfo(infos);
-
- return count;
-}
-
-void net_freeipport(IP_Port *ip_ports)
-{
- free(ip_ports);
-}
-
-/* return 1 on success
- * return 0 on failure
- */
-int bind_to_port(Socket sock, int family, uint16_t port)
-{
- struct sockaddr_storage addr = {0};
- size_t addrsize;
-
- if (family == TOX_AF_INET) {
- struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
-
- addrsize = sizeof(struct sockaddr_in);
- addr4->sin_family = AF_INET;
- addr4->sin_port = net_htons(port);
- } else if (family == TOX_AF_INET6) {
- struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
-
- addrsize = sizeof(struct sockaddr_in6);
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = net_htons(port);
- } else {
- return 0;
- }
-
- return (bind(sock, (struct sockaddr *)&addr, addrsize) == 0);
-}
-
-static int make_tox_family(int family)
-{
- switch (family) {
- case AF_INET:
- return TOX_AF_INET;
-
- case AF_INET6:
- return TOX_AF_INET6;
-
- case AF_UNSPEC:
- return TOX_AF_UNSPEC;
-
- default:
- return family;
- }
-}
-
-static int make_family(int tox_family)
-{
- switch (tox_family) {
- case TOX_AF_INET:
- return AF_INET;
-
- case TOX_AF_INET6:
- return AF_INET6;
-
- case TOX_AF_UNSPEC:
- return AF_UNSPEC;
-
- default:
- return tox_family;
- }
-}
-
-static int make_socktype(int type)
-{
- switch (type) {
- case TOX_SOCK_STREAM:
- return SOCK_STREAM;
-
- case TOX_SOCK_DGRAM:
- return SOCK_DGRAM;
-
- default:
- return type;
- }
-}
-
-static int make_proto(int proto)
-{
- switch (proto) {
- case TOX_PROTO_TCP:
- return IPPROTO_TCP;
-
- case TOX_PROTO_UDP:
- return IPPROTO_UDP;
-
- default:
- return proto;
- }
-}
-
-Socket net_socket(int domain, int type, int protocol)
-{
- int platform_domain = make_family(domain);
- int platform_type = make_socktype(type);
- int platform_prot = make_proto(protocol);
- return socket(platform_domain, platform_type, platform_prot);
-}
-
-/* TODO: Remove, when tox DNS support will be removed.
- * Used only by dns3_test.c
- */
-size_t net_sendto_ip4(Socket sock, const char *buf, size_t n, IP_Port ip_port)
-{
- struct sockaddr_in target;
- size_t addrsize = sizeof(target);
- target.sin_family = make_family(ip_port.ip.family);
- target.sin_port = net_htons(ip_port.port);
- fill_addr4(ip_port.ip.ip4, &target.sin_addr);
-
- return (size_t)sendto(sock, buf, n, 0, (struct sockaddr *)&target, addrsize);
-}
-
-uint32_t net_htonl(uint32_t hostlong)
-{
- return htonl(hostlong);
-}
-
-uint16_t net_htons(uint16_t hostshort)
-{
- return htons(hostshort);
-}
-
-uint32_t net_ntohl(uint32_t hostlong)
-{
- return ntohl(hostlong);
-}
-
-uint16_t net_ntohs(uint16_t hostshort)
-{
- return ntohs(hostshort);
-}
diff --git a/libs/libtox/src/toxcore/network.h b/libs/libtox/src/toxcore/network.h
deleted file mode 100644
index 0b9da5a40f..0000000000
--- a/libs/libtox/src/toxcore/network.h
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Datatypes, functions and includes for the core networking.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef NETWORK_H
-#define NETWORK_H
-
-#ifdef PLAN9
-#include <u.h> // Plan 9 requires this is imported first
-// Comment line here to avoid reordering by source code formatters.
-#include <libc.h>
-#endif
-
-#include "ccompat.h"
-#include "logger.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) /* Put win32 includes here */
-#ifndef WINVER
-//Windows XP
-#define WINVER 0x0501
-#endif
-
-// The mingw32/64 Windows library warns about including winsock2.h after
-// windows.h even though with the above it's a valid thing to do. So, to make
-// mingw32 headers happy, we include winsock2.h first.
-#include <winsock2.h>
-
-#include <windows.h>
-#include <ws2tcpip.h>
-
-#else // UNIX includes
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#endif
-
-typedef short Family;
-
-typedef int Socket;
-Socket net_socket(int domain, int type, int protocol);
-
-#define MAX_UDP_PACKET_SIZE 2048
-
-typedef enum NET_PACKET_TYPE {
- NET_PACKET_PING_REQUEST = 0x00, /* Ping request packet ID. */
- NET_PACKET_PING_RESPONSE = 0x01, /* Ping response packet ID. */
- NET_PACKET_GET_NODES = 0x02, /* Get nodes request packet ID. */
- NET_PACKET_SEND_NODES_IPV6 = 0x04, /* Send nodes response packet ID for other addresses. */
- NET_PACKET_COOKIE_REQUEST = 0x18, /* Cookie request packet */
- NET_PACKET_COOKIE_RESPONSE = 0x19, /* Cookie response packet */
- NET_PACKET_CRYPTO_HS = 0x1a, /* Crypto handshake packet */
- NET_PACKET_CRYPTO_DATA = 0x1b, /* Crypto data packet */
- NET_PACKET_CRYPTO = 0x20, /* Encrypted data packet ID. */
- NET_PACKET_LAN_DISCOVERY = 0x21, /* LAN discovery packet ID. */
-
- /* See: docs/Prevent_Tracking.txt and onion.{c,h} */
- NET_PACKET_ONION_SEND_INITIAL = 0x80,
- NET_PACKET_ONION_SEND_1 = 0x81,
- NET_PACKET_ONION_SEND_2 = 0x82,
-
- NET_PACKET_ANNOUNCE_REQUEST = 0x83,
- NET_PACKET_ANNOUNCE_RESPONSE = 0x84,
- NET_PACKET_ONION_DATA_REQUEST = 0x85,
- NET_PACKET_ONION_DATA_RESPONSE = 0x86,
-
- NET_PACKET_ONION_RECV_3 = 0x8c,
- NET_PACKET_ONION_RECV_2 = 0x8d,
- NET_PACKET_ONION_RECV_1 = 0x8e,
-
- BOOTSTRAP_INFO_PACKET_ID = 0xf0, /* Only used for bootstrap nodes */
-
- NET_PACKET_MAX = 0xff, /* This type must remain within a single uint8. */
-} NET_PACKET_TYPE;
-
-
-#define TOX_PORTRANGE_FROM 33445
-#define TOX_PORTRANGE_TO 33545
-#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
-
-/* Redefinitions of variables for safe transfer over wire. */
-#define TOX_AF_UNSPEC 0
-#define TOX_AF_INET 2
-#define TOX_AF_INET6 10
-#define TOX_TCP_INET 130
-#define TOX_TCP_INET6 138
-
-#define TOX_SOCK_STREAM 1
-#define TOX_SOCK_DGRAM 2
-
-#define TOX_PROTO_TCP 1
-#define TOX_PROTO_UDP 2
-
-/* TCP related */
-#define TCP_ONION_FAMILY (TOX_AF_INET6 + 1)
-#define TCP_INET (TOX_AF_INET6 + 2)
-#define TCP_INET6 (TOX_AF_INET6 + 3)
-#define TCP_FAMILY (TOX_AF_INET6 + 4)
-
-typedef union {
- uint32_t uint32;
- uint16_t uint16[2];
- uint8_t uint8[4];
-}
-IP4;
-
-IP4 get_ip4_loopback(void);
-extern const IP4 IP4_BROADCAST;
-
-typedef union {
- uint8_t uint8[16];
- uint16_t uint16[8];
- uint32_t uint32[4];
- uint64_t uint64[2];
-}
-IP6;
-
-IP6 get_ip6_loopback(void);
-extern const IP6 IP6_BROADCAST;
-
-typedef struct {
- uint8_t family;
- GNU_EXTENSION union {
- IP4 ip4;
- IP6 ip6;
- };
-}
-IP;
-
-typedef struct {
- IP ip;
- uint16_t port;
-}
-IP_Port;
-
-/* Convert values between host and network byte order.
- */
-uint32_t net_htonl(uint32_t hostlong);
-uint16_t net_htons(uint16_t hostshort);
-uint32_t net_ntohl(uint32_t hostlong);
-uint16_t net_ntohs(uint16_t hostshort);
-
-/* Does the IP6 struct a contain an IPv4 address in an IPv6 one? */
-#define IPV6_IPV4_IN_V6(a) ((a.uint64[0] == 0) && (a.uint32[2] == net_htonl (0xffff)))
-
-#define SIZE_IP4 4
-#define SIZE_IP6 16
-#define SIZE_IP (1 + SIZE_IP6)
-#define SIZE_PORT 2
-#define SIZE_IPPORT (SIZE_IP + SIZE_PORT)
-
-#define TOX_ENABLE_IPV6_DEFAULT 1
-
-/* addr_resolve return values */
-#define TOX_ADDR_RESOLVE_INET 1
-#define TOX_ADDR_RESOLVE_INET6 2
-
-#define TOX_INET6_ADDRSTRLEN 66
-#define TOX_INET_ADDRSTRLEN 22
-
-/* ip_ntoa
- * converts ip into a string
- * ip_str must be of length at least IP_NTOA_LEN
- *
- * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
- * writes error message into the buffer on error
- *
- * returns ip_str
- */
-/* this would be TOX_INET6_ADDRSTRLEN, but it might be too short for the error message */
-#define IP_NTOA_LEN 96 // TODO(irungentoo): magic number. Why not INET6_ADDRSTRLEN ?
-const char *ip_ntoa(const IP *ip, char *ip_str, size_t length);
-
-/*
- * ip_parse_addr
- * parses IP structure into an address string
- *
- * input
- * ip: ip of TOX_AF_INET or TOX_AF_INET6 families
- * length: length of the address buffer
- * Must be at least TOX_INET_ADDRSTRLEN for TOX_AF_INET
- * and TOX_INET6_ADDRSTRLEN for TOX_AF_INET6
- *
- * output
- * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
- *
- * returns 1 on success, 0 on failure
- */
-int ip_parse_addr(const IP *ip, char *address, size_t length);
-
-/*
- * addr_parse_ip
- * directly parses the input into an IP structure
- * tries IPv4 first, then IPv6
- *
- * input
- * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
- *
- * output
- * IP: family and the value is set on success
- *
- * returns 1 on success, 0 on failure
- */
-int addr_parse_ip(const char *address, IP *to);
-
-/* ip_equal
- * compares two IPAny structures
- * unset means unequal
- *
- * returns 0 when not equal or when uninitialized
- */
-int ip_equal(const IP *a, const IP *b);
-
-/* ipport_equal
- * compares two IPAny_Port structures
- * unset means unequal
- *
- * returns 0 when not equal or when uninitialized
- */
-int ipport_equal(const IP_Port *a, const IP_Port *b);
-
-/* nulls out ip */
-void ip_reset(IP *ip);
-/* nulls out ip, sets family according to flag */
-void ip_init(IP *ip, uint8_t ipv6enabled);
-/* checks if ip is valid */
-int ip_isset(const IP *ip);
-/* checks if ip is valid */
-int ipport_isset(const IP_Port *ipport);
-/* copies an ip structure */
-void ip_copy(IP *target, const IP *source);
-/* copies an ip_port structure */
-void ipport_copy(IP_Port *target, const IP_Port *source);
-
-/*
- * addr_resolve():
- * uses getaddrinfo to resolve an address into an IP address
- * uses the first IPv4/IPv6 addresses returned by getaddrinfo
- *
- * input
- * address: a hostname (or something parseable to an IP address)
- * to: to.family MUST be initialized, either set to a specific IP version
- * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
- * IP versions are acceptable
- * extra can be NULL and is only set in special circumstances, see returns
- *
- * returns in *to a valid IPAny (v4/v6),
- * prefers v6 if ip.family was TOX_AF_UNSPEC and both available
- * returns in *extra an IPv4 address, if family was TOX_AF_UNSPEC and *to is TOX_AF_INET6
- * returns 0 on failure
- */
-int addr_resolve(const char *address, IP *to, IP *extra);
-
-/*
- * addr_resolve_or_parse_ip
- * resolves string into an IP address
- *
- * address: a hostname (or something parseable to an IP address)
- * to: to.family MUST be initialized, either set to a specific IP version
- * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (= 0), if both
- * IP versions are acceptable
- * extra can be NULL and is only set in special circumstances, see returns
- *
- * returns in *tro a matching address (IPv6 or IPv4)
- * returns in *extra, if not NULL, an IPv4 address, if to->family was TOX_AF_UNSPEC
- * returns 1 on success
- * returns 0 on failure
- */
-int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra);
-
-/* Function to receive data, ip and port of sender is put into ip_port.
- * Packet data is put into data.
- * Packet length is put into length.
- */
-typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, const uint8_t *data, uint16_t len,
- void *userdata);
-
-typedef struct {
- packet_handler_callback function;
- void *object;
-} Packet_Handles;
-
-typedef struct {
- Logger *log;
- Packet_Handles packethandlers[256];
-
- Family family;
- uint16_t port;
- /* Our UDP socket. */
- Socket sock;
-} Networking_Core;
-
-/* Run this before creating sockets.
- *
- * return 0 on success
- * return -1 on failure
- */
-int networking_at_startup(void);
-
-/* Check if socket is valid.
- *
- * return 1 if valid
- * return 0 if not valid
- */
-int sock_valid(Socket sock);
-
-/* Close the socket.
- */
-void kill_sock(Socket sock);
-
-/* Set socket as nonblocking
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_nonblock(Socket sock);
-
-/* Set socket to not emit SIGPIPE
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_nosigpipe(Socket sock);
-
-/* Enable SO_REUSEADDR on socket.
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_reuseaddr(Socket sock);
-
-/* Set socket to dual (IPv4 + IPv6 socket)
- *
- * return 1 on success
- * return 0 on failure
- */
-int set_socket_dualstack(Socket sock);
-
-/* return current monotonic time in milliseconds (ms). */
-uint64_t current_time_monotonic(void);
-
-/* Basic network functions: */
-
-/* Function to send packet(data) of length length to ip_port. */
-int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint16_t length);
-
-/* Function to call when packet beginning with byte is received. */
-void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
-
-/* Call this several times a second. */
-void networking_poll(Networking_Core *net, void *userdata);
-
-/* Connect a socket to the address specified by the ip_port. */
-int net_connect(Socket sock, IP_Port ip_port);
-
-/* High-level getaddrinfo implementation.
- * Given node, which identifies an Internet host, net_getipport() fills an array
- * with one or more IP_Port structures, each of which contains an Internet
- * address that can be specified by calling net_connect(), the port is ignored.
- *
- * Skip all addresses with socktype != type (use type = -1 to get all addresses)
- * To correctly deallocate array memory use net_freeipport()
- *
- * return number of elements in res array
- * and -1 on error.
- */
-int32_t net_getipport(const char *node, IP_Port **res, int tox_type);
-
-/* Deallocates memory allocated by net_getipport
- */
-void net_freeipport(IP_Port *ip_ports);
-
-/* return 1 on success
- * return 0 on failure
- */
-int bind_to_port(Socket sock, int family, uint16_t port);
-
-size_t net_sendto_ip4(Socket sock, const char *buf, size_t n, IP_Port ip_port);
-
-/* Initialize networking.
- * bind to ip and port.
- * ip must be in network order EX: 127.0.0.1 = (7F000001).
- * port is in host byte order (this means don't worry about it).
- *
- * return Networking_Core object if no problems
- * return NULL if there are problems.
- *
- * If error is non NULL it is set to 0 if no issues, 1 if socket related error, 2 if other.
- */
-Networking_Core *new_networking(Logger *log, IP ip, uint16_t port);
-Networking_Core *new_networking_ex(Logger *log, IP ip, uint16_t port_from, uint16_t port_to, unsigned int *error);
-
-/* Function to cleanup networking stuff (doesn't do much right now). */
-void kill_networking(Networking_Core *net);
-
-#endif
diff --git a/libs/libtox/src/toxcore/onion.c b/libs/libtox/src/toxcore/onion.c
deleted file mode 100644
index fbaf7205d9..0000000000
--- a/libs/libtox/src/toxcore/onion.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Implementation of the onion part of docs/Prevent_Tracking.txt
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "onion.h"
-
-#include "util.h"
-
-#define RETURN_1 ONION_RETURN_1
-#define RETURN_2 ONION_RETURN_2
-#define RETURN_3 ONION_RETURN_3
-
-#define SEND_BASE ONION_SEND_BASE
-#define SEND_3 ONION_SEND_3
-#define SEND_2 ONION_SEND_2
-#define SEND_1 ONION_SEND_1
-
-/* Change symmetric keys every 2 hours to make paths expire eventually. */
-#define KEY_REFRESH_INTERVAL (2 * 60 * 60)
-static void change_symmetric_key(Onion *onion)
-{
- if (is_timeout(onion->timestamp, KEY_REFRESH_INTERVAL)) {
- new_symmetric_key(onion->secret_symmetric_key);
- onion->timestamp = unix_time();
- }
-}
-
-/* packing and unpacking functions */
-static void ip_pack(uint8_t *data, IP source)
-{
- data[0] = source.family;
-
- if (source.family == TOX_AF_INET || source.family == TOX_TCP_INET) {
- memset(data + 1, 0, SIZE_IP6);
- memcpy(data + 1, source.ip4.uint8, SIZE_IP4);
- } else {
- memcpy(data + 1, source.ip6.uint8, SIZE_IP6);
- }
-}
-
-/* return 0 on success, -1 on failure. */
-static int ip_unpack(IP *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
-{
- if (data_size < (1 + SIZE_IP6)) {
- return -1;
- }
-
- target->family = data[0];
-
- if (target->family == TOX_AF_INET || target->family == TOX_TCP_INET) {
- memcpy(target->ip4.uint8, data + 1, SIZE_IP4);
- } else {
- memcpy(target->ip6.uint8, data + 1, SIZE_IP6);
- }
-
- bool valid = disable_family_check ||
- target->family == TOX_AF_INET ||
- target->family == TOX_AF_INET6;
-
- return valid ? 0 : -1;
-}
-
-static void ipport_pack(uint8_t *data, const IP_Port *source)
-{
- ip_pack(data, source->ip);
- memcpy(data + SIZE_IP, &source->port, SIZE_PORT);
-}
-
-/* return 0 on success, -1 on failure. */
-static int ipport_unpack(IP_Port *target, const uint8_t *data, unsigned int data_size, bool disable_family_check)
-{
- if (data_size < (SIZE_IP + SIZE_PORT)) {
- return -1;
- }
-
- if (ip_unpack(&target->ip, data, data_size, disable_family_check) == -1) {
- return -1;
- }
-
- memcpy(&target->port, data + SIZE_IP, SIZE_PORT);
- return 0;
-}
-
-
-/* Create a new onion path.
- *
- * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
- *
- * new_path must be an empty memory location of atleast Onion_Path size.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes)
-{
- if (!new_path || !nodes) {
- return -1;
- }
-
- encrypt_precompute(nodes[0].public_key, dht->self_secret_key, new_path->shared_key1);
- memcpy(new_path->public_key1, dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- crypto_new_keypair(random_public_key, random_secret_key);
- encrypt_precompute(nodes[1].public_key, random_secret_key, new_path->shared_key2);
- memcpy(new_path->public_key2, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- crypto_new_keypair(random_public_key, random_secret_key);
- encrypt_precompute(nodes[2].public_key, random_secret_key, new_path->shared_key3);
- memcpy(new_path->public_key3, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- new_path->ip_port1 = nodes[0].ip_port;
- new_path->ip_port2 = nodes[1].ip_port;
- new_path->ip_port3 = nodes[2].ip_port;
-
- memcpy(new_path->node_public_key1, nodes[0].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(new_path->node_public_key2, nodes[1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(new_path->node_public_key3, nodes[2].public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- return 0;
-}
-
-/* Dump nodes in onion path to nodes of length num_nodes;
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path)
-{
- if (num_nodes < ONION_PATH_LENGTH) {
- return -1;
- }
-
- nodes[0].ip_port = path->ip_port1;
- nodes[1].ip_port = path->ip_port2;
- nodes[2].ip_port = path->ip_port3;
-
- memcpy(nodes[0].public_key, path->node_public_key1, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(nodes[1].public_key, path->node_public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(nodes[2].public_key, path->node_public_key3, CRYPTO_PUBLIC_KEY_SIZE);
- return 0;
-}
-
-/* Create a onion packet.
- *
- * Use Onion_Path path to create packet for data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- * packet should be at least ONION_MAX_PACKET_SIZE big.
- *
- * return -1 on failure.
- * return length of created packet on success.
- */
-int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
- const uint8_t *data, uint16_t length)
-{
- if (1 + length + SEND_1 > max_packet_length || length == 0) {
- return -1;
- }
-
- VLA(uint8_t, step1, SIZE_IPPORT + length);
-
- ipport_pack(step1, &dest);
- memcpy(step1 + SIZE_IPPORT, data, length);
-
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
-
- VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
- ipport_pack(step2, &path->ip_port3);
- memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
-
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
- step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- VLA(uint8_t, step3, SIZE_IPPORT + SEND_BASE * 2 + length);
- ipport_pack(step3, &path->ip_port2);
- memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
- step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- packet[0] = NET_PACKET_ONION_SEND_INITIAL;
- memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
- memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
-
- len = encrypt_data_symmetric(path->shared_key1, nonce, step3, SIZEOF_VLA(step3),
- packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- return 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len;
-}
-
-/* Create a onion packet to be sent over tcp.
- *
- * Use Onion_Path path to create packet for data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- * packet should be at least ONION_MAX_PACKET_SIZE big.
- *
- * return -1 on failure.
- * return length of created packet on success.
- */
-int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
- const uint8_t *data, uint16_t length)
-{
- if (CRYPTO_NONCE_SIZE + SIZE_IPPORT + SEND_BASE * 2 + length > max_packet_length || length == 0) {
- return -1;
- }
-
- VLA(uint8_t, step1, SIZE_IPPORT + length);
-
- ipport_pack(step1, &dest);
- memcpy(step1 + SIZE_IPPORT, data, length);
-
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
-
- VLA(uint8_t, step2, SIZE_IPPORT + SEND_BASE + length);
- ipport_pack(step2, &path->ip_port3);
- memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
-
- int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, SIZEOF_VLA(step1),
- step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
- memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
- len = encrypt_data_symmetric(path->shared_key2, nonce, step2, SIZEOF_VLA(step2),
- packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
- return -1;
- }
-
- memcpy(packet, nonce, CRYPTO_NONCE_SIZE);
-
- return CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE + len;
-}
-
-/* Create and send a onion packet.
- *
- * Use Onion_Path path to send data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length)
-{
- uint8_t packet[ONION_MAX_PACKET_SIZE];
- int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
-
- if (len == -1) {
- return -1;
- }
-
- if (sendpacket(net, path->ip_port1, packet, len) != len) {
- return -1;
- }
-
- return 0;
-}
-
-/* Create and send a onion response sent initially to dest with.
- * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret)
-{
- if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) {
- return -1;
- }
-
- VLA(uint8_t, packet, 1 + RETURN_3 + length);
- packet[0] = NET_PACKET_ONION_RECV_3;
- memcpy(packet + 1, ret, RETURN_3);
- memcpy(packet + 1 + RETURN_3, data, length);
-
- if ((uint32_t)sendpacket(net, dest, packet, SIZEOF_VLA(packet)) != SIZEOF_VLA(packet)) {
- return -1;
- }
-
- return 0;
-}
-
-static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + SEND_1) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[ONION_MAX_PACKET_SIZE];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), plain);
-
- if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)) {
- return 1;
- }
-
- return onion_send_1(onion, plain, len, source, packet + 1);
-}
-
-int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce)
-{
- if (len > ONION_MAX_PACKET_SIZE + SIZE_IPPORT - (1 + CRYPTO_NONCE_SIZE + ONION_RETURN_1)) {
- return 1;
- }
-
- if (len <= SIZE_IPPORT + SEND_BASE * 2) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 0) == -1) {
- return 1;
- }
-
- uint8_t ip_port[SIZE_IPPORT];
- ipport_pack(ip_port, &source);
-
- uint8_t data[ONION_MAX_PACKET_SIZE];
- data[0] = NET_PACKET_ONION_SEND_1;
- memcpy(data + 1, nonce, CRYPTO_NONCE_SIZE);
- memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
- uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
- uint8_t *ret_part = data + data_len;
- random_nonce(ret_part);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
- ret_part + CRYPTO_NONCE_SIZE);
-
- if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
- return 1;
- }
-
- data_len += CRYPTO_NONCE_SIZE + len;
-
- if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-static int handle_send_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + SEND_2) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[ONION_MAX_PACKET_SIZE];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
-
- if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 0) == -1) {
- return 1;
- }
-
- uint8_t data[ONION_MAX_PACKET_SIZE];
- data[0] = NET_PACKET_ONION_SEND_2;
- memcpy(data + 1, packet + 1, CRYPTO_NONCE_SIZE);
- memcpy(data + 1 + CRYPTO_NONCE_SIZE, plain + SIZE_IPPORT, len - SIZE_IPPORT);
- uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
- uint8_t *ret_part = data + data_len;
- random_nonce(ret_part);
- uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
- ipport_pack(ret_data, &source);
- memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
- ret_part + CRYPTO_NONCE_SIZE);
-
- if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
- return 1;
- }
-
- data_len += CRYPTO_NONCE_SIZE + len;
-
- if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + SEND_3) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[ONION_MAX_PACKET_SIZE];
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + CRYPTO_NONCE_SIZE);
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
-
- if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 0) == -1) {
- return 1;
- }
-
- uint8_t data[ONION_MAX_PACKET_SIZE];
- memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
- uint16_t data_len = (len - SIZE_IPPORT);
- uint8_t *ret_part = data + (len - SIZE_IPPORT);
- random_nonce(ret_part);
- uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
- ipport_pack(ret_data, &source);
- memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
- len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
- ret_part + CRYPTO_NONCE_SIZE);
-
- if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
- return 1;
- }
-
- data_len += RETURN_3;
-
- if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-
-static int handle_recv_3(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + RETURN_3) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[SIZE_IPPORT + RETURN_2];
- int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
-
- if ((uint32_t)len != sizeof(plain)) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 0) == -1) {
- return 1;
- }
-
- uint8_t data[ONION_MAX_PACKET_SIZE];
- data[0] = NET_PACKET_ONION_RECV_2;
- memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2);
- memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3));
- uint16_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3));
-
- if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-static int handle_recv_2(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + RETURN_2) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[SIZE_IPPORT + RETURN_1];
- int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
-
- if ((uint32_t)len != sizeof(plain)) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 0) == -1) {
- return 1;
- }
-
- uint8_t data[ONION_MAX_PACKET_SIZE];
- data[0] = NET_PACKET_ONION_RECV_1;
- memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1);
- memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2));
- uint16_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2));
-
- if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-static int handle_recv_1(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion *onion = (Onion *)object;
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- if (length <= 1 + RETURN_1) {
- return 1;
- }
-
- change_symmetric_key(onion);
-
- uint8_t plain[SIZE_IPPORT];
- int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
- SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
-
- if ((uint32_t)len != SIZE_IPPORT) {
- return 1;
- }
-
- IP_Port send_to;
-
- if (ipport_unpack(&send_to, plain, len, 1) == -1) {
- return 1;
- }
-
- uint16_t data_len = length - (1 + RETURN_1);
-
- if (onion->recv_1_function &&
- send_to.ip.family != TOX_AF_INET &&
- send_to.ip.family != TOX_AF_INET6) {
- return onion->recv_1_function(onion->callback_object, send_to, packet + (1 + RETURN_1), data_len);
- }
-
- if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) {
- return 1;
- }
-
- return 0;
-}
-
-void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, const uint8_t *, uint16_t), void *object)
-{
- onion->recv_1_function = function;
- onion->callback_object = object;
-}
-
-Onion *new_onion(DHT *dht)
-{
- if (dht == NULL) {
- return NULL;
- }
-
- Onion *onion = (Onion *)calloc(1, sizeof(Onion));
-
- if (onion == NULL) {
- return NULL;
- }
-
- onion->dht = dht;
- onion->net = dht->net;
- new_symmetric_key(onion->secret_symmetric_key);
- onion->timestamp = unix_time();
-
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion);
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion);
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, &handle_send_2, onion);
-
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, &handle_recv_3, onion);
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, &handle_recv_2, onion);
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, &handle_recv_1, onion);
-
- return onion;
-}
-
-void kill_onion(Onion *onion)
-{
- if (onion == NULL) {
- return;
- }
-
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL);
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL);
- networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, NULL, NULL);
-
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, NULL, NULL);
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, NULL, NULL);
- networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, NULL, NULL);
-
- free(onion);
-}
diff --git a/libs/libtox/src/toxcore/onion.h b/libs/libtox/src/toxcore/onion.h
deleted file mode 100644
index e81b3a52ae..0000000000
--- a/libs/libtox/src/toxcore/onion.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Implementation of the onion part of docs/Prevent_Tracking.txt
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef ONION_H
-#define ONION_H
-
-#include "DHT.h"
-
-typedef struct {
- DHT *dht;
- Networking_Core *net;
- uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
- uint64_t timestamp;
-
- Shared_Keys shared_keys_1;
- Shared_Keys shared_keys_2;
- Shared_Keys shared_keys_3;
-
- int (*recv_1_function)(void *, IP_Port, const uint8_t *, uint16_t);
- void *callback_object;
-} Onion;
-
-#define ONION_MAX_PACKET_SIZE 1400
-
-#define ONION_RETURN_1 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
-#define ONION_RETURN_2 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_1)
-#define ONION_RETURN_3 (CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE + ONION_RETURN_2)
-
-#define ONION_SEND_BASE (CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + CRYPTO_MAC_SIZE)
-#define ONION_SEND_3 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE + ONION_RETURN_2)
-#define ONION_SEND_2 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*2 + ONION_RETURN_1)
-#define ONION_SEND_1 (CRYPTO_NONCE_SIZE + ONION_SEND_BASE*3)
-
-#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1))
-#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3))
-
-#define ONION_PATH_LENGTH 3
-
-typedef struct {
- uint8_t shared_key1[CRYPTO_SHARED_KEY_SIZE];
- uint8_t shared_key2[CRYPTO_SHARED_KEY_SIZE];
- uint8_t shared_key3[CRYPTO_SHARED_KEY_SIZE];
-
- uint8_t public_key1[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t public_key2[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t public_key3[CRYPTO_PUBLIC_KEY_SIZE];
-
- IP_Port ip_port1;
- uint8_t node_public_key1[CRYPTO_PUBLIC_KEY_SIZE];
-
- IP_Port ip_port2;
- uint8_t node_public_key2[CRYPTO_PUBLIC_KEY_SIZE];
-
- IP_Port ip_port3;
- uint8_t node_public_key3[CRYPTO_PUBLIC_KEY_SIZE];
-
- uint32_t path_num;
-} Onion_Path;
-
-/* Create a new onion path.
- *
- * Create a new onion path out of nodes (nodes is a list of ONION_PATH_LENGTH nodes)
- *
- * new_path must be an empty memory location of atleast Onion_Path size.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int create_onion_path(const DHT *dht, Onion_Path *new_path, const Node_format *nodes);
-
-/* Dump nodes in onion path to nodes of length num_nodes;
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_Path *path);
-
-/* Create a onion packet.
- *
- * Use Onion_Path path to create packet for data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- * packet should be at least ONION_MAX_PACKET_SIZE big.
- *
- * return -1 on failure.
- * return length of created packet on success.
- */
-int create_onion_packet(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
- const uint8_t *data, uint16_t length);
-
-
-/* Create a onion packet to be sent over tcp.
- *
- * Use Onion_Path path to create packet for data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- * packet should be at least ONION_MAX_PACKET_SIZE big.
- *
- * return -1 on failure.
- * return length of created packet on success.
- */
-int create_onion_packet_tcp(uint8_t *packet, uint16_t max_packet_length, const Onion_Path *path, IP_Port dest,
- const uint8_t *data, uint16_t length);
-
-/* Create and send a onion packet.
- *
- * Use Onion_Path path to send data of length to dest.
- * Maximum length of data is ONION_MAX_DATA_SIZE.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_onion_packet(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *data, uint16_t length);
-
-/* Create and send a onion response sent initially to dest with.
- * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_onion_response(Networking_Core *net, IP_Port dest, const uint8_t *data, uint16_t length, const uint8_t *ret);
-
-/* Function to handle/send received decrypted versions of the packet sent with send_onion_packet.
- *
- * return 0 on success.
- * return 1 on failure.
- *
- * Used to handle these packets that are received in a non traditional way (by TCP for example).
- *
- * Source family must be set to something else than TOX_AF_INET6 or TOX_AF_INET so that the callback gets called
- * when the response is received.
- */
-int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, IP_Port source, const uint8_t *nonce);
-
-/* Set the callback to be called when the dest ip_port doesn't have TOX_AF_INET6 or TOX_AF_INET as the family.
- *
- * Format: function(void *object, IP_Port dest, uint8_t *data, uint16_t length)
- */
-void set_callback_handle_recv_1(Onion *onion, int (*function)(void *, IP_Port, const uint8_t *, uint16_t),
- void *object);
-
-Onion *new_onion(DHT *dht);
-
-void kill_onion(Onion *onion);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/onion_announce.c b/libs/libtox/src/toxcore/onion_announce.c
deleted file mode 100644
index c093800719..0000000000
--- a/libs/libtox/src/toxcore/onion_announce.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Implementation of the announce part of docs/Prevent_Tracking.txt
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "onion_announce.h"
-
-#include "LAN_discovery.h"
-#include "util.h"
-
-#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
-
-#define ANNOUNCE_REQUEST_SIZE_RECV (ONION_ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
-
-#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE
-#define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3)
-
-/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
- *
- * dest_client_id is the public key of the node the packet will be sent to.
- * public_key and secret_key is the kepair which will be used to encrypt the request.
- * ping_id is the ping id that will be sent in the request.
- * client_id is the client id of the node we are searching for.
- * data_public_key is the public key we want others to encrypt their data packets with.
- * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
- * receive back in the response.
- *
- * return -1 on failure.
- * return packet length on success.
- */
-int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
- const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
- const uint8_t *data_public_key, uint64_t sendback_data)
-{
- if (max_packet_length < ONION_ANNOUNCE_REQUEST_SIZE) {
- return -1;
- }
-
- uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
- ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
- memcpy(plain, ping_id, ONION_PING_ID_SIZE);
- memcpy(plain + ONION_PING_ID_SIZE, client_id, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE, &sendback_data,
- sizeof(sendback_data));
-
- packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
- random_nonce(packet + 1);
-
- int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
- packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
-
- if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_SIZE) {
- return -1;
- }
-
- memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- return ONION_ANNOUNCE_REQUEST_SIZE;
-}
-
-/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
- *
- * public_key is the real public key of the node which we want to send the data of length length to.
- * encrypt_public_key is the public key used to encrypt the data packet.
- *
- * nonce is the nonce to encrypt this packet with
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
- const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
-{
- if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
- return -1;
- }
-
- if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) {
- return -1;
- }
-
- packet[0] = NET_PACKET_ONION_DATA_REQUEST;
- memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
-
- uint8_t random_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t random_secret_key[CRYPTO_SECRET_KEY_SIZE];
- crypto_new_keypair(random_public_key, random_secret_key);
-
- memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
- length) {
- return -1;
- }
-
- return DATA_REQUEST_MIN_SIZE + length;
-}
-
-/* Create and send an onion announce request packet.
- *
- * path is the path the request will take before it is sent to dest.
- *
- * public_key and secret_key is the kepair which will be used to encrypt the request.
- * ping_id is the ping id that will be sent in the request.
- * client_id is the client id of the node we are searching for.
- * data_public_key is the public key we want others to encrypt their data packets with.
- * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
- * receive back in the response.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key,
- const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
- uint64_t sendback_data)
-{
- uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
- int len = create_announce_request(request, sizeof(request), dest.public_key, public_key, secret_key, ping_id, client_id,
- data_public_key, sendback_data);
-
- if (len != sizeof(request)) {
- return -1;
- }
-
- uint8_t packet[ONION_MAX_PACKET_SIZE];
- len = create_onion_packet(packet, sizeof(packet), path, dest.ip_port, request, sizeof(request));
-
- if (len == -1) {
- return -1;
- }
-
- if (sendpacket(net, path->ip_port1, packet, len) != len) {
- return -1;
- }
-
- return 0;
-}
-
-/* Create and send an onion data request packet.
- *
- * path is the path the request will take before it is sent to dest.
- * (if dest knows the person with the public_key they should
- * send the packet to that person in the form of a response)
- *
- * public_key is the real public key of the node which we want to send the data of length length to.
- * encrypt_public_key is the public key used to encrypt the data packet.
- *
- * nonce is the nonce to encrypt this packet with
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key,
- const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
-{
- uint8_t request[ONION_MAX_DATA_SIZE];
- int len = create_data_request(request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
-
- if (len == -1) {
- return -1;
- }
-
- uint8_t packet[ONION_MAX_PACKET_SIZE];
- len = create_onion_packet(packet, sizeof(packet), path, dest, request, len);
-
- if (len == -1) {
- return -1;
- }
-
- if (sendpacket(net, path->ip_port1, packet, len) != len) {
- return -1;
- }
-
- return 0;
-}
-
-/* Generate a ping_id and put it in ping_id */
-static void generate_ping_id(const Onion_Announce *onion_a, uint64_t time, const uint8_t *public_key,
- IP_Port ret_ip_port, uint8_t *ping_id)
-{
- time /= PING_ID_TIMEOUT;
- uint8_t data[CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(ret_ip_port)];
- memcpy(data, onion_a->secret_bytes, CRYPTO_SYMMETRIC_KEY_SIZE);
- memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE, &time, sizeof(time));
- memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time), public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(data + CRYPTO_SYMMETRIC_KEY_SIZE + sizeof(time) + CRYPTO_PUBLIC_KEY_SIZE, &ret_ip_port, sizeof(ret_ip_port));
- crypto_sha256(ping_id, data, sizeof(data));
-}
-
-/* check if public key is in entries list
- *
- * return -1 if no
- * return position in list if yes
- */
-static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
-{
- unsigned int i;
-
- for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
- if (!is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)
- && public_key_cmp(onion_a->entries[i].public_key, public_key) == 0) {
- return i;
- }
- }
-
- return -1;
-}
-
-typedef struct {
- const uint8_t *base_public_key;
- Onion_Announce_Entry entry;
-} Cmp_data;
-
-static int cmp_entry(const void *a, const void *b)
-{
- Cmp_data cmp1, cmp2;
- memcpy(&cmp1, a, sizeof(Cmp_data));
- memcpy(&cmp2, b, sizeof(Cmp_data));
- Onion_Announce_Entry entry1 = cmp1.entry;
- Onion_Announce_Entry entry2 = cmp2.entry;
- const uint8_t *cmp_public_key = cmp1.base_public_key;
-
- int t1 = is_timeout(entry1.time, ONION_ANNOUNCE_TIMEOUT);
- int t2 = is_timeout(entry2.time, ONION_ANNOUNCE_TIMEOUT);
-
- if (t1 && t2) {
- return 0;
- }
-
- if (t1) {
- return -1;
- }
-
- if (t2) {
- return 1;
- }
-
- int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
-
- if (close == 1) {
- return 1;
- }
-
- if (close == 2) {
- return -1;
- }
-
- return 0;
-}
-
-static void sort_onion_announce_list(Onion_Announce_Entry *list, unsigned int length, const uint8_t *comp_public_key)
-{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- VLA(Cmp_data, cmp_list, length);
-
- for (uint32_t i = 0; i < length; i++) {
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
- }
-
- qsort(cmp_list, length, sizeof(Cmp_data), cmp_entry);
-
- for (uint32_t i = 0; i < length; i++) {
- list[i] = cmp_list[i].entry;
- }
-}
-
-/* add entry to entries list
- *
- * return -1 if failure
- * return position if added
- */
-static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, const uint8_t *public_key,
- const uint8_t *data_public_key, const uint8_t *ret)
-{
-
- int pos = in_entries(onion_a, public_key);
-
- unsigned int i;
-
- if (pos == -1) {
- for (i = 0; i < ONION_ANNOUNCE_MAX_ENTRIES; ++i) {
- if (is_timeout(onion_a->entries[i].time, ONION_ANNOUNCE_TIMEOUT)) {
- pos = i;
- }
- }
- }
-
- if (pos == -1) {
- if (id_closest(onion_a->dht->self_public_key, public_key, onion_a->entries[0].public_key) == 1) {
- pos = 0;
- }
- }
-
- if (pos == -1) {
- return -1;
- }
-
- memcpy(onion_a->entries[pos].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- onion_a->entries[pos].ret_ip_port = ret_ip_port;
- memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
- memcpy(onion_a->entries[pos].data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- onion_a->entries[pos].time = unix_time();
-
- sort_onion_announce_list(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, onion_a->dht->self_public_key);
- return in_entries(onion_a, public_key);
-}
-
-static int handle_announce_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion_Announce *onion_a = (Onion_Announce *)object;
-
- if (length != ANNOUNCE_REQUEST_SIZE_RECV) {
- return 1;
- }
-
- const uint8_t *packet_public_key = packet + 1 + CRYPTO_NONCE_SIZE;
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
- get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key);
-
- uint8_t plain[ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE +
- ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
- int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
- CRYPTO_MAC_SIZE, plain);
-
- if ((uint32_t)len != sizeof(plain)) {
- return 1;
- }
-
- uint8_t ping_id1[ONION_PING_ID_SIZE];
- generate_ping_id(onion_a, unix_time(), packet_public_key, source, ping_id1);
-
- uint8_t ping_id2[ONION_PING_ID_SIZE];
- generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet_public_key, source, ping_id2);
-
- int index = -1;
-
- uint8_t *data_public_key = plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE;
-
- if (crypto_memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0
- || crypto_memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
- index = add_to_entries(onion_a, source, packet_public_key, data_public_key,
- packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
- } else {
- index = in_entries(onion_a, plain + ONION_PING_ID_SIZE);
- }
-
- /*Respond with a announce response packet*/
- Node_format nodes_list[MAX_SENT_NODES];
- unsigned int num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0,
- LAN_ip(source.ip) == 0, 1);
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
-
- uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];
-
- if (index == -1) {
- pl[0] = 0;
- memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
- } else {
- if (public_key_cmp(onion_a->entries[index].public_key, packet_public_key) == 0) {
- if (public_key_cmp(onion_a->entries[index].data_public_key, data_public_key) != 0) {
- pl[0] = 0;
- memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
- } else {
- pl[0] = 2;
- memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
- }
- } else {
- pl[0] = 1;
- memcpy(pl + 1, onion_a->entries[index].data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- }
- }
-
- int nodes_length = 0;
-
- if (num_nodes != 0) {
- nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes);
-
- if (nodes_length <= 0) {
- return 1;
- }
- }
-
- uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
- len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length,
- data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);
-
- if (len != 1 + ONION_PING_ID_SIZE + nodes_length + CRYPTO_MAC_SIZE) {
- return 1;
- }
-
- data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
- memcpy(data + 1, plain + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
- memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, CRYPTO_NONCE_SIZE);
-
- if (send_onion_response(onion_a->net, source, data,
- 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + len,
- packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) {
- return 1;
- }
-
- return 0;
-}
-
-static int handle_data_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion_Announce *onion_a = (Onion_Announce *)object;
-
- if (length <= DATA_REQUEST_MIN_SIZE_RECV) {
- return 1;
- }
-
- if (length > ONION_MAX_PACKET_SIZE) {
- return 1;
- }
-
- int index = in_entries(onion_a, packet + 1);
-
- if (index == -1) {
- return 1;
- }
-
- VLA(uint8_t, data, length - (CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
- data[0] = NET_PACKET_ONION_DATA_RESPONSE;
- memcpy(data + 1, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE + ONION_RETURN_3));
-
- if (send_onion_response(onion_a->net, onion_a->entries[index].ret_ip_port, data, SIZEOF_VLA(data),
- onion_a->entries[index].ret) == -1) {
- return 1;
- }
-
- return 0;
-}
-
-Onion_Announce *new_onion_announce(DHT *dht)
-{
- if (dht == NULL) {
- return NULL;
- }
-
- Onion_Announce *onion_a = (Onion_Announce *)calloc(1, sizeof(Onion_Announce));
-
- if (onion_a == NULL) {
- return NULL;
- }
-
- onion_a->dht = dht;
- onion_a->net = dht->net;
- new_symmetric_key(onion_a->secret_bytes);
-
- networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_announce_request, onion_a);
- networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, &handle_data_request, onion_a);
-
- return onion_a;
-}
-
-void kill_onion_announce(Onion_Announce *onion_a)
-{
- if (onion_a == NULL) {
- return;
- }
-
- networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, NULL, NULL);
- networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, NULL, NULL);
- free(onion_a);
-}
diff --git a/libs/libtox/src/toxcore/onion_announce.h b/libs/libtox/src/toxcore/onion_announce.h
deleted file mode 100644
index 548d4b798b..0000000000
--- a/libs/libtox/src/toxcore/onion_announce.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Implementation of the announce part of docs/Prevent_Tracking.txt
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef ONION_ANNOUNCE_H
-#define ONION_ANNOUNCE_H
-
-#include "onion.h"
-
-#define ONION_ANNOUNCE_MAX_ENTRIES 160
-#define ONION_ANNOUNCE_TIMEOUT 300
-#define ONION_PING_ID_SIZE CRYPTO_SHA256_SIZE
-
-#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t))
-
-#define ONION_ANNOUNCE_REQUEST_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_PING_ID_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_PUBLIC_KEY_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_MAC_SIZE)
-
-#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE + 1 + ONION_PING_ID_SIZE + CRYPTO_MAC_SIZE)
-#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
-
-#define ONION_DATA_RESPONSE_MIN_SIZE (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
-
-#if ONION_PING_ID_SIZE != CRYPTO_PUBLIC_KEY_SIZE
-#error announce response packets assume that ONION_PING_ID_SIZE is equal to CRYPTO_PUBLIC_KEY_SIZE
-#endif
-
-#define ONION_DATA_REQUEST_MIN_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
-#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- IP_Port ret_ip_port;
- uint8_t ret[ONION_RETURN_3];
- uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint64_t time;
-} Onion_Announce_Entry;
-
-typedef struct {
- DHT *dht;
- Networking_Core *net;
- Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
- /* This is CRYPTO_SYMMETRIC_KEY_SIZE long just so we can use new_symmetric_key() to fill it */
- uint8_t secret_bytes[CRYPTO_SYMMETRIC_KEY_SIZE];
-
- Shared_Keys shared_keys_recv;
-} Onion_Announce;
-
-/* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
- *
- * dest_client_id is the public key of the node the packet will be sent to.
- * public_key and secret_key is the kepair which will be used to encrypt the request.
- * ping_id is the ping id that will be sent in the request.
- * client_id is the client id of the node we are searching for.
- * data_public_key is the public key we want others to encrypt their data packets with.
- * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
- * receive back in the response.
- *
- * return -1 on failure.
- * return packet length on success.
- */
-int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
- const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
- const uint8_t *data_public_key, uint64_t sendback_data);
-
-/* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
- *
- * public_key is the real public key of the node which we want to send the data of length length to.
- * encrypt_public_key is the public key used to encrypt the data packet.
- *
- * nonce is the nonce to encrypt this packet with
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
- const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
-
-/* Create and send an onion announce request packet.
- *
- * path is the path the request will take before it is sent to dest.
- *
- * public_key and secret_key is the kepair which will be used to encrypt the request.
- * ping_id is the ping id that will be sent in the request.
- * client_id is the client id of the node we are searching for.
- * data_public_key is the public key we want others to encrypt their data packets with.
- * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
- * receive back in the response.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key,
- const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
- uint64_t sendback_data);
-
-/* Create and send an onion data request packet.
- *
- * path is the path the request will take before it is sent to dest.
- * (if dest knows the person with the public_key they should
- * send the packet to that person in the form of a response)
- *
- * public_key is the real public key of the node which we want to send the data of length length to.
- * encrypt_public_key is the public key used to encrypt the data packet.
- *
- * nonce is the nonce to encrypt this packet with
- *
- * The maximum length of data is MAX_DATA_REQUEST_SIZE.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key,
- const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
-
-
-Onion_Announce *new_onion_announce(DHT *dht);
-
-void kill_onion_announce(Onion_Announce *onion_a);
-
-
-#endif
diff --git a/libs/libtox/src/toxcore/onion_client.c b/libs/libtox/src/toxcore/onion_client.c
deleted file mode 100644
index 94e9c91652..0000000000
--- a/libs/libtox/src/toxcore/onion_client.c
+++ /dev/null
@@ -1,1771 +0,0 @@
-/*
- * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
- * uses the onion stuff to connect to the friend)
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "onion_client.h"
-
-#include "LAN_discovery.h"
-#include "util.h"
-
-/* defines for the array size and
- timeout for onion announce packets. */
-#define ANNOUNCE_ARRAY_SIZE 256
-#define ANNOUNCE_TIMEOUT 10
-
-/* Add a node to the path_nodes bootstrap array.
- *
- * return -1 on failure
- * return 0 on success
- */
-int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
-{
- if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_PATH_NODES; ++i) {
- if (public_key_cmp(public_key, onion_c->path_nodes_bs[i].public_key) == 0) {
- return -1;
- }
- }
-
- onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = ip_port;
- memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,
- CRYPTO_PUBLIC_KEY_SIZE);
-
- uint16_t last = onion_c->path_nodes_index_bs;
- ++onion_c->path_nodes_index_bs;
-
- if (onion_c->path_nodes_index_bs < last) {
- onion_c->path_nodes_index_bs = MAX_PATH_NODES + 1;
- }
-
- return 0;
-}
-
-/* Add a node to the path_nodes array.
- *
- * return -1 on failure
- * return 0 on success
- */
-static int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key)
-{
- if (ip_port.ip.family != TOX_AF_INET && ip_port.ip.family != TOX_AF_INET6) {
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_PATH_NODES; ++i) {
- if (public_key_cmp(public_key, onion_c->path_nodes[i].public_key) == 0) {
- return -1;
- }
- }
-
- onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port;
- memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,
- CRYPTO_PUBLIC_KEY_SIZE);
-
- uint16_t last = onion_c->path_nodes_index;
- ++onion_c->path_nodes_index;
-
- if (onion_c->path_nodes_index < last) {
- onion_c->path_nodes_index = MAX_PATH_NODES + 1;
- }
-
- return 0;
-}
-
-/* Put up to max_num nodes in nodes.
- *
- * return the number of nodes.
- */
-uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
-{
- unsigned int i;
-
- if (!max_num) {
- return 0;
- }
-
- unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
-
- if (num_nodes == 0) {
- return 0;
- }
-
- if (num_nodes < max_num) {
- max_num = num_nodes;
- }
-
- for (i = 0; i < max_num; ++i) {
- nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes];
- }
-
- return max_num;
-}
-
-/* Put up to max_num random nodes in nodes.
- *
- * return the number of nodes.
- */
-static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
-{
- unsigned int i;
-
- if (!max_num) {
- return 0;
- }
-
- unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
-
- //if (DHT_non_lan_connected(onion_c->dht)) {
- if (DHT_isconnected(onion_c->dht)) {
- if (num_nodes == 0) {
- return 0;
- }
-
- for (i = 0; i < max_num; ++i) {
- nodes[i] = onion_c->path_nodes[rand() % num_nodes];
- }
- } else {
- int random_tcp = get_random_tcp_con_number(onion_c->c);
-
- if (random_tcp == -1) {
- return 0;
- }
-
- if (num_nodes >= 2) {
- nodes[0].ip_port.ip.family = TCP_FAMILY;
- nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
-
- for (i = 1; i < max_num; ++i) {
- nodes[i] = onion_c->path_nodes[rand() % num_nodes];
- }
- } else {
- unsigned int num_nodes_bs = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs :
- MAX_PATH_NODES;
-
- if (num_nodes_bs == 0) {
- return 0;
- }
-
- nodes[0].ip_port.ip.family = TCP_FAMILY;
- nodes[0].ip_port.ip.ip4.uint32 = random_tcp;
-
- for (i = 1; i < max_num; ++i) {
- nodes[i] = onion_c->path_nodes_bs[rand() % num_nodes_bs];
- }
- }
- }
-
- return max_num;
-}
-
-/*
- * return -1 if nodes are suitable for creating a new path.
- * return path number of already existing similar path if one already exists.
- */
-static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format *nodes)
-{
- unsigned int i;
-
- for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
- if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
- continue;
- }
-
- if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
- continue;
- }
-
- // TODO(irungentoo): do we really have to check it with the last node?
- if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
- return i;
- }
- }
-
- return -1;
-}
-
-/* is path timed out */
-static bool path_timed_out(Onion_Client_Paths *onion_paths, uint32_t pathnum)
-{
- pathnum = pathnum % NUMBER_ONION_PATHS;
-
- bool is_new = onion_paths->last_path_success[pathnum] == onion_paths->path_creation_time[pathnum];
- uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;
-
- return ((onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES
- && is_timeout(onion_paths->last_path_used[pathnum], timeout))
- || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME));
-}
-
-/* should node be considered to have timed out */
-static bool onion_node_timed_out(const Onion_Node *node)
-{
- return (node->timestamp == 0
- || (node->unsuccessful_pings >= ONION_NODE_MAX_PINGS
- && is_timeout(node->last_pinged, ONION_NODE_TIMEOUT)));
-}
-
-/* Create a new path or use an old suitable one (if pathnum is valid)
- * or a random one from onion_paths.
- *
- * return -1 on failure
- * return 0 on success
- *
- * TODO(irungentoo): Make this function better, it currently probably is
- * vulnerable to some attacks that could deanonimize us.
- */
-static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
-{
- if (pathnum == UINT32_MAX) {
- pathnum = rand() % NUMBER_ONION_PATHS;
- } else {
- pathnum = pathnum % NUMBER_ONION_PATHS;
- }
-
- if (path_timed_out(onion_paths, pathnum)) {
- Node_format nodes[ONION_PATH_LENGTH];
-
- if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {
- return -1;
- }
-
- int n = is_path_used(onion_paths, nodes);
-
- if (n == -1) {
- if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {
- return -1;
- }
-
- onion_paths->path_creation_time[pathnum] = unix_time();
- onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];
- onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2;
-
- uint32_t path_num = rand();
- path_num /= NUMBER_ONION_PATHS;
- path_num *= NUMBER_ONION_PATHS;
- path_num += pathnum;
-
- onion_paths->paths[pathnum].path_num = path_num;
- } else {
- pathnum = n;
- }
- }
-
- if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) {
- onion_paths->last_path_used[pathnum] = unix_time();
- }
-
- ++onion_paths->last_path_used_times[pathnum];
- memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
- return 0;
-}
-
-/* Does path with path_num exist. */
-static bool path_exists(Onion_Client_Paths *onion_paths, uint32_t path_num)
-{
- if (path_timed_out(onion_paths, path_num)) {
- return 0;
- }
-
- return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
-}
-
-/* Set path timeouts, return the path number.
- *
- */
-static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num)
-{
- if (num > onion_c->num_friends) {
- return -1;
- }
-
- Onion_Client_Paths *onion_paths;
-
- if (num == 0) {
- onion_paths = &onion_c->onion_paths_self;
- } else {
- onion_paths = &onion_c->onion_paths_friends;
- }
-
- if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
- onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time();
- onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
-
- Node_format nodes[ONION_PATH_LENGTH];
-
- if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
- unsigned int i;
-
- for (i = 0; i < ONION_PATH_LENGTH; ++i) {
- onion_add_path_node(onion_c, nodes[i].ip_port, nodes[i].public_key);
- }
- }
-
- return path_num;
- }
-
- return ~0;
-}
-
-/* Function to send onion packet via TCP and UDP.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest,
- const uint8_t *data, uint16_t length)
-{
- if (path->ip_port1.ip.family == TOX_AF_INET || path->ip_port1.ip.family == TOX_AF_INET6) {
- uint8_t packet[ONION_MAX_PACKET_SIZE];
- int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
-
- if (len == -1) {
- return -1;
- }
-
- if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len) {
- return -1;
- }
-
- return 0;
- }
-
- if (path->ip_port1.ip.family == TCP_FAMILY) {
- uint8_t packet[ONION_MAX_PACKET_SIZE];
- int len = create_onion_packet_tcp(packet, sizeof(packet), path, dest, data, length);
-
- if (len == -1) {
- return -1;
- }
-
- return send_tcp_onion_request(onion_c->c, path->ip_port1.ip.ip4.uint32, packet, len);
- }
-
- return -1;
-}
-
-/* Creates a sendback for use in an announce request.
- *
- * num is 0 if we used our secret public key for the announce
- * num is 1 + friendnum if we use a temporary one.
- *
- * Public key is the key we will be sending it to.
- * ip_port is the ip_port of the node we will be sending
- * it to.
- *
- * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
- *
- * return -1 on failure
- * return 0 on success
- *
- */
-static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
- uint32_t path_num, uint64_t *sendback)
-{
- uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
- memcpy(data, &num, sizeof(uint32_t));
- memcpy(data + sizeof(uint32_t), public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, &ip_port, sizeof(IP_Port));
- memcpy(data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), &path_num, sizeof(uint32_t));
- *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data));
-
- if (*sendback == 0) {
- return -1;
- }
-
- return 0;
-}
-
-/* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
- * ip contained in it in ret_ip_port
- *
- * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
- * ret_pubkey must be at least CRYPTO_PUBLIC_KEY_SIZE big
- * ret_ip_port must be at least 1 big
- *
- * return ~0 on failure
- * return num (see new_sendback(...)) on success
- */
-static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, uint8_t *ret_pubkey,
- IP_Port *ret_ip_port, uint32_t *path_num)
-{
- uint64_t sback;
- memcpy(&sback, sendback, sizeof(uint64_t));
- uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port) + sizeof(uint32_t)];
-
- if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) {
- return ~0;
- }
-
- memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
- memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port), sizeof(uint32_t));
-
- uint32_t num;
- memcpy(&num, data, sizeof(uint32_t));
- return num;
-}
-
-static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
- const uint8_t *ping_id, uint32_t pathnum)
-{
- if (num > onion_c->num_friends) {
- return -1;
- }
-
- uint64_t sendback;
- Onion_Path path;
-
- if (num == 0) {
- if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) {
- return -1;
- }
- } else {
- if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) {
- return -1;
- }
- }
-
- if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1) {
- return -1;
- }
-
- uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
-
- if (ping_id == NULL) {
- ping_id = zero_ping_id;
- }
-
- uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
- int len;
-
- if (num == 0) {
- len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->c->self_public_key,
- onion_c->c->self_secret_key, ping_id, onion_c->c->self_public_key, onion_c->temp_public_key, sendback);
- } else {
- len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
- onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_public_key, zero_ping_id,
- sendback);
- }
-
- if (len == -1) {
- return -1;
- }
-
- return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
-}
-
-typedef struct {
- const uint8_t *base_public_key;
- Onion_Node entry;
-} Onion_Client_Cmp_data;
-
-static int onion_client_cmp_entry(const void *a, const void *b)
-{
- Onion_Client_Cmp_data cmp1, cmp2;
- memcpy(&cmp1, a, sizeof(Onion_Client_Cmp_data));
- memcpy(&cmp2, b, sizeof(Onion_Client_Cmp_data));
- Onion_Node entry1 = cmp1.entry;
- Onion_Node entry2 = cmp2.entry;
- const uint8_t *cmp_public_key = cmp1.base_public_key;
-
- int t1 = onion_node_timed_out(&entry1);
- int t2 = onion_node_timed_out(&entry2);
-
- if (t1 && t2) {
- return 0;
- }
-
- if (t1) {
- return -1;
- }
-
- if (t2) {
- return 1;
- }
-
- int close = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
-
- if (close == 1) {
- return 1;
- }
-
- if (close == 2) {
- return -1;
- }
-
- return 0;
-}
-
-static void sort_onion_node_list(Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
-{
- // Pass comp_public_key to qsort with each Client_data entry, so the
- // comparison function can use it as the base of comparison.
- VLA(Onion_Client_Cmp_data, cmp_list, length);
-
- for (uint32_t i = 0; i < length; i++) {
- cmp_list[i].base_public_key = comp_public_key;
- cmp_list[i].entry = list[i];
- }
-
- qsort(cmp_list, length, sizeof(Onion_Client_Cmp_data), onion_client_cmp_entry);
-
- for (uint32_t i = 0; i < length; i++) {
- list[i] = cmp_list[i].entry;
- }
-}
-
-static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
- uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_used)
-{
- if (num > onion_c->num_friends) {
- return -1;
- }
-
- Onion_Node *list_nodes = NULL;
- uint8_t *reference_id = NULL;
- unsigned int list_length;
-
- if (num == 0) {
- list_nodes = onion_c->clients_announce_list;
- reference_id = onion_c->c->self_public_key;
- list_length = MAX_ONION_CLIENTS_ANNOUNCE;
-
- if (is_stored == 1 && public_key_cmp(pingid_or_key, onion_c->temp_public_key) != 0) {
- is_stored = 0;
- }
- } else {
- if (is_stored >= 2) {
- return -1;
- }
-
- if (is_stored == 1) {
- onion_c->friends_list[num - 1].last_reported_announced = unix_time();
- }
-
- list_nodes = onion_c->friends_list[num - 1].clients_list;
- reference_id = onion_c->friends_list[num - 1].real_public_key;
- list_length = MAX_ONION_CLIENTS;
- }
-
- sort_onion_node_list(list_nodes, list_length, reference_id);
-
- int index = -1, stored = 0;
- unsigned int i;
-
- if (onion_node_timed_out(&list_nodes[0])
- || id_closest(reference_id, list_nodes[0].public_key, public_key) == 2) {
- index = 0;
- }
-
- for (i = 0; i < list_length; ++i) {
- if (public_key_cmp(list_nodes[i].public_key, public_key) == 0) {
- index = i;
- stored = 1;
- break;
- }
- }
-
- if (index == -1) {
- return 0;
- }
-
- memcpy(list_nodes[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- list_nodes[index].ip_port = ip_port;
-
- // TODO(irungentoo): remove this and find a better source of nodes to use for paths.
- onion_add_path_node(onion_c, ip_port, public_key);
-
- if (is_stored == 1) {
- memcpy(list_nodes[index].data_public_key, pingid_or_key, CRYPTO_PUBLIC_KEY_SIZE);
- } else {
- memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
- }
-
- list_nodes[index].is_stored = is_stored;
- list_nodes[index].timestamp = unix_time();
- list_nodes[index].unsuccessful_pings = 0;
-
- if (!stored) {
- list_nodes[index].last_pinged = 0;
- list_nodes[index].added_time = unix_time();
- }
-
- list_nodes[index].path_used = path_used;
- return 0;
-}
-
-static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *public_key)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
- if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {
- if (public_key_cmp(last_pinged[i].public_key, public_key) == 0) {
- return 0;
- }
- }
- }
-
- memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
- ++*last_pinged_index;
- return 1;
-}
-
-static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes,
- IP_Port source)
-{
- if (num > onion_c->num_friends) {
- return -1;
- }
-
- if (num_nodes == 0) {
- return 0;
- }
-
- Onion_Node *list_nodes = NULL;
- uint8_t *reference_id = NULL;
- unsigned int list_length;
-
- Last_Pinged *last_pinged = NULL;
- uint8_t *last_pinged_index = NULL;
-
- if (num == 0) {
- list_nodes = onion_c->clients_announce_list;
- reference_id = onion_c->c->self_public_key;
- list_length = MAX_ONION_CLIENTS_ANNOUNCE;
- last_pinged = onion_c->last_pinged;
- last_pinged_index = &onion_c->last_pinged_index;
- } else {
- list_nodes = onion_c->friends_list[num - 1].clients_list;
- reference_id = onion_c->friends_list[num - 1].real_public_key;
- list_length = MAX_ONION_CLIENTS;
- last_pinged = onion_c->friends_list[num - 1].last_pinged;
- last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
- }
-
- unsigned int i, j;
- int lan_ips_accepted = (LAN_ip(source.ip) == 0);
-
- for (i = 0; i < num_nodes; ++i) {
-
- if (!lan_ips_accepted) {
- if (LAN_ip(nodes[i].ip_port.ip) == 0) {
- continue;
- }
- }
-
- if (onion_node_timed_out(&list_nodes[0])
- || id_closest(reference_id, list_nodes[0].public_key, nodes[i].public_key) == 2
- || onion_node_timed_out(&list_nodes[1])
- || id_closest(reference_id, list_nodes[1].public_key, nodes[i].public_key) == 2) {
- /* check if node is already in list. */
- for (j = 0; j < list_length; ++j) {
- if (public_key_cmp(list_nodes[j].public_key, nodes[i].public_key) == 0) {
- break;
- }
- }
-
- if (j == list_length && good_to_ping(last_pinged, last_pinged_index, nodes[i].public_key)) {
- client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].public_key, NULL, ~0);
- }
- }
- }
-
- return 0;
-}
-
-static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length,
- void *userdata)
-{
- Onion_Client *onion_c = (Onion_Client *)object;
-
- if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
- return 1;
- }
-
- uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
-
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- IP_Port ip_port;
- uint32_t path_num;
- uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
-
- if (num > onion_c->num_friends) {
- return 1;
- }
-
- VLA(uint8_t, plain, 1 + ONION_PING_ID_SIZE + len_nodes);
- int len = -1;
-
- if (num == 0) {
- len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
- packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
- length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
- } else {
- if (onion_c->friends_list[num - 1].status == 0) {
- return 1;
- }
-
- len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
- packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
- packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
- length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE), plain);
- }
-
- if ((uint32_t)len != SIZEOF_VLA(plain)) {
- return 1;
- }
-
- uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
-
- if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_used) == -1) {
- return 1;
- }
-
- if (len_nodes != 0) {
- Node_format nodes[MAX_SENT_NODES];
- int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);
-
- if (num_nodes <= 0) {
- return 1;
- }
-
- if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
- return 1;
- }
- }
-
- // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
- onion_c->last_packet_recv = unix_time();
- return 0;
-}
-
-#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
-
-static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- Onion_Client *onion_c = (Onion_Client *)object;
-
- if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) {
- return 1;
- }
-
- if (length > MAX_DATA_REQUEST_SIZE) {
- return 1;
- }
-
- VLA(uint8_t, temp_plain, length - ONION_DATA_RESPONSE_MIN_SIZE);
- int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
- packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
- length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
-
- if ((uint32_t)len != SIZEOF_VLA(temp_plain)) {
- return 1;
- }
-
- VLA(uint8_t, plain, SIZEOF_VLA(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE);
- len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
- SIZEOF_VLA(temp_plain) - CRYPTO_PUBLIC_KEY_SIZE, plain);
-
- if ((uint32_t)len != SIZEOF_VLA(plain)) {
- return 1;
- }
-
- if (!onion_c->Onion_Data_Handlers[plain[0]].function) {
- return 1;
- }
-
- return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
- SIZEOF_VLA(plain), userdata);
-}
-
-#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE)
-#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
-static int handle_dhtpk_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint16_t length,
- void *userdata)
-{
- Onion_Client *onion_c = (Onion_Client *)object;
-
- if (length < DHTPK_DATA_MIN_LENGTH) {
- return 1;
- }
-
- if (length > DHTPK_DATA_MAX_LENGTH) {
- return 1;
- }
-
- int friend_num = onion_friend_num(onion_c, source_pubkey);
-
- if (friend_num == -1) {
- return 1;
- }
-
- uint64_t no_replay;
- memcpy(&no_replay, data + 1, sizeof(uint64_t));
- net_to_host((uint8_t *) &no_replay, sizeof(no_replay));
-
- if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) {
- return 1;
- }
-
- onion_c->friends_list[friend_num].last_noreplay = no_replay;
-
- if (onion_c->friends_list[friend_num].dht_pk_callback) {
- onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object,
- onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t), userdata);
- }
-
- onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
- onion_c->friends_list[friend_num].last_seen = unix_time();
-
- uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
-
- if (len_nodes != 0) {
- Node_format nodes[MAX_SENT_NODES];
- int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE,
- len_nodes, 1);
-
- if (num_nodes <= 0) {
- return 1;
- }
-
- int i;
-
- for (i = 0; i < num_nodes; ++i) {
- uint8_t family = nodes[i].ip_port.ip.family;
-
- if (family == TOX_AF_INET || family == TOX_AF_INET6) {
- DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
- } else if (family == TCP_INET || family == TCP_INET6) {
- if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
- void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
- uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
- onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].public_key);
- }
- }
- }
- }
-
- return 0;
-}
-
-static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length, void *userdata)
-{
- if (length == 0) {
- return 1;
- }
-
- IP_Port ip_port = {{0}};
- ip_port.ip.family = TCP_FAMILY;
-
- if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) {
- return handle_announce_response(object, ip_port, data, length, userdata);
- }
-
- if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) {
- return handle_data_response(object, ip_port, data, length, userdata);
- }
-
- return 1;
-}
-
-/* Send data of length length to friendnum.
- * This data will be received by the friend using the Onion_Data_Handlers callbacks.
- *
- * Even if this function succeeds, the friend might not receive any data.
- *
- * return the number of packets sent on success
- * return -1 on failure.
- */
-int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) {
- return -1;
- }
-
- if (length == 0) {
- return -1;
- }
-
- unsigned int i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
- Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
-
- for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
- if (onion_node_timed_out(&list_nodes[i])) {
- continue;
- }
-
- ++num_nodes;
-
- if (list_nodes[i].is_stored) {
- good_nodes[num_good] = i;
- ++num_good;
- }
- }
-
- if (num_good < (num_nodes - 1) / 4 + 1) {
- return -1;
- }
-
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
-
- VLA(uint8_t, packet, DATA_IN_RESPONSE_MIN_SIZE + length);
- memcpy(packet, onion_c->c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
- length, packet + CRYPTO_PUBLIC_KEY_SIZE);
-
- if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != SIZEOF_VLA(packet)) {
- return -1;
- }
-
- unsigned int good = 0;
-
- for (i = 0; i < num_good; ++i) {
- Onion_Path path;
-
- if (random_path(onion_c, &onion_c->onion_paths_friends, ~0, &path) == -1) {
- continue;
- }
-
- uint8_t o_packet[ONION_MAX_PACKET_SIZE];
- len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
- list_nodes[good_nodes[i]].data_public_key, nonce, packet, SIZEOF_VLA(packet));
-
- if (len == -1) {
- continue;
- }
-
- if (send_onion_packet_tcp_udp(onion_c, &path, list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0) {
- ++good;
- }
- }
-
- return good;
-}
-
-/* Try to send the dht public key via the DHT instead of onion
- *
- * Even if this function succeeds, the friend might not receive any data.
- *
- * return the number of packets sent on success
- * return -1 on failure.
- */
-static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- if (!onion_c->friends_list[friend_num].know_dht_public_key) {
- return -1;
- }
-
- uint8_t nonce[CRYPTO_NONCE_SIZE];
- random_nonce(nonce);
-
- VLA(uint8_t, temp, DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length);
- memcpy(temp, onion_c->c->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
- int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, onion_c->c->self_secret_key, nonce, data,
- length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
-
- if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != SIZEOF_VLA(temp)) {
- return -1;
- }
-
- uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
- len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
- onion_c->friends_list[friend_num].dht_public_key, temp, SIZEOF_VLA(temp), CRYPTO_PACKET_DHTPK);
-
- if (len == -1) {
- return -1;
- }
-
- return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, packet, len);
-}
-
-static int handle_dht_dhtpk(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
- uint16_t length, void *userdata)
-{
- Onion_Client *onion_c = (Onion_Client *)object;
-
- if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
- return 1;
- }
-
- if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
- return 1;
- }
-
- uint8_t plain[DHTPK_DATA_MAX_LENGTH];
- int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + CRYPTO_PUBLIC_KEY_SIZE,
- packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
- length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);
-
- if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE)) {
- return 1;
- }
-
- if (public_key_cmp(source_pubkey, plain + 1 + sizeof(uint64_t)) != 0) {
- return 1;
- }
-
- return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);
-}
-/* Send the packets to tell our friends what our DHT public key is.
- *
- * if onion_dht_both is 0, use only the onion to send the packet.
- * if it is 1, use only the dht.
- * if it is something else, use both.
- *
- * return the number of packets sent on success
- * return -1 on failure.
- */
-static int send_dhtpk_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
-{
- if (friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- uint8_t data[DHTPK_DATA_MAX_LENGTH];
- data[0] = ONION_DATA_DHTPK;
- uint64_t no_replay = unix_time();
- host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
- memcpy(data + 1, &no_replay, sizeof(no_replay));
- memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- Node_format nodes[MAX_SENT_NODES];
- uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2));
- uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
- num_nodes += num_relays;
- int nodes_len = 0;
-
- if (num_nodes != 0) {
- nodes_len = pack_nodes(data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH, nodes,
- num_nodes);
-
- if (nodes_len <= 0) {
- return -1;
- }
- }
-
- int num1 = -1, num2 = -1;
-
- if (onion_dht_both != 1) {
- num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
- }
-
- if (onion_dht_both != 0) {
- num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
- }
-
- if (num1 == -1) {
- return num2;
- }
-
- if (num2 == -1) {
- return num1;
- }
-
- return num1 + num2;
-}
-
-/* Get the friend_num of a friend.
- *
- * return -1 on failure.
- * return friend number on success.
- */
-int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
-{
- unsigned int i;
-
- for (i = 0; i < onion_c->num_friends; ++i) {
- if (onion_c->friends_list[i].status == 0) {
- continue;
- }
-
- if (public_key_cmp(public_key, onion_c->friends_list[i].real_public_key) == 0) {
- return i;
- }
- }
-
- return -1;
-}
-
-/* Set the size of the friend list to num.
- *
- * return -1 if realloc fails.
- * return 0 if it succeeds.
- */
-static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
-{
- if (num == 0) {
- free(onion_c->friends_list);
- onion_c->friends_list = NULL;
- return 0;
- }
-
- Onion_Friend *newonion_friends = (Onion_Friend *)realloc(onion_c->friends_list, num * sizeof(Onion_Friend));
-
- if (newonion_friends == NULL) {
- return -1;
- }
-
- onion_c->friends_list = newonion_friends;
- return 0;
-}
-
-/* Add a friend who we want to connect to.
- *
- * return -1 on failure.
- * return the friend number on success or if the friend was already added.
- */
-int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
-{
- int num = onion_friend_num(onion_c, public_key);
-
- if (num != -1) {
- return num;
- }
-
- unsigned int i, index = ~0;
-
- for (i = 0; i < onion_c->num_friends; ++i) {
- if (onion_c->friends_list[i].status == 0) {
- index = i;
- break;
- }
- }
-
- if (index == (uint32_t)~0) {
- if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) {
- return -1;
- }
-
- index = onion_c->num_friends;
- memset(&(onion_c->friends_list[onion_c->num_friends]), 0, sizeof(Onion_Friend));
- ++onion_c->num_friends;
- }
-
- onion_c->friends_list[index].status = 1;
- memcpy(onion_c->friends_list[index].real_public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- crypto_new_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key);
- return index;
-}
-
-/* Delete a friend.
- *
- * return -1 on failure.
- * return the deleted friend number on success.
- */
-int onion_delfriend(Onion_Client *onion_c, int friend_num)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- //if (onion_c->friends_list[friend_num].know_dht_public_key)
- // DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
-
- crypto_memzero(&(onion_c->friends_list[friend_num]), sizeof(Onion_Friend));
- unsigned int i;
-
- for (i = onion_c->num_friends; i != 0; --i) {
- if (onion_c->friends_list[i - 1].status != 0) {
- break;
- }
- }
-
- if (onion_c->num_friends != i) {
- onion_c->num_friends = i;
- realloc_onion_friends(onion_c, onion_c->num_friends);
- }
-
- return friend_num;
-}
-
-/* Set the function for this friend that will be callbacked with object and number
- * when that friends gives us one of the TCP relays he is connected to.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
- uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback;
- onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
- onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
- return 0;
-}
-
-/* Set the function for this friend that will be callbacked with object and number
- * when that friend gives us his DHT temporary public key.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
- const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- onion_c->friends_list[friend_num].dht_pk_callback = function;
- onion_c->friends_list[friend_num].dht_pk_callback_object = object;
- onion_c->friends_list[friend_num].dht_pk_callback_number = number;
- return 0;
-}
-
-/* Set a friends DHT public key.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- if (onion_c->friends_list[friend_num].status == 0) {
- return -1;
- }
-
- if (onion_c->friends_list[friend_num].know_dht_public_key) {
- if (public_key_cmp(dht_key, onion_c->friends_list[friend_num].dht_public_key) == 0) {
- return -1;
- }
-
- onion_c->friends_list[friend_num].know_dht_public_key = 0;
- }
-
- onion_c->friends_list[friend_num].last_seen = unix_time();
- onion_c->friends_list[friend_num].know_dht_public_key = 1;
- memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE);
-
- return 0;
-}
-
-/* Copy friends DHT public key into dht_key.
- *
- * return 0 on failure (no key copied).
- * return 1 on success (key copied).
- */
-unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return 0;
- }
-
- if (onion_c->friends_list[friend_num].status == 0) {
- return 0;
- }
-
- if (!onion_c->friends_list[friend_num].know_dht_public_key) {
- return 0;
- }
-
- memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- return 1;
-}
-
-/* Get the ip of friend friendnum and put it in ip_port
- *
- * return -1, -- if public_key does NOT refer to a friend
- * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
- * return 1, ip if public_key refers to a friend and we found him
- *
- */
-int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
-{
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
-
- if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) {
- return -1;
- }
-
- return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
-}
-
-
-/* Set if friend is online or not.
- * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
- *
- * is_online 1 means friend is online.
- * is_online 0 means friend is offline
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
-{
- if ((uint32_t)friend_num >= onion_c->num_friends) {
- return -1;
- }
-
- if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1) {
- onion_c->friends_list[friend_num].last_seen = unix_time();
- }
-
- onion_c->friends_list[friend_num].is_online = is_online;
-
- /* This should prevent some clock related issues */
- if (!is_online) {
- onion_c->friends_list[friend_num].last_noreplay = 0;
- onion_c->friends_list[friend_num].run_count = 0;
- }
-
- return 0;
-}
-
-static void populate_path_nodes(Onion_Client *onion_c)
-{
- Node_format nodes_list[MAX_FRIEND_CLIENTS];
-
- unsigned int num_nodes = randfriends_nodes(onion_c->dht, nodes_list, MAX_FRIEND_CLIENTS);
-
- unsigned int i;
-
- for (i = 0; i < num_nodes; ++i) {
- onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
- }
-}
-
-static void populate_path_nodes_tcp(Onion_Client *onion_c)
-{
- Node_format nodes_list[MAX_SENT_NODES];
-
- unsigned int num_nodes = copy_connected_tcp_relays(onion_c->c, nodes_list, MAX_SENT_NODES);;
- unsigned int i;
-
- for (i = 0; i < num_nodes; ++i) {
- onion_add_bs_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].public_key);
- }
-}
-
-#define ANNOUNCE_FRIEND (ONION_NODE_PING_INTERVAL * 6)
-#define ANNOUNCE_FRIEND_BEGINNING 3
-
-#define RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING 17
-
-#define ONION_FRIEND_BACKOFF_FACTOR 4
-#define ONION_FRIEND_MAX_PING_INTERVAL (5*60*MAX_ONION_CLIENTS)
-
-static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
-{
- if (friendnum >= onion_c->num_friends) {
- return;
- }
-
- if (onion_c->friends_list[friendnum].status == 0) {
- return;
- }
-
- unsigned int interval = ANNOUNCE_FRIEND;
-
- if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING) {
- interval = ANNOUNCE_FRIEND_BEGINNING;
- } else {
- if (onion_c->friends_list[friendnum].last_reported_announced == 0) {
- onion_c->friends_list[friendnum].last_reported_announced = unix_time();
- }
-
- uint64_t backoff_interval = (unix_time() - onion_c->friends_list[friendnum].last_reported_announced)
- / ONION_FRIEND_BACKOFF_FACTOR;
-
- if (backoff_interval > ONION_FRIEND_MAX_PING_INTERVAL) {
- backoff_interval = ONION_FRIEND_MAX_PING_INTERVAL;
- }
-
- if (interval < backoff_interval) {
- interval = backoff_interval;
- }
- }
-
- unsigned int i, count = 0;
- Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;
-
- if (!onion_c->friends_list[friendnum].is_online) {
- // ensure we get a response from some node roughly once per
- // (interval / MAX_ONION_CLIENTS)
- bool ping_random = true;
-
- for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
- if (!(is_timeout(list_nodes[i].timestamp, interval / MAX_ONION_CLIENTS)
- && is_timeout(list_nodes[i].last_pinged, ONION_NODE_PING_INTERVAL))) {
- ping_random = false;
- break;
- }
- }
-
- for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
- if (onion_node_timed_out(&list_nodes[i])) {
- continue;
- }
-
- ++count;
-
-
- if (list_nodes[i].last_pinged == 0) {
- list_nodes[i].last_pinged = unix_time();
- continue;
- }
-
- if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
- continue;
- }
-
- if (is_timeout(list_nodes[i].last_pinged, interval)
- || (ping_random && rand() % (MAX_ONION_CLIENTS - i) == 0)) {
- if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].public_key, 0, ~0) == 0) {
- list_nodes[i].last_pinged = unix_time();
- ++list_nodes[i].unsuccessful_pings;
- ping_random = false;
- }
- }
- }
-
- if (count != MAX_ONION_CLIENTS) {
- unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
-
- unsigned int n = num_nodes;
-
- if (num_nodes > (MAX_ONION_CLIENTS / 2)) {
- n = (MAX_ONION_CLIENTS / 2);
- }
-
- if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS) {
- if (num_nodes != 0) {
- unsigned int j;
-
- for (j = 0; j < n; ++j) {
- unsigned int num = rand() % num_nodes;
- client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port,
- onion_c->path_nodes[num].public_key, 0, ~0);
- }
-
- ++onion_c->friends_list[friendnum].run_count;
- }
- }
- } else {
- ++onion_c->friends_list[friendnum].run_count;
- }
-
- /* send packets to friend telling them our DHT public key. */
- if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_onion_sent, ONION_DHTPK_SEND_INTERVAL)) {
- if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) {
- onion_c->friends_list[friendnum].last_dht_pk_onion_sent = unix_time();
- }
- }
-
- if (is_timeout(onion_c->friends_list[friendnum].last_dht_pk_dht_sent, DHT_DHTPK_SEND_INTERVAL)) {
- if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) {
- onion_c->friends_list[friendnum].last_dht_pk_dht_sent = unix_time();
- }
- }
- }
-}
-
-
-/* Function to call when onion data packet with contents beginning with byte is received. */
-void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
-{
- onion_c->Onion_Data_Handlers[byte].function = cb;
- onion_c->Onion_Data_Handlers[byte].object = object;
-}
-
-#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 3
-#define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL
-
-#define TIME_TO_STABLE (ONION_NODE_PING_INTERVAL * 6)
-#define ANNOUNCE_INTERVAL_STABLE (ONION_NODE_PING_INTERVAL * 8)
-
-static void do_announce(Onion_Client *onion_c)
-{
- unsigned int i, count = 0;
- Onion_Node *list_nodes = onion_c->clients_announce_list;
-
- for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
- if (onion_node_timed_out(&list_nodes[i])) {
- continue;
- }
-
- ++count;
-
- /* Don't announce ourselves the first time this is run to new peers */
- if (list_nodes[i].last_pinged == 0) {
- list_nodes[i].last_pinged = 1;
- continue;
- }
-
- if (list_nodes[i].unsuccessful_pings >= ONION_NODE_MAX_PINGS) {
- continue;
- }
-
-
- unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
-
- if (list_nodes[i].is_stored && path_exists(&onion_c->onion_paths_self, list_nodes[i].path_used)) {
- interval = ANNOUNCE_INTERVAL_ANNOUNCED;
-
- uint32_t pathnum = list_nodes[i].path_used % NUMBER_ONION_PATHS;
-
- /* A node/path is considered 'stable', and can be pinged less
- * aggressively, if it has survived for at least TIME_TO_STABLE
- * and the latest packets sent to it are not timing out.
- */
- if (is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)
- && !(list_nodes[i].unsuccessful_pings > 0
- && is_timeout(list_nodes[i].last_pinged, ONION_NODE_TIMEOUT))
- && is_timeout(onion_c->onion_paths_self.path_creation_time[pathnum], TIME_TO_STABLE)
- && !(onion_c->onion_paths_self.last_path_used_times[pathnum] > 0
- && is_timeout(onion_c->onion_paths_self.last_path_used[pathnum], ONION_PATH_TIMEOUT))) {
- interval = ANNOUNCE_INTERVAL_STABLE;
- }
- }
-
- if (is_timeout(list_nodes[i].last_pinged, interval)
- || (is_timeout(onion_c->last_announce, ONION_NODE_PING_INTERVAL)
- && rand() % (MAX_ONION_CLIENTS_ANNOUNCE - i) == 0)) {
- uint32_t path_to_use = list_nodes[i].path_used;
-
- if (list_nodes[i].unsuccessful_pings == ONION_NODE_MAX_PINGS - 1
- && is_timeout(list_nodes[i].added_time, TIME_TO_STABLE)) {
- /* Last chance for a long-lived node - try a random path */
- path_to_use = ~0;
- }
-
- if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].public_key,
- list_nodes[i].ping_id, path_to_use) == 0) {
- list_nodes[i].last_pinged = unix_time();
- ++list_nodes[i].unsuccessful_pings;
- onion_c->last_announce = unix_time();
- }
- }
- }
-
- if (count != MAX_ONION_CLIENTS_ANNOUNCE) {
- unsigned int num_nodes;
- Node_format *path_nodes;
-
- if (rand() % 2 == 0 || onion_c->path_nodes_index == 0) {
- num_nodes = (onion_c->path_nodes_index_bs < MAX_PATH_NODES) ? onion_c->path_nodes_index_bs : MAX_PATH_NODES;
- path_nodes = onion_c->path_nodes_bs;
- } else {
- num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
- path_nodes = onion_c->path_nodes;
- }
-
- if (count <= (uint32_t)rand() % MAX_ONION_CLIENTS_ANNOUNCE) {
- if (num_nodes != 0) {
- for (i = 0; i < (MAX_ONION_CLIENTS_ANNOUNCE / 2); ++i) {
- unsigned int num = rand() % num_nodes;
- client_send_announce_request(onion_c, 0, path_nodes[num].ip_port, path_nodes[num].public_key, 0, ~0);
- }
- }
- }
- }
-}
-
-/* return 0 if we are not connected to the network.
- * return 1 if we are.
- */
-static int onion_isconnected(const Onion_Client *onion_c)
-{
- unsigned int i, num = 0, announced = 0;
-
- if (is_timeout(onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
- return 0;
- }
-
- if (onion_c->path_nodes_index == 0) {
- return 0;
- }
-
- for (i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
- if (!onion_node_timed_out(&onion_c->clients_announce_list[i])) {
- ++num;
-
- if (onion_c->clients_announce_list[i].is_stored) {
- ++announced;
- }
- }
- }
-
- unsigned int pnodes = onion_c->path_nodes_index;
-
- if (pnodes > MAX_ONION_CLIENTS_ANNOUNCE) {
- pnodes = MAX_ONION_CLIENTS_ANNOUNCE;
- }
-
- /* Consider ourselves online if we are announced to half or more nodes
- we are connected to */
- if (num && announced) {
- if ((num / 2) <= announced && (pnodes / 2) <= num) {
- return 1;
- }
- }
-
- return 0;
-}
-
-#define ONION_CONNECTION_SECONDS 3
-
-/* return 0 if we are not connected to the network.
- * return 1 if we are connected with TCP only.
- * return 2 if we are also connected with UDP.
- */
-unsigned int onion_connection_status(const Onion_Client *onion_c)
-{
- if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) {
- if (onion_c->UDP_connected) {
- return 2;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-void do_onion_client(Onion_Client *onion_c)
-{
- unsigned int i;
-
- if (onion_c->last_run == unix_time()) {
- return;
- }
-
- if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS)) {
- populate_path_nodes(onion_c);
- do_announce(onion_c);
- }
-
- if (onion_isconnected(onion_c)) {
- if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) {
- ++onion_c->onion_connected;
- }
- } else {
- populate_path_nodes_tcp(onion_c);
-
- if (onion_c->onion_connected != 0) {
- --onion_c->onion_connected;
- }
- }
-
- bool UDP_connected = DHT_non_lan_connected(onion_c->dht);
-
- if (is_timeout(onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {
- set_tcp_onion_status(onion_c->c->tcp_c, !UDP_connected);
- }
-
- onion_c->UDP_connected = UDP_connected
- || get_random_tcp_onion_conn_number(onion_c->c->tcp_c) == -1; /* Check if connected to any TCP relays. */
-
- if (onion_connection_status(onion_c)) {
- for (i = 0; i < onion_c->num_friends; ++i) {
- do_friend(onion_c, i);
- }
- }
-
- if (onion_c->last_run == 0) {
- onion_c->first_run = unix_time();
- }
-
- onion_c->last_run = unix_time();
-}
-
-Onion_Client *new_onion_client(Net_Crypto *c)
-{
- if (c == NULL) {
- return NULL;
- }
-
- Onion_Client *onion_c = (Onion_Client *)calloc(1, sizeof(Onion_Client));
-
- if (onion_c == NULL) {
- return NULL;
- }
-
- if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
- free(onion_c);
- return NULL;
- }
-
- onion_c->dht = c->dht;
- onion_c->net = c->dht->net;
- onion_c->c = c;
- new_symmetric_key(onion_c->secret_symmetric_key);
- crypto_new_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
- networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
- networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
- oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
- cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
- set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, &handle_tcp_onion, onion_c);
-
- return onion_c;
-}
-
-void kill_onion_client(Onion_Client *onion_c)
-{
- if (onion_c == NULL) {
- return;
- }
-
- ping_array_free_all(&onion_c->announce_ping_array);
- realloc_onion_friends(onion_c, 0);
- networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
- networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
- oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, NULL, NULL);
- cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, NULL, NULL);
- set_onion_packet_tcp_connection_callback(onion_c->c->tcp_c, NULL, NULL);
- crypto_memzero(onion_c, sizeof(Onion_Client));
- free(onion_c);
-}
-
diff --git a/libs/libtox/src/toxcore/onion_client.h b/libs/libtox/src/toxcore/onion_client.h
deleted file mode 100644
index 216dbec050..0000000000
--- a/libs/libtox/src/toxcore/onion_client.h
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
- * uses the onion stuff to connect to the friend)
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef ONION_CLIENT_H
-#define ONION_CLIENT_H
-
-#include "net_crypto.h"
-#include "onion_announce.h"
-#include "ping_array.h"
-
-#define MAX_ONION_CLIENTS 8
-#define MAX_ONION_CLIENTS_ANNOUNCE 12 /* Number of nodes to announce ourselves to. */
-#define ONION_NODE_PING_INTERVAL 15
-#define ONION_NODE_TIMEOUT ONION_NODE_PING_INTERVAL
-
-/* The interval in seconds at which to tell our friends where we are */
-#define ONION_DHTPK_SEND_INTERVAL 30
-#define DHT_DHTPK_SEND_INTERVAL 20
-
-#define NUMBER_ONION_PATHS 6
-
-/* The timeout the first time the path is added and
- then for all the next consecutive times */
-#define ONION_PATH_FIRST_TIMEOUT 4
-#define ONION_PATH_TIMEOUT 10
-#define ONION_PATH_MAX_LIFETIME 1200
-#define ONION_PATH_MAX_NO_RESPONSE_USES 4
-
-#define MAX_STORED_PINGED_NODES 9
-#define MIN_NODE_PING_TIME 10
-
-#define ONION_NODE_MAX_PINGS 3
-
-#define MAX_PATH_NODES 32
-
-/* If no announce response packets are received within this interval tox will
- * be considered offline. We give time for a node to be pinged often enough
- * that it times out, which leads to the network being thoroughly tested as it
- * is replaced.
- */
-#define ONION_OFFLINE_TIMEOUT (ONION_NODE_PING_INTERVAL * (ONION_NODE_MAX_PINGS+2))
-
-/* Onion data packet ids. */
-#define ONION_DATA_FRIEND_REQ CRYPTO_PACKET_FRIEND_REQ
-#define ONION_DATA_DHTPK CRYPTO_PACKET_DHTPK
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- IP_Port ip_port;
- uint8_t ping_id[ONION_PING_ID_SIZE];
- uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t is_stored;
-
- uint64_t added_time;
-
- uint64_t timestamp;
-
- uint64_t last_pinged;
-
- uint8_t unsuccessful_pings;
-
- uint32_t path_used;
-} Onion_Node;
-
-typedef struct {
- Onion_Path paths[NUMBER_ONION_PATHS];
- uint64_t last_path_success[NUMBER_ONION_PATHS];
- uint64_t last_path_used[NUMBER_ONION_PATHS];
- uint64_t path_creation_time[NUMBER_ONION_PATHS];
- /* number of times used without success. */
- unsigned int last_path_used_times[NUMBER_ONION_PATHS];
-} Onion_Client_Paths;
-
-typedef struct {
- uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint64_t timestamp;
-} Last_Pinged;
-
-typedef struct {
- uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
- uint8_t is_online; /* Set by the onion_set_friend_status function. */
-
- uint8_t know_dht_public_key; /* 0 if we don't know the dht public key of the other, 1 if we do. */
- uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
-
- Onion_Node clients_list[MAX_ONION_CLIENTS];
- uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- uint64_t last_reported_announced;
-
- uint64_t last_dht_pk_onion_sent;
- uint64_t last_dht_pk_dht_sent;
-
- uint64_t last_noreplay;
-
- uint64_t last_seen;
-
- Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
- uint8_t last_pinged_index;
-
- int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, const uint8_t *public_key);
- void *tcp_relay_node_callback_object;
- uint32_t tcp_relay_node_callback_number;
-
- void (*dht_pk_callback)(void *data, int32_t number, const uint8_t *dht_public_key, void *userdata);
- void *dht_pk_callback_object;
- uint32_t dht_pk_callback_number;
-
- uint32_t run_count;
-} Onion_Friend;
-
-typedef int (*oniondata_handler_callback)(void *object, const uint8_t *source_pubkey, const uint8_t *data,
- uint16_t len, void *userdata);
-
-typedef struct {
- DHT *dht;
- Net_Crypto *c;
- Networking_Core *net;
- Onion_Friend *friends_list;
- uint16_t num_friends;
-
- Onion_Node clients_announce_list[MAX_ONION_CLIENTS_ANNOUNCE];
- uint64_t last_announce;
-
- Onion_Client_Paths onion_paths_self;
- Onion_Client_Paths onion_paths_friends;
-
- uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
- uint64_t last_run, first_run;
-
- uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
-
- Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
-
- Node_format path_nodes[MAX_PATH_NODES];
- uint16_t path_nodes_index;
-
- Node_format path_nodes_bs[MAX_PATH_NODES];
- uint16_t path_nodes_index_bs;
-
- Ping_Array announce_ping_array;
- uint8_t last_pinged_index;
- struct {
- oniondata_handler_callback function;
- void *object;
- } Onion_Data_Handlers[256];
-
- uint64_t last_packet_recv;
-
- unsigned int onion_connected;
- bool UDP_connected;
-} Onion_Client;
-
-
-/* Add a node to the path_nodes bootstrap array.
- *
- * return -1 on failure
- * return 0 on success
- */
-int onion_add_bs_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *public_key);
-
-/* Put up to max_num nodes in nodes.
- *
- * return the number of nodes.
- */
-uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num);
-
-/* Add a friend who we want to connect to.
- *
- * return -1 on failure.
- * return the friend number on success or if the friend was already added.
- */
-int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key);
-
-/* Add a friend who we want to connect to.
- *
- * return -1 on failure.
- * return the friend number on success.
- */
-int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key);
-
-/* Delete a friend.
- *
- * return -1 on failure.
- * return the deleted friend number on success.
- */
-int onion_delfriend(Onion_Client *onion_c, int friend_num);
-
-/* Set if friend is online or not.
- * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
- *
- * is_online 1 means friend is online.
- * is_online 0 means friend is offline
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online);
-
-/* Get the ip of friend friendnum and put it in ip_port
- *
- * return -1, -- if public_key does NOT refer to a friend
- * return 0, -- if public_key refers to a friend and we failed to find the friend (yet)
- * return 1, ip if public_key refers to a friend and we found him
- *
- */
-int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
-
-/* Set the function for this friend that will be callbacked with object and number
- * when that friends gives us one of the TCP relays he is connected to.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
- uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number);
-
-
-/* Set the function for this friend that will be callbacked with object and number
- * when that friend gives us his DHT temporary public key.
- *
- * object and number will be passed as argument to this function.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num, void (*function)(void *data, int32_t number,
- const uint8_t *dht_public_key, void *userdata), void *object, uint32_t number);
-
-/* Set a friends DHT public key.
- * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
- * the other peer.
- *
- * return -1 on failure.
- * return 0 on success.
- */
-int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key);
-
-/* Copy friends DHT public key into dht_key.
- *
- * return 0 on failure (no key copied).
- * return 1 on success (key copied).
- */
-unsigned int onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
-
-#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
-#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
-
-/* Send data of length length to friendnum.
- * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE.
- * This data will be received by the friend using the Onion_Data_Handlers callbacks.
- *
- * Even if this function succeeds, the friend might not receive any data.
- *
- * return the number of packets sent on success
- * return -1 on failure.
- */
-int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length);
-
-/* Function to call when onion data packet with contents beginning with byte is received. */
-void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
-
-void do_onion_client(Onion_Client *onion_c);
-
-Onion_Client *new_onion_client(Net_Crypto *c);
-
-void kill_onion_client(Onion_Client *onion_c);
-
-
-/* return 0 if we are not connected to the network.
- * return 1 if we are connected with TCP only.
- * return 2 if we are also connected with UDP.
- */
-unsigned int onion_connection_status(const Onion_Client *onion_c);
-
-#endif
diff --git a/libs/libtox/src/toxcore/ping.c b/libs/libtox/src/toxcore/ping.c
deleted file mode 100644
index 72b3fe6259..0000000000
--- a/libs/libtox/src/toxcore/ping.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Buffered pinging using cyclic arrays.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- * Copyright © 2013 plutooo
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- * This file is donated to the Tox Project.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ping.h"
-
-#include "DHT.h"
-#include "network.h"
-#include "ping_array.h"
-#include "util.h"
-
-#include <stdint.h>
-
-#define PING_NUM_MAX 512
-
-/* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */
-#define MAX_TO_PING 32
-
-/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/
-#define TIME_TO_PING 2
-
-
-struct PING {
- DHT *dht;
-
- Ping_Array ping_array;
- Node_format to_ping[MAX_TO_PING];
- uint64_t last_to_ping;
-};
-
-
-#define PING_PLAIN_SIZE (1 + sizeof(uint64_t))
-#define DHT_PING_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + PING_PLAIN_SIZE + CRYPTO_MAC_SIZE)
-#define PING_DATA_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(IP_Port))
-
-int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key)
-{
- uint8_t pk[DHT_PING_SIZE];
- int rc;
- uint64_t ping_id;
-
- if (id_equal(public_key, ping->dht->self_public_key)) {
- return 1;
- }
-
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
-
- // generate key to encrypt ping_id with recipient privkey
- DHT_get_shared_key_sent(ping->dht, shared_key, public_key);
- // Generate random ping_id.
- uint8_t data[PING_DATA_SIZE];
- id_copy(data, public_key);
- memcpy(data + CRYPTO_PUBLIC_KEY_SIZE, &ipp, sizeof(IP_Port));
- ping_id = ping_array_add(&ping->ping_array, data, sizeof(data));
-
- if (ping_id == 0) {
- return 1;
- }
-
- uint8_t ping_plain[PING_PLAIN_SIZE];
- ping_plain[0] = NET_PACKET_PING_REQUEST;
- memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
-
- pk[0] = NET_PACKET_PING_REQUEST;
- id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
- random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
-
-
- rc = encrypt_data_symmetric(shared_key,
- pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- ping_plain, sizeof(ping_plain),
- pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
-
- if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
- return 1;
- }
-
- return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
-}
-
-static int send_ping_response(PING *ping, IP_Port ipp, const uint8_t *public_key, uint64_t ping_id,
- uint8_t *shared_encryption_key)
-{
- uint8_t pk[DHT_PING_SIZE];
- int rc;
-
- if (id_equal(public_key, ping->dht->self_public_key)) {
- return 1;
- }
-
- uint8_t ping_plain[PING_PLAIN_SIZE];
- ping_plain[0] = NET_PACKET_PING_RESPONSE;
- memcpy(ping_plain + 1, &ping_id, sizeof(ping_id));
-
- pk[0] = NET_PACKET_PING_RESPONSE;
- id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
- random_nonce(pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
-
- // Encrypt ping_id using recipient privkey
- rc = encrypt_data_symmetric(shared_encryption_key,
- pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- ping_plain, sizeof(ping_plain),
- pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
-
- if (rc != PING_PLAIN_SIZE + CRYPTO_MAC_SIZE) {
- return 1;
- }
-
- return sendpacket(ping->dht->net, ipp, pk, sizeof(pk));
-}
-
-static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
- int rc;
-
- if (length != DHT_PING_SIZE) {
- return 1;
- }
-
- PING *ping = dht->ping;
-
- if (id_equal(packet + 1, ping->dht->self_public_key)) {
- return 1;
- }
-
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
-
- uint8_t ping_plain[PING_PLAIN_SIZE];
- // Decrypt ping_id
- DHT_get_shared_key_recv(dht, shared_key, packet + 1);
- rc = decrypt_data_symmetric(shared_key,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
- PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
- ping_plain);
-
- if (rc != sizeof(ping_plain)) {
- return 1;
- }
-
- if (ping_plain[0] != NET_PACKET_PING_REQUEST) {
- return 1;
- }
-
- uint64_t ping_id;
- memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
- // Send response
- send_ping_response(ping, source, packet + 1, ping_id, shared_key);
- add_to_ping(ping, packet + 1, source);
-
- return 0;
-}
-
-static int handle_ping_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata)
-{
- DHT *dht = (DHT *)object;
- int rc;
-
- if (length != DHT_PING_SIZE) {
- return 1;
- }
-
- PING *ping = dht->ping;
-
- if (id_equal(packet + 1, ping->dht->self_public_key)) {
- return 1;
- }
-
- uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
-
- // generate key to encrypt ping_id with recipient privkey
- DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);
-
- uint8_t ping_plain[PING_PLAIN_SIZE];
- // Decrypt ping_id
- rc = decrypt_data_symmetric(shared_key,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
- packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
- PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
- ping_plain);
-
- if (rc != sizeof(ping_plain)) {
- return 1;
- }
-
- if (ping_plain[0] != NET_PACKET_PING_RESPONSE) {
- return 1;
- }
-
- uint64_t ping_id;
- memcpy(&ping_id, ping_plain + 1, sizeof(ping_id));
- uint8_t data[PING_DATA_SIZE];
-
- if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) {
- return 1;
- }
-
- if (!id_equal(packet + 1, data)) {
- return 1;
- }
-
- IP_Port ipp;
- memcpy(&ipp, data + CRYPTO_PUBLIC_KEY_SIZE, sizeof(IP_Port));
-
- if (!ipport_equal(&ipp, &source)) {
- return 1;
- }
-
- addto_lists(dht, source, packet + 1);
- return 0;
-}
-
-/* Check if public_key with ip_port is in the list.
- *
- * return 1 if it is.
- * return 0 if it isn't.
- */
-static int in_list(const Client_data *list, uint16_t length, const uint8_t *public_key, IP_Port ip_port)
-{
- unsigned int i;
-
- for (i = 0; i < length; ++i) {
- if (id_equal(list[i].public_key, public_key)) {
- const IPPTsPng *ipptp;
-
- if (ip_port.ip.family == TOX_AF_INET) {
- ipptp = &list[i].assoc4;
- } else {
- ipptp = &list[i].assoc6;
- }
-
- if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) {
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-/* Add nodes to the to_ping list.
- * All nodes in this list are pinged every TIME_TO_PING seconds
- * and are then removed from the list.
- * If the list is full the nodes farthest from our public_key are replaced.
- * The purpose of this list is to enable quick integration of new nodes into the
- * network while preventing amplification attacks.
- *
- * return 0 if node was added.
- * return -1 if node was not added.
- */
-int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port)
-{
- if (!ip_isset(&ip_port.ip)) {
- return -1;
- }
-
- if (!node_addable_to_close_list(ping->dht, public_key, ip_port)) {
- return -1;
- }
-
- if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, public_key, ip_port)) {
- return -1;
- }
-
- IP_Port temp;
-
- if (DHT_getfriendip(ping->dht, public_key, &temp) == 0) {
- send_ping_request(ping, ip_port, public_key);
- return -1;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_TO_PING; ++i) {
- if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
- memcpy(ping->to_ping[i].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
- ipport_copy(&ping->to_ping[i].ip_port, &ip_port);
- return 0;
- }
-
- if (public_key_cmp(ping->to_ping[i].public_key, public_key) == 0) {
- return -1;
- }
- }
-
- if (add_to_list(ping->to_ping, MAX_TO_PING, public_key, ip_port, ping->dht->self_public_key)) {
- return 0;
- }
-
- return -1;
-}
-
-
-/* Ping all the valid nodes in the to_ping list every TIME_TO_PING seconds.
- * This function must be run at least once every TIME_TO_PING seconds.
- */
-void do_to_ping(PING *ping)
-{
- if (!is_timeout(ping->last_to_ping, TIME_TO_PING)) {
- return;
- }
-
- if (!ip_isset(&ping->to_ping[0].ip_port.ip)) {
- return;
- }
-
- unsigned int i;
-
- for (i = 0; i < MAX_TO_PING; ++i) {
- if (!ip_isset(&ping->to_ping[i].ip_port.ip)) {
- break;
- }
-
- if (!node_addable_to_close_list(ping->dht, ping->to_ping[i].public_key, ping->to_ping[i].ip_port)) {
- continue;
- }
-
- send_ping_request(ping, ping->to_ping[i].ip_port, ping->to_ping[i].public_key);
- ip_reset(&ping->to_ping[i].ip_port.ip);
- }
-
- if (i != 0) {
- ping->last_to_ping = unix_time();
- }
-}
-
-
-PING *new_ping(DHT *dht)
-{
- PING *ping = (PING *)calloc(1, sizeof(PING));
-
- if (ping == NULL) {
- return NULL;
- }
-
- if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) {
- free(ping);
- return NULL;
- }
-
- ping->dht = dht;
- networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
- networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
-
- return ping;
-}
-
-void kill_ping(PING *ping)
-{
- networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL);
- networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL);
- ping_array_free_all(&ping->ping_array);
-
- free(ping);
-}
diff --git a/libs/libtox/src/toxcore/ping.h b/libs/libtox/src/toxcore/ping.h
deleted file mode 100644
index cc3428c548..0000000000
--- a/libs/libtox/src/toxcore/ping.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Buffered pinging using cyclic arrays.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- * Copyright © 2013 plutooo
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- * This file is donated to the Tox Project.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef PING_H
-#define PING_H
-
-#include "DHT.h"
-#include "network.h"
-
-#include <stdint.h>
-
-typedef struct PING PING;
-
-/* Add nodes to the to_ping list.
- * All nodes in this list are pinged every TIME_TOPING seconds
- * and are then removed from the list.
- * If the list is full the nodes farthest from our public_key are replaced.
- * The purpose of this list is to enable quick integration of new nodes into the
- * network while preventing amplification attacks.
- *
- * return 0 if node was added.
- * return -1 if node was not added.
- */
-int add_to_ping(PING *ping, const uint8_t *public_key, IP_Port ip_port);
-void do_to_ping(PING *ping);
-
-PING *new_ping(DHT *dht);
-void kill_ping(PING *ping);
-
-int send_ping_request(PING *ping, IP_Port ipp, const uint8_t *public_key);
-
-#endif /* PING_H */
diff --git a/libs/libtox/src/toxcore/ping_array.c b/libs/libtox/src/toxcore/ping_array.c
deleted file mode 100644
index ea3e5101b1..0000000000
--- a/libs/libtox/src/toxcore/ping_array.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Implementation of an efficient array to store that we pinged something.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ping_array.h"
-
-#include "crypto_core.h"
-#include "util.h"
-
-static void clear_entry(Ping_Array *array, uint32_t index)
-{
- free(array->entries[index].data);
- array->entries[index].data = NULL;
- array->entries[index].length =
- array->entries[index].time =
- array->entries[index].ping_id = 0;
-}
-
-/* Clear timed out entries.
- */
-static void ping_array_clear_timedout(Ping_Array *array)
-{
- while (array->last_deleted != array->last_added) {
- uint32_t index = array->last_deleted % array->total_size;
-
- if (!is_timeout(array->entries[index].time, array->timeout)) {
- break;
- }
-
- clear_entry(array, index);
- ++array->last_deleted;
- }
-}
-
-/* Add a data with length to the Ping_Array list and return a ping_id.
- *
- * return ping_id on success.
- * return 0 on failure.
- */
-uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length)
-{
- ping_array_clear_timedout(array);
- uint32_t index = array->last_added % array->total_size;
-
- if (array->entries[index].data != NULL) {
- array->last_deleted = array->last_added - array->total_size;
- clear_entry(array, index);
- }
-
- array->entries[index].data = malloc(length);
-
- if (array->entries[index].data == NULL) {
- return 0;
- }
-
- memcpy(array->entries[index].data, data, length);
- array->entries[index].length = length;
- array->entries[index].time = unix_time();
- ++array->last_added;
- uint64_t ping_id = random_64b();
- ping_id /= array->total_size;
- ping_id *= array->total_size;
- ping_id += index;
-
- if (ping_id == 0) {
- ping_id += array->total_size;
- }
-
- array->entries[index].ping_id = ping_id;
- return ping_id;
-}
-
-
-/* Check if ping_id is valid and not timed out.
- *
- * On success, copies the data into data of length,
- *
- * return length of data copied on success.
- * return -1 on failure.
- */
-int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id)
-{
- if (ping_id == 0) {
- return -1;
- }
-
- uint32_t index = ping_id % array->total_size;
-
- if (array->entries[index].ping_id != ping_id) {
- return -1;
- }
-
- if (is_timeout(array->entries[index].time, array->timeout)) {
- return -1;
- }
-
- if (array->entries[index].length > length) {
- return -1;
- }
-
- if (array->entries[index].data == NULL) {
- return -1;
- }
-
- memcpy(data, array->entries[index].data, array->entries[index].length);
- uint32_t len = array->entries[index].length;
- clear_entry(array, index);
- return len;
-}
-
-/* Initialize a Ping_Array.
- * size represents the total size of the array and should be a power of 2.
- * timeout represents the maximum timeout in seconds for the entry.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout)
-{
- if (size == 0 || timeout == 0 || empty_array == NULL) {
- return -1;
- }
-
- empty_array->entries = (Ping_Array_Entry *)calloc(size, sizeof(Ping_Array_Entry));
-
- if (empty_array->entries == NULL) {
- return -1;
- }
-
- empty_array->last_deleted = empty_array->last_added = 0;
- empty_array->total_size = size;
- empty_array->timeout = timeout;
- return 0;
-}
-
-/* Free all the allocated memory in a Ping_Array.
- */
-void ping_array_free_all(Ping_Array *array)
-{
- while (array->last_deleted != array->last_added) {
- uint32_t index = array->last_deleted % array->total_size;
- clear_entry(array, index);
- ++array->last_deleted;
- }
-
- free(array->entries);
- array->entries = NULL;
-}
-
diff --git a/libs/libtox/src/toxcore/ping_array.h b/libs/libtox/src/toxcore/ping_array.h
deleted file mode 100644
index bdf3c6db3d..0000000000
--- a/libs/libtox/src/toxcore/ping_array.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Implementation of an efficient array to store that we pinged something.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef PING_ARRAY_H
-#define PING_ARRAY_H
-
-#include "network.h"
-
-typedef struct {
- void *data;
- uint32_t length;
- uint64_t time;
- uint64_t ping_id;
-} Ping_Array_Entry;
-
-
-typedef struct {
- Ping_Array_Entry *entries;
-
- uint32_t last_deleted; /* number representing the next entry to be deleted. */
- uint32_t last_added; /* number representing the last entry to be added. */
- uint32_t total_size; /* The length of entries */
- uint32_t timeout; /* The timeout after which entries are cleared. */
-} Ping_Array;
-
-
-/* Add a data with length to the Ping_Array list and return a ping_id.
- *
- * return ping_id on success.
- * return 0 on failure.
- */
-uint64_t ping_array_add(Ping_Array *array, const uint8_t *data, uint32_t length);
-
-/* Check if ping_id is valid and not timed out.
- *
- * On success, copies the data into data of length,
- *
- * return length of data copied on success.
- * return -1 on failure.
- */
-int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id);
-
-/* Initialize a Ping_Array.
- * size represents the total size of the array and should be a power of 2.
- * timeout represents the maximum timeout in seconds for the entry.
- *
- * return 0 on success.
- * return -1 on failure.
- */
-int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout);
-
-/* Free all the allocated memory in a Ping_Array.
- */
-void ping_array_free_all(Ping_Array *array);
-
-#endif
diff --git a/libs/libtox/src/toxcore/tox.api.h b/libs/libtox/src/toxcore/tox.api.h
deleted file mode 100644
index 0763c7789d..0000000000
--- a/libs/libtox/src/toxcore/tox.api.h
+++ /dev/null
@@ -1,2583 +0,0 @@
-%{
-/*
- * The Tox public API.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOX_H
-#define TOX_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-%}
-
-
-/*****************************************************************************
- * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
- * `tox.api.h`, located in `toxcore/`. For instructions on how to *
- * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md` *
- *****************************************************************************/
-
-
-/** \page core Public core API for Tox clients.
- *
- * Every function that can fail takes a function-specific error code pointer
- * that can be used to diagnose problems with the Tox state or the function
- * arguments. The error code pointer can be NULL, which does not influence the
- * function's behaviour, but can be done if the reason for failure is irrelevant
- * to the client.
- *
- * The exception to this rule are simple allocation functions whose only failure
- * mode is allocation failure. They return NULL in that case, and do not set an
- * error code.
- *
- * Every error code type has an OK value to which functions will set their error
- * code value on success. Clients can keep their error code uninitialised before
- * passing it to a function. The library guarantees that after returning, the
- * value pointed to by the error code pointer has been initialised.
- *
- * Functions with pointer parameters often have a NULL error code, meaning they
- * could not perform any operation, because one of the required parameters was
- * NULL. Some functions operate correctly or are defined as effectless on NULL.
- *
- * Some functions additionally return a value outside their
- * return type domain, or a bool containing true on success and false on
- * failure.
- *
- * All functions that take a Tox instance pointer will cause undefined behaviour
- * when passed a NULL Tox pointer.
- *
- * All integer values are expected in host byte order.
- *
- * Functions with parameters with enum types cause unspecified behaviour if the
- * enumeration value is outside the valid range of the type. If possible, the
- * function will try to use a sane default, but there will be no error code,
- * and one possible action for the function to take is to have no effect.
- *
- * Integer constants and the memory layout of publicly exposed structs are not
- * part of the ABI.
- */
-
-/** \subsection events Events and callbacks
- *
- * Events are handled by callbacks. One callback can be registered per event.
- * All events have a callback function type named `tox_{event}_cb` and a
- * function to register it named `tox_callback_{event}`. Passing a NULL
- * callback will result in no callback being registered for that event. Only
- * one callback per event can be registered, so if a client needs multiple
- * event listeners, it needs to implement the dispatch functionality itself.
- *
- * The last argument to a callback is the user data pointer. It is passed from
- * ${tox.iterate} to each callback in sequence.
- *
- * The user data pointer is never stored or dereferenced by any library code, so
- * can be any pointer, including NULL. Callbacks must all operate on the same
- * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
- * `any` in ${tox.iterate} must be the same `any` as in all callbacks. In C,
- * lacking parametric polymorphism, this is a pointer to void.
- *
- * Old style callbacks that are registered together with a user data pointer
- * receive that pointer as argument when they are called. They can each have
- * their own user data pointer of their own type.
- */
-
-/** \subsection threading Threading implications
- *
- * It is possible to run multiple concurrent threads with a Tox instance for
- * each thread. It is also possible to run all Tox instances in the same thread.
- * A common way to run Tox (multiple or single instance) is to have one thread
- * running a simple ${tox.iterate} loop, sleeping for ${tox.iteration_interval}
- * milliseconds on each iteration.
- *
- * If you want to access a single Tox instance from multiple threads, access
- * to the instance must be synchronised. While multiple threads can concurrently
- * access multiple different Tox instances, no more than one API function can
- * operate on a single instance at any given time.
- *
- * Functions that write to variable length byte arrays will always have a size
- * function associated with them. The result of this size function is only valid
- * until another mutating function (one that takes a pointer to non-const Tox)
- * is called. Thus, clients must ensure that no other thread calls a mutating
- * function between the call to the size function and the call to the retrieval
- * function.
- *
- * E.g. to get the current nickname, one would write
- *
- * \code
- * size_t length = ${tox.self.name.size}(tox);
- * uint8_t *name = malloc(length);
- * if (!name) abort();
- * ${tox.self.name.get}(tox, name);
- * \endcode
- *
- * If any other thread calls ${tox.self.name.set} while this thread is allocating
- * memory, the length may have become invalid, and the call to
- * ${tox.self.name.get} may cause undefined behaviour.
- */
-
-// The rest of this file is in class tox.
-class tox {
-
-/**
- * The Tox instance type. All the state associated with a connection is held
- * within the instance. Multiple instances can exist and operate concurrently.
- * The maximum number of Tox instances that can exist on a single network
- * device is limited. Note that this is not just a per-process limit, since the
- * limiting factor is the number of usable ports on a device.
- */
-struct this;
-
-
-/*******************************************************************************
- *
- * :: API version
- *
- ******************************************************************************/
-
-
-/**
- * The major version number. Incremented when the API or ABI changes in an
- * incompatible way.
- *
- * The function variants of these constants return the version number of the
- * library. They can be used to display the Tox library version or to check
- * whether the client is compatible with the dynamically linked version of Tox.
- */
-const VERSION_MAJOR = 0;
-
-/**
- * The minor version number. Incremented when functionality is added without
- * breaking the API or ABI. Set to 0 when the major version number is
- * incremented.
- */
-const VERSION_MINOR = 1;
-
-/**
- * The patch or revision number. Incremented when bugfixes are applied without
- * changing any functionality or API or ABI.
- */
-const VERSION_PATCH = 10;
-
-/**
- * A macro to check at preprocessing time whether the client code is compatible
- * with the installed version of Tox. Leading zeros in the version number are
- * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new
- * features, but can't break the API.
- */
-#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
- (TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && ( \
- /* 1.x.x, 2.x.x, etc. with matching major version. */ \
- TOX_VERSION_MINOR > MINOR || \
- TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH \
- ) || (TOX_VERSION_MAJOR == 0 && MAJOR == 0) && ( \
- /* 0.x.x makes minor behave like major above. */ \
- (TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && ( \
- TOX_VERSION_PATCH >= PATCH \
- ) || (TOX_VERSION_MINOR == 0 && MINOR == 0) && ( \
- /* 0.0.x and 0.0.y are only compatible if x == y. */ \
- TOX_VERSION_PATCH == PATCH \
- ) \
- )
-
-static namespace version {
-
- /**
- * Return whether the compiled library version is compatible with the passed
- * version numbers.
- */
- bool is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
-
-}
-
-/**
- * A convenience macro to call tox_version_is_compatible with the currently
- * compiling API version.
- */
-#define TOX_VERSION_IS_ABI_COMPATIBLE() \
- tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH)
-
-/*******************************************************************************
- *
- * :: Numeric constants
- *
- * The values of these are not part of the ABI. Prefer to use the function
- * versions of them for code that should remain compatible with future versions
- * of toxcore.
- *
- ******************************************************************************/
-
-
-/**
- * The size of a Tox Public Key in bytes.
- */
-const PUBLIC_KEY_SIZE = 32;
-
-/**
- * The size of a Tox Secret Key in bytes.
- */
-const SECRET_KEY_SIZE = 32;
-
-/**
- * The size of the nospam in bytes when written in a Tox address.
- */
-const NOSPAM_SIZE = sizeof(uint32_t);
-
-/**
- * The size of a Tox address in bytes. Tox addresses are in the format
- * [Public Key ($PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
- *
- * The checksum is computed over the Public Key and the nospam value. The first
- * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
- * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
- */
-const ADDRESS_SIZE = PUBLIC_KEY_SIZE + NOSPAM_SIZE + sizeof(uint16_t);
-
-/**
- * Maximum length of a nickname in bytes.
- */
-const MAX_NAME_LENGTH = 128;
-
-/**
- * Maximum length of a status message in bytes.
- */
-const MAX_STATUS_MESSAGE_LENGTH = 1007;
-
-/**
- * Maximum length of a friend request message in bytes.
- */
-const MAX_FRIEND_REQUEST_LENGTH = 1016;
-
-/**
- * Maximum length of a single message after which it should be split.
- */
-const MAX_MESSAGE_LENGTH = 1372;
-
-/**
- * Maximum size of custom packets. TODO(iphydf): should be LENGTH?
- */
-const MAX_CUSTOM_PACKET_SIZE = 1373;
-
-/**
- * The number of bytes in a hash generated by $hash.
- */
-const HASH_LENGTH = 32;
-
-/**
- * The number of bytes in a file id.
- */
-const FILE_ID_LENGTH = 32;
-
-/**
- * Maximum file name length for file transfers.
- */
-const MAX_FILENAME_LENGTH = 255;
-
-
-/*******************************************************************************
- *
- * :: Global enumerations
- *
- ******************************************************************************/
-
-
-/**
- * Represents the possible statuses a client can have.
- */
-enum class USER_STATUS {
- /**
- * User is online and available.
- */
- NONE,
- /**
- * User is away. Clients can set this e.g. after a user defined
- * inactivity time.
- */
- AWAY,
- /**
- * User is busy. Signals to other clients that this client does not
- * currently wish to communicate.
- */
- BUSY,
-}
-
-
-/**
- * Represents message types for ${tox.friend.send.message} and conference
- * messages.
- */
-enum class MESSAGE_TYPE {
- /**
- * Normal text message. Similar to PRIVMSG on IRC.
- */
- NORMAL,
- /**
- * A message describing an user action. This is similar to /me (CTCP ACTION)
- * on IRC.
- */
- ACTION,
-}
-
-
-/*******************************************************************************
- *
- * :: Startup options
- *
- ******************************************************************************/
-
-
-/**
- * Type of proxy used to connect to TCP relays.
- */
-enum class PROXY_TYPE {
- /**
- * Don't use a proxy.
- */
- NONE,
- /**
- * HTTP proxy using CONNECT.
- */
- HTTP,
- /**
- * SOCKS proxy for simple socket pipes.
- */
- SOCKS5,
-}
-
-/**
- * Type of savedata to create the Tox instance from.
- */
-enum class SAVEDATA_TYPE {
- /**
- * No savedata.
- */
- NONE,
- /**
- * Savedata is one that was obtained from ${savedata.get}.
- */
- TOX_SAVE,
- /**
- * Savedata is a secret key of length $SECRET_KEY_SIZE.
- */
- SECRET_KEY,
-}
-
-
-/**
- * Severity level of log messages.
- */
-enum class LOG_LEVEL {
- /**
- * Very detailed traces including all network activity.
- */
- TRACE,
- /**
- * Debug messages such as which port we bind to.
- */
- DEBUG,
- /**
- * Informational log messages such as video call status changes.
- */
- INFO,
- /**
- * Warnings about internal inconsistency or logic errors.
- */
- WARNING,
- /**
- * Severe unexpected errors caused by external or internal inconsistency.
- */
- ERROR,
-}
-
-/**
- * This event is triggered when the toxcore library logs an internal message.
- * This is mostly useful for debugging. This callback can be called from any
- * function, not just $iterate. This means the user data lifetime must at
- * least extend between registering and unregistering it or $kill.
- *
- * Other toxcore modules such as toxav may concurrently call this callback at
- * any time. Thus, user code must make sure it is equipped to handle concurrent
- * execution, e.g. by employing appropriate mutex locking.
- *
- * @param level The severity of the log message.
- * @param file The source file from which the message originated.
- * @param line The source line from which the message originated.
- * @param func The function from which the message originated.
- * @param message The log message.
- * @param user_data The user data pointer passed to $new in options.
- */
-typedef void log_cb(LOG_LEVEL level, string file, uint32_t line, string func, string message, any user_data);
-
-
-static class options {
- /**
- * This struct contains all the startup options for Tox. You must $new to
- * allocate an object of this type.
- *
- * WARNING: Although this struct happens to be visible in the API, it is
- * effectively private. Do not allocate this yourself or access members
- * directly, as it *will* break binary compatibility frequently.
- *
- * @deprecated The memory layout of this struct (size, alignment, and field
- * order) is not part of the ABI. To remain compatible, prefer to use $new to
- * allocate the object and accessor functions to set the members. The struct
- * will become opaque (i.e. the definition will become private) in v0.2.0.
- */
- struct this [get, set] {
- /**
- * The type of socket to create.
- *
- * If this is set to false, an IPv4 socket is created, which subsequently
- * only allows IPv4 communication.
- * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
- * IPv6 communication.
- */
- bool ipv6_enabled;
-
- /**
- * Enable the use of UDP communication when available.
- *
- * Setting this to false will force Tox to use TCP only. Communications will
- * need to be relayed through a TCP relay node, potentially slowing them down.
- * Disabling UDP support is necessary when using anonymous proxies or Tor.
- */
- bool udp_enabled;
-
- /**
- * Enable local network peer discovery.
- *
- * Disabling this will cause Tox to not look for peers on the local network.
- */
- bool local_discovery_enabled;
-
- namespace proxy {
- /**
- * Pass communications through a proxy.
- */
- PROXY_TYPE type;
-
- /**
- * The IP address or DNS name of the proxy to be used.
- *
- * If used, this must be non-NULL and be a valid DNS name. The name must not
- * exceed 255 characters, and be in a NUL-terminated C string format
- * (255 chars + 1 NUL byte).
- *
- * This member is ignored (it can be NULL) if proxy_type is ${PROXY_TYPE.NONE}.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- string host;
-
- /**
- * The port to use to connect to the proxy server.
- *
- * Ports must be in the range (1, 65535). The value is ignored if
- * proxy_type is ${PROXY_TYPE.NONE}.
- */
- uint16_t port;
- }
-
- /**
- * The start port of the inclusive port range to attempt to use.
- *
- * If both start_port and end_port are 0, the default port range will be
- * used: [33445, 33545].
- *
- * If either start_port or end_port is 0 while the other is non-zero, the
- * non-zero port will be the only port in the range.
- *
- * Having start_port > end_port will yield the same behavior as if start_port
- * and end_port were swapped.
- */
- uint16_t start_port;
-
- /**
- * The end port of the inclusive port range to attempt to use.
- */
- uint16_t end_port;
-
- /**
- * The port to use for the TCP server (relay). If 0, the TCP server is
- * disabled.
- *
- * Enabling it is not required for Tox to function properly.
- *
- * When enabled, your Tox instance can act as a TCP relay for other Tox
- * instance. This leads to increased traffic, thus when writing a client
- * it is recommended to enable TCP server only if the user has an option
- * to disable it.
- */
- uint16_t tcp_port;
-
- /**
- * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
- */
- bool hole_punching_enabled;
-
- namespace savedata {
- /**
- * The type of savedata to load from.
- */
- SAVEDATA_TYPE type;
-
- /**
- * The savedata.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- const uint8_t[length] data;
-
- /**
- * The length of the savedata.
- */
- size_t length;
- }
-
- namespace log {
- /**
- * Logging callback for the new tox instance.
- */
- log_cb *callback;
-
- /**
- * User data pointer passed to the logging callback.
- */
- any user_data;
- }
- }
-
-
- /**
- * Initialises a $this object with the default options.
- *
- * The result of this function is independent of the original options. All
- * values will be overwritten, no values will be read (so it is permissible
- * to pass an uninitialised object).
- *
- * If options is NULL, this function has no effect.
- *
- * @param options An options object to be filled with default options.
- */
- void default();
-
-
- /**
- * Allocates a new $this object and initialises it with the default
- * options. This function can be used to preserve long term ABI compatibility by
- * giving the responsibility of allocation and deallocation to the Tox library.
- *
- * Objects returned from this function must be freed using the $free
- * function.
- *
- * @return A new $this object with default options or NULL on failure.
- */
- static this new() {
- /**
- * The function failed to allocate enough memory for the options struct.
- */
- MALLOC,
- }
-
-
- /**
- * Releases all resources associated with an options objects.
- *
- * Passing a pointer that was not returned by $new results in
- * undefined behaviour.
- */
- void free();
-}
-
-
-/*******************************************************************************
- *
- * :: Creation and destruction
- *
- ******************************************************************************/
-
-
-/**
- * @brief Creates and initialises a new Tox instance with the options passed.
- *
- * This function will bring the instance into a valid state. Running the event
- * loop with a new instance will operate correctly.
- *
- * If loading failed or succeeded only partially, the new or partially loaded
- * instance is returned and an error code is set.
- *
- * @param options An options object as described above. If this parameter is
- * NULL, the default options are used.
- *
- * @see $iterate for the event loop.
- *
- * @return A new Tox instance pointer on success or NULL on failure.
- */
-static this new(const options_t *options) {
- NULL,
- /**
- * The function was unable to allocate enough memory to store the internal
- * structures for the Tox object.
- */
- MALLOC,
- /**
- * The function was unable to bind to a port. This may mean that all ports
- * have already been bound, e.g. by other Tox instances, or it may mean
- * a permission error. You may be able to gather more information from errno.
- */
- PORT_ALLOC,
-
- namespace PROXY {
- /**
- * proxy_type was invalid.
- */
- BAD_TYPE,
- /**
- * proxy_type was valid but the proxy_host passed had an invalid format
- * or was NULL.
- */
- BAD_HOST,
- /**
- * proxy_type was valid, but the proxy_port was invalid.
- */
- BAD_PORT,
- /**
- * The proxy address passed could not be resolved.
- */
- NOT_FOUND,
- }
-
- namespace LOAD {
- /**
- * The byte array to be loaded contained an encrypted save.
- */
- ENCRYPTED,
- /**
- * The data format was invalid. This can happen when loading data that was
- * saved by an older version of Tox, or when the data has been corrupted.
- * When loading from badly formatted data, some data may have been loaded,
- * and the rest is discarded. Passing an invalid length parameter also
- * causes this error.
- */
- BAD_FORMAT,
- }
-}
-
-
-/**
- * Releases all resources associated with the Tox instance and disconnects from
- * the network.
- *
- * After calling this function, the Tox pointer becomes invalid. No other
- * functions can be called, and the pointer value can no longer be read.
- */
-void kill();
-
-
-uint8_t[size] savedata {
- /**
- * Calculates the number of bytes required to store the tox instance with
- * $get. This function cannot fail. The result is always greater than 0.
- *
- * @see threading for concurrency implications.
- */
- size();
-
- /**
- * Store all information associated with the tox instance to a byte array.
- *
- * @param savedata A memory region large enough to store the tox instance
- * data. Call $size to find the number of bytes required. If this parameter
- * is NULL, this function has no effect.
- */
- get();
-}
-
-
-/*******************************************************************************
- *
- * :: Connection lifecycle and event loop
- *
- ******************************************************************************/
-
-
-/**
- * Sends a "get nodes" request to the given bootstrap node with IP, port, and
- * public key to setup connections.
- *
- * This function will attempt to connect to the node using UDP. You must use
- * this function even if ${options.this.udp_enabled} was set to false.
- *
- * @param address The hostname or IP address (IPv4 or IPv6) of the node.
- * @param port The port on the host on which the bootstrap Tox instance is
- * listening.
- * @param public_key The long term public key of the bootstrap node
- * ($PUBLIC_KEY_SIZE bytes).
- * @return true on success.
- */
-bool bootstrap(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key) {
- NULL,
- /**
- * The address could not be resolved to an IP address, or the IP address
- * passed was invalid.
- */
- BAD_HOST,
- /**
- * The port passed was invalid. The valid port range is (1, 65535).
- */
- BAD_PORT,
-}
-
-
-/**
- * Adds additional host:port pair as TCP relay.
- *
- * This function can be used to initiate TCP connections to different ports on
- * the same bootstrap node, or to add TCP relays without using them as
- * bootstrap nodes.
- *
- * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay.
- * @param port The port on the host on which the TCP relay is listening.
- * @param public_key The long term public key of the TCP relay
- * ($PUBLIC_KEY_SIZE bytes).
- * @return true on success.
- */
-bool add_tcp_relay(string address, uint16_t port, const uint8_t[PUBLIC_KEY_SIZE] public_key)
- with error for bootstrap;
-
-
-/**
- * Protocols that can be used to connect to the network or friends.
- */
-enum class CONNECTION {
- /**
- * There is no connection. This instance, or the friend the state change is
- * about, is now offline.
- */
- NONE,
- /**
- * A TCP connection has been established. For the own instance, this means it
- * is connected through a TCP relay, only. For a friend, this means that the
- * connection to that particular friend goes through a TCP relay.
- */
- TCP,
- /**
- * A UDP connection has been established. For the own instance, this means it
- * is able to send UDP packets to DHT nodes, but may still be connected to
- * a TCP relay. For a friend, this means that the connection to that
- * particular friend was built using direct UDP packets.
- */
- UDP,
-}
-
-
-inline namespace self {
-
- CONNECTION connection_status {
- /**
- * Return whether we are connected to the DHT. The return value is equal to the
- * last value received through the `${event connection_status}` callback.
- */
- get();
- }
-
-
- /**
- * This event is triggered whenever there is a change in the DHT connection
- * state. When disconnected, a client may choose to call $bootstrap again, to
- * reconnect to the DHT. Note that this state may frequently change for short
- * amounts of time. Clients should therefore not immediately bootstrap on
- * receiving a disconnect.
- *
- * TODO(iphydf): how long should a client wait before bootstrapping again?
- */
- event connection_status const {
- /**
- * @param connection_status Whether we are connected to the DHT.
- */
- typedef void(CONNECTION connection_status);
- }
-
-}
-
-
-/**
- * Return the time in milliseconds before $iterate() should be called again
- * for optimal performance.
- */
-const uint32_t iteration_interval();
-
-
-/**
- * The main loop that needs to be run in intervals of $iteration_interval()
- * milliseconds.
- */
-void iterate(any user_data);
-
-
-/*******************************************************************************
- *
- * :: Internal client information (Tox address/id)
- *
- ******************************************************************************/
-
-
-inline namespace self {
-
- uint8_t[ADDRESS_SIZE] address {
- /**
- * Writes the Tox friend address of the client to a byte array. The address is
- * not in human-readable format. If a client wants to display the address,
- * formatting is required.
- *
- * @param address A memory region of at least $ADDRESS_SIZE bytes. If this
- * parameter is NULL, this function has no effect.
- * @see $ADDRESS_SIZE for the address format.
- */
- get();
- }
-
-
- uint32_t nospam {
- /**
- * Set the 4-byte nospam part of the address. This value is expected in host
- * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the
- * nospam part of the Tox friend address.
- *
- * @param nospam Any 32 bit unsigned integer.
- */
- set();
-
- /**
- * Get the 4-byte nospam part of the address. This value is returned in host
- * byte order.
- */
- get();
- }
-
-
- uint8_t[PUBLIC_KEY_SIZE] public_key {
- /**
- * Copy the Tox Public Key (long term) from the Tox object.
- *
- * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- */
- get();
- }
-
-
- uint8_t[SECRET_KEY_SIZE] secret_key {
- /**
- * Copy the Tox Secret Key from the Tox object.
- *
- * @param secret_key A memory region of at least $SECRET_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- */
- get();
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: User-visible client information (nickname/status)
- *
- ******************************************************************************/
-
-
-/**
- * Common error codes for all functions that set a piece of user-visible
- * client information.
- */
-error for set_info {
- NULL,
- /**
- * Information length exceeded maximum permissible size.
- */
- TOO_LONG,
-}
-
-
-inline namespace self {
-
- uint8_t[length <= MAX_NAME_LENGTH] name {
- /**
- * Set the nickname for the Tox client.
- *
- * Nickname length cannot exceed $MAX_NAME_LENGTH. If length is 0, the name
- * parameter is ignored (it can be NULL), and the nickname is set back to empty.
- *
- * @param name A byte array containing the new nickname.
- * @param length The size of the name byte array.
- *
- * @return true on success.
- */
- set() with error for set_info;
-
- /**
- * Return the length of the current nickname as passed to $set.
- *
- * If no nickname was set before calling this function, the name is empty,
- * and this function returns 0.
- *
- * @see threading for concurrency implications.
- */
- size();
-
- /**
- * Write the nickname set by $set to a byte array.
- *
- * If no nickname was set before calling this function, the name is empty,
- * and this function has no effect.
- *
- * Call $size to find out how much memory to allocate for
- * the result.
- *
- * @param name A valid memory location large enough to hold the nickname.
- * If this parameter is NULL, the function has no effect.
- */
- get();
- }
-
-
- uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
- /**
- * Set the client's status message.
- *
- * Status message length cannot exceed $MAX_STATUS_MESSAGE_LENGTH. If
- * length is 0, the status parameter is ignored (it can be NULL), and the
- * user status is set back to empty.
- */
- set() with error for set_info;
-
- /**
- * Return the length of the current status message as passed to $set.
- *
- * If no status message was set before calling this function, the status
- * is empty, and this function returns 0.
- *
- * @see threading for concurrency implications.
- */
- size();
-
- /**
- * Write the status message set by $set to a byte array.
- *
- * If no status message was set before calling this function, the status is
- * empty, and this function has no effect.
- *
- * Call $size to find out how much memory to allocate for
- * the result.
- *
- * @param status_message A valid memory location large enough to hold the
- * status message. If this parameter is NULL, the function has no effect.
- */
- get();
- }
-
-
- USER_STATUS status {
- /**
- * Set the client's user status.
- *
- * @param status One of the user statuses listed in the enumeration above.
- */
- set();
-
- /**
- * Returns the client's user status.
- */
- get();
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Friend list management
- *
- ******************************************************************************/
-
-
-namespace friend {
-
- /**
- * Add a friend to the friend list and send a friend request.
- *
- * A friend request message must be at least 1 byte long and at most
- * $MAX_FRIEND_REQUEST_LENGTH.
- *
- * Friend numbers are unique identifiers used in all functions that operate on
- * friends. Once added, a friend number is stable for the lifetime of the Tox
- * object. After saving the state and reloading it, the friend numbers may not
- * be the same as before. Deleting a friend creates a gap in the friend number
- * set, which is filled by the next adding of a friend. Any pattern in friend
- * numbers should not be relied on.
- *
- * If more than INT32_MAX friends are added, this function causes undefined
- * behaviour.
- *
- * @param address The address of the friend (returned by ${self.address.get} of
- * the friend you wish to add) it must be $ADDRESS_SIZE bytes.
- * @param message The message that will be sent along with the friend request.
- * @param length The length of the data byte array.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- */
- uint32_t add(
- const uint8_t[ADDRESS_SIZE] address,
- const uint8_t[length <= MAX_FRIEND_REQUEST_LENGTH] message
- ) {
- NULL,
- /**
- * The length of the friend request message exceeded
- * $MAX_FRIEND_REQUEST_LENGTH.
- */
- TOO_LONG,
- /**
- * The friend request message was empty. This, and the TOO_LONG code will
- * never be returned from $add_norequest.
- */
- NO_MESSAGE,
- /**
- * The friend address belongs to the sending client.
- */
- OWN_KEY,
- /**
- * A friend request has already been sent, or the address belongs to a friend
- * that is already on the friend list.
- */
- ALREADY_SENT,
- /**
- * The friend address checksum failed.
- */
- BAD_CHECKSUM,
- /**
- * The friend was already there, but the nospam value was different.
- */
- SET_NEW_NOSPAM,
- /**
- * A memory allocation failed when trying to increase the friend list size.
- */
- MALLOC,
- }
-
-
- /**
- * Add a friend without sending a friend request.
- *
- * This function is used to add a friend in response to a friend request. If the
- * client receives a friend request, it can be reasonably sure that the other
- * client added this client as a friend, eliminating the need for a friend
- * request.
- *
- * This function is also useful in a situation where both instances are
- * controlled by the same entity, so that this entity can perform the mutual
- * friend adding. In this case, there is no need for a friend request, either.
- *
- * @param public_key A byte array of length $PUBLIC_KEY_SIZE containing the
- * Public Key (not the Address) of the friend to add.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- * @see $add for a more detailed description of friend numbers.
- */
- uint32_t add_norequest(const uint8_t[PUBLIC_KEY_SIZE] public_key)
- with error for add;
-
-
- /**
- * Remove a friend from the friend list.
- *
- * This does not notify the friend of their deletion. After calling this
- * function, this client will appear offline to the friend and no communication
- * can occur between the two.
- *
- * @param friend_number Friend number for the friend to be deleted.
- *
- * @return true on success.
- */
- bool delete(uint32_t friend_number) {
- /**
- * There was no friend with the given friend number. No friends were deleted.
- */
- FRIEND_NOT_FOUND,
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Friend list queries
- *
- ******************************************************************************/
-
-namespace friend {
-
- /**
- * Return the friend number associated with that Public Key.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- * @param public_key A byte array containing the Public Key.
- */
- const uint32_t by_public_key(const uint8_t[PUBLIC_KEY_SIZE] public_key) {
- NULL,
- /**
- * No friend with the given Public Key exists on the friend list.
- */
- NOT_FOUND,
- }
-
-
- /**
- * Checks if a friend with the given friend number exists and returns true if
- * it does.
- */
- const bool exists(uint32_t friend_number);
-
-}
-
-inline namespace self {
-
- uint32_t[size] friend_list {
- /**
- * Return the number of friends on the friend list.
- *
- * This function can be used to determine how much memory to allocate for
- * $get.
- */
- size();
-
-
- /**
- * Copy a list of valid friend numbers into an array.
- *
- * Call $size to determine the number of elements to allocate.
- *
- * @param friend_list A memory region with enough space to hold the friend
- * list. If this parameter is NULL, this function has no effect.
- */
- get();
- }
-
-}
-
-
-
-namespace friend {
-
- uint8_t[PUBLIC_KEY_SIZE] public_key {
- /**
- * Copies the Public Key associated with a given friend number to a byte array.
- *
- * @param friend_number The friend number you want the Public Key of.
- * @param public_key A memory region of at least $PUBLIC_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
- get(uint32_t friend_number) {
- /**
- * No friend with the given number exists on the friend list.
- */
- FRIEND_NOT_FOUND,
- }
- }
-
-}
-
-namespace friend {
-
- uint64_t last_online {
- /**
- * Return a unix-time timestamp of the last time the friend associated with a given
- * friend number was seen online. This function will return UINT64_MAX on error.
- *
- * @param friend_number The friend number you want to query.
- */
- get(uint32_t friend_number) {
- /**
- * No friend with the given number exists on the friend list.
- */
- FRIEND_NOT_FOUND,
- }
- }
-
-}
-
-/*******************************************************************************
- *
- * :: Friend-specific state queries (can also be received through callbacks)
- *
- ******************************************************************************/
-
-
-namespace friend {
-
- /**
- * Common error codes for friend state query functions.
- */
- error for query {
- /**
- * The pointer parameter for storing the query result (name, message) was
- * NULL. Unlike the `_self_` variants of these functions, which have no effect
- * when a parameter is NULL, these functions return an error in that case.
- */
- NULL,
- /**
- * The friend_number did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- }
-
-
- uint8_t[length <= MAX_NAME_LENGTH] name {
- /**
- * Return the length of the friend's name. If the friend number is invalid, the
- * return value is unspecified.
- *
- * The return value is equal to the `length` argument received by the last
- * `${event name}` callback.
- */
- size(uint32_t friend_number)
- with error for query;
-
- /**
- * Write the name of the friend designated by the given friend number to a byte
- * array.
- *
- * Call $size to determine the allocation size for the `name`
- * parameter.
- *
- * The data written to `name` is equal to the data received by the last
- * `${event name}` callback.
- *
- * @param name A valid memory region large enough to store the friend's name.
- *
- * @return true on success.
- */
- get(uint32_t friend_number)
- with error for query;
- }
-
-
- /**
- * This event is triggered when a friend changes their name.
- */
- event name const {
- /**
- * @param friend_number The friend number of the friend whose name changed.
- * @param name A byte array containing the same data as
- * ${name.get} would write to its `name` parameter.
- * @param length A value equal to the return value of
- * ${name.size}.
- */
- typedef void(uint32_t friend_number, const uint8_t[length <= MAX_NAME_LENGTH] name);
- }
-
-
- uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] status_message {
- /**
- * Return the length of the friend's status message. If the friend number is
- * invalid, the return value is SIZE_MAX.
- */
- size(uint32_t friend_number)
- with error for query;
-
- /**
- * Write the status message of the friend designated by the given friend number to a byte
- * array.
- *
- * Call $size to determine the allocation size for the `status_name`
- * parameter.
- *
- * The data written to `status_message` is equal to the data received by the last
- * `${event status_message}` callback.
- *
- * @param status_message A valid memory region large enough to store the friend's status message.
- */
- get(uint32_t friend_number)
- with error for query;
- }
-
-
- /**
- * This event is triggered when a friend changes their status message.
- */
- event status_message const {
- /**
- * @param friend_number The friend number of the friend whose status message
- * changed.
- * @param message A byte array containing the same data as
- * ${status_message.get} would write to its `status_message` parameter.
- * @param length A value equal to the return value of
- * ${status_message.size}.
- */
- typedef void(uint32_t friend_number, const uint8_t[length <= MAX_STATUS_MESSAGE_LENGTH] message);
- }
-
-
- USER_STATUS status {
- /**
- * Return the friend's user status (away/busy/...). If the friend number is
- * invalid, the return value is unspecified.
- *
- * The status returned is equal to the last status received through the
- * `${event status}` callback.
- */
- get(uint32_t friend_number)
- with error for query;
- }
-
-
- /**
- * This event is triggered when a friend changes their user status.
- */
- event status const {
- /**
- * @param friend_number The friend number of the friend whose user status
- * changed.
- * @param status The new user status.
- */
- typedef void(uint32_t friend_number, USER_STATUS status);
- }
-
-
- CONNECTION connection_status {
- /**
- * Check whether a friend is currently connected to this client.
- *
- * The result of this function is equal to the last value received by the
- * `${event connection_status}` callback.
- *
- * @param friend_number The friend number for which to query the connection
- * status.
- *
- * @return the friend's connection status as it was received through the
- * `${event connection_status}` event.
- */
- get(uint32_t friend_number)
- with error for query;
- }
-
-
- /**
- * This event is triggered when a friend goes offline after having been online,
- * or when a friend goes online.
- *
- * This callback is not called when adding friends. It is assumed that when
- * adding friends, their connection status is initially offline.
- */
- event connection_status const {
- /**
- * @param friend_number The friend number of the friend whose connection status
- * changed.
- * @param connection_status The result of calling
- * ${connection_status.get} on the passed friend_number.
- */
- typedef void(uint32_t friend_number, CONNECTION connection_status);
- }
-
-
- bool typing {
- /**
- * Check whether a friend is currently typing a message.
- *
- * @param friend_number The friend number for which to query the typing status.
- *
- * @return true if the friend is typing.
- * @return false if the friend is not typing, or the friend number was
- * invalid. Inspect the error code to determine which case it is.
- */
- get(uint32_t friend_number)
- with error for query;
- }
-
-
- /**
- * This event is triggered when a friend starts or stops typing.
- */
- event typing const {
- /**
- * @param friend_number The friend number of the friend who started or stopped
- * typing.
- * @param is_typing The result of calling ${typing.get} on the passed
- * friend_number.
- */
- typedef void(uint32_t friend_number, bool is_typing);
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Sending private messages
- *
- ******************************************************************************/
-
-
-inline namespace self {
-
- bool typing {
- /**
- * Set the client's typing status for a friend.
- *
- * The client is responsible for turning it on or off.
- *
- * @param friend_number The friend to which the client is typing a message.
- * @param typing The typing status. True means the client is typing.
- *
- * @return true on success.
- */
- set(uint32_t friend_number) {
- /**
- * The friend number did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- }
- }
-
-}
-
-
-namespace friend {
-
- namespace send {
-
- /**
- * Send a text chat message to an online friend.
- *
- * This function creates a chat message packet and pushes it into the send
- * queue.
- *
- * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments. Messages may not be empty.
- *
- * The return value of this function is the message ID. If a read receipt is
- * received, the triggered `${event read_receipt}` event will be passed this message ID.
- *
- * Message IDs are unique per friend. The first message ID is 0. Message IDs are
- * incremented by 1 each time a message is sent. If UINT32_MAX messages were
- * sent, the next message ID is 0.
- *
- * @param type Message type (normal, action, ...).
- * @param friend_number The friend number of the friend to send the message to.
- * @param message A non-NULL pointer to the first element of a byte array
- * containing the message text.
- * @param length Length of the message to be sent.
- */
- uint32_t message(uint32_t friend_number, MESSAGE_TYPE type,
- const uint8_t[length <= MAX_MESSAGE_LENGTH] message) {
- NULL,
- /**
- * The friend number did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * An allocation error occurred while increasing the send queue size.
- */
- SENDQ,
- /**
- * Message length exceeded $MAX_MESSAGE_LENGTH.
- */
- TOO_LONG,
- /**
- * Attempted to send a zero-length message.
- */
- EMPTY,
- }
-
- }
-
-
- /**
- * This event is triggered when the friend receives the message sent with
- * ${send.message} with the corresponding message ID.
- */
- event read_receipt const {
- /**
- * @param friend_number The friend number of the friend who received the message.
- * @param message_id The message ID as returned from ${send.message}
- * corresponding to the message sent.
- */
- typedef void(uint32_t friend_number, uint32_t message_id);
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Receiving private messages and friend requests
- *
- ******************************************************************************/
-
-
-namespace friend {
-
- /**
- * This event is triggered when a friend request is received.
- */
- event request const {
- /**
- * @param public_key The Public Key of the user who sent the friend request.
- * @param message The message they sent along with the request.
- * @param length The size of the message byte array.
- */
- typedef void(const uint8_t[PUBLIC_KEY_SIZE] public_key,
- const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
- }
-
-
- /**
- * This event is triggered when a message from a friend is received.
- */
- event message const {
- /**
- * @param friend_number The friend number of the friend who sent the message.
- * @param message The message data they sent.
- * @param length The size of the message byte array.
- */
- typedef void(uint32_t friend_number, MESSAGE_TYPE type,
- const uint8_t[length <= MAX_MESSAGE_LENGTH] message);
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: File transmission: common between sending and receiving
- *
- ******************************************************************************/
-
-
-/**
- * Generates a cryptographic hash of the given data.
- *
- * This function may be used by clients for any purpose, but is provided
- * primarily for validating cached avatars. This use is highly recommended to
- * avoid unnecessary avatar updates.
- *
- * If hash is NULL or data is NULL while length is not 0 the function returns false,
- * otherwise it returns true.
- *
- * This function is a wrapper to internal message-digest functions.
- *
- * @param hash A valid memory location the hash data. It must be at least
- * $HASH_LENGTH bytes in size.
- * @param data Data to be hashed or NULL.
- * @param length Size of the data array or 0.
- *
- * @return true if hash was not NULL.
- */
-static bool hash(uint8_t[HASH_LENGTH] hash, const uint8_t[length] data);
-
-
-namespace file {
-
- enum KIND {
- /**
- * Arbitrary file data. Clients can choose to handle it based on the file name
- * or magic or any other way they choose.
- */
- DATA,
- /**
- * Avatar file_id. This consists of $hash(image).
- * Avatar data. This consists of the image data.
- *
- * Avatars can be sent at any time the client wishes. Generally, a client will
- * send the avatar to a friend when that friend comes online, and to all
- * friends when the avatar changed. A client can save some traffic by
- * remembering which friend received the updated avatar already and only send
- * it if the friend has an out of date avatar.
- *
- * Clients who receive avatar send requests can reject it (by sending
- * ${CONTROL.CANCEL} before any other controls), or accept it (by
- * sending ${CONTROL.RESUME}). The file_id of length $HASH_LENGTH bytes
- * (same length as $FILE_ID_LENGTH) will contain the hash. A client can compare
- * this hash with a saved hash and send ${CONTROL.CANCEL} to terminate the avatar
- * transfer if it matches.
- *
- * When file_size is set to 0 in the transfer request it means that the client
- * has no avatar.
- */
- AVATAR,
- }
-
-
- enum class CONTROL {
- /**
- * Sent by the receiving side to accept a file send request. Also sent after a
- * $PAUSE command to continue sending or receiving.
- */
- RESUME,
- /**
- * Sent by clients to pause the file transfer. The initial state of a file
- * transfer is always paused on the receiving side and running on the sending
- * side. If both the sending and receiving side pause the transfer, then both
- * need to send $RESUME for the transfer to resume.
- */
- PAUSE,
- /**
- * Sent by the receiving side to reject a file send request before any other
- * commands are sent. Also sent by either side to terminate a file transfer.
- */
- CANCEL,
- }
-
-
- /**
- * Sends a file control command to a friend for a given file transfer.
- *
- * @param friend_number The friend number of the friend the file is being
- * transferred to or received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param control The control command to send.
- *
- * @return true on success.
- */
- bool control(uint32_t friend_number, uint32_t file_number, CONTROL control) {
- /**
- * The friend_number passed did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- NOT_FOUND,
- /**
- * A RESUME control was sent, but the file transfer is running normally.
- */
- NOT_PAUSED,
- /**
- * A RESUME control was sent, but the file transfer was paused by the other
- * party. Only the party that paused the transfer can resume it.
- */
- DENIED,
- /**
- * A PAUSE control was sent, but the file transfer was already paused.
- */
- ALREADY_PAUSED,
- /**
- * Packet queue is full.
- */
- SENDQ,
- }
-
-
- /**
- * This event is triggered when a file control command is received from a
- * friend.
- */
- event recv_control const {
- /**
- * When receiving ${CONTROL.CANCEL}, the client should release the
- * resources associated with the file number and consider the transfer failed.
- *
- * @param friend_number The friend number of the friend who is sending the file.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param control The file control command received.
- */
- typedef void(uint32_t friend_number, uint32_t file_number, CONTROL control);
- }
-
- /**
- * Sends a file seek control command to a friend for a given file transfer.
- *
- * This function can only be called to resume a file transfer right before
- * ${CONTROL.RESUME} is sent.
- *
- * @param friend_number The friend number of the friend the file is being
- * received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param position The position that the file should be seeked to.
- */
- bool seek(uint32_t friend_number, uint32_t file_number, uint64_t position) {
- /**
- * The friend_number passed did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- NOT_FOUND,
- /**
- * File was not in a state where it could be seeked.
- */
- DENIED,
- /**
- * Seek position was invalid
- */
- INVALID_POSITION,
- /**
- * Packet queue is full.
- */
- SENDQ,
- }
-
-
- error for get {
- NULL,
- /**
- * The friend_number passed did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- NOT_FOUND,
- }
-
- uint8_t[FILE_ID_LENGTH] file_id {
- /**
- * Copy the file id associated to the file transfer to a byte array.
- *
- * @param friend_number The friend number of the friend the file is being
- * transferred to or received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param file_id A memory region of at least $FILE_ID_LENGTH bytes. If
- * this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
- get(uint32_t friend_number, uint32_t file_number)
- with error for get;
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: File transmission: sending
- *
- ******************************************************************************/
-
-
-namespace file {
-
- /**
- * Send a file transmission request.
- *
- * Maximum filename length is $MAX_FILENAME_LENGTH bytes. The filename
- * should generally just be a file name, not a path with directory names.
- *
- * If a non-UINT64_MAX file size is provided, it can be used by both sides to
- * determine the sending progress. File size can be set to UINT64_MAX for streaming
- * data of unknown size.
- *
- * File transmission occurs in chunks, which are requested through the
- * `${event chunk_request}` event.
- *
- * When a friend goes offline, all file transfers associated with the friend are
- * purged from core.
- *
- * If the file contents change during a transfer, the behaviour is unspecified
- * in general. What will actually happen depends on the mode in which the file
- * was modified and how the client determines the file size.
- *
- * - If the file size was increased
- * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour
- * will be as expected.
- * - and sending mode was file (file_size != UINT64_MAX), the
- * ${event chunk_request} callback will receive length = 0 when Core thinks
- * the file transfer has finished. If the client remembers the file size as
- * it was when sending the request, it will terminate the transfer normally.
- * If the client re-reads the size, it will think the friend cancelled the
- * transfer.
- * - If the file size was decreased
- * - and sending mode was streaming, the behaviour is as expected.
- * - and sending mode was file, the callback will return 0 at the new
- * (earlier) end-of-file, signalling to the friend that the transfer was
- * cancelled.
- * - If the file contents were modified
- * - at a position before the current read, the two files (local and remote)
- * will differ after the transfer terminates.
- * - at a position after the current read, the file transfer will succeed as
- * expected.
- * - In either case, both sides will regard the transfer as complete and
- * successful.
- *
- * @param friend_number The friend number of the friend the file send request
- * should be sent to.
- * @param kind The meaning of the file to be sent.
- * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
- * unknown or streaming.
- * @param file_id A file identifier of length $FILE_ID_LENGTH that can be used to
- * uniquely identify file transfers across core restarts. If NULL, a random one will
- * be generated by core. It can then be obtained by using ${file_id.get}().
- * @param filename Name of the file. Does not need to be the actual name. This
- * name will be sent along with the file send request.
- * @param filename_length Size in bytes of the filename.
- *
- * @return A file number used as an identifier in subsequent callbacks. This
- * number is per friend. File numbers are reused after a transfer terminates.
- * On failure, this function returns UINT32_MAX. Any pattern in file numbers
- * should not be relied on.
- */
- uint32_t send(uint32_t friend_number, uint32_t kind, uint64_t file_size,
- const uint8_t[FILE_ID_LENGTH] file_id,
- const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename) {
- NULL,
- /**
- * The friend_number passed did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * Filename length exceeded $MAX_FILENAME_LENGTH bytes.
- */
- NAME_TOO_LONG,
- /**
- * Too many ongoing transfers. The maximum number of concurrent file transfers
- * is 256 per friend per direction (sending and receiving).
- */
- TOO_MANY,
- }
-
-
- /**
- * Send a chunk of file data to a friend.
- *
- * This function is called in response to the `${event chunk_request}` callback. The
- * length parameter should be equal to the one received though the callback.
- * If it is zero, the transfer is assumed complete. For files with known size,
- * Core will know that the transfer is complete after the last byte has been
- * received, so it is not necessary (though not harmful) to send a zero-length
- * chunk to terminate. For streams, core will know that the transfer is finished
- * if a chunk with length less than the length requested in the callback is sent.
- *
- * @param friend_number The friend number of the receiving friend for this file.
- * @param file_number The file transfer identifier returned by tox_file_send.
- * @param position The file or stream position from which to continue reading.
- * @return true on success.
- */
- bool send_chunk(uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t[length] data) {
- /**
- * The length parameter was non-zero, but data was NULL.
- */
- NULL,
- /**
- * The friend_number passed did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- NOT_FOUND,
- /**
- * File transfer was found but isn't in a transferring state: (paused, done,
- * broken, etc...) (happens only when not called from the request chunk callback).
- */
- NOT_TRANSFERRING,
- /**
- * Attempted to send more or less data than requested. The requested data size is
- * adjusted according to maximum transmission unit and the expected end of
- * the file. Trying to send less or more than requested will return this error.
- */
- INVALID_LENGTH,
- /**
- * Packet queue is full.
- */
- SENDQ,
- /**
- * Position parameter was wrong.
- */
- WRONG_POSITION,
- }
-
-
- /**
- * This event is triggered when Core is ready to send more file data.
- */
- event chunk_request const {
- /**
- * If the length parameter is 0, the file transfer is finished, and the client's
- * resources associated with the file number should be released. After a call
- * with zero length, the file number can be reused for future file transfers.
- *
- * If the requested position is not equal to the client's idea of the current
- * file or stream position, it will need to seek. In case of read-once streams,
- * the client should keep the last read chunk so that a seek back can be
- * supported. A seek-back only ever needs to read from the last requested chunk.
- * This happens when a chunk was requested, but the send failed. A seek-back
- * request can occur an arbitrary number of times for any given chunk.
- *
- * In response to receiving this callback, the client should call the function
- * `$send_chunk` with the requested chunk. If the number of bytes sent
- * through that function is zero, the file transfer is assumed complete. A
- * client must send the full length of data requested with this callback.
- *
- * @param friend_number The friend number of the receiving friend for this file.
- * @param file_number The file transfer identifier returned by $send.
- * @param position The file or stream position from which to continue reading.
- * @param length The number of bytes requested for the current chunk.
- */
- typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position, size_t length);
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: File transmission: receiving
- *
- ******************************************************************************/
-
-
-namespace file {
-
- /**
- * This event is triggered when a file transfer request is received.
- */
- event recv const {
- /**
- * The client should acquire resources to be associated with the file transfer.
- * Incoming file transfers start in the PAUSED state. After this callback
- * returns, a transfer can be rejected by sending a ${CONTROL.CANCEL}
- * control command before any other control commands. It can be accepted by
- * sending ${CONTROL.RESUME}.
- *
- * @param friend_number The friend number of the friend who is sending the file
- * transfer request.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param kind The meaning of the file to be sent.
- * @param file_size Size in bytes of the file the client wants to send,
- * UINT64_MAX if unknown or streaming.
- * @param filename Name of the file. Does not need to be the actual name. This
- * name will be sent along with the file send request.
- * @param filename_length Size in bytes of the filename.
- */
- typedef void(uint32_t friend_number, uint32_t file_number, uint32_t kind,
- uint64_t file_size, const uint8_t[filename_length <= MAX_FILENAME_LENGTH] filename);
- }
-
-
- /**
- * This event is first triggered when a file transfer request is received, and
- * subsequently when a chunk of file data for an accepted request was received.
- */
- event recv_chunk const {
- /**
- * When length is 0, the transfer is finished and the client should release the
- * resources it acquired for the transfer. After a call with length = 0, the
- * file number can be reused for new file transfers.
- *
- * If position is equal to file_size (received in the file_receive callback)
- * when the transfer finishes, the file was received completely. Otherwise, if
- * file_size was UINT64_MAX, streaming ended successfully when length is 0.
- *
- * @param friend_number The friend number of the friend who is sending the file.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param position The file position of the first byte in data.
- * @param data A byte array containing the received chunk.
- * @param length The length of the received chunk.
- */
- typedef void(uint32_t friend_number, uint32_t file_number, uint64_t position,
- const uint8_t[length] data);
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Conference management
- *
- ******************************************************************************/
-
-namespace conference {
-
- /**
- * Conference types for the ${event invite} event.
- */
- enum class TYPE {
- /**
- * Text-only conferences that must be accepted with the $join function.
- */
- TEXT,
- /**
- * Video conference. The function to accept these is in toxav.
- */
- AV,
- }
-
-
- /**
- * This event is triggered when the client is invited to join a conference.
- */
- event invite const {
- /**
- * The invitation will remain valid until the inviting friend goes offline
- * or exits the conference.
- *
- * @param friend_number The friend who invited us.
- * @param type The conference type (text only or audio/video).
- * @param cookie A piece of data of variable length required to join the
- * conference.
- * @param length The length of the cookie.
- */
- typedef void(uint32_t friend_number, TYPE type, const uint8_t[length] cookie);
- }
-
-
- /**
- * This event is triggered when the client receives a conference message.
- */
- event message const {
- /**
- * @param conference_number The conference number of the conference the message is intended for.
- * @param peer_number The ID of the peer who sent the message.
- * @param type The type of message (normal, action, ...).
- * @param message The message data.
- * @param length The length of the message.
- */
- typedef void(uint32_t conference_number, uint32_t peer_number, MESSAGE_TYPE type,
- const uint8_t[length] message);
- }
-
-
- /**
- * This event is triggered when a peer changes the conference title.
- *
- * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
- */
- event title const {
- /**
- * @param conference_number The conference number of the conference the title change is intended for.
- * @param peer_number The ID of the peer who changed the title.
- * @param title The title data.
- * @param length The title length.
- */
- typedef void(uint32_t conference_number, uint32_t peer_number, const uint8_t[length] title);
- }
-
- /**
- * Peer list state change types.
- */
- enum class STATE_CHANGE {
- /**
- * A peer has joined the conference.
- */
- PEER_JOIN,
- /**
- * A peer has exited the conference.
- */
- PEER_EXIT,
- /**
- * A peer has changed their name.
- */
- PEER_NAME_CHANGE,
- }
-
- /**
- * This event is triggered when the peer list changes (name change, peer join, peer exit).
- */
- event namelist_change const {
- /**
- * @param conference_number The conference number of the conference the title change is intended for.
- * @param peer_number The ID of the peer who changed the title.
- * @param change The type of change (one of $STATE_CHANGE).
- */
- typedef void(uint32_t conference_number, uint32_t peer_number, STATE_CHANGE change);
- }
-
-
- /**
- * Creates a new conference.
- *
- * This function creates a new text conference.
- *
- * @return conference number on success, or UINT32_MAX on failure.
- */
- uint32_t new() {
- /**
- * The conference instance failed to initialize.
- */
- INIT,
- }
-
- /**
- * This function deletes a conference.
- *
- * @param conference_number The conference number of the conference to be deleted.
- *
- * @return true on success.
- */
- bool delete(uint32_t conference_number) {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- }
-
-
- namespace peer {
-
- /**
- * Error codes for peer info queries.
- */
- error for query {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- /**
- * The peer number passed did not designate a valid peer.
- */
- PEER_NOT_FOUND,
- /**
- * The client is not connected to the conference.
- */
- NO_CONNECTION,
- }
-
- /**
- * Return the number of peers in the conference. Return value is unspecified on failure.
- */
- const uint32_t count(uint32_t conference_number)
- with error for query;
-
- uint8_t[size] name {
-
- /**
- * Return the length of the peer's name. Return value is unspecified on failure.
- */
- size(uint32_t conference_number, uint32_t peer_number)
- with error for query;
-
- /**
- * Copy the name of peer_number who is in conference_number to name.
- * name must be at least $MAX_NAME_LENGTH long.
- *
- * @return true on success.
- */
- get(uint32_t conference_number, uint32_t peer_number)
- with error for query;
- }
-
- /**
- * Copy the public key of peer_number who is in conference_number to public_key.
- * public_key must be $PUBLIC_KEY_SIZE long.
- *
- * @return true on success.
- */
- uint8_t[PUBLIC_KEY_SIZE] public_key {
- get(uint32_t conference_number, uint32_t peer_number)
- with error for query;
- }
-
- /**
- * Return true if passed peer_number corresponds to our own.
- */
- const bool number_is_ours(uint32_t conference_number, uint32_t peer_number)
- with error for query;
-
- }
-
-
- /**
- * Invites a friend to a conference.
- *
- * @param friend_number The friend number of the friend we want to invite.
- * @param conference_number The conference number of the conference we want to invite the friend to.
- *
- * @return true on success.
- */
- bool invite(uint32_t friend_number, uint32_t conference_number) {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- /**
- * The invite packet failed to send.
- */
- FAIL_SEND,
- }
-
-
- /**
- * Joins a conference that the client has been invited to.
- *
- * @param friend_number The friend number of the friend who sent the invite.
- * @param cookie Received via the `${event invite}` event.
- * @param length The size of cookie.
- *
- * @return conference number on success, UINT32_MAX on failure.
- */
- uint32_t join(uint32_t friend_number, const uint8_t[length] cookie) {
- /**
- * The cookie passed has an invalid length.
- */
- INVALID_LENGTH,
- /**
- * The conference is not the expected type. This indicates an invalid cookie.
- */
- WRONG_TYPE,
- /**
- * The friend number passed does not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * Client is already in this conference.
- */
- DUPLICATE,
- /**
- * Conference instance failed to initialize.
- */
- INIT_FAIL,
- /**
- * The join packet failed to send.
- */
- FAIL_SEND,
- }
-
-
- namespace send {
-
- /**
- * Send a text chat message to the conference.
- *
- * This function creates a conference message packet and pushes it into the send
- * queue.
- *
- * The message length may not exceed $MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments.
- *
- * @param conference_number The conference number of the conference the message is intended for.
- * @param type Message type (normal, action, ...).
- * @param message A non-NULL pointer to the first element of a byte array
- * containing the message text.
- * @param length Length of the message to be sent.
- *
- * @return true on success.
- */
- bool message(uint32_t conference_number, MESSAGE_TYPE type, const uint8_t[length] message) {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- /**
- * The message is too long.
- */
- TOO_LONG,
- /**
- * The client is not connected to the conference.
- */
- NO_CONNECTION,
- /**
- * The message packet failed to send.
- */
- FAIL_SEND,
- }
- }
-
- error for title {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- /**
- * The title is too long or empty.
- */
- INVALID_LENGTH,
- /**
- * The title packet failed to send.
- */
- FAIL_SEND,
- }
-
- uint8_t[length <= MAX_NAME_LENGTH] title {
-
- /**
- * Return the length of the conference title. Return value is unspecified on failure.
- *
- * The return value is equal to the `length` argument received by the last
- * `${event title}` callback.
- */
- size(uint32_t conference_number)
- with error for title;
-
- /**
- * Write the title designated by the given conference number to a byte array.
- *
- * Call $size to determine the allocation size for the `title` parameter.
- *
- * The data written to `title` is equal to the data received by the last
- * `${event title}` callback.
- *
- * @param title A valid memory region large enough to store the title.
- * If this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
- get(uint32_t conference_number)
- with error for title;
-
- /**
- * Set the conference title and broadcast it to the rest of the conference.
- *
- * Title length cannot be longer than $MAX_NAME_LENGTH.
- *
- * @return true on success.
- */
- set(uint32_t conference_number)
- with error for title;
- }
-
-
- uint32_t[size] chatlist {
- /**
- * Return the number of conferences in the Tox instance.
- * This should be used to determine how much memory to allocate for `$get`.
- */
- size();
-
- /**
- * Copy a list of valid conference IDs into the array chatlist. Determine how much space
- * to allocate for the array with the `$size` function.
- */
- get();
- }
-
-
- /**
- * Returns the type of conference ($TYPE) that conference_number is. Return value is
- * unspecified on failure.
- */
- TYPE type {
- get(uint32_t conference_number) {
- /**
- * The conference number passed did not designate a valid conference.
- */
- CONFERENCE_NOT_FOUND,
- }
- }
-
-}
-
-
-/*******************************************************************************
- *
- * :: Low-level custom packet sending and receiving
- *
- ******************************************************************************/
-
-
-namespace friend {
-
- inline namespace send {
-
- error for custom_packet {
- NULL,
- /**
- * The friend number did not designate a valid friend.
- */
- FRIEND_NOT_FOUND,
- /**
- * This client is currently not connected to the friend.
- */
- FRIEND_NOT_CONNECTED,
- /**
- * The first byte of data was not in the specified range for the packet type.
- * This range is 200-254 for lossy, and 160-191 for lossless packets.
- */
- INVALID,
- /**
- * Attempted to send an empty packet.
- */
- EMPTY,
- /**
- * Packet data length exceeded $MAX_CUSTOM_PACKET_SIZE.
- */
- TOO_LONG,
- /**
- * Packet queue is full.
- */
- SENDQ,
- }
-
- /**
- * Send a custom lossy packet to a friend.
- *
- * The first byte of data must be in the range 200-254. Maximum length of a
- * custom packet is $MAX_CUSTOM_PACKET_SIZE.
- *
- * Lossy packets behave like UDP packets, meaning they might never reach the
- * other side or might arrive more than once (if someone is messing with the
- * connection) or might arrive in the wrong order.
- *
- * Unless latency is an issue, it is recommended that you use lossless custom
- * packets instead.
- *
- * @param friend_number The friend number of the friend this lossy packet
- * should be sent to.
- * @param data A byte array containing the packet data.
- * @param length The length of the packet data byte array.
- *
- * @return true on success.
- */
- bool lossy_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
- with error for custom_packet;
-
-
- /**
- * Send a custom lossless packet to a friend.
- *
- * The first byte of data must be in the range 160-191. Maximum length of a
- * custom packet is $MAX_CUSTOM_PACKET_SIZE.
- *
- * Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
- * but with packets instead of a stream.
- *
- * @param friend_number The friend number of the friend this lossless packet
- * should be sent to.
- * @param data A byte array containing the packet data.
- * @param length The length of the packet data byte array.
- *
- * @return true on success.
- */
- bool lossless_packet(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data)
- with error for custom_packet;
-
- }
-
-
- event lossy_packet const {
- /**
- * @param friend_number The friend number of the friend who sent a lossy packet.
- * @param data A byte array containing the received packet data.
- * @param length The length of the packet data byte array.
- */
- typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
- }
-
-
- event lossless_packet const {
- /**
- * @param friend_number The friend number of the friend who sent the packet.
- * @param data A byte array containing the received packet data.
- * @param length The length of the packet data byte array.
- */
- typedef void(uint32_t friend_number, const uint8_t[length <= MAX_CUSTOM_PACKET_SIZE] data);
- }
-
-}
-
-
-
-/*******************************************************************************
- *
- * :: Low-level network information
- *
- ******************************************************************************/
-
-
-inline namespace self {
-
- uint8_t[PUBLIC_KEY_SIZE] dht_id {
- /**
- * Writes the temporary DHT public key of this instance to a byte array.
- *
- * This can be used in combination with an externally accessible IP address and
- * the bound port (from ${udp_port.get}) to run a temporary bootstrap node.
- *
- * Be aware that every time a new instance is created, the DHT public key
- * changes, meaning this cannot be used to run a permanent bootstrap node.
- *
- * @param dht_id A memory region of at least $PUBLIC_KEY_SIZE bytes. If this
- * parameter is NULL, this function has no effect.
- */
- get();
- }
-
-
- error for get_port {
- /**
- * The instance was not bound to any port.
- */
- NOT_BOUND,
- }
-
-
- uint16_t udp_port {
- /**
- * Return the UDP port this Tox instance is bound to.
- */
- get() with error for get_port;
- }
-
-
- uint16_t tcp_port {
- /**
- * Return the TCP port this Tox instance is bound to. This is only relevant if
- * the instance is acting as a TCP relay.
- */
- get() with error for get_port;
- }
-
-}
-
-} // class tox
-
-%{
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-%}
diff --git a/libs/libtox/src/toxcore/tox.c b/libs/libtox/src/toxcore/tox.c
deleted file mode 100644
index 12f3762083..0000000000
--- a/libs/libtox/src/toxcore/tox.c
+++ /dev/null
@@ -1,1551 +0,0 @@
-/*
- * The Tox public API.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _XOPEN_SOURCE 600
-
-#define TOX_DEFINED
-typedef struct Messenger Tox;
-#include "tox.h"
-
-#include "Messenger.h"
-#include "group.h"
-#include "logger.h"
-
-#include "../toxencryptsave/defines.h"
-
-#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
-
-#if TOX_HASH_LENGTH != CRYPTO_SHA256_SIZE
-#error TOX_HASH_LENGTH is assumed to be equal to CRYPTO_SHA256_SIZE
-#endif
-
-#if FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
-#error FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
-#endif
-
-#if TOX_FILE_ID_LENGTH != CRYPTO_SYMMETRIC_KEY_SIZE
-#error TOX_FILE_ID_LENGTH is assumed to be equal to CRYPTO_SYMMETRIC_KEY_SIZE
-#endif
-
-#if TOX_FILE_ID_LENGTH != TOX_HASH_LENGTH
-#error TOX_FILE_ID_LENGTH is assumed to be equal to TOX_HASH_LENGTH
-#endif
-
-#if TOX_PUBLIC_KEY_SIZE != CRYPTO_PUBLIC_KEY_SIZE
-#error TOX_PUBLIC_KEY_SIZE is assumed to be equal to CRYPTO_PUBLIC_KEY_SIZE
-#endif
-
-#if TOX_SECRET_KEY_SIZE != CRYPTO_SECRET_KEY_SIZE
-#error TOX_SECRET_KEY_SIZE is assumed to be equal to CRYPTO_SECRET_KEY_SIZE
-#endif
-
-#if TOX_MAX_NAME_LENGTH != MAX_NAME_LENGTH
-#error TOX_MAX_NAME_LENGTH is assumed to be equal to MAX_NAME_LENGTH
-#endif
-
-#if TOX_MAX_STATUS_MESSAGE_LENGTH != MAX_STATUSMESSAGE_LENGTH
-#error TOX_MAX_STATUS_MESSAGE_LENGTH is assumed to be equal to MAX_STATUSMESSAGE_LENGTH
-#endif
-
-
-bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
-{
- return TOX_VERSION_IS_API_COMPATIBLE(major, minor, patch);
-}
-
-
-Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error)
-{
- Messenger_Options m_options = {0};
-
- bool load_savedata_sk = 0, load_savedata_tox = 0;
-
- if (options == NULL) {
- m_options.ipv6enabled = TOX_ENABLE_IPV6_DEFAULT;
- } else {
- if (tox_options_get_savedata_type(options) != TOX_SAVEDATA_TYPE_NONE) {
- if (tox_options_get_savedata_data(options) == NULL || tox_options_get_savedata_length(options) == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
- return NULL;
- }
- }
-
- if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_SECRET_KEY) {
- if (tox_options_get_savedata_length(options) != TOX_SECRET_KEY_SIZE) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
- return NULL;
- }
-
- load_savedata_sk = 1;
- } else if (tox_options_get_savedata_type(options) == TOX_SAVEDATA_TYPE_TOX_SAVE) {
- if (tox_options_get_savedata_length(options) < TOX_ENC_SAVE_MAGIC_LENGTH) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
- return NULL;
- }
-
- if (crypto_memcmp(tox_options_get_savedata_data(options), TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_ENCRYPTED);
- return NULL;
- }
-
- load_savedata_tox = 1;
- }
-
- m_options.ipv6enabled = tox_options_get_ipv6_enabled(options);
- m_options.udp_disabled = !tox_options_get_udp_enabled(options);
- m_options.port_range[0] = tox_options_get_start_port(options);
- m_options.port_range[1] = tox_options_get_end_port(options);
- m_options.tcp_server_port = tox_options_get_tcp_port(options);
- m_options.hole_punching_enabled = tox_options_get_hole_punching_enabled(options);
- m_options.local_discovery_enabled = tox_options_get_local_discovery_enabled(options);
-
- m_options.log_callback = (logger_cb *)tox_options_get_log_callback(options);
- m_options.log_user_data = tox_options_get_log_user_data(options);
-
- switch (tox_options_get_proxy_type(options)) {
- case TOX_PROXY_TYPE_HTTP:
- m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
- break;
-
- case TOX_PROXY_TYPE_SOCKS5:
- m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5;
- break;
-
- case TOX_PROXY_TYPE_NONE:
- m_options.proxy_info.proxy_type = TCP_PROXY_NONE;
- break;
-
- default:
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_TYPE);
- return NULL;
- }
-
- if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
- if (tox_options_get_proxy_port(options) == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_PORT);
- return NULL;
- }
-
- ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
-
- if (m_options.ipv6enabled) {
- m_options.proxy_info.ip_port.ip.family = TOX_AF_UNSPEC;
- }
-
- if (!addr_resolve_or_parse_ip(tox_options_get_proxy_host(options), &m_options.proxy_info.ip_port.ip, NULL)) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
- // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
- return NULL;
- }
-
- m_options.proxy_info.ip_port.port = net_htons(tox_options_get_proxy_port(options));
- }
- }
-
- unsigned int m_error;
- Messenger *m = new_messenger(&m_options, &m_error);
-
- if (!new_groupchats(m)) {
- kill_messenger(m);
-
- if (m_error == MESSENGER_ERROR_PORT) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
- } else if (m_error == MESSENGER_ERROR_TCP_SERVER) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PORT_ALLOC);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_MALLOC);
- }
-
- return NULL;
- }
-
- if (load_savedata_tox
- && messenger_load(m, tox_options_get_savedata_data(options), tox_options_get_savedata_length(options)) == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_BAD_FORMAT);
- } else if (load_savedata_sk) {
- load_secret_key(m->net_crypto, tox_options_get_savedata_data(options));
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_NEW_OK);
- }
-
- return m;
-}
-
-void tox_kill(Tox *tox)
-{
- if (tox == NULL) {
- return;
- }
-
- Messenger *m = tox;
- kill_groupchats((Group_Chats *)m->conferences_object);
- kill_messenger(m);
-}
-
-size_t tox_get_savedata_size(const Tox *tox)
-{
- const Messenger *m = tox;
- return messenger_size(m);
-}
-
-void tox_get_savedata(const Tox *tox, uint8_t *savedata)
-{
- if (savedata) {
- const Messenger *m = tox;
- messenger_save(m, savedata);
- }
-}
-
-bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error)
-{
- if (!address || !public_key) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
- return 0;
- }
-
- if (port == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
- return 0;
- }
-
- IP_Port *root;
-
- int32_t count = net_getipport(address, &root, TOX_SOCK_DGRAM);
-
- if (count == -1) {
- net_freeipport(root);
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
- return 0;
- }
-
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- root[i].port = net_htons(port);
-
- Messenger *m = tox;
- onion_add_bs_path_node(m->onion_c, root[i], public_key);
- DHT_bootstrap(m->dht, root[i], public_key);
- }
-
- net_freeipport(root);
-
- if (count) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
- return 1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
- return 0;
-}
-
-bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key,
- TOX_ERR_BOOTSTRAP *error)
-{
- if (!address || !public_key) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_NULL);
- return 0;
- }
-
- if (port == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_PORT);
- return 0;
- }
-
- IP_Port *root;
-
- int32_t count = net_getipport(address, &root, TOX_SOCK_STREAM);
-
- if (count == -1) {
- net_freeipport(root);
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
- return 0;
- }
-
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- root[i].port = net_htons(port);
-
- Messenger *m = tox;
- add_tcp_relay(m->net_crypto, root[i], public_key);
- }
-
- net_freeipport(root);
-
- if (count) {
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_OK);
- return 1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_BOOTSTRAP_BAD_HOST);
- return 0;
-}
-
-TOX_CONNECTION tox_self_get_connection_status(const Tox *tox)
-{
- const Messenger *m = tox;
-
- unsigned int ret = onion_connection_status(m->onion_c);
-
- if (ret == 2) {
- return TOX_CONNECTION_UDP;
- }
-
- if (ret == 1) {
- return TOX_CONNECTION_TCP;
- }
-
- return TOX_CONNECTION_NONE;
-}
-
-
-void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback)
-{
- Messenger *m = tox;
- m_callback_core_connection(m, (void (*)(Messenger *, unsigned int, void *))callback);
-}
-
-uint32_t tox_iteration_interval(const Tox *tox)
-{
- const Messenger *m = tox;
- return messenger_run_interval(m);
-}
-
-void tox_iterate(Tox *tox, void *user_data)
-{
- Messenger *m = tox;
- do_messenger(m, user_data);
- do_groupchats((Group_Chats *)m->conferences_object, user_data);
-}
-
-void tox_self_get_address(const Tox *tox, uint8_t *address)
-{
- if (address) {
- const Messenger *m = tox;
- getaddress(m, address);
- }
-}
-
-void tox_self_set_nospam(Tox *tox, uint32_t nospam)
-{
- Messenger *m = tox;
- set_nospam(&(m->fr), net_htonl(nospam));
-}
-
-uint32_t tox_self_get_nospam(const Tox *tox)
-{
- const Messenger *m = tox;
- return net_ntohl(get_nospam(&(m->fr)));
-}
-
-void tox_self_get_public_key(const Tox *tox, uint8_t *public_key)
-{
- const Messenger *m = tox;
-
- if (public_key) {
- memcpy(public_key, m->net_crypto->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- }
-}
-
-void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key)
-{
- const Messenger *m = tox;
-
- if (secret_key) {
- memcpy(secret_key, m->net_crypto->self_secret_key, CRYPTO_SECRET_KEY_SIZE);
- }
-}
-
-bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error)
-{
- if (!name && length != 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
- return 0;
- }
-
- Messenger *m = tox;
-
- if (setname(m, name, length) == 0) {
- // TODO(irungentoo): function to set different per group names?
- send_name_all_groups((Group_Chats *)m->conferences_object);
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
- return 1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
- return 0;
-}
-
-size_t tox_self_get_name_size(const Tox *tox)
-{
- const Messenger *m = tox;
- return m_get_self_name_size(m);
-}
-
-void tox_self_get_name(const Tox *tox, uint8_t *name)
-{
- if (name) {
- const Messenger *m = tox;
- getself_name(m, name);
- }
-}
-
-bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, TOX_ERR_SET_INFO *error)
-{
- if (!status_message && length != 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_NULL);
- return 0;
- }
-
- Messenger *m = tox;
-
- if (m_set_statusmessage(m, status_message, length) == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_OK);
- return 1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_INFO_TOO_LONG);
- return 0;
-}
-
-size_t tox_self_get_status_message_size(const Tox *tox)
-{
- const Messenger *m = tox;
- return m_get_self_statusmessage_size(m);
-}
-
-void tox_self_get_status_message(const Tox *tox, uint8_t *status_message)
-{
- if (status_message) {
- const Messenger *m = tox;
- m_copy_self_statusmessage(m, status_message);
- }
-}
-
-void tox_self_set_status(Tox *tox, TOX_USER_STATUS status)
-{
- Messenger *m = tox;
- m_set_userstatus(m, status);
-}
-
-TOX_USER_STATUS tox_self_get_status(const Tox *tox)
-{
- const Messenger *m = tox;
- return (TOX_USER_STATUS)m_get_self_userstatus(m);
-}
-
-static void set_friend_error(int32_t ret, TOX_ERR_FRIEND_ADD *error)
-{
- switch (ret) {
- case FAERR_TOOLONG:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_TOO_LONG);
- break;
-
- case FAERR_NOMESSAGE:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE);
- break;
-
- case FAERR_OWNKEY:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OWN_KEY);
- break;
-
- case FAERR_ALREADYSENT:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT);
- break;
-
- case FAERR_BADCHECKSUM:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM);
- break;
-
- case FAERR_SETNEWNOSPAM:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM);
- break;
-
- case FAERR_NOMEM:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_MALLOC);
- break;
- }
-}
-
-uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
- TOX_ERR_FRIEND_ADD *error)
-{
- if (!address || !message) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
- return UINT32_MAX;
- }
-
- Messenger *m = tox;
- int32_t ret = m_addfriend(m, address, message, length);
-
- if (ret >= 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
- return ret;
- }
-
- set_friend_error(ret, error);
- return UINT32_MAX;
-}
-
-uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error)
-{
- if (!public_key) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_NULL);
- return UINT32_MAX;
- }
-
- Messenger *m = tox;
- int32_t ret = m_addfriend_norequest(m, public_key);
-
- if (ret >= 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_ADD_OK);
- return ret;
- }
-
- set_friend_error(ret, error);
- return UINT32_MAX;
-}
-
-bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error)
-{
- Messenger *m = tox;
- int ret = m_delfriend(m, friend_number);
-
- // TODO(irungentoo): handle if realloc fails?
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_DELETE_OK);
- return 1;
-}
-
-uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error)
-{
- if (!public_key) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL);
- return UINT32_MAX;
- }
-
- const Messenger *m = tox;
- int32_t ret = getfriend_id(m, public_key);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND);
- return UINT32_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK);
- return ret;
-}
-
-bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
- TOX_ERR_FRIEND_GET_PUBLIC_KEY *error)
-{
- if (!public_key) {
- return 0;
- }
-
- const Messenger *m = tox;
-
- if (get_real_pk(m, friend_number, public_key) == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK);
- return 1;
-}
-
-bool tox_friend_exists(const Tox *tox, uint32_t friend_number)
-{
- const Messenger *m = tox;
- return m_friend_exists(m, friend_number);
-}
-
-uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error)
-{
- const Messenger *m = tox;
- uint64_t timestamp = m_get_last_online(m, friend_number);
-
- if (timestamp == UINT64_MAX) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND)
- return UINT64_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_GET_LAST_ONLINE_OK);
- return timestamp;
-}
-
-size_t tox_self_get_friend_list_size(const Tox *tox)
-{
- const Messenger *m = tox;
- return count_friendlist(m);
-}
-
-void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list)
-{
- if (friend_list) {
- const Messenger *m = tox;
- // TODO(irungentoo): size parameter?
- copy_friendlist(m, friend_list, tox_self_get_friend_list_size(tox));
- }
-}
-
-size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = m_get_name_size(m, friend_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return SIZE_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return ret;
-}
-
-bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error)
-{
- if (!name) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
- return 0;
- }
-
- const Messenger *m = tox;
- int ret = getname(m, friend_number, name);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return 1;
-}
-
-void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback)
-{
- Messenger *m = tox;
- m_callback_namechange(m, callback);
-}
-
-size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = m_get_statusmessage_size(m, friend_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return SIZE_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return ret;
-}
-
-bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
- TOX_ERR_FRIEND_QUERY *error)
-{
- if (!status_message) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_NULL);
- return 0;
- }
-
- const Messenger *m = tox;
- // TODO(irungentoo): size parameter?
- int ret = m_copy_statusmessage(m, friend_number, status_message, m_get_statusmessage_size(m, friend_number));
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return 1;
-}
-
-void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback)
-{
- Messenger *m = tox;
- m_callback_statusmessage(m, callback);
-}
-
-TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- const Messenger *m = tox;
-
- int ret = m_get_userstatus(m, friend_number);
-
- if (ret == USERSTATUS_INVALID) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return (TOX_USER_STATUS)(TOX_USER_STATUS_BUSY + 1);
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return (TOX_USER_STATUS)ret;
-}
-
-void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback)
-{
- Messenger *m = tox;
- m_callback_userstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
-}
-
-TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- const Messenger *m = tox;
-
- int ret = m_get_friend_connectionstatus(m, friend_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return TOX_CONNECTION_NONE;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return (TOX_CONNECTION)ret;
-}
-
-void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback)
-{
- Messenger *m = tox;
- m_callback_connectionstatus(m, (void (*)(Messenger *, uint32_t, unsigned int, void *))callback);
-}
-
-bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = m_get_istyping(m, friend_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_QUERY_OK);
- return !!ret;
-}
-
-void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback)
-{
- Messenger *m = tox;
- m_callback_typingchange(m, callback);
-}
-
-bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, TOX_ERR_SET_TYPING *error)
-{
- Messenger *m = tox;
-
- if (m_set_usertyping(m, friend_number, typing) == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_SET_TYPING_OK);
- return 1;
-}
-
-static void set_message_error(int ret, TOX_ERR_FRIEND_SEND_MESSAGE *error)
-{
- switch (ret) {
- case 0:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_OK);
- break;
-
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND);
- break;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG);
- break;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED);
- break;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ);
- break;
-
- case -5:
- /* can't happen */
- break;
- }
-}
-
-uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
- size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error)
-{
- if (!message) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_NULL);
- return 0;
- }
-
- if (!length) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY);
- return 0;
- }
-
- Messenger *m = tox;
- uint32_t message_id = 0;
- set_message_error(m_send_message_generic(m, friend_number, type, message, length, &message_id), error);
- return message_id;
-}
-
-void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback)
-{
- Messenger *m = tox;
- m_callback_read_receipt(m, callback);
-}
-
-void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback)
-{
- Messenger *m = tox;
- m_callback_friendrequest(m, callback);
-}
-
-void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback)
-{
- Messenger *m = tox;
- m_callback_friendmessage(m, (void (*)(Messenger *, uint32_t, unsigned int, const uint8_t *, size_t, void *))callback);
-}
-
-bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length)
-{
- if (!hash || (length && !data)) {
- return 0;
- }
-
- crypto_sha256(hash, data, length);
- return 1;
-}
-
-bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
- TOX_ERR_FILE_CONTROL *error)
-{
- Messenger *m = tox;
- int ret = file_control(m, friend_number, file_number, control);
-
- if (ret == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_OK);
- return 1;
- }
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND);
- return 0;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED);
- return 0;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_FOUND);
- return 0;
-
- case -4:
- /* can't happen */
- return 0;
-
- case -5:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_ALREADY_PAUSED);
- return 0;
-
- case -6:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_DENIED);
- return 0;
-
- case -7:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_NOT_PAUSED);
- return 0;
-
- case -8:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_CONTROL_SENDQ);
- return 0;
- }
-
- /* can't happen */
- return 0;
-}
-
-bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- TOX_ERR_FILE_SEEK *error)
-{
- Messenger *m = tox;
- int ret = file_seek(m, friend_number, file_number, position);
-
- if (ret == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_OK);
- return 1;
- }
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND);
- return 0;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED);
- return 0;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_NOT_FOUND);
- return 0;
-
- case -4: // fall-through
- case -5:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_DENIED);
- return 0;
-
- case -6:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_INVALID_POSITION);
- return 0;
-
- case -8:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEEK_SENDQ);
- return 0;
- }
-
- /* can't happen */
- return 0;
-}
-
-void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback)
-{
- Messenger *m = tox;
- callback_file_control(m, (void (*)(Messenger *, uint32_t, uint32_t, unsigned int, void *))callback);
-}
-
-bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
- TOX_ERR_FILE_GET *error)
-{
- if (!file_id) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NULL);
- return 0;
- }
-
- const Messenger *m = tox;
- int ret = file_get_id(m, friend_number, file_number, file_id);
-
- if (ret == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_OK);
- return 1;
- }
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_FRIEND_NOT_FOUND);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_GET_NOT_FOUND);
- }
-
- return 0;
-}
-
-uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
- const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error)
-{
- if (filename_length && !filename) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NULL);
- return UINT32_MAX;
- }
-
- uint8_t f_id[FILE_ID_LENGTH];
-
- if (!file_id) {
- /* Tox keys are 32 bytes like FILE_ID_LENGTH. */
- new_symmetric_key(f_id);
- file_id = f_id;
- }
-
- Messenger *m = tox;
- long int file_num = new_filesender(m, friend_number, kind, file_size, file_id, filename, filename_length);
-
- if (file_num >= 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_OK);
- return file_num;
- }
-
- switch (file_num) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND);
- return UINT32_MAX;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_NAME_TOO_LONG);
- return UINT32_MAX;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_TOO_MANY);
- return UINT32_MAX;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED);
- return UINT32_MAX;
- }
-
- /* can't happen */
- return UINT32_MAX;
-}
-
-bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
- size_t length, TOX_ERR_FILE_SEND_CHUNK *error)
-{
- Messenger *m = tox;
- int ret = file_data(m, friend_number, file_number, position, data, length);
-
- if (ret == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_OK);
- return 1;
- }
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND);
- return 0;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED);
- return 0;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND);
- return 0;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING);
- return 0;
-
- case -5:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH);
- return 0;
-
- case -6:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_SENDQ);
- return 0;
-
- case -7:
- SET_ERROR_PARAMETER(error, TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION);
- return 0;
- }
-
- /* can't happen */
- return 0;
-}
-
-void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback)
-{
- Messenger *m = tox;
- callback_file_reqchunk(m, callback);
-}
-
-void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback)
-{
- Messenger *m = tox;
- callback_file_sendrequest(m, callback);
-}
-
-void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback)
-{
- Messenger *m = tox;
- callback_file_data(m, callback);
-}
-
-void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback)
-{
- Messenger *m = tox;
- g_callback_group_invite((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, int, const uint8_t *,
- size_t,
- void *))callback);
-}
-
-void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback)
-{
- Messenger *m = tox;
- g_callback_group_message((Group_Chats *)m->conferences_object, (void (*)(Messenger * m, uint32_t, uint32_t, int,
- const uint8_t *,
- size_t, void *))callback);
-}
-
-void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback)
-{
- Messenger *m = tox;
- g_callback_group_title((Group_Chats *)m->conferences_object, callback);
-}
-
-void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback)
-{
- Messenger *m = tox;
- g_callback_group_namelistchange((Group_Chats *)m->conferences_object, (void (*)(struct Messenger *, int, int, uint8_t,
- void *))callback);
-}
-
-uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error)
-{
- Messenger *m = tox;
- int ret = add_groupchat((Group_Chats *)m->conferences_object, GROUPCHAT_TYPE_TEXT);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_INIT);
- return UINT32_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_NEW_OK);
- return ret;
-}
-
-bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error)
-{
- Messenger *m = tox;
- int ret = del_groupchat((Group_Chats *)m->conferences_object, conference_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_DELETE_OK);
- return true;
-}
-
-uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = group_number_peers((Group_Chats *)m->conferences_object, conference_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
- return UINT32_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
- return ret;
-}
-
-size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_ERR_CONFERENCE_PEER_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = group_peername_size((Group_Chats *)m->conferences_object, conference_number, peer_number);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
- return -1;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
- return -1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
- return ret;
-}
-
-bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
- TOX_ERR_CONFERENCE_PEER_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = group_peername((Group_Chats *)m->conferences_object, conference_number, peer_number, name);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
- return true;
-}
-
-bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = group_peer_pubkey((Group_Chats *)m->conferences_object, conference_number, peer_number, public_key);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
- return true;
-}
-
-bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_ERR_CONFERENCE_PEER_QUERY *error)
-{
- const Messenger *m = tox;
- int ret = group_peernumber_is_ours((Group_Chats *)m->conferences_object, conference_number, peer_number);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND);
- return false;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_PEER_QUERY_OK);
- return ret;
-}
-
-bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
- TOX_ERR_CONFERENCE_INVITE *error)
-{
- Messenger *m = tox;
- int ret = invite_friend((Group_Chats *)m->conferences_object, friend_number, conference_number);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_FAIL_SEND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_INVITE_OK);
- return true;
-}
-
-uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
- TOX_ERR_CONFERENCE_JOIN *error)
-{
- Messenger *m = tox;
- int ret = join_groupchat((Group_Chats *)m->conferences_object, friend_number, GROUPCHAT_TYPE_TEXT, cookie, length);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH);
- return UINT32_MAX;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE);
- return UINT32_MAX;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND);
- return UINT32_MAX;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_DUPLICATE);
- return UINT32_MAX;
-
- case -5:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_INIT_FAIL);
- return UINT32_MAX;
-
- case -6:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_FAIL_SEND);
- return UINT32_MAX;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_JOIN_OK);
- return ret;
-}
-
-bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
- size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error)
-{
- Messenger *m = tox;
- int ret = 0;
-
- if (type == TOX_MESSAGE_TYPE_NORMAL) {
- ret = group_message_send((Group_Chats *)m->conferences_object, conference_number, message, length);
- } else {
- ret = group_action_send((Group_Chats *)m->conferences_object, conference_number, message, length);
- }
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG);
- return false;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION);
- return false;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_SEND_MESSAGE_OK);
- return true;
-}
-
-size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error)
-{
- const Messenger *m = tox;
- int ret = group_title_get_size((Group_Chats *)m->conferences_object, conference_number);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
- return -1;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
- return -1;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
- return ret;
-}
-
-bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
- TOX_ERR_CONFERENCE_TITLE *error)
-{
- const Messenger *m = tox;
- int ret = group_title_get((Group_Chats *)m->conferences_object, conference_number, title);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
- return true;
-}
-
-bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
- TOX_ERR_CONFERENCE_TITLE *error)
-{
- Messenger *m = tox;
- int ret = group_title_send((Group_Chats *)m->conferences_object, conference_number, title, length);
-
- switch (ret) {
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND);
- return false;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH);
- return false;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_FAIL_SEND);
- return false;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_TITLE_OK);
- return true;
-}
-
-size_t tox_conference_get_chatlist_size(const Tox *tox)
-{
- const Messenger *m = tox;
- return count_chatlist((Group_Chats *)m->conferences_object);
-}
-
-void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist)
-{
- const Messenger *m = tox;
- size_t list_size = tox_conference_get_chatlist_size(tox);
- copy_chatlist((Group_Chats *)m->conferences_object, chatlist, list_size);
-}
-
-TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
- TOX_ERR_CONFERENCE_GET_TYPE *error)
-{
- const Messenger *m = tox;
- int ret = group_get_type((Group_Chats *)m->conferences_object, conference_number);
-
- if (ret == -1) {
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND);
- return (TOX_CONFERENCE_TYPE)ret;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_CONFERENCE_GET_TYPE_OK);
- return (TOX_CONFERENCE_TYPE)ret;
-}
-
-static void set_custom_packet_error(int ret, TOX_ERR_FRIEND_CUSTOM_PACKET *error)
-{
- switch (ret) {
- case 0:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_OK);
- break;
-
- case -1:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND);
- break;
-
- case -2:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG);
- break;
-
- case -3:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
- break;
-
- case -4:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED);
- break;
-
- case -5:
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ);
- break;
- }
-}
-
-bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- TOX_ERR_FRIEND_CUSTOM_PACKET *error)
-{
- if (!data) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
- return 0;
- }
-
- Messenger *m = tox;
-
- if (length == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
- return 0;
- }
-
- if (data[0] < (PACKET_ID_LOSSY_RANGE_START + PACKET_LOSSY_AV_RESERVED)) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID);
- return 0;
- }
-
- int ret = m_send_custom_lossy_packet(m, friend_number, data, length);
-
- set_custom_packet_error(ret, error);
-
- if (ret == 0) {
- return 1;
- }
-
- return 0;
-}
-
-void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback)
-{
- Messenger *m = tox;
- custom_lossy_packet_registerhandler(m, callback);
-}
-
-bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- TOX_ERR_FRIEND_CUSTOM_PACKET *error)
-{
- if (!data) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_NULL);
- return 0;
- }
-
- Messenger *m = tox;
-
- if (length == 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY);
- return 0;
- }
-
- int ret = send_custom_lossless_packet(m, friend_number, data, length);
-
- set_custom_packet_error(ret, error);
-
- if (ret == 0) {
- return 1;
- }
-
- return 0;
-}
-
-void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback)
-{
- Messenger *m = tox;
- custom_lossless_packet_registerhandler(m, callback);
-}
-
-void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id)
-{
- if (dht_id) {
- const Messenger *m = tox;
- memcpy(dht_id, m->dht->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- }
-}
-
-uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
-{
- const Messenger *m = tox;
- uint16_t port = net_htons(m->net->port);
-
- if (port) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
- } else {
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
- }
-
- return port;
-}
-
-uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error)
-{
- const Messenger *m = tox;
-
- if (m->tcp_server) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_OK);
- return m->options.tcp_server_port;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_PORT_NOT_BOUND);
- return 0;
-}
diff --git a/libs/libtox/src/toxcore/tox.h b/libs/libtox/src/toxcore/tox.h
deleted file mode 100644
index 30bc950964..0000000000
--- a/libs/libtox/src/toxcore/tox.h
+++ /dev/null
@@ -1,2947 +0,0 @@
-/*
- * The Tox public API.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOX_H
-#define TOX_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*******************************************************************************
- * `tox.h` SHOULD *NOT* BE EDITED MANUALLY – any changes should be made to *
- * `tox.api.h`, located in `toxcore/`. For instructions on how to *
- * generate `tox.h` from `tox.api.h` please refer to `docs/apidsl.md` *
- ******************************************************************************/
-
-
-
-/** \page core Public core API for Tox clients.
- *
- * Every function that can fail takes a function-specific error code pointer
- * that can be used to diagnose problems with the Tox state or the function
- * arguments. The error code pointer can be NULL, which does not influence the
- * function's behaviour, but can be done if the reason for failure is irrelevant
- * to the client.
- *
- * The exception to this rule are simple allocation functions whose only failure
- * mode is allocation failure. They return NULL in that case, and do not set an
- * error code.
- *
- * Every error code type has an OK value to which functions will set their error
- * code value on success. Clients can keep their error code uninitialised before
- * passing it to a function. The library guarantees that after returning, the
- * value pointed to by the error code pointer has been initialised.
- *
- * Functions with pointer parameters often have a NULL error code, meaning they
- * could not perform any operation, because one of the required parameters was
- * NULL. Some functions operate correctly or are defined as effectless on NULL.
- *
- * Some functions additionally return a value outside their
- * return type domain, or a bool containing true on success and false on
- * failure.
- *
- * All functions that take a Tox instance pointer will cause undefined behaviour
- * when passed a NULL Tox pointer.
- *
- * All integer values are expected in host byte order.
- *
- * Functions with parameters with enum types cause unspecified behaviour if the
- * enumeration value is outside the valid range of the type. If possible, the
- * function will try to use a sane default, but there will be no error code,
- * and one possible action for the function to take is to have no effect.
- *
- * Integer constants and the memory layout of publicly exposed structs are not
- * part of the ABI.
- */
-/** \subsection events Events and callbacks
- *
- * Events are handled by callbacks. One callback can be registered per event.
- * All events have a callback function type named `tox_{event}_cb` and a
- * function to register it named `tox_callback_{event}`. Passing a NULL
- * callback will result in no callback being registered for that event. Only
- * one callback per event can be registered, so if a client needs multiple
- * event listeners, it needs to implement the dispatch functionality itself.
- *
- * The last argument to a callback is the user data pointer. It is passed from
- * tox_iterate to each callback in sequence.
- *
- * The user data pointer is never stored or dereferenced by any library code, so
- * can be any pointer, including NULL. Callbacks must all operate on the same
- * object type. In the apidsl code (tox.in.h), this is denoted with `any`. The
- * `any` in tox_iterate must be the same `any` as in all callbacks. In C,
- * lacking parametric polymorphism, this is a pointer to void.
- *
- * Old style callbacks that are registered together with a user data pointer
- * receive that pointer as argument when they are called. They can each have
- * their own user data pointer of their own type.
- */
-/** \subsection threading Threading implications
- *
- * It is possible to run multiple concurrent threads with a Tox instance for
- * each thread. It is also possible to run all Tox instances in the same thread.
- * A common way to run Tox (multiple or single instance) is to have one thread
- * running a simple tox_iterate loop, sleeping for tox_iteration_interval
- * milliseconds on each iteration.
- *
- * If you want to access a single Tox instance from multiple threads, access
- * to the instance must be synchronised. While multiple threads can concurrently
- * access multiple different Tox instances, no more than one API function can
- * operate on a single instance at any given time.
- *
- * Functions that write to variable length byte arrays will always have a size
- * function associated with them. The result of this size function is only valid
- * until another mutating function (one that takes a pointer to non-const Tox)
- * is called. Thus, clients must ensure that no other thread calls a mutating
- * function between the call to the size function and the call to the retrieval
- * function.
- *
- * E.g. to get the current nickname, one would write
- *
- * \code
- * size_t length = tox_self_get_name_size(tox);
- * uint8_t *name = malloc(length);
- * if (!name) abort();
- * tox_self_get_name(tox, name);
- * \endcode
- *
- * If any other thread calls tox_self_set_name while this thread is allocating
- * memory, the length may have become invalid, and the call to
- * tox_self_get_name may cause undefined behaviour.
- */
-/**
- * The Tox instance type. All the state associated with a connection is held
- * within the instance. Multiple instances can exist and operate concurrently.
- * The maximum number of Tox instances that can exist on a single network
- * device is limited. Note that this is not just a per-process limit, since the
- * limiting factor is the number of usable ports on a device.
- */
-#ifndef TOX_DEFINED
-#define TOX_DEFINED
-typedef struct Tox Tox;
-#endif /* TOX_DEFINED */
-
-
-/*******************************************************************************
- *
- * :: API version
- *
- ******************************************************************************/
-
-
-
-/**
- * The major version number. Incremented when the API or ABI changes in an
- * incompatible way.
- *
- * The function variants of these constants return the version number of the
- * library. They can be used to display the Tox library version or to check
- * whether the client is compatible with the dynamically linked version of Tox.
- */
-#define TOX_VERSION_MAJOR 0
-
-uint32_t tox_version_major(void);
-
-/**
- * The minor version number. Incremented when functionality is added without
- * breaking the API or ABI. Set to 0 when the major version number is
- * incremented.
- */
-#define TOX_VERSION_MINOR 1
-
-uint32_t tox_version_minor(void);
-
-/**
- * The patch or revision number. Incremented when bugfixes are applied without
- * changing any functionality or API or ABI.
- */
-#define TOX_VERSION_PATCH 10
-
-uint32_t tox_version_patch(void);
-
-/**
- * A macro to check at preprocessing time whether the client code is compatible
- * with the installed version of Tox. Leading zeros in the version number are
- * ignored. E.g. 0.1.5 is to 0.1.4 what 1.5 is to 1.4, that is: it can add new
- * features, but can't break the API.
- */
-#define TOX_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
- (TOX_VERSION_MAJOR > 0 && TOX_VERSION_MAJOR == MAJOR) && ( \
- /* 1.x.x, 2.x.x, etc. with matching major version. */ \
- TOX_VERSION_MINOR > MINOR || \
- TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH \
- ) || (TOX_VERSION_MAJOR == 0 && MAJOR == 0) && ( \
- /* 0.x.x makes minor behave like major above. */ \
- (TOX_VERSION_MINOR > 0 && TOX_VERSION_MINOR == MINOR) && ( \
- TOX_VERSION_PATCH >= PATCH \
- ) || (TOX_VERSION_MINOR == 0 && MINOR == 0) && ( \
- /* 0.0.x and 0.0.y are only compatible if x == y. */ \
- TOX_VERSION_PATCH == PATCH \
- ) \
- )
-
-/**
- * Return whether the compiled library version is compatible with the passed
- * version numbers.
- */
-bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
-
-/**
- * A convenience macro to call tox_version_is_compatible with the currently
- * compiling API version.
- */
-#define TOX_VERSION_IS_ABI_COMPATIBLE() \
- tox_version_is_compatible(TOX_VERSION_MAJOR, TOX_VERSION_MINOR, TOX_VERSION_PATCH)
-
-
-/*******************************************************************************
- *
- * :: Numeric constants
- *
- * The values of these are not part of the ABI. Prefer to use the function
- * versions of them for code that should remain compatible with future versions
- * of toxcore.
- *
- ******************************************************************************/
-
-
-
-/**
- * The size of a Tox Public Key in bytes.
- */
-#define TOX_PUBLIC_KEY_SIZE 32
-
-uint32_t tox_public_key_size(void);
-
-/**
- * The size of a Tox Secret Key in bytes.
- */
-#define TOX_SECRET_KEY_SIZE 32
-
-uint32_t tox_secret_key_size(void);
-
-/**
- * The size of the nospam in bytes when written in a Tox address.
- */
-#define TOX_NOSPAM_SIZE (sizeof(uint32_t))
-
-uint32_t tox_nospam_size(void);
-
-/**
- * The size of a Tox address in bytes. Tox addresses are in the format
- * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)].
- *
- * The checksum is computed over the Public Key and the nospam value. The first
- * byte is an XOR of all the even bytes (0, 2, 4, ...), the second byte is an
- * XOR of all the odd bytes (1, 3, 5, ...) of the Public Key and nospam.
- */
-#define TOX_ADDRESS_SIZE (TOX_PUBLIC_KEY_SIZE + TOX_NOSPAM_SIZE + sizeof(uint16_t))
-
-uint32_t tox_address_size(void);
-
-/**
- * Maximum length of a nickname in bytes.
- */
-#define TOX_MAX_NAME_LENGTH 128
-
-uint32_t tox_max_name_length(void);
-
-/**
- * Maximum length of a status message in bytes.
- */
-#define TOX_MAX_STATUS_MESSAGE_LENGTH 1007
-
-uint32_t tox_max_status_message_length(void);
-
-/**
- * Maximum length of a friend request message in bytes.
- */
-#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016
-
-uint32_t tox_max_friend_request_length(void);
-
-/**
- * Maximum length of a single message after which it should be split.
- */
-#define TOX_MAX_MESSAGE_LENGTH 1372
-
-uint32_t tox_max_message_length(void);
-
-/**
- * Maximum size of custom packets. TODO(iphydf): should be LENGTH?
- */
-#define TOX_MAX_CUSTOM_PACKET_SIZE 1373
-
-uint32_t tox_max_custom_packet_size(void);
-
-/**
- * The number of bytes in a hash generated by tox_hash.
- */
-#define TOX_HASH_LENGTH 32
-
-uint32_t tox_hash_length(void);
-
-/**
- * The number of bytes in a file id.
- */
-#define TOX_FILE_ID_LENGTH 32
-
-uint32_t tox_file_id_length(void);
-
-/**
- * Maximum file name length for file transfers.
- */
-#define TOX_MAX_FILENAME_LENGTH 255
-
-uint32_t tox_max_filename_length(void);
-
-
-/*******************************************************************************
- *
- * :: Global enumerations
- *
- ******************************************************************************/
-
-
-
-/**
- * Represents the possible statuses a client can have.
- */
-typedef enum TOX_USER_STATUS {
-
- /**
- * User is online and available.
- */
- TOX_USER_STATUS_NONE,
-
- /**
- * User is away. Clients can set this e.g. after a user defined
- * inactivity time.
- */
- TOX_USER_STATUS_AWAY,
-
- /**
- * User is busy. Signals to other clients that this client does not
- * currently wish to communicate.
- */
- TOX_USER_STATUS_BUSY,
-
-} TOX_USER_STATUS;
-
-
-/**
- * Represents message types for tox_friend_send_message and conference
- * messages.
- */
-typedef enum TOX_MESSAGE_TYPE {
-
- /**
- * Normal text message. Similar to PRIVMSG on IRC.
- */
- TOX_MESSAGE_TYPE_NORMAL,
-
- /**
- * A message describing an user action. This is similar to /me (CTCP ACTION)
- * on IRC.
- */
- TOX_MESSAGE_TYPE_ACTION,
-
-} TOX_MESSAGE_TYPE;
-
-
-
-/*******************************************************************************
- *
- * :: Startup options
- *
- ******************************************************************************/
-
-
-
-/**
- * Type of proxy used to connect to TCP relays.
- */
-typedef enum TOX_PROXY_TYPE {
-
- /**
- * Don't use a proxy.
- */
- TOX_PROXY_TYPE_NONE,
-
- /**
- * HTTP proxy using CONNECT.
- */
- TOX_PROXY_TYPE_HTTP,
-
- /**
- * SOCKS proxy for simple socket pipes.
- */
- TOX_PROXY_TYPE_SOCKS5,
-
-} TOX_PROXY_TYPE;
-
-
-/**
- * Type of savedata to create the Tox instance from.
- */
-typedef enum TOX_SAVEDATA_TYPE {
-
- /**
- * No savedata.
- */
- TOX_SAVEDATA_TYPE_NONE,
-
- /**
- * Savedata is one that was obtained from tox_get_savedata.
- */
- TOX_SAVEDATA_TYPE_TOX_SAVE,
-
- /**
- * Savedata is a secret key of length TOX_SECRET_KEY_SIZE.
- */
- TOX_SAVEDATA_TYPE_SECRET_KEY,
-
-} TOX_SAVEDATA_TYPE;
-
-
-/**
- * Severity level of log messages.
- */
-typedef enum TOX_LOG_LEVEL {
-
- /**
- * Very detailed traces including all network activity.
- */
- TOX_LOG_LEVEL_TRACE,
-
- /**
- * Debug messages such as which port we bind to.
- */
- TOX_LOG_LEVEL_DEBUG,
-
- /**
- * Informational log messages such as video call status changes.
- */
- TOX_LOG_LEVEL_INFO,
-
- /**
- * Warnings about internal inconsistency or logic errors.
- */
- TOX_LOG_LEVEL_WARNING,
-
- /**
- * Severe unexpected errors caused by external or internal inconsistency.
- */
- TOX_LOG_LEVEL_ERROR,
-
-} TOX_LOG_LEVEL;
-
-
-/**
- * This event is triggered when the toxcore library logs an internal message.
- * This is mostly useful for debugging. This callback can be called from any
- * function, not just tox_iterate. This means the user data lifetime must at
- * least extend between registering and unregistering it or tox_kill.
- *
- * Other toxcore modules such as toxav may concurrently call this callback at
- * any time. Thus, user code must make sure it is equipped to handle concurrent
- * execution, e.g. by employing appropriate mutex locking.
- *
- * @param level The severity of the log message.
- * @param file The source file from which the message originated.
- * @param line The source line from which the message originated.
- * @param func The function from which the message originated.
- * @param message The log message.
- * @param user_data The user data pointer passed to tox_new in options.
- */
-typedef void tox_log_cb(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
- const char *message, void *user_data);
-
-
-/**
- * This struct contains all the startup options for Tox. You must tox_options_new to
- * allocate an object of this type.
- *
- * WARNING: Although this struct happens to be visible in the API, it is
- * effectively private. Do not allocate this yourself or access members
- * directly, as it *will* break binary compatibility frequently.
- *
- * @deprecated The memory layout of this struct (size, alignment, and field
- * order) is not part of the ABI. To remain compatible, prefer to use tox_options_new to
- * allocate the object and accessor functions to set the members. The struct
- * will become opaque (i.e. the definition will become private) in v0.2.0.
- */
-struct Tox_Options {
-
- /**
- * The type of socket to create.
- *
- * If this is set to false, an IPv4 socket is created, which subsequently
- * only allows IPv4 communication.
- * If it is set to true, an IPv6 socket is created, allowing both IPv4 and
- * IPv6 communication.
- */
- bool ipv6_enabled;
-
-
- /**
- * Enable the use of UDP communication when available.
- *
- * Setting this to false will force Tox to use TCP only. Communications will
- * need to be relayed through a TCP relay node, potentially slowing them down.
- * Disabling UDP support is necessary when using anonymous proxies or Tor.
- */
- bool udp_enabled;
-
-
- /**
- * Enable local network peer discovery.
- *
- * Disabling this will cause Tox to not look for peers on the local network.
- */
- bool local_discovery_enabled;
-
-
- /**
- * Pass communications through a proxy.
- */
- TOX_PROXY_TYPE proxy_type;
-
-
- /**
- * The IP address or DNS name of the proxy to be used.
- *
- * If used, this must be non-NULL and be a valid DNS name. The name must not
- * exceed 255 characters, and be in a NUL-terminated C string format
- * (255 chars + 1 NUL byte).
- *
- * This member is ignored (it can be NULL) if proxy_type is TOX_PROXY_TYPE_NONE.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- const char *proxy_host;
-
-
- /**
- * The port to use to connect to the proxy server.
- *
- * Ports must be in the range (1, 65535). The value is ignored if
- * proxy_type is TOX_PROXY_TYPE_NONE.
- */
- uint16_t proxy_port;
-
-
- /**
- * The start port of the inclusive port range to attempt to use.
- *
- * If both start_port and end_port are 0, the default port range will be
- * used: [33445, 33545].
- *
- * If either start_port or end_port is 0 while the other is non-zero, the
- * non-zero port will be the only port in the range.
- *
- * Having start_port > end_port will yield the same behavior as if start_port
- * and end_port were swapped.
- */
- uint16_t start_port;
-
-
- /**
- * The end port of the inclusive port range to attempt to use.
- */
- uint16_t end_port;
-
-
- /**
- * The port to use for the TCP server (relay). If 0, the TCP server is
- * disabled.
- *
- * Enabling it is not required for Tox to function properly.
- *
- * When enabled, your Tox instance can act as a TCP relay for other Tox
- * instance. This leads to increased traffic, thus when writing a client
- * it is recommended to enable TCP server only if the user has an option
- * to disable it.
- */
- uint16_t tcp_port;
-
-
- /**
- * Enables or disables UDP hole-punching in toxcore. (Default: enabled).
- */
- bool hole_punching_enabled;
-
-
- /**
- * The type of savedata to load from.
- */
- TOX_SAVEDATA_TYPE savedata_type;
-
-
- /**
- * The savedata.
- *
- * The data pointed at by this member is owned by the user, so must
- * outlive the options object.
- */
- const uint8_t *savedata_data;
-
-
- /**
- * The length of the savedata.
- */
- size_t savedata_length;
-
-
- /**
- * Logging callback for the new tox instance.
- */
- tox_log_cb *log_callback;
-
-
- /**
- * User data pointer passed to the logging callback.
- */
- void *log_user_data;
-
-};
-
-
-bool tox_options_get_ipv6_enabled(const struct Tox_Options *options);
-
-void tox_options_set_ipv6_enabled(struct Tox_Options *options, bool ipv6_enabled);
-
-bool tox_options_get_udp_enabled(const struct Tox_Options *options);
-
-void tox_options_set_udp_enabled(struct Tox_Options *options, bool udp_enabled);
-
-bool tox_options_get_local_discovery_enabled(const struct Tox_Options *options);
-
-void tox_options_set_local_discovery_enabled(struct Tox_Options *options, bool local_discovery_enabled);
-
-TOX_PROXY_TYPE tox_options_get_proxy_type(const struct Tox_Options *options);
-
-void tox_options_set_proxy_type(struct Tox_Options *options, TOX_PROXY_TYPE type);
-
-const char *tox_options_get_proxy_host(const struct Tox_Options *options);
-
-void tox_options_set_proxy_host(struct Tox_Options *options, const char *host);
-
-uint16_t tox_options_get_proxy_port(const struct Tox_Options *options);
-
-void tox_options_set_proxy_port(struct Tox_Options *options, uint16_t port);
-
-uint16_t tox_options_get_start_port(const struct Tox_Options *options);
-
-void tox_options_set_start_port(struct Tox_Options *options, uint16_t start_port);
-
-uint16_t tox_options_get_end_port(const struct Tox_Options *options);
-
-void tox_options_set_end_port(struct Tox_Options *options, uint16_t end_port);
-
-uint16_t tox_options_get_tcp_port(const struct Tox_Options *options);
-
-void tox_options_set_tcp_port(struct Tox_Options *options, uint16_t tcp_port);
-
-bool tox_options_get_hole_punching_enabled(const struct Tox_Options *options);
-
-void tox_options_set_hole_punching_enabled(struct Tox_Options *options, bool hole_punching_enabled);
-
-TOX_SAVEDATA_TYPE tox_options_get_savedata_type(const struct Tox_Options *options);
-
-void tox_options_set_savedata_type(struct Tox_Options *options, TOX_SAVEDATA_TYPE type);
-
-const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options);
-
-void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length);
-
-size_t tox_options_get_savedata_length(const struct Tox_Options *options);
-
-void tox_options_set_savedata_length(struct Tox_Options *options, size_t length);
-
-tox_log_cb *tox_options_get_log_callback(const struct Tox_Options *options);
-
-void tox_options_set_log_callback(struct Tox_Options *options, tox_log_cb *callback);
-
-void *tox_options_get_log_user_data(const struct Tox_Options *options);
-
-void tox_options_set_log_user_data(struct Tox_Options *options, void *user_data);
-
-/**
- * Initialises a Tox_Options object with the default options.
- *
- * The result of this function is independent of the original options. All
- * values will be overwritten, no values will be read (so it is permissible
- * to pass an uninitialised object).
- *
- * If options is NULL, this function has no effect.
- *
- * @param options An options object to be filled with default options.
- */
-void tox_options_default(struct Tox_Options *options);
-
-typedef enum TOX_ERR_OPTIONS_NEW {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_OPTIONS_NEW_OK,
-
- /**
- * The function failed to allocate enough memory for the options struct.
- */
- TOX_ERR_OPTIONS_NEW_MALLOC,
-
-} TOX_ERR_OPTIONS_NEW;
-
-
-/**
- * Allocates a new Tox_Options object and initialises it with the default
- * options. This function can be used to preserve long term ABI compatibility by
- * giving the responsibility of allocation and deallocation to the Tox library.
- *
- * Objects returned from this function must be freed using the tox_options_free
- * function.
- *
- * @return A new Tox_Options object with default options or NULL on failure.
- */
-struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error);
-
-/**
- * Releases all resources associated with an options objects.
- *
- * Passing a pointer that was not returned by tox_options_new results in
- * undefined behaviour.
- */
-void tox_options_free(struct Tox_Options *options);
-
-
-/*******************************************************************************
- *
- * :: Creation and destruction
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_NEW {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_NEW_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_NEW_NULL,
-
- /**
- * The function was unable to allocate enough memory to store the internal
- * structures for the Tox object.
- */
- TOX_ERR_NEW_MALLOC,
-
- /**
- * The function was unable to bind to a port. This may mean that all ports
- * have already been bound, e.g. by other Tox instances, or it may mean
- * a permission error. You may be able to gather more information from errno.
- */
- TOX_ERR_NEW_PORT_ALLOC,
-
- /**
- * proxy_type was invalid.
- */
- TOX_ERR_NEW_PROXY_BAD_TYPE,
-
- /**
- * proxy_type was valid but the proxy_host passed had an invalid format
- * or was NULL.
- */
- TOX_ERR_NEW_PROXY_BAD_HOST,
-
- /**
- * proxy_type was valid, but the proxy_port was invalid.
- */
- TOX_ERR_NEW_PROXY_BAD_PORT,
-
- /**
- * The proxy address passed could not be resolved.
- */
- TOX_ERR_NEW_PROXY_NOT_FOUND,
-
- /**
- * The byte array to be loaded contained an encrypted save.
- */
- TOX_ERR_NEW_LOAD_ENCRYPTED,
-
- /**
- * The data format was invalid. This can happen when loading data that was
- * saved by an older version of Tox, or when the data has been corrupted.
- * When loading from badly formatted data, some data may have been loaded,
- * and the rest is discarded. Passing an invalid length parameter also
- * causes this error.
- */
- TOX_ERR_NEW_LOAD_BAD_FORMAT,
-
-} TOX_ERR_NEW;
-
-
-/**
- * @brief Creates and initialises a new Tox instance with the options passed.
- *
- * This function will bring the instance into a valid state. Running the event
- * loop with a new instance will operate correctly.
- *
- * If loading failed or succeeded only partially, the new or partially loaded
- * instance is returned and an error code is set.
- *
- * @param options An options object as described above. If this parameter is
- * NULL, the default options are used.
- *
- * @see tox_iterate for the event loop.
- *
- * @return A new Tox instance pointer on success or NULL on failure.
- */
-Tox *tox_new(const struct Tox_Options *options, TOX_ERR_NEW *error);
-
-/**
- * Releases all resources associated with the Tox instance and disconnects from
- * the network.
- *
- * After calling this function, the Tox pointer becomes invalid. No other
- * functions can be called, and the pointer value can no longer be read.
- */
-void tox_kill(Tox *tox);
-
-/**
- * Calculates the number of bytes required to store the tox instance with
- * tox_get_savedata. This function cannot fail. The result is always greater than 0.
- *
- * @see threading for concurrency implications.
- */
-size_t tox_get_savedata_size(const Tox *tox);
-
-/**
- * Store all information associated with the tox instance to a byte array.
- *
- * @param savedata A memory region large enough to store the tox instance
- * data. Call tox_get_savedata_size to find the number of bytes required. If this parameter
- * is NULL, this function has no effect.
- */
-void tox_get_savedata(const Tox *tox, uint8_t *savedata);
-
-
-/*******************************************************************************
- *
- * :: Connection lifecycle and event loop
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_BOOTSTRAP {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_BOOTSTRAP_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_BOOTSTRAP_NULL,
-
- /**
- * The address could not be resolved to an IP address, or the IP address
- * passed was invalid.
- */
- TOX_ERR_BOOTSTRAP_BAD_HOST,
-
- /**
- * The port passed was invalid. The valid port range is (1, 65535).
- */
- TOX_ERR_BOOTSTRAP_BAD_PORT,
-
-} TOX_ERR_BOOTSTRAP;
-
-
-/**
- * Sends a "get nodes" request to the given bootstrap node with IP, port, and
- * public key to setup connections.
- *
- * This function will attempt to connect to the node using UDP. You must use
- * this function even if Tox_Options.udp_enabled was set to false.
- *
- * @param address The hostname or IP address (IPv4 or IPv6) of the node.
- * @param port The port on the host on which the bootstrap Tox instance is
- * listening.
- * @param public_key The long term public key of the bootstrap node
- * (TOX_PUBLIC_KEY_SIZE bytes).
- * @return true on success.
- */
-bool tox_bootstrap(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error);
-
-/**
- * Adds additional host:port pair as TCP relay.
- *
- * This function can be used to initiate TCP connections to different ports on
- * the same bootstrap node, or to add TCP relays without using them as
- * bootstrap nodes.
- *
- * @param address The hostname or IP address (IPv4 or IPv6) of the TCP relay.
- * @param port The port on the host on which the TCP relay is listening.
- * @param public_key The long term public key of the TCP relay
- * (TOX_PUBLIC_KEY_SIZE bytes).
- * @return true on success.
- */
-bool tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key,
- TOX_ERR_BOOTSTRAP *error);
-
-/**
- * Protocols that can be used to connect to the network or friends.
- */
-typedef enum TOX_CONNECTION {
-
- /**
- * There is no connection. This instance, or the friend the state change is
- * about, is now offline.
- */
- TOX_CONNECTION_NONE,
-
- /**
- * A TCP connection has been established. For the own instance, this means it
- * is connected through a TCP relay, only. For a friend, this means that the
- * connection to that particular friend goes through a TCP relay.
- */
- TOX_CONNECTION_TCP,
-
- /**
- * A UDP connection has been established. For the own instance, this means it
- * is able to send UDP packets to DHT nodes, but may still be connected to
- * a TCP relay. For a friend, this means that the connection to that
- * particular friend was built using direct UDP packets.
- */
- TOX_CONNECTION_UDP,
-
-} TOX_CONNECTION;
-
-
-/**
- * Return whether we are connected to the DHT. The return value is equal to the
- * last value received through the `self_connection_status` callback.
- */
-TOX_CONNECTION tox_self_get_connection_status(const Tox *tox);
-
-/**
- * @param connection_status Whether we are connected to the DHT.
- */
-typedef void tox_self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data);
-
-
-/**
- * Set the callback for the `self_connection_status` event. Pass NULL to unset.
- *
- * This event is triggered whenever there is a change in the DHT connection
- * state. When disconnected, a client may choose to call tox_bootstrap again, to
- * reconnect to the DHT. Note that this state may frequently change for short
- * amounts of time. Clients should therefore not immediately bootstrap on
- * receiving a disconnect.
- *
- * TODO(iphydf): how long should a client wait before bootstrapping again?
- */
-void tox_callback_self_connection_status(Tox *tox, tox_self_connection_status_cb *callback);
-
-/**
- * Return the time in milliseconds before tox_iterate() should be called again
- * for optimal performance.
- */
-uint32_t tox_iteration_interval(const Tox *tox);
-
-/**
- * The main loop that needs to be run in intervals of tox_iteration_interval()
- * milliseconds.
- */
-void tox_iterate(Tox *tox, void *user_data);
-
-
-/*******************************************************************************
- *
- * :: Internal client information (Tox address/id)
- *
- ******************************************************************************/
-
-
-
-/**
- * Writes the Tox friend address of the client to a byte array. The address is
- * not in human-readable format. If a client wants to display the address,
- * formatting is required.
- *
- * @param address A memory region of at least TOX_ADDRESS_SIZE bytes. If this
- * parameter is NULL, this function has no effect.
- * @see TOX_ADDRESS_SIZE for the address format.
- */
-void tox_self_get_address(const Tox *tox, uint8_t *address);
-
-/**
- * Set the 4-byte nospam part of the address. This value is expected in host
- * byte order. I.e. 0x12345678 will form the bytes [12, 34, 56, 78] in the
- * nospam part of the Tox friend address.
- *
- * @param nospam Any 32 bit unsigned integer.
- */
-void tox_self_set_nospam(Tox *tox, uint32_t nospam);
-
-/**
- * Get the 4-byte nospam part of the address. This value is returned in host
- * byte order.
- */
-uint32_t tox_self_get_nospam(const Tox *tox);
-
-/**
- * Copy the Tox Public Key (long term) from the Tox object.
- *
- * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- */
-void tox_self_get_public_key(const Tox *tox, uint8_t *public_key);
-
-/**
- * Copy the Tox Secret Key from the Tox object.
- *
- * @param secret_key A memory region of at least TOX_SECRET_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- */
-void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key);
-
-
-/*******************************************************************************
- *
- * :: User-visible client information (nickname/status)
- *
- ******************************************************************************/
-
-
-
-/**
- * Common error codes for all functions that set a piece of user-visible
- * client information.
- */
-typedef enum TOX_ERR_SET_INFO {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_SET_INFO_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_SET_INFO_NULL,
-
- /**
- * Information length exceeded maximum permissible size.
- */
- TOX_ERR_SET_INFO_TOO_LONG,
-
-} TOX_ERR_SET_INFO;
-
-
-/**
- * Set the nickname for the Tox client.
- *
- * Nickname length cannot exceed TOX_MAX_NAME_LENGTH. If length is 0, the name
- * parameter is ignored (it can be NULL), and the nickname is set back to empty.
- *
- * @param name A byte array containing the new nickname.
- * @param length The size of the name byte array.
- *
- * @return true on success.
- */
-bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error);
-
-/**
- * Return the length of the current nickname as passed to tox_self_set_name.
- *
- * If no nickname was set before calling this function, the name is empty,
- * and this function returns 0.
- *
- * @see threading for concurrency implications.
- */
-size_t tox_self_get_name_size(const Tox *tox);
-
-/**
- * Write the nickname set by tox_self_set_name to a byte array.
- *
- * If no nickname was set before calling this function, the name is empty,
- * and this function has no effect.
- *
- * Call tox_self_get_name_size to find out how much memory to allocate for
- * the result.
- *
- * @param name A valid memory location large enough to hold the nickname.
- * If this parameter is NULL, the function has no effect.
- */
-void tox_self_get_name(const Tox *tox, uint8_t *name);
-
-/**
- * Set the client's status message.
- *
- * Status message length cannot exceed TOX_MAX_STATUS_MESSAGE_LENGTH. If
- * length is 0, the status parameter is ignored (it can be NULL), and the
- * user status is set back to empty.
- */
-bool tox_self_set_status_message(Tox *tox, const uint8_t *status_message, size_t length, TOX_ERR_SET_INFO *error);
-
-/**
- * Return the length of the current status message as passed to tox_self_set_status_message.
- *
- * If no status message was set before calling this function, the status
- * is empty, and this function returns 0.
- *
- * @see threading for concurrency implications.
- */
-size_t tox_self_get_status_message_size(const Tox *tox);
-
-/**
- * Write the status message set by tox_self_set_status_message to a byte array.
- *
- * If no status message was set before calling this function, the status is
- * empty, and this function has no effect.
- *
- * Call tox_self_get_status_message_size to find out how much memory to allocate for
- * the result.
- *
- * @param status_message A valid memory location large enough to hold the
- * status message. If this parameter is NULL, the function has no effect.
- */
-void tox_self_get_status_message(const Tox *tox, uint8_t *status_message);
-
-/**
- * Set the client's user status.
- *
- * @param status One of the user statuses listed in the enumeration above.
- */
-void tox_self_set_status(Tox *tox, TOX_USER_STATUS status);
-
-/**
- * Returns the client's user status.
- */
-TOX_USER_STATUS tox_self_get_status(const Tox *tox);
-
-
-/*******************************************************************************
- *
- * :: Friend list management
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_FRIEND_ADD {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_ADD_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FRIEND_ADD_NULL,
-
- /**
- * The length of the friend request message exceeded
- * TOX_MAX_FRIEND_REQUEST_LENGTH.
- */
- TOX_ERR_FRIEND_ADD_TOO_LONG,
-
- /**
- * The friend request message was empty. This, and the TOO_LONG code will
- * never be returned from tox_friend_add_norequest.
- */
- TOX_ERR_FRIEND_ADD_NO_MESSAGE,
-
- /**
- * The friend address belongs to the sending client.
- */
- TOX_ERR_FRIEND_ADD_OWN_KEY,
-
- /**
- * A friend request has already been sent, or the address belongs to a friend
- * that is already on the friend list.
- */
- TOX_ERR_FRIEND_ADD_ALREADY_SENT,
-
- /**
- * The friend address checksum failed.
- */
- TOX_ERR_FRIEND_ADD_BAD_CHECKSUM,
-
- /**
- * The friend was already there, but the nospam value was different.
- */
- TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM,
-
- /**
- * A memory allocation failed when trying to increase the friend list size.
- */
- TOX_ERR_FRIEND_ADD_MALLOC,
-
-} TOX_ERR_FRIEND_ADD;
-
-
-/**
- * Add a friend to the friend list and send a friend request.
- *
- * A friend request message must be at least 1 byte long and at most
- * TOX_MAX_FRIEND_REQUEST_LENGTH.
- *
- * Friend numbers are unique identifiers used in all functions that operate on
- * friends. Once added, a friend number is stable for the lifetime of the Tox
- * object. After saving the state and reloading it, the friend numbers may not
- * be the same as before. Deleting a friend creates a gap in the friend number
- * set, which is filled by the next adding of a friend. Any pattern in friend
- * numbers should not be relied on.
- *
- * If more than INT32_MAX friends are added, this function causes undefined
- * behaviour.
- *
- * @param address The address of the friend (returned by tox_self_get_address of
- * the friend you wish to add) it must be TOX_ADDRESS_SIZE bytes.
- * @param message The message that will be sent along with the friend request.
- * @param length The length of the data byte array.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- */
-uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length,
- TOX_ERR_FRIEND_ADD *error);
-
-/**
- * Add a friend without sending a friend request.
- *
- * This function is used to add a friend in response to a friend request. If the
- * client receives a friend request, it can be reasonably sure that the other
- * client added this client as a friend, eliminating the need for a friend
- * request.
- *
- * This function is also useful in a situation where both instances are
- * controlled by the same entity, so that this entity can perform the mutual
- * friend adding. In this case, there is no need for a friend request, either.
- *
- * @param public_key A byte array of length TOX_PUBLIC_KEY_SIZE containing the
- * Public Key (not the Address) of the friend to add.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- * @see tox_friend_add for a more detailed description of friend numbers.
- */
-uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error);
-
-typedef enum TOX_ERR_FRIEND_DELETE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_DELETE_OK,
-
- /**
- * There was no friend with the given friend number. No friends were deleted.
- */
- TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND,
-
-} TOX_ERR_FRIEND_DELETE;
-
-
-/**
- * Remove a friend from the friend list.
- *
- * This does not notify the friend of their deletion. After calling this
- * function, this client will appear offline to the friend and no communication
- * can occur between the two.
- *
- * @param friend_number Friend number for the friend to be deleted.
- *
- * @return true on success.
- */
-bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error);
-
-
-/*******************************************************************************
- *
- * :: Friend list queries
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_FRIEND_BY_PUBLIC_KEY {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL,
-
- /**
- * No friend with the given Public Key exists on the friend list.
- */
- TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND,
-
-} TOX_ERR_FRIEND_BY_PUBLIC_KEY;
-
-
-/**
- * Return the friend number associated with that Public Key.
- *
- * @return the friend number on success, UINT32_MAX on failure.
- * @param public_key A byte array containing the Public Key.
- */
-uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error);
-
-/**
- * Checks if a friend with the given friend number exists and returns true if
- * it does.
- */
-bool tox_friend_exists(const Tox *tox, uint32_t friend_number);
-
-/**
- * Return the number of friends on the friend list.
- *
- * This function can be used to determine how much memory to allocate for
- * tox_self_get_friend_list.
- */
-size_t tox_self_get_friend_list_size(const Tox *tox);
-
-/**
- * Copy a list of valid friend numbers into an array.
- *
- * Call tox_self_get_friend_list_size to determine the number of elements to allocate.
- *
- * @param friend_list A memory region with enough space to hold the friend
- * list. If this parameter is NULL, this function has no effect.
- */
-void tox_self_get_friend_list(const Tox *tox, uint32_t *friend_list);
-
-typedef enum TOX_ERR_FRIEND_GET_PUBLIC_KEY {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK,
-
- /**
- * No friend with the given number exists on the friend list.
- */
- TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND,
-
-} TOX_ERR_FRIEND_GET_PUBLIC_KEY;
-
-
-/**
- * Copies the Public Key associated with a given friend number to a byte array.
- *
- * @param friend_number The friend number you want the Public Key of.
- * @param public_key A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If
- * this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
-bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key,
- TOX_ERR_FRIEND_GET_PUBLIC_KEY *error);
-
-typedef enum TOX_ERR_FRIEND_GET_LAST_ONLINE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_GET_LAST_ONLINE_OK,
-
- /**
- * No friend with the given number exists on the friend list.
- */
- TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND,
-
-} TOX_ERR_FRIEND_GET_LAST_ONLINE;
-
-
-/**
- * Return a unix-time timestamp of the last time the friend associated with a given
- * friend number was seen online. This function will return UINT64_MAX on error.
- *
- * @param friend_number The friend number you want to query.
- */
-uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error);
-
-
-/*******************************************************************************
- *
- * :: Friend-specific state queries (can also be received through callbacks)
- *
- ******************************************************************************/
-
-
-
-/**
- * Common error codes for friend state query functions.
- */
-typedef enum TOX_ERR_FRIEND_QUERY {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_QUERY_OK,
-
- /**
- * The pointer parameter for storing the query result (name, message) was
- * NULL. Unlike the `_self_` variants of these functions, which have no effect
- * when a parameter is NULL, these functions return an error in that case.
- */
- TOX_ERR_FRIEND_QUERY_NULL,
-
- /**
- * The friend_number did not designate a valid friend.
- */
- TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND,
-
-} TOX_ERR_FRIEND_QUERY;
-
-
-/**
- * Return the length of the friend's name. If the friend number is invalid, the
- * return value is unspecified.
- *
- * The return value is equal to the `length` argument received by the last
- * `friend_name` callback.
- */
-size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * Write the name of the friend designated by the given friend number to a byte
- * array.
- *
- * Call tox_friend_get_name_size to determine the allocation size for the `name`
- * parameter.
- *
- * The data written to `name` is equal to the data received by the last
- * `friend_name` callback.
- *
- * @param name A valid memory region large enough to store the friend's name.
- *
- * @return true on success.
- */
-bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * @param friend_number The friend number of the friend whose name changed.
- * @param name A byte array containing the same data as
- * tox_friend_get_name would write to its `name` parameter.
- * @param length A value equal to the return value of
- * tox_friend_get_name_size.
- */
-typedef void tox_friend_name_cb(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `friend_name` event. Pass NULL to unset.
- *
- * This event is triggered when a friend changes their name.
- */
-void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *callback);
-
-/**
- * Return the length of the friend's status message. If the friend number is
- * invalid, the return value is SIZE_MAX.
- */
-size_t tox_friend_get_status_message_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * Write the status message of the friend designated by the given friend number to a byte
- * array.
- *
- * Call tox_friend_get_status_message_size to determine the allocation size for the `status_name`
- * parameter.
- *
- * The data written to `status_message` is equal to the data received by the last
- * `friend_status_message` callback.
- *
- * @param status_message A valid memory region large enough to store the friend's status message.
- */
-bool tox_friend_get_status_message(const Tox *tox, uint32_t friend_number, uint8_t *status_message,
- TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * @param friend_number The friend number of the friend whose status message
- * changed.
- * @param message A byte array containing the same data as
- * tox_friend_get_status_message would write to its `status_message` parameter.
- * @param length A value equal to the return value of
- * tox_friend_get_status_message_size.
- */
-typedef void tox_friend_status_message_cb(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
- void *user_data);
-
-
-/**
- * Set the callback for the `friend_status_message` event. Pass NULL to unset.
- *
- * This event is triggered when a friend changes their status message.
- */
-void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *callback);
-
-/**
- * Return the friend's user status (away/busy/...). If the friend number is
- * invalid, the return value is unspecified.
- *
- * The status returned is equal to the last status received through the
- * `friend_status` callback.
- */
-TOX_USER_STATUS tox_friend_get_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * @param friend_number The friend number of the friend whose user status
- * changed.
- * @param status The new user status.
- */
-typedef void tox_friend_status_cb(Tox *tox, uint32_t friend_number, TOX_USER_STATUS status, void *user_data);
-
-
-/**
- * Set the callback for the `friend_status` event. Pass NULL to unset.
- *
- * This event is triggered when a friend changes their user status.
- */
-void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *callback);
-
-/**
- * Check whether a friend is currently connected to this client.
- *
- * The result of this function is equal to the last value received by the
- * `friend_connection_status` callback.
- *
- * @param friend_number The friend number for which to query the connection
- * status.
- *
- * @return the friend's connection status as it was received through the
- * `friend_connection_status` event.
- */
-TOX_CONNECTION tox_friend_get_connection_status(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * @param friend_number The friend number of the friend whose connection status
- * changed.
- * @param connection_status The result of calling
- * tox_friend_get_connection_status on the passed friend_number.
- */
-typedef void tox_friend_connection_status_cb(Tox *tox, uint32_t friend_number, TOX_CONNECTION connection_status,
- void *user_data);
-
-
-/**
- * Set the callback for the `friend_connection_status` event. Pass NULL to unset.
- *
- * This event is triggered when a friend goes offline after having been online,
- * or when a friend goes online.
- *
- * This callback is not called when adding friends. It is assumed that when
- * adding friends, their connection status is initially offline.
- */
-void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *callback);
-
-/**
- * Check whether a friend is currently typing a message.
- *
- * @param friend_number The friend number for which to query the typing status.
- *
- * @return true if the friend is typing.
- * @return false if the friend is not typing, or the friend number was
- * invalid. Inspect the error code to determine which case it is.
- */
-bool tox_friend_get_typing(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error);
-
-/**
- * @param friend_number The friend number of the friend who started or stopped
- * typing.
- * @param is_typing The result of calling tox_friend_get_typing on the passed
- * friend_number.
- */
-typedef void tox_friend_typing_cb(Tox *tox, uint32_t friend_number, bool is_typing, void *user_data);
-
-
-/**
- * Set the callback for the `friend_typing` event. Pass NULL to unset.
- *
- * This event is triggered when a friend starts or stops typing.
- */
-void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: Sending private messages
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_SET_TYPING {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_SET_TYPING_OK,
-
- /**
- * The friend number did not designate a valid friend.
- */
- TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND,
-
-} TOX_ERR_SET_TYPING;
-
-
-/**
- * Set the client's typing status for a friend.
- *
- * The client is responsible for turning it on or off.
- *
- * @param friend_number The friend to which the client is typing a message.
- * @param typing The typing status. True means the client is typing.
- *
- * @return true on success.
- */
-bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool typing, TOX_ERR_SET_TYPING *error);
-
-typedef enum TOX_ERR_FRIEND_SEND_MESSAGE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_NULL,
-
- /**
- * The friend number did not designate a valid friend.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED,
-
- /**
- * An allocation error occurred while increasing the send queue size.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ,
-
- /**
- * Message length exceeded TOX_MAX_MESSAGE_LENGTH.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG,
-
- /**
- * Attempted to send a zero-length message.
- */
- TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY,
-
-} TOX_ERR_FRIEND_SEND_MESSAGE;
-
-
-/**
- * Send a text chat message to an online friend.
- *
- * This function creates a chat message packet and pushes it into the send
- * queue.
- *
- * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments. Messages may not be empty.
- *
- * The return value of this function is the message ID. If a read receipt is
- * received, the triggered `friend_read_receipt` event will be passed this message ID.
- *
- * Message IDs are unique per friend. The first message ID is 0. Message IDs are
- * incremented by 1 each time a message is sent. If UINT32_MAX messages were
- * sent, the next message ID is 0.
- *
- * @param type Message type (normal, action, ...).
- * @param friend_number The friend number of the friend to send the message to.
- * @param message A non-NULL pointer to the first element of a byte array
- * containing the message text.
- * @param length Length of the message to be sent.
- */
-uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
- size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error);
-
-/**
- * @param friend_number The friend number of the friend who received the message.
- * @param message_id The message ID as returned from tox_friend_send_message
- * corresponding to the message sent.
- */
-typedef void tox_friend_read_receipt_cb(Tox *tox, uint32_t friend_number, uint32_t message_id, void *user_data);
-
-
-/**
- * Set the callback for the `friend_read_receipt` event. Pass NULL to unset.
- *
- * This event is triggered when the friend receives the message sent with
- * tox_friend_send_message with the corresponding message ID.
- */
-void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: Receiving private messages and friend requests
- *
- ******************************************************************************/
-
-
-
-/**
- * @param public_key The Public Key of the user who sent the friend request.
- * @param message The message they sent along with the request.
- * @param length The size of the message byte array.
- */
-typedef void tox_friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
- void *user_data);
-
-
-/**
- * Set the callback for the `friend_request` event. Pass NULL to unset.
- *
- * This event is triggered when a friend request is received.
- */
-void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *callback);
-
-/**
- * @param friend_number The friend number of the friend who sent the message.
- * @param message The message data they sent.
- * @param length The size of the message byte array.
- */
-typedef void tox_friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
- size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `friend_message` event. Pass NULL to unset.
- *
- * This event is triggered when a message from a friend is received.
- */
-void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: File transmission: common between sending and receiving
- *
- ******************************************************************************/
-
-
-
-/**
- * Generates a cryptographic hash of the given data.
- *
- * This function may be used by clients for any purpose, but is provided
- * primarily for validating cached avatars. This use is highly recommended to
- * avoid unnecessary avatar updates.
- *
- * If hash is NULL or data is NULL while length is not 0 the function returns false,
- * otherwise it returns true.
- *
- * This function is a wrapper to internal message-digest functions.
- *
- * @param hash A valid memory location the hash data. It must be at least
- * TOX_HASH_LENGTH bytes in size.
- * @param data Data to be hashed or NULL.
- * @param length Size of the data array or 0.
- *
- * @return true if hash was not NULL.
- */
-bool tox_hash(uint8_t *hash, const uint8_t *data, size_t length);
-
-enum TOX_FILE_KIND {
-
- /**
- * Arbitrary file data. Clients can choose to handle it based on the file name
- * or magic or any other way they choose.
- */
- TOX_FILE_KIND_DATA,
-
- /**
- * Avatar file_id. This consists of tox_hash(image).
- * Avatar data. This consists of the image data.
- *
- * Avatars can be sent at any time the client wishes. Generally, a client will
- * send the avatar to a friend when that friend comes online, and to all
- * friends when the avatar changed. A client can save some traffic by
- * remembering which friend received the updated avatar already and only send
- * it if the friend has an out of date avatar.
- *
- * Clients who receive avatar send requests can reject it (by sending
- * TOX_FILE_CONTROL_CANCEL before any other controls), or accept it (by
- * sending TOX_FILE_CONTROL_RESUME). The file_id of length TOX_HASH_LENGTH bytes
- * (same length as TOX_FILE_ID_LENGTH) will contain the hash. A client can compare
- * this hash with a saved hash and send TOX_FILE_CONTROL_CANCEL to terminate the avatar
- * transfer if it matches.
- *
- * When file_size is set to 0 in the transfer request it means that the client
- * has no avatar.
- */
- TOX_FILE_KIND_AVATAR,
-
-};
-
-
-typedef enum TOX_FILE_CONTROL {
-
- /**
- * Sent by the receiving side to accept a file send request. Also sent after a
- * TOX_FILE_CONTROL_PAUSE command to continue sending or receiving.
- */
- TOX_FILE_CONTROL_RESUME,
-
- /**
- * Sent by clients to pause the file transfer. The initial state of a file
- * transfer is always paused on the receiving side and running on the sending
- * side. If both the sending and receiving side pause the transfer, then both
- * need to send TOX_FILE_CONTROL_RESUME for the transfer to resume.
- */
- TOX_FILE_CONTROL_PAUSE,
-
- /**
- * Sent by the receiving side to reject a file send request before any other
- * commands are sent. Also sent by either side to terminate a file transfer.
- */
- TOX_FILE_CONTROL_CANCEL,
-
-} TOX_FILE_CONTROL;
-
-
-typedef enum TOX_ERR_FILE_CONTROL {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FILE_CONTROL_OK,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED,
-
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- TOX_ERR_FILE_CONTROL_NOT_FOUND,
-
- /**
- * A RESUME control was sent, but the file transfer is running normally.
- */
- TOX_ERR_FILE_CONTROL_NOT_PAUSED,
-
- /**
- * A RESUME control was sent, but the file transfer was paused by the other
- * party. Only the party that paused the transfer can resume it.
- */
- TOX_ERR_FILE_CONTROL_DENIED,
-
- /**
- * A PAUSE control was sent, but the file transfer was already paused.
- */
- TOX_ERR_FILE_CONTROL_ALREADY_PAUSED,
-
- /**
- * Packet queue is full.
- */
- TOX_ERR_FILE_CONTROL_SENDQ,
-
-} TOX_ERR_FILE_CONTROL;
-
-
-/**
- * Sends a file control command to a friend for a given file transfer.
- *
- * @param friend_number The friend number of the friend the file is being
- * transferred to or received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param control The control command to send.
- *
- * @return true on success.
- */
-bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
- TOX_ERR_FILE_CONTROL *error);
-
-/**
- * When receiving TOX_FILE_CONTROL_CANCEL, the client should release the
- * resources associated with the file number and consider the transfer failed.
- *
- * @param friend_number The friend number of the friend who is sending the file.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param control The file control command received.
- */
-typedef void tox_file_recv_control_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control,
- void *user_data);
-
-
-/**
- * Set the callback for the `file_recv_control` event. Pass NULL to unset.
- *
- * This event is triggered when a file control command is received from a
- * friend.
- */
-void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *callback);
-
-typedef enum TOX_ERR_FILE_SEEK {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FILE_SEEK_OK,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED,
-
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- TOX_ERR_FILE_SEEK_NOT_FOUND,
-
- /**
- * File was not in a state where it could be seeked.
- */
- TOX_ERR_FILE_SEEK_DENIED,
-
- /**
- * Seek position was invalid
- */
- TOX_ERR_FILE_SEEK_INVALID_POSITION,
-
- /**
- * Packet queue is full.
- */
- TOX_ERR_FILE_SEEK_SENDQ,
-
-} TOX_ERR_FILE_SEEK;
-
-
-/**
- * Sends a file seek control command to a friend for a given file transfer.
- *
- * This function can only be called to resume a file transfer right before
- * TOX_FILE_CONTROL_RESUME is sent.
- *
- * @param friend_number The friend number of the friend the file is being
- * received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param position The position that the file should be seeked to.
- */
-bool tox_file_seek(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, TOX_ERR_FILE_SEEK *error);
-
-typedef enum TOX_ERR_FILE_GET {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FILE_GET_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FILE_GET_NULL,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOX_ERR_FILE_GET_FRIEND_NOT_FOUND,
-
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- TOX_ERR_FILE_GET_NOT_FOUND,
-
-} TOX_ERR_FILE_GET;
-
-
-/**
- * Copy the file id associated to the file transfer to a byte array.
- *
- * @param friend_number The friend number of the friend the file is being
- * transferred to or received from.
- * @param file_number The friend-specific identifier for the file transfer.
- * @param file_id A memory region of at least TOX_FILE_ID_LENGTH bytes. If
- * this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
-bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id,
- TOX_ERR_FILE_GET *error);
-
-
-/*******************************************************************************
- *
- * :: File transmission: sending
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_FILE_SEND {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FILE_SEND_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FILE_SEND_NULL,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED,
-
- /**
- * Filename length exceeded TOX_MAX_FILENAME_LENGTH bytes.
- */
- TOX_ERR_FILE_SEND_NAME_TOO_LONG,
-
- /**
- * Too many ongoing transfers. The maximum number of concurrent file transfers
- * is 256 per friend per direction (sending and receiving).
- */
- TOX_ERR_FILE_SEND_TOO_MANY,
-
-} TOX_ERR_FILE_SEND;
-
-
-/**
- * Send a file transmission request.
- *
- * Maximum filename length is TOX_MAX_FILENAME_LENGTH bytes. The filename
- * should generally just be a file name, not a path with directory names.
- *
- * If a non-UINT64_MAX file size is provided, it can be used by both sides to
- * determine the sending progress. File size can be set to UINT64_MAX for streaming
- * data of unknown size.
- *
- * File transmission occurs in chunks, which are requested through the
- * `file_chunk_request` event.
- *
- * When a friend goes offline, all file transfers associated with the friend are
- * purged from core.
- *
- * If the file contents change during a transfer, the behaviour is unspecified
- * in general. What will actually happen depends on the mode in which the file
- * was modified and how the client determines the file size.
- *
- * - If the file size was increased
- * - and sending mode was streaming (file_size = UINT64_MAX), the behaviour
- * will be as expected.
- * - and sending mode was file (file_size != UINT64_MAX), the
- * file_chunk_request callback will receive length = 0 when Core thinks
- * the file transfer has finished. If the client remembers the file size as
- * it was when sending the request, it will terminate the transfer normally.
- * If the client re-reads the size, it will think the friend cancelled the
- * transfer.
- * - If the file size was decreased
- * - and sending mode was streaming, the behaviour is as expected.
- * - and sending mode was file, the callback will return 0 at the new
- * (earlier) end-of-file, signalling to the friend that the transfer was
- * cancelled.
- * - If the file contents were modified
- * - at a position before the current read, the two files (local and remote)
- * will differ after the transfer terminates.
- * - at a position after the current read, the file transfer will succeed as
- * expected.
- * - In either case, both sides will regard the transfer as complete and
- * successful.
- *
- * @param friend_number The friend number of the friend the file send request
- * should be sent to.
- * @param kind The meaning of the file to be sent.
- * @param file_size Size in bytes of the file the client wants to send, UINT64_MAX if
- * unknown or streaming.
- * @param file_id A file identifier of length TOX_FILE_ID_LENGTH that can be used to
- * uniquely identify file transfers across core restarts. If NULL, a random one will
- * be generated by core. It can then be obtained by using tox_file_get_file_id().
- * @param filename Name of the file. Does not need to be the actual name. This
- * name will be sent along with the file send request.
- * @param filename_length Size in bytes of the filename.
- *
- * @return A file number used as an identifier in subsequent callbacks. This
- * number is per friend. File numbers are reused after a transfer terminates.
- * On failure, this function returns UINT32_MAX. Any pattern in file numbers
- * should not be relied on.
- */
-uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id,
- const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error);
-
-typedef enum TOX_ERR_FILE_SEND_CHUNK {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FILE_SEND_CHUNK_OK,
-
- /**
- * The length parameter was non-zero, but data was NULL.
- */
- TOX_ERR_FILE_SEND_CHUNK_NULL,
-
- /**
- * The friend_number passed did not designate a valid friend.
- */
- TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED,
-
- /**
- * No file transfer with the given file number was found for the given friend.
- */
- TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND,
-
- /**
- * File transfer was found but isn't in a transferring state: (paused, done,
- * broken, etc...) (happens only when not called from the request chunk callback).
- */
- TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING,
-
- /**
- * Attempted to send more or less data than requested. The requested data size is
- * adjusted according to maximum transmission unit and the expected end of
- * the file. Trying to send less or more than requested will return this error.
- */
- TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH,
-
- /**
- * Packet queue is full.
- */
- TOX_ERR_FILE_SEND_CHUNK_SENDQ,
-
- /**
- * Position parameter was wrong.
- */
- TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION,
-
-} TOX_ERR_FILE_SEND_CHUNK;
-
-
-/**
- * Send a chunk of file data to a friend.
- *
- * This function is called in response to the `file_chunk_request` callback. The
- * length parameter should be equal to the one received though the callback.
- * If it is zero, the transfer is assumed complete. For files with known size,
- * Core will know that the transfer is complete after the last byte has been
- * received, so it is not necessary (though not harmful) to send a zero-length
- * chunk to terminate. For streams, core will know that the transfer is finished
- * if a chunk with length less than the length requested in the callback is sent.
- *
- * @param friend_number The friend number of the receiving friend for this file.
- * @param file_number The file transfer identifier returned by tox_file_send.
- * @param position The file or stream position from which to continue reading.
- * @return true on success.
- */
-bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data,
- size_t length, TOX_ERR_FILE_SEND_CHUNK *error);
-
-/**
- * If the length parameter is 0, the file transfer is finished, and the client's
- * resources associated with the file number should be released. After a call
- * with zero length, the file number can be reused for future file transfers.
- *
- * If the requested position is not equal to the client's idea of the current
- * file or stream position, it will need to seek. In case of read-once streams,
- * the client should keep the last read chunk so that a seek back can be
- * supported. A seek-back only ever needs to read from the last requested chunk.
- * This happens when a chunk was requested, but the send failed. A seek-back
- * request can occur an arbitrary number of times for any given chunk.
- *
- * In response to receiving this callback, the client should call the function
- * `tox_file_send_chunk` with the requested chunk. If the number of bytes sent
- * through that function is zero, the file transfer is assumed complete. A
- * client must send the full length of data requested with this callback.
- *
- * @param friend_number The friend number of the receiving friend for this file.
- * @param file_number The file transfer identifier returned by tox_file_send.
- * @param position The file or stream position from which to continue reading.
- * @param length The number of bytes requested for the current chunk.
- */
-typedef void tox_file_chunk_request_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `file_chunk_request` event. Pass NULL to unset.
- *
- * This event is triggered when Core is ready to send more file data.
- */
-void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: File transmission: receiving
- *
- ******************************************************************************/
-
-
-
-/**
- * The client should acquire resources to be associated with the file transfer.
- * Incoming file transfers start in the PAUSED state. After this callback
- * returns, a transfer can be rejected by sending a TOX_FILE_CONTROL_CANCEL
- * control command before any other control commands. It can be accepted by
- * sending TOX_FILE_CONTROL_RESUME.
- *
- * @param friend_number The friend number of the friend who is sending the file
- * transfer request.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param kind The meaning of the file to be sent.
- * @param file_size Size in bytes of the file the client wants to send,
- * UINT64_MAX if unknown or streaming.
- * @param filename Name of the file. Does not need to be the actual name. This
- * name will be sent along with the file send request.
- * @param filename_length Size in bytes of the filename.
- */
-typedef void tox_file_recv_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t file_size,
- const uint8_t *filename, size_t filename_length, void *user_data);
-
-
-/**
- * Set the callback for the `file_recv` event. Pass NULL to unset.
- *
- * This event is triggered when a file transfer request is received.
- */
-void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *callback);
-
-/**
- * When length is 0, the transfer is finished and the client should release the
- * resources it acquired for the transfer. After a call with length = 0, the
- * file number can be reused for new file transfers.
- *
- * If position is equal to file_size (received in the file_receive callback)
- * when the transfer finishes, the file was received completely. Otherwise, if
- * file_size was UINT64_MAX, streaming ended successfully when length is 0.
- *
- * @param friend_number The friend number of the friend who is sending the file.
- * @param file_number The friend-specific file number the data received is
- * associated with.
- * @param position The file position of the first byte in data.
- * @param data A byte array containing the received chunk.
- * @param length The length of the received chunk.
- */
-typedef void tox_file_recv_chunk_cb(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
- const uint8_t *data, size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `file_recv_chunk` event. Pass NULL to unset.
- *
- * This event is first triggered when a file transfer request is received, and
- * subsequently when a chunk of file data for an accepted request was received.
- */
-void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: Conference management
- *
- ******************************************************************************/
-
-
-
-/**
- * Conference types for the conference_invite event.
- */
-typedef enum TOX_CONFERENCE_TYPE {
-
- /**
- * Text-only conferences that must be accepted with the tox_conference_join function.
- */
- TOX_CONFERENCE_TYPE_TEXT,
-
- /**
- * Video conference. The function to accept these is in toxav.
- */
- TOX_CONFERENCE_TYPE_AV,
-
-} TOX_CONFERENCE_TYPE;
-
-
-/**
- * The invitation will remain valid until the inviting friend goes offline
- * or exits the conference.
- *
- * @param friend_number The friend who invited us.
- * @param type The conference type (text only or audio/video).
- * @param cookie A piece of data of variable length required to join the
- * conference.
- * @param length The length of the cookie.
- */
-typedef void tox_conference_invite_cb(Tox *tox, uint32_t friend_number, TOX_CONFERENCE_TYPE type, const uint8_t *cookie,
- size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `conference_invite` event. Pass NULL to unset.
- *
- * This event is triggered when the client is invited to join a conference.
- */
-void tox_callback_conference_invite(Tox *tox, tox_conference_invite_cb *callback);
-
-/**
- * @param conference_number The conference number of the conference the message is intended for.
- * @param peer_number The ID of the peer who sent the message.
- * @param type The type of message (normal, action, ...).
- * @param message The message data.
- * @param length The length of the message.
- */
-typedef void tox_conference_message_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `conference_message` event. Pass NULL to unset.
- *
- * This event is triggered when the client receives a conference message.
- */
-void tox_callback_conference_message(Tox *tox, tox_conference_message_cb *callback);
-
-/**
- * @param conference_number The conference number of the conference the title change is intended for.
- * @param peer_number The ID of the peer who changed the title.
- * @param title The title data.
- * @param length The title length.
- */
-typedef void tox_conference_title_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number, const uint8_t *title,
- size_t length, void *user_data);
-
-
-/**
- * Set the callback for the `conference_title` event. Pass NULL to unset.
- *
- * This event is triggered when a peer changes the conference title.
- *
- * If peer_number == UINT32_MAX, then author is unknown (e.g. initial joining the conference).
- */
-void tox_callback_conference_title(Tox *tox, tox_conference_title_cb *callback);
-
-/**
- * Peer list state change types.
- */
-typedef enum TOX_CONFERENCE_STATE_CHANGE {
-
- /**
- * A peer has joined the conference.
- */
- TOX_CONFERENCE_STATE_CHANGE_PEER_JOIN,
-
- /**
- * A peer has exited the conference.
- */
- TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT,
-
- /**
- * A peer has changed their name.
- */
- TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE,
-
-} TOX_CONFERENCE_STATE_CHANGE;
-
-
-/**
- * @param conference_number The conference number of the conference the title change is intended for.
- * @param peer_number The ID of the peer who changed the title.
- * @param change The type of change (one of TOX_CONFERENCE_STATE_CHANGE).
- */
-typedef void tox_conference_namelist_change_cb(Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_CONFERENCE_STATE_CHANGE change, void *user_data);
-
-
-/**
- * Set the callback for the `conference_namelist_change` event. Pass NULL to unset.
- *
- * This event is triggered when the peer list changes (name change, peer join, peer exit).
- */
-void tox_callback_conference_namelist_change(Tox *tox, tox_conference_namelist_change_cb *callback);
-
-typedef enum TOX_ERR_CONFERENCE_NEW {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_NEW_OK,
-
- /**
- * The conference instance failed to initialize.
- */
- TOX_ERR_CONFERENCE_NEW_INIT,
-
-} TOX_ERR_CONFERENCE_NEW;
-
-
-/**
- * Creates a new conference.
- *
- * This function creates a new text conference.
- *
- * @return conference number on success, or UINT32_MAX on failure.
- */
-uint32_t tox_conference_new(Tox *tox, TOX_ERR_CONFERENCE_NEW *error);
-
-typedef enum TOX_ERR_CONFERENCE_DELETE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_DELETE_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_DELETE_CONFERENCE_NOT_FOUND,
-
-} TOX_ERR_CONFERENCE_DELETE;
-
-
-/**
- * This function deletes a conference.
- *
- * @param conference_number The conference number of the conference to be deleted.
- *
- * @return true on success.
- */
-bool tox_conference_delete(Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_DELETE *error);
-
-/**
- * Error codes for peer info queries.
- */
-typedef enum TOX_ERR_CONFERENCE_PEER_QUERY {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_PEER_QUERY_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_PEER_QUERY_CONFERENCE_NOT_FOUND,
-
- /**
- * The peer number passed did not designate a valid peer.
- */
- TOX_ERR_CONFERENCE_PEER_QUERY_PEER_NOT_FOUND,
-
- /**
- * The client is not connected to the conference.
- */
- TOX_ERR_CONFERENCE_PEER_QUERY_NO_CONNECTION,
-
-} TOX_ERR_CONFERENCE_PEER_QUERY;
-
-
-/**
- * Return the number of peers in the conference. Return value is unspecified on failure.
- */
-uint32_t tox_conference_peer_count(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_PEER_QUERY *error);
-
-/**
- * Return the length of the peer's name. Return value is unspecified on failure.
- */
-size_t tox_conference_peer_get_name_size(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_ERR_CONFERENCE_PEER_QUERY *error);
-
-/**
- * Copy the name of peer_number who is in conference_number to name.
- * name must be at least TOX_MAX_NAME_LENGTH long.
- *
- * @return true on success.
- */
-bool tox_conference_peer_get_name(const Tox *tox, uint32_t conference_number, uint32_t peer_number, uint8_t *name,
- TOX_ERR_CONFERENCE_PEER_QUERY *error);
-
-/**
- * Copy the public key of peer_number who is in conference_number to public_key.
- * public_key must be TOX_PUBLIC_KEY_SIZE long.
- *
- * @return true on success.
- */
-bool tox_conference_peer_get_public_key(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- uint8_t *public_key, TOX_ERR_CONFERENCE_PEER_QUERY *error);
-
-/**
- * Return true if passed peer_number corresponds to our own.
- */
-bool tox_conference_peer_number_is_ours(const Tox *tox, uint32_t conference_number, uint32_t peer_number,
- TOX_ERR_CONFERENCE_PEER_QUERY *error);
-
-typedef enum TOX_ERR_CONFERENCE_INVITE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_INVITE_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_INVITE_CONFERENCE_NOT_FOUND,
-
- /**
- * The invite packet failed to send.
- */
- TOX_ERR_CONFERENCE_INVITE_FAIL_SEND,
-
-} TOX_ERR_CONFERENCE_INVITE;
-
-
-/**
- * Invites a friend to a conference.
- *
- * @param friend_number The friend number of the friend we want to invite.
- * @param conference_number The conference number of the conference we want to invite the friend to.
- *
- * @return true on success.
- */
-bool tox_conference_invite(Tox *tox, uint32_t friend_number, uint32_t conference_number,
- TOX_ERR_CONFERENCE_INVITE *error);
-
-typedef enum TOX_ERR_CONFERENCE_JOIN {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_JOIN_OK,
-
- /**
- * The cookie passed has an invalid length.
- */
- TOX_ERR_CONFERENCE_JOIN_INVALID_LENGTH,
-
- /**
- * The conference is not the expected type. This indicates an invalid cookie.
- */
- TOX_ERR_CONFERENCE_JOIN_WRONG_TYPE,
-
- /**
- * The friend number passed does not designate a valid friend.
- */
- TOX_ERR_CONFERENCE_JOIN_FRIEND_NOT_FOUND,
-
- /**
- * Client is already in this conference.
- */
- TOX_ERR_CONFERENCE_JOIN_DUPLICATE,
-
- /**
- * Conference instance failed to initialize.
- */
- TOX_ERR_CONFERENCE_JOIN_INIT_FAIL,
-
- /**
- * The join packet failed to send.
- */
- TOX_ERR_CONFERENCE_JOIN_FAIL_SEND,
-
-} TOX_ERR_CONFERENCE_JOIN;
-
-
-/**
- * Joins a conference that the client has been invited to.
- *
- * @param friend_number The friend number of the friend who sent the invite.
- * @param cookie Received via the `conference_invite` event.
- * @param length The size of cookie.
- *
- * @return conference number on success, UINT32_MAX on failure.
- */
-uint32_t tox_conference_join(Tox *tox, uint32_t friend_number, const uint8_t *cookie, size_t length,
- TOX_ERR_CONFERENCE_JOIN *error);
-
-typedef enum TOX_ERR_CONFERENCE_SEND_MESSAGE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_SEND_MESSAGE_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_SEND_MESSAGE_CONFERENCE_NOT_FOUND,
-
- /**
- * The message is too long.
- */
- TOX_ERR_CONFERENCE_SEND_MESSAGE_TOO_LONG,
-
- /**
- * The client is not connected to the conference.
- */
- TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION,
-
- /**
- * The message packet failed to send.
- */
- TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND,
-
-} TOX_ERR_CONFERENCE_SEND_MESSAGE;
-
-
-/**
- * Send a text chat message to the conference.
- *
- * This function creates a conference message packet and pushes it into the send
- * queue.
- *
- * The message length may not exceed TOX_MAX_MESSAGE_LENGTH. Larger messages
- * must be split by the client and sent as separate messages. Other clients can
- * then reassemble the fragments.
- *
- * @param conference_number The conference number of the conference the message is intended for.
- * @param type Message type (normal, action, ...).
- * @param message A non-NULL pointer to the first element of a byte array
- * containing the message text.
- * @param length Length of the message to be sent.
- *
- * @return true on success.
- */
-bool tox_conference_send_message(Tox *tox, uint32_t conference_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
- size_t length, TOX_ERR_CONFERENCE_SEND_MESSAGE *error);
-
-typedef enum TOX_ERR_CONFERENCE_TITLE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_TITLE_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_TITLE_CONFERENCE_NOT_FOUND,
-
- /**
- * The title is too long or empty.
- */
- TOX_ERR_CONFERENCE_TITLE_INVALID_LENGTH,
-
- /**
- * The title packet failed to send.
- */
- TOX_ERR_CONFERENCE_TITLE_FAIL_SEND,
-
-} TOX_ERR_CONFERENCE_TITLE;
-
-
-/**
- * Return the length of the conference title. Return value is unspecified on failure.
- *
- * The return value is equal to the `length` argument received by the last
- * `conference_title` callback.
- */
-size_t tox_conference_get_title_size(const Tox *tox, uint32_t conference_number, TOX_ERR_CONFERENCE_TITLE *error);
-
-/**
- * Write the title designated by the given conference number to a byte array.
- *
- * Call tox_conference_get_title_size to determine the allocation size for the `title` parameter.
- *
- * The data written to `title` is equal to the data received by the last
- * `conference_title` callback.
- *
- * @param title A valid memory region large enough to store the title.
- * If this parameter is NULL, this function has no effect.
- *
- * @return true on success.
- */
-bool tox_conference_get_title(const Tox *tox, uint32_t conference_number, uint8_t *title,
- TOX_ERR_CONFERENCE_TITLE *error);
-
-/**
- * Set the conference title and broadcast it to the rest of the conference.
- *
- * Title length cannot be longer than TOX_MAX_NAME_LENGTH.
- *
- * @return true on success.
- */
-bool tox_conference_set_title(Tox *tox, uint32_t conference_number, const uint8_t *title, size_t length,
- TOX_ERR_CONFERENCE_TITLE *error);
-
-/**
- * Return the number of conferences in the Tox instance.
- * This should be used to determine how much memory to allocate for `tox_conference_get_chatlist`.
- */
-size_t tox_conference_get_chatlist_size(const Tox *tox);
-
-/**
- * Copy a list of valid conference IDs into the array chatlist. Determine how much space
- * to allocate for the array with the `tox_conference_get_chatlist_size` function.
- */
-void tox_conference_get_chatlist(const Tox *tox, uint32_t *chatlist);
-
-/**
- * Returns the type of conference (TOX_CONFERENCE_TYPE) that conference_number is. Return value is
- * unspecified on failure.
- */
-typedef enum TOX_ERR_CONFERENCE_GET_TYPE {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_CONFERENCE_GET_TYPE_OK,
-
- /**
- * The conference number passed did not designate a valid conference.
- */
- TOX_ERR_CONFERENCE_GET_TYPE_CONFERENCE_NOT_FOUND,
-
-} TOX_ERR_CONFERENCE_GET_TYPE;
-
-
-TOX_CONFERENCE_TYPE tox_conference_get_type(const Tox *tox, uint32_t conference_number,
- TOX_ERR_CONFERENCE_GET_TYPE *error);
-
-
-/*******************************************************************************
- *
- * :: Low-level custom packet sending and receiving
- *
- ******************************************************************************/
-
-
-
-typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_NULL,
-
- /**
- * The friend number did not designate a valid friend.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND,
-
- /**
- * This client is currently not connected to the friend.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED,
-
- /**
- * The first byte of data was not in the specified range for the packet type.
- * This range is 200-254 for lossy, and 160-191 for lossless packets.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID,
-
- /**
- * Attempted to send an empty packet.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY,
-
- /**
- * Packet data length exceeded TOX_MAX_CUSTOM_PACKET_SIZE.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG,
-
- /**
- * Packet queue is full.
- */
- TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ,
-
-} TOX_ERR_FRIEND_CUSTOM_PACKET;
-
-
-/**
- * Send a custom lossy packet to a friend.
- *
- * The first byte of data must be in the range 200-254. Maximum length of a
- * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
- *
- * Lossy packets behave like UDP packets, meaning they might never reach the
- * other side or might arrive more than once (if someone is messing with the
- * connection) or might arrive in the wrong order.
- *
- * Unless latency is an issue, it is recommended that you use lossless custom
- * packets instead.
- *
- * @param friend_number The friend number of the friend this lossy packet
- * should be sent to.
- * @param data A byte array containing the packet data.
- * @param length The length of the packet data byte array.
- *
- * @return true on success.
- */
-bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- TOX_ERR_FRIEND_CUSTOM_PACKET *error);
-
-/**
- * Send a custom lossless packet to a friend.
- *
- * The first byte of data must be in the range 160-191. Maximum length of a
- * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE.
- *
- * Lossless packet behaviour is comparable to TCP (reliability, arrive in order)
- * but with packets instead of a stream.
- *
- * @param friend_number The friend number of the friend this lossless packet
- * should be sent to.
- * @param data A byte array containing the packet data.
- * @param length The length of the packet data byte array.
- *
- * @return true on success.
- */
-bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- TOX_ERR_FRIEND_CUSTOM_PACKET *error);
-
-/**
- * @param friend_number The friend number of the friend who sent a lossy packet.
- * @param data A byte array containing the received packet data.
- * @param length The length of the packet data byte array.
- */
-typedef void tox_friend_lossy_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data);
-
-
-/**
- * Set the callback for the `friend_lossy_packet` event. Pass NULL to unset.
- *
- */
-void tox_callback_friend_lossy_packet(Tox *tox, tox_friend_lossy_packet_cb *callback);
-
-/**
- * @param friend_number The friend number of the friend who sent the packet.
- * @param data A byte array containing the received packet data.
- * @param length The length of the packet data byte array.
- */
-typedef void tox_friend_lossless_packet_cb(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length,
- void *user_data);
-
-
-/**
- * Set the callback for the `friend_lossless_packet` event. Pass NULL to unset.
- *
- */
-void tox_callback_friend_lossless_packet(Tox *tox, tox_friend_lossless_packet_cb *callback);
-
-
-/*******************************************************************************
- *
- * :: Low-level network information
- *
- ******************************************************************************/
-
-
-
-/**
- * Writes the temporary DHT public key of this instance to a byte array.
- *
- * This can be used in combination with an externally accessible IP address and
- * the bound port (from tox_self_get_udp_port) to run a temporary bootstrap node.
- *
- * Be aware that every time a new instance is created, the DHT public key
- * changes, meaning this cannot be used to run a permanent bootstrap node.
- *
- * @param dht_id A memory region of at least TOX_PUBLIC_KEY_SIZE bytes. If this
- * parameter is NULL, this function has no effect.
- */
-void tox_self_get_dht_id(const Tox *tox, uint8_t *dht_id);
-
-typedef enum TOX_ERR_GET_PORT {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_GET_PORT_OK,
-
- /**
- * The instance was not bound to any port.
- */
- TOX_ERR_GET_PORT_NOT_BOUND,
-
-} TOX_ERR_GET_PORT;
-
-
-/**
- * Return the UDP port this Tox instance is bound to.
- */
-uint16_t tox_self_get_udp_port(const Tox *tox, TOX_ERR_GET_PORT *error);
-
-/**
- * Return the TCP port this Tox instance is bound to. This is only relevant if
- * the instance is acting as a TCP relay.
- */
-uint16_t tox_self_get_tcp_port(const Tox *tox, TOX_ERR_GET_PORT *error);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxcore/tox_api.c b/libs/libtox/src/toxcore/tox_api.c
deleted file mode 100644
index b6c8c38618..0000000000
--- a/libs/libtox/src/toxcore/tox_api.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "tox.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
-
-
-#define CONST_FUNCTION(lowercase, uppercase) \
-uint32_t tox_##lowercase(void) \
-{ \
- return TOX_##uppercase; \
-}
-
-CONST_FUNCTION(version_major, VERSION_MAJOR)
-CONST_FUNCTION(version_minor, VERSION_MINOR)
-CONST_FUNCTION(version_patch, VERSION_PATCH)
-CONST_FUNCTION(public_key_size, PUBLIC_KEY_SIZE)
-CONST_FUNCTION(secret_key_size, SECRET_KEY_SIZE)
-CONST_FUNCTION(address_size, ADDRESS_SIZE)
-CONST_FUNCTION(max_name_length, MAX_NAME_LENGTH)
-CONST_FUNCTION(max_status_message_length, MAX_STATUS_MESSAGE_LENGTH)
-CONST_FUNCTION(max_friend_request_length, MAX_FRIEND_REQUEST_LENGTH)
-CONST_FUNCTION(max_message_length, MAX_MESSAGE_LENGTH)
-CONST_FUNCTION(max_custom_packet_size, MAX_CUSTOM_PACKET_SIZE)
-CONST_FUNCTION(hash_length, HASH_LENGTH)
-CONST_FUNCTION(file_id_length, FILE_ID_LENGTH)
-CONST_FUNCTION(max_filename_length, MAX_FILENAME_LENGTH)
-
-
-#define ACCESSORS(type, ns, name) \
-type tox_options_get_##ns##name(const struct Tox_Options *options) \
-{ \
- return options->ns##name; \
-} \
-void tox_options_set_##ns##name(struct Tox_Options *options, type name) \
-{ \
- options->ns##name = name; \
-}
-
-ACCESSORS(bool, , ipv6_enabled)
-ACCESSORS(bool, , udp_enabled)
-ACCESSORS(TOX_PROXY_TYPE, proxy_ , type)
-ACCESSORS(const char *, proxy_ , host)
-ACCESSORS(uint16_t, proxy_ , port)
-ACCESSORS(uint16_t, , start_port)
-ACCESSORS(uint16_t, , end_port)
-ACCESSORS(uint16_t, , tcp_port)
-ACCESSORS(bool, , hole_punching_enabled)
-ACCESSORS(TOX_SAVEDATA_TYPE, savedata_, type)
-ACCESSORS(size_t, savedata_, length)
-ACCESSORS(tox_log_cb *, log_, callback)
-ACCESSORS(void *, log_, user_data)
-ACCESSORS(bool, , local_discovery_enabled)
-
-const uint8_t *tox_options_get_savedata_data(const struct Tox_Options *options)
-{
- return options->savedata_data;
-}
-
-void tox_options_set_savedata_data(struct Tox_Options *options, const uint8_t *data, size_t length)
-{
- options->savedata_data = data;
- options->savedata_length = length;
-}
-
-void tox_options_default(struct Tox_Options *options)
-{
- if (options) {
- struct Tox_Options default_options = { 0 };
- *options = default_options;
- tox_options_set_ipv6_enabled(options, true);
- tox_options_set_udp_enabled(options, true);
- tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE);
- tox_options_set_hole_punching_enabled(options, true);
- tox_options_set_local_discovery_enabled(options, true);
- }
-}
-
-struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error)
-{
- struct Tox_Options *options = (struct Tox_Options *)malloc(sizeof(struct Tox_Options));
-
- if (options) {
- tox_options_default(options);
- SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_OK);
- return options;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_OPTIONS_NEW_MALLOC);
- return NULL;
-}
-
-void tox_options_free(struct Tox_Options *options)
-{
- free(options);
-}
diff --git a/libs/libtox/src/toxcore/util.c b/libs/libtox/src/toxcore/util.c
deleted file mode 100644
index 5202598518..0000000000
--- a/libs/libtox/src/toxcore/util.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Utilities.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- * Copyright © 2013 plutooo
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- * This file is donated to the Tox Project.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _XOPEN_SOURCE 600
-
-#include "util.h"
-
-#include "crypto_core.h" /* for CRYPTO_PUBLIC_KEY_SIZE */
-#include "network.h" /* for current_time_monotonic */
-
-#include <time.h>
-
-
-/* don't call into system billions of times for no reason */
-static uint64_t unix_time_value;
-static uint64_t unix_base_time_value;
-
-/* XXX: note that this is not thread-safe; if multiple threads call unix_time_update() concurrently, the return value of
- * unix_time() may fail to increase monotonically with increasing time */
-void unix_time_update(void)
-{
- if (unix_base_time_value == 0) {
- unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL));
- }
-
- unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value;
-}
-
-uint64_t unix_time(void)
-{
- return unix_time_value;
-}
-
-int is_timeout(uint64_t timestamp, uint64_t timeout)
-{
- return timestamp + timeout <= unix_time();
-}
-
-
-/* id functions */
-bool id_equal(const uint8_t *dest, const uint8_t *src)
-{
- return public_key_cmp(dest, src) == 0;
-}
-
-uint32_t id_copy(uint8_t *dest, const uint8_t *src)
-{
- memcpy(dest, src, CRYPTO_PUBLIC_KEY_SIZE);
- return CRYPTO_PUBLIC_KEY_SIZE;
-}
-
-void host_to_net(uint8_t *num, uint16_t numbytes)
-{
-#ifndef WORDS_BIGENDIAN
- uint32_t i;
- VLA(uint8_t, buff, numbytes);
-
- for (i = 0; i < numbytes; ++i) {
- buff[i] = num[numbytes - i - 1];
- }
-
- memcpy(num, buff, numbytes);
-#endif
-}
-
-uint16_t lendian_to_host16(uint16_t lendian)
-{
-#ifdef WORDS_BIGENDIAN
- return (lendian << 8) | (lendian >> 8);
-#else
- return lendian;
-#endif
-}
-
-void host_to_lendian32(uint8_t *dest, uint32_t num)
-{
-#ifdef WORDS_BIGENDIAN
- num = ((num << 8) & 0xFF00FF00) | ((num >> 8) & 0xFF00FF);
- num = (num << 16) | (num >> 16);
-#endif
- memcpy(dest, &num, sizeof(uint32_t));
-}
-
-void lendian_to_host32(uint32_t *dest, const uint8_t *lendian)
-{
- uint32_t d;
- memcpy(&d, lendian, sizeof(uint32_t));
-#ifdef WORDS_BIGENDIAN
- d = ((d << 8) & 0xFF00FF00) | ((d >> 8) & 0xFF00FF);
- d = (d << 16) | (d >> 16);
-#endif
- *dest = d;
-}
-
-/* state load/save */
-int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
- const uint8_t *data, uint32_t length, uint16_t cookie_inner)
-{
- if (!load_state_callback || !data) {
- LOGGER_ERROR(log, "load_state() called with invalid args.\n");
- return -1;
- }
-
-
- uint16_t type;
- uint32_t length_sub, cookie_type;
- uint32_t size_head = sizeof(uint32_t) * 2;
-
- while (length >= size_head) {
- lendian_to_host32(&length_sub, data);
- lendian_to_host32(&cookie_type, data + sizeof(length_sub));
- data += size_head;
- length -= size_head;
-
- if (length < length_sub) {
- /* file truncated */
- LOGGER_ERROR(log, "state file too short: %u < %u\n", length, length_sub);
- return -1;
- }
-
- if (lendian_to_host16((cookie_type >> 16)) != cookie_inner) {
- /* something is not matching up in a bad way, give up */
- LOGGER_ERROR(log, "state file garbled: %04x != %04x\n", (cookie_type >> 16), cookie_inner);
- return -1;
- }
-
- type = lendian_to_host16(cookie_type & 0xFFFF);
-
- int ret = load_state_callback(outer, data, length_sub, type);
-
- if (ret == -1) {
- return -1;
- }
-
- /* -2 means end of save. */
- if (ret == -2) {
- return 0;
- }
-
- data += length_sub;
- length -= length_sub;
- }
-
- return length == 0 ? 0 : -1;
-}
-
-int create_recursive_mutex(pthread_mutex_t *mutex)
-{
- pthread_mutexattr_t attr;
-
- if (pthread_mutexattr_init(&attr) != 0) {
- return -1;
- }
-
- if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
- pthread_mutexattr_destroy(&attr);
- return -1;
- }
-
- if (pthread_mutex_init(mutex, &attr) != 0) {
- pthread_mutexattr_destroy(&attr);
- return -1;
- }
-
- pthread_mutexattr_destroy(&attr);
-
- return 0;
-}
diff --git a/libs/libtox/src/toxcore/util.h b/libs/libtox/src/toxcore/util.h
deleted file mode 100644
index 6ef9a75f8c..0000000000
--- a/libs/libtox/src/toxcore/util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Utilities.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- * Copyright © 2013 plutooo
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- * This file is donated to the Tox Project.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef UTIL_H
-#define UTIL_H
-
-#include <pthread.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "logger.h"
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define PAIR(TYPE1__, TYPE2__) struct { TYPE1__ first; TYPE2__ second; }
-
-void unix_time_update(void);
-uint64_t unix_time(void);
-int is_timeout(uint64_t timestamp, uint64_t timeout);
-
-
-/* id functions */
-bool id_equal(const uint8_t *dest, const uint8_t *src);
-uint32_t id_copy(uint8_t *dest, const uint8_t *src); /* return value is CLIENT_ID_SIZE */
-
-void host_to_net(uint8_t *num, uint16_t numbytes);
-#define net_to_host(x, y) host_to_net(x, y)
-
-uint16_t lendian_to_host16(uint16_t lendian);
-#define host_tolendian16(x) lendian_to_host16(x)
-
-void host_to_lendian32(uint8_t *dest, uint32_t num);
-void lendian_to_host32(uint32_t *dest, const uint8_t *lendian);
-
-/* state load/save */
-typedef int (*load_state_callback_func)(void *outer, const uint8_t *data, uint32_t len, uint16_t type);
-int load_state(load_state_callback_func load_state_callback, Logger *log, void *outer,
- const uint8_t *data, uint32_t length, uint16_t cookie_inner);
-
-/* Returns -1 if failed or 0 if success */
-//int create_recursive_mutex(pthread_mutex_t *mutex);
-
-#endif /* UTIL_H */
diff --git a/libs/libtox/src/toxdns/Makefile.inc b/libs/libtox/src/toxdns/Makefile.inc
deleted file mode 100644
index 5b7c012320..0000000000
--- a/libs/libtox/src/toxdns/Makefile.inc
+++ /dev/null
@@ -1,35 +0,0 @@
-lib_LTLIBRARIES += libtoxdns.la
-
-libtoxdns_la_include_HEADERS = \
- ../toxdns/toxdns.h
-
-libtoxdns_la_includedir = $(includedir)/tox
-
-libtoxdns_la_SOURCES = ../toxdns/toxdns.h \
- ../toxdns/toxdns.c
-
-libtoxdns_la_CFLAGS = -I$(top_srcdir) \
- -I$(top_srcdir)/toxcore \
- $(LIBSODIUM_CFLAGS) \
- $(NACL_CFLAGS) \
- $(PTHREAD_CFLAGS)
-
-libtoxdns_la_LDFLAGS = $(LT_LDFLAGS) \
- $(EXTRA_LT_LDFLAGS) \
- $(LIBSODIUM_LDFLAGS) \
- $(NACL_LDFLAGS) \
- $(MATH_LDFLAGS) \
- $(RT_LIBS) \
- $(WINSOCK2_LIBS)
-
-libtoxdns_la_LIBADD = $(LIBSODIUM_LIBS) \
- $(NACL_OBJECTS) \
- $(NAC_LIBS) \
- $(PTHREAD_LIBS) \
- libtoxcore.la
-
-if SET_SO_VERSION
-
-EXTRA_libtoxdns_la_DEPENDENCIES = ../so.version
-
-endif
diff --git a/libs/libtox/src/toxdns/toxdns.c b/libs/libtox/src/toxdns/toxdns.c
deleted file mode 100644
index 96f3081f80..0000000000
--- a/libs/libtox/src/toxdns/toxdns.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Tox secure username DNS toxid resolving functions.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "../toxcore/Messenger.h"
-#include "../toxcore/logger.h"
-#include "toxdns.h"
-
-static const char base32[32] = {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5',
-};
-
-#define _encode(a, b, c) \
-{ \
- uint8_t _i = 0; \
- while (_i != c) { \
- *a++ = base32[((b[0] >> bits) | (b[1] << (8 - bits))) & 0x1F]; \
- bits += 5; \
- if(bits >= 8) { \
- bits -= 8; \
- b++; \
- _i++; \
- } \
- } \
-}
-
-typedef struct {
- uint8_t temp_pk[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t temp_sk[CRYPTO_SECRET_KEY_SIZE];
- uint8_t server_public_key[CRYPTO_PUBLIC_KEY_SIZE];
- uint8_t shared_key[CRYPTO_SYMMETRIC_KEY_SIZE];
- uint32_t nonce;
- uint32_t nonce_start;
-} DNS_Object;
-
-static void dns_new_temp_keys(DNS_Object *d)
-{
- d->nonce = d->nonce_start = random_int();
- crypto_new_keypair(d->temp_pk, d->temp_sk);
- encrypt_precompute(d->server_public_key, d->temp_sk, d->shared_key);
-}
-
-/* Create a new tox_dns3 object for server with server_public_key.
- *
- * return Null on failure.
- * return pointer object on success.
- */
-void *tox_dns3_new(uint8_t *server_public_key)
-{
- DNS_Object *d = (DNS_Object *)malloc(sizeof(DNS_Object));
-
- if (d == NULL) {
- return NULL;
- }
-
- memcpy(d->server_public_key, server_public_key, CRYPTO_PUBLIC_KEY_SIZE);
- dns_new_temp_keys(d);
- return d;
-}
-
-/* Destroy the tox dns3 object.
- */
-void tox_dns3_kill(void *dns3_object)
-{
- memset(dns3_object, 0, sizeof(DNS_Object));
- free(dns3_object);
-}
-
-/* Generate a dns3 string of string_max_len used to query the dns server referred to by to
- * dns3_object for a tox id registered to user with name of name_len.
- *
- * the uint32_t pointed by request_id will be set to the request id which must be passed to
- * tox_decrypt_dns3_TXT() to correctly decode the response.
- *
- * This is what the string returned looks like:
- * 4haaaaipr1o3mz0bxweox541airydbovqlbju51mb4p0ebxq.rlqdj4kkisbep2ks3fj2nvtmk4daduqiueabmexqva1jc
- *
- * returns length of string on success.
- * returns -1 on failure.
- */
-int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string_max_len, uint32_t *request_id,
- uint8_t *name, uint8_t name_len)
-{
-#define DOT_INTERVAL (6 * 5)
- int base = (sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + name_len + CRYPTO_MAC_SIZE);
- int end_len = ((base * 8) / 5) + (base / DOT_INTERVAL) + !!(base % 5);
- end_len -= !(base % DOT_INTERVAL);
-
- if (end_len > string_max_len) {
- return -1;
- }
-
- DNS_Object *d = (DNS_Object *)dns3_object;
- uint8_t buffer[1024];
- uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
- memcpy(nonce, &d->nonce, sizeof(uint32_t));
- memcpy(buffer, &d->nonce, sizeof(uint32_t));
- memcpy(buffer + sizeof(uint32_t), d->temp_pk, CRYPTO_PUBLIC_KEY_SIZE);
- int len = encrypt_data_symmetric(d->shared_key, nonce, name, name_len,
- buffer + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE);
-
- if (len == -1) {
- return -1;
- }
-
- int total_len = len + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE;
- uint8_t *buff = buffer, *old_str = string;
- buffer[total_len] = 0;
- uint8_t bits = 0;
- int i;
-
- for (i = !(total_len % DOT_INTERVAL); i < (total_len / DOT_INTERVAL); ++i) {
- _encode(string, buff, DOT_INTERVAL);
- *string = '.';
- ++string;
- }
-
- int left = total_len - (buff - buffer);
- _encode(string, buff, left);
-#undef DOT_INTERVAL
- *request_id = d->nonce;
- ++d->nonce;
-
- if (d->nonce == d->nonce_start) {
- dns_new_temp_keys(d);
- }
-
- if (end_len != string - old_str) {
- // TODO(iphydf): This currently has no access to a logger.
- LOGGER_ERROR(NULL, "tox_generate_dns3_string Fail, %u != %lu\n", end_len, string - old_str);
- return -1;
- }
-
- return string - old_str;
-}
-
-
-static int decode(uint8_t *dest, uint8_t *src)
-{
- uint8_t *p = src, *op = dest, bits = 0;
- *op = 0;
-
- while (*p) {
- uint8_t ch = *p++;
-
- if ('A' <= ch && ch <= 'Z') {
- ch = ch - 'A';
- } else if ('a' <= ch && ch <= 'z') {
- ch = ch - 'a';
- } else if ('0' <= ch && ch <= '5') {
- ch = ch - '0' + 26;
- } else {
- return - 1;
- }
-
- *op |= (ch << bits);
- bits += 5;
-
- if (bits >= 8) {
- bits -= 8;
- ++op;
- *op = (ch >> (5 - bits));
- }
- }
-
- return op - dest;
-}
-
-/* Decode and decrypt the id_record returned of length id_record_len into
- * tox_id (needs to be at least TOX_FRIEND_ADDRESS_SIZE).
- *
- * request_id is the request id given by tox_generate_dns3_string() when creating the request.
- *
- * the id_record passed to this function should look somewhat like this:
- * 2vgcxuycbuctvauik3plsv3d3aadv4zfjfhi3thaizwxinelrvigchv0ah3qjcsx5qhmaksb2lv2hm5cwbtx0yp
- *
- * returns -1 on failure.
- * returns 0 on success.
- *
- */
-int tox_decrypt_dns3_TXT(void *dns3_object, uint8_t *tox_id, uint8_t *id_record, uint32_t id_record_len,
- uint32_t request_id)
-{
- DNS_Object *d = (DNS_Object *)dns3_object;
-
- if (id_record_len != 87) {
- return -1;
- }
-
-#if 0
-
- if (id_record_len > 255 || id_record_len <= (sizeof(uint32_t) + CRYPTO_MAC_SIZE)) {
- return -1;
- }
-
-#endif
-
- VLA(uint8_t, id_record_null, id_record_len + 1);
- memcpy(id_record_null, id_record, id_record_len);
- id_record_null[id_record_len] = 0;
- VLA(uint8_t, data, id_record_len);
- int length = decode(data, id_record_null);
-
- if (length == -1) {
- return -1;
- }
-
- uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
- memcpy(nonce, &request_id, sizeof(uint32_t));
- nonce[sizeof(uint32_t)] = 1;
- int len = decrypt_data_symmetric(d->shared_key, nonce, data, length, tox_id);
-
- if (len != FRIEND_ADDRESS_SIZE) {
- return -1;
- }
-
- return 0;
-}
diff --git a/libs/libtox/src/toxdns/toxdns.h b/libs/libtox/src/toxdns/toxdns.h
deleted file mode 100644
index b280925eb1..0000000000
--- a/libs/libtox/src/toxdns/toxdns.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Tox secure username DNS toxid resolving functions.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2014 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOXDNS_H
-#define TOXDNS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-/* Clients are encouraged to set this as the maximum length names can have. */
-#define TOXDNS_MAX_RECOMMENDED_NAME_LENGTH 32
-
-/* How to use this api to make secure tox dns3 requests:
- *
- * 1. Get the public key of a server that supports tox dns3.
- * 2. use tox_dns3_new() to create a new object to create DNS requests
- * and handle responses for that server.
- * 3. Use tox_generate_dns3_string() to generate a string based on the name we want to query and a request_id
- * that must be stored somewhere for when we want to decrypt the response.
- * 4. take the string and use it for your DNS request like this:
- * _4haaaaipr1o3mz0bxweox541airydbovqlbju51mb4p0ebxq.rlqdj4kkisbep2ks3fj2nvtmk4daduqiueabmexqva1jc._tox.utox.org
- * 5. The TXT in the DNS you receive should look like this:
- * v=tox3;id=2vgcxuycbuctvauik3plsv3d3aadv4zfjfhi3thaizwxinelrvigchv0ah3qjcsx5qhmaksb2lv2hm5cwbtx0yp
- * 6. Take the id string and use it with tox_decrypt_dns3_TXT() and the request_id corresponding to the
- * request we stored earlier to get the Tox id returned by the DNS server.
- */
-
-/* Create a new tox_dns3 object for server with server_public_key of size TOX_CLIENT_ID_SIZE.
- *
- * return Null on failure.
- * return pointer object on success.
- */
-void *tox_dns3_new(uint8_t *server_public_key);
-
-/* Destroy the tox dns3 object.
- */
-void tox_dns3_kill(void *dns3_object);
-
-/* Generate a dns3 string of string_max_len used to query the dns server referred to by to
- * dns3_object for a tox id registered to user with name of name_len.
- *
- * the uint32_t pointed by request_id will be set to the request id which must be passed to
- * tox_decrypt_dns3_TXT() to correctly decode the response.
- *
- * This is what the string returned looks like:
- * 4haaaaipr1o3mz0bxweox541airydbovqlbju51mb4p0ebxq.rlqdj4kkisbep2ks3fj2nvtmk4daduqiueabmexqva1jc
- *
- * returns length of string on success.
- * returns -1 on failure.
- */
-int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string_max_len, uint32_t *request_id,
- uint8_t *name, uint8_t name_len);
-
-/* Decode and decrypt the id_record returned of length id_record_len into
- * tox_id (needs to be at least TOX_FRIEND_ADDRESS_SIZE).
- *
- * request_id is the request id given by tox_generate_dns3_string() when creating the request.
- *
- * the id_record passed to this function should look somewhat like this:
- * 2vgcxuycbuctvauik3plsv3d3aadv4zfjfhi3thaizwxinelrvigchv0ah3qjcsx5qhmaksb2lv2hm5cwbtx0yp
- *
- * returns -1 on failure.
- * returns 0 on success.
- *
- */
-int tox_decrypt_dns3_TXT(void *dns3_object, uint8_t *tox_id, uint8_t *id_record, uint32_t id_record_len,
- uint32_t request_id);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/Makefile.inc b/libs/libtox/src/toxencryptsave/Makefile.inc
deleted file mode 100644
index bde026cdaf..0000000000
--- a/libs/libtox/src/toxencryptsave/Makefile.inc
+++ /dev/null
@@ -1,55 +0,0 @@
-lib_LTLIBRARIES += libtoxencryptsave.la
-
-libtoxencryptsave_la_include_HEADERS = \
- ../toxencryptsave/toxencryptsave.h
-
-libtoxencryptsave_la_includedir = $(includedir)/tox
-
-libtoxencryptsave_la_SOURCES = ../toxencryptsave/toxencryptsave.h \
- ../toxencryptsave/toxencryptsave.c \
- ../toxencryptsave/defines.h
-
-
-if WITH_NACL
-libtoxencryptsave_la_SOURCES += ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c \
- ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
-endif
-
-libtoxencryptsave_la_CFLAGS = -I$(top_srcdir) \
- -I$(top_srcdir)/toxcore \
- $(LIBSODIUM_CFLAGS) \
- $(NACL_CFLAGS) \
- $(PTHREAD_CFLAGS)
-
-libtoxencryptsave_la_LDFLAGS = $(LT_LDFLAGS) \
- $(EXTRA_LT_LDFLAGS) \
- $(LIBSODIUM_LDFLAGS) \
- $(NACL_LDFLAGS) \
- $(MATH_LDFLAGS) \
- $(RT_LIBS) \
- $(WINSOCK2_LIBS)
-
-libtoxencryptsave_la_LIBADD = $(LIBSODIUM_LIBS) \
- $(NACL_OBJECTS) \
- $(NAC_LIBS) \
- $(PTHREAD_LIBS) \
- libtoxcore.la
-
-if SET_SO_VERSION
-
-EXTRA_libtoxencryptsave_la_DEPENDENCIES = ../so.version
-
-endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h
deleted file mode 100644
index 5cb32f8dcf..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef crypto_pwhash_scryptsalsa208sha256_H
-#define crypto_pwhash_scryptsalsa208sha256_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "export.h"
-
-#ifdef __cplusplus
-# if __GNUC__
-# pragma GCC diagnostic ignored "-Wlong-long"
-# endif
-extern "C" {
-#endif
-
-#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_saltbytes(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_STRBYTES 102U
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_strbytes(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_STRPREFIX "$7$"
-SODIUM_EXPORT
-const char *crypto_pwhash_scryptsalsa208sha256_strprefix(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 524288ULL
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 16777216ULL
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432ULL
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void);
-
-#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824ULL
-SODIUM_EXPORT
-size_t crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void);
-
-SODIUM_EXPORT
-int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
- unsigned long long outlen,
- const char * const passwd,
- unsigned long long passwdlen,
- const unsigned char * const salt,
- unsigned long long opslimit,
- size_t memlimit);
-
-SODIUM_EXPORT
-int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen,
- unsigned long long opslimit,
- size_t memlimit);
-
-SODIUM_EXPORT
-int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen);
-
-SODIUM_EXPORT
-int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
- const uint8_t * salt, size_t saltlen,
- uint64_t N, uint32_t r, uint32_t p,
- uint8_t * buf, size_t buflen);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Backward compatibility with version 0.5.0 */
-
-#define crypto_pwhash_scryptxsalsa208sha256_SALTBYTES crypto_pwhash_scryptsalsa208sha256_SALTBYTES
-#define crypto_pwhash_scryptxsalsa208sha256_saltbytes crypto_pwhash_scryptsalsa208sha256_saltbytes
-#define crypto_pwhash_scryptxsalsa208sha256_STRBYTES crypto_pwhash_scryptsalsa208sha256_STRBYTES
-#define crypto_pwhash_scryptxsalsa208sha256_strbytes crypto_pwhash_scryptsalsa208sha256_strbytes
-#define crypto_pwhash_scryptxsalsa208sha256 crypto_pwhash_scryptsalsa208sha256
-#define crypto_pwhash_scryptxsalsa208sha256_str crypto_pwhash_scryptsalsa208sha256_str
-#define crypto_pwhash_scryptxsalsa208sha256_str_verify crypto_pwhash_scryptsalsa208sha256_str_verify
-
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c
deleted file mode 100644
index 5a5c5525f3..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c
+++ /dev/null
@@ -1,257 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2013 Alexander Peslyak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdint.h>
-#include <string.h>
-
-#include "crypto_pwhash_scryptsalsa208sha256.h"
-#include "crypto_scrypt.h"
-#include "runtime.h"
-#include "utils.h"
-
-static const char * const itoa64 =
- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-static uint8_t *
-encode64_uint32(uint8_t * dst, size_t dstlen, uint32_t src, uint32_t srcbits)
-{
- uint32_t bit;
-
- for (bit = 0; bit < srcbits; bit += 6) {
- if (dstlen < 1) {
- return NULL;
- }
- *dst++ = itoa64[src & 0x3f];
- dstlen--;
- src >>= 6;
- }
-
- return dst;
-}
-
-static uint8_t *
-encode64(uint8_t * dst, size_t dstlen, const uint8_t * src, size_t srclen)
-{
- size_t i;
-
- for (i = 0; i < srclen; ) {
- uint8_t * dnext;
- uint32_t value = 0, bits = 0;
- do {
- value |= (uint32_t)src[i++] << bits;
- bits += 8;
- } while (bits < 24 && i < srclen);
- dnext = encode64_uint32(dst, dstlen, value, bits);
- if (!dnext) {
- return NULL;
- }
- dstlen -= dnext - dst;
- dst = dnext;
- }
-
- return dst;
-}
-
-static int
-decode64_one(uint32_t * dst, uint8_t src)
-{
- const char *ptr = strchr(itoa64, src);
-
- if (ptr) {
- *dst = ptr - itoa64;
- return 0;
- }
- *dst = 0;
- return -1;
-}
-
-static const uint8_t *
-decode64_uint32(uint32_t * dst, uint32_t dstbits, const uint8_t * src)
-{
- uint32_t bit;
- uint32_t value;
-
- value = 0;
- for (bit = 0; bit < dstbits; bit += 6) {
- uint32_t one;
- if (decode64_one(&one, *src)) {
- *dst = 0;
- return NULL;
- }
- src++;
- value |= one << bit;
- }
-
- *dst = value;
- return src;
-}
-
-uint8_t *
-escrypt_r(escrypt_local_t * local, const uint8_t * passwd, size_t passwdlen,
- const uint8_t * setting, uint8_t * buf, size_t buflen)
-{
- uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
- escrypt_kdf_t escrypt_kdf;
- const uint8_t *src;
- const uint8_t *salt;
- uint8_t *dst;
- size_t prefixlen;
- size_t saltlen;
- size_t need;
- uint64_t N;
- uint32_t N_log2;
- uint32_t r;
- uint32_t p;
-
- if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
- return NULL;
- }
- src = setting + 3;
-
- if (decode64_one(&N_log2, *src)) {
- return NULL;
- }
- src++;
- N = (uint64_t)1 << N_log2;
-
- src = decode64_uint32(&r, 30, src);
- if (!src) {
- return NULL;
- }
- src = decode64_uint32(&p, 30, src);
- if (!src) {
- return NULL;
- }
- prefixlen = src - setting;
-
- salt = src;
- src = (uint8_t *) strrchr((char *)salt, '$');
- if (src) {
- saltlen = src - salt;
- } else {
- saltlen = strlen((char *)salt);
- }
- need = prefixlen + saltlen + 1 +
- crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
- if (need > buflen || need < saltlen) {
- return NULL;
- }
-#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
- escrypt_kdf =
- sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
-#else
- escrypt_kdf = escrypt_kdf_nosse;
-#endif
- if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
- N, r, p, hash, sizeof(hash))) {
- return NULL;
- }
-
- dst = buf;
- memcpy(dst, setting, prefixlen + saltlen);
- dst += prefixlen + saltlen;
- *dst++ = '$';
-
- dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
- sodium_memzero(hash, sizeof hash);
- if (!dst || dst >= buf + buflen) { /* Can't happen */
- return NULL;
- }
- *dst = 0; /* NUL termination */
-
- return buf;
-}
-
-uint8_t *
-escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p,
- const uint8_t * src, size_t srclen,
- uint8_t * buf, size_t buflen)
-{
- uint8_t *dst;
- size_t prefixlen =
- (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
- size_t saltlen = BYTES2CHARS(srclen);
- size_t need;
-
- need = prefixlen + saltlen + 1;
- if (need > buflen || need < saltlen || saltlen < srclen) {
- return NULL;
- }
- if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) {
- return NULL;
- }
- dst = buf;
- *dst++ = '$';
- *dst++ = '7';
- *dst++ = '$';
-
- *dst++ = itoa64[N_log2];
-
- dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
- if (!dst) { /* Can't happen */
- return NULL;
- }
- dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
- if (!dst) { /* Can't happen */
- return NULL;
- }
- dst = encode64(dst, buflen - (dst - buf), src, srclen);
- if (!dst || dst >= buf + buflen) { /* Can't happen */
- return NULL;
- }
- *dst = 0; /* NUL termination */
-
- return buf;
-}
-
-int
-crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen,
- const uint8_t * salt, size_t saltlen,
- uint64_t N, uint32_t r, uint32_t p,
- uint8_t * buf, size_t buflen)
-{
- escrypt_kdf_t escrypt_kdf;
- escrypt_local_t local;
- int retval;
-
- if (escrypt_init_local(&local)) {
- return -1;
- }
-#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
- escrypt_kdf =
- sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
-#else
- escrypt_kdf = escrypt_kdf_nosse;
-#endif
- retval = escrypt_kdf(&local,
- passwd, passwdlen, salt, saltlen,
- N, r, p, buf, buflen);
- if (escrypt_free_local(&local)) {
- return -1;
- }
- return retval;
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h
deleted file mode 100644
index 3f0b7d72f5..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2009 Colin Percival
- * Copyright 2013 Alexander Peslyak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file was originally written by Colin Percival as part of the Tarsnap
- * online backup system.
- */
-#ifndef _CRYPTO_SCRYPT_H_
-#define _CRYPTO_SCRYPT_H_
-
-#include <stdint.h>
-
-#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14
-#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57
-#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32
-#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43
-#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32
-#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43
-
-#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6)
-
-typedef struct {
- void * base, * aligned;
- size_t size;
-} escrypt_region_t;
-
-typedef escrypt_region_t escrypt_local_t;
-
-extern int escrypt_init_local(escrypt_local_t * __local);
-
-extern int escrypt_free_local(escrypt_local_t * __local);
-
-extern void *alloc_region(escrypt_region_t * region, size_t size);
-extern int free_region(escrypt_region_t * region);
-
-typedef int (*escrypt_kdf_t)(escrypt_local_t * __local,
- const uint8_t * __passwd, size_t __passwdlen,
- const uint8_t * __salt, size_t __saltlen,
- uint64_t __N, uint32_t __r, uint32_t __p,
- uint8_t * __buf, size_t __buflen);
-
-extern int escrypt_kdf_nosse(escrypt_local_t * __local,
- const uint8_t * __passwd, size_t __passwdlen,
- const uint8_t * __salt, size_t __saltlen,
- uint64_t __N, uint32_t __r, uint32_t __p,
- uint8_t * __buf, size_t __buflen);
-
-extern int escrypt_kdf_sse(escrypt_local_t * __local,
- const uint8_t * __passwd, size_t __passwdlen,
- const uint8_t * __salt, size_t __saltlen,
- uint64_t __N, uint32_t __r, uint32_t __p,
- uint8_t * __buf, size_t __buflen);
-
-extern uint8_t * escrypt_r(escrypt_local_t * __local,
- const uint8_t * __passwd, size_t __passwdlen,
- const uint8_t * __setting,
- uint8_t * __buf, size_t __buflen);
-
-extern uint8_t * escrypt_gensalt_r(
- uint32_t __N_log2, uint32_t __r, uint32_t __p,
- const uint8_t * __src, size_t __srclen,
- uint8_t * __buf, size_t __buflen);
-
-#endif /* !_CRYPTO_SCRYPT_H_ */
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h
deleted file mode 100644
index ee5b30f7f1..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef __SODIUM_EXPORT_H__
-#define __SODIUM_EXPORT_H__
-
-#ifndef __GNUC__
-# ifdef __attribute__
-# undef __attribute__
-# endif
-# define __attribute__(a)
-#endif
-
-#ifdef SODIUM_STATIC
-# define SODIUM_EXPORT
-#else
-# if defined(_MSC_VER)
-# ifdef DLL_EXPORT
-# define SODIUM_EXPORT __declspec(dllexport)
-# else
-# define SODIUM_EXPORT __declspec(dllimport)
-# endif
-# else
-# if defined(__SUNPRO_C)
-# define SODIUM_EXPORT __attribute__ __global
-# elif defined(_MSG_VER)
-# define SODIUM_EXPORT extern __declspec(dllexport)
-# else
-# define SODIUM_EXPORT __attribute__ ((visibility ("default")))
-# endif
-# endif
-#endif
-
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
deleted file mode 100644
index 97d9ba6878..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
+++ /dev/null
@@ -1,309 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2009 Colin Percival
- * Copyright 2013 Alexander Peslyak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file was originally written by Colin Percival as part of the Tarsnap
- * online backup system.
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../pbkdf2-sha256.h"
-#include "../sysendian.h"
-#include "../crypto_scrypt.h"
-
-static inline void
-blkcpy(void * dest, const void * src, size_t len)
-{
- size_t * D = (size_t *) dest;
- const size_t * S = (const size_t *) src;
- size_t L = len / sizeof(size_t);
- size_t i;
-
- for (i = 0; i < L; i++)
- D[i] = S[i];
-}
-
-static inline void
-blkxor(void * dest, const void * src, size_t len)
-{
- size_t * D = (size_t *) dest;
- const size_t * S = (const size_t *) src;
- size_t L = len / sizeof(size_t);
- size_t i;
-
- for (i = 0; i < L; i++)
- D[i] ^= S[i];
-}
-
-/**
- * salsa20_8(B):
- * Apply the salsa20/8 core to the provided block.
- */
-static void
-salsa20_8(uint32_t B[16])
-{
- uint32_t x[16];
- size_t i;
-
- blkcpy(x, B, 64);
- for (i = 0; i < 8; i += 2) {
-#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
- /* Operate on columns. */
- x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
- x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
-
- x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
- x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
-
- x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
- x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
-
- x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
- x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
-
- /* Operate on rows. */
- x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
- x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
-
- x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
- x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
-
- x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
- x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
-
- x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
- x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
-#undef R
- }
- for (i = 0; i < 16; i++)
- B[i] += x[i];
-}
-
-/**
- * blockmix_salsa8(Bin, Bout, X, r):
- * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
- * bytes in length; the output Bout must also be the same size. The
- * temporary space X must be 64 bytes.
- */
-static void
-blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)
-{
- size_t i;
-
- /* 1: X <-- B_{2r - 1} */
- blkcpy(X, &Bin[(2 * r - 1) * 16], 64);
-
- /* 2: for i = 0 to 2r - 1 do */
- for (i = 0; i < 2 * r; i += 2) {
- /* 3: X <-- H(X \xor B_i) */
- blkxor(X, &Bin[i * 16], 64);
- salsa20_8(X);
-
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- blkcpy(&Bout[i * 8], X, 64);
-
- /* 3: X <-- H(X \xor B_i) */
- blkxor(X, &Bin[i * 16 + 16], 64);
- salsa20_8(X);
-
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- blkcpy(&Bout[i * 8 + r * 16], X, 64);
- }
-}
-
-/**
- * integerify(B, r):
- * Return the result of parsing B_{2r-1} as a little-endian integer.
- */
-static inline uint64_t
-integerify(const void * B, size_t r)
-{
- const uint32_t * X = (const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
-
- return (((uint64_t)(X[1]) << 32) + X[0]);
-}
-
-/**
- * smix(B, r, N, V, XY):
- * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
- * the temporary storage V must be 128rN bytes in length; the temporary
- * storage XY must be 256r + 64 bytes in length. The value N must be a
- * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
- * multiple of 64 bytes.
- */
-static void
-smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)
-{
- uint32_t * X = XY;
- uint32_t * Y = &XY[32 * r];
- uint32_t * Z = &XY[64 * r];
- uint64_t i;
- uint64_t j;
- size_t k;
-
- /* 1: X <-- B */
- for (k = 0; k < 32 * r; k++)
- X[k] = le32dec(&B[4 * k]);
-
- /* 2: for i = 0 to N - 1 do */
- for (i = 0; i < N; i += 2) {
- /* 3: V_i <-- X */
- blkcpy(&V[i * (32 * r)], X, 128 * r);
-
- /* 4: X <-- H(X) */
- blockmix_salsa8(X, Y, Z, r);
-
- /* 3: V_i <-- X */
- blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);
-
- /* 4: X <-- H(X) */
- blockmix_salsa8(Y, X, Z, r);
- }
-
- /* 6: for i = 0 to N - 1 do */
- for (i = 0; i < N; i += 2) {
- /* 7: j <-- Integerify(X) mod N */
- j = integerify(X, r) & (N - 1);
-
- /* 8: X <-- H(X \xor V_j) */
- blkxor(X, &V[j * (32 * r)], 128 * r);
- blockmix_salsa8(X, Y, Z, r);
-
- /* 7: j <-- Integerify(X) mod N */
- j = integerify(Y, r) & (N - 1);
-
- /* 8: X <-- H(X \xor V_j) */
- blkxor(Y, &V[j * (32 * r)], 128 * r);
- blockmix_salsa8(Y, X, Z, r);
- }
- /* 10: B' <-- X */
- for (k = 0; k < 32 * r; k++)
- le32enc(&B[4 * k], X[k]);
-}
-
-/**
- * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
- * N, r, p, buf, buflen):
- * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
- * p, buflen) and write the result into buf. The parameters r, p, and buflen
- * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
- * must be a power of 2 greater than 1.
- *
- * Return 0 on success; or -1 on error.
- */
-int
-escrypt_kdf_nosse(escrypt_local_t * local,
- const uint8_t * passwd, size_t passwdlen,
- const uint8_t * salt, size_t saltlen,
- uint64_t N, uint32_t _r, uint32_t _p,
- uint8_t * buf, size_t buflen)
-{
- size_t B_size, V_size, XY_size, need;
- uint8_t * B;
- uint32_t * V, * XY;
- size_t r = _r, p = _p;
- uint32_t i;
-
- /* Sanity-check parameters. */
-#if SIZE_MAX > UINT32_MAX
- if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
- errno = EFBIG;
- return -1;
- }
-#endif
- if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
- errno = EFBIG;
- return -1;
- }
- if (((N & (N - 1)) != 0) || (N < 2)) {
- errno = EINVAL;
- return -1;
- }
- if (r == 0 || p == 0) {
- errno = EINVAL;
- return -1;
- }
- if ((r > SIZE_MAX / 128 / p) ||
-#if SIZE_MAX / 256 <= UINT32_MAX
- (r > SIZE_MAX / 256) ||
-#endif
- (N > SIZE_MAX / 128 / r)) {
- errno = ENOMEM;
- return -1;
- }
-
- /* Allocate memory. */
- B_size = (size_t)128 * r * p;
- V_size = (size_t)128 * r * N;
- need = B_size + V_size;
- if (need < V_size) {
- errno = ENOMEM;
- return -1;
- }
- XY_size = (size_t)256 * r + 64;
- need += XY_size;
- if (need < XY_size) {
- errno = ENOMEM;
- return -1;
- }
- if (local->size < need) {
- if (free_region(local))
- return -1;
- if (!alloc_region(local, need))
- return -1;
- }
- B = (uint8_t *)local->aligned;
- V = (uint32_t *)((uint8_t *)B + B_size);
- XY = (uint32_t *)((uint8_t *)V + V_size);
-
- /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
- PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
-
- /* 2: for i = 0 to p - 1 do */
- for (i = 0; i < p; i++) {
- /* 3: B_i <-- MF(B_i, N) */
- smix(&B[(size_t)128 * i * r], r, N, V, XY);
- }
-
- /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
- PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
-
- /* Success! */
- return 0;
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt
deleted file mode 100644
index 66bbfe2db9..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-This folder is only meant for use with nacl, i.e. when sodium is unavailable.
-
-
-The files in this folder were mostly copied from
-https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/crypto_pwhash/scryptsalsa208sha256,
-with #ifdef VANILLA_NACL added around each of them as required for this module.
-
-export.h, utils.h, and runtime.h were copied from
-https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/include/sodium.
-utils.h was significantly truncated.
-
-utils.c and runtime.c were copied from
-https://github.com/jedisct1/libsodium/blob/0.7.0/src/libsodium/sodium.
-utils.c was also significantly truncated.
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c
deleted file mode 100644
index 3dfe54db5f..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2005,2007,2009 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <crypto_hash_sha256.h>
-#include <crypto_auth_hmacsha256.h>
-
-#include "pbkdf2-sha256.h"
-#include "sysendian.h"
-#include "utils.h"
-
-/**
- * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
- * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
- * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
- */
-void
-PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
- size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
-{
- uint8_t key[32] = {0};
- size_t i;
- uint8_t salt_and_ivec[saltlen + 4];
- uint8_t U[32];
- uint8_t T[32];
- uint64_t j;
- int k;
- size_t clen;
-
- if (passwdlen > 32) {
- /* For some reason libsodium allows 64byte keys meaning keys
- * between 32byte and 64bytes are not compatible with libsodium.
- toxencryptsave should only give 32byte passwds so this isn't an issue here.*/
- crypto_hash_sha256(key, passwd, passwdlen);
- } else {
- memcpy(key, passwd, passwdlen);
- }
-
- memcpy(salt_and_ivec, salt, saltlen);
-
- for (i = 0; i * 32 < dkLen; i++) {
- be32enc(salt_and_ivec + saltlen, (uint32_t)(i + 1));
- crypto_auth_hmacsha256(U, salt_and_ivec, sizeof(salt_and_ivec), key);
-
- memcpy(T, U, 32);
-
- for (j = 2; j <= c; j++) {
- crypto_auth_hmacsha256(U, U, 32, key);
-
- for (k = 0; k < 32; k++) {
- T[k] ^= U[k];
- }
- }
-
- clen = dkLen - i * 32;
- if (clen > 32) {
- clen = 32;
- }
- memcpy(&buf[i * 32], T, clen);
- }
- sodium_memzero((void *) key, sizeof(key));
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h
deleted file mode 100644
index b74bc6a340..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2005,2007,2009 Colin Percival
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#ifndef _SHA256_H_
-#define _SHA256_H_
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-#include "crypto_auth_hmacsha256.h"
-
-/**
- * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
- * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
- * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
- */
-void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
- uint64_t, uint8_t *, size_t);
-
-#endif /* !_SHA256_H_ */
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
deleted file mode 100644
index 52c51abc3b..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
+++ /dev/null
@@ -1,211 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#include <errno.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-//#include <stdio.h>
-
-#include "crypto_pwhash_scryptsalsa208sha256.h"
-#include "crypto_scrypt.h"
-#include "randombytes.h"
-#include "utils.h"
-
-#define SETTING_SIZE(saltbytes) \
- (sizeof "$7$" - 1U) + \
- (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes)
-
-static int
-pickparams(unsigned long long opslimit, const size_t memlimit,
- uint32_t * const N_log2, uint32_t * const p, uint32_t * const r)
-{
- unsigned long long maxN;
- unsigned long long maxrp;
-
- if (opslimit < 32768) {
- opslimit = 32768;
- }
- *r = 8;
- if (opslimit < memlimit / 32) {
- *p = 1;
- maxN = opslimit / (*r * 4);
- for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
- if ((uint64_t)(1) << *N_log2 > maxN / 2) {
- break;
- }
- }
- } else {
- maxN = memlimit / (*r * 128);
- for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
- if ((uint64_t) (1) << *N_log2 > maxN / 2) {
- break;
- }
- }
- maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2);
- if (maxrp > 0x3fffffff) {
- maxrp = 0x3fffffff;
- }
- *p = (uint32_t) (maxrp) / *r;
- }
- return 0;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_strbytes(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
-}
-
-const char *
-crypto_pwhash_scryptsalsa208sha256_strprefix(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
-}
-
-size_t
-crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
-{
- return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
-}
-
-int
-crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
- unsigned long long outlen,
- const char * const passwd,
- unsigned long long passwdlen,
- const unsigned char * const salt,
- unsigned long long opslimit,
- size_t memlimit)
-{
- //fprintf(stderr, "Doing that dirty thang!!!!\n");
- uint32_t N_log2;
- uint32_t p;
- uint32_t r;
-
- memset(out, 0, outlen);
- if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) {
- errno = EFBIG;
- return -1;
- }
- if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
- errno = EINVAL;
- return -1;
- }
- return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd,
- (size_t) passwdlen,
- (const uint8_t *) salt,
- crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
- (uint64_t) (1) << N_log2, r, p,
- out, (size_t) outlen);
-}
-
-int
-crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen,
- unsigned long long opslimit,
- size_t memlimit)
-{
- uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
- char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
- escrypt_local_t escrypt_local;
- uint32_t N_log2;
- uint32_t p;
- uint32_t r;
-
- memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
- if (passwdlen > SIZE_MAX) {
- errno = EFBIG;
- return -1;
- }
- if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
- errno = EINVAL;
- return -1;
- }
- randombytes(salt, sizeof salt);
- if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt,
- (uint8_t *) setting, sizeof setting) == NULL) {
- errno = EINVAL;
- return -1;
- }
- if (escrypt_init_local(&escrypt_local) != 0) {
- return -1;
- }
- if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
- (const uint8_t *) setting, (uint8_t *) out,
- crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
- escrypt_free_local(&escrypt_local);
- errno = EINVAL;
- return -1;
- }
- escrypt_free_local(&escrypt_local);
-
- (void) sizeof
- (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES)
- == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]);
- (void) sizeof
- (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
- crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U
- == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]);
-
- return 0;
-}
-
-int
-crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
- const char * const passwd,
- unsigned long long passwdlen)
-{
- char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
- escrypt_local_t escrypt_local;
- int ret = -1;
-
- if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
- &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
- return -1;
- }
- if (escrypt_init_local(&escrypt_local) != 0) {
- return -1;
- }
- if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
- (const uint8_t *) str, (uint8_t *) wanted,
- sizeof wanted) == NULL) {
- escrypt_free_local(&escrypt_local);
- return -1;
- }
- escrypt_free_local(&escrypt_local);
- ret = sodium_memcmp(wanted, str, sizeof wanted);
- sodium_memzero(wanted, sizeof wanted);
-
- return ret;
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c
deleted file mode 100644
index 9b5c513193..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifdef HAVE_ANDROID_GETCPUFEATURES
-# include <cpu-features.h>
-#endif
-
-#include "runtime.h"
-
-typedef struct CPUFeatures_ {
- int initialized;
- int has_neon;
- int has_sse2;
- int has_sse3;
-} CPUFeatures;
-
-static CPUFeatures _cpu_features;
-
-#define CPUID_SSE2 0x04000000
-#define CPUIDECX_SSE3 0x00000001
-
-static int
-_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features)
-{
-#ifndef __arm__
- cpu_features->has_neon = 0;
- return -1;
-#else
-# ifdef __APPLE__
-# ifdef __ARM_NEON__
- cpu_features->has_neon = 1;
-# else
- cpu_features->has_neon = 0;
-# endif
-# elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON)
- cpu_features->has_neon =
- (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0;
-# else
- cpu_features->has_neon = 0;
-# endif
- return 0;
-#endif
-}
-
-static void
-_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type)
-{
-#ifdef _MSC_VER
- __cpuidex((int *) cpu_info, cpu_info_type, 0);
-#elif defined(HAVE_CPUID)
- cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
-# ifdef __i386__
- __asm__ __volatile__ ("pushfl; pushfl; "
- "popl %0; "
- "movl %0, %1; xorl %2, %0; "
- "pushl %0; "
- "popfl; pushfl; popl %0; popfl" :
- "=&r" (cpu_info[0]), "=&r" (cpu_info[1]) :
- "i" (0x200000));
- if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) {
- return;
- }
-# endif
-# ifdef __i386__
- __asm__ __volatile__ ("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1" :
- "=a" (cpu_info[0]), "=&r" (cpu_info[1]),
- "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
- "0" (cpu_info_type), "2" (0U));
-# elif defined(__x86_64__)
- __asm__ __volatile__ ("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1" :
- "=a" (cpu_info[0]), "=&r" (cpu_info[1]),
- "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
- "0" (cpu_info_type), "2" (0U));
-# else
- __asm__ __volatile__ ("cpuid" :
- "=a" (cpu_info[0]), "=b" (cpu_info[1]),
- "=c" (cpu_info[2]), "=d" (cpu_info[3]) :
- "0" (cpu_info_type), "2" (0U));
-# endif
-#else
- cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0;
-#endif
-}
-
-static int
-_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
-{
- unsigned int cpu_info[4];
- unsigned int id;
-
- _cpuid(cpu_info, 0x0);
- if ((id = cpu_info[0]) == 0U) {
- return -1;
- }
- _cpuid(cpu_info, 0x00000001);
-#ifndef HAVE_EMMINTRIN_H
- cpu_features->has_sse2 = 0;
-#else
- cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0);
-#endif
-
-#ifndef HAVE_PMMINTRIN_H
- cpu_features->has_sse3 = 0;
-#else
- cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0);
-#endif
-
- return 0;
-}
-
-int
-sodium_runtime_get_cpu_features(void)
-{
- int ret = -1;
-
- ret &= _sodium_runtime_arm_cpu_features(&_cpu_features);
- ret &= _sodium_runtime_intel_cpu_features(&_cpu_features);
- _cpu_features.initialized = 1;
-
- return ret;
-}
-
-int
-sodium_runtime_has_neon(void) {
- return _cpu_features.has_neon;
-}
-
-int
-sodium_runtime_has_sse2(void) {
- return _cpu_features.has_sse2;
-}
-
-int
-sodium_runtime_has_sse3(void) {
- return _cpu_features.has_sse3;
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h
deleted file mode 100644
index 874915ef42..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef __SODIUM_RUNTIME_H__
-#define __SODIUM_RUNTIME_H__ 1
-
-#include "export.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SODIUM_EXPORT
-int sodium_runtime_get_cpu_features(void);
-
-SODIUM_EXPORT
-int sodium_runtime_has_neon(void);
-
-SODIUM_EXPORT
-int sodium_runtime_has_sse2(void);
-
-SODIUM_EXPORT
-int sodium_runtime_has_sse3(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c
deleted file mode 100644
index 5819651454..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2013 Alexander Peslyak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-#endif
-#include <errno.h>
-#include <stdlib.h>
-
-#include "crypto_scrypt.h"
-#include "runtime.h"
-
-#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
-# define MAP_ANON MAP_ANONYMOUS
-#endif
-
-void *
-alloc_region(escrypt_region_t * region, size_t size)
-{
- uint8_t * base, * aligned;
-#ifdef MAP_ANON
- if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE,
-#ifdef MAP_NOCORE
- MAP_ANON | MAP_PRIVATE | MAP_NOCORE,
-#else
- MAP_ANON | MAP_PRIVATE,
-#endif
- -1, 0)) == MAP_FAILED)
- base = NULL;
- aligned = base;
-#elif defined(HAVE_POSIX_MEMALIGN)
- if ((errno = posix_memalign((void **) &base, 64, size)) != 0)
- base = NULL;
- aligned = base;
-#else
- base = aligned = NULL;
- if (size + 63 < size)
- errno = ENOMEM;
- else if ((base = (uint8_t *) malloc(size + 63)) != NULL) {
- aligned = base + 63;
- aligned -= (uintptr_t)aligned & 63;
- }
-#endif
- region->base = base;
- region->aligned = aligned;
- region->size = base ? size : 0;
- return aligned;
-}
-
-static inline void
-init_region(escrypt_region_t * region)
-{
- region->base = region->aligned = NULL;
- region->size = 0;
-}
-
-int
-free_region(escrypt_region_t * region)
-{
- if (region->base) {
-#ifdef MAP_ANON
- if (munmap(region->base, region->size))
- return -1;
-#else
- free(region->base);
-#endif
- }
- init_region(region);
- return 0;
-}
-
-int
-escrypt_init_local(escrypt_local_t * local)
-{
- init_region(local);
- return 0;
-}
-
-int
-escrypt_free_local(escrypt_local_t * local)
-{
- return free_region(local);
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
deleted file mode 100644
index 856a655e3f..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
+++ /dev/null
@@ -1,398 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-/*-
- * Copyright 2009 Colin Percival
- * Copyright 2012,2013 Alexander Peslyak
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file was originally written by Colin Percival as part of the Tarsnap
- * online backup system.
- */
-
-#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER)
-#if __GNUC__
-# pragma GCC target("sse2")
-#endif
-#include <emmintrin.h>
-#if defined(__XOP__) && defined(DISABLED)
-# include <x86intrin.h>
-#endif
-
-#include <errno.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../pbkdf2-sha256.h"
-#include "../sysendian.h"
-#include "../crypto_scrypt.h"
-
-#if defined(__XOP__) && defined(DISABLED)
-#define ARX(out, in1, in2, s) \
- out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s));
-#else
-#define ARX(out, in1, in2, s) \
- { \
- __m128i T = _mm_add_epi32(in1, in2); \
- out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \
- out = _mm_xor_si128(out, _mm_srli_epi32(T, 32-s)); \
- }
-#endif
-
-#define SALSA20_2ROUNDS \
- /* Operate on "columns". */ \
- ARX(X1, X0, X3, 7) \
- ARX(X2, X1, X0, 9) \
- ARX(X3, X2, X1, 13) \
- ARX(X0, X3, X2, 18) \
-\
- /* Rearrange data. */ \
- X1 = _mm_shuffle_epi32(X1, 0x93); \
- X2 = _mm_shuffle_epi32(X2, 0x4E); \
- X3 = _mm_shuffle_epi32(X3, 0x39); \
-\
- /* Operate on "rows". */ \
- ARX(X3, X0, X1, 7) \
- ARX(X2, X3, X0, 9) \
- ARX(X1, X2, X3, 13) \
- ARX(X0, X1, X2, 18) \
-\
- /* Rearrange data. */ \
- X1 = _mm_shuffle_epi32(X1, 0x39); \
- X2 = _mm_shuffle_epi32(X2, 0x4E); \
- X3 = _mm_shuffle_epi32(X3, 0x93);
-
-/**
- * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3).
- */
-#define SALSA20_8_XOR(in, out) \
- { \
- __m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \
- __m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \
- __m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \
- __m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \
- SALSA20_2ROUNDS \
- SALSA20_2ROUNDS \
- SALSA20_2ROUNDS \
- SALSA20_2ROUNDS \
- (out)[0] = X0 = _mm_add_epi32(X0, Y0); \
- (out)[1] = X1 = _mm_add_epi32(X1, Y1); \
- (out)[2] = X2 = _mm_add_epi32(X2, Y2); \
- (out)[3] = X3 = _mm_add_epi32(X3, Y3); \
- }
-
-/**
- * blockmix_salsa8(Bin, Bout, r):
- * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r
- * bytes in length; the output Bout must also be the same size.
- */
-static inline void
-blockmix_salsa8(const __m128i * Bin, __m128i * Bout, size_t r)
-{
- __m128i X0, X1, X2, X3;
- size_t i;
-
- /* 1: X <-- B_{2r - 1} */
- X0 = Bin[8 * r - 4];
- X1 = Bin[8 * r - 3];
- X2 = Bin[8 * r - 2];
- X3 = Bin[8 * r - 1];
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- SALSA20_8_XOR(Bin, Bout)
-
- /* 2: for i = 0 to 2r - 1 do */
- r--;
- for (i = 0; i < r;) {
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
-
- i++;
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4])
- }
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4])
-}
-
-#define XOR4(in) \
- X0 = _mm_xor_si128(X0, (in)[0]); \
- X1 = _mm_xor_si128(X1, (in)[1]); \
- X2 = _mm_xor_si128(X2, (in)[2]); \
- X3 = _mm_xor_si128(X3, (in)[3]);
-
-#define XOR4_2(in1, in2) \
- X0 = _mm_xor_si128((in1)[0], (in2)[0]); \
- X1 = _mm_xor_si128((in1)[1], (in2)[1]); \
- X2 = _mm_xor_si128((in1)[2], (in2)[2]); \
- X3 = _mm_xor_si128((in1)[3], (in2)[3]);
-
-static inline uint32_t
-blockmix_salsa8_xor(const __m128i * Bin1, const __m128i * Bin2, __m128i * Bout,
- size_t r)
-{
- __m128i X0, X1, X2, X3;
- size_t i;
-
- /* 1: X <-- B_{2r - 1} */
- XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4])
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- XOR4(Bin1)
- SALSA20_8_XOR(Bin2, Bout)
-
- /* 2: for i = 0 to 2r - 1 do */
- r--;
- for (i = 0; i < r;) {
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- XOR4(&Bin1[i * 8 + 4])
- SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
-
- i++;
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- XOR4(&Bin1[i * 8])
- SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4])
- }
-
- /* 3: X <-- H(X \xor B_i) */
- /* 4: Y_i <-- X */
- /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
- XOR4(&Bin1[i * 8 + 4])
- SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4])
-
- return _mm_cvtsi128_si32(X0);
-}
-
-#undef ARX
-#undef SALSA20_2ROUNDS
-#undef SALSA20_8_XOR
-#undef XOR4
-#undef XOR4_2
-
-/**
- * integerify(B, r):
- * Return the result of parsing B_{2r-1} as a little-endian integer.
- */
-static inline uint32_t
-integerify(const void * B, size_t r)
-{
- return *(const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64);
-}
-
-/**
- * smix(B, r, N, V, XY):
- * Compute B = SMix_r(B, N). The input B must be 128r bytes in length;
- * the temporary storage V must be 128rN bytes in length; the temporary
- * storage XY must be 256r + 64 bytes in length. The value N must be a
- * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a
- * multiple of 64 bytes.
- */
-static void
-smix(uint8_t * B, size_t r, uint32_t N, void * V, void * XY)
-{
- size_t s = 128 * r;
- __m128i * X = (__m128i *) V, * Y;
- uint32_t * X32 = (uint32_t *) V;
- uint32_t i, j;
- size_t k;
-
- /* 1: X <-- B */
- /* 3: V_i <-- X */
- for (k = 0; k < 2 * r; k++) {
- for (i = 0; i < 16; i++) {
- X32[k * 16 + i] =
- le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);
- }
- }
-
- /* 2: for i = 0 to N - 1 do */
- for (i = 1; i < N - 1; i += 2) {
- /* 4: X <-- H(X) */
- /* 3: V_i <-- X */
- Y = (__m128i *)((uintptr_t)(V) + i * s);
- blockmix_salsa8(X, Y, r);
-
- /* 4: X <-- H(X) */
- /* 3: V_i <-- X */
- X = (__m128i *)((uintptr_t)(V) + (i + 1) * s);
- blockmix_salsa8(Y, X, r);
- }
-
- /* 4: X <-- H(X) */
- /* 3: V_i <-- X */
- Y = (__m128i *)((uintptr_t)(V) + i * s);
- blockmix_salsa8(X, Y, r);
-
- /* 4: X <-- H(X) */
- /* 3: V_i <-- X */
- X = (__m128i *) XY;
- blockmix_salsa8(Y, X, r);
-
- X32 = (uint32_t *) XY;
- Y = (__m128i *)((uintptr_t)(XY) + s);
-
- /* 7: j <-- Integerify(X) mod N */
- j = integerify(X, r) & (N - 1);
-
- /* 6: for i = 0 to N - 1 do */
- for (i = 0; i < N; i += 2) {
- __m128i * V_j = (__m128i *)((uintptr_t)(V) + j * s);
-
- /* 8: X <-- H(X \xor V_j) */
- /* 7: j <-- Integerify(X) mod N */
- j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1);
- V_j = (__m128i *)((uintptr_t)(V) + j * s);
-
- /* 8: X <-- H(X \xor V_j) */
- /* 7: j <-- Integerify(X) mod N */
- j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1);
- }
-
- /* 10: B' <-- X */
- for (k = 0; k < 2 * r; k++) {
- for (i = 0; i < 16; i++) {
- le32enc(&B[(k * 16 + (i * 5 % 16)) * 4],
- X32[k * 16 + i]);
- }
- }
-}
-
-/**
- * escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
- * N, r, p, buf, buflen):
- * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
- * p, buflen) and write the result into buf. The parameters r, p, and buflen
- * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
- * must be a power of 2 greater than 1.
- *
- * Return 0 on success; or -1 on error.
- */
-int
-escrypt_kdf_sse(escrypt_local_t * local,
- const uint8_t * passwd, size_t passwdlen,
- const uint8_t * salt, size_t saltlen,
- uint64_t N, uint32_t _r, uint32_t _p,
- uint8_t * buf, size_t buflen)
-{
- size_t B_size, V_size, XY_size, need;
- uint8_t * B;
- uint32_t * V, * XY;
- size_t r = _r, p = _p;
- uint32_t i;
-
- /* Sanity-check parameters. */
-#if SIZE_MAX > UINT32_MAX
- if (buflen > (((uint64_t)(1) << 32) - 1) * 32) {
- errno = EFBIG;
- return -1;
- }
-#endif
- if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {
- errno = EFBIG;
- return -1;
- }
- if (N > UINT32_MAX) {
- errno = EFBIG;
- return -1;
- }
- if (((N & (N - 1)) != 0) || (N < 2)) {
- errno = EINVAL;
- return -1;
- }
- if (r == 0 || p == 0) {
- errno = EINVAL;
- return -1;
- }
- if ((r > SIZE_MAX / 128 / p) ||
-#if SIZE_MAX / 256 <= UINT32_MAX
- (r > SIZE_MAX / 256) ||
-#endif
- (N > SIZE_MAX / 128 / r)) {
- errno = ENOMEM;
- return -1;
- }
-
- /* Allocate memory. */
- B_size = (size_t)128 * r * p;
- V_size = (size_t)128 * r * N;
- need = B_size + V_size;
- if (need < V_size) {
- errno = ENOMEM;
- return -1;
- }
- XY_size = (size_t)256 * r + 64;
- need += XY_size;
- if (need < XY_size) {
- errno = ENOMEM;
- return -1;
- }
- if (local->size < need) {
- if (free_region(local))
- return -1;
- if (!alloc_region(local, need))
- return -1;
- }
- B = (uint8_t *)local->aligned;
- V = (uint32_t *)((uint8_t *)B + B_size);
- XY = (uint32_t *)((uint8_t *)V + V_size);
-
- /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
- PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
-
- /* 2: for i = 0 to p - 1 do */
- for (i = 0; i < p; i++) {
- /* 3: B_i <-- MF(B_i, N) */
- smix(&B[(size_t)128 * i * r], r, N, V, XY);
- }
-
- /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
- PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
-
- /* Success! */
- return 0;
-}
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h
deleted file mode 100644
index 04e5c1ed45..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef _SYSENDIAN_H_
-#define _SYSENDIAN_H_
-
-#include <stdint.h>
-
-/* Avoid namespace collisions with BSD <sys/endian.h>. */
-#define be16dec scrypt_be16dec
-#define be16enc scrypt_be16enc
-#define be32dec scrypt_be32dec
-#define be32enc scrypt_be32enc
-#define be64dec scrypt_be64dec
-#define be64enc scrypt_be64enc
-#define le16dec scrypt_le16dec
-#define le16enc scrypt_le16enc
-#define le32dec scrypt_le32dec
-#define le32enc scrypt_le32enc
-#define le64dec scrypt_le64dec
-#define le64enc scrypt_le64enc
-
-static inline uint16_t
-be16dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8));
-}
-
-static inline void
-be16enc(void *pp, uint16_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[1] = x & 0xff;
- p[0] = (x >> 8) & 0xff;
-}
-
-static inline uint32_t
-be32dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
- ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
-}
-
-static inline void
-be32enc(void *pp, uint32_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[3] = x & 0xff;
- p[2] = (x >> 8) & 0xff;
- p[1] = (x >> 16) & 0xff;
- p[0] = (x >> 24) & 0xff;
-}
-
-static inline uint64_t
-be64dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
- ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
- ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
- ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
-}
-
-static inline void
-be64enc(void *pp, uint64_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[7] = x & 0xff;
- p[6] = (x >> 8) & 0xff;
- p[5] = (x >> 16) & 0xff;
- p[4] = (x >> 24) & 0xff;
- p[3] = (x >> 32) & 0xff;
- p[2] = (x >> 40) & 0xff;
- p[1] = (x >> 48) & 0xff;
- p[0] = (x >> 56) & 0xff;
-}
-
-static inline uint16_t
-le16dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8));
-}
-
-static inline void
-le16enc(void *pp, uint16_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[0] = x & 0xff;
- p[1] = (x >> 8) & 0xff;
-}
-
-static inline uint32_t
-le32dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
- ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
-}
-
-static inline void
-le32enc(void *pp, uint32_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[0] = x & 0xff;
- p[1] = (x >> 8) & 0xff;
- p[2] = (x >> 16) & 0xff;
- p[3] = (x >> 24) & 0xff;
-}
-
-static inline uint64_t
-le64dec(const void *pp)
-{
- const uint8_t *p = (uint8_t const *)pp;
-
- return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
- ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
- ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
- ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
-}
-
-static inline void
-le64enc(void *pp, uint64_t x)
-{
- uint8_t * p = (uint8_t *)pp;
-
- p[0] = x & 0xff;
- p[1] = (x >> 8) & 0xff;
- p[2] = (x >> 16) & 0xff;
- p[3] = (x >> 24) & 0xff;
- p[4] = (x >> 32) & 0xff;
- p[5] = (x >> 40) & 0xff;
- p[6] = (x >> 48) & 0xff;
- p[7] = (x >> 56) & 0xff;
-}
-
-#endif /* !_SYSENDIAN_H_ */
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c
deleted file mode 100644
index e61ccf3ecf..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef __STDC_WANT_LIB_EXT1__
-# define __STDC_WANT_LIB_EXT1__ 1
-#endif
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-#endif
-
-#include "utils.h"
-
-#ifdef _WIN32
-# include <windows.h>
-# include <wincrypt.h>
-#else
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_WEAK_SYMBOLS
-__attribute__((weak)) void
-__sodium_dummy_symbol_to_prevent_lto(void * const pnt, const size_t len)
-{
- (void) pnt;
- (void) len;
-}
-#endif
-
-void
-sodium_memzero(void * const pnt, const size_t len)
-{
-#ifdef _WIN32
- SecureZeroMemory(pnt, len);
-#elif defined(HAVE_MEMSET_S)
- if (memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) {
- abort();
- }
-#elif defined(HAVE_EXPLICIT_BZERO)
- explicit_bzero(pnt, len);
-#elif HAVE_WEAK_SYMBOLS
- memset(pnt, 0, len);
- __sodium_dummy_symbol_to_prevent_lto(pnt, len);
-#else
- volatile unsigned char *pnt_ = (volatile unsigned char *) pnt;
- size_t i = (size_t) 0U;
-
- while (i < len) {
- pnt_[i++] = 0U;
- }
-#endif
-}
-
-int
-sodium_memcmp(const void * const b1_, const void * const b2_, size_t len)
-{
- const unsigned char *b1 = (const unsigned char *) b1_;
- const unsigned char *b2 = (const unsigned char *) b2_;
- size_t i;
- unsigned char d = (unsigned char) 0U;
-
- for (i = 0U; i < len; i++) {
- d |= b1[i] ^ b2[i];
- }
- return (int) ((1 & ((d - 1) >> 8)) - 1);
-}
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h
deleted file mode 100644
index fb2020c35d..0000000000
--- a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */
-
-#ifndef __SODIUM_UTILS_H__
-#define __SODIUM_UTILS_H__
-
-#include <stddef.h>
-
-#include "export.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
-# define _SODIUM_C99(X)
-#else
-# define _SODIUM_C99(X) X
-#endif
-
-SODIUM_EXPORT
-void sodium_memzero(void * const pnt, const size_t len);
-
-/* WARNING: sodium_memcmp() must be used to verify if two secret keys
- * are equal, in constant time.
- * It returns 0 if the keys are equal, and -1 if they differ.
- * This function is not designed for lexicographical comparisons.
- */
-SODIUM_EXPORT
-int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-#endif
diff --git a/libs/libtox/src/toxencryptsave/defines.h b/libs/libtox/src/toxencryptsave/defines.h
deleted file mode 100644
index e3fca073e3..0000000000
--- a/libs/libtox/src/toxencryptsave/defines.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave"
-#define TOX_ENC_SAVE_MAGIC_LENGTH 8
diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.api.h b/libs/libtox/src/toxencryptsave/toxencryptsave.api.h
deleted file mode 100644
index 61f685f86b..0000000000
--- a/libs/libtox/src/toxencryptsave/toxencryptsave.api.h
+++ /dev/null
@@ -1,327 +0,0 @@
-%{
-/*
- * Batch encryption functions.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013-2016 Tox Developers.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOXENCRYPTSAVE_H
-#define TOXENCRYPTSAVE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-%}
-
-/*******************************************************************************
- *
- * This module is organized into two parts.
- *
- * 1. A simple API operating on plain text/cipher text data and a password to
- * encrypt or decrypt it.
- * 2. A more advanced API that splits key derivation and encryption into two
- * separate function calls.
- *
- * The first part is implemented in terms of the second part and simply calls
- * the separate functions in sequence. Since key derivation is very expensive
- * compared to the actual encryption, clients that do a lot of crypto should
- * prefer the advanced API and reuse pass-key objects.
- *
- * To use the second part, first derive an encryption key from a password with
- * ${tox.pass_Key.derive}, then use the derived key to encrypt the data.
- *
- * The encrypted data is prepended with a magic number, to aid validity
- * checking (no guarantees are made of course). Any data to be decrypted must
- * start with the magic number.
- *
- * Clients should consider alerting their users that, unlike plain data, if
- * even one bit becomes corrupted, the data will be entirely unrecoverable.
- * Ditto if they forget their password, there is no way to recover the data.
- *
- *******************************************************************************/
-
-class tox {
-
-/**
- * The size of the salt part of a pass-key.
- */
-const PASS_SALT_LENGTH = 32;
-/**
- * The size of the key part of a pass-key.
- */
-const PASS_KEY_LENGTH = 32;
-/**
- * The amount of additional data required to store any encrypted byte array.
- * Encrypting an array of N bytes requires N + $PASS_ENCRYPTION_EXTRA_LENGTH
- * bytes in the encrypted byte array.
- */
-const PASS_ENCRYPTION_EXTRA_LENGTH = 80;
-
-error for key_derivation {
- NULL,
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- FAILED,
-}
-
-error for encryption {
- NULL,
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- KEY_DERIVATION_FAILED,
- /**
- * The encryption itself failed.
- */
- FAILED,
-}
-
-error for decryption {
- NULL,
- /**
- * The input data was shorter than $PASS_ENCRYPTION_EXTRA_LENGTH bytes
- */
- INVALID_LENGTH,
- /**
- * The input data is missing the magic number (i.e. wasn't created by this
- * module, or is corrupted).
- */
- BAD_FORMAT,
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- KEY_DERIVATION_FAILED,
- /**
- * The encrypted byte array could not be decrypted. Either the data was
- * corrupted or the password/key was incorrect.
- */
- FAILED,
-}
-
-
-/*******************************************************************************
- *
- * BEGIN PART 1
- *
- * The simple API is presented first. If your code spends too much time using
- * these functions, consider using the advanced functions instead and caching
- * the generated pass-key.
- *
- *******************************************************************************/
-
-/**
- * Encrypts the given data with the given passphrase.
- *
- * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to ${pass_Key.derive} and
- * ${pass_Key.encrypt}.
- *
- * @param plaintext A byte array of length `plaintext_len`.
- * @param plaintext_len The length of the plain text array. Bigger than 0.
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param ciphertext The cipher text array to write the encrypted data to.
- *
- * @return true on success.
- */
-static bool pass_encrypt(const uint8_t[plaintext_len] plaintext, const uint8_t[passphrase_len] passphrase, uint8_t *ciphertext)
- with error for encryption;
-
-
-/**
- * Decrypts the given data with the given passphrase.
- *
- * The output array must be at least `ciphertext_len - $PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to ${pass_Key.decrypt}.
- *
- * @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH.
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param plaintext The plain text array to write the decrypted data to.
- *
- * @return true on success.
- */
-static bool pass_decrypt(const uint8_t[ciphertext_len] ciphertext, const uint8_t[passphrase_len] passphrase, uint8_t *plaintext)
- with error for decryption;
-
-
-/*******************************************************************************
- *
- * BEGIN PART 2
- *
- * And now part 2, which does the actual encryption, and can be used to write
- * less CPU intensive client code than part one.
- *
- *******************************************************************************/
-
-class pass_Key {
- /**
- * This type represents a pass-key.
- *
- * A pass-key and a password are two different concepts: a password is given
- * by the user in plain text. A pass-key is the generated symmetric key used
- * for encryption and decryption. It is derived from a salt and the user-
- * provided password.
- *
- * The $this structure is hidden in the implementation. It can be allocated
- * using $new and must be deallocated using $free.
- */
- struct this;
-
- /**
- * Create a new $this. The initial value of it is indeterminate. To
- * initialise it, use one of the derive_* functions below.
- *
- * In case of failure, this function returns NULL. The only failure mode at
- * this time is memory allocation failure, so this function has no error code.
- */
- static this new();
-
- /**
- * Deallocate a $this. This function behaves like free(), so NULL is an
- * acceptable argument value.
- */
- void free();
-
- /**
- * Generates a secret symmetric key from the given passphrase.
- *
- * Be sure to not compromise the key! Only keep it in memory, do not write
- * it to disk.
- *
- * Note that this function is not deterministic; to derive the same key from
- * a password, you also must know the random salt that was used. A
- * deterministic version of this function is $derive_with_salt.
- *
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- *
- * @return true on success.
- */
- bool derive(const uint8_t[passphrase_len] passphrase)
- with error for key_derivation;
-
- /**
- * Same as above, except use the given salt for deterministic key derivation.
- *
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param salt An array of at least $PASS_SALT_LENGTH bytes.
- *
- * @return true on success.
- */
- bool derive_with_salt(const uint8_t[passphrase_len] passphrase, const uint8_t[PASS_SALT_LENGTH] salt)
- with error for key_derivation;
-
- /**
- * Encrypt a plain text with a key produced by $derive or $derive_with_salt.
- *
- * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long.
- *
- * @param plaintext A byte array of length `plaintext_len`.
- * @param plaintext_len The length of the plain text array. Bigger than 0.
- * @param ciphertext The cipher text array to write the encrypted data to.
- *
- * @return true on success.
- */
- const bool encrypt(const uint8_t[plaintext_len] plaintext, uint8_t *ciphertext)
- with error for encryption;
-
- /**
- * This is the inverse of $encrypt, also using only keys produced by
- * $derive or $derive_with_salt.
- *
- * @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH.
- * @param plaintext The plain text array to write the decrypted data to.
- *
- * @return true on success.
- */
- const bool decrypt(const uint8_t[ciphertext_len] ciphertext, uint8_t *plaintext)
- with error for decryption;
-}
-
-/**
- * Retrieves the salt used to encrypt the given data.
- *
- * The retrieved salt can then be passed to ${pass_Key.derive_with_salt} to
- * produce the same key as was previously used. Any data encrypted with this
- * module can be used as input.
- *
- * The cipher text must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
- * The salt must be $PASS_SALT_LENGTH bytes in length.
- * If the passed byte arrays are smaller than required, the behaviour is
- * undefined.
- *
- * If the cipher text pointer or the salt is NULL, this function returns false.
- *
- * Success does not say anything about the validity of the data, only that
- * data of the appropriate size was copied.
- *
- * @return true on success.
- */
-static bool get_salt(const uint8_t *ciphertext, uint8_t[PASS_SALT_LENGTH] salt) {
- NULL,
- /**
- * The input data is missing the magic number (i.e. wasn't created by this
- * module, or is corrupted).
- */
- BAD_FORMAT,
-}
-
-/**
- * Determines whether or not the given data is encrypted by this module.
- *
- * It does this check by verifying that the magic number is the one put in
- * place by the encryption functions.
- *
- * The data must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
- * If the passed byte array is smaller than required, the behaviour is
- * undefined.
- *
- * If the data pointer is NULL, the behaviour is undefined
- *
- * @return true if the data is encrypted by this module.
- */
-static bool is_data_encrypted(const uint8_t *data);
-
-}
-
-%{
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-%}
diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.c b/libs/libtox/src/toxencryptsave/toxencryptsave.c
deleted file mode 100644
index 5640e82fc7..0000000000
--- a/libs/libtox/src/toxencryptsave/toxencryptsave.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Batch encryption functions.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013 Tox project.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "../toxcore/crypto_core.h"
-#include "defines.h"
-#include "toxencryptsave.h"
-#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
-
-#ifdef VANILLA_NACL
-#include <crypto_box.h>
-#include <crypto_hash_sha256.h>
-#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
-#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
-#else
-#include <sodium.h>
-#endif
-
-#include <string.h>
-
-#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES
-#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES
-#endif
-
-#if TOX_PASS_KEY_LENGTH != CRYPTO_SHARED_KEY_SIZE
-#error TOX_PASS_KEY_LENGTH is assumed to be equal to CRYPTO_SHARED_KEY_SIZE
-#endif
-
-#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
-#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
-#endif
-
-uint32_t tox_pass_salt_length(void)
-{
- return TOX_PASS_SALT_LENGTH;
-}
-uint32_t tox_pass_key_length(void)
-{
- return TOX_PASS_KEY_LENGTH;
-}
-uint32_t tox_pass_encryption_extra_length(void)
-{
- return TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
-}
-
-struct Tox_Pass_Key {
- uint8_t salt[TOX_PASS_SALT_LENGTH];
- uint8_t key[TOX_PASS_KEY_LENGTH];
-};
-
-Tox_Pass_Key *tox_pass_key_new(void)
-{
- return (Tox_Pass_Key *)malloc(sizeof(Tox_Pass_Key));
-}
-
-void tox_pass_key_free(Tox_Pass_Key *pass_key)
-{
- free(pass_key);
-}
-
-/* Clients should consider alerting their users that, unlike plain data, if even one bit
- * becomes corrupted, the data will be entirely unrecoverable.
- * Ditto if they forget their password, there is no way to recover the data.
- */
-
-/* This retrieves the salt used to encrypt the given data, which can then be passed to
- * tox_pass_key_derive_with_salt to produce the same key as was previously used. Any encrpyted
- * data with this module can be used as input.
- *
- * returns true if magic number matches
- * success does not say anything about the validity of the data, only that data of
- * the appropriate size was copied
- */
-bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error)
-{
- if (!data || !salt) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL);
- return false;
- }
-
- if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_BAD_FORMAT);
- return false;
- }
-
- data += TOX_ENC_SAVE_MAGIC_LENGTH;
- memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
- SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_OK);
- return true;
-}
-
-/* Generates a secret symmetric key from the given passphrase. out_key must be at least
- * TOX_PASS_KEY_LENGTH bytes long.
- * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
- * The password is zeroed after key derivation.
- * The key should only be used with the other functions in this module, as it
- * includes a salt.
- * Note that this function is not deterministic; to derive the same key from a
- * password, you also must know the random salt that was used. See below.
- *
- * returns true on success
- */
-bool tox_pass_key_derive(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
- TOX_ERR_KEY_DERIVATION *error)
-{
- uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
- randombytes(salt, sizeof salt);
- return tox_pass_key_derive_with_salt(out_key, passphrase, pplength, salt, error);
-}
-
-/* Same as above, except with use the given salt for deterministic key derivation.
- * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
- */
-bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
- const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error)
-{
- if (!salt || !out_key || (!passphrase && pplength != 0)) {
- SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
- return 0;
- }
-
- uint8_t passkey[crypto_hash_sha256_BYTES];
- crypto_hash_sha256(passkey, passphrase, pplength);
-
- uint8_t key[CRYPTO_SHARED_KEY_SIZE];
-
- /* Derive a key from the password */
- /* http://doc.libsodium.org/key_derivation/README.html */
- /* note that, according to the documentation, a generic pwhash interface will be created
- * once the pwhash competition (https://password-hashing.net/) is over */
- if (crypto_pwhash_scryptsalsa208sha256(
- key, sizeof(key), (char *)passkey, sizeof(passkey), salt,
- crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
- crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
- /* out of memory most likely */
- SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED);
- return 0;
- }
-
- sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
- memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
- memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE);
- SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK);
- return 1;
-}
-
-/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output
- * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
- * key must be TOX_PASS_KEY_LENGTH bytes.
- * If you already have a symmetric key from somewhere besides this module, simply
- * call encrypt_data_symmetric in toxcore/crypto_core directly.
- *
- * returns true on success
- */
-bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t data_len, uint8_t *out,
- TOX_ERR_ENCRYPTION *error)
-{
- if (data_len == 0 || !data || !key || !out) {
- SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
- return 0;
- }
-
- /* the output data consists of, in order:
- * salt, nonce, mac, enc_data
- * where the mac is automatically prepended by the encrypt()
- * the salt+nonce is called the prefix
- * I'm not sure what else I'm supposed to do with the salt and nonce, since we
- * need them to decrypt the data
- */
-
- /* first add the magic number */
- memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
- out += TOX_ENC_SAVE_MAGIC_LENGTH;
-
- /* then add the rest prefix */
- memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
- out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
-
- uint8_t nonce[crypto_box_NONCEBYTES];
- random_nonce(nonce);
- memcpy(out, nonce, crypto_box_NONCEBYTES);
- out += crypto_box_NONCEBYTES;
-
- /* now encrypt */
- if (encrypt_data_symmetric(key->key, nonce, data, data_len, out)
- != data_len + crypto_box_MACBYTES) {
- SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK);
- return 1;
-}
-
-/* Encrypts the given data with the given passphrase. The output array must be
- * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
- * to tox_derive_key and tox_pass_key_encrypt.
- *
- * returns true on success
- */
-bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out,
- TOX_ERR_ENCRYPTION *error)
-{
- Tox_Pass_Key key;
- TOX_ERR_KEY_DERIVATION _error;
-
- if (!tox_pass_key_derive(&key, passphrase, pplength, &_error)) {
- if (_error == TOX_ERR_KEY_DERIVATION_NULL) {
- SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
- } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) {
- SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED);
- }
-
- return 0;
- }
-
- return tox_pass_key_encrypt(&key, data, data_len, out, error);
-}
-
-/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
- * tox_derive_key.
- *
- * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
- *
- * returns true on success
- */
-bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out,
- TOX_ERR_DECRYPTION *error)
-{
- if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
- return 0;
- }
-
- if (!data || !key || !out) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
- return 0;
- }
-
- if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
- return 0;
- }
-
- data += TOX_ENC_SAVE_MAGIC_LENGTH;
- data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation
-
- size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
-
- uint8_t nonce[crypto_box_NONCEBYTES];
- memcpy(nonce, data, crypto_box_NONCEBYTES);
- data += crypto_box_NONCEBYTES;
-
- /* decrypt the data */
- if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
- != decrypt_length) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED);
- return 0;
- }
-
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK);
- return 1;
-}
-
-/* Decrypts the given data with the given passphrase. The output array must be
- * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
- * to tox_pass_key_decrypt.
- *
- * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
- *
- * returns true on success
- */
-bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out,
- TOX_ERR_DECRYPTION *error)
-{
- if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
- return 0;
- }
-
- if (!data || !passphrase || !out) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
- return 0;
- }
-
- if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
- return 0;
- }
-
- uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
- memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
-
- /* derive the key */
- Tox_Pass_Key key;
-
- if (!tox_pass_key_derive_with_salt(&key, passphrase, pplength, salt, NULL)) {
- /* out of memory most likely */
- SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED);
- return 0;
- }
-
- return tox_pass_key_decrypt(&key, data, length, out, error);
-}
-
-/* Determines whether or not the given data is encrypted (by checking the magic number)
- */
-bool tox_is_data_encrypted(const uint8_t *data)
-{
- if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) {
- return 1;
- }
-
- return 0;
-}
diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.h b/libs/libtox/src/toxencryptsave/toxencryptsave.h
deleted file mode 100644
index ef1ab15289..0000000000
--- a/libs/libtox/src/toxencryptsave/toxencryptsave.h
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Batch encryption functions.
- */
-
-/*
- * Copyright © 2016-2017 The TokTok team.
- * Copyright © 2013-2016 Tox Developers.
- *
- * This file is part of Tox, the free peer to peer instant messenger.
- *
- * Tox is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tox is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tox. If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef TOXENCRYPTSAVE_H
-#define TOXENCRYPTSAVE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-
-/*******************************************************************************
- *
- * This module is organized into two parts.
- *
- * 1. A simple API operating on plain text/cipher text data and a password to
- * encrypt or decrypt it.
- * 2. A more advanced API that splits key derivation and encryption into two
- * separate function calls.
- *
- * The first part is implemented in terms of the second part and simply calls
- * the separate functions in sequence. Since key derivation is very expensive
- * compared to the actual encryption, clients that do a lot of crypto should
- * prefer the advanced API and reuse pass-key objects.
- *
- * To use the second part, first derive an encryption key from a password with
- * tox_pass_key_derive, then use the derived key to encrypt the data.
- *
- * The encrypted data is prepended with a magic number, to aid validity
- * checking (no guarantees are made of course). Any data to be decrypted must
- * start with the magic number.
- *
- * Clients should consider alerting their users that, unlike plain data, if
- * even one bit becomes corrupted, the data will be entirely unrecoverable.
- * Ditto if they forget their password, there is no way to recover the data.
- *
- ******************************************************************************/
-
-
-
-/**
- * The size of the salt part of a pass-key.
- */
-#define TOX_PASS_SALT_LENGTH 32
-
-uint32_t tox_pass_salt_length(void);
-
-/**
- * The size of the key part of a pass-key.
- */
-#define TOX_PASS_KEY_LENGTH 32
-
-uint32_t tox_pass_key_length(void);
-
-/**
- * The amount of additional data required to store any encrypted byte array.
- * Encrypting an array of N bytes requires N + TOX_PASS_ENCRYPTION_EXTRA_LENGTH
- * bytes in the encrypted byte array.
- */
-#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80
-
-uint32_t tox_pass_encryption_extra_length(void);
-
-typedef enum TOX_ERR_KEY_DERIVATION {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_KEY_DERIVATION_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_KEY_DERIVATION_NULL,
-
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- TOX_ERR_KEY_DERIVATION_FAILED,
-
-} TOX_ERR_KEY_DERIVATION;
-
-
-typedef enum TOX_ERR_ENCRYPTION {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_ENCRYPTION_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_ENCRYPTION_NULL,
-
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED,
-
- /**
- * The encryption itself failed.
- */
- TOX_ERR_ENCRYPTION_FAILED,
-
-} TOX_ERR_ENCRYPTION;
-
-
-typedef enum TOX_ERR_DECRYPTION {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_DECRYPTION_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_DECRYPTION_NULL,
-
- /**
- * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
- */
- TOX_ERR_DECRYPTION_INVALID_LENGTH,
-
- /**
- * The input data is missing the magic number (i.e. wasn't created by this
- * module, or is corrupted).
- */
- TOX_ERR_DECRYPTION_BAD_FORMAT,
-
- /**
- * The crypto lib was unable to derive a key from the given passphrase,
- * which is usually a lack of memory issue. The functions accepting keys
- * do not produce this error.
- */
- TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED,
-
- /**
- * The encrypted byte array could not be decrypted. Either the data was
- * corrupted or the password/key was incorrect.
- */
- TOX_ERR_DECRYPTION_FAILED,
-
-} TOX_ERR_DECRYPTION;
-
-
-
-/*******************************************************************************
- *
- * BEGIN PART 1
- *
- * The simple API is presented first. If your code spends too much time using
- * these functions, consider using the advanced functions instead and caching
- * the generated pass-key.
- *
- ******************************************************************************/
-
-
-
-/**
- * Encrypts the given data with the given passphrase.
- *
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_derive and
- * tox_pass_key_encrypt.
- *
- * @param plaintext A byte array of length `plaintext_len`.
- * @param plaintext_len The length of the plain text array. Bigger than 0.
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param ciphertext The cipher text array to write the encrypted data to.
- *
- * @return true on success.
- */
-bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len,
- uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error);
-
-/**
- * Decrypts the given data with the given passphrase.
- *
- * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long. This delegates to tox_pass_key_decrypt.
- *
- * @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param plaintext The plain text array to write the decrypted data to.
- *
- * @return true on success.
- */
-bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase,
- size_t passphrase_len, uint8_t *plaintext, TOX_ERR_DECRYPTION *error);
-
-
-/*******************************************************************************
- *
- * BEGIN PART 2
- *
- * And now part 2, which does the actual encryption, and can be used to write
- * less CPU intensive client code than part one.
- *
- ******************************************************************************/
-
-
-
-/**
- * This type represents a pass-key.
- *
- * A pass-key and a password are two different concepts: a password is given
- * by the user in plain text. A pass-key is the generated symmetric key used
- * for encryption and decryption. It is derived from a salt and the user-
- * provided password.
- *
- * The Tox_Pass_Key structure is hidden in the implementation. It can be allocated
- * using tox_pass_key_new and must be deallocated using tox_pass_key_free.
- */
-#ifndef TOX_PASS_KEY_DEFINED
-#define TOX_PASS_KEY_DEFINED
-typedef struct Tox_Pass_Key Tox_Pass_Key;
-#endif /* TOX_PASS_KEY_DEFINED */
-
-/**
- * Create a new Tox_Pass_Key. The initial value of it is indeterminate. To
- * initialise it, use one of the derive_* functions below.
- *
- * In case of failure, this function returns NULL. The only failure mode at
- * this time is memory allocation failure, so this function has no error code.
- */
-struct Tox_Pass_Key *tox_pass_key_new(void);
-
-/**
- * Deallocate a Tox_Pass_Key. This function behaves like free(), so NULL is an
- * acceptable argument value.
- */
-void tox_pass_key_free(struct Tox_Pass_Key *_key);
-
-/**
- * Generates a secret symmetric key from the given passphrase.
- *
- * Be sure to not compromise the key! Only keep it in memory, do not write
- * it to disk.
- *
- * Note that this function is not deterministic; to derive the same key from
- * a password, you also must know the random salt that was used. A
- * deterministic version of this function is tox_pass_key_derive_with_salt.
- *
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- *
- * @return true on success.
- */
-bool tox_pass_key_derive(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len,
- TOX_ERR_KEY_DERIVATION *error);
-
-/**
- * Same as above, except use the given salt for deterministic key derivation.
- *
- * @param passphrase The user-provided password. Can be empty.
- * @param passphrase_len The length of the password.
- * @param salt An array of at least TOX_PASS_SALT_LENGTH bytes.
- *
- * @return true on success.
- */
-bool tox_pass_key_derive_with_salt(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len,
- const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error);
-
-/**
- * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.
- *
- * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
- * bytes long.
- *
- * @param plaintext A byte array of length `plaintext_len`.
- * @param plaintext_len The length of the plain text array. Bigger than 0.
- * @param ciphertext The cipher text array to write the encrypted data to.
- *
- * @return true on success.
- */
-bool tox_pass_key_encrypt(const struct Tox_Pass_Key *_key, const uint8_t *plaintext, size_t plaintext_len,
- uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error);
-
-/**
- * This is the inverse of tox_pass_key_encrypt, also using only keys produced by
- * tox_pass_key_derive or tox_pass_key_derive_with_salt.
- *
- * @param ciphertext A byte array of length `ciphertext_len`.
- * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
- * @param plaintext The plain text array to write the decrypted data to.
- *
- * @return true on success.
- */
-bool tox_pass_key_decrypt(const struct Tox_Pass_Key *_key, const uint8_t *ciphertext, size_t ciphertext_len,
- uint8_t *plaintext, TOX_ERR_DECRYPTION *error);
-
-typedef enum TOX_ERR_GET_SALT {
-
- /**
- * The function returned successfully.
- */
- TOX_ERR_GET_SALT_OK,
-
- /**
- * One of the arguments to the function was NULL when it was not expected.
- */
- TOX_ERR_GET_SALT_NULL,
-
- /**
- * The input data is missing the magic number (i.e. wasn't created by this
- * module, or is corrupted).
- */
- TOX_ERR_GET_SALT_BAD_FORMAT,
-
-} TOX_ERR_GET_SALT;
-
-
-/**
- * Retrieves the salt used to encrypt the given data.
- *
- * The retrieved salt can then be passed to tox_pass_key_derive_with_salt to
- * produce the same key as was previously used. Any data encrypted with this
- * module can be used as input.
- *
- * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
- * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
- * If the passed byte arrays are smaller than required, the behaviour is
- * undefined.
- *
- * If the cipher text pointer or the salt is NULL, this function returns false.
- *
- * Success does not say anything about the validity of the data, only that
- * data of the appropriate size was copied.
- *
- * @return true on success.
- */
-bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, TOX_ERR_GET_SALT *error);
-
-/**
- * Determines whether or not the given data is encrypted by this module.
- *
- * It does this check by verifying that the magic number is the one put in
- * place by the encryption functions.
- *
- * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
- * If the passed byte array is smaller than required, the behaviour is
- * undefined.
- *
- * If the data pointer is NULL, the behaviour is undefined
- *
- * @return true if the data is encrypted by this module.
- */
-bool tox_is_data_encrypted(const uint8_t *data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif