Compare commits
36 Commits
e89f1be660
...
master
Author | SHA1 | Date | |
---|---|---|---|
3567aba4db | |||
9b07cb4dce | |||
c89bba25a3 | |||
f9bc83811c | |||
5c4bb1aa42 | |||
2a143a4c2e | |||
3072d2936e | |||
7458841417 | |||
2b3ee3316a | |||
622c9d9d96 | |||
caa913fa51 | |||
261c487cf2 | |||
086fc52e92 | |||
cd6141ee00 | |||
5fa8dc712a | |||
e0d4c4d1e1 | |||
de247c9e91 | |||
20c41e1a02 | |||
613ae14530 | |||
294a427eb0 | |||
9f8f681e18 | |||
365edc35e9 | |||
d888e91ada | |||
2e745b617d | |||
2f1bb3fac2 | |||
92dcc81731 | |||
83dcf2af82 | |||
5d4108c3e6 | |||
4ee1a865aa | |||
65c6398369 | |||
c0187ae405 | |||
999ef20437 | |||
3b17fca6b2 | |||
b74cc8f6bf | |||
1f0e086b7a | |||
78069a8032 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: Green-Sky
|
43
.github/workflows/cd.yml
vendored
Normal file
43
.github/workflows/cd.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: ContinuousDelivery
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
timeout-minutes: 15
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: amd64
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ github.event.repository.name }}-windows-msvc-x86_64
|
||||
# TODO: do propper packing
|
||||
path: |
|
||||
${{github.workspace}}/build/bin/
|
||||
|
@ -36,7 +36,7 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
link_libraries(-fsanitize=address,undefined)
|
||||
#link_libraries(-fsanitize=address,undefined)
|
||||
#link_libraries(-fsanitize=undefined)
|
||||
endif()
|
||||
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Erik Scholz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
63
README.md
Normal file
63
README.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Tool to send and receive files using Tox NGC FileTransfers
|
||||
currently on prototype FT1
|
||||
|
||||
## Example
|
||||
|
||||
### sender (seeder)
|
||||
`$ tox_ngc_ft1_tool -F sender.tox -G <ngc_chat_id> -a sha1_info -f file_to_transfer`
|
||||
|
||||
this will print this tools tox_id and the generated info_hash
|
||||
|
||||
### receivers (leechers)
|
||||
`$ tox_ngc_ft1_tool -F sender.tox -G <ngc_chat_id> -a sha1_info -D <info_hash>`
|
||||
|
||||
this will first download the info using the info_hash and then all the file chunks listed in the info
|
||||
while simultaneously resharing allready downloaded chunks and info (swarming)
|
||||
to increase the amount of parallel chunk down/up loads, you can increase the value with the -I and -O option. the default for -I is 32 and for -O 16, which are relatively low numbers, which in practice can get you up to ~700KiB/s.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
$ tox_ngc_ft1_tool
|
||||
~~~ HELP ~~~
|
||||
meta:
|
||||
-v version info
|
||||
-V verbose
|
||||
-h help
|
||||
|
||||
connectivity:
|
||||
-G <chat_id>
|
||||
-F profile.tox
|
||||
-N <self_name> (defaults to 'tox_ngc_ft1_tool')
|
||||
will print friend id at startup
|
||||
will autoaccept any invite
|
||||
if no -F given, will not save profile.
|
||||
if profile exists load, otherwise create new
|
||||
|
||||
transfer variant:
|
||||
-a id1/sha1_single/sha1_info/sha2_single/sha2_info
|
||||
|
||||
send:
|
||||
-f send_this_file.zip
|
||||
|
||||
receive:
|
||||
-d dump/everything/in/this/dir
|
||||
-D <id/hash> (what to dl)
|
||||
|
||||
!!! ADVANCED !!!
|
||||
tox:
|
||||
-L disable local discovery
|
||||
-U disable udp
|
||||
-P proxy_host proxy_port
|
||||
-p tox_port (bind tox to that port)
|
||||
|
||||
FT1:
|
||||
--ft_ack_per_packet
|
||||
--ft_init_retry_timeout_after
|
||||
--ft_sending_give_up_after
|
||||
|
||||
transfer logic:
|
||||
-I <max_incoming_transfers>
|
||||
-O <max_outgoing_transfers>
|
||||
```
|
||||
|
2
external/mio/single_include/mio/mio.hpp
vendored
2
external/mio/single_include/mio/mio.hpp
vendored
@ -794,7 +794,7 @@ inline DWORD int64_low(int64_t n) noexcept
|
||||
return n & 0xffffffff;
|
||||
}
|
||||
|
||||
std::wstring s_2_ws(const std::string& s)
|
||||
inline std::wstring s_2_ws(const std::string& s)
|
||||
{
|
||||
if (s.empty())
|
||||
return{};
|
||||
|
2
external/tox_ngc_ext/tox_ngc_ext
vendored
2
external/tox_ngc_ext/tox_ngc_ext
vendored
Submodule external/tox_ngc_ext/tox_ngc_ext updated: c947915389...026bf080c3
3
external/tox_ngc_ft1/CMakeLists.txt
vendored
3
external/tox_ngc_ft1/CMakeLists.txt
vendored
@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
add_library(tox_ngc_ft1 STATIC
|
||||
./tox_ngc_ft1/ngc_ft1.h
|
||||
./tox_ngc_ft1/ngc_ft1.cpp
|
||||
|
||||
./tox_ngc_ft1/ledbat.hpp
|
||||
./tox_ngc_ft1/ledbat.cpp
|
||||
)
|
||||
|
||||
target_include_directories(tox_ngc_ft1 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/tox_ngc_ft1")
|
||||
|
2
external/tox_ngc_ft1/tox_ngc_ft1
vendored
2
external/tox_ngc_ft1/tox_ngc_ft1
vendored
Submodule external/tox_ngc_ft1/tox_ngc_ft1 updated: 04befb21be...08a083f346
194
external/toxcore/CMakeLists.txt
vendored
194
external/toxcore/CMakeLists.txt
vendored
@ -2,6 +2,198 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
include(./toxcore.cmake)
|
||||
set(TOX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c-toxcore/")
|
||||
|
||||
# TODO: shared
|
||||
add_library(toxcore STATIC
|
||||
${TOX_DIR}third_party/cmp/cmp.c
|
||||
${TOX_DIR}third_party/cmp/cmp.h
|
||||
|
||||
${TOX_DIR}toxcore/announce.c
|
||||
${TOX_DIR}toxcore/announce.h
|
||||
${TOX_DIR}toxcore/bin_pack.c
|
||||
${TOX_DIR}toxcore/bin_pack.h
|
||||
${TOX_DIR}toxcore/bin_unpack.c
|
||||
${TOX_DIR}toxcore/bin_unpack.h
|
||||
${TOX_DIR}toxcore/ccompat.c
|
||||
${TOX_DIR}toxcore/ccompat.h
|
||||
${TOX_DIR}toxcore/crypto_core.c
|
||||
${TOX_DIR}toxcore/crypto_core.h
|
||||
${TOX_DIR}toxcore/DHT.c
|
||||
${TOX_DIR}toxcore/DHT.h
|
||||
${TOX_DIR}toxcore/events/conference_connected.c
|
||||
${TOX_DIR}toxcore/events/conference_invite.c
|
||||
${TOX_DIR}toxcore/events/conference_message.c
|
||||
${TOX_DIR}toxcore/events/conference_peer_list_changed.c
|
||||
${TOX_DIR}toxcore/events/conference_peer_name.c
|
||||
${TOX_DIR}toxcore/events/conference_title.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.h
|
||||
${TOX_DIR}toxcore/events/file_chunk_request.c
|
||||
${TOX_DIR}toxcore/events/file_recv.c
|
||||
${TOX_DIR}toxcore/events/file_recv_chunk.c
|
||||
${TOX_DIR}toxcore/events/file_recv_control.c
|
||||
${TOX_DIR}toxcore/events/friend_connection_status.c
|
||||
${TOX_DIR}toxcore/events/friend_lossless_packet.c
|
||||
${TOX_DIR}toxcore/events/friend_lossy_packet.c
|
||||
${TOX_DIR}toxcore/events/friend_message.c
|
||||
${TOX_DIR}toxcore/events/friend_name.c
|
||||
${TOX_DIR}toxcore/events/friend_read_receipt.c
|
||||
${TOX_DIR}toxcore/events/friend_request.c
|
||||
${TOX_DIR}toxcore/events/friend_status.c
|
||||
${TOX_DIR}toxcore/events/friend_status_message.c
|
||||
${TOX_DIR}toxcore/events/friend_typing.c
|
||||
${TOX_DIR}toxcore/events/self_connection_status.c
|
||||
#${TOX_DIR}toxcore/events/group_custom_packet.c
|
||||
#${TOX_DIR}toxcore/events/group_custom_private_packet.c
|
||||
#${TOX_DIR}toxcore/events/group_invite.c
|
||||
#${TOX_DIR}toxcore/events/group_join_fail.c
|
||||
#${TOX_DIR}toxcore/events/group_message.c
|
||||
#${TOX_DIR}toxcore/events/group_moderation.c
|
||||
#${TOX_DIR}toxcore/events/group_password.c
|
||||
#${TOX_DIR}toxcore/events/group_peer_exit.c
|
||||
#${TOX_DIR}toxcore/events/group_peer_join.c
|
||||
#${TOX_DIR}toxcore/events/group_peer_limit.c
|
||||
#${TOX_DIR}toxcore/events/group_peer_name.c
|
||||
#${TOX_DIR}toxcore/events/group_peer_status.c
|
||||
#${TOX_DIR}toxcore/events/group_privacy_state.c
|
||||
#${TOX_DIR}toxcore/events/group_private_message.c
|
||||
#${TOX_DIR}toxcore/events/group_self_join.c
|
||||
#${TOX_DIR}toxcore/events/group_topic.c
|
||||
#${TOX_DIR}toxcore/events/group_topic_lock.c
|
||||
#${TOX_DIR}toxcore/events/group_voice_state.c
|
||||
${TOX_DIR}toxcore/forwarding.c
|
||||
${TOX_DIR}toxcore/forwarding.h
|
||||
${TOX_DIR}toxcore/friend_connection.c
|
||||
${TOX_DIR}toxcore/friend_connection.h
|
||||
${TOX_DIR}toxcore/friend_requests.c
|
||||
${TOX_DIR}toxcore/friend_requests.h
|
||||
${TOX_DIR}toxcore/group.c
|
||||
${TOX_DIR}toxcore/group.h
|
||||
${TOX_DIR}toxcore/group_announce.c
|
||||
${TOX_DIR}toxcore/group_announce.h
|
||||
${TOX_DIR}toxcore/group_moderation.c
|
||||
${TOX_DIR}toxcore/group_moderation.h
|
||||
${TOX_DIR}toxcore/group_chats.c
|
||||
${TOX_DIR}toxcore/group_chats.h
|
||||
${TOX_DIR}toxcore/group_common.h
|
||||
${TOX_DIR}toxcore/group_connection.c
|
||||
${TOX_DIR}toxcore/group_connection.h
|
||||
${TOX_DIR}toxcore/group_onion_announce.c
|
||||
${TOX_DIR}toxcore/group_onion_announce.h
|
||||
${TOX_DIR}toxcore/group_pack.c
|
||||
${TOX_DIR}toxcore/group_pack.h
|
||||
${TOX_DIR}toxcore/LAN_discovery.c
|
||||
${TOX_DIR}toxcore/LAN_discovery.h
|
||||
${TOX_DIR}toxcore/list.c
|
||||
${TOX_DIR}toxcore/list.h
|
||||
${TOX_DIR}toxcore/logger.c
|
||||
${TOX_DIR}toxcore/logger.h
|
||||
${TOX_DIR}toxcore/Messenger.c
|
||||
${TOX_DIR}toxcore/Messenger.h
|
||||
${TOX_DIR}toxcore/mem.c
|
||||
${TOX_DIR}toxcore/mem.h
|
||||
${TOX_DIR}toxcore/mono_time.c
|
||||
${TOX_DIR}toxcore/mono_time.h
|
||||
${TOX_DIR}toxcore/net_crypto.c
|
||||
${TOX_DIR}toxcore/net_crypto.h
|
||||
${TOX_DIR}toxcore/network.c
|
||||
${TOX_DIR}toxcore/network.h
|
||||
${TOX_DIR}toxcore/onion_announce.c
|
||||
${TOX_DIR}toxcore/onion_announce.h
|
||||
${TOX_DIR}toxcore/onion.c
|
||||
${TOX_DIR}toxcore/onion_client.c
|
||||
${TOX_DIR}toxcore/onion_client.h
|
||||
${TOX_DIR}toxcore/onion.h
|
||||
${TOX_DIR}toxcore/ping_array.c
|
||||
${TOX_DIR}toxcore/ping_array.h
|
||||
${TOX_DIR}toxcore/ping.c
|
||||
${TOX_DIR}toxcore/ping.h
|
||||
${TOX_DIR}toxcore/shared_key_cache.c
|
||||
${TOX_DIR}toxcore/shared_key_cache.h
|
||||
${TOX_DIR}toxcore/state.c
|
||||
${TOX_DIR}toxcore/state.h
|
||||
${TOX_DIR}toxcore/TCP_client.c
|
||||
${TOX_DIR}toxcore/TCP_client.h
|
||||
${TOX_DIR}toxcore/TCP_common.c
|
||||
${TOX_DIR}toxcore/TCP_common.h
|
||||
${TOX_DIR}toxcore/TCP_connection.c
|
||||
${TOX_DIR}toxcore/TCP_connection.h
|
||||
${TOX_DIR}toxcore/TCP_server.c
|
||||
${TOX_DIR}toxcore/TCP_server.h
|
||||
${TOX_DIR}toxcore/timed_auth.c
|
||||
${TOX_DIR}toxcore/timed_auth.h
|
||||
${TOX_DIR}toxcore/tox_api.c
|
||||
${TOX_DIR}toxcore/tox.c
|
||||
${TOX_DIR}toxcore/tox_dispatch.c
|
||||
${TOX_DIR}toxcore/tox_dispatch.h
|
||||
${TOX_DIR}toxcore/tox_events.c
|
||||
${TOX_DIR}toxcore/tox_events.h
|
||||
${TOX_DIR}toxcore/tox.h
|
||||
${TOX_DIR}toxcore/tox_private.c
|
||||
${TOX_DIR}toxcore/tox_private.h
|
||||
${TOX_DIR}toxcore/tox_unpack.c
|
||||
${TOX_DIR}toxcore/tox_unpack.h
|
||||
${TOX_DIR}toxcore/util.c
|
||||
${TOX_DIR}toxcore/util.h
|
||||
)
|
||||
|
||||
# HACK: "install" api headers into self
|
||||
# this is dirty, should be binary dir
|
||||
# TODO: add the others
|
||||
configure_file(
|
||||
${TOX_DIR}toxcore/tox.h
|
||||
${TOX_DIR}tox/tox.h
|
||||
@ONLY
|
||||
)
|
||||
configure_file(
|
||||
${TOX_DIR}toxcore/tox_events.h
|
||||
${TOX_DIR}tox/tox_events.h
|
||||
@ONLY
|
||||
)
|
||||
|
||||
target_include_directories(toxcore PRIVATE "${TOX_DIR}toxcore")
|
||||
target_include_directories(toxcore PUBLIC "${TOX_DIR}")
|
||||
|
||||
target_compile_definitions(toxcore PUBLIC USE_IPV6=1)
|
||||
#target_compile_definitions(toxcore PUBLIC MIN_LOGGER_LEVEL=LOGGER_LEVEL_DEBUG)
|
||||
target_compile_definitions(toxcore PUBLIC MIN_LOGGER_LEVEL=LOGGER_LEVEL_INFO)
|
||||
|
||||
find_package(unofficial-sodium CONFIG QUIET)
|
||||
find_package(sodium QUIET)
|
||||
if(unofficial-sodium_FOUND) # vcpkg
|
||||
if(TARGET unofficial-sodium::sodium)
|
||||
target_link_libraries(toxcore unofficial-sodium::sodium)
|
||||
endif()
|
||||
if(TARGET unofficial-sodium::sodium_config_public)
|
||||
target_link_libraries(toxcore unofficial-sodium::sodium_config_public)
|
||||
endif()
|
||||
elseif(sodium_FOUND)
|
||||
target_link_libraries(toxcore sodium)
|
||||
else()
|
||||
message(SEND_ERROR "missing libsodium")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(toxcore ws2_32 iphlpapi)
|
||||
endif()
|
||||
|
||||
find_package(pthreads QUIET)
|
||||
if(TARGET PThreads4W::PThreads4W)
|
||||
target_link_libraries(toxcore PThreads4W::PThreads4W)
|
||||
else()
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(toxcore Threads::Threads)
|
||||
endif()
|
||||
|
||||
add_executable(DHT_Bootstrap EXCLUDE_FROM_ALL
|
||||
${TOX_DIR}other/DHT_bootstrap.c
|
||||
${TOX_DIR}other/bootstrap_node_packets.h
|
||||
${TOX_DIR}other/bootstrap_node_packets.c
|
||||
${TOX_DIR}testing/misc_tools.h
|
||||
${TOX_DIR}testing/misc_tools.c
|
||||
)
|
||||
|
||||
target_link_libraries(DHT_Bootstrap toxcore)
|
||||
|
||||
|
2
external/toxcore/c-toxcore
vendored
2
external/toxcore/c-toxcore
vendored
Submodule external/toxcore/c-toxcore updated: 88ffd1a649...24b54722ae
158
external/toxcore/toxcore.cmake
vendored
158
external/toxcore/toxcore.cmake
vendored
@ -1,158 +0,0 @@
|
||||
set(TOX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c-toxcore/")
|
||||
|
||||
# TODO: shared
|
||||
add_library(toxcore STATIC
|
||||
${TOX_DIR}third_party/cmp/cmp.c
|
||||
${TOX_DIR}third_party/cmp/cmp.h
|
||||
|
||||
${TOX_DIR}toxcore/announce.c
|
||||
${TOX_DIR}toxcore/announce.h
|
||||
${TOX_DIR}toxcore/bin_pack.c
|
||||
${TOX_DIR}toxcore/bin_pack.h
|
||||
${TOX_DIR}toxcore/bin_unpack.c
|
||||
${TOX_DIR}toxcore/bin_unpack.h
|
||||
${TOX_DIR}toxcore/ccompat.c
|
||||
${TOX_DIR}toxcore/ccompat.h
|
||||
${TOX_DIR}toxcore/crypto_core.c
|
||||
${TOX_DIR}toxcore/crypto_core.h
|
||||
${TOX_DIR}toxcore/DHT.c
|
||||
${TOX_DIR}toxcore/DHT.h
|
||||
${TOX_DIR}toxcore/events/conference_connected.c
|
||||
${TOX_DIR}toxcore/events/conference_invite.c
|
||||
${TOX_DIR}toxcore/events/conference_message.c
|
||||
${TOX_DIR}toxcore/events/conference_peer_list_changed.c
|
||||
${TOX_DIR}toxcore/events/conference_peer_name.c
|
||||
${TOX_DIR}toxcore/events/conference_title.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.c
|
||||
${TOX_DIR}toxcore/events/events_alloc.h
|
||||
${TOX_DIR}toxcore/events/file_chunk_request.c
|
||||
${TOX_DIR}toxcore/events/file_recv.c
|
||||
${TOX_DIR}toxcore/events/file_recv_chunk.c
|
||||
${TOX_DIR}toxcore/events/file_recv_control.c
|
||||
${TOX_DIR}toxcore/events/friend_connection_status.c
|
||||
${TOX_DIR}toxcore/events/friend_lossless_packet.c
|
||||
${TOX_DIR}toxcore/events/friend_lossy_packet.c
|
||||
${TOX_DIR}toxcore/events/friend_message.c
|
||||
${TOX_DIR}toxcore/events/friend_name.c
|
||||
${TOX_DIR}toxcore/events/friend_read_receipt.c
|
||||
${TOX_DIR}toxcore/events/friend_request.c
|
||||
${TOX_DIR}toxcore/events/friend_status.c
|
||||
${TOX_DIR}toxcore/events/friend_status_message.c
|
||||
${TOX_DIR}toxcore/events/friend_typing.c
|
||||
${TOX_DIR}toxcore/events/self_connection_status.c
|
||||
${TOX_DIR}toxcore/forwarding.c
|
||||
${TOX_DIR}toxcore/forwarding.h
|
||||
${TOX_DIR}toxcore/friend_connection.c
|
||||
${TOX_DIR}toxcore/friend_connection.h
|
||||
${TOX_DIR}toxcore/friend_requests.c
|
||||
${TOX_DIR}toxcore/friend_requests.h
|
||||
${TOX_DIR}toxcore/group.c
|
||||
${TOX_DIR}toxcore/group.h
|
||||
${TOX_DIR}toxcore/group_announce.c
|
||||
${TOX_DIR}toxcore/group_announce.h
|
||||
${TOX_DIR}toxcore/group_moderation.c
|
||||
${TOX_DIR}toxcore/group_moderation.h
|
||||
${TOX_DIR}toxcore/group_chats.c
|
||||
${TOX_DIR}toxcore/group_chats.h
|
||||
${TOX_DIR}toxcore/group_common.h
|
||||
${TOX_DIR}toxcore/group_connection.c
|
||||
${TOX_DIR}toxcore/group_connection.h
|
||||
${TOX_DIR}toxcore/group_onion_announce.c
|
||||
${TOX_DIR}toxcore/group_onion_announce.h
|
||||
${TOX_DIR}toxcore/group_pack.c
|
||||
${TOX_DIR}toxcore/group_pack.h
|
||||
${TOX_DIR}toxcore/LAN_discovery.c
|
||||
${TOX_DIR}toxcore/LAN_discovery.h
|
||||
${TOX_DIR}toxcore/list.c
|
||||
${TOX_DIR}toxcore/list.h
|
||||
${TOX_DIR}toxcore/logger.c
|
||||
${TOX_DIR}toxcore/logger.h
|
||||
${TOX_DIR}toxcore/Messenger.c
|
||||
${TOX_DIR}toxcore/Messenger.h
|
||||
${TOX_DIR}toxcore/mono_time.c
|
||||
${TOX_DIR}toxcore/mono_time.h
|
||||
${TOX_DIR}toxcore/net_crypto.c
|
||||
${TOX_DIR}toxcore/net_crypto.h
|
||||
${TOX_DIR}toxcore/network.c
|
||||
${TOX_DIR}toxcore/network.h
|
||||
${TOX_DIR}toxcore/onion_announce.c
|
||||
${TOX_DIR}toxcore/onion_announce.h
|
||||
${TOX_DIR}toxcore/onion.c
|
||||
${TOX_DIR}toxcore/onion_client.c
|
||||
${TOX_DIR}toxcore/onion_client.h
|
||||
${TOX_DIR}toxcore/onion.h
|
||||
${TOX_DIR}toxcore/ping_array.c
|
||||
${TOX_DIR}toxcore/ping_array.h
|
||||
${TOX_DIR}toxcore/ping.c
|
||||
${TOX_DIR}toxcore/ping.h
|
||||
${TOX_DIR}toxcore/shared_key_cache.c
|
||||
${TOX_DIR}toxcore/shared_key_cache.h
|
||||
${TOX_DIR}toxcore/state.c
|
||||
${TOX_DIR}toxcore/state.h
|
||||
${TOX_DIR}toxcore/TCP_client.c
|
||||
${TOX_DIR}toxcore/TCP_client.h
|
||||
${TOX_DIR}toxcore/TCP_common.c
|
||||
${TOX_DIR}toxcore/TCP_common.h
|
||||
${TOX_DIR}toxcore/TCP_connection.c
|
||||
${TOX_DIR}toxcore/TCP_connection.h
|
||||
${TOX_DIR}toxcore/TCP_server.c
|
||||
${TOX_DIR}toxcore/TCP_server.h
|
||||
${TOX_DIR}toxcore/timed_auth.c
|
||||
${TOX_DIR}toxcore/timed_auth.h
|
||||
${TOX_DIR}toxcore/tox_api.c
|
||||
${TOX_DIR}toxcore/tox.c
|
||||
${TOX_DIR}toxcore/tox_dispatch.c
|
||||
${TOX_DIR}toxcore/tox_dispatch.h
|
||||
${TOX_DIR}toxcore/tox_events.c
|
||||
${TOX_DIR}toxcore/tox_events.h
|
||||
${TOX_DIR}toxcore/tox.h
|
||||
${TOX_DIR}toxcore/tox_private.c
|
||||
${TOX_DIR}toxcore/tox_private.h
|
||||
${TOX_DIR}toxcore/tox_unpack.c
|
||||
${TOX_DIR}toxcore/tox_unpack.h
|
||||
${TOX_DIR}toxcore/util.c
|
||||
${TOX_DIR}toxcore/util.h
|
||||
)
|
||||
|
||||
# HACK: "install" api headers into self
|
||||
# this is dirty, should be binary dir
|
||||
# TODO: add the others
|
||||
configure_file(
|
||||
${TOX_DIR}toxcore/tox.h
|
||||
${TOX_DIR}tox/tox.h
|
||||
@ONLY
|
||||
)
|
||||
|
||||
target_include_directories(toxcore PRIVATE "${TOX_DIR}toxcore")
|
||||
target_include_directories(toxcore PUBLIC "${TOX_DIR}")
|
||||
|
||||
target_compile_definitions(toxcore PUBLIC USE_IPV6=1)
|
||||
target_compile_definitions(toxcore PUBLIC MIN_LOGGER_LEVEL=LOGGER_LEVEL_DEBUG)
|
||||
|
||||
find_package(unofficial-sodium CONFIG QUIET)
|
||||
find_package(sodium QUIET)
|
||||
if(unofficial-sodium_FOUND) # vcpkg
|
||||
target_link_libraries(toxcore unofficial-sodium::sodium unofficial-sodium::sodium_config_public)
|
||||
elseif(sodium_FOUND)
|
||||
target_link_libraries(toxcore sodium)
|
||||
else()
|
||||
message(SEND_ERROR "missing libsodium")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(toxcore ws2_32 iphlpapi)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(toxcore Threads::Threads)
|
||||
|
||||
add_executable(DHT_Bootstrap EXCLUDE_FROM_ALL
|
||||
${TOX_DIR}other/DHT_bootstrap.c
|
||||
${TOX_DIR}other/bootstrap_node_packets.h
|
||||
${TOX_DIR}other/bootstrap_node_packets.c
|
||||
${TOX_DIR}testing/misc_tools.h
|
||||
${TOX_DIR}testing/misc_tools.c
|
||||
)
|
||||
|
||||
target_link_libraries(DHT_Bootstrap toxcore)
|
||||
|
@ -1,85 +1,135 @@
|
||||
#include "./command_line.hpp"
|
||||
|
||||
#include <charconv>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
struct CLParser {
|
||||
const size_t argc;
|
||||
const char*const* argv;
|
||||
size_t& i;
|
||||
|
||||
bool error {false};
|
||||
|
||||
bool parseFlag(std::string_view arg_sv, bool& flag) {
|
||||
std::string_view arg0_sv{argv[i]};
|
||||
|
||||
if (arg0_sv != arg_sv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flag = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename FN, typename Arg0, typename ...Args>
|
||||
static void visit(FN&& fn, Arg0&& arg0, Args&& ...args) {
|
||||
fn(arg0);
|
||||
(fn(args),...);
|
||||
}
|
||||
|
||||
template<typename Arg0, typename ...Args>
|
||||
bool parseParam(std::string_view arg_sv, Arg0& arg0, Args& ...args) {
|
||||
std::string_view arg0_sv{argv[i]};
|
||||
|
||||
if (arg0_sv != arg_sv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (argc < 1+1+sizeof...(args)) {
|
||||
std::cerr << "ERROR: " << arg_sv << " not enough parameters!\n\n";
|
||||
error = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
visit([this](auto& arg) {
|
||||
if (error) return;
|
||||
|
||||
std::string_view argX_sv{argv[++i]};
|
||||
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, std::string>) {
|
||||
arg = argX_sv;
|
||||
} else if constexpr (std::is_integral_v<T>) {
|
||||
auto res = std::from_chars(argX_sv.data(), argX_sv.data()+argX_sv.size(), arg);
|
||||
if (res.ptr != argX_sv.data() + argX_sv.size()) {
|
||||
std::cerr << "ERROR: invalid parameter!\n\n";
|
||||
error = true;
|
||||
//PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, float>) {
|
||||
// HACK: wait for more charconv <.<
|
||||
std::string tmp_str {argX_sv};
|
||||
arg = std::stof(tmp_str);
|
||||
} else {
|
||||
assert(false && "invalid parameter type");
|
||||
}
|
||||
}, arg0, args...);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CommandLine::CommandLine(int argc, char** argv) {
|
||||
assert(argc > 0);
|
||||
|
||||
exe = argv[0];
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::string_view arg_sv{argv[i]};
|
||||
for (size_t i = 1; i < size_t(argc); i++) {
|
||||
CLParser parser{size_t(argc), argv, i};
|
||||
std::string_view arg_sv{argv[i]}; // alt
|
||||
|
||||
#define PRINT_HELP_AND_BAIL printHelp(); _should_exit = true; return;
|
||||
|
||||
if (arg_sv == "-v") {
|
||||
version = true;
|
||||
if (parser.parseFlag("-v", version)) {
|
||||
_should_exit = true;
|
||||
} else if (arg_sv == "-V") {
|
||||
verbose = true;
|
||||
} else if (parser.parseFlag("-V", verbose)) {
|
||||
} else if (arg_sv == "-h") {
|
||||
help = true;
|
||||
printHelp();
|
||||
_should_exit = true;
|
||||
} else if (arg_sv == "-G") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -G missing <chat_id> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
chat_id = argv[++i];
|
||||
} else if (arg_sv == "-F") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -F missing <path> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
profile_path = argv[++i];
|
||||
} else if (arg_sv == "-N") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -N missing <self_name> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
self_name = argv[++i];
|
||||
} else if (arg_sv == "-a") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -a missing <transfer_variant> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
std::string_view tv_sv{argv[++i]};
|
||||
|
||||
if (tv_sv == "id1") {
|
||||
} else if (parser.parseParam("-G", chat_id)) {
|
||||
} else if (parser.parseParam("-F", profile_path)) {
|
||||
} else if (parser.parseParam("-N", self_name)) {
|
||||
} else if (std::string tv; parser.parseParam("-a", tv)) {
|
||||
if (tv == "id1") {
|
||||
transfer_variant = TransferE::ID;
|
||||
} else if (tv_sv == "sha1_single") {
|
||||
} else if (tv == "sha1_single") {
|
||||
transfer_variant = TransferE::SHA1_SINGLE;
|
||||
} else if (tv_sv == "sha1_info") {
|
||||
} else if (tv == "sha1_info") {
|
||||
transfer_variant = TransferE::SHA1_INFO;
|
||||
} else {
|
||||
std::cerr << "ERROR: invalid <transfer_variant> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
|
||||
} else if (arg_sv == "-f") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -f missing <path> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
send_path = argv[++i];
|
||||
} else if (arg_sv == "-d") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -d missing <path> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
receive_dump_dir = argv[++i];
|
||||
} else if (arg_sv == "-D") {
|
||||
if (i+1 >= argc) {
|
||||
std::cerr << "ERROR: -D missing <id/hash> parameter!\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
receive_id = argv[++i];
|
||||
} else if (parser.parseParam("-f", send_path)) {
|
||||
} else if (parser.parseParam("-d", receive_dump_dir)) {
|
||||
std::cout << "CL going to write to '" << receive_dump_dir << "'\n";
|
||||
} else if (parser.parseParam("-D", receive_id)) {
|
||||
} else if (parser.parseFlag("-L", tox_disable_local_discovery)) {
|
||||
std::cout << "CL disabled local discovery\n";
|
||||
} else if (parser.parseFlag("-U", tox_disable_udp)) {
|
||||
std::cout << "CL disabled udp\n";
|
||||
} else if (parser.parseParam("-P", proxy_host, proxy_port)) {
|
||||
std::cout << "CL set proxy to " << proxy_host << proxy_port << "\n";
|
||||
} else if (parser.parseParam("-p", tox_port)) {
|
||||
std::cout << "CL set tox_port to " << tox_port << "\n";
|
||||
} else if (parser.parseParam("--ft_ack_per_packet", ft_acks_per_packet)) {
|
||||
} else if (parser.parseParam("--ft_init_retry_timeout_after", ft_init_retry_timeout_after)) {
|
||||
} else if (parser.parseParam("--ft_sending_give_up_after", ft_sending_give_up_after)) {
|
||||
} else if (parser.parseParam("-I", max_incoming_transfers)) {
|
||||
} else if (parser.parseParam("-O", max_outgoing_transfers)) {
|
||||
} else {
|
||||
std::cerr << "ERROR: unknown parameter '" << arg_sv << "' !\n\n";
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
|
||||
if (parser.error) {
|
||||
PRINT_HELP_AND_BAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (transfer_variant == TransferE::INVALID) {
|
||||
@ -102,7 +152,7 @@ void CommandLine::printHelp(void) {
|
||||
<< " -N <self_name> (defaults to 'tox_ngc_ft1_tool')\n"
|
||||
<< " will print friend id at startup\n"
|
||||
<< " will autoaccept any invite\n"
|
||||
<< " if no -F give, will not save profile.\n"
|
||||
<< " if no -F given, will not save profile.\n"
|
||||
<< " if profile exists load, otherwise create new\n"
|
||||
<< "\n"
|
||||
<< " transfer variant:\n"
|
||||
@ -114,6 +164,22 @@ void CommandLine::printHelp(void) {
|
||||
<< " receive:\n"
|
||||
<< " -d dump/everything/in/this/dir\n"
|
||||
<< " -D <id/hash> (what to dl)\n"
|
||||
<< "\n"
|
||||
<< "!!! ADVANCED !!!\n"
|
||||
<< " tox:\n"
|
||||
<< " -L disable local discovery\n"
|
||||
<< " -U disable udp\n"
|
||||
<< " -P proxy_host proxy_port\n"
|
||||
<< " -p tox_port (bind tox to that port)\n"
|
||||
<< "\n"
|
||||
<< " FT1:\n"
|
||||
<< " --ft_ack_per_packet\n"
|
||||
<< " --ft_init_retry_timeout_after\n"
|
||||
<< " --ft_sending_give_up_after\n"
|
||||
<< "\n"
|
||||
<< " transfer logic:\n"
|
||||
<< " -I <max_incoming_transfers>\n"
|
||||
<< " -O <max_outgoing_transfers>\n"
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -2,30 +2,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
// meta:
|
||||
// -v version info
|
||||
// -V verbose
|
||||
// -h help
|
||||
//
|
||||
// connectivity:
|
||||
// -G <chat_id>
|
||||
// -F profile.tox
|
||||
// -N <self_name>
|
||||
// will print friend id at startup
|
||||
// will autoaccept any invite
|
||||
// if no -F give, will not save profile.
|
||||
// if profile exists load, otherwise create new
|
||||
//
|
||||
// transfer variant:
|
||||
// -a id1/sha1_single/sha1_info/sha2_single/sha2_info
|
||||
//
|
||||
// send:
|
||||
// -f send_this_file.zip
|
||||
//
|
||||
// receive:
|
||||
// -d dump/everything/in/this/dir
|
||||
// -D <id/hash> (what to dl)
|
||||
|
||||
enum class TransferE {
|
||||
INVALID,
|
||||
|
||||
@ -68,6 +44,35 @@ struct CommandLine {
|
||||
// -D <id/hash> (what to dl)
|
||||
std::string receive_id;
|
||||
|
||||
// advanced tox:
|
||||
// -L disable local discovery
|
||||
bool tox_disable_local_discovery {false};
|
||||
// -U disable udp (why?)
|
||||
bool tox_disable_udp {false};
|
||||
// -P proxy_host proxy_port
|
||||
std::string proxy_host;
|
||||
uint16_t proxy_port {0};
|
||||
// -p port (start and end is set to the same port)
|
||||
uint16_t tox_port {0};
|
||||
|
||||
// advanced FT1:
|
||||
// --ft_ack_per_packet
|
||||
size_t ft_acks_per_packet {3};
|
||||
// --ft_init_retry_timeout_after
|
||||
float ft_init_retry_timeout_after {5.f};
|
||||
// --ft_sending_give_up_after
|
||||
float ft_sending_give_up_after {30.f};
|
||||
|
||||
// ---- TODO ----
|
||||
|
||||
// advaced dl:
|
||||
// -I max_incoming_transfers
|
||||
size_t max_incoming_transfers {32};
|
||||
// -O max_outgoing_transfers
|
||||
size_t max_outgoing_transfers {8};
|
||||
// -u request chunks only from UDP-direct peers
|
||||
bool request_only_from_udp_peer {false};
|
||||
|
||||
CommandLine(int argc, char** argv);
|
||||
|
||||
void printHelp(void);
|
||||
|
@ -54,20 +54,28 @@ std::vector<uint8_t> FTInfoSHA1::toBuffer(void) const {
|
||||
}
|
||||
assert(buffer.size() == 256+8);
|
||||
|
||||
// chunk size?
|
||||
// chunk size
|
||||
{ // HACK: endianess
|
||||
buffer.push_back((chunk_size>>(0*8)) & 0xff);
|
||||
buffer.push_back((chunk_size>>(1*8)) & 0xff);
|
||||
buffer.push_back((chunk_size>>(2*8)) & 0xff);
|
||||
buffer.push_back((chunk_size>>(3*8)) & 0xff);
|
||||
}
|
||||
|
||||
assert(buffer.size() == 256+8+4);
|
||||
|
||||
for (const auto& chunk : chunks) {
|
||||
for (size_t i = 0; i < chunk.data.size(); i++) {
|
||||
buffer.push_back(chunk.data[i]);
|
||||
}
|
||||
}
|
||||
assert(buffer.size() == 256+8+20*chunks.size());
|
||||
assert(buffer.size() == 256+8+4+20*chunks.size());
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void FTInfoSHA1::fromBuffer(const std::vector<uint8_t>& buffer) {
|
||||
assert(buffer.size() >= 256+8);
|
||||
assert(buffer.size() >= 256+8+4);
|
||||
|
||||
// TODO: optimize
|
||||
file_name.clear();
|
||||
@ -91,9 +99,17 @@ void FTInfoSHA1::fromBuffer(const std::vector<uint8_t>& buffer) {
|
||||
file_size |= uint64_t(buffer[256+7]) << (7*8);
|
||||
}
|
||||
|
||||
assert((buffer.size()-(256+8)) % 20 == 0);
|
||||
{ // HACK: endianess
|
||||
chunk_size = 0;
|
||||
chunk_size |= uint32_t(buffer[256+8+0]) << (0*8);
|
||||
chunk_size |= uint32_t(buffer[256+8+1]) << (1*8);
|
||||
chunk_size |= uint32_t(buffer[256+8+2]) << (2*8);
|
||||
chunk_size |= uint32_t(buffer[256+8+3]) << (3*8);
|
||||
}
|
||||
|
||||
for (size_t offset = 256+8; offset < buffer.size();) {
|
||||
assert((buffer.size()-(256+8+4)) % 20 == 0);
|
||||
|
||||
for (size_t offset = 256+8+4; offset < buffer.size();) {
|
||||
assert(buffer.size() >= offset + 20);
|
||||
|
||||
auto& chunk = chunks.emplace_back();
|
||||
@ -107,6 +123,7 @@ void FTInfoSHA1::fromBuffer(const std::vector<uint8_t>& buffer) {
|
||||
std::ostream& operator<<(std::ostream& out, const FTInfoSHA1& v) {
|
||||
out << " file_name: " << v.file_name << "\n";
|
||||
out << " file_size: " << v.file_size << "\n";
|
||||
out << " chunk_size: " << v.chunk_size << "\n";
|
||||
out << " chunks.size(): " << v.chunks.size() << "\n";
|
||||
return out;
|
||||
}
|
||||
|
@ -43,12 +43,23 @@ namespace std { // inject
|
||||
struct FTInfoSHA1 {
|
||||
std::string file_name;
|
||||
uint64_t file_size {0};
|
||||
static constexpr size_t chunk_size {64*1024}; // 64KiB for now
|
||||
uint32_t chunk_size {128*1024}; // 128KiB for now
|
||||
std::vector<SHA1Digest> chunks;
|
||||
|
||||
std::vector<uint8_t> toBuffer(void) const;
|
||||
void fromBuffer(const std::vector<uint8_t>& buffer);
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& out, const FTInfoSHA1& v);
|
||||
|
||||
// TODO: use
|
||||
struct FTInfoSHA1v2 {
|
||||
std::vector<std::string> file_names;
|
||||
uint64_t file_size {0};
|
||||
uint32_t chunk_size {128*1024}; // 128KiB for now
|
||||
std::vector<SHA1Digest> chunks;
|
||||
|
||||
std::vector<uint8_t> toBuffer(void) const;
|
||||
void fromBuffer(const std::vector<uint8_t>& buffer);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const FTInfoSHA1& v);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
// returns the 20bytes sha1 hash
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace States {
|
||||
|
||||
ReceiveStartSHA1::ReceiveStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl) {
|
||||
ReceiveStartSHA1::ReceiveStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl), _cl(cl), _dump_dir(cl.receive_dump_dir) {
|
||||
if (cl.receive_id.empty()) {
|
||||
throw std::runtime_error("receiver missing id");
|
||||
}
|
||||
@ -41,14 +41,13 @@ bool ReceiveStartSHA1::iterate(float delta) {
|
||||
|
||||
// timout if not heard after 10s
|
||||
if (time_since_remote_activity >= 10.f) {
|
||||
std::cerr << "ReceiveStartSHA1 info tansfer timed out " << std::get<0>(*_transfer) << ":" << std::get<1>(*_transfer) << "." << std::get<2>(*_transfer) << "\n";
|
||||
std::cerr << "ReceiveStartSHA1 info tansfer timed out " << std::get<0>(*_transfer) << ":" << std::get<1>(*_transfer) << "." << int(std::get<2>(*_transfer)) << "\n";
|
||||
|
||||
_transfer.reset();
|
||||
}
|
||||
} else if (_time_since_last_request >= 15.f) { // blast ever 15sec
|
||||
_time_since_last_request = 0.f;
|
||||
// TODO: select random and try, not blas
|
||||
// ... and we are blasing
|
||||
|
||||
_tcl.forEachGroup([this](const uint32_t group_number) {
|
||||
_tcl.forEachGroupPeer(group_number, [this, group_number](uint32_t peer_number) {
|
||||
_tcl.sendFT1RequestPrivate(
|
||||
@ -56,13 +55,17 @@ bool ReceiveStartSHA1::iterate(float delta) {
|
||||
NGC_FT1_file_kind::HASH_SHA1_INFO,
|
||||
_sha1_info_hash.data.data(), _sha1_info_hash.size()
|
||||
);
|
||||
std::cout << "ReceiveStartSHA1 sendig info request to " << group_number << ":" << peer_number << "\n";
|
||||
std::cout
|
||||
<< "ReceiveStartSHA1 sendig info request to "
|
||||
<< group_number << ":" << peer_number
|
||||
<< " over " << (_tcl.getGroupPeerConnectionStatus(group_number, peer_number) == Tox_Connection::TOX_CONNECTION_TCP ? "tcp" : "udp")
|
||||
<< "\n"
|
||||
;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// if not transfer, request from random peer (equal dist!!)
|
||||
// TODO: return true if done
|
||||
return _done;
|
||||
}
|
||||
|
||||
@ -72,38 +75,49 @@ std::unique_ptr<StateI> ReceiveStartSHA1::nextState(void) {
|
||||
|
||||
std::cout << "ReceiveStartSHA1 info is: \n" << sha1_info;
|
||||
|
||||
bool file_existed = std::filesystem::exists(sha1_info.file_name);
|
||||
auto file_path = std::filesystem::path{_dump_dir} / sha1_info.file_name;
|
||||
|
||||
bool file_existed = std::filesystem::exists(file_path);
|
||||
if (!file_existed) {
|
||||
std::ofstream(sha1_info.file_name) << '\0'; // create the file
|
||||
if (!_dump_dir.empty()) {
|
||||
std::filesystem::create_directories(_dump_dir);
|
||||
}
|
||||
std::filesystem::resize_file(sha1_info.file_name, sha1_info.file_size);
|
||||
std::ofstream(file_path) << '\0'; // create the file
|
||||
}
|
||||
std::filesystem::resize_file(file_path, sha1_info.file_size);
|
||||
|
||||
// open file for writing (pre allocate?)
|
||||
std::error_code err;
|
||||
mio::mmap_sink file_map = mio::make_mmap_sink(sha1_info.file_name, 0, sha1_info.file_size, err);
|
||||
mio::mmap_sink file_map = mio::make_mmap_sink(file_path.string(), 0, sha1_info.file_size, err);
|
||||
|
||||
std::vector<bool> have_chunk(sha1_info.chunks.size(), false);
|
||||
|
||||
// dont overwrite correct existing data
|
||||
if (file_existed) {
|
||||
std::cout << "ReceiveStartSHA1 checking existing file\n";
|
||||
size_t f_i = 0;
|
||||
for (size_t c_i = 0; f_i + FTInfoSHA1::chunk_size < file_map.length(); f_i += FTInfoSHA1::chunk_size, c_i++) {
|
||||
if (sha1_info.chunks[c_i] == hash_sha1(file_map.data()+f_i, FTInfoSHA1::chunk_size)) {
|
||||
size_t f_i {0};
|
||||
size_t tmp_have_count {0};
|
||||
for (size_t c_i = 0; f_i + sha1_info.chunk_size < file_map.length(); f_i += sha1_info.chunk_size, c_i++) {
|
||||
if (sha1_info.chunks[c_i] == hash_sha1(file_map.data()+f_i, sha1_info.chunk_size)) {
|
||||
have_chunk[c_i] = true;
|
||||
tmp_have_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (f_i < file_map.length()) {
|
||||
if (sha1_info.chunks.back() == hash_sha1(file_map.data()+f_i, file_map.length()-f_i)) {
|
||||
have_chunk.back() = true;
|
||||
tmp_have_count++;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "ReceiveStartSHA1 have " << tmp_have_count << "/" << sha1_info.chunks.size() << " chunks (" << float(tmp_have_count)/sha1_info.chunks.size() * 100.f << "%)\n";
|
||||
}
|
||||
|
||||
std::cout << "ReceiveStartSHA1 switching state to SHA1\n";
|
||||
return std::make_unique<SHA1>(
|
||||
_tcl,
|
||||
_cl,
|
||||
std::move(file_map),
|
||||
std::move(sha1_info),
|
||||
std::move(_sha1_info_data),
|
||||
@ -132,13 +146,13 @@ bool ReceiveStartSHA1::onFT1ReceiveInitSHA1Info(uint32_t group_number, uint32_t
|
||||
|
||||
if (_transfer.has_value()) {
|
||||
// TODO: log?
|
||||
return false; // allready in progress
|
||||
return false; // already in progress
|
||||
}
|
||||
|
||||
_sha1_info_data.resize(file_size);
|
||||
|
||||
_transfer = std::make_tuple(group_number, peer_number, transfer_id, 0.f);
|
||||
std::cout << "ReceiveStartSHA1 accepted info transfer" << group_number << ":" << peer_number << "." << transfer_id << "\n";
|
||||
std::cout << "ReceiveStartSHA1 accepted info transfer " << group_number << ":" << peer_number << "." << int(transfer_id) << "\n";
|
||||
|
||||
// accept
|
||||
return true;
|
||||
@ -162,12 +176,12 @@ void ReceiveStartSHA1::onFT1ReceiveDataSHA1Info(uint32_t group_number, uint32_t
|
||||
std::cerr << "ReceiveStartSHA1 received info's hash does not match!, discarding\n";
|
||||
_transfer.reset();
|
||||
_sha1_info_data.clear();
|
||||
}
|
||||
|
||||
std::cout << "ReceiveStartSHA1 info tansfer finished " << group_number << ":" << peer_number << "." << transfer_id << "\n";
|
||||
} else {
|
||||
std::cout << "ReceiveStartSHA1 info tansfer finished " << group_number << ":" << peer_number << "." << int(transfer_id) << "\n";
|
||||
_done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiveStartSHA1::onFT1SendDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, uint8_t*, size_t) {
|
||||
// we cant send what we dont have
|
||||
|
@ -33,6 +33,9 @@ struct ReceiveStartSHA1 final : public StateI {
|
||||
void onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) override;
|
||||
|
||||
private:
|
||||
const CommandLine& _cl;
|
||||
std::string _dump_dir;
|
||||
|
||||
//FTInfoSHA1 _sha1_info;
|
||||
std::vector<uint8_t> _sha1_info_data;
|
||||
SHA1Digest _sha1_info_hash; // treat as const
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
namespace States {
|
||||
|
||||
SendStartSHA1::SendStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl), _file_path(cl.send_path) {
|
||||
SendStartSHA1::SendStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl), _cl(cl), _file_path(cl.send_path) {
|
||||
std::cout << "SendStartSHA1 start building sha1_info\n";
|
||||
std::error_code err;
|
||||
_file_map = mio::make_mmap_source(cl.send_path, 0, mio::map_entire_file, err);
|
||||
@ -27,13 +27,14 @@ SendStartSHA1::SendStartSHA1(ToxClient& tcl, const CommandLine& cl) : StateI(tcl
|
||||
assert(!_file_map.empty());
|
||||
|
||||
// build info
|
||||
_sha1_info.file_name = std::filesystem::path(cl.send_path).filename();
|
||||
_sha1_info.file_name = std::filesystem::path(cl.send_path).filename().string();
|
||||
_sha1_info.file_size = _file_map.length();
|
||||
//_sha1_info.chunk_size;
|
||||
|
||||
{ // build chunks
|
||||
size_t i = 0;
|
||||
for (; i + FTInfoSHA1::chunk_size < _file_map.length(); i += FTInfoSHA1::chunk_size) {
|
||||
_sha1_info.chunks.push_back(hash_sha1(_file_map.data()+i, FTInfoSHA1::chunk_size));
|
||||
for (; i + _sha1_info.chunk_size < _file_map.length(); i += _sha1_info.chunk_size) {
|
||||
_sha1_info.chunks.push_back(hash_sha1(_file_map.data()+i, _sha1_info.chunk_size));
|
||||
}
|
||||
|
||||
if (i < _file_map.length()) {
|
||||
@ -72,6 +73,7 @@ std::unique_ptr<StateI> SendStartSHA1::nextState(void) {
|
||||
// we are done setting up
|
||||
return std::make_unique<SHA1>(
|
||||
_tcl,
|
||||
_cl,
|
||||
std::move(new_file_map),
|
||||
std::move(_sha1_info),
|
||||
std::move(_sha1_info_data),
|
||||
|
@ -33,6 +33,8 @@ struct SendStartSHA1 final : public StateI {
|
||||
void onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) override;
|
||||
|
||||
private:
|
||||
const CommandLine& _cl;
|
||||
|
||||
std::string _file_path;
|
||||
mio::mmap_source _file_map;
|
||||
FTInfoSHA1 _sha1_info;
|
||||
|
@ -4,13 +4,16 @@
|
||||
|
||||
#include "../hash_utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <random>
|
||||
|
||||
namespace States {
|
||||
|
||||
SHA1::SHA1(
|
||||
ToxClient& tcl,
|
||||
const CommandLine& cl,
|
||||
mio::mmap_sink&& file_map,
|
||||
const FTInfoSHA1&& sha1_info,
|
||||
const std::vector<uint8_t>&& sha1_info_data,
|
||||
@ -27,6 +30,16 @@ SHA1::SHA1(
|
||||
{
|
||||
assert(_have_chunk.size() == _sha1_info.chunks.size());
|
||||
|
||||
_udp_only = cl.request_only_from_udp_peer;
|
||||
_max_concurrent_in = cl.max_incoming_transfers;
|
||||
_max_concurrent_out = cl.max_outgoing_transfers;
|
||||
|
||||
// build lookup table
|
||||
for (size_t i = _sha1_info.chunks.size(); i > 0; i--) {
|
||||
// chunks can have more then 1 index ..., for now, build reverse and have the first index be the real index
|
||||
_chunk_hash_to_index[_sha1_info.chunks.at(i-1)] = i-1;
|
||||
}
|
||||
|
||||
_have_all = true;
|
||||
_have_count = 0;
|
||||
for (size_t i = 0; i < _have_chunk.size(); i++) {
|
||||
@ -34,15 +47,24 @@ SHA1::SHA1(
|
||||
_have_count++;
|
||||
} else {
|
||||
_have_all = false;
|
||||
|
||||
// avoid same chunk hash dups
|
||||
if (_chunk_hash_to_index.at(_sha1_info.chunks.at(i)) == i) {
|
||||
_chunk_want_queue.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_have_all) {
|
||||
assert(_chunk_want_queue.size() > 0);
|
||||
|
||||
{ // load last chunk first :)
|
||||
size_t tmp = _chunk_want_queue.back();
|
||||
_chunk_want_queue.push_front(tmp);
|
||||
_chunk_want_queue.pop_back();
|
||||
}
|
||||
|
||||
// if not sequential, shuffle _chunk_want_queue
|
||||
|
||||
// build lookup table
|
||||
for (size_t i = 0; i < _sha1_info.chunks.size(); i++) {
|
||||
_chunk_hash_to_index[_sha1_info.chunks[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,11 +104,36 @@ bool SHA1::iterate(float delta) {
|
||||
// if we have not heard for 10sec, timeout
|
||||
if (time_since_remove_activity >= 10.f) {
|
||||
std::cerr << "SHA1 receiving chunk tansfer timed out " << std::get<0>(*it) << ":" << std::get<1>(*it) << "." << int(std::get<2>(*it)) << "\n";
|
||||
_chunk_want_queue.push_front(std::get<4>(*it)); // put it back
|
||||
it = _transfers_receiving_chunk.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// sent requests
|
||||
for (auto it = _chunks_requested.begin(); it != _chunks_requested.end();) {
|
||||
it->second += delta;
|
||||
|
||||
// if we have not heard for 15sec, timeout
|
||||
if (it->second >= 15.f) {
|
||||
_chunk_want_queue.push_front(it->first); // put it back
|
||||
it = _chunks_requested.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// queued requests
|
||||
for (auto it = _queue_requested_chunk.begin(); it != _queue_requested_chunk.end();) {
|
||||
float& timer = std::get<float>(*it);
|
||||
timer += delta;
|
||||
|
||||
if (timer >= 10.f) {
|
||||
it = _queue_requested_chunk.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have not reached the total cap for transfers
|
||||
@ -98,16 +145,16 @@ bool SHA1::iterate(float delta) {
|
||||
// send init to _queue_requested_info
|
||||
const auto [group_number, peer_number] = _queue_requested_info.front();
|
||||
|
||||
if (_tcl.getGroupPeerConnectionStatus(group_number, peer_number) != TOX_CONNECTION_NONE) {
|
||||
uint8_t transfer_id {0};
|
||||
|
||||
_tcl.sendFT1InitPrivate(
|
||||
if (_tcl.sendFT1InitPrivate(
|
||||
group_number, peer_number,
|
||||
NGC_FT1_file_kind::HASH_SHA1_INFO,
|
||||
_sha1_info_hash.data.data(), _sha1_info_hash.size(), // id (info hash)
|
||||
_sha1_info_data.size(), // "file_size"
|
||||
transfer_id
|
||||
);
|
||||
|
||||
)) {
|
||||
_transfers_requested_info.push_back({
|
||||
group_number, peer_number,
|
||||
transfer_id,
|
||||
@ -115,22 +162,28 @@ bool SHA1::iterate(float delta) {
|
||||
});
|
||||
|
||||
_queue_requested_info.pop_front();
|
||||
}
|
||||
}
|
||||
} else if (!_queue_requested_chunk.empty()) { // then check for chunk requests
|
||||
const auto [group_number, peer_number, chunk_hash] = _queue_requested_chunk.front();
|
||||
const auto [group_number, peer_number, chunk_hash, _] = _queue_requested_chunk.front();
|
||||
|
||||
if (_tcl.getGroupPeerConnectionStatus(group_number, peer_number) != TOX_CONNECTION_NONE) {
|
||||
if (!chunkIndex(chunk_hash).has_value()) {
|
||||
std::cerr << "!chunkIndex(chunk_hash).has_value()\n";
|
||||
exit(1);
|
||||
}
|
||||
size_t chunk_index = chunkIndex(chunk_hash).value();
|
||||
size_t chunk_file_size = chunkSize(chunk_index);
|
||||
|
||||
uint8_t transfer_id {0};
|
||||
|
||||
_tcl.sendFT1InitPrivate(
|
||||
if (_tcl.sendFT1InitPrivate(
|
||||
group_number, peer_number,
|
||||
NGC_FT1_file_kind::HASH_SHA1_CHUNK,
|
||||
chunk_hash.data.data(), chunk_hash.size(), // id (chunk hash)
|
||||
chunk_file_size,
|
||||
transfer_id
|
||||
);
|
||||
|
||||
)) {
|
||||
_transfers_sending_chunk.push_back({
|
||||
group_number, peer_number,
|
||||
transfer_id,
|
||||
@ -141,32 +194,119 @@ bool SHA1::iterate(float delta) {
|
||||
_queue_requested_chunk.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_have_all && !_chunk_want_queue.empty() && _transfers_receiving_chunk.size() < _max_concurrent_in) {
|
||||
// update speeds and targets
|
||||
_peer_speed_mesurement_interval_timer += delta;
|
||||
if (_peer_speed_mesurement_interval_timer >= _peer_speed_mesurement_interval) {
|
||||
_peer_speed_mesurement_interval_timer = 0.f; // we lose some time here, but precision is not the issue
|
||||
|
||||
_peer_in_bytes_array_index = (_peer_in_bytes_array_index + 1) % _peer_speed_mesurement_interval_count;
|
||||
//for (const auto& [peer, array] : _peer_in_bytes_array) {
|
||||
for (auto it = _peer_in_bytes_array.begin(); it != _peer_in_bytes_array.end();) {
|
||||
const auto& [peer, array] = *it;
|
||||
|
||||
float avg {0.f};
|
||||
for (size_t i = 0; i < array.size(); i++) {
|
||||
avg += array[i];
|
||||
}
|
||||
|
||||
if (avg == 0.f || _tcl.getGroupPeerConnectionStatus(peer.first, peer.second) == Tox_Connection::TOX_CONNECTION_NONE) {
|
||||
_peer_in_speed.erase(peer);
|
||||
it = _peer_in_bytes_array.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
// if 6 mesurment every 0.5sec -> avg is over 3sec -> /3 for /s
|
||||
avg /= _peer_speed_mesurement_interval * _peer_speed_mesurement_interval_count;
|
||||
|
||||
// reset byte count for next round
|
||||
_peer_in_bytes_array[peer][_peer_in_bytes_array_index] = 0;
|
||||
|
||||
_peer_in_speed[peer] = avg;
|
||||
|
||||
it++;
|
||||
}
|
||||
|
||||
_peer_in_targets.clear();
|
||||
_tcl.forEachGroup([this](uint32_t group_number) {
|
||||
_tcl.forEachGroupPeer(group_number, [group_number, this](uint32_t peer_number) {
|
||||
if (!_udp_only || _tcl.getGroupPeerConnectionStatus(group_number, peer_number) == Tox_Connection::TOX_CONNECTION_UDP) {
|
||||
_peer_in_targets.push_back({group_number, peer_number});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!_peer_in_targets.empty()) {
|
||||
std::vector<double> weights;
|
||||
for (const auto& peer : _peer_in_targets) {
|
||||
if (_peer_in_speed.count(peer)) {
|
||||
weights.push_back(
|
||||
std::clamp(
|
||||
(_peer_in_speed.at(peer) / 1024.f) // KiB/s
|
||||
* (20.f/500.f), // map to a range from 0 to 20, max at 500KiB/s
|
||||
1.f,
|
||||
20.f
|
||||
)
|
||||
);
|
||||
} else {
|
||||
weights.push_back(1.f);
|
||||
}
|
||||
}
|
||||
|
||||
std::discrete_distribution<size_t> tmp_dist{weights.cbegin(), weights.cend()};
|
||||
_peer_in_targets_dist.param(tmp_dist.param());
|
||||
}
|
||||
}
|
||||
|
||||
if (!_have_all && !_peer_in_targets.empty() && !_chunk_want_queue.empty() && _chunks_requested.size() + _transfers_receiving_chunk.size() < _max_concurrent_in) {
|
||||
// send out request, no burst tho
|
||||
std::vector<std::pair<uint32_t, uint32_t>> target_peers;
|
||||
_tcl.forEachGroup([&target_peers, this](uint32_t group_number) {
|
||||
_tcl.forEachGroupPeer(group_number, [&target_peers, group_number](uint32_t peer_number) {
|
||||
target_peers.push_back({group_number, peer_number});
|
||||
});
|
||||
});
|
||||
uint32_t group_number;
|
||||
uint32_t peer_number;
|
||||
|
||||
if (!target_peers.empty()) {
|
||||
//if (_distrib.max() != target_peers.size()) {
|
||||
//std::uniform_int_distribution<size_t> new_dist{0, target_peers.size()-1};
|
||||
//_distrib.param(new_dist.param());
|
||||
//}
|
||||
|
||||
//size_t target_index = _distrib(_rng);
|
||||
size_t target_index = _rng()%target_peers.size();
|
||||
auto [group_number, peer_number] = target_peers.at(target_index);
|
||||
//size_t target_index = _rng()%target_peers.size();
|
||||
size_t target_index = _peer_in_targets_dist(_rng);
|
||||
std::tie(group_number, peer_number) = _peer_in_targets.at(target_index);
|
||||
|
||||
size_t chunk_index = _chunk_want_queue.front();
|
||||
_chunks_requested.emplace(chunk_index);
|
||||
_chunks_requested[chunk_index] = 0.f;
|
||||
_chunk_want_queue.pop_front();
|
||||
|
||||
_tcl.sendFT1RequestPrivate(group_number, peer_number, NGC_FT1_file_kind::HASH_SHA1_CHUNK, _sha1_info.chunks[chunk_index].data.data(), 20);
|
||||
//std::cout << "sent request " << group_number << ":" << peer_number << "\n";
|
||||
}
|
||||
|
||||
// log
|
||||
_io_log_timer += delta;
|
||||
static const float log_interval {10.f};
|
||||
if (_io_log_timer >= log_interval) {
|
||||
_io_log_timer = 0.f;
|
||||
|
||||
size_t bytes_up_since {_bytes_up - _bytes_up_last_log};
|
||||
_bytes_up_last_log = _bytes_up;
|
||||
|
||||
size_t bytes_down_since {_bytes_down - _bytes_down_last_log};
|
||||
_bytes_down_last_log = _bytes_down;
|
||||
|
||||
float up_kibs {(bytes_up_since / 1024.f) / log_interval};
|
||||
float down_kibs {(bytes_down_since / 1024.f) / log_interval};
|
||||
|
||||
std::cout << std::string(40, '-') << "\n";
|
||||
std::cout << "SHA1 speed down: " << down_kibs << "KiB/s up: " << up_kibs << "KiB/s\n";
|
||||
std::cout << "SHA1 total down: " << _bytes_down / 1024 << "KiB up: " << _bytes_up / 1024 << "KiB\n";
|
||||
|
||||
std::cout << "SHA1 cwq:" << _chunk_want_queue.size() << " cwqr:" << _chunks_requested.size() << " trc:" << _transfers_receiving_chunk.size() << " tsc:" << _transfers_sending_chunk.size() << "\n";
|
||||
std::cout << "SHA1 peer down speeds:\n";
|
||||
for (const auto& [peer, speed] : _peer_in_speed) {
|
||||
std::cout
|
||||
<< " " << peer.first << ":" << peer.second
|
||||
<< " " << (_tcl.getGroupPeerConnectionStatus(peer.first, peer.second) == Tox_Connection::TOX_CONNECTION_TCP ? "tcp" : "udp")
|
||||
<< " (" << _tcl.getGroupPeerName(peer.first, peer.second) << ")"
|
||||
<< " " << speed / 1024.f << "KiB/s\n"
|
||||
;
|
||||
}
|
||||
std::cout << std::string(40, '-') << "\n";
|
||||
}
|
||||
|
||||
// TODO: unmap and remap the file every couple of minutes to keep ram usage down?
|
||||
@ -207,7 +347,7 @@ bool SHA1::onFT1ReceiveInitSHA1Info(uint32_t, uint32_t, const uint8_t*, size_t,
|
||||
|
||||
void SHA1::onFT1ReceiveDataSHA1Info(uint32_t, uint32_t, uint8_t, size_t, const uint8_t*, size_t) {
|
||||
// no, in this state we have init
|
||||
assert(false && "ft should have said dropped this for us!");
|
||||
assert(false && "ft should have dropped this for us!");
|
||||
}
|
||||
|
||||
void SHA1::onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size) {
|
||||
@ -233,7 +373,7 @@ void SHA1::onFT1SendDataSHA1Info(uint32_t group_number, uint32_t peer_number, ui
|
||||
// this transfer is "done" (ft still could have to retransfer)
|
||||
for (auto it = _transfers_requested_info.cbegin(); it != _transfers_requested_info.cend(); it++) {
|
||||
if (std::get<0>(*it) == group_number && std::get<1>(*it) == peer_number && std::get<2>(*it) == transfer_id) {
|
||||
std::cout << "SHA1 info tansfer finished " << std::get<0>(*it) << ":" << std::get<1>(*it) << "." << std::get<2>(*it) << "\n";
|
||||
std::cout << "SHA1 info tansfer finished " << std::get<0>(*it) << ":" << std::get<1>(*it) << "." << int(std::get<2>(*it)) << "\n";
|
||||
_transfers_requested_info.erase(it);
|
||||
break;
|
||||
}
|
||||
@ -271,7 +411,7 @@ bool SHA1::onFT1ReceiveInitSHA1Chunk(uint32_t group_number, uint32_t peer_number
|
||||
SHA1Digest incomming_hash(file_id, file_id_size);
|
||||
|
||||
if (haveChunk(incomming_hash)) {
|
||||
std::cout << "SHA1 ignoring init for chunk we allready have " << incomming_hash << "\n";
|
||||
std::cout << "SHA1 ignoring init for chunk we already have " << incomming_hash << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -287,7 +427,7 @@ bool SHA1::onFT1ReceiveInitSHA1Chunk(uint32_t group_number, uint32_t peer_number
|
||||
// check transfers
|
||||
for (const auto& it : _transfers_receiving_chunk) {
|
||||
if (std::get<4>(it) == chunk_index) {
|
||||
// allready in transition
|
||||
// already in transition
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -301,6 +441,9 @@ bool SHA1::onFT1ReceiveInitSHA1Chunk(uint32_t group_number, uint32_t peer_number
|
||||
)
|
||||
);
|
||||
|
||||
// remove form requests
|
||||
_chunks_requested.erase(chunk_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -308,6 +451,10 @@ void SHA1::onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number
|
||||
// check transfers
|
||||
for (auto it = _transfers_receiving_chunk.begin(); it != _transfers_receiving_chunk.end(); it++) {
|
||||
if (std::get<0>(*it) == group_number && std::get<1>(*it) == peer_number && std::get<2>(*it) == transfer_id) {
|
||||
_bytes_down += data_size;
|
||||
|
||||
_peer_in_bytes_array[std::make_pair(group_number, peer_number)][_peer_in_bytes_array_index] += data_size;
|
||||
|
||||
std::get<float>(*it) = 0.f; // time
|
||||
|
||||
const size_t chunk_index = std::get<4>(*it);
|
||||
@ -327,7 +474,9 @@ void SHA1::onFT1ReceiveDataSHA1Chunk(uint32_t group_number, uint32_t peer_number
|
||||
SHA1Digest test_hash = hash_sha1(_file_map.data()+file_offset, chunk_file_size);
|
||||
if (test_hash != _sha1_info.chunks[chunk_index]) {
|
||||
std::cerr << "SHA1 received chunks's hash does not match!, discarding\n";
|
||||
_bytes_down -= chunk_file_size; // penalize wrong data
|
||||
_transfers_receiving_chunk.erase(it);
|
||||
_chunk_want_queue.push_front(chunk_index); // put back in queue
|
||||
break;
|
||||
}
|
||||
|
||||
@ -347,6 +496,8 @@ void SHA1::onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, u
|
||||
// TODO: sub optimal
|
||||
for (auto it = _transfers_sending_chunk.begin(); it != _transfers_sending_chunk.end(); it++) {
|
||||
if (std::get<0>(*it) == group_number && std::get<1>(*it) == peer_number && std::get<2>(*it) == transfer_id) {
|
||||
_bytes_up += data_size;
|
||||
|
||||
std::get<float>(*it) = 0.f; // time
|
||||
|
||||
const size_t chunk_index = std::get<4>(*it);
|
||||
@ -372,14 +523,14 @@ void SHA1::onFT1SendDataSHA1Chunk(uint32_t group_number, uint32_t peer_number, u
|
||||
void SHA1::queueUpRequestInfo(uint32_t group_number, uint32_t peer_number) {
|
||||
// check ongoing transfers for dup
|
||||
for (const auto& it : _transfers_requested_info) {
|
||||
// if allready in queue
|
||||
// if already in queue
|
||||
if (std::get<0>(it) == group_number && std::get<1>(it) == peer_number) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [i_g, i_p] : _queue_requested_info) {
|
||||
// if allready in queue
|
||||
// if already in queue
|
||||
if (i_g == group_number && i_p == peer_number) {
|
||||
return;
|
||||
}
|
||||
@ -392,15 +543,17 @@ void SHA1::queueUpRequestInfo(uint32_t group_number, uint32_t peer_number) {
|
||||
void SHA1::queueUpRequestChunk(uint32_t group_number, uint32_t peer_number, const SHA1Digest& hash) {
|
||||
// TODO: transfers
|
||||
|
||||
for (auto& [i_g, i_p, i_h] : _queue_requested_chunk) {
|
||||
// if allready in queue
|
||||
for (auto& [i_g, i_p, i_h, i_t] : _queue_requested_chunk) {
|
||||
// if already in queue
|
||||
if (i_g == group_number && i_p == peer_number && i_h == hash) {
|
||||
// update timer
|
||||
i_t = 0.f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// not in queue yet
|
||||
_queue_requested_chunk.push_back(std::make_tuple(group_number, peer_number, hash));
|
||||
_queue_requested_chunk.push_back(std::make_tuple(group_number, peer_number, hash, 0.f));
|
||||
}
|
||||
|
||||
std::optional<size_t> SHA1::chunkIndex(const SHA1Digest& hash) const {
|
||||
|
@ -3,11 +3,13 @@
|
||||
#include "../state.hpp"
|
||||
|
||||
#include "../ft_sha1_info.hpp"
|
||||
#include "../command_line.hpp"
|
||||
|
||||
#include <mio/mio.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <random>
|
||||
@ -20,6 +22,7 @@ struct SHA1 final : public StateI {
|
||||
public: // general interface
|
||||
SHA1(
|
||||
ToxClient& tcl,
|
||||
const CommandLine& cl,
|
||||
mio::mmap_sink&& file_map,
|
||||
const FTInfoSHA1&& sha1_info,
|
||||
const std::vector<uint8_t>&& sha1_info_data,
|
||||
@ -55,24 +58,33 @@ struct SHA1 final : public StateI {
|
||||
size_t chunkSize(size_t chunk_index) const;
|
||||
bool haveChunk(const SHA1Digest& hash) const;
|
||||
|
||||
public: // config
|
||||
bool _udp_only {false};
|
||||
|
||||
size_t _max_concurrent_in {32};
|
||||
size_t _max_concurrent_out {16};
|
||||
|
||||
private:
|
||||
mio::mmap_sink _file_map; // writable if not all
|
||||
const FTInfoSHA1 _sha1_info;
|
||||
const std::vector<uint8_t> _sha1_info_data;
|
||||
const SHA1Digest _sha1_info_hash;
|
||||
|
||||
float _io_log_timer {0.f};
|
||||
size_t _bytes_up {0};
|
||||
size_t _bytes_up_last_log {0};
|
||||
size_t _bytes_down {0};
|
||||
size_t _bytes_down_last_log {0};
|
||||
|
||||
// index is the same as for info
|
||||
std::vector<bool> _have_chunk;
|
||||
bool _have_all {false};
|
||||
size_t _have_count {0};
|
||||
std::deque<size_t> _chunk_want_queue;
|
||||
std::set<size_t> _chunks_requested;
|
||||
|
||||
const size_t _max_concurrent_out {4};
|
||||
const size_t _max_concurrent_in {4};
|
||||
// chunk_index -> time since request
|
||||
std::map<size_t, float> _chunks_requested;
|
||||
|
||||
std::minstd_rand _rng {1337};
|
||||
std::uniform_int_distribution<size_t> _distrib;
|
||||
|
||||
std::unordered_map<SHA1Digest, size_t> _chunk_hash_to_index;
|
||||
|
||||
@ -82,11 +94,27 @@ struct SHA1 final : public StateI {
|
||||
std::vector<std::tuple<uint32_t, uint32_t, uint8_t, float>> _transfers_requested_info;
|
||||
|
||||
// group_number, peer_number, chunk_hash
|
||||
std::deque<std::tuple<uint32_t, uint32_t, SHA1Digest>> _queue_requested_chunk;
|
||||
std::deque<std::tuple<uint32_t, uint32_t, SHA1Digest, float>> _queue_requested_chunk;
|
||||
|
||||
// group_number, peer_number, transfer_id(i/o), seconds since (remote) activity, chunk index
|
||||
std::vector<std::tuple<uint32_t, uint32_t, uint8_t, float, size_t>> _transfers_sending_chunk;
|
||||
std::vector<std::tuple<uint32_t, uint32_t, uint8_t, float, size_t>> _transfers_receiving_chunk;
|
||||
|
||||
static constexpr size_t _peer_speed_mesurement_interval_count {20};
|
||||
const float _peer_speed_mesurement_interval {0.5f}; // seconds
|
||||
float _peer_speed_mesurement_interval_timer {0.f}; // seconds
|
||||
// bytes received for last 6 intervals for peer
|
||||
std::map<std::pair<uint32_t, uint32_t>, std::array<int64_t, _peer_speed_mesurement_interval_count>> _peer_in_bytes_array;
|
||||
size_t _peer_in_bytes_array_index {0}; // current index into _peer_in_bytes_array. !ringbuffer!
|
||||
// when chunk data is received, it is added to _peer_in_bytes_array_index in _peer_in_bytes_array
|
||||
// every _peer_speed_mesurement_interval the avg is calculed and written to _peer_in_speed
|
||||
// and the _peer_in_bytes_array_index is incremented by 1
|
||||
std::map<std::pair<uint32_t, uint32_t>, float> _peer_in_speed;
|
||||
// speed might be not the actual speed, since wrong data is removed afterwards (on "completion")
|
||||
// so it can get negative. this makes this more useful for peer selection, less for userfacing stats
|
||||
// _peer_in_speed feeds directly into _peer_in_targets_dist
|
||||
std::vector<std::pair<uint32_t, uint32_t>> _peer_in_targets;
|
||||
std::discrete_distribution<size_t> _peer_in_targets_dist;
|
||||
};
|
||||
|
||||
} // States
|
||||
|
@ -21,6 +21,11 @@ void self_connection_status_cb(Tox*, TOX_CONNECTION connection_status, void *use
|
||||
void friend_request_cb(Tox*, const uint8_t *public_key, const uint8_t *message, size_t length, void *user_data) {
|
||||
static_cast<ToxClient*>(user_data)->onToxFriendRequest(public_key, std::string_view{reinterpret_cast<const char*>(message), length});
|
||||
}
|
||||
|
||||
void group_peer_name_cb(Tox*, uint32_t group_number, uint32_t peer_id, const uint8_t* name, size_t length, void *user_data) {
|
||||
static_cast<ToxClient*>(user_data)->onToxGroupPeerName(group_number, peer_id, std::string_view{reinterpret_cast<const char*>(name), length});
|
||||
}
|
||||
|
||||
void group_custom_packet_cb(Tox*, uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length, void *user_data) {
|
||||
static_cast<ToxClient*>(user_data)->onToxGroupCustomPacket(group_number, peer_id, data, length);
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
// logging
|
||||
void log_cb(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func, const char *message, void *user_data);
|
||||
|
||||
@ -19,7 +21,7 @@ void friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *messa
|
||||
//static void friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *user_data);
|
||||
|
||||
// ngc
|
||||
//static void group_peer_name_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t length, void *user_data);
|
||||
void group_peer_name_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *name, size_t length, void *user_data);
|
||||
//static void group_peer_status_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, Tox_User_Status status, void *user_data);
|
||||
//static void group_topic_cb(Tox *tox, uint32_t group_number, uint32_t peer_id, const uint8_t *topic, size_t length, void *user_data);
|
||||
//static void group_privacy_state_cb(Tox *tox, uint32_t group_number, Tox_Group_Privacy_State privacy_state, void *user_data);
|
||||
@ -52,3 +54,5 @@ bool ft1_recv_init_sha1_chunk_cb(Tox *tox, uint32_t group_number, uint32_t peer_
|
||||
void ft1_recv_data_sha1_chunk_cb(Tox *tox, uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, const uint8_t* data, size_t data_size, void* user_data);
|
||||
void ft1_send_data_sha1_chunk_cb(Tox *tox, uint32_t group_number, uint32_t peer_number, uint8_t transfer_id, size_t data_offset, uint8_t* data, size_t data_size, void* user_data);
|
||||
|
||||
} // extern C
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "./states/send_start_sha1.hpp"
|
||||
#include "./states/receive_start_sha1.hpp"
|
||||
#include "ngc_ft1.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sodium.h>
|
||||
@ -26,9 +25,22 @@ ToxClient::ToxClient(const CommandLine& cl) :
|
||||
|
||||
// use cl for options
|
||||
tox_options_set_log_callback(options, log_cb);
|
||||
tox_options_set_local_discovery_enabled(options, false);
|
||||
tox_options_set_udp_enabled(options, true);
|
||||
tox_options_set_hole_punching_enabled(options, true);
|
||||
tox_options_set_local_discovery_enabled(options, !cl.tox_disable_local_discovery);
|
||||
tox_options_set_udp_enabled(options, !cl.tox_disable_udp);
|
||||
tox_options_set_hole_punching_enabled(options, !cl.tox_disable_udp);
|
||||
if (!cl.proxy_host.empty()) {
|
||||
tox_options_set_proxy_host(options, cl.proxy_host.c_str());
|
||||
tox_options_set_proxy_port(options, cl.proxy_port);
|
||||
tox_options_set_proxy_type(options, Tox_Proxy_Type::TOX_PROXY_TYPE_SOCKS5);
|
||||
} else {
|
||||
tox_options_set_proxy_type(options, Tox_Proxy_Type::TOX_PROXY_TYPE_NONE);
|
||||
}
|
||||
|
||||
if (cl.tox_port != 0) {
|
||||
tox_options_set_start_port(options, cl.tox_port);
|
||||
// TODO: extra end port?
|
||||
tox_options_set_end_port(options, cl.tox_port);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> profile_data{};
|
||||
if (!_tox_profile_path.empty()) {
|
||||
@ -93,6 +105,7 @@ ToxClient::ToxClient(const CommandLine& cl) :
|
||||
//CALLBACK_REG(friend_lossy_packet);
|
||||
//CALLBACK_REG(friend_lossless_packet);
|
||||
|
||||
TOX_CALLBACK_REG(group_peer_name);
|
||||
TOX_CALLBACK_REG(group_custom_packet);
|
||||
TOX_CALLBACK_REG(group_custom_private_packet);
|
||||
TOX_CALLBACK_REG(group_invite);
|
||||
@ -109,6 +122,9 @@ ToxClient::ToxClient(const CommandLine& cl) :
|
||||
_ext_ctx = NGC_EXT_new();
|
||||
|
||||
NGC_FT1_options ft1_options {};
|
||||
ft1_options.acks_per_packet = cl.ft_acks_per_packet;
|
||||
ft1_options.init_retry_timeout_after = cl.ft_init_retry_timeout_after;
|
||||
ft1_options.sending_give_up_after = cl.ft_sending_give_up_after;
|
||||
_ft1_ctx = NGC_FT1_new(&ft1_options);
|
||||
NGC_FT1_register_ext(_ft1_ctx, _ext_ctx);
|
||||
|
||||
@ -163,6 +179,12 @@ ToxClient::ToxClient(const CommandLine& cl) :
|
||||
}
|
||||
}
|
||||
|
||||
if (!cl.chat_id.empty()) {
|
||||
// TODO: move conversion and size check to cl
|
||||
_join_group_after_dht_connect = hex2bin(cl.chat_id);
|
||||
assert(_join_group_after_dht_connect.size() == TOX_GROUP_CHAT_ID_SIZE);
|
||||
}
|
||||
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
@ -174,11 +196,14 @@ ToxClient::~ToxClient(void) {
|
||||
}
|
||||
|
||||
bool ToxClient::iterate(void) {
|
||||
tox_iterate(_tox, this);
|
||||
NGC_FT1_iterate(_tox, _ft1_ctx);
|
||||
auto new_time = std::chrono::high_resolution_clock::now();
|
||||
const float time_delta {std::chrono::duration<float>(new_time - _last_time).count()};
|
||||
_last_time = new_time;
|
||||
|
||||
// HACK: hardcoded 5ms sleep in main
|
||||
if (_state->iterate(0.005f)) {
|
||||
tox_iterate(_tox, this);
|
||||
NGC_FT1_iterate(_tox, _ft1_ctx, time_delta);
|
||||
|
||||
if (_state->iterate(time_delta)) {
|
||||
_state = _state->nextState();
|
||||
|
||||
if (!_state) {
|
||||
@ -187,6 +212,25 @@ bool ToxClient::iterate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
_rejoin_group_timer -= time_delta;
|
||||
if (_rejoin_group_timer <= 0.f) {
|
||||
_rejoin_group_timer = 6.f * 60.f;
|
||||
|
||||
forEachGroup([this](const uint32_t group_number) {
|
||||
// is connected or trying to connect
|
||||
if (!tox_group_is_connected(_tox, group_number, nullptr)) {
|
||||
std::cerr << "TCL disconnected group " << group_number << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// never seen another peer
|
||||
if (_groups.at(group_number).empty()) {
|
||||
tox_group_reconnect(_tox, group_number, nullptr);
|
||||
std::cerr << "TCL reconnecting empty group " << group_number << "\n";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_tox_profile_dirty) {
|
||||
saveToxProfile();
|
||||
}
|
||||
@ -203,6 +247,18 @@ std::string ToxClient::getOwnAddress(void) const {
|
||||
return bin2hex(self_addr);
|
||||
}
|
||||
|
||||
std::string_view ToxClient::getGroupPeerName(uint32_t group_number, uint32_t peer_number) const {
|
||||
if (_groups.count(group_number) && _groups.at(group_number).count(peer_number)) {
|
||||
return _groups.at(group_number).at(peer_number).name;
|
||||
} else {
|
||||
return {""};
|
||||
}
|
||||
}
|
||||
|
||||
TOX_CONNECTION ToxClient::getGroupPeerConnectionStatus(uint32_t group_number, uint32_t peer_number) const {
|
||||
return tox_group_peer_get_connection_status(_tox, group_number, peer_number, nullptr);
|
||||
}
|
||||
|
||||
void ToxClient::onToxSelfConnectionStatus(TOX_CONNECTION connection_status) {
|
||||
std::cout << "TCL self status: ";
|
||||
switch (connection_status) {
|
||||
@ -210,6 +266,25 @@ void ToxClient::onToxSelfConnectionStatus(TOX_CONNECTION connection_status) {
|
||||
case TOX_CONNECTION::TOX_CONNECTION_TCP: std::cout << "TCP-relayed\n"; break;
|
||||
case TOX_CONNECTION::TOX_CONNECTION_UDP: std::cout << "UDP-direct\n"; break;
|
||||
}
|
||||
|
||||
if (connection_status != TOX_CONNECTION::TOX_CONNECTION_NONE && !_join_group_after_dht_connect.empty()) {
|
||||
Tox_Err_Group_Join err;
|
||||
uint32_t new_group_number = tox_group_join(
|
||||
_tox,
|
||||
_join_group_after_dht_connect.data(),
|
||||
reinterpret_cast<const uint8_t*>(_self_name.data()), _self_name.size(),
|
||||
nullptr, 0,
|
||||
&err
|
||||
);
|
||||
if (err == TOX_ERR_GROUP_JOIN_OK) {
|
||||
std::cout << "TCL joining group " << bin2hex(_join_group_after_dht_connect) << "\n";
|
||||
_groups[new_group_number] = {};
|
||||
} else {
|
||||
std::cerr << "TCL error joining group failed " << err << "\n";
|
||||
}
|
||||
_join_group_after_dht_connect.clear();
|
||||
}
|
||||
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
@ -221,6 +296,20 @@ void ToxClient::onToxFriendRequest(const uint8_t* public_key, std::string_view m
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
void ToxClient::onToxGroupPeerName(uint32_t group_number, uint32_t peer_id, std::string_view name) {
|
||||
std::cout << "TCL peer " << group_number << ":" << peer_id << " is now known as " << name << "\n";
|
||||
_groups[group_number][peer_id].name = name;
|
||||
}
|
||||
|
||||
//void ToxClient::onToxGroupPeerConnection(uint32_t group_number, uint32_t peer_id, TOX_CONNECTION connection_status) {
|
||||
//std::cout << "TCL peer " << group_number << ":" << peer_id << " status: ";
|
||||
//switch (connection_status) {
|
||||
//case TOX_CONNECTION::TOX_CONNECTION_NONE: std::cout << "offline\n"; break;
|
||||
//case TOX_CONNECTION::TOX_CONNECTION_TCP: std::cout << "TCP-relayed\n"; break;
|
||||
//case TOX_CONNECTION::TOX_CONNECTION_UDP: std::cout << "UDP-direct\n"; break;
|
||||
//}
|
||||
//}
|
||||
|
||||
void ToxClient::onToxGroupCustomPacket(uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length) {
|
||||
// TODO: signal private?
|
||||
NGC_EXT_handle_group_custom_packet(_tox, _ext_ctx, group_number, peer_id, data, length);
|
||||
@ -240,19 +329,37 @@ void ToxClient::onToxGroupInvite(uint32_t friend_number, const uint8_t* invite_d
|
||||
|
||||
void ToxClient::onToxGroupPeerJoin(uint32_t group_number, uint32_t peer_id) {
|
||||
std::cout << "TCL group peer join " << group_number << ":" << peer_id << "\n";
|
||||
_groups[group_number].emplace(peer_id);
|
||||
|
||||
std::vector<uint8_t> tmp_name;
|
||||
{
|
||||
Tox_Err_Group_Peer_Query err;
|
||||
size_t length = tox_group_peer_get_name_size(_tox, group_number, peer_id, &err);
|
||||
if (err == Tox_Err_Group_Peer_Query::TOX_ERR_GROUP_PEER_QUERY_OK) {
|
||||
tmp_name.resize(length, '\0');
|
||||
tox_group_peer_get_name(_tox, group_number, peer_id, tmp_name.data(), nullptr);
|
||||
}
|
||||
}
|
||||
tmp_name.push_back('\0'); // make sure its null terminated
|
||||
|
||||
_groups[group_number][peer_id] = {
|
||||
//tox_group_peer_get_connection_status(_tox, group_number, peer_id, nullptr),
|
||||
reinterpret_cast<const char*>(tmp_name.data())
|
||||
};
|
||||
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
void ToxClient::onToxGroupPeerExit(uint32_t group_number, uint32_t peer_id, Tox_Group_Exit_Type exit_type, std::string_view name, std::string_view part_message) {
|
||||
std::cout << "TCL group peer exit " << group_number << ":" << peer_id << "\n";
|
||||
std::cout << "TCL group peer exit " << group_number << ":" << peer_id << " " << name << "\n";
|
||||
_groups[group_number].erase(peer_id);
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
void ToxClient::onToxGroupSelfJoin(uint32_t group_number) {
|
||||
std::cout << "TCL group self join " << group_number << "\n";
|
||||
tox_group_self_set_name(_tox, group_number, reinterpret_cast<const uint8_t*>(_self_name.data()), _self_name.size(), nullptr);
|
||||
// ???
|
||||
// can be triggered after other peers already joined o.o
|
||||
_tox_profile_dirty = true;
|
||||
}
|
||||
|
||||
@ -262,7 +369,7 @@ StateI& ToxClient::getState(void) {
|
||||
return *_state.get();
|
||||
}
|
||||
|
||||
bool ToxClient::sendFT1RequestPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size) {
|
||||
bool ToxClient::sendFT1RequestPrivate(uint32_t group_number, uint32_t peer_number, uint32_t file_kind, const uint8_t* file_id, size_t file_id_size) {
|
||||
NGC_FT1_send_request_private(
|
||||
_tox, _ft1_ctx,
|
||||
group_number, peer_number,
|
||||
@ -274,7 +381,7 @@ bool ToxClient::sendFT1RequestPrivate(uint32_t group_number, uint32_t peer_numbe
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToxClient::sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id) {
|
||||
bool ToxClient::sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, uint32_t file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id) {
|
||||
return NGC_FT1_send_init_private(
|
||||
_tox, _ft1_ctx,
|
||||
group_number, peer_number,
|
||||
|
@ -4,15 +4,17 @@
|
||||
|
||||
#include "./state.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <tox/tox.h>
|
||||
#include <ngc_ext.h>
|
||||
#include <ngc_ft1.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
// fwd
|
||||
namespace States {
|
||||
@ -31,6 +33,9 @@ struct ToxClient {
|
||||
|
||||
std::string getOwnAddress(void) const;
|
||||
|
||||
std::string_view getGroupPeerName(uint32_t group_number, uint32_t peer_number) const;
|
||||
TOX_CONNECTION getGroupPeerConnectionStatus(uint32_t group_number, uint32_t peer_number) const;
|
||||
|
||||
template<typename FN>
|
||||
void forEachGroup(FN&& fn) const {
|
||||
for (const auto& it : _groups) {
|
||||
@ -41,7 +46,7 @@ struct ToxClient {
|
||||
template<typename FN>
|
||||
void forEachGroupPeer(uint32_t group_number, FN&& fn) const {
|
||||
if (_groups.count(group_number)) {
|
||||
for (const uint32_t peer_number : _groups.at(group_number)) {
|
||||
for (const auto& [peer_number, peer] : _groups.at(group_number)) {
|
||||
fn(peer_number);
|
||||
}
|
||||
}
|
||||
@ -50,6 +55,8 @@ struct ToxClient {
|
||||
public: // tox callbacks
|
||||
void onToxSelfConnectionStatus(TOX_CONNECTION connection_status);
|
||||
void onToxFriendRequest(const uint8_t* public_key, std::string_view message);
|
||||
void onToxGroupPeerName(uint32_t group_number, uint32_t peer_id, std::string_view name);
|
||||
//void onToxGroupPeerConnection(uint32_t group_number, uint32_t peer_id, TOX_CONNECTION connection_status);
|
||||
void onToxGroupCustomPacket(uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length);
|
||||
void onToxGroupCustomPrivatePacket(uint32_t group_number, uint32_t peer_id, const uint8_t *data, size_t length);
|
||||
void onToxGroupInvite(uint32_t friend_number, const uint8_t* invite_data, size_t invite_length, std::string_view group_name);
|
||||
@ -61,8 +68,8 @@ struct ToxClient {
|
||||
StateI& getState(void); // public accessor for callbacks
|
||||
|
||||
public: // FT1 sends
|
||||
bool sendFT1RequestPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size);
|
||||
bool sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, NGC_FT1_file_kind file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id);
|
||||
bool sendFT1RequestPrivate(uint32_t group_number, uint32_t peer_number, uint32_t file_kind, const uint8_t* file_id, size_t file_id_size);
|
||||
bool sendFT1InitPrivate(uint32_t group_number, uint32_t peer_number, uint32_t file_kind, const uint8_t* file_id, size_t file_id_size, uint64_t file_size, uint8_t& transfer_id);
|
||||
|
||||
private:
|
||||
void saveToxProfile(void);
|
||||
@ -72,14 +79,22 @@ struct ToxClient {
|
||||
NGC_EXT_CTX* _ext_ctx {nullptr};
|
||||
NGC_FT1* _ft1_ctx {nullptr};
|
||||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> _last_time {std::chrono::high_resolution_clock::now()};
|
||||
|
||||
std::string _self_name;
|
||||
|
||||
std::string _tox_profile_path;
|
||||
bool _tox_profile_dirty {false}; // set in callbacks
|
||||
|
||||
std::vector<uint8_t> _join_group_after_dht_connect;
|
||||
float _rejoin_group_timer {4.f * 60.f};
|
||||
|
||||
std::unique_ptr<StateI> _state;
|
||||
|
||||
// key groupid, value set of peer ids
|
||||
std::map<uint32_t, std::set<uint32_t>> _groups;
|
||||
struct Peer {
|
||||
std::string name;
|
||||
};
|
||||
// key groupid, key peerid
|
||||
std::map<uint32_t, std::map<uint32_t, Peer>> _groups;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user