Compare commits
	
		
			152 Commits
		
	
	
		
			3deb6e8
			...
			dev-8c2423
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8c24234126 | ||
| e0d873d41c | |||
| 5728432b76 | |||
| 0030487613 | |||
| f932f5ffb4 | |||
| da83065024 | |||
| a6614e76ce | |||
| cdd67f4779 | |||
| a845609660 | |||
| de3b8f059e | |||
| 7b4af58544 | |||
| f287348550 | |||
| 498b4435c7 | |||
| a5e67d0ee8 | |||
| 9e30983b22 | |||
| 195a87b8ab | |||
| dfbb1dea68 | |||
| 2597edd579 | |||
| 85a29372f4 | |||
| a9f6a5d763 | |||
| 73180195fe | |||
| 10b689ca95 | |||
| 3796841961 | |||
| 854ed851b4 | |||
| 5c3b797a99 | |||
| 8a580e2fbb | |||
| 3cede91aa0 | |||
| 0610a6a64a | |||
| 26d07b06db | |||
| fd0b210bbb | |||
| 268cbe137e | |||
| 31bb0d3e61 | |||
| 248f68f6a2 | |||
| 3b010bd16f | |||
| 7e285290fe | |||
| 5767834f71 | |||
| 53ce292e82 | |||
| 84bd24807d | |||
| 8d0518c2e3 | |||
| 6d150ba441 | |||
| c737715c66 | |||
| b640b5a06b | |||
| 1b9363e7b5 | |||
| 16d2238f35 | |||
| 19844a9423 | |||
| 19fd99f713 | |||
| f22f523774 | |||
| 8b17ed195f | |||
| def7fc1959 | |||
| 318be9cd62 | |||
| 2772c8ee69 | |||
| eac2927379 | |||
| 77a0ae6acd | |||
| 7879a0927b | |||
| 88ea3e177d | |||
| bc22451524 | |||
| 7b8e93eec3 | |||
| 71be5c3c6e | |||
| 2b8cee6a29 | |||
| 5bf4640d61 | |||
| 0e0e81720b | |||
| 592a4cb9cf | |||
| 93f60bd073 | |||
| 6a6de77ae9 | |||
| 89f065a610 | |||
| 52e95ca654 | |||
| eaa316a2aa | |||
| bdf4e60f2f | |||
| 2e3c779bec | |||
| 461a4f1aa7 | |||
| 78488daa9b | |||
| 22f2c8f514 | |||
| e442191aad | |||
| 795ab2d4e1 | |||
| 0896038dd6 | |||
| 67c6f9adb0 | |||
| 6aac44cda9 | |||
| 4fb2b51b7d | |||
| 182d844e32 | |||
| 6f511016bc | |||
| fb885b5c21 | |||
| 527a7c63f6 | |||
| d21dbb43e2 | |||
| 7ac62274f4 | |||
| 4ec87337c8 | |||
| 20f7c6d011 | |||
| 24dc5a03f3 | |||
| 3d0863ff9a | |||
| 97aedca844 | |||
| 2e7d5538d1 | |||
| 1bfd04680e | |||
| 73d1d65142 | |||
| f6e55851cc | |||
| 0b0245d844 | |||
| d278391528 | |||
| aa7a5d6013 | |||
| 84987216cb | |||
| 58e9fd5514 | |||
| 3d41eedf48 | |||
| 2bc30ffcdc | |||
| e67d7d37b5 | |||
| 98ab974515 | |||
| 267f8dffc1 | |||
| b38a1a2507 | |||
| ee87dbc532 | |||
| 78c7ef5b46 | |||
| 95ec596cfd | |||
| 47ad96e2b6 | |||
| 396477f66b | |||
| 01edf9e76e | |||
| bde0f2c7c3 | |||
| 83bbac2cd1 | |||
| d5dede5a61 | |||
| 719400068a | |||
| aaf8c6adc1 | |||
| dc081ae2aa | |||
| 3cf3097094 | |||
| a5093c4aa3 | |||
| e801626232 | |||
| c311bb5c95 | |||
| 887705969f | |||
| 316871523d | |||
| a3d193516c | |||
| 6709dba0e7 | |||
| a8d8613f2c | |||
| aae086cc65 | |||
| 6ec6fe96e4 | |||
| 2d31b57097 | |||
| b1d4848b81 | |||
| 3678301916 | |||
| 459ccf7d6b | |||
| db54afd180 | |||
| f4fe94dfe6 | |||
| 28b92b0f4c | |||
| c966fc6954 | |||
| d0761bf60e | |||
| 0f41ee6a2e | |||
| 0aeafec019 | |||
| 9a0df4f577 | |||
| 61714836bb | |||
| cff0c100ec | |||
| 010c49d100 | |||
| ff5dbaffc0 | |||
| b56d581e4b | |||
| aa661aaaa7 | |||
| cc3f430bab | |||
| 139db5b03b | |||
| 7d0e5c80bd | |||
| f716ad9dd1 | |||
| 671772a20e | |||
| b0173f6d68 | |||
| 3da5872df8 | 
							
								
								
									
										29
									
								
								.github/workflows/cd.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								.github/workflows/cd.yml
									
									
									
									
										vendored
									
									
								
							@@ -30,9 +30,6 @@ jobs:
 | 
				
			|||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: temp test
 | 
					 | 
				
			||||||
      run: ${{github.workspace}}/build/bin/mono_time_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Determine tag name
 | 
					    - name: Determine tag name
 | 
				
			||||||
      id: tag
 | 
					      id: tag
 | 
				
			||||||
      shell: bash
 | 
					      shell: bash
 | 
				
			||||||
@@ -40,10 +37,10 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Compress artifacts
 | 
					    - name: Compress artifacts
 | 
				
			||||||
@@ -84,9 +81,6 @@ jobs:
 | 
				
			|||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: temp test
 | 
					 | 
				
			||||||
      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Determine tag name
 | 
					    - name: Determine tag name
 | 
				
			||||||
      id: tag
 | 
					      id: tag
 | 
				
			||||||
      shell: bash
 | 
					      shell: bash
 | 
				
			||||||
@@ -94,10 +88,10 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Compress artifacts
 | 
					    - name: Compress artifacts
 | 
				
			||||||
@@ -138,9 +132,6 @@ jobs:
 | 
				
			|||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: temp test
 | 
					 | 
				
			||||||
      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Determine tag name
 | 
					    - name: Determine tag name
 | 
				
			||||||
      id: tag
 | 
					      id: tag
 | 
				
			||||||
      shell: bash
 | 
					      shell: bash
 | 
				
			||||||
@@ -148,10 +139,10 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Compress artifacts
 | 
					    - name: Compress artifacts
 | 
				
			||||||
@@ -192,10 +183,10 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
					        SHORT_HASH="$(git rev-parse --short=7 HEAD)"
 | 
				
			||||||
        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
					        if [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
 | 
				
			||||||
          echo "name=${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
					          SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-')
 | 
				
			||||||
          echo "name=${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
					          echo "name=dev-${SAFE_NAME}-${SHORT_HASH}" >> $GITHUB_OUTPUT
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Download artifacts
 | 
					    - name: Download artifacts
 | 
				
			||||||
@@ -212,8 +203,8 @@ jobs:
 | 
				
			|||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        gh release create "$tag" \
 | 
					        gh release create "$tag" \
 | 
				
			||||||
            --repo="$GITHUB_REPOSITORY" \
 | 
					            --repo="$GITHUB_REPOSITORY" \
 | 
				
			||||||
            --title="nightly ${tag#v}" \
 | 
					            --title="${tag#v}" \
 | 
				
			||||||
            --notes="nightly build" \
 | 
					            --notes="preview build of the latest commit" \
 | 
				
			||||||
            --prerelease
 | 
					            --prerelease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Upload artifacts
 | 
					    - name: Upload artifacts
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -29,9 +29,6 @@ jobs:
 | 
				
			|||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: temp test
 | 
					 | 
				
			||||||
      run: ${{github.workspace}}/build/bin/mono_time_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  macos:
 | 
					  macos:
 | 
				
			||||||
    timeout-minutes: 10
 | 
					    timeout-minutes: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,6 +72,3 @@ jobs:
 | 
				
			|||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
					      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -j 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: temp test
 | 
					 | 
				
			||||||
      run: ${{github.workspace}}/build/bin/mono_time_test.exe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -20,3 +20,9 @@
 | 
				
			|||||||
[submodule "external/solanaceae_plugin"]
 | 
					[submodule "external/solanaceae_plugin"]
 | 
				
			||||||
	path = external/solanaceae_plugin
 | 
						path = external/solanaceae_plugin
 | 
				
			||||||
	url = https://github.com/Green-Sky/solanaceae_plugin.git
 | 
						url = https://github.com/Green-Sky/solanaceae_plugin.git
 | 
				
			||||||
 | 
					[submodule "external/solanaceae_object_store"]
 | 
				
			||||||
 | 
						path = external/solanaceae_object_store
 | 
				
			||||||
 | 
						url = https://github.com/Green-Sky/solanaceae_object_store.git
 | 
				
			||||||
 | 
					[submodule "external/solanaceae_message_serializer"]
 | 
				
			||||||
 | 
						path = external/solanaceae_message_serializer
 | 
				
			||||||
 | 
						url = https://github.com/Green-Sky/solanaceae_message_serializer.git
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,8 @@ option(TOMATO_ASAN "Build tomato with asan (gcc/clang/msvc)" OFF)
 | 
				
			|||||||
if (TOMATO_ASAN)
 | 
					if (TOMATO_ASAN)
 | 
				
			||||||
	if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
 | 
						if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
 | 
				
			||||||
		if (NOT WIN32) # exclude mingw
 | 
							if (NOT WIN32) # exclude mingw
 | 
				
			||||||
			link_libraries(-fsanitize=address)
 | 
								#link_libraries(-fsanitize=address)
 | 
				
			||||||
			#link_libraries(-fsanitize=address,undefined)
 | 
								link_libraries(-fsanitize=address,undefined)
 | 
				
			||||||
			#link_libraries(-fsanitize=undefined)
 | 
								#link_libraries(-fsanitize=undefined)
 | 
				
			||||||
			message("II enabled ASAN")
 | 
								message("II enabled ASAN")
 | 
				
			||||||
		else()
 | 
							else()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,3 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Highly experimental solanaceae client with Tox built-in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								external/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								external/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,11 @@
 | 
				
			|||||||
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
 | 
					cmake_minimum_required(VERSION 3.14...3.24 FATAL_ERROR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(./entt)
 | 
					add_subdirectory(./entt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(./solanaceae_util)
 | 
					add_subdirectory(./solanaceae_util)
 | 
				
			||||||
add_subdirectory(./solanaceae_contact)
 | 
					add_subdirectory(./solanaceae_contact)
 | 
				
			||||||
add_subdirectory(./solanaceae_message3)
 | 
					add_subdirectory(./solanaceae_message3)
 | 
				
			||||||
 | 
					add_subdirectory(./solanaceae_message_serializer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(./solanaceae_plugin)
 | 
					add_subdirectory(./solanaceae_plugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,9 +13,12 @@ add_subdirectory(./toxcore)
 | 
				
			|||||||
add_subdirectory(./solanaceae_toxcore)
 | 
					add_subdirectory(./solanaceae_toxcore)
 | 
				
			||||||
add_subdirectory(./solanaceae_tox)
 | 
					add_subdirectory(./solanaceae_tox)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_subdirectory(./solanaceae_object_store)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(./sdl)
 | 
					add_subdirectory(./sdl)
 | 
				
			||||||
add_subdirectory(./imgui)
 | 
					add_subdirectory(./imgui)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(./stb)
 | 
					add_subdirectory(./stb)
 | 
				
			||||||
add_subdirectory(./libwebp)
 | 
					add_subdirectory(./libwebp)
 | 
				
			||||||
 | 
					add_subdirectory(./qoi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								external/qoi/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								external/qoi/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					cmake_minimum_required(VERSION 3.13...3.24 FATAL_ERROR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(qoi C CXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(qoi_interface INTERFACE)
 | 
				
			||||||
 | 
					target_include_directories(qoi_interface SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# static lib with impl
 | 
				
			||||||
 | 
					add_library(qoi "qoi.cpp")
 | 
				
			||||||
 | 
					target_link_libraries(qoi qoi_interface)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								external/qoi/qoi.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/qoi/qoi.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#define QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include <qoi/qoi.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								external/qoi/qoi/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								external/qoi/qoi/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					images/
 | 
				
			||||||
 | 
					stb_image.h
 | 
				
			||||||
 | 
					stb_image_write.h
 | 
				
			||||||
 | 
					qoibench
 | 
				
			||||||
 | 
					qoiconv
 | 
				
			||||||
							
								
								
									
										21
									
								
								external/qoi/qoi/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								external/qoi/qoi/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2022 Dominic Szablewski
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										22
									
								
								external/qoi/qoi/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								external/qoi/qoi/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					CC ?= gcc
 | 
				
			||||||
 | 
					CFLAGS_BENCH ?= -std=gnu99 -O3
 | 
				
			||||||
 | 
					LFLAGS_BENCH ?= -lpng
 | 
				
			||||||
 | 
					CFLAGS_CONV ?= -std=c99 -O3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TARGET_BENCH ?= qoibench
 | 
				
			||||||
 | 
					TARGET_CONV ?= qoiconv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: $(TARGET_BENCH) $(TARGET_CONV)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bench: $(TARGET_BENCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(TARGET_BENCH):$(TARGET_BENCH).c
 | 
				
			||||||
 | 
						$(CC) $(CFLAGS_BENCH) $(CFLAGS) $(TARGET_BENCH).c -o $(TARGET_BENCH) $(LFLAGS_BENCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					conv: $(TARGET_CONV)
 | 
				
			||||||
 | 
					$(TARGET_CONV):$(TARGET_CONV).c
 | 
				
			||||||
 | 
						$(CC) $(CFLAGS_CONV) $(CFLAGS) $(TARGET_CONV).c -o $(TARGET_CONV)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: clean
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						$(RM) $(TARGET_BENCH) $(TARGET_CONV)
 | 
				
			||||||
							
								
								
									
										179
									
								
								external/qoi/qoi/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								external/qoi/qoi/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# QOI - The “Quite OK Image Format” for fast, lossless image compression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Single-file MIT licensed library for C/C++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See [qoi.h](https://github.com/phoboslab/qoi/blob/master/qoi.h) for
 | 
				
			||||||
 | 
					the documentation and format specification.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More info at https://qoiformat.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Why?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Compared to stb_image and stb_image_write QOI offers 20x-50x faster encoding,
 | 
				
			||||||
 | 
					3x-4x faster decoding and 20% better compression. It's also stupidly simple and
 | 
				
			||||||
 | 
					fits in about 300 lines of C.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Example Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [qoiconv.c](https://github.com/phoboslab/qoi/blob/master/qoiconv.c)
 | 
				
			||||||
 | 
					converts between png <> qoi
 | 
				
			||||||
 | 
					 - [qoibench.c](https://github.com/phoboslab/qoi/blob/master/qoibench.c)
 | 
				
			||||||
 | 
					a simple wrapper to benchmark stbi, libpng and qoi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## MIME Type, File Extension
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The recommended MIME type for QOI images is `image/qoi`. While QOI is not yet
 | 
				
			||||||
 | 
					officially registered with IANA, I believe QOI has found enough adoption to
 | 
				
			||||||
 | 
					prevent any future image format from choosing the same name, thus making a 
 | 
				
			||||||
 | 
					MIME type collision highly unlikely ([see #167](https://github.com/phoboslab/qoi/issues/167)).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The recommended file extension for QOI images is `.qoi`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Limitations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The QOI file format allows for huge images with up to 18 exa-pixels. A streaming 
 | 
				
			||||||
 | 
					en-/decoder can handle these with minimal RAM requirements, assuming there is 
 | 
				
			||||||
 | 
					enough storage space.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This particular implementation of QOI however is limited to images with a 
 | 
				
			||||||
 | 
					maximum size of 400 million pixels. It will safely refuse to en-/decode anything
 | 
				
			||||||
 | 
					larger than that. This is not a streaming en-/decoder. It loads the whole image
 | 
				
			||||||
 | 
					file into RAM before doing any work and is not extensively optimized for 
 | 
				
			||||||
 | 
					performance (but it's still very fast).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If this is a limitation for your use case, please look into any of the other 
 | 
				
			||||||
 | 
					implementations listed below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Improvements, New Versions and Contributing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The QOI format has been finalized. It was a conscious decision to **not** have a
 | 
				
			||||||
 | 
					version number in the file header. If you have a working QOI implementation today, 
 | 
				
			||||||
 | 
					you can rest assured that it will be compatible with all QOI files tomorrow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are a lot of interesting ideas for a successor of QOI, but none of these will 
 | 
				
			||||||
 | 
					be implemented here. That doesn't mean you shouldn't experiment with QOI, but please
 | 
				
			||||||
 | 
					be aware that pull requests that change the format will not be accepted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Likewise, pull requests for performance improvements will probably not be accepted
 | 
				
			||||||
 | 
					either, as this "reference implementation" tries to be as easy to read as possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [floooh/qoiview](https://github.com/floooh/qoiview) - native QOI viewer
 | 
				
			||||||
 | 
					- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu/releases) - QOI Plugin installer for Windows Explorer, Finder, GNOME, GIMP, Paint.NET and XnView
 | 
				
			||||||
 | 
					- [iOrange/QoiFileTypeNet](https://github.com/iOrange/QoiFileTypeNet/releases) - QOI Plugin for Paint.NET
 | 
				
			||||||
 | 
					- [iOrange/QOIThumbnailProvider](https://github.com/iOrange/QOIThumbnailProvider) - Add thumbnails for QOI images in Windows Explorer
 | 
				
			||||||
 | 
					- [Tom94/tev](https://github.com/Tom94/tev) - another native QOI viewer (allows pixel peeping and comparison with other image formats)
 | 
				
			||||||
 | 
					- [qoiconverterx](https://apps.apple.com/br/app/qoiconverterx/id1602159820) QOI <=> PNG converter available on the Mac App Store
 | 
				
			||||||
 | 
					- [kaetemi/qoi-ma](https://github.com/kaetemi/qoi-max) - QOI Bitmap I/O Plugin for 3ds Max
 | 
				
			||||||
 | 
					- [rtexviewer](https://raylibtech.itch.io/rtexviewer) - texture viewer, supports QOI
 | 
				
			||||||
 | 
					- [rtexpacker](https://raylibtech.itch.io/rtexpacker) - texture packer, supports QOI
 | 
				
			||||||
 | 
					- [DmitriySalnikov/godot_qoi](https://github.com/DmitriySalnikov/godot_qoi) - QOI GDNative Addon for Godot Engine
 | 
				
			||||||
 | 
					- [dan9er/farbfeld-convert-qoi](https://gitlab.com/dan9er/farbfeld-convert-qoi) - QOI <=> farbfeld converter
 | 
				
			||||||
 | 
					- [LTMX/Unity.QOI](https://github.com/LTMX/Unity.QOI) - QOI Importer and Exporter for the Unity3D Game Engine
 | 
				
			||||||
 | 
					- [Ben1138/unity-qoi](https://github.com/Ben1138/unity-qoi) - QOI Importer(only) support for the Unity3D Game Engine
 | 
				
			||||||
 | 
					- [xiaozhuai/jetbrains-qo](https://github.com/xiaozhuai/jetbrains-qoi) - [QOI Support](https://plugins.jetbrains.com/plugin/19352-qoi-support) for Jetbrains' IDE.
 | 
				
			||||||
 | 
					- [serge-ivamov/QOIql](https://github.com/serge-ivamov/QOIql) - MacOS QuickLook plugin for QOI
 | 
				
			||||||
 | 
					- [tobozo/kde-thumbnailer-qoi](https://github.com/tobozo/kde-thumbnailer-qoi) - QOI Thumbnailer for KDE
 | 
				
			||||||
 | 
					- [walksanatora/qoi-thumbnailer-nemo](https://github.com/walksanatora/qoi-thumbnailer-nemo) - QOI Thumbnailer for Nemo
 | 
				
			||||||
 | 
					- [hzeller/timg](https://github.com/hzeller/timg) - a terminal image viewer with QOI support
 | 
				
			||||||
 | 
					- [LuisAlfredo92/Super-QOI-converter](https://github.com/LuisAlfredo92/Super-QOI-converter "LuisAlfredo92/Super-QOI-converter") - A program to convert JPG, JPEG, BMP, and PNG to QOI
 | 
				
			||||||
 | 
						- [Console version](https://github.com/LuisAlfredo92/Super-QOI-converter-Console- "Console version"): Available for Linux, OSX and Windows
 | 
				
			||||||
 | 
						- [GUI version](https://github.com/LuisAlfredo92/Super-QOI-converter-GUI- "GUI version"): Available only for windows
 | 
				
			||||||
 | 
					- [tacent view](https://github.com/bluescan/tacentview) - Image and texture viewer, supports QOI
 | 
				
			||||||
 | 
					- [colemanrgb/qoi2spr](https://github.com/colemanrgb/qoi2spr) - A variety of applications for decoding and encoding of QOI images on [RISC OS](https://www.riscosopen.org/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Implementations & Bindings of QOI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [pfusik/qoi-fu](https://github.com/pfusik/qoi-fu) - Fusion, transpiling to C, C++, C#, D, Java, JavaScript, Python, Swift and TypeScript
 | 
				
			||||||
 | 
					- [kodonnell/qoi](https://github.com/kodonnell/qoi) - Python
 | 
				
			||||||
 | 
					- [JaffaKetchup/dqoi](https://github.com/JaffaKetchup/dqoi) - Dart, with Flutter support
 | 
				
			||||||
 | 
					- [Cr4xy/lua-qoi](https://github.com/Cr4xy/lua-qoi) - Lua
 | 
				
			||||||
 | 
					- [superzazu/SDL_QOI](https://github.com/superzazu/SDL_QOI) - C, SDL2 bindings
 | 
				
			||||||
 | 
					- [saharNooby/qoi-java](https://github.com/saharNooby/qoi-java) - Java
 | 
				
			||||||
 | 
					- [MasterQ32/zig-qoi](https://github.com/MasterQ32/zig-qoi) - Zig
 | 
				
			||||||
 | 
					- [rbino/qoix](https://github.com/rbino/qoix) - Elixir
 | 
				
			||||||
 | 
					- [NUlliiON/QoiSharp](https://github.com/NUlliiON/QoiSharp) - C#
 | 
				
			||||||
 | 
					- [aldanor/qoi-rust](https://github.com/aldanor/qoi-rust) - Rust
 | 
				
			||||||
 | 
					- [zakarumych/rapid-qoi](https://github.com/zakarumych/rapid-qoi) - Rust
 | 
				
			||||||
 | 
					- [takeyourhatoff/qoi](https://github.com/takeyourhatoff/qoi) - Go
 | 
				
			||||||
 | 
					- [DosWorld/pasqoi](https://github.com/DosWorld/pasqoi) - Pascal
 | 
				
			||||||
 | 
					- [elihwyma/Swift-QOI](https://github.com/elihwyma/Swift-QOI) - Swift
 | 
				
			||||||
 | 
					- [xfmoulet/qoi](https://github.com/xfmoulet/qoi) - Go
 | 
				
			||||||
 | 
					- [erratique.ch/qoic](https://erratique.ch/software/qoic) - OCaml
 | 
				
			||||||
 | 
					- [arian/go-qoi](https://github.com/arian/go-qoi) - Go
 | 
				
			||||||
 | 
					- [kchapelier/qoijs](https://github.com/kchapelier/qoijs) - JavaScript
 | 
				
			||||||
 | 
					- [KristofferC/QOI.jl](https://github.com/KristofferC/QOI.jl) - Julia
 | 
				
			||||||
 | 
					- [shadowMitia/libqoi](https://github.com/shadowMitia/libqoi) - C++
 | 
				
			||||||
 | 
					- [MKCG/php-qoi](https://github.com/MKCG/php-qoi) - PHP
 | 
				
			||||||
 | 
					- [LightHouseSoftware/qoiformats](https://github.com/LightHouseSoftware/qoiformats) - D
 | 
				
			||||||
 | 
					- [mhoward540/qoi-nim](https://github.com/mhoward540/qoi-nim) - Nim
 | 
				
			||||||
 | 
					- [wx257osn2/qoixx](https://github.com/wx257osn2/qoixx) - C++
 | 
				
			||||||
 | 
					- [Tiefseetauchner/lr-paint](https://github.com/Tiefseetauchner/lr-paint) - Processing
 | 
				
			||||||
 | 
					- [amstan/qoi-fpga](https://github.com/amstan/qoi-fpga) - FPGA: verilog
 | 
				
			||||||
 | 
					- [musabkilic/qoi-decoder](https://github.com/musabkilic/qoi-decoder) - Python
 | 
				
			||||||
 | 
					- [mathpn/py-qoi](https://github.com/mathpn/py-qoi) - Python
 | 
				
			||||||
 | 
					- [JohannesFriedrich/qoi4R](https://github.com/JohannesFriedrich/qoi4R) - R
 | 
				
			||||||
 | 
					- [shraiwi/mini-qoi](https://github.com/shraiwi/mini-qoi) - C, streaming decoder
 | 
				
			||||||
 | 
					- [10maurycy10/libqoi/](https://github.com/10maurycy10/libqoi/) - Rust
 | 
				
			||||||
 | 
					- [0xd34df00d/hsqoi](https://github.com/0xd34df00d/hsqoi) - Haskell
 | 
				
			||||||
 | 
					- [418Coffee/qoi-v](https://github.com/418Coffee/qoi-v) - V
 | 
				
			||||||
 | 
					- [Imagine-Programming/QoiImagePlugin](https://github.com/Imagine-Programming/QoiImagePlugin) - PureBasic
 | 
				
			||||||
 | 
					- [Fabien-Chouteau/qoi-spark](https://github.com/Fabien-Chouteau/qoi-spark) - Ada/SPARK formally proven
 | 
				
			||||||
 | 
					- [mzgreen/qoi-kotlin](https://github.com/mzgreen/qoi-kotlin) - Kotlin Multiplatform
 | 
				
			||||||
 | 
					- [Aftersol/Simplified-QOI-Codec](https://github.com/Aftersol/Simplified-QOI-Codec) - C99, encoder and decoder, freestanding
 | 
				
			||||||
 | 
					- [AuburnSounds/gamut](https://github.com/AuburnSounds/gamut) - D
 | 
				
			||||||
 | 
					- [AngusJohnson/TQoiImage](https://github.com/AngusJohnson/TQoiImage) - Delphi
 | 
				
			||||||
 | 
					- [MarkJeronimus/qoi-java-spi](https://github.com/MarkJeronimus/qoi-java-spi) - Java SPI
 | 
				
			||||||
 | 
					- [aumouvantsillage/qoi-racket](https://github.com/aumouvantsillage/qoi-racket) - Racket
 | 
				
			||||||
 | 
					- [rubikscraft/qoi-stream](https://github.com/rubikscraft/qoi-stream) - C99, one byte at a time streaming encoder and decoder
 | 
				
			||||||
 | 
					- [rubikscraft/qoi-img](https://github.com/rubikscraft/qoi-img) - NodeJS typescript, bindings to both [QOIxx](https://github.com/wx257osn2/qoixx) and [qoi-stream](https://github.com/rubikscraft/qoi-stream)
 | 
				
			||||||
 | 
					- [grego/hare-qoi](https://git.sr.ht/~grego/hare-qoi) - Hare
 | 
				
			||||||
 | 
					- [MrNocole/ZTQOI](https://github.com/MrNocole/ZTQOI) - Objective-C
 | 
				
			||||||
 | 
					- [bpanthi977/qoi](https://github.com/bpanthi977/qoi) - Common Lisp
 | 
				
			||||||
 | 
					- [Floessie/pam2qoi](https://github.com/Floessie/pam2qoi) - C++
 | 
				
			||||||
 | 
					- [SpeckyYT/spwn-qoi](https://github.com/SpeckyYT/spwn-qoi) - SPWN
 | 
				
			||||||
 | 
					- [n00bmind/qoi](https://github.com/n00bmind/qoi) - Jai
 | 
				
			||||||
 | 
					- [SixLabors/ImageSharp](https://github.com/SixLabors/ImageSharp) - C# image proccesing library
 | 
				
			||||||
 | 
					- [zertovitch/gid](https://github.com/zertovitch/gid) - Ada
 | 
				
			||||||
 | 
					- [nazrin/lil](https://codeberg.org/nazrin/lil) - Lua image library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## QOI Support in Other Software
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Amiga OS QOI datatype](https://github.com/dgaw/qoi-datatype) - adds support for decoding QOI images to the Amiga operating system.
 | 
				
			||||||
 | 
					- [SerenityOS](https://github.com/SerenityOS/serenity) - supports decoding QOI system wide through a custom [cpp implementation in LibGfx](https://github.com/SerenityOS/serenity/blob/master/Userland/Libraries/LibGfx/QOILoader.h)
 | 
				
			||||||
 | 
					- [Raylib](https://github.com/raysan5/raylib) - supports decoding and encoding QOI textures through its [rtextures module](https://github.com/raysan5/raylib/blob/master/src/rtextures.c)
 | 
				
			||||||
 | 
					- [Rebol3](https://github.com/Oldes/Rebol3/issues/39) - supports decoding and encoding QOI using a native codec
 | 
				
			||||||
 | 
					- [c-ray](https://github.com/vkoskiv/c-ray) - supports QOI natively
 | 
				
			||||||
 | 
					- [SAIL](https://sail.software) - image decoding library, supports decoding and encoding QOI images
 | 
				
			||||||
 | 
					- [Orx](https://github.com/orx/orx) - 2D game engine, supports QOI natively
 | 
				
			||||||
 | 
					- [IrfanView](https://www.irfanview.com) - supports decoding and encoding QOI through its Formats plugin
 | 
				
			||||||
 | 
					- [ImageMagick](https://github.com/ImageMagick/ImageMagick) - supports decoding and encoding QOI, since 7.1.0-20
 | 
				
			||||||
 | 
					- [barebox](https://barebox.org) - bootloader, supports decoding QOI images for splash logo, since v2022.03.0
 | 
				
			||||||
 | 
					- [KorGE](https://korge.org) - & KorIM Kotlin 2D game engine and imaging library, supports decoding and encoding QOI natively since 2.7.0
 | 
				
			||||||
 | 
					- [DOjS](https://github.com/SuperIlu/DOjS) - DOS JavaScript Canvas implementation supports loading QOI files
 | 
				
			||||||
 | 
					- [XnView MP](https://www.xnview.com/en/xnviewmp/) - supports decoding QOI since 1.00
 | 
				
			||||||
 | 
					- [ffmpeg](https://ffmpeg.org/) - supports decoding and encoding QOI since 5.1
 | 
				
			||||||
 | 
					- [JPEGView](https://github.com/sylikc/jpegview) - lightweight Windows image viewer, supports decoding and encoding of QOI natively, since 1.1.44
 | 
				
			||||||
 | 
					- [darktable](https://github.com/darktable-org/darktable) - photography workflow application and raw developer, supports decoding since 4.4.0
 | 
				
			||||||
 | 
					- [KDE](https://kde.org) - supports decoding and encoding QOI images. Implemented in [KImageFormats](https://invent.kde.org/frameworks/kimageformats)
 | 
				
			||||||
 | 
					- [EFL](https://www.enlightenment.org) - supports decoding and encoding QOI images since 1.27.
 | 
				
			||||||
 | 
					- [Swingland](https://git.sr.ht/~phlash/swingland) - supports QOI decoding/loading via the `ImageIO` API of this Java Swing reimplemenation for Wayland
 | 
				
			||||||
 | 
					- [Imagine](https://www.nyam.pe.kr/dev/imagine/) - supports decoding and encoding QOI images since 1.3.9
 | 
				
			||||||
 | 
					- [Uiua](https://uiua.org) - supports decoding and encoding QOI images since 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [AUR](https://aur.archlinux.org/pkgbase/qoi-git/) - system-wide qoi.h, qoiconv and qoibench install as split packages.
 | 
				
			||||||
 | 
					- [Debian](https://packages.debian.org/bookworm/source/qoi) - packages for binaries and qoi.h
 | 
				
			||||||
 | 
					- [Ubuntu](https://launchpad.net/ubuntu/+source/qoi) - packages for binaries and qoi.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Packages for other systems [tracked at Repology](https://repology.org/project/qoi/versions).
 | 
				
			||||||
							
								
								
									
										649
									
								
								external/qoi/qoi/qoi.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										649
									
								
								external/qoi/qoi/qoi.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,649 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QOI - The "Quite OK Image" format for fast, lossless image compression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- About
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QOI encodes and decodes images in a lossless format. Compared to stb_image and
 | 
				
			||||||
 | 
					stb_image_write QOI offers 20x-50x faster encoding, 3x-4x faster decoding and
 | 
				
			||||||
 | 
					20% better compression.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Synopsis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Define `QOI_IMPLEMENTATION` in *one* C/C++ file before including this
 | 
				
			||||||
 | 
					// library to create the implementation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "qoi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Encode and store an RGBA buffer to the file system. The qoi_desc describes
 | 
				
			||||||
 | 
					// the input pixel data.
 | 
				
			||||||
 | 
					qoi_write("image_new.qoi", rgba_pixels, &(qoi_desc){
 | 
				
			||||||
 | 
						.width = 1920,
 | 
				
			||||||
 | 
						.height = 1080,
 | 
				
			||||||
 | 
						.channels = 4,
 | 
				
			||||||
 | 
						.colorspace = QOI_SRGB
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Load and decode a QOI image from the file system into a 32bbp RGBA buffer.
 | 
				
			||||||
 | 
					// The qoi_desc struct will be filled with the width, height, number of channels
 | 
				
			||||||
 | 
					// and colorspace read from the file header.
 | 
				
			||||||
 | 
					qoi_desc desc;
 | 
				
			||||||
 | 
					void *rgba_pixels = qoi_read("image.qoi", &desc, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This library provides the following functions;
 | 
				
			||||||
 | 
					- qoi_read    -- read and decode a QOI file
 | 
				
			||||||
 | 
					- qoi_decode  -- decode the raw bytes of a QOI image from memory
 | 
				
			||||||
 | 
					- qoi_write   -- encode and write a QOI file
 | 
				
			||||||
 | 
					- qoi_encode  -- encode an rgba buffer into a QOI image in memory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					See the function declaration below for the signature and more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you don't want/need the qoi_read and qoi_write functions, you can define
 | 
				
			||||||
 | 
					QOI_NO_STDIO before including this library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This library uses malloc() and free(). To supply your own malloc implementation
 | 
				
			||||||
 | 
					you can define QOI_MALLOC and QOI_FREE before including this library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This library uses memset() to zero-initialize the index. To supply your own
 | 
				
			||||||
 | 
					implementation you can define QOI_ZEROARR before including this library.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Data Format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A QOI file has a 14 byte header, followed by any number of data "chunks" and an
 | 
				
			||||||
 | 
					8-byte end marker.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct qoi_header_t {
 | 
				
			||||||
 | 
						char     magic[4];   // magic bytes "qoif"
 | 
				
			||||||
 | 
						uint32_t width;      // image width in pixels (BE)
 | 
				
			||||||
 | 
						uint32_t height;     // image height in pixels (BE)
 | 
				
			||||||
 | 
						uint8_t  channels;   // 3 = RGB, 4 = RGBA
 | 
				
			||||||
 | 
						uint8_t  colorspace; // 0 = sRGB with linear alpha, 1 = all channels linear
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Images are encoded row by row, left to right, top to bottom. The decoder and
 | 
				
			||||||
 | 
					encoder start with {r: 0, g: 0, b: 0, a: 255} as the previous pixel value. An
 | 
				
			||||||
 | 
					image is complete when all pixels specified by width * height have been covered.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pixels are encoded as
 | 
				
			||||||
 | 
					 - a run of the previous pixel
 | 
				
			||||||
 | 
					 - an index into an array of previously seen pixels
 | 
				
			||||||
 | 
					 - a difference to the previous pixel value in r,g,b
 | 
				
			||||||
 | 
					 - full r,g,b or r,g,b,a values
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The color channels are assumed to not be premultiplied with the alpha channel
 | 
				
			||||||
 | 
					("un-premultiplied alpha").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A running array[64] (zero-initialized) of previously seen pixel values is
 | 
				
			||||||
 | 
					maintained by the encoder and decoder. Each pixel that is seen by the encoder
 | 
				
			||||||
 | 
					and decoder is put into this array at the position formed by a hash function of
 | 
				
			||||||
 | 
					the color value. In the encoder, if the pixel value at the index matches the
 | 
				
			||||||
 | 
					current pixel, this index position is written to the stream as QOI_OP_INDEX.
 | 
				
			||||||
 | 
					The hash function for the index is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						index_position = (r * 3 + g * 5 + b * 7 + a * 11) % 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each chunk starts with a 2- or 8-bit tag, followed by a number of data bits. The
 | 
				
			||||||
 | 
					bit length of chunks is divisible by 8 - i.e. all chunks are byte aligned. All
 | 
				
			||||||
 | 
					values encoded in these data bits have the most significant bit on the left.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The 8-bit tags have precedence over the 2-bit tags. A decoder must check for the
 | 
				
			||||||
 | 
					presence of an 8-bit tag first.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The byte stream's end is marked with 7 0x00 bytes followed a single 0x01 byte.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The possible chunks are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_INDEX ----------.
 | 
				
			||||||
 | 
					|         Byte[0]         |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 |
 | 
				
			||||||
 | 
					|-------+-----------------|
 | 
				
			||||||
 | 
					|  0  0 |     index       |
 | 
				
			||||||
 | 
					`-------------------------`
 | 
				
			||||||
 | 
					2-bit tag b00
 | 
				
			||||||
 | 
					6-bit index into the color index array: 0..63
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A valid encoder must not issue 2 or more consecutive QOI_OP_INDEX chunks to the
 | 
				
			||||||
 | 
					same index. QOI_OP_RUN should be used instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_DIFF -----------.
 | 
				
			||||||
 | 
					|         Byte[0]         |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 |
 | 
				
			||||||
 | 
					|-------+-----+-----+-----|
 | 
				
			||||||
 | 
					|  0  1 |  dr |  dg |  db |
 | 
				
			||||||
 | 
					`-------------------------`
 | 
				
			||||||
 | 
					2-bit tag b01
 | 
				
			||||||
 | 
					2-bit   red channel difference from the previous pixel between -2..1
 | 
				
			||||||
 | 
					2-bit green channel difference from the previous pixel between -2..1
 | 
				
			||||||
 | 
					2-bit  blue channel difference from the previous pixel between -2..1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The difference to the current channel values are using a wraparound operation,
 | 
				
			||||||
 | 
					so "1 - 2" will result in 255, while "255 + 1" will result in 0.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Values are stored as unsigned integers with a bias of 2. E.g. -2 is stored as
 | 
				
			||||||
 | 
					0 (b00). 1 is stored as 3 (b11).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The alpha value remains unchanged from the previous pixel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_LUMA -------------------------------------.
 | 
				
			||||||
 | 
					|         Byte[0]         |         Byte[1]         |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 |  7  6  5  4  3  2  1  0 |
 | 
				
			||||||
 | 
					|-------+-----------------+-------------+-----------|
 | 
				
			||||||
 | 
					|  1  0 |  green diff     |   dr - dg   |  db - dg  |
 | 
				
			||||||
 | 
					`---------------------------------------------------`
 | 
				
			||||||
 | 
					2-bit tag b10
 | 
				
			||||||
 | 
					6-bit green channel difference from the previous pixel -32..31
 | 
				
			||||||
 | 
					4-bit   red channel difference minus green channel difference -8..7
 | 
				
			||||||
 | 
					4-bit  blue channel difference minus green channel difference -8..7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The green channel is used to indicate the general direction of change and is
 | 
				
			||||||
 | 
					encoded in 6 bits. The red and blue channels (dr and db) base their diffs off
 | 
				
			||||||
 | 
					of the green channel difference and are encoded in 4 bits. I.e.:
 | 
				
			||||||
 | 
						dr_dg = (cur_px.r - prev_px.r) - (cur_px.g - prev_px.g)
 | 
				
			||||||
 | 
						db_dg = (cur_px.b - prev_px.b) - (cur_px.g - prev_px.g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The difference to the current channel values are using a wraparound operation,
 | 
				
			||||||
 | 
					so "10 - 13" will result in 253, while "250 + 7" will result in 1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Values are stored as unsigned integers with a bias of 32 for the green channel
 | 
				
			||||||
 | 
					and a bias of 8 for the red and blue channel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The alpha value remains unchanged from the previous pixel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_RUN ------------.
 | 
				
			||||||
 | 
					|         Byte[0]         |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 |
 | 
				
			||||||
 | 
					|-------+-----------------|
 | 
				
			||||||
 | 
					|  1  1 |       run       |
 | 
				
			||||||
 | 
					`-------------------------`
 | 
				
			||||||
 | 
					2-bit tag b11
 | 
				
			||||||
 | 
					6-bit run-length repeating the previous pixel: 1..62
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The run-length is stored with a bias of -1. Note that the run-lengths 63 and 64
 | 
				
			||||||
 | 
					(b111110 and b111111) are illegal as they are occupied by the QOI_OP_RGB and
 | 
				
			||||||
 | 
					QOI_OP_RGBA tags.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_RGB ------------------------------------------.
 | 
				
			||||||
 | 
					|         Byte[0]         | Byte[1] | Byte[2] | Byte[3] |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 | 7 .. 0  | 7 .. 0  | 7 .. 0  |
 | 
				
			||||||
 | 
					|-------------------------+---------+---------+---------|
 | 
				
			||||||
 | 
					|  1  1  1  1  1  1  1  0 |   red   |  green  |  blue   |
 | 
				
			||||||
 | 
					`-------------------------------------------------------`
 | 
				
			||||||
 | 
					8-bit tag b11111110
 | 
				
			||||||
 | 
					8-bit   red channel value
 | 
				
			||||||
 | 
					8-bit green channel value
 | 
				
			||||||
 | 
					8-bit  blue channel value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The alpha value remains unchanged from the previous pixel.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.- QOI_OP_RGBA ---------------------------------------------------.
 | 
				
			||||||
 | 
					|         Byte[0]         | Byte[1] | Byte[2] | Byte[3] | Byte[4] |
 | 
				
			||||||
 | 
					|  7  6  5  4  3  2  1  0 | 7 .. 0  | 7 .. 0  | 7 .. 0  | 7 .. 0  |
 | 
				
			||||||
 | 
					|-------------------------+---------+---------+---------+---------|
 | 
				
			||||||
 | 
					|  1  1  1  1  1  1  1  1 |   red   |  green  |  blue   |  alpha  |
 | 
				
			||||||
 | 
					`-----------------------------------------------------------------`
 | 
				
			||||||
 | 
					8-bit tag b11111111
 | 
				
			||||||
 | 
					8-bit   red channel value
 | 
				
			||||||
 | 
					8-bit green channel value
 | 
				
			||||||
 | 
					8-bit  blue channel value
 | 
				
			||||||
 | 
					8-bit alpha channel value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					Header - Public functions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef QOI_H
 | 
				
			||||||
 | 
					#define QOI_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A pointer to a qoi_desc struct has to be supplied to all of qoi's functions.
 | 
				
			||||||
 | 
					It describes either the input format (for qoi_write and qoi_encode), or is
 | 
				
			||||||
 | 
					filled with the description read from the file header (for qoi_read and
 | 
				
			||||||
 | 
					qoi_decode).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The colorspace in this qoi_desc is an enum where
 | 
				
			||||||
 | 
						0 = sRGB, i.e. gamma scaled RGB channels and a linear alpha channel
 | 
				
			||||||
 | 
						1 = all channels are linear
 | 
				
			||||||
 | 
					You may use the constants QOI_SRGB or QOI_LINEAR. The colorspace is purely
 | 
				
			||||||
 | 
					informative. It will be saved to the file header, but does not affect
 | 
				
			||||||
 | 
					how chunks are en-/decoded. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_SRGB   0
 | 
				
			||||||
 | 
					#define QOI_LINEAR 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						unsigned int width;
 | 
				
			||||||
 | 
						unsigned int height;
 | 
				
			||||||
 | 
						unsigned char channels;
 | 
				
			||||||
 | 
						unsigned char colorspace;
 | 
				
			||||||
 | 
					} qoi_desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef QOI_NO_STDIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encode raw RGB or RGBA pixels into a QOI image and write it to the file
 | 
				
			||||||
 | 
					system. The qoi_desc struct must be filled with the image width, height,
 | 
				
			||||||
 | 
					number of channels (3 = RGB, 4 = RGBA) and the colorspace.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The function returns 0 on failure (invalid parameters, or fopen or malloc
 | 
				
			||||||
 | 
					failed) or the number of bytes written on success. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qoi_write(const char *filename, const void *data, const qoi_desc *desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read and decode a QOI image from the file system. If channels is 0, the
 | 
				
			||||||
 | 
					number of channels from the file header is used. If channels is 3 or 4 the
 | 
				
			||||||
 | 
					output format will be forced into this number of channels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The function either returns NULL on failure (invalid data, or malloc or fopen
 | 
				
			||||||
 | 
					failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
 | 
				
			||||||
 | 
					will be filled with the description from the file header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The returned pixel data should be free()d after use. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_read(const char *filename, qoi_desc *desc, int channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* QOI_NO_STDIO */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Encode raw RGB or RGBA pixels into a QOI image in memory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The function either returns NULL on failure (invalid parameters or malloc
 | 
				
			||||||
 | 
					failed) or a pointer to the encoded data on success. On success the out_len
 | 
				
			||||||
 | 
					is set to the size in bytes of the encoded data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The returned qoi data should be free()d after use. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Decode a QOI image from memory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The function either returns NULL on failure (invalid parameters or malloc
 | 
				
			||||||
 | 
					failed) or a pointer to the decoded pixels. On success, the qoi_desc struct
 | 
				
			||||||
 | 
					is filled with the description from the file header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The returned pixel data should be free()d after use. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif /* QOI_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					Implementation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef QOI_MALLOC
 | 
				
			||||||
 | 
						#define QOI_MALLOC(sz) malloc(sz)
 | 
				
			||||||
 | 
						#define QOI_FREE(p)    free(p)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef QOI_ZEROARR
 | 
				
			||||||
 | 
						#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_OP_INDEX  0x00 /* 00xxxxxx */
 | 
				
			||||||
 | 
					#define QOI_OP_DIFF   0x40 /* 01xxxxxx */
 | 
				
			||||||
 | 
					#define QOI_OP_LUMA   0x80 /* 10xxxxxx */
 | 
				
			||||||
 | 
					#define QOI_OP_RUN    0xc0 /* 11xxxxxx */
 | 
				
			||||||
 | 
					#define QOI_OP_RGB    0xfe /* 11111110 */
 | 
				
			||||||
 | 
					#define QOI_OP_RGBA   0xff /* 11111111 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_MASK_2    0xc0 /* 11000000 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
 | 
				
			||||||
 | 
					#define QOI_MAGIC \
 | 
				
			||||||
 | 
						(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
 | 
				
			||||||
 | 
						 ((unsigned int)'i') <<  8 | ((unsigned int)'f'))
 | 
				
			||||||
 | 
					#define QOI_HEADER_SIZE 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 2GB is the max file size that this implementation can safely handle. We guard
 | 
				
			||||||
 | 
					against anything larger than that, assuming the worst case with 5 bytes per
 | 
				
			||||||
 | 
					pixel, rounded down to a nice clean value. 400 million pixels ought to be
 | 
				
			||||||
 | 
					enough for anybody. */
 | 
				
			||||||
 | 
					#define QOI_PIXELS_MAX ((unsigned int)400000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
						struct { unsigned char r, g, b, a; } rgba;
 | 
				
			||||||
 | 
						unsigned int v;
 | 
				
			||||||
 | 
					} qoi_rgba_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
 | 
				
			||||||
 | 
						bytes[(*p)++] = (0xff000000 & v) >> 24;
 | 
				
			||||||
 | 
						bytes[(*p)++] = (0x00ff0000 & v) >> 16;
 | 
				
			||||||
 | 
						bytes[(*p)++] = (0x0000ff00 & v) >> 8;
 | 
				
			||||||
 | 
						bytes[(*p)++] = (0x000000ff & v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static unsigned int qoi_read_32(const unsigned char *bytes, int *p) {
 | 
				
			||||||
 | 
						unsigned int a = bytes[(*p)++];
 | 
				
			||||||
 | 
						unsigned int b = bytes[(*p)++];
 | 
				
			||||||
 | 
						unsigned int c = bytes[(*p)++];
 | 
				
			||||||
 | 
						unsigned int d = bytes[(*p)++];
 | 
				
			||||||
 | 
						return a << 24 | b << 16 | c << 8 | d;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
 | 
				
			||||||
 | 
						int i, max_size, p, run;
 | 
				
			||||||
 | 
						int px_len, px_end, px_pos, channels;
 | 
				
			||||||
 | 
						unsigned char *bytes;
 | 
				
			||||||
 | 
						const unsigned char *pixels;
 | 
				
			||||||
 | 
						qoi_rgba_t index[64];
 | 
				
			||||||
 | 
						qoi_rgba_t px, px_prev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (
 | 
				
			||||||
 | 
							data == NULL || out_len == NULL || desc == NULL ||
 | 
				
			||||||
 | 
							desc->width == 0 || desc->height == 0 ||
 | 
				
			||||||
 | 
							desc->channels < 3 || desc->channels > 4 ||
 | 
				
			||||||
 | 
							desc->colorspace > 1 ||
 | 
				
			||||||
 | 
							desc->height >= QOI_PIXELS_MAX / desc->width
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						max_size =
 | 
				
			||||||
 | 
							desc->width * desc->height * (desc->channels + 1) +
 | 
				
			||||||
 | 
							QOI_HEADER_SIZE + sizeof(qoi_padding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = 0;
 | 
				
			||||||
 | 
						bytes = (unsigned char *) QOI_MALLOC(max_size);
 | 
				
			||||||
 | 
						if (!bytes) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qoi_write_32(bytes, &p, QOI_MAGIC);
 | 
				
			||||||
 | 
						qoi_write_32(bytes, &p, desc->width);
 | 
				
			||||||
 | 
						qoi_write_32(bytes, &p, desc->height);
 | 
				
			||||||
 | 
						bytes[p++] = desc->channels;
 | 
				
			||||||
 | 
						bytes[p++] = desc->colorspace;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pixels = (const unsigned char *)data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QOI_ZEROARR(index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						run = 0;
 | 
				
			||||||
 | 
						px_prev.rgba.r = 0;
 | 
				
			||||||
 | 
						px_prev.rgba.g = 0;
 | 
				
			||||||
 | 
						px_prev.rgba.b = 0;
 | 
				
			||||||
 | 
						px_prev.rgba.a = 255;
 | 
				
			||||||
 | 
						px = px_prev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						px_len = desc->width * desc->height * desc->channels;
 | 
				
			||||||
 | 
						px_end = px_len - desc->channels;
 | 
				
			||||||
 | 
						channels = desc->channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (px_pos = 0; px_pos < px_len; px_pos += channels) {
 | 
				
			||||||
 | 
							px.rgba.r = pixels[px_pos + 0];
 | 
				
			||||||
 | 
							px.rgba.g = pixels[px_pos + 1];
 | 
				
			||||||
 | 
							px.rgba.b = pixels[px_pos + 2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (channels == 4) {
 | 
				
			||||||
 | 
								px.rgba.a = pixels[px_pos + 3];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (px.v == px_prev.v) {
 | 
				
			||||||
 | 
								run++;
 | 
				
			||||||
 | 
								if (run == 62 || px_pos == px_end) {
 | 
				
			||||||
 | 
									bytes[p++] = QOI_OP_RUN | (run - 1);
 | 
				
			||||||
 | 
									run = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								int index_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (run > 0) {
 | 
				
			||||||
 | 
									bytes[p++] = QOI_OP_RUN | (run - 1);
 | 
				
			||||||
 | 
									run = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								index_pos = QOI_COLOR_HASH(px) % 64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (index[index_pos].v == px.v) {
 | 
				
			||||||
 | 
									bytes[p++] = QOI_OP_INDEX | index_pos;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									index[index_pos] = px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (px.rgba.a == px_prev.rgba.a) {
 | 
				
			||||||
 | 
										signed char vr = px.rgba.r - px_prev.rgba.r;
 | 
				
			||||||
 | 
										signed char vg = px.rgba.g - px_prev.rgba.g;
 | 
				
			||||||
 | 
										signed char vb = px.rgba.b - px_prev.rgba.b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										signed char vg_r = vr - vg;
 | 
				
			||||||
 | 
										signed char vg_b = vb - vg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (
 | 
				
			||||||
 | 
											vr > -3 && vr < 2 &&
 | 
				
			||||||
 | 
											vg > -3 && vg < 2 &&
 | 
				
			||||||
 | 
											vb > -3 && vb < 2
 | 
				
			||||||
 | 
										) {
 | 
				
			||||||
 | 
											bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if (
 | 
				
			||||||
 | 
											vg_r >  -9 && vg_r <  8 &&
 | 
				
			||||||
 | 
											vg   > -33 && vg   < 32 &&
 | 
				
			||||||
 | 
											vg_b >  -9 && vg_b <  8
 | 
				
			||||||
 | 
										) {
 | 
				
			||||||
 | 
											bytes[p++] = QOI_OP_LUMA     | (vg   + 32);
 | 
				
			||||||
 | 
											bytes[p++] = (vg_r + 8) << 4 | (vg_b +  8);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else {
 | 
				
			||||||
 | 
											bytes[p++] = QOI_OP_RGB;
 | 
				
			||||||
 | 
											bytes[p++] = px.rgba.r;
 | 
				
			||||||
 | 
											bytes[p++] = px.rgba.g;
 | 
				
			||||||
 | 
											bytes[p++] = px.rgba.b;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										bytes[p++] = QOI_OP_RGBA;
 | 
				
			||||||
 | 
										bytes[p++] = px.rgba.r;
 | 
				
			||||||
 | 
										bytes[p++] = px.rgba.g;
 | 
				
			||||||
 | 
										bytes[p++] = px.rgba.b;
 | 
				
			||||||
 | 
										bytes[p++] = px.rgba.a;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							px_prev = px;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < (int)sizeof(qoi_padding); i++) {
 | 
				
			||||||
 | 
							bytes[p++] = qoi_padding[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*out_len = p;
 | 
				
			||||||
 | 
						return bytes;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
 | 
				
			||||||
 | 
						const unsigned char *bytes;
 | 
				
			||||||
 | 
						unsigned int header_magic;
 | 
				
			||||||
 | 
						unsigned char *pixels;
 | 
				
			||||||
 | 
						qoi_rgba_t index[64];
 | 
				
			||||||
 | 
						qoi_rgba_t px;
 | 
				
			||||||
 | 
						int px_len, chunks_len, px_pos;
 | 
				
			||||||
 | 
						int p = 0, run = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (
 | 
				
			||||||
 | 
							data == NULL || desc == NULL ||
 | 
				
			||||||
 | 
							(channels != 0 && channels != 3 && channels != 4) ||
 | 
				
			||||||
 | 
							size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding)
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bytes = (const unsigned char *)data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						header_magic = qoi_read_32(bytes, &p);
 | 
				
			||||||
 | 
						desc->width = qoi_read_32(bytes, &p);
 | 
				
			||||||
 | 
						desc->height = qoi_read_32(bytes, &p);
 | 
				
			||||||
 | 
						desc->channels = bytes[p++];
 | 
				
			||||||
 | 
						desc->colorspace = bytes[p++];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (
 | 
				
			||||||
 | 
							desc->width == 0 || desc->height == 0 ||
 | 
				
			||||||
 | 
							desc->channels < 3 || desc->channels > 4 ||
 | 
				
			||||||
 | 
							desc->colorspace > 1 ||
 | 
				
			||||||
 | 
							header_magic != QOI_MAGIC ||
 | 
				
			||||||
 | 
							desc->height >= QOI_PIXELS_MAX / desc->width
 | 
				
			||||||
 | 
						) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (channels == 0) {
 | 
				
			||||||
 | 
							channels = desc->channels;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						px_len = desc->width * desc->height * channels;
 | 
				
			||||||
 | 
						pixels = (unsigned char *) QOI_MALLOC(px_len);
 | 
				
			||||||
 | 
						if (!pixels) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QOI_ZEROARR(index);
 | 
				
			||||||
 | 
						px.rgba.r = 0;
 | 
				
			||||||
 | 
						px.rgba.g = 0;
 | 
				
			||||||
 | 
						px.rgba.b = 0;
 | 
				
			||||||
 | 
						px.rgba.a = 255;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						chunks_len = size - (int)sizeof(qoi_padding);
 | 
				
			||||||
 | 
						for (px_pos = 0; px_pos < px_len; px_pos += channels) {
 | 
				
			||||||
 | 
							if (run > 0) {
 | 
				
			||||||
 | 
								run--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (p < chunks_len) {
 | 
				
			||||||
 | 
								int b1 = bytes[p++];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (b1 == QOI_OP_RGB) {
 | 
				
			||||||
 | 
									px.rgba.r = bytes[p++];
 | 
				
			||||||
 | 
									px.rgba.g = bytes[p++];
 | 
				
			||||||
 | 
									px.rgba.b = bytes[p++];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (b1 == QOI_OP_RGBA) {
 | 
				
			||||||
 | 
									px.rgba.r = bytes[p++];
 | 
				
			||||||
 | 
									px.rgba.g = bytes[p++];
 | 
				
			||||||
 | 
									px.rgba.b = bytes[p++];
 | 
				
			||||||
 | 
									px.rgba.a = bytes[p++];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) {
 | 
				
			||||||
 | 
									px = index[b1];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) {
 | 
				
			||||||
 | 
									px.rgba.r += ((b1 >> 4) & 0x03) - 2;
 | 
				
			||||||
 | 
									px.rgba.g += ((b1 >> 2) & 0x03) - 2;
 | 
				
			||||||
 | 
									px.rgba.b += ( b1       & 0x03) - 2;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) {
 | 
				
			||||||
 | 
									int b2 = bytes[p++];
 | 
				
			||||||
 | 
									int vg = (b1 & 0x3f) - 32;
 | 
				
			||||||
 | 
									px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
 | 
				
			||||||
 | 
									px.rgba.g += vg;
 | 
				
			||||||
 | 
									px.rgba.b += vg - 8 +  (b2       & 0x0f);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) {
 | 
				
			||||||
 | 
									run = (b1 & 0x3f);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								index[QOI_COLOR_HASH(px) % 64] = px;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pixels[px_pos + 0] = px.rgba.r;
 | 
				
			||||||
 | 
							pixels[px_pos + 1] = px.rgba.g;
 | 
				
			||||||
 | 
							pixels[px_pos + 2] = px.rgba.b;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (channels == 4) {
 | 
				
			||||||
 | 
								pixels[px_pos + 3] = px.rgba.a;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pixels;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef QOI_NO_STDIO
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int qoi_write(const char *filename, const void *data, const qoi_desc *desc) {
 | 
				
			||||||
 | 
						FILE *f = fopen(filename, "wb");
 | 
				
			||||||
 | 
						int size, err;
 | 
				
			||||||
 | 
						void *encoded;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!f) {
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						encoded = qoi_encode(data, desc, &size);
 | 
				
			||||||
 | 
						if (!encoded) {
 | 
				
			||||||
 | 
							fclose(f);
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fwrite(encoded, 1, size, f);
 | 
				
			||||||
 | 
						fflush(f);
 | 
				
			||||||
 | 
						err = ferror(f);
 | 
				
			||||||
 | 
						fclose(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						QOI_FREE(encoded);
 | 
				
			||||||
 | 
						return err ? 0 : size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *qoi_read(const char *filename, qoi_desc *desc, int channels) {
 | 
				
			||||||
 | 
						FILE *f = fopen(filename, "rb");
 | 
				
			||||||
 | 
						int size, bytes_read;
 | 
				
			||||||
 | 
						void *pixels, *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!f) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fseek(f, 0, SEEK_END);
 | 
				
			||||||
 | 
						size = ftell(f);
 | 
				
			||||||
 | 
						if (size <= 0 || fseek(f, 0, SEEK_SET) != 0) {
 | 
				
			||||||
 | 
							fclose(f);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data = QOI_MALLOC(size);
 | 
				
			||||||
 | 
						if (!data) {
 | 
				
			||||||
 | 
							fclose(f);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bytes_read = fread(data, 1, size, f);
 | 
				
			||||||
 | 
						fclose(f);
 | 
				
			||||||
 | 
						pixels = (bytes_read != size) ? NULL : qoi_decode(data, bytes_read, desc, channels);
 | 
				
			||||||
 | 
						QOI_FREE(data);
 | 
				
			||||||
 | 
						return pixels;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* QOI_NO_STDIO */
 | 
				
			||||||
 | 
					#endif /* QOI_IMPLEMENTATION */
 | 
				
			||||||
							
								
								
									
										610
									
								
								external/qoi/qoi/qoibench.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										610
									
								
								external/qoi/qoi/qoibench.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,610 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Simple benchmark suite for png, stbi and qoi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Requires libpng, "stb_image.h" and "stb_image_write.h"
 | 
				
			||||||
 | 
					Compile with: 
 | 
				
			||||||
 | 
						gcc qoibench.c -std=gnu99 -lpng -O3 -o qoibench 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <dirent.h>
 | 
				
			||||||
 | 
					#include <png.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STB_IMAGE_IMPLEMENTATION
 | 
				
			||||||
 | 
					#define STBI_ONLY_PNG
 | 
				
			||||||
 | 
					#define STBI_NO_LINEAR
 | 
				
			||||||
 | 
					#include "stb_image.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STB_IMAGE_WRITE_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "stb_image_write.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "qoi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// Cross platform high resolution timer
 | 
				
			||||||
 | 
					// From https://gist.github.com/ForeverZer0/0a4f80fc02b96e19380ebb7a3debbee5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#if defined(__linux)
 | 
				
			||||||
 | 
						#define HAVE_POSIX_TIMER
 | 
				
			||||||
 | 
						#include <time.h>
 | 
				
			||||||
 | 
						#ifdef CLOCK_MONOTONIC
 | 
				
			||||||
 | 
							#define CLOCKID CLOCK_MONOTONIC
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							#define CLOCKID CLOCK_REALTIME
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					#elif defined(__APPLE__)
 | 
				
			||||||
 | 
						#define HAVE_MACH_TIMER
 | 
				
			||||||
 | 
						#include <mach/mach_time.h>
 | 
				
			||||||
 | 
					#elif defined(_WIN32)
 | 
				
			||||||
 | 
						#define WIN32_LEAN_AND_MEAN
 | 
				
			||||||
 | 
						#include <windows.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint64_t ns() {
 | 
				
			||||||
 | 
						static uint64_t is_init = 0;
 | 
				
			||||||
 | 
					#if defined(__APPLE__)
 | 
				
			||||||
 | 
							static mach_timebase_info_data_t info;
 | 
				
			||||||
 | 
							if (0 == is_init) {
 | 
				
			||||||
 | 
								mach_timebase_info(&info);
 | 
				
			||||||
 | 
								is_init = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							uint64_t now;
 | 
				
			||||||
 | 
							now = mach_absolute_time();
 | 
				
			||||||
 | 
							now *= info.numer;
 | 
				
			||||||
 | 
							now /= info.denom;
 | 
				
			||||||
 | 
							return now;
 | 
				
			||||||
 | 
					#elif defined(__linux)
 | 
				
			||||||
 | 
							static struct timespec linux_rate;
 | 
				
			||||||
 | 
							if (0 == is_init) {
 | 
				
			||||||
 | 
								clock_getres(CLOCKID, &linux_rate);
 | 
				
			||||||
 | 
								is_init = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							uint64_t now;
 | 
				
			||||||
 | 
							struct timespec spec;
 | 
				
			||||||
 | 
							clock_gettime(CLOCKID, &spec);
 | 
				
			||||||
 | 
							now = spec.tv_sec * 1.0e9 + spec.tv_nsec;
 | 
				
			||||||
 | 
							return now;
 | 
				
			||||||
 | 
					#elif defined(_WIN32)
 | 
				
			||||||
 | 
							static LARGE_INTEGER win_frequency;
 | 
				
			||||||
 | 
							if (0 == is_init) {
 | 
				
			||||||
 | 
								QueryPerformanceFrequency(&win_frequency);
 | 
				
			||||||
 | 
								is_init = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							LARGE_INTEGER now;
 | 
				
			||||||
 | 
							QueryPerformanceCounter(&now);
 | 
				
			||||||
 | 
							return (uint64_t) ((1e9 * now.QuadPart)	/ win_frequency.QuadPart);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STRINGIFY(x) #x
 | 
				
			||||||
 | 
					#define TOSTRING(x) STRINGIFY(x)
 | 
				
			||||||
 | 
					#define ERROR(...) printf("abort at line " TOSTRING(__LINE__) ": " __VA_ARGS__); printf("\n"); exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// libpng encode/decode wrappers
 | 
				
			||||||
 | 
					// Seriously, who thought this was a good abstraction for an API to read/write
 | 
				
			||||||
 | 
					// images?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						int size;
 | 
				
			||||||
 | 
						int capacity;
 | 
				
			||||||
 | 
						unsigned char *data;
 | 
				
			||||||
 | 
					} libpng_write_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void libpng_encode_callback(png_structp png_ptr, png_bytep data, png_size_t length) {
 | 
				
			||||||
 | 
						libpng_write_t *write_data = (libpng_write_t*)png_get_io_ptr(png_ptr);
 | 
				
			||||||
 | 
						if (write_data->size + length >= write_data->capacity) {
 | 
				
			||||||
 | 
							ERROR("PNG write");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memcpy(write_data->data + write_data->size, data, length);
 | 
				
			||||||
 | 
						write_data->size += length;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *libpng_encode(void *pixels, int w, int h, int channels, int *out_len) {
 | 
				
			||||||
 | 
						png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 | 
				
			||||||
 | 
						if (!png) {
 | 
				
			||||||
 | 
							ERROR("png_create_write_struct");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_infop info = png_create_info_struct(png);
 | 
				
			||||||
 | 
						if (!info) {
 | 
				
			||||||
 | 
							ERROR("png_create_info_struct");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (setjmp(png_jmpbuf(png))) {
 | 
				
			||||||
 | 
							ERROR("png_jmpbuf");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Output is 8bit depth, RGBA format.
 | 
				
			||||||
 | 
						png_set_IHDR(
 | 
				
			||||||
 | 
							png,
 | 
				
			||||||
 | 
							info,
 | 
				
			||||||
 | 
							w, h,
 | 
				
			||||||
 | 
							8,
 | 
				
			||||||
 | 
							channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
 | 
				
			||||||
 | 
							PNG_INTERLACE_NONE,
 | 
				
			||||||
 | 
							PNG_COMPRESSION_TYPE_DEFAULT,
 | 
				
			||||||
 | 
							PNG_FILTER_TYPE_DEFAULT
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_bytep row_pointers[h];
 | 
				
			||||||
 | 
						for(int y = 0; y < h; y++){
 | 
				
			||||||
 | 
							row_pointers[y] = ((unsigned char *)pixels + y * w * channels);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						libpng_write_t write_data = {
 | 
				
			||||||
 | 
							.size = 0,
 | 
				
			||||||
 | 
							.capacity = w * h * channels,
 | 
				
			||||||
 | 
							.data = malloc(w * h * channels)
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_set_rows(png, info, row_pointers);
 | 
				
			||||||
 | 
						png_set_write_fn(png, &write_data, libpng_encode_callback, NULL);
 | 
				
			||||||
 | 
						png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_destroy_write_struct(&png, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*out_len = write_data.size;
 | 
				
			||||||
 | 
						return write_data.data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						int pos;
 | 
				
			||||||
 | 
						int size;
 | 
				
			||||||
 | 
						unsigned char *data;
 | 
				
			||||||
 | 
					} libpng_read_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void png_decode_callback(png_structp png, png_bytep data, png_size_t length) {
 | 
				
			||||||
 | 
						libpng_read_t *read_data = (libpng_read_t*)png_get_io_ptr(png);
 | 
				
			||||||
 | 
						if (read_data->pos + length > read_data->size) {
 | 
				
			||||||
 | 
							ERROR("PNG read %ld bytes at pos %d (size: %d)", length, read_data->pos, read_data->size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memcpy(data, read_data->data + read_data->pos, length);
 | 
				
			||||||
 | 
						read_data->pos += length;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void png_warning_callback(png_structp png_ptr, png_const_charp warning_msg) {
 | 
				
			||||||
 | 
						// Ignore warnings about sRGB profiles and such.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *libpng_decode(void *data, int size, int *out_w, int *out_h) {	
 | 
				
			||||||
 | 
						png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, png_warning_callback);
 | 
				
			||||||
 | 
						if (!png) {
 | 
				
			||||||
 | 
							ERROR("png_create_read_struct");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						png_infop info = png_create_info_struct(png);
 | 
				
			||||||
 | 
						if (!info) {
 | 
				
			||||||
 | 
							ERROR("png_create_info_struct");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						libpng_read_t read_data = {
 | 
				
			||||||
 | 
							.pos = 0,
 | 
				
			||||||
 | 
							.size = size,
 | 
				
			||||||
 | 
							.data = data
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						png_set_read_fn(png, &read_data, png_decode_callback);
 | 
				
			||||||
 | 
						png_set_sig_bytes(png, 0);
 | 
				
			||||||
 | 
						png_read_info(png, info);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						png_uint_32 w, h;
 | 
				
			||||||
 | 
						int bitDepth, colorType, interlaceType;
 | 
				
			||||||
 | 
						png_get_IHDR(png, info, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// 16 bit -> 8 bit
 | 
				
			||||||
 | 
						png_set_strip_16(png);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// 1, 2, 4 bit -> 8 bit
 | 
				
			||||||
 | 
						if (bitDepth < 8) {
 | 
				
			||||||
 | 
							png_set_packing(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (colorType & PNG_COLOR_MASK_PALETTE) {
 | 
				
			||||||
 | 
							png_set_expand(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!(colorType & PNG_COLOR_MASK_COLOR)) {
 | 
				
			||||||
 | 
							png_set_gray_to_rgb(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// set paletted or RGB images with transparency to full alpha so we get RGBA
 | 
				
			||||||
 | 
						if (png_get_valid(png, info, PNG_INFO_tRNS)) {
 | 
				
			||||||
 | 
							png_set_tRNS_to_alpha(png);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// make sure every pixel has an alpha value
 | 
				
			||||||
 | 
						if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
 | 
				
			||||||
 | 
							png_set_filler(png, 255, PNG_FILLER_AFTER);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						png_read_update_info(png, info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned char* out = malloc(w * h * 4);
 | 
				
			||||||
 | 
						*out_w = w;
 | 
				
			||||||
 | 
						*out_h = h;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// png_uint_32 rowBytes = png_get_rowbytes(png, info);
 | 
				
			||||||
 | 
						png_bytep row_pointers[h];
 | 
				
			||||||
 | 
						for (png_uint_32 row = 0; row < h; row++ ) {
 | 
				
			||||||
 | 
							row_pointers[row] = (png_bytep)(out + (row * w * 4));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						png_read_image(png, row_pointers);
 | 
				
			||||||
 | 
						png_read_end(png, info);
 | 
				
			||||||
 | 
						png_destroy_read_struct( &png, &info, NULL);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// stb_image encode callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stbi_write_callback(void *context, void *data, int size) {
 | 
				
			||||||
 | 
						int *encoded_size = (int *)context;
 | 
				
			||||||
 | 
						*encoded_size += size;
 | 
				
			||||||
 | 
						// In theory we'd need to do another malloc(), memcpy() and free() here to 
 | 
				
			||||||
 | 
						// be fair to the other decode functions...
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// function to load a whole file into memory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *fload(const char *path, int *out_size) {
 | 
				
			||||||
 | 
						FILE *fh = fopen(path, "rb");
 | 
				
			||||||
 | 
						if (!fh) {
 | 
				
			||||||
 | 
							ERROR("Can't open file");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fseek(fh, 0, SEEK_END);
 | 
				
			||||||
 | 
						int size = ftell(fh);
 | 
				
			||||||
 | 
						fseek(fh, 0, SEEK_SET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void *buffer = malloc(size);
 | 
				
			||||||
 | 
						if (!buffer) {
 | 
				
			||||||
 | 
							ERROR("Malloc for %d bytes failed", size);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!fread(buffer, size, 1, fh)) {
 | 
				
			||||||
 | 
							ERROR("Can't read file %s", path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fclose(fh);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*out_size = size;
 | 
				
			||||||
 | 
						return buffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// benchmark runner
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int opt_runs = 1;
 | 
				
			||||||
 | 
					int opt_nopng = 0;
 | 
				
			||||||
 | 
					int opt_nowarmup = 0;
 | 
				
			||||||
 | 
					int opt_noverify = 0;
 | 
				
			||||||
 | 
					int opt_nodecode = 0;
 | 
				
			||||||
 | 
					int opt_noencode = 0;
 | 
				
			||||||
 | 
					int opt_norecurse = 0;
 | 
				
			||||||
 | 
					int opt_onlytotals = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						LIBPNG,
 | 
				
			||||||
 | 
						STBI,
 | 
				
			||||||
 | 
						QOI,
 | 
				
			||||||
 | 
						BENCH_COUNT /* must be the last element */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					static const char *const lib_names[BENCH_COUNT] = {
 | 
				
			||||||
 | 
						// NOTE: pad with spaces so everything lines up properly
 | 
				
			||||||
 | 
						[LIBPNG] =  "libpng: ",
 | 
				
			||||||
 | 
						[STBI]   =  "stbi:   ",
 | 
				
			||||||
 | 
						[QOI]    =  "qoi:    ",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						uint64_t size;
 | 
				
			||||||
 | 
						uint64_t encode_time;
 | 
				
			||||||
 | 
						uint64_t decode_time;
 | 
				
			||||||
 | 
					} benchmark_lib_result_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
						uint64_t raw_size;
 | 
				
			||||||
 | 
						uint64_t px;
 | 
				
			||||||
 | 
						int w;
 | 
				
			||||||
 | 
						int h;
 | 
				
			||||||
 | 
						benchmark_lib_result_t libs[BENCH_COUNT];
 | 
				
			||||||
 | 
					} benchmark_result_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void benchmark_print_result(benchmark_result_t res) {
 | 
				
			||||||
 | 
						res.px /= res.count;
 | 
				
			||||||
 | 
						res.raw_size /= res.count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double px = res.px;
 | 
				
			||||||
 | 
						printf("          decode ms   encode ms   decode mpps   encode mpps   size kb    rate\n");
 | 
				
			||||||
 | 
						for (int i = 0; i < BENCH_COUNT; ++i) {
 | 
				
			||||||
 | 
							if (opt_nopng && (i == LIBPNG || i == STBI)) {
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							res.libs[i].encode_time /= res.count;
 | 
				
			||||||
 | 
							res.libs[i].decode_time /= res.count;
 | 
				
			||||||
 | 
							res.libs[i].size /= res.count;
 | 
				
			||||||
 | 
							printf(
 | 
				
			||||||
 | 
								"%s   %8.1f    %8.1f      %8.2f      %8.2f  %8ld   %4.1f%%\n",
 | 
				
			||||||
 | 
								lib_names[i],
 | 
				
			||||||
 | 
								(double)res.libs[i].decode_time/1000000.0,
 | 
				
			||||||
 | 
								(double)res.libs[i].encode_time/1000000.0,
 | 
				
			||||||
 | 
								(res.libs[i].decode_time > 0 ? px / ((double)res.libs[i].decode_time/1000.0) : 0),
 | 
				
			||||||
 | 
								(res.libs[i].encode_time > 0 ? px / ((double)res.libs[i].encode_time/1000.0) : 0),
 | 
				
			||||||
 | 
								res.libs[i].size/1024,
 | 
				
			||||||
 | 
								((double)res.libs[i].size/(double)res.raw_size) * 100.0
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						printf("\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Run __VA_ARGS__ a number of times and measure the time taken. The first
 | 
				
			||||||
 | 
					// run is ignored.
 | 
				
			||||||
 | 
					#define BENCHMARK_FN(NOWARMUP, RUNS, AVG_TIME, ...) \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							uint64_t time = 0; \
 | 
				
			||||||
 | 
							for (int i = NOWARMUP; i <= RUNS; i++) { \
 | 
				
			||||||
 | 
								uint64_t time_start = ns(); \
 | 
				
			||||||
 | 
								__VA_ARGS__ \
 | 
				
			||||||
 | 
								uint64_t time_end = ns(); \
 | 
				
			||||||
 | 
								if (i > 0) { \
 | 
				
			||||||
 | 
									time += time_end - time_start; \
 | 
				
			||||||
 | 
								} \
 | 
				
			||||||
 | 
							} \
 | 
				
			||||||
 | 
							AVG_TIME = time / RUNS; \
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					benchmark_result_t benchmark_image(const char *path) {
 | 
				
			||||||
 | 
						int encoded_png_size;
 | 
				
			||||||
 | 
						int encoded_qoi_size;
 | 
				
			||||||
 | 
						int w;
 | 
				
			||||||
 | 
						int h;
 | 
				
			||||||
 | 
						int channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Load the encoded PNG, encoded QOI and raw pixels into memory
 | 
				
			||||||
 | 
						if(!stbi_info(path, &w, &h, &channels)) {
 | 
				
			||||||
 | 
							ERROR("Error decoding header %s", path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (channels != 3) {
 | 
				
			||||||
 | 
							channels = 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void *pixels = (void *)stbi_load(path, &w, &h, NULL, channels);
 | 
				
			||||||
 | 
						void *encoded_png = fload(path, &encoded_png_size);
 | 
				
			||||||
 | 
						void *encoded_qoi = qoi_encode(pixels, &(qoi_desc){
 | 
				
			||||||
 | 
								.width = w,
 | 
				
			||||||
 | 
								.height = h, 
 | 
				
			||||||
 | 
								.channels = channels,
 | 
				
			||||||
 | 
								.colorspace = QOI_SRGB
 | 
				
			||||||
 | 
							}, &encoded_qoi_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pixels || !encoded_qoi || !encoded_png) {
 | 
				
			||||||
 | 
							ERROR("Error encoding %s", path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Verify QOI Output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!opt_noverify) {
 | 
				
			||||||
 | 
							qoi_desc dc;
 | 
				
			||||||
 | 
							void *pixels_qoi = qoi_decode(encoded_qoi, encoded_qoi_size, &dc, channels);
 | 
				
			||||||
 | 
							if (memcmp(pixels, pixels_qoi, w * h * channels) != 0) {
 | 
				
			||||||
 | 
								ERROR("QOI roundtrip pixel mismatch for %s", path);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							free(pixels_qoi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						benchmark_result_t res = {0};
 | 
				
			||||||
 | 
						res.count = 1;
 | 
				
			||||||
 | 
						res.raw_size = w * h * channels;
 | 
				
			||||||
 | 
						res.px = w * h;
 | 
				
			||||||
 | 
						res.w = w;
 | 
				
			||||||
 | 
						res.h = h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Decoding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!opt_nodecode) {
 | 
				
			||||||
 | 
							if (!opt_nopng) {
 | 
				
			||||||
 | 
								BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].decode_time, {
 | 
				
			||||||
 | 
									int dec_w, dec_h;
 | 
				
			||||||
 | 
									void *dec_p = libpng_decode(encoded_png, encoded_png_size, &dec_w, &dec_h);
 | 
				
			||||||
 | 
									free(dec_p);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].decode_time, {
 | 
				
			||||||
 | 
									int dec_w, dec_h, dec_channels;
 | 
				
			||||||
 | 
									void *dec_p = stbi_load_from_memory(encoded_png, encoded_png_size, &dec_w, &dec_h, &dec_channels, 4);
 | 
				
			||||||
 | 
									free(dec_p);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].decode_time, {
 | 
				
			||||||
 | 
								qoi_desc desc;
 | 
				
			||||||
 | 
								void *dec_p = qoi_decode(encoded_qoi, encoded_qoi_size, &desc, 4);
 | 
				
			||||||
 | 
								free(dec_p);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Encoding
 | 
				
			||||||
 | 
						if (!opt_noencode) {
 | 
				
			||||||
 | 
							if (!opt_nopng) {
 | 
				
			||||||
 | 
								BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[LIBPNG].encode_time, {
 | 
				
			||||||
 | 
									int enc_size;
 | 
				
			||||||
 | 
									void *enc_p = libpng_encode(pixels, w, h, channels, &enc_size);
 | 
				
			||||||
 | 
									res.libs[LIBPNG].size = enc_size;
 | 
				
			||||||
 | 
									free(enc_p);
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[STBI].encode_time, {
 | 
				
			||||||
 | 
									int enc_size = 0;
 | 
				
			||||||
 | 
									stbi_write_png_to_func(stbi_write_callback, &enc_size, w, h, channels, pixels, 0);
 | 
				
			||||||
 | 
									res.libs[STBI].size = enc_size;
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							BENCHMARK_FN(opt_nowarmup, opt_runs, res.libs[QOI].encode_time, {
 | 
				
			||||||
 | 
								int enc_size;
 | 
				
			||||||
 | 
								void *enc_p = qoi_encode(pixels, &(qoi_desc){
 | 
				
			||||||
 | 
									.width = w,
 | 
				
			||||||
 | 
									.height = h, 
 | 
				
			||||||
 | 
									.channels = channels,
 | 
				
			||||||
 | 
									.colorspace = QOI_SRGB
 | 
				
			||||||
 | 
								}, &enc_size);
 | 
				
			||||||
 | 
								res.libs[QOI].size = enc_size;
 | 
				
			||||||
 | 
								free(enc_p);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pixels);
 | 
				
			||||||
 | 
						free(encoded_png);
 | 
				
			||||||
 | 
						free(encoded_qoi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void benchmark_directory(const char *path, benchmark_result_t *grand_total) {
 | 
				
			||||||
 | 
						DIR *dir = opendir(path);
 | 
				
			||||||
 | 
						if (!dir) {
 | 
				
			||||||
 | 
							ERROR("Couldn't open directory %s", path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct dirent *file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!opt_norecurse) {
 | 
				
			||||||
 | 
							for (int i = 0; (file = readdir(dir)) != NULL; i++) {
 | 
				
			||||||
 | 
								if (
 | 
				
			||||||
 | 
									file->d_type & DT_DIR &&
 | 
				
			||||||
 | 
									strcmp(file->d_name, ".") != 0 &&
 | 
				
			||||||
 | 
									strcmp(file->d_name, "..") != 0
 | 
				
			||||||
 | 
								) {
 | 
				
			||||||
 | 
									char subpath[1024];
 | 
				
			||||||
 | 
									snprintf(subpath, 1024, "%s/%s", path, file->d_name);
 | 
				
			||||||
 | 
									benchmark_directory(subpath, grand_total);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rewinddir(dir);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						benchmark_result_t dir_total = {0};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						int has_shown_head = 0;
 | 
				
			||||||
 | 
						for (int i = 0; (file = readdir(dir)) != NULL; i++) {
 | 
				
			||||||
 | 
							if (strcmp(file->d_name + strlen(file->d_name) - 4, ".png") != 0) {
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!has_shown_head) {
 | 
				
			||||||
 | 
								has_shown_head = 1;
 | 
				
			||||||
 | 
								printf("## Benchmarking %s/*.png -- %d runs\n\n", path, opt_runs);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							char *file_path = malloc(strlen(file->d_name) + strlen(path)+8);
 | 
				
			||||||
 | 
							sprintf(file_path, "%s/%s", path, file->d_name);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							benchmark_result_t res = benchmark_image(file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!opt_onlytotals) {
 | 
				
			||||||
 | 
								printf("## %s size: %dx%d\n", file_path, res.w, res.h);
 | 
				
			||||||
 | 
								benchmark_print_result(res);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							free(file_path);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							dir_total.count++;
 | 
				
			||||||
 | 
							dir_total.raw_size += res.raw_size;
 | 
				
			||||||
 | 
							dir_total.px += res.px;
 | 
				
			||||||
 | 
							for (int i = 0; i < BENCH_COUNT; ++i) {
 | 
				
			||||||
 | 
								dir_total.libs[i].encode_time += res.libs[i].encode_time;
 | 
				
			||||||
 | 
								dir_total.libs[i].decode_time += res.libs[i].decode_time;
 | 
				
			||||||
 | 
								dir_total.libs[i].size += res.libs[i].size;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							grand_total->count++;
 | 
				
			||||||
 | 
							grand_total->raw_size += res.raw_size;
 | 
				
			||||||
 | 
							grand_total->px += res.px;
 | 
				
			||||||
 | 
							for (int i = 0; i < BENCH_COUNT; ++i) {
 | 
				
			||||||
 | 
								grand_total->libs[i].encode_time += res.libs[i].encode_time;
 | 
				
			||||||
 | 
								grand_total->libs[i].decode_time += res.libs[i].decode_time;
 | 
				
			||||||
 | 
								grand_total->libs[i].size += res.libs[i].size;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						closedir(dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dir_total.count > 0) {
 | 
				
			||||||
 | 
							printf("## Total for %s\n", path);
 | 
				
			||||||
 | 
							benchmark_print_result(dir_total);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
						if (argc < 3) {
 | 
				
			||||||
 | 
							printf("Usage: qoibench <iterations> <directory> [options]\n");
 | 
				
			||||||
 | 
							printf("Options:\n");
 | 
				
			||||||
 | 
							printf("    --nowarmup ... don't perform a warmup run\n");
 | 
				
			||||||
 | 
							printf("    --nopng ...... don't run png encode/decode\n");
 | 
				
			||||||
 | 
							printf("    --noverify ... don't verify qoi roundtrip\n");
 | 
				
			||||||
 | 
							printf("    --noencode ... don't run encoders\n");
 | 
				
			||||||
 | 
							printf("    --nodecode ... don't run decoders\n");
 | 
				
			||||||
 | 
							printf("    --norecurse .. don't descend into directories\n");
 | 
				
			||||||
 | 
							printf("    --onlytotals . don't print individual image results\n");
 | 
				
			||||||
 | 
							printf("Examples\n");
 | 
				
			||||||
 | 
							printf("    qoibench 10 images/textures/\n");
 | 
				
			||||||
 | 
							printf("    qoibench 1 images/textures/ --nopng --nowarmup\n");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 3; i < argc; i++) {
 | 
				
			||||||
 | 
							if (strcmp(argv[i], "--nowarmup") == 0) { opt_nowarmup = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--nopng") == 0) { opt_nopng = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--noverify") == 0) { opt_noverify = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--noencode") == 0) { opt_noencode = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--nodecode") == 0) { opt_nodecode = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--norecurse") == 0) { opt_norecurse = 1; }
 | 
				
			||||||
 | 
							else if (strcmp(argv[i], "--onlytotals") == 0) { opt_onlytotals = 1; }
 | 
				
			||||||
 | 
							else { ERROR("Unknown option %s", argv[i]); }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						opt_runs = atoi(argv[1]);
 | 
				
			||||||
 | 
						if (opt_runs <=0) {
 | 
				
			||||||
 | 
							ERROR("Invalid number of runs %d", opt_runs);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						benchmark_result_t grand_total = {0};
 | 
				
			||||||
 | 
						benchmark_directory(argv[2], &grand_total);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (grand_total.count > 0) {
 | 
				
			||||||
 | 
							printf("# Grand total for %s\n", argv[2]);
 | 
				
			||||||
 | 
							benchmark_print_result(grand_total);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							printf("No images found in %s\n", argv[2]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								external/qoi/qoi/qoiconv.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								external/qoi/qoi/qoiconv.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Command line tool to convert between png <> qoi format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Requires:
 | 
				
			||||||
 | 
						-"stb_image.h" (https://github.com/nothings/stb/blob/master/stb_image.h)
 | 
				
			||||||
 | 
						-"stb_image_write.h" (https://github.com/nothings/stb/blob/master/stb_image_write.h)
 | 
				
			||||||
 | 
						-"qoi.h" (https://github.com/phoboslab/qoi/blob/master/qoi.h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Compile with: 
 | 
				
			||||||
 | 
						gcc qoiconv.c -std=c99 -O3 -o qoiconv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STB_IMAGE_IMPLEMENTATION
 | 
				
			||||||
 | 
					#define STBI_ONLY_PNG
 | 
				
			||||||
 | 
					#define STBI_NO_LINEAR
 | 
				
			||||||
 | 
					#include "stb_image.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STB_IMAGE_WRITE_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "stb_image_write.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "qoi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STR_ENDS_WITH(S, E) (strcmp(S + strlen(S) - (sizeof(E)-1), E) == 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
 | 
						if (argc < 3) {
 | 
				
			||||||
 | 
							puts("Usage: qoiconv <infile> <outfile>");
 | 
				
			||||||
 | 
							puts("Examples:");
 | 
				
			||||||
 | 
							puts("  qoiconv input.png output.qoi");
 | 
				
			||||||
 | 
							puts("  qoiconv input.qoi output.png");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void *pixels = NULL;
 | 
				
			||||||
 | 
						int w, h, channels;
 | 
				
			||||||
 | 
						if (STR_ENDS_WITH(argv[1], ".png")) {
 | 
				
			||||||
 | 
							if(!stbi_info(argv[1], &w, &h, &channels)) {
 | 
				
			||||||
 | 
								printf("Couldn't read header %s\n", argv[1]);
 | 
				
			||||||
 | 
								exit(1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Force all odd encodings to be RGBA
 | 
				
			||||||
 | 
							if(channels != 3) {
 | 
				
			||||||
 | 
								channels = 4;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pixels = (void *)stbi_load(argv[1], &w, &h, NULL, channels);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (STR_ENDS_WITH(argv[1], ".qoi")) {
 | 
				
			||||||
 | 
							qoi_desc desc;
 | 
				
			||||||
 | 
							pixels = qoi_read(argv[1], &desc, 0);
 | 
				
			||||||
 | 
							channels = desc.channels;
 | 
				
			||||||
 | 
							w = desc.width;
 | 
				
			||||||
 | 
							h = desc.height;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pixels == NULL) {
 | 
				
			||||||
 | 
							printf("Couldn't load/decode %s\n", argv[1]);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int encoded = 0;
 | 
				
			||||||
 | 
						if (STR_ENDS_WITH(argv[2], ".png")) {
 | 
				
			||||||
 | 
							encoded = stbi_write_png(argv[2], w, h, channels, pixels, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (STR_ENDS_WITH(argv[2], ".qoi")) {
 | 
				
			||||||
 | 
							encoded = qoi_write(argv[2], pixels, &(qoi_desc){
 | 
				
			||||||
 | 
								.width = w,
 | 
				
			||||||
 | 
								.height = h, 
 | 
				
			||||||
 | 
								.channels = channels,
 | 
				
			||||||
 | 
								.colorspace = QOI_SRGB
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!encoded) {
 | 
				
			||||||
 | 
							printf("Couldn't write/encode %s\n", argv[2]);
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(pixels);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								external/qoi/qoi/qoifuzz.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								external/qoi/qoi/qoifuzz.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clang fuzzing harness for qoi_decode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Compile and run with: 
 | 
				
			||||||
 | 
						clang -fsanitize=address,fuzzer -g -O0 qoifuzz.c && ./a.out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define QOI_IMPLEMENTATION
 | 
				
			||||||
 | 
					#include "qoi.h"
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 | 
				
			||||||
 | 
						int w, h;
 | 
				
			||||||
 | 
						if (size < 4) {
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qoi_desc desc;
 | 
				
			||||||
 | 
						void* decoded = qoi_decode((void*)(data + 4), (int)(size - 4), &desc, *((int *)data));
 | 
				
			||||||
 | 
						if (decoded != NULL) {
 | 
				
			||||||
 | 
							free(decoded);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_contact
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_contact updated: 2d73c7272c...e40271670b
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_message3
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_message3 updated: ab282235b5...f9f70a05b1
									
								
							
							
								
								
									
										1
									
								
								external/solanaceae_message_serializer
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								external/solanaceae_message_serializer
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule external/solanaceae_message_serializer added at 1409485ef1
									
								
							
							
								
								
									
										1
									
								
								external/solanaceae_object_store
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								external/solanaceae_object_store
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule external/solanaceae_object_store added at e26959c380
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_plugin
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_plugin
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_plugin updated: 17ffaee013...82cfb6d492
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_tox
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_tox
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_tox updated: b2a3cb7052...d5c1bf07db
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_toxcore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_toxcore
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_toxcore updated: fa4298d790...cf3679018b
									
								
							
							
								
								
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								external/solanaceae_util
									
									
									
									
										vendored
									
									
								
							 Submodule external/solanaceae_util updated: 390b123fb7...2420af464f
									
								
							
							
								
								
									
										8
									
								
								external/toxcore/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								external/toxcore/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							@@ -19,6 +19,8 @@ add_library(toxcore STATIC
 | 
				
			|||||||
	${TOX_DIR}toxcore/ccompat.h
 | 
						${TOX_DIR}toxcore/ccompat.h
 | 
				
			||||||
	${TOX_DIR}toxcore/crypto_core.c
 | 
						${TOX_DIR}toxcore/crypto_core.c
 | 
				
			||||||
	${TOX_DIR}toxcore/crypto_core.h
 | 
						${TOX_DIR}toxcore/crypto_core.h
 | 
				
			||||||
 | 
						${TOX_DIR}toxcore/crypto_core_pack.c
 | 
				
			||||||
 | 
						${TOX_DIR}toxcore/crypto_core_pack.h
 | 
				
			||||||
	${TOX_DIR}toxcore/DHT.c
 | 
						${TOX_DIR}toxcore/DHT.c
 | 
				
			||||||
	${TOX_DIR}toxcore/DHT.h
 | 
						${TOX_DIR}toxcore/DHT.h
 | 
				
			||||||
	${TOX_DIR}toxcore/events/conference_connected.c
 | 
						${TOX_DIR}toxcore/events/conference_connected.c
 | 
				
			||||||
@@ -27,6 +29,7 @@ add_library(toxcore STATIC
 | 
				
			|||||||
	${TOX_DIR}toxcore/events/conference_peer_list_changed.c
 | 
						${TOX_DIR}toxcore/events/conference_peer_list_changed.c
 | 
				
			||||||
	${TOX_DIR}toxcore/events/conference_peer_name.c
 | 
						${TOX_DIR}toxcore/events/conference_peer_name.c
 | 
				
			||||||
	${TOX_DIR}toxcore/events/conference_title.c
 | 
						${TOX_DIR}toxcore/events/conference_title.c
 | 
				
			||||||
 | 
						${TOX_DIR}toxcore/events/dht_get_nodes_response.c
 | 
				
			||||||
	${TOX_DIR}toxcore/events/events_alloc.c
 | 
						${TOX_DIR}toxcore/events/events_alloc.c
 | 
				
			||||||
	${TOX_DIR}toxcore/events/events_alloc.h
 | 
						${TOX_DIR}toxcore/events/events_alloc.h
 | 
				
			||||||
	${TOX_DIR}toxcore/events/file_chunk_request.c
 | 
						${TOX_DIR}toxcore/events/file_chunk_request.c
 | 
				
			||||||
@@ -209,8 +212,3 @@ add_executable(DHT_Bootstrap EXCLUDE_FROM_ALL
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
target_link_libraries(DHT_Bootstrap toxcore)
 | 
					target_link_libraries(DHT_Bootstrap toxcore)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(mono_time_test
 | 
					 | 
				
			||||||
	./mono_time_test.cc
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
target_link_libraries(mono_time_test toxcore)
 | 
					 | 
				
			||||||
target_compile_features(mono_time_test PUBLIC cxx_std_11)
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								external/toxcore/c-toxcore/.cirrus.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								external/toxcore/c-toxcore/.cirrus.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,13 +7,14 @@ bazel-opt_task:
 | 
				
			|||||||
  configure_script:
 | 
					  configure_script:
 | 
				
			||||||
    - git submodule update --init --recursive
 | 
					    - git submodule update --init --recursive
 | 
				
			||||||
    - /src/workspace/tools/inject-repo c-toxcore
 | 
					    - /src/workspace/tools/inject-repo c-toxcore
 | 
				
			||||||
 | 
					    - sed -i -e 's/build --config=remote/#&/' /src/workspace/.bazelrc.local
 | 
				
			||||||
  test_all_script:
 | 
					  test_all_script:
 | 
				
			||||||
    - cd /src/workspace && bazel test -k
 | 
					    - cd /src/workspace && bazel test -k
 | 
				
			||||||
        --build_tag_filters=-haskell
 | 
					        --build_tag_filters=-haskell
 | 
				
			||||||
        --test_tag_filters=-haskell
 | 
					        --test_tag_filters=-haskell
 | 
				
			||||||
        --
 | 
					        --
 | 
				
			||||||
        //c-toxcore/...
 | 
					        //c-toxcore/...
 | 
				
			||||||
        -//c-toxcore/auto_tests:tcp_relay_test # TODO(robinlinden): Why does this pass locally but not in Cirrus?
 | 
					        -//c-toxcore/auto_tests:tcp_relay_test # Cirrus doesn't allow external network connections.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bazel-dbg_task:
 | 
					bazel-dbg_task:
 | 
				
			||||||
  container:
 | 
					  container:
 | 
				
			||||||
@@ -27,9 +28,10 @@ bazel-dbg_task:
 | 
				
			|||||||
    - cd /src/workspace && bazel test -k
 | 
					    - cd /src/workspace && bazel test -k
 | 
				
			||||||
        --build_tag_filters=-haskell
 | 
					        --build_tag_filters=-haskell
 | 
				
			||||||
        --test_tag_filters=-haskell
 | 
					        --test_tag_filters=-haskell
 | 
				
			||||||
 | 
					        --remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST
 | 
				
			||||||
        --
 | 
					        --
 | 
				
			||||||
        //c-toxcore/...
 | 
					        //c-toxcore/...
 | 
				
			||||||
        -//c-toxcore/auto_tests:tcp_relay_test # TODO(robinlinden): Why does this pass locally but not in Cirrus?
 | 
					        -//c-toxcore/auto_tests:tcp_relay_test # Cirrus doesn't allow external network connections.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cimple_task:
 | 
					cimple_task:
 | 
				
			||||||
  container:
 | 
					  container:
 | 
				
			||||||
@@ -39,6 +41,7 @@ cimple_task:
 | 
				
			|||||||
  configure_script:
 | 
					  configure_script:
 | 
				
			||||||
    - git submodule update --init --recursive
 | 
					    - git submodule update --init --recursive
 | 
				
			||||||
    - /src/workspace/tools/inject-repo c-toxcore
 | 
					    - /src/workspace/tools/inject-repo c-toxcore
 | 
				
			||||||
 | 
					    - sed -i -e 's/build --config=remote/#&/' /src/workspace/.bazelrc.local
 | 
				
			||||||
  test_all_script:
 | 
					  test_all_script:
 | 
				
			||||||
    - cd /src/workspace && bazel test -k
 | 
					    - cd /src/workspace && bazel test -k
 | 
				
			||||||
        --build_tag_filters=haskell
 | 
					        --build_tag_filters=haskell
 | 
				
			||||||
@@ -47,13 +50,30 @@ cimple_task:
 | 
				
			|||||||
        //c-toxcore/...
 | 
					        //c-toxcore/...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
freebsd_task:
 | 
					freebsd_task:
 | 
				
			||||||
  container:
 | 
					  freebsd_instance:
 | 
				
			||||||
    image: toxchat/freebsd:latest
 | 
					    image_family: freebsd-14-0
 | 
				
			||||||
    cpu: 2
 | 
					 | 
				
			||||||
    memory: 4G
 | 
					 | 
				
			||||||
    kvm: true
 | 
					 | 
				
			||||||
  configure_script:
 | 
					  configure_script:
 | 
				
			||||||
 | 
					    - PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
 | 
				
			||||||
 | 
					        cmake
 | 
				
			||||||
 | 
					        git
 | 
				
			||||||
 | 
					        gmake
 | 
				
			||||||
 | 
					        googletest
 | 
				
			||||||
 | 
					        libconfig
 | 
				
			||||||
 | 
					        libsodium
 | 
				
			||||||
 | 
					        libvpx
 | 
				
			||||||
 | 
					        opus
 | 
				
			||||||
 | 
					        pkgconf
 | 
				
			||||||
    - git submodule update --init --recursive
 | 
					    - git submodule update --init --recursive
 | 
				
			||||||
    - cd .. && mv cirrus-ci-build /work/c-toxcore && mkdir cirrus-ci-build
 | 
					 | 
				
			||||||
  test_all_script:
 | 
					  test_all_script:
 | 
				
			||||||
    - cd /work/c-toxcore && .github/scripts/cmake-freebsd
 | 
					    - |
 | 
				
			||||||
 | 
					      # TODO(iphydf): Investigate FreeBSD failures on these tests.
 | 
				
			||||||
 | 
					      sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
 | 
				
			||||||
 | 
					      cmake . \
 | 
				
			||||||
 | 
					        -DMIN_LOGGER_LEVEL=TRACE \
 | 
				
			||||||
 | 
					        -DMUST_BUILD_TOXAV=ON \
 | 
				
			||||||
 | 
					        -DNON_HERMETIC_TESTS=OFF \
 | 
				
			||||||
 | 
					        -DTEST_TIMEOUT_SECONDS=50 \
 | 
				
			||||||
 | 
					        -DUSE_IPV6=OFF \
 | 
				
			||||||
 | 
					        -DAUTOTEST=ON
 | 
				
			||||||
 | 
					      cmake --build . --target install
 | 
				
			||||||
 | 
					      ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								external/toxcore/c-toxcore/.clang-tidy
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								external/toxcore/c-toxcore/.clang-tidy
									
									
									
									
										vendored
									
									
								
							@@ -21,7 +21,7 @@ CheckOptions:
 | 
				
			|||||||
  - key:             readability-identifier-naming.MacroDefinitionCase
 | 
					  - key:             readability-identifier-naming.MacroDefinitionCase
 | 
				
			||||||
    value:           UPPER_CASE
 | 
					    value:           UPPER_CASE
 | 
				
			||||||
  - key:             readability-identifier-naming.MacroDefinitionIgnoredRegexp
 | 
					  - key:             readability-identifier-naming.MacroDefinitionIgnoredRegexp
 | 
				
			||||||
    value:           "^_.*|nullable|non_null|nullptr|static_assert|ck_.*"
 | 
					    value:           "^_.*|bitwise|force|nullable|non_null|nullptr|static_assert|ck_.*"
 | 
				
			||||||
  - key:             readability-identifier-naming.ParameterCase
 | 
					  - key:             readability-identifier-naming.ParameterCase
 | 
				
			||||||
    value:           lower_case
 | 
					    value:           lower_case
 | 
				
			||||||
  - key:             readability-identifier-naming.StructCase
 | 
					  - key:             readability-identifier-naming.StructCase
 | 
				
			||||||
@@ -36,12 +36,14 @@ CheckOptions:
 | 
				
			|||||||
    value:           lower_case
 | 
					    value:           lower_case
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - key:             llvmlibc-restrict-system-libc-headers.Includes
 | 
					  - key:             llvmlibc-restrict-system-libc-headers.Includes
 | 
				
			||||||
    value:           "arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
 | 
					    value:           "alloca.h,arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
 | 
				
			||||||
  - key:             hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
 | 
					  - key:             hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
 | 
				
			||||||
    value:           true
 | 
					    value:           true
 | 
				
			||||||
  - key:             concurrency-mt-unsafe.FunctionSet
 | 
					  - key:             concurrency-mt-unsafe.FunctionSet
 | 
				
			||||||
    value:           posix
 | 
					    value:           posix
 | 
				
			||||||
  - key:             misc-include-cleaner.IgnoreHeaders
 | 
					 | 
				
			||||||
    value:           "pthread.h;stdbool.h;stddef.h;stdint.;stdint.h;stdint...;cstdint;sodium.*;sys/.*;unistd.h;opus.*;vpx.*;attributes.h;tox_struct.h"
 | 
					 | 
				
			||||||
  - key:             readability-function-cognitive-complexity.Threshold
 | 
					  - key:             readability-function-cognitive-complexity.Threshold
 | 
				
			||||||
    value:           153  # TODO(iphydf): Decrease. tox_new is the highest at the moment.
 | 
					    value:           153  # TODO(iphydf): Decrease. tox_new is the highest at the moment.
 | 
				
			||||||
 | 
					  - key:             cppcoreguidelines-avoid-do-while.IgnoreMacros
 | 
				
			||||||
 | 
					    value:           true
 | 
				
			||||||
 | 
					  - key:             readability-simplify-boolean-expr.SimplifyDeMorgan
 | 
				
			||||||
 | 
					    value:           false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ docker run \
 | 
				
			|||||||
  -e ENABLE_ARCH_i686="$i686" \
 | 
					  -e ENABLE_ARCH_i686="$i686" \
 | 
				
			||||||
  -e ENABLE_ARCH_x86_64="$x86_64" \
 | 
					  -e ENABLE_ARCH_x86_64="$x86_64" \
 | 
				
			||||||
  -e ENABLE_TEST=true \
 | 
					  -e ENABLE_TEST=true \
 | 
				
			||||||
  -e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON" \
 | 
					  -e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON -DUSE_IPV6=OFF" \
 | 
				
			||||||
  -e CMAKE_C_FLAGS="$C_FLAGS" \
 | 
					  -e CMAKE_C_FLAGS="$C_FLAGS" \
 | 
				
			||||||
  -e CMAKE_CXX_FLAGS="$CXX_FLAGS" \
 | 
					  -e CMAKE_CXX_FLAGS="$CXX_FLAGS" \
 | 
				
			||||||
  -e CMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \
 | 
					  -e CMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \
 | 
				
			||||||
@@ -26,4 +26,6 @@ docker run \
 | 
				
			|||||||
  -v "$PWD:/toxcore" \
 | 
					  -v "$PWD:/toxcore" \
 | 
				
			||||||
  -v "$PWD/result:/prefix" \
 | 
					  -v "$PWD/result:/prefix" \
 | 
				
			||||||
  --rm \
 | 
					  --rm \
 | 
				
			||||||
 | 
					  -t \
 | 
				
			||||||
 | 
					  --pull never \
 | 
				
			||||||
  "toxchat/windows:$WINDOWS_ARCH"
 | 
					  "toxchat/windows:$WINDOWS_ARCH"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,10 +3,11 @@
 | 
				
			|||||||
set -exu -o pipefail
 | 
					set -exu -o pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOCAL="${1:-}"
 | 
					LOCAL="${1:-}"
 | 
				
			||||||
 | 
					CHECK="${2:-}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
readarray -t FILES <<<"$(git ls-files)"
 | 
					readarray -t FILES <<<"$(git ls-files)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ! tar c "${FILES[@]}" | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
 | 
					if ! tar c "${FILES[@]}" | docker build --build-arg="CHECK=$CHECK" -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
 | 
				
			||||||
  grep -o "::error.*::[a-f0-9]*  /usr/local/bin/tox-bootstrapd" docker-build.log
 | 
					  grep -o "::error.*::[a-f0-9]*  /usr/local/bin/tox-bootstrapd" docker-build.log
 | 
				
			||||||
  false
 | 
					  false
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,16 +15,24 @@ jobs:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  analysis:
 | 
					  analysis:
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
 | 
					      fail-fast: false
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, infer, misra, tcc, tokstyle]
 | 
					        tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, goblint, infer, freebsd, misra, modules, pkgsrc, rpm, slimcc, sparse, tcc, tokstyle]
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
        uses: docker/setup-buildx-action@v3
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
      - name: Docker Build
 | 
					 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/docker/${{ matrix.tool }}/Dockerfile
 | 
					          driver: docker
 | 
				
			||||||
 | 
					      - name: Build toxchat/c-toxcore:sources
 | 
				
			||||||
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          file: other/docker/sources/sources.Dockerfile
 | 
				
			||||||
 | 
					          tags: toxchat/c-toxcore:sources
 | 
				
			||||||
 | 
					      - name: Docker Build
 | 
				
			||||||
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          file: other/docker/${{ matrix.tool }}/${{ matrix.tool }}.Dockerfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  coverage-linux:
 | 
					  coverage-linux:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
@@ -75,7 +83,7 @@ jobs:
 | 
				
			|||||||
      - name: Build and test
 | 
					      - name: Build and test
 | 
				
			||||||
        run: .github/scripts/cmake-osx
 | 
					        run: .github/scripts/cmake-osx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  build-msvc:
 | 
					  build-windows-msvc:
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        version: [2019, 2022]
 | 
					        version: [2019, 2022]
 | 
				
			||||||
@@ -102,17 +110,77 @@ jobs:
 | 
				
			|||||||
          cd _build
 | 
					          cd _build
 | 
				
			||||||
          ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug
 | 
					          ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  build-windows:
 | 
					  build-netbsd:
 | 
				
			||||||
    strategy:
 | 
					 | 
				
			||||||
      matrix:
 | 
					 | 
				
			||||||
        bits: [32, 64]
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v4
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          submodules: recursive
 | 
					          submodules: recursive
 | 
				
			||||||
      - name: Cross compilation
 | 
					      - name: Test in NetBSD
 | 
				
			||||||
        run: .github/scripts/cmake-win${{ matrix.bits }} script
 | 
					        id: test
 | 
				
			||||||
 | 
					        uses: vmactions/netbsd-vm@v1
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          usesh: true
 | 
				
			||||||
 | 
					          copyback: false
 | 
				
			||||||
 | 
					          prepare:
 | 
				
			||||||
 | 
					            /usr/sbin/pkg_add
 | 
				
			||||||
 | 
					              cmake
 | 
				
			||||||
 | 
					              googletest
 | 
				
			||||||
 | 
					              libconfig
 | 
				
			||||||
 | 
					              libopus
 | 
				
			||||||
 | 
					              libsodium
 | 
				
			||||||
 | 
					              libvpx
 | 
				
			||||||
 | 
					              pkg-config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          run: |
 | 
				
			||||||
 | 
					            # TODO(iphydf): Investigate NetBSD failures on these tests.
 | 
				
			||||||
 | 
					            sed -Ei -e '/\((TCP|dht_getnodes_api)\)/s/^/#/' auto_tests/CMakeLists.txt
 | 
				
			||||||
 | 
					            cmake . \
 | 
				
			||||||
 | 
					              -DMIN_LOGGER_LEVEL=TRACE \
 | 
				
			||||||
 | 
					              -DMUST_BUILD_TOXAV=ON \
 | 
				
			||||||
 | 
					              -DNON_HERMETIC_TESTS=ON \
 | 
				
			||||||
 | 
					              -DTEST_TIMEOUT_SECONDS=90 \
 | 
				
			||||||
 | 
					              -DUSE_IPV6=OFF \
 | 
				
			||||||
 | 
					              -DAUTOTEST=ON
 | 
				
			||||||
 | 
					            cmake --build . --target install
 | 
				
			||||||
 | 
					            ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-freebsd:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: recursive
 | 
				
			||||||
 | 
					      - name: Test in FreeBSD
 | 
				
			||||||
 | 
					        id: test
 | 
				
			||||||
 | 
					        uses: vmactions/freebsd-vm@v1
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          usesh: true
 | 
				
			||||||
 | 
					          copyback: false
 | 
				
			||||||
 | 
					          prepare:
 | 
				
			||||||
 | 
					            PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
 | 
				
			||||||
 | 
					              cmake
 | 
				
			||||||
 | 
					              git
 | 
				
			||||||
 | 
					              gmake
 | 
				
			||||||
 | 
					              googletest
 | 
				
			||||||
 | 
					              libconfig
 | 
				
			||||||
 | 
					              libsodium
 | 
				
			||||||
 | 
					              libvpx
 | 
				
			||||||
 | 
					              opus
 | 
				
			||||||
 | 
					              pkgconf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          run: |
 | 
				
			||||||
 | 
					            # TODO(iphydf): Investigate FreeBSD failures on these tests.
 | 
				
			||||||
 | 
					            sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
 | 
				
			||||||
 | 
					            cmake . \
 | 
				
			||||||
 | 
					              -DMIN_LOGGER_LEVEL=TRACE \
 | 
				
			||||||
 | 
					              -DMUST_BUILD_TOXAV=ON \
 | 
				
			||||||
 | 
					              -DNON_HERMETIC_TESTS=ON \
 | 
				
			||||||
 | 
					              -DTEST_TIMEOUT_SECONDS=50 \
 | 
				
			||||||
 | 
					              -DUSE_IPV6=OFF \
 | 
				
			||||||
 | 
					              -DAUTOTEST=ON
 | 
				
			||||||
 | 
					            cmake --build . --target install
 | 
				
			||||||
 | 
					            ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mypy:
 | 
					  mypy:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ jobs:
 | 
				
			|||||||
  latest:
 | 
					  latest:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          submodules: recursive
 | 
					          submodules: recursive
 | 
				
			||||||
      - name: Install libraries
 | 
					      - name: Install libraries
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,9 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          submodules: recursive
 | 
					          submodules: recursive
 | 
				
			||||||
      - name: Docker Build
 | 
					      - name: Docker Build
 | 
				
			||||||
        run: .github/scripts/tox-bootstrapd-docker local
 | 
					        run: .github/scripts/tox-bootstrapd-docker local "$CHECK"
 | 
				
			||||||
 | 
					        env:
 | 
				
			||||||
 | 
					          CHECK: "${{ contains(github.event.pull_request.title, 'chore: Release ') && 'sha256sum' || 'echo' }}"
 | 
				
			||||||
      - name: Push latest image to DockerHub
 | 
					      - name: Push latest image to DockerHub
 | 
				
			||||||
        if: ${{ github.event_name == 'push' }}
 | 
					        if: ${{ github.event_name == 'push' }}
 | 
				
			||||||
        run: docker push toxchat/bootstrap-node:latest
 | 
					        run: docker push toxchat/bootstrap-node:latest
 | 
				
			||||||
@@ -46,7 +48,7 @@ jobs:
 | 
				
			|||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          context: "{{defaultContext}}:other/bootstrap_daemon/websocket"
 | 
					          context: "{{defaultContext}}:other/bootstrap_daemon/websocket"
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
@@ -67,7 +69,7 @@ jobs:
 | 
				
			|||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          context: "."
 | 
					          context: "."
 | 
				
			||||||
          file: .clusterfuzzlite/Dockerfile
 | 
					          file: .clusterfuzzlite/Dockerfile
 | 
				
			||||||
@@ -88,7 +90,7 @@ jobs:
 | 
				
			|||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: testing/Dockerfile
 | 
					          file: testing/Dockerfile
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
@@ -108,7 +110,7 @@ jobs:
 | 
				
			|||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/emscripten/Dockerfile
 | 
					          file: other/emscripten/Dockerfile
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
@@ -121,21 +123,14 @@ jobs:
 | 
				
			|||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
        uses: docker/setup-buildx-action@v3
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          driver: docker
 | 
					 | 
				
			||||||
      - name: Login to DockerHub
 | 
					      - name: Login to DockerHub
 | 
				
			||||||
        if: ${{ github.event_name == 'push' }}
 | 
					        if: ${{ github.event_name == 'push' }}
 | 
				
			||||||
        uses: docker/login-action@v3
 | 
					        uses: docker/login-action@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build toxchat/c-toxcore:sources
 | 
					 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          file: other/docker/sources/Dockerfile
 | 
					 | 
				
			||||||
          tags: toxchat/c-toxcore:sources
 | 
					 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/docker/esp32/Dockerfile
 | 
					          file: other/docker/esp32/Dockerfile
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
@@ -143,9 +138,15 @@ jobs:
 | 
				
			|||||||
          cache-from: type=registry,ref=toxchat/c-toxcore:esp32
 | 
					          cache-from: type=registry,ref=toxchat/c-toxcore:esp32
 | 
				
			||||||
          cache-to: type=inline
 | 
					          cache-to: type=inline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  docker-win32:
 | 
					  docker-windows-mingw:
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        bits: [32, 64]
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: recursive
 | 
				
			||||||
      - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
        uses: docker/setup-buildx-action@v3
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
      - name: Login to DockerHub
 | 
					      - name: Login to DockerHub
 | 
				
			||||||
@@ -154,39 +155,27 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and store to local Docker daemon
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          context: "{{defaultContext}}:other/docker/windows"
 | 
					          context: other/docker/windows
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          load: true
 | 
				
			||||||
          tags: toxchat/windows:win32
 | 
					          tags: toxchat/windows:win${{ matrix.bits }}
 | 
				
			||||||
          cache-from: type=registry,ref=toxchat/windows:win32
 | 
					          cache-from: type=registry,ref=toxchat/windows:win${{ matrix.bits }}
 | 
				
			||||||
          cache-to: type=inline
 | 
					 | 
				
			||||||
          build-args: |
 | 
					          build-args: |
 | 
				
			||||||
            SUPPORT_ARCH_i686=true
 | 
					            SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
 | 
				
			||||||
            SUPPORT_ARCH_x86_64=false
 | 
					            SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
 | 
				
			||||||
            SUPPORT_TEST=true
 | 
					            SUPPORT_TEST=true
 | 
				
			||||||
 | 
					      - name: Push the stored image to Dockerhub
 | 
				
			||||||
  docker-win64:
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					 | 
				
			||||||
    steps:
 | 
					 | 
				
			||||||
      - name: Set up Docker Buildx
 | 
					 | 
				
			||||||
        uses: docker/setup-buildx-action@v3
 | 
					 | 
				
			||||||
      - name: Login to DockerHub
 | 
					 | 
				
			||||||
        if: ${{ github.event_name == 'push' }}
 | 
					        if: ${{ github.event_name == 'push' }}
 | 
				
			||||||
        uses: docker/login-action@v3
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          context: other/docker/windows
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					 | 
				
			||||||
      - name: Build and push
 | 
					 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          context: "{{defaultContext}}:other/docker/windows"
 | 
					 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
          tags: toxchat/windows:win64
 | 
					          tags: toxchat/windows:win${{ matrix.bits }}
 | 
				
			||||||
          cache-from: type=registry,ref=toxchat/windows:win64
 | 
					 | 
				
			||||||
          cache-to: type=inline
 | 
					 | 
				
			||||||
          build-args: |
 | 
					          build-args: |
 | 
				
			||||||
            SUPPORT_ARCH_i686=false
 | 
					            SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
 | 
				
			||||||
            SUPPORT_ARCH_x86_64=true
 | 
					            SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
 | 
				
			||||||
            SUPPORT_TEST=true
 | 
					            SUPPORT_TEST=true
 | 
				
			||||||
 | 
					      - name: Cross-compile
 | 
				
			||||||
 | 
					        run: .github/scripts/cmake-win${{ matrix.bits }} script
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ jobs:
 | 
				
			|||||||
      - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
        uses: docker/setup-buildx-action@v3
 | 
					        uses: docker/setup-buildx-action@v3
 | 
				
			||||||
      - name: Docker Build
 | 
					      - name: Docker Build
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/docker/alpine-s390x/Dockerfile
 | 
					          file: other/docker/alpine-s390x/Dockerfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,14 +29,14 @@ jobs:
 | 
				
			|||||||
          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
					          username: ${{ secrets.DOCKERHUB_USERNAME }}
 | 
				
			||||||
          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
					          password: ${{ secrets.DOCKERHUB_TOKEN }}
 | 
				
			||||||
      - name: Build toxchat/c-toxcore:sources
 | 
					      - name: Build toxchat/c-toxcore:sources
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/docker/sources/Dockerfile
 | 
					          file: other/docker/sources/sources.Dockerfile
 | 
				
			||||||
          tags: toxchat/c-toxcore:sources
 | 
					          tags: toxchat/c-toxcore:sources
 | 
				
			||||||
      - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
        uses: docker/build-push-action@v4
 | 
					        uses: docker/build-push-action@v5
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          file: other/docker/coverage/Dockerfile
 | 
					          file: other/docker/coverage/coverage.Dockerfile
 | 
				
			||||||
          push: ${{ github.event_name == 'push' }}
 | 
					          push: ${{ github.event_name == 'push' }}
 | 
				
			||||||
          tags: toxchat/c-toxcore:coverage
 | 
					          tags: toxchat/c-toxcore:coverage
 | 
				
			||||||
          cache-from: type=registry,ref=toxchat/c-toxcore:coverage
 | 
					          cache-from: type=registry,ref=toxchat/c-toxcore:coverage
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								external/toxcore/c-toxcore/.restyled.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								external/toxcore/c-toxcore/.restyled.yaml
									
									
									
									
										vendored
									
									
								
							@@ -1,20 +1,25 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
exclude:
 | 
					exclude:
 | 
				
			||||||
  - "**/*.api.h"
 | 
					  # shfmt doesn't support this file.
 | 
				
			||||||
    # shfmt doesn't support this file
 | 
					 | 
				
			||||||
  - "other/analysis/run-clang-tidy"
 | 
					  - "other/analysis/run-clang-tidy"
 | 
				
			||||||
 | 
					  # Generated file.
 | 
				
			||||||
 | 
					  - "CHANGELOG.md"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
restylers:
 | 
					restylers:
 | 
				
			||||||
  - astyle:
 | 
					  - astyle:
 | 
				
			||||||
 | 
					      image: restyled/restyler-astyle:d7967bcb8b622a98524b7df1da1b02652114cf9a
 | 
				
			||||||
      arguments: ["--options=other/astyle/astylerc"]
 | 
					      arguments: ["--options=other/astyle/astylerc"]
 | 
				
			||||||
      include:
 | 
					      include:
 | 
				
			||||||
        - "!**/*.cc"
 | 
					        - "**/*.c"
 | 
				
			||||||
 | 
					        - "**/*.h"
 | 
				
			||||||
  - autopep8
 | 
					  - autopep8
 | 
				
			||||||
  - black
 | 
					  - black
 | 
				
			||||||
  - clang-format:
 | 
					  - clang-format:
 | 
				
			||||||
      image: restyled/restyler-clang-format:13.0.1
 | 
					      image: restyled/restyler-clang-format:v16.0.6
 | 
				
			||||||
      include:
 | 
					      include:
 | 
				
			||||||
        - "**/*.cc"
 | 
					        - "**/*.cc"
 | 
				
			||||||
 | 
					        - "**/*.hh"
 | 
				
			||||||
 | 
					  - prettier-markdown
 | 
				
			||||||
  - prettier-yaml
 | 
					  - prettier-yaml
 | 
				
			||||||
  - reorder-python-imports
 | 
					  - reorder-python-imports
 | 
				
			||||||
  - shellharden
 | 
					  - shellharden
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										266
									
								
								external/toxcore/c-toxcore/CHANGELOG.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										266
									
								
								external/toxcore/c-toxcore/CHANGELOG.md
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,274 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## v0.2.19
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Merged PRs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [#2744](https://github.com/TokTok/c-toxcore/pull/2744) docs: Document that group topic lock is default on.
 | 
				
			||||||
 | 
					- [#2743](https://github.com/TokTok/c-toxcore/pull/2743) docs: Add missing param docs for callbacks.
 | 
				
			||||||
 | 
					- [#2742](https://github.com/TokTok/c-toxcore/pull/2742) chore: Add cmake flag to disable unit tests.
 | 
				
			||||||
 | 
					- [#2741](https://github.com/TokTok/c-toxcore/pull/2741) refactor: Don't expose Tox_System in the public API
 | 
				
			||||||
 | 
					- [#2736](https://github.com/TokTok/c-toxcore/pull/2736) cleanup: A more descriptive error for group invite accept function
 | 
				
			||||||
 | 
					- [#2735](https://github.com/TokTok/c-toxcore/pull/2735) chore: Small API doc fixes
 | 
				
			||||||
 | 
					- [#2732](https://github.com/TokTok/c-toxcore/pull/2732) cleanup: event length naming inconsistencies
 | 
				
			||||||
 | 
					- [#2731](https://github.com/TokTok/c-toxcore/pull/2731) cleanup: align group send err enum order
 | 
				
			||||||
 | 
					- [#2729](https://github.com/TokTok/c-toxcore/pull/2729) cleanup: use typedef for private message ID's in callback
 | 
				
			||||||
 | 
					- [#2728](https://github.com/TokTok/c-toxcore/pull/2728) refactor: Observers/ignored peers can now send and receive custom packets
 | 
				
			||||||
 | 
					- [#2727](https://github.com/TokTok/c-toxcore/pull/2727) feat: add message IDs to private group messages
 | 
				
			||||||
 | 
					- [#2726](https://github.com/TokTok/c-toxcore/pull/2726) refactor: Rename `out` parameters to `out_$something`.
 | 
				
			||||||
 | 
					- [#2718](https://github.com/TokTok/c-toxcore/pull/2718) chore: Use a specific non-broken slimcc version.
 | 
				
			||||||
 | 
					- [#2713](https://github.com/TokTok/c-toxcore/pull/2713) feat: Update and improve the Windows cross-compilation
 | 
				
			||||||
 | 
					- [#2712](https://github.com/TokTok/c-toxcore/pull/2712) chore: Update github actions.
 | 
				
			||||||
 | 
					- [#2710](https://github.com/TokTok/c-toxcore/pull/2710) docs: Update the list of CMake options
 | 
				
			||||||
 | 
					- [#2709](https://github.com/TokTok/c-toxcore/pull/2709) refactor: Remove "mod" and "founder" from group API naming scheme
 | 
				
			||||||
 | 
					- [#2708](https://github.com/TokTok/c-toxcore/pull/2708) docs: add the experimental api build option to INSTALL.md
 | 
				
			||||||
 | 
					- [#2705](https://github.com/TokTok/c-toxcore/pull/2705) refactor: Rename Queries to Query to align with other enums.
 | 
				
			||||||
 | 
					- [#2704](https://github.com/TokTok/c-toxcore/pull/2704) fix: Correct type for conference offline peer numbers.
 | 
				
			||||||
 | 
					- [#2700](https://github.com/TokTok/c-toxcore/pull/2700) test: Add FreeBSD VM action on GitHub.
 | 
				
			||||||
 | 
					- [#2699](https://github.com/TokTok/c-toxcore/pull/2699) test: Add pkgsrc build.
 | 
				
			||||||
 | 
					- [#2698](https://github.com/TokTok/c-toxcore/pull/2698) chore: Only install tox_private.h on request.
 | 
				
			||||||
 | 
					- [#2697](https://github.com/TokTok/c-toxcore/pull/2697) test: Build toxcore on NetBSD (VM).
 | 
				
			||||||
 | 
					- [#2696](https://github.com/TokTok/c-toxcore/pull/2696) fix: save_compatibility_test failing on big-endian systems
 | 
				
			||||||
 | 
					- [#2695](https://github.com/TokTok/c-toxcore/pull/2695) fix: Don't serve files from websockify.
 | 
				
			||||||
 | 
					- [#2689](https://github.com/TokTok/c-toxcore/pull/2689) fix: Correctly pass extended public keys to group moderation code.
 | 
				
			||||||
 | 
					- [#2686](https://github.com/TokTok/c-toxcore/pull/2686) chore: Compile libsodium reference implementation with compcert.
 | 
				
			||||||
 | 
					- [#2685](https://github.com/TokTok/c-toxcore/pull/2685) cleanup: correct a few nullable annotations
 | 
				
			||||||
 | 
					- [#2684](https://github.com/TokTok/c-toxcore/pull/2684) cleanup: Don't use `memcpy` to cast arbitrary `struct`s to `uint8_t[]`.
 | 
				
			||||||
 | 
					- [#2683](https://github.com/TokTok/c-toxcore/pull/2683) fix: Pass array, not array pointer, to `memcmp`.
 | 
				
			||||||
 | 
					- [#2682](https://github.com/TokTok/c-toxcore/pull/2682) cleanup: Never pass `void*` directly to `memcpy`.
 | 
				
			||||||
 | 
					- [#2678](https://github.com/TokTok/c-toxcore/pull/2678) chore: Disable NGC saving by default, enable through Tox_Options.
 | 
				
			||||||
 | 
					- [#2675](https://github.com/TokTok/c-toxcore/pull/2675) cleanup: Replace pointer arithmetic with explicit `&arr[i]`.
 | 
				
			||||||
 | 
					- [#2672](https://github.com/TokTok/c-toxcore/pull/2672) refactor: Use `structs` for extended public/secret keys.
 | 
				
			||||||
 | 
					- [#2671](https://github.com/TokTok/c-toxcore/pull/2671) refactor: Use tox rng to seed the keypair generation.
 | 
				
			||||||
 | 
					- [#2666](https://github.com/TokTok/c-toxcore/pull/2666) cleanup: Small improvements found by PVS Studio.
 | 
				
			||||||
 | 
					- [#2664](https://github.com/TokTok/c-toxcore/pull/2664) docs: Run prettier-markdown on markdown files.
 | 
				
			||||||
 | 
					- [#2662](https://github.com/TokTok/c-toxcore/pull/2662) fix: Correct a few potential null derefs in bootstrap daemon.
 | 
				
			||||||
 | 
					- [#2661](https://github.com/TokTok/c-toxcore/pull/2661) fix: Zero out stack-allocated secret key before return.
 | 
				
			||||||
 | 
					- [#2660](https://github.com/TokTok/c-toxcore/pull/2660) fix: Add missing memunlock of local variable when it goes out of scope.
 | 
				
			||||||
 | 
					- [#2659](https://github.com/TokTok/c-toxcore/pull/2659) cleanup: Simplify custom packet length check in NGC.
 | 
				
			||||||
 | 
					- [#2658](https://github.com/TokTok/c-toxcore/pull/2658) refactor: Make prune_gc_sanctions_list more obviously correct.
 | 
				
			||||||
 | 
					- [#2657](https://github.com/TokTok/c-toxcore/pull/2657) fix: Fix some false positive from PVS Studio.
 | 
				
			||||||
 | 
					- [#2656](https://github.com/TokTok/c-toxcore/pull/2656) docs: Add static analysis tool list to README.
 | 
				
			||||||
 | 
					- [#2655](https://github.com/TokTok/c-toxcore/pull/2655) cleanup: Check that WINXP macro exists before comparing it.
 | 
				
			||||||
 | 
					- [#2652](https://github.com/TokTok/c-toxcore/pull/2652) refactor: Make tox mutex non-recursive.
 | 
				
			||||||
 | 
					- [#2648](https://github.com/TokTok/c-toxcore/pull/2648) docs: Add more documentation to crypto_core.
 | 
				
			||||||
 | 
					- [#2647](https://github.com/TokTok/c-toxcore/pull/2647) docs: Fix up doxyfile.
 | 
				
			||||||
 | 
					- [#2645](https://github.com/TokTok/c-toxcore/pull/2645) refactor: Remove `Tox *` from `tox_dispatch`.
 | 
				
			||||||
 | 
					- [#2644](https://github.com/TokTok/c-toxcore/pull/2644) refactor: Don't rely on tox_dispatch passing tox in tests.
 | 
				
			||||||
 | 
					- [#2643](https://github.com/TokTok/c-toxcore/pull/2643) refactor: Use strong typedef for NGC peer id.
 | 
				
			||||||
 | 
					- [#2642](https://github.com/TokTok/c-toxcore/pull/2642) chore: Use C++ mode for clang-tidy.
 | 
				
			||||||
 | 
					- [#2640](https://github.com/TokTok/c-toxcore/pull/2640) refactor: Use strong `typedef` instead of `struct` for `Socket`.
 | 
				
			||||||
 | 
					- [#2637](https://github.com/TokTok/c-toxcore/pull/2637) chore: Check that both gtest and gmock exist for tests.
 | 
				
			||||||
 | 
					- [#2634](https://github.com/TokTok/c-toxcore/pull/2634) chore: Add some comments to the astyle config.
 | 
				
			||||||
 | 
					- [#2629](https://github.com/TokTok/c-toxcore/pull/2629) chore: Reformat sources with astyle.
 | 
				
			||||||
 | 
					- [#2626](https://github.com/TokTok/c-toxcore/pull/2626) chore: Rename C++ headers to .hh suffixes.
 | 
				
			||||||
 | 
					- [#2624](https://github.com/TokTok/c-toxcore/pull/2624) test: Add slimcc compiler compatibility test.
 | 
				
			||||||
 | 
					- [#2622](https://github.com/TokTok/c-toxcore/pull/2622) cleanup: Add more `const` where possible.
 | 
				
			||||||
 | 
					- [#2621](https://github.com/TokTok/c-toxcore/pull/2621) cleanup: Remove implicit bool conversions.
 | 
				
			||||||
 | 
					- [#2620](https://github.com/TokTok/c-toxcore/pull/2620) chore: Only check the bootstrap daemon checksum on release.
 | 
				
			||||||
 | 
					- [#2617](https://github.com/TokTok/c-toxcore/pull/2617) cleanup: Further `#include` cleanups.
 | 
				
			||||||
 | 
					- [#2614](https://github.com/TokTok/c-toxcore/pull/2614) cleanup: Use Bazel modules to enforce proper `#include` hygiene.
 | 
				
			||||||
 | 
					- [#2612](https://github.com/TokTok/c-toxcore/pull/2612) refactor: Move pack/unpack `IP_Port` from DHT into network module.
 | 
				
			||||||
 | 
					- [#2611](https://github.com/TokTok/c-toxcore/pull/2611) chore: Really fix coverage docker image build.
 | 
				
			||||||
 | 
					- [#2610](https://github.com/TokTok/c-toxcore/pull/2610) chore: Fix post-submit coverage image.
 | 
				
			||||||
 | 
					- [#2609](https://github.com/TokTok/c-toxcore/pull/2609) fix: partially fix a bug that prevented group part messages from sending
 | 
				
			||||||
 | 
					- [#2605](https://github.com/TokTok/c-toxcore/pull/2605) fix: Don't use `memcmp` to compare `IP_Port`s.
 | 
				
			||||||
 | 
					- [#2604](https://github.com/TokTok/c-toxcore/pull/2604) chore: Fix rpm build; add a CI check for it.
 | 
				
			||||||
 | 
					- [#2603](https://github.com/TokTok/c-toxcore/pull/2603) chore: Speed up docker builds a bit by reducing layer count.
 | 
				
			||||||
 | 
					- [#2602](https://github.com/TokTok/c-toxcore/pull/2602) cleanup: Add `const` where possible in auto tests.
 | 
				
			||||||
 | 
					- [#2601](https://github.com/TokTok/c-toxcore/pull/2601) fix: a few off by one errors in group autotests
 | 
				
			||||||
 | 
					- [#2598](https://github.com/TokTok/c-toxcore/pull/2598) refactor: Rename `system_{memory,...}` to `os_{memory,...}`.
 | 
				
			||||||
 | 
					- [#2597](https://github.com/TokTok/c-toxcore/pull/2597) test: Add goblint static analyser.
 | 
				
			||||||
 | 
					- [#2594](https://github.com/TokTok/c-toxcore/pull/2594) cleanup: Use `memzero(x, s)` instead of `memset(x, 0, s)`.
 | 
				
			||||||
 | 
					- [#2593](https://github.com/TokTok/c-toxcore/pull/2593) cleanup: Use explicit 0 instead of `PACKET_ID_PADDING`.
 | 
				
			||||||
 | 
					- [#2592](https://github.com/TokTok/c-toxcore/pull/2592) cleanup: Remove all uses of `SIZEOF_VLA`.
 | 
				
			||||||
 | 
					- [#2591](https://github.com/TokTok/c-toxcore/pull/2591) cleanup: Expand the `Tox_Options` accessor macros.
 | 
				
			||||||
 | 
					- [#2590](https://github.com/TokTok/c-toxcore/pull/2590) test: Add a simple new/delete test for Tox.
 | 
				
			||||||
 | 
					- [#2588](https://github.com/TokTok/c-toxcore/pull/2588) cleanup: Remove plan9 support.
 | 
				
			||||||
 | 
					- [#2587](https://github.com/TokTok/c-toxcore/pull/2587) cleanup: Add comment after every `#endif`.
 | 
				
			||||||
 | 
					- [#2583](https://github.com/TokTok/c-toxcore/pull/2583) test: Fix comment I broke in the events test PR.
 | 
				
			||||||
 | 
					- [#2582](https://github.com/TokTok/c-toxcore/pull/2582) cleanup: Rename group to conference in groupav documentation.
 | 
				
			||||||
 | 
					- [#2581](https://github.com/TokTok/c-toxcore/pull/2581) cleanup: Ensure handler params are named after callback params.
 | 
				
			||||||
 | 
					- [#2580](https://github.com/TokTok/c-toxcore/pull/2580) cleanup: Minor cleanup of event unpack code.
 | 
				
			||||||
 | 
					- [#2578](https://github.com/TokTok/c-toxcore/pull/2578) refactor: Allow NULL pointers for byte arrays in events.
 | 
				
			||||||
 | 
					- [#2577](https://github.com/TokTok/c-toxcore/pull/2577) refactor: Add common msgpack array packer with callback.
 | 
				
			||||||
 | 
					- [#2576](https://github.com/TokTok/c-toxcore/pull/2576) cleanup: make some improvements to group moderation test
 | 
				
			||||||
 | 
					- [#2575](https://github.com/TokTok/c-toxcore/pull/2575) refactor: Pass `this` pointer as first param to s11n callbacks.
 | 
				
			||||||
 | 
					- [#2573](https://github.com/TokTok/c-toxcore/pull/2573) cleanup: skip a do_gc iteration before removing peers marked for deletion
 | 
				
			||||||
 | 
					- [#2572](https://github.com/TokTok/c-toxcore/pull/2572) cleanup: Remove `bin_pack_{new,free}`.
 | 
				
			||||||
 | 
					- [#2568](https://github.com/TokTok/c-toxcore/pull/2568) feat: Add dht_get_nodes_response event to the events system.
 | 
				
			||||||
 | 
					- [#2567](https://github.com/TokTok/c-toxcore/pull/2567) refactor: Use enum-specific pack functions for enum values.
 | 
				
			||||||
 | 
					- [#2566](https://github.com/TokTok/c-toxcore/pull/2566) cleanup: Remove empty test doing nothing.
 | 
				
			||||||
 | 
					- [#2565](https://github.com/TokTok/c-toxcore/pull/2565) refactor: Factor out union pack switch from event packer.
 | 
				
			||||||
 | 
					- [#2564](https://github.com/TokTok/c-toxcore/pull/2564) cleanup: Move the 2-element array pack out of individual events.
 | 
				
			||||||
 | 
					- [#2563](https://github.com/TokTok/c-toxcore/pull/2563) test: Add printf log statement to group_moderation_test.
 | 
				
			||||||
 | 
					- [#2562](https://github.com/TokTok/c-toxcore/pull/2562) chore: add clangd files to .gitignore
 | 
				
			||||||
 | 
					- [#2561](https://github.com/TokTok/c-toxcore/pull/2561) refactor: Move file streaming test to its own file.
 | 
				
			||||||
 | 
					- [#2560](https://github.com/TokTok/c-toxcore/pull/2560) fix(ci): window builds now build in parallel
 | 
				
			||||||
 | 
					- [#2559](https://github.com/TokTok/c-toxcore/pull/2559) refactor: Migrate auto_tests to new events API.
 | 
				
			||||||
 | 
					- [#2557](https://github.com/TokTok/c-toxcore/pull/2557) test: Add C++ classes wrapping system interfaces.
 | 
				
			||||||
 | 
					- [#2555](https://github.com/TokTok/c-toxcore/pull/2555) fix: Remove fatal error for non-erroneous case
 | 
				
			||||||
 | 
					- [#2554](https://github.com/TokTok/c-toxcore/pull/2554) fix: Make all the fuzzers work again, and add a test for protodump.
 | 
				
			||||||
 | 
					- [#2552](https://github.com/TokTok/c-toxcore/pull/2552) fix: Make sure there's enough space for CONSUME1 in fuzzers.
 | 
				
			||||||
 | 
					- [#2551](https://github.com/TokTok/c-toxcore/pull/2551) chore: Move from gcov to llvm source-based coverage.
 | 
				
			||||||
 | 
					- [#2549](https://github.com/TokTok/c-toxcore/pull/2549) fix: issues with packet broadcast error reporting
 | 
				
			||||||
 | 
					- [#2547](https://github.com/TokTok/c-toxcore/pull/2547) test: Add fuzz tests to the coverage run.
 | 
				
			||||||
 | 
					- [#2545](https://github.com/TokTok/c-toxcore/pull/2545) refactor: Use `operator==` for equality tests of `Node_format`.
 | 
				
			||||||
 | 
					- [#2543](https://github.com/TokTok/c-toxcore/pull/2543) refactor(test): Slightly nicer C++ interface to tox Random.
 | 
				
			||||||
 | 
					- [#2542](https://github.com/TokTok/c-toxcore/pull/2542) refactor: packet broadcast functions now return errors
 | 
				
			||||||
 | 
					- [#2541](https://github.com/TokTok/c-toxcore/pull/2541) fix: don't pass garbage data buffer to packet send functions
 | 
				
			||||||
 | 
					- [#2540](https://github.com/TokTok/c-toxcore/pull/2540) cleanup: Make group packet entry creation less error-prone
 | 
				
			||||||
 | 
					- [#2539](https://github.com/TokTok/c-toxcore/pull/2539) refactor: Minor refactoring of get_close_nodes functions.
 | 
				
			||||||
 | 
					- [#2538](https://github.com/TokTok/c-toxcore/pull/2538) refactor: Factor out malloc+memcpy into memdup.
 | 
				
			||||||
 | 
					- [#2536](https://github.com/TokTok/c-toxcore/pull/2536) cleanup: Some more test cleanups, removing overly smart code.
 | 
				
			||||||
 | 
					- [#2531](https://github.com/TokTok/c-toxcore/pull/2531) test: Add more unit tests for `add_to_list`.
 | 
				
			||||||
 | 
					- [#2530](https://github.com/TokTok/c-toxcore/pull/2530) refactor: Assign malloc return to a local variable first.
 | 
				
			||||||
 | 
					- [#2529](https://github.com/TokTok/c-toxcore/pull/2529) test: Add "infer" CI check to github, remove from circle.
 | 
				
			||||||
 | 
					- [#2527](https://github.com/TokTok/c-toxcore/pull/2527) cleanup: Add Toxav alias for ToxAV.
 | 
				
			||||||
 | 
					- [#2526](https://github.com/TokTok/c-toxcore/pull/2526) cleanup: Make Tox_Options a typedef.
 | 
				
			||||||
 | 
					- [#2525](https://github.com/TokTok/c-toxcore/pull/2525) cleanup: Add dynamically derived array sizes to the API.
 | 
				
			||||||
 | 
					- [#2524](https://github.com/TokTok/c-toxcore/pull/2524) cleanup: Add explicit array sizes to toxencryptsave.
 | 
				
			||||||
 | 
					- [#2523](https://github.com/TokTok/c-toxcore/pull/2523) cleanup: Move `tox_get_system` out of the public API.
 | 
				
			||||||
 | 
					- [#2522](https://github.com/TokTok/c-toxcore/pull/2522) cleanup: Make setters take non-const `Tox *`.
 | 
				
			||||||
 | 
					- [#2521](https://github.com/TokTok/c-toxcore/pull/2521) cleanup: Make array params in toxav `[]` instead of `*`.
 | 
				
			||||||
 | 
					- [#2520](https://github.com/TokTok/c-toxcore/pull/2520) cleanup: Mark arrays in the tox API as `[]` instead of `*`.
 | 
				
			||||||
 | 
					- [#2519](https://github.com/TokTok/c-toxcore/pull/2519) refactor: Align group message sending with other send functions.
 | 
				
			||||||
 | 
					- [#2518](https://github.com/TokTok/c-toxcore/pull/2518) cleanup: Add typedefs for public API int identifiers.
 | 
				
			||||||
 | 
					- [#2517](https://github.com/TokTok/c-toxcore/pull/2517) chore: Spellcheck tox-bootstrapd
 | 
				
			||||||
 | 
					- [#2516](https://github.com/TokTok/c-toxcore/pull/2516) chore: Remove settings.yml in favour of hs-github-tools.
 | 
				
			||||||
 | 
					- [#2515](https://github.com/TokTok/c-toxcore/pull/2515) chore: Use GPL license with https.
 | 
				
			||||||
 | 
					- [#2513](https://github.com/TokTok/c-toxcore/pull/2513) chore: Add fetch-sha256 script to update bootstrap node hash.
 | 
				
			||||||
 | 
					- [#2512](https://github.com/TokTok/c-toxcore/pull/2512) cleanup: Move all vptr-to-ptr casts to the beginning of a function.
 | 
				
			||||||
 | 
					- [#2510](https://github.com/TokTok/c-toxcore/pull/2510) cleanup: Use github actions matrix to simplify CI.
 | 
				
			||||||
 | 
					- [#2509](https://github.com/TokTok/c-toxcore/pull/2509) fix: Use QueryPerformanceCounter on windows for monotonic time.
 | 
				
			||||||
 | 
					- [#2508](https://github.com/TokTok/c-toxcore/pull/2508) chore: Add `net_(new|kill)_strerror` to cppcheck's allocators.
 | 
				
			||||||
 | 
					- [#2507](https://github.com/TokTok/c-toxcore/pull/2507) cleanup: Run clang-tidy on headers, as well.
 | 
				
			||||||
 | 
					- [#2506](https://github.com/TokTok/c-toxcore/pull/2506) cleanup: Make TCP connection failures a warning instead of error.
 | 
				
			||||||
 | 
					- [#2505](https://github.com/TokTok/c-toxcore/pull/2505) cleanup: Make all .c files include the headers they need.
 | 
				
			||||||
 | 
					- [#2504](https://github.com/TokTok/c-toxcore/pull/2504) cleanup: Upgrade cppcheck, fix some warnings.
 | 
				
			||||||
 | 
					- [#2503](https://github.com/TokTok/c-toxcore/pull/2503) cleanup: Upgrade to clang-tidy-17 and fix some warnings.
 | 
				
			||||||
 | 
					- [#2502](https://github.com/TokTok/c-toxcore/pull/2502) chore: Use `pkg_search_module` directly in cmake.
 | 
				
			||||||
 | 
					- [#2501](https://github.com/TokTok/c-toxcore/pull/2501) chore: Add `IMPORTED_TARGET` to pkg-config packages.
 | 
				
			||||||
 | 
					- [#2499](https://github.com/TokTok/c-toxcore/pull/2499) cleanup: Use target_link_libraries directly in cmake.
 | 
				
			||||||
 | 
					- [#2498](https://github.com/TokTok/c-toxcore/pull/2498) chore: Simplify msvc build using vcpkg.
 | 
				
			||||||
 | 
					- [#2497](https://github.com/TokTok/c-toxcore/pull/2497) cleanup: Remove NaCl support.
 | 
				
			||||||
 | 
					- [#2494](https://github.com/TokTok/c-toxcore/pull/2494) fix: unpack enum function names in event impl generator
 | 
				
			||||||
 | 
					- [#2493](https://github.com/TokTok/c-toxcore/pull/2493) chore: Disable targets for cross-compilation.
 | 
				
			||||||
 | 
					- [#2491](https://github.com/TokTok/c-toxcore/pull/2491) chore: Build a docker image with coverage info in it.
 | 
				
			||||||
 | 
					- [#2490](https://github.com/TokTok/c-toxcore/pull/2490) cleanup: Some portability/warning fixes for Windows builds.
 | 
				
			||||||
 | 
					- [#2488](https://github.com/TokTok/c-toxcore/pull/2488) fix: Correct a use-after-free and fix some memory leaks.
 | 
				
			||||||
 | 
					- [#2487](https://github.com/TokTok/c-toxcore/pull/2487) refactor: Change all enum-like `#define` sequences into enums.
 | 
				
			||||||
 | 
					- [#2486](https://github.com/TokTok/c-toxcore/pull/2486) refactor: Change the `TCP_PACKET_*` defines into an enum.
 | 
				
			||||||
 | 
					- [#2485](https://github.com/TokTok/c-toxcore/pull/2485) refactor: event generation tool for reorder pr
 | 
				
			||||||
 | 
					- [#2484](https://github.com/TokTok/c-toxcore/pull/2484) chore: Fix make_single_file to support core-only.
 | 
				
			||||||
 | 
					- [#2481](https://github.com/TokTok/c-toxcore/pull/2481) chore: Update github actions `uses`.
 | 
				
			||||||
 | 
					- [#2480](https://github.com/TokTok/c-toxcore/pull/2480) feat: add ngc related unpack functions
 | 
				
			||||||
 | 
					- [#2479](https://github.com/TokTok/c-toxcore/pull/2479) feat: Add `to_string` functions for all public enums.
 | 
				
			||||||
 | 
					- [#2477](https://github.com/TokTok/c-toxcore/pull/2477) test: add real timeout test
 | 
				
			||||||
 | 
					- [#2476](https://github.com/TokTok/c-toxcore/pull/2476) chore: Move s390x build to post-merge.
 | 
				
			||||||
 | 
					- [#2475](https://github.com/TokTok/c-toxcore/pull/2475) refactor: Give `enum-from-int` functions the ability to report errors.
 | 
				
			||||||
 | 
					- [#2474](https://github.com/TokTok/c-toxcore/pull/2474) cleanup: Remove test net support.
 | 
				
			||||||
 | 
					- [#2472](https://github.com/TokTok/c-toxcore/pull/2472) feat: Enable ubsan on bootstrap nodes.
 | 
				
			||||||
 | 
					- [#2470](https://github.com/TokTok/c-toxcore/pull/2470) test: Add check-c run to bazel build.
 | 
				
			||||||
 | 
					- [#2468](https://github.com/TokTok/c-toxcore/pull/2468) fix(test): tests use ipv6 by default, even with USE_IPV6 set to 0
 | 
				
			||||||
 | 
					- [#2466](https://github.com/TokTok/c-toxcore/pull/2466) cleanup: Make group saving/loading more forgiving with data errors
 | 
				
			||||||
 | 
					- [#2465](https://github.com/TokTok/c-toxcore/pull/2465) refactor: replace memset with a loop
 | 
				
			||||||
 | 
					- [#2459](https://github.com/TokTok/c-toxcore/pull/2459) fix: Enable debug flag for ubsan.
 | 
				
			||||||
 | 
					- [#2458](https://github.com/TokTok/c-toxcore/pull/2458) fix: also Install header for private/experimental API functions with autotools
 | 
				
			||||||
 | 
					- [#2456](https://github.com/TokTok/c-toxcore/pull/2456) docs: Remove defunct IRC channel from README.md
 | 
				
			||||||
 | 
					- [#2454](https://github.com/TokTok/c-toxcore/pull/2454) fix: memory leaks
 | 
				
			||||||
 | 
					- [#2453](https://github.com/TokTok/c-toxcore/pull/2453) refactor: Install header for private/experimental API functions
 | 
				
			||||||
 | 
					- [#2452](https://github.com/TokTok/c-toxcore/pull/2452) refactor: replace DEFAULT_TCP_RELAY_PORTS_COUNT with a compile-time calculation
 | 
				
			||||||
 | 
					- [#2451](https://github.com/TokTok/c-toxcore/pull/2451) cleanup: clarify disabling of static assert checks
 | 
				
			||||||
 | 
					- [#2449](https://github.com/TokTok/c-toxcore/pull/2449) cleanup: replace tabs with spaces
 | 
				
			||||||
 | 
					- [#2448](https://github.com/TokTok/c-toxcore/pull/2448) feat: group connection queries now return our own connection type
 | 
				
			||||||
 | 
					- [#2447](https://github.com/TokTok/c-toxcore/pull/2447) fix: Docker tox-bootstrapd hash update failing when using BuildKit
 | 
				
			||||||
 | 
					- [#2446](https://github.com/TokTok/c-toxcore/pull/2446) feat: Add groupchat API function that returns an IP address string for a peer
 | 
				
			||||||
 | 
					- [#2442](https://github.com/TokTok/c-toxcore/pull/2442) perf: Slightly reduce bandwidth usage when there are few nodes.
 | 
				
			||||||
 | 
					- [#2439](https://github.com/TokTok/c-toxcore/pull/2439) test: Make esp32 build actually try to instantiate tox.
 | 
				
			||||||
 | 
					- [#2438](https://github.com/TokTok/c-toxcore/pull/2438) cleanup: Remove explicit layering_check feature.
 | 
				
			||||||
 | 
					- [#2437](https://github.com/TokTok/c-toxcore/pull/2437) chore: Upgrade sonar-scan jvm to java 17.
 | 
				
			||||||
 | 
					- [#2436](https://github.com/TokTok/c-toxcore/pull/2436) fix: Add missing `htons` call when adding configured TCP relay.
 | 
				
			||||||
 | 
					- [#2434](https://github.com/TokTok/c-toxcore/pull/2434) chore: Cancel old PR builds on docker and sonar-scan workflows.
 | 
				
			||||||
 | 
					- [#2432](https://github.com/TokTok/c-toxcore/pull/2432) chore: Use C99 on MSVC instead of C11.
 | 
				
			||||||
 | 
					- [#2430](https://github.com/TokTok/c-toxcore/pull/2430) chore: Retry freebsd tests 2 times.
 | 
				
			||||||
 | 
					- [#2429](https://github.com/TokTok/c-toxcore/pull/2429) test: Add an s390x build (on alpine) for CI.
 | 
				
			||||||
 | 
					- [#2428](https://github.com/TokTok/c-toxcore/pull/2428) chore: Add a compcert docker run script.
 | 
				
			||||||
 | 
					- [#2427](https://github.com/TokTok/c-toxcore/pull/2427) cleanup: Use tcc docker image for CI.
 | 
				
			||||||
 | 
					- [#2424](https://github.com/TokTok/c-toxcore/pull/2424) fix: Fix memory leak in the error path of loading savedata.
 | 
				
			||||||
 | 
					- [#2420](https://github.com/TokTok/c-toxcore/pull/2420) refactor: Use Bin_Pack for packing Node_format.
 | 
				
			||||||
 | 
					- [#2416](https://github.com/TokTok/c-toxcore/pull/2416) chore: Add more logging to loading conferences from savedata.
 | 
				
			||||||
 | 
					- [#2415](https://github.com/TokTok/c-toxcore/pull/2415) refactor: Add a `bin_unpack_bin_max` for max-length arrays.
 | 
				
			||||||
 | 
					- [#2414](https://github.com/TokTok/c-toxcore/pull/2414) fix: inversed return values
 | 
				
			||||||
 | 
					- [#2413](https://github.com/TokTok/c-toxcore/pull/2413) cleanup: Fix GCC compatibility.
 | 
				
			||||||
 | 
					- [#2408](https://github.com/TokTok/c-toxcore/pull/2408) fix: Ensure we have allocators available for the error paths.
 | 
				
			||||||
 | 
					- [#2407](https://github.com/TokTok/c-toxcore/pull/2407) cleanup: Remove redundant `-DSODIUM_EXPORT` from definitions.
 | 
				
			||||||
 | 
					- [#2406](https://github.com/TokTok/c-toxcore/pull/2406) cleanup: Fix a few more clang-tidy warnings.
 | 
				
			||||||
 | 
					- [#2405](https://github.com/TokTok/c-toxcore/pull/2405) cleanup: Fix a few more clang-tidy warnings.
 | 
				
			||||||
 | 
					- [#2404](https://github.com/TokTok/c-toxcore/pull/2404) cleanup: Enforce stricter identifier naming using clang-tidy.
 | 
				
			||||||
 | 
					- [#2396](https://github.com/TokTok/c-toxcore/pull/2396) chore: Add devcontainer setup for codespaces.
 | 
				
			||||||
 | 
					- [#2393](https://github.com/TokTok/c-toxcore/pull/2393) refactor: Add `mem` module to allow tests to override allocators.
 | 
				
			||||||
 | 
					- [#2392](https://github.com/TokTok/c-toxcore/pull/2392) refactor: Make event dispatch ordered by receive time.
 | 
				
			||||||
 | 
					- [#2391](https://github.com/TokTok/c-toxcore/pull/2391) docs: Fix doxygen config and remove some redundant comments.
 | 
				
			||||||
 | 
					- [#2390](https://github.com/TokTok/c-toxcore/pull/2390) chore: Fix the Android CI job
 | 
				
			||||||
 | 
					- [#2389](https://github.com/TokTok/c-toxcore/pull/2389) fix: Add missing `#include <array>`.
 | 
				
			||||||
 | 
					- [#2388](https://github.com/TokTok/c-toxcore/pull/2388) chore: Add missing module dependencies.
 | 
				
			||||||
 | 
					- [#2384](https://github.com/TokTok/c-toxcore/pull/2384) feat: increase NGC lossy custom packet size
 | 
				
			||||||
 | 
					- [#2383](https://github.com/TokTok/c-toxcore/pull/2383) fix: add missing ngc constants getter declarations and definitions
 | 
				
			||||||
 | 
					- [#2381](https://github.com/TokTok/c-toxcore/pull/2381) fix: incorrect documentation
 | 
				
			||||||
 | 
					- [#2380](https://github.com/TokTok/c-toxcore/pull/2380) feat: allow for larger incoming NGC packets
 | 
				
			||||||
 | 
					- [#2371](https://github.com/TokTok/c-toxcore/pull/2371) docs: fix group_peer_exit_cb
 | 
				
			||||||
 | 
					- [#2370](https://github.com/TokTok/c-toxcore/pull/2370) fix: behaviour of group api function
 | 
				
			||||||
 | 
					- [#2369](https://github.com/TokTok/c-toxcore/pull/2369) fix: flaky tcp test
 | 
				
			||||||
 | 
					- [#2367](https://github.com/TokTok/c-toxcore/pull/2367) fix: fuzz support for TCP server
 | 
				
			||||||
 | 
					- [#2364](https://github.com/TokTok/c-toxcore/pull/2364) fix: potential endless loop under extremely high load
 | 
				
			||||||
 | 
					- [#2362](https://github.com/TokTok/c-toxcore/pull/2362) test: enable tcp relay for bootstrap fuzzing
 | 
				
			||||||
 | 
					- [#2361](https://github.com/TokTok/c-toxcore/pull/2361) fix: resolve_bootstrap_node() not checking net_getipport() returned count correctly
 | 
				
			||||||
 | 
					- [#2357](https://github.com/TokTok/c-toxcore/pull/2357) feat: get the number of close dht nodes with announce/store support
 | 
				
			||||||
 | 
					- [#2355](https://github.com/TokTok/c-toxcore/pull/2355) fix: group custom packet size limits
 | 
				
			||||||
 | 
					- [#2354](https://github.com/TokTok/c-toxcore/pull/2354) fix: DHTBootstrap should always respond to version packets with toxcore version
 | 
				
			||||||
 | 
					- [#2351](https://github.com/TokTok/c-toxcore/pull/2351) fix: Increase max group message length by four bytes
 | 
				
			||||||
 | 
					- [#2348](https://github.com/TokTok/c-toxcore/pull/2348) refactor: Make some improvements to how often/when we announce a group
 | 
				
			||||||
 | 
					- [#2341](https://github.com/TokTok/c-toxcore/pull/2341) fix: #1144 by forcing misc_tools to be a static lib
 | 
				
			||||||
 | 
					- [#2340](https://github.com/TokTok/c-toxcore/pull/2340) fix: missing net to host conversion of port in logging in group_chat.c
 | 
				
			||||||
 | 
					- [#2339](https://github.com/TokTok/c-toxcore/pull/2339) fix: missing net to host conversion of port in logging
 | 
				
			||||||
 | 
					- [#2338](https://github.com/TokTok/c-toxcore/pull/2338) fix: bug causing friend group invites to sometimes fail & improve logging
 | 
				
			||||||
 | 
					- [#2333](https://github.com/TokTok/c-toxcore/pull/2333) docs: Update README for bootstrap node docker
 | 
				
			||||||
 | 
					- [#2329](https://github.com/TokTok/c-toxcore/pull/2329) refactor: extract each case in handle packet in messenger
 | 
				
			||||||
 | 
					- [#2327](https://github.com/TokTok/c-toxcore/pull/2327) fix: unlock correct dht_friend
 | 
				
			||||||
 | 
					- [#2325](https://github.com/TokTok/c-toxcore/pull/2325) fix: Remove cmake cache files after copying to container build directory
 | 
				
			||||||
 | 
					- [#2323](https://github.com/TokTok/c-toxcore/pull/2323) docs: Update README.md to include cmp submodule info
 | 
				
			||||||
 | 
					- [#2318](https://github.com/TokTok/c-toxcore/pull/2318) chore: disable warning about pre C99 code
 | 
				
			||||||
 | 
					- [#2317](https://github.com/TokTok/c-toxcore/pull/2317) Refactor: Extract shared key cache into separate file
 | 
				
			||||||
 | 
					- [#2311](https://github.com/TokTok/c-toxcore/pull/2311) cleanup: make it more clear that assert and uint32_t increment both only exist if NDEBUG is not defined
 | 
				
			||||||
 | 
					- [#2291](https://github.com/TokTok/c-toxcore/pull/2291) test: Add a protocol dump test to generate initial fuzzer input.
 | 
				
			||||||
 | 
					- [#2271](https://github.com/TokTok/c-toxcore/pull/2271) chore: Migrate from Appveyor to Azure Pipelines
 | 
				
			||||||
 | 
					- [#2269](https://github.com/TokTok/c-toxcore/pull/2269) feat: Merge the remainder of the new groupchats implementation
 | 
				
			||||||
 | 
					- [#2203](https://github.com/TokTok/c-toxcore/pull/2203) refactor: Store time in Mono_Time in milliseconds.
 | 
				
			||||||
 | 
					- [#1944](https://github.com/TokTok/c-toxcore/pull/1944) chore: tox_new() should return null when savedata loading fails
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Closed issues:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [#2739](https://github.com/TokTok/c-toxcore/issues/2739) Tox_Options.operating_system is not clear about it being an experimental option
 | 
				
			||||||
 | 
					- [#2734](https://github.com/TokTok/c-toxcore/issues/2734) error compiling on fedora
 | 
				
			||||||
 | 
					- [#2649](https://github.com/TokTok/c-toxcore/issues/2649) create_extended_keypair should use Random and be made deterministic for fuzzing
 | 
				
			||||||
 | 
					- [#2358](https://github.com/TokTok/c-toxcore/issues/2358) resolve_bootstrap_node assert hit
 | 
				
			||||||
 | 
					- [#2352](https://github.com/TokTok/c-toxcore/issues/2352) SEGV after infinite loop retrying proxy_socks5_read_connection_response
 | 
				
			||||||
 | 
					- [#2335](https://github.com/TokTok/c-toxcore/issues/2335) ipv6 disabled on kernel cmdline disrupts Tox = most tests fail
 | 
				
			||||||
 | 
					- [#2303](https://github.com/TokTok/c-toxcore/issues/2303) Add new group chats events to tox_events and tox_dispatch modules.
 | 
				
			||||||
 | 
					- [#2302](https://github.com/TokTok/c-toxcore/issues/2302) Run strong fuzz tests against NGC
 | 
				
			||||||
 | 
					- [#2301](https://github.com/TokTok/c-toxcore/issues/2301) Implement NGC save/load in hs-toxcore and run round-trip tests against c-toxcore
 | 
				
			||||||
 | 
					- [#2192](https://github.com/TokTok/c-toxcore/issues/2192) Provide official signed release tarballs
 | 
				
			||||||
 | 
					- [#2118](https://github.com/TokTok/c-toxcore/issues/2118) Add a private "get mono_time" API to `tox_private.h` and use it in auto_tests.
 | 
				
			||||||
 | 
					- [#2029](https://github.com/TokTok/c-toxcore/issues/2029) Migrate all auto tests to the events API.
 | 
				
			||||||
 | 
					- [#2014](https://github.com/TokTok/c-toxcore/issues/2014) Add sodium autotools CI build
 | 
				
			||||||
 | 
					- [#1144](https://github.com/TokTok/c-toxcore/issues/1144) DHT_bootstrap should not link against misc_tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## v0.2.18
 | 
					## v0.2.18
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Merged PRs:
 | 
					### Merged PRs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [#2300](https://github.com/TokTok/c-toxcore/pull/2300) chore: Release 0.2.18
 | 
				
			||||||
- [#2299](https://github.com/TokTok/c-toxcore/pull/2299) fix: remove the assert because buffer can be larger than UINT16_MAX.
 | 
					- [#2299](https://github.com/TokTok/c-toxcore/pull/2299) fix: remove the assert because buffer can be larger than UINT16_MAX.
 | 
				
			||||||
- [#2297](https://github.com/TokTok/c-toxcore/pull/2297) cleanup: remove unused field last_seen from Onion_Friend
 | 
					- [#2297](https://github.com/TokTok/c-toxcore/pull/2297) cleanup: remove unused field last_seen from Onion_Friend
 | 
				
			||||||
- [#2289](https://github.com/TokTok/c-toxcore/pull/2289) test: Add a Null_System used in toxsave_harness.
 | 
					- [#2289](https://github.com/TokTok/c-toxcore/pull/2289) test: Add a Null_System used in toxsave_harness.
 | 
				
			||||||
@@ -107,6 +372,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Closed issues:
 | 
					### Closed issues:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [#2298](https://github.com/TokTok/c-toxcore/issues/2298) assert makes incorrect assumption
 | 
				
			||||||
- [#2256](https://github.com/TokTok/c-toxcore/issues/2256) New Defects reported by Coverity Scan for TokTok/c-toxcore
 | 
					- [#2256](https://github.com/TokTok/c-toxcore/issues/2256) New Defects reported by Coverity Scan for TokTok/c-toxcore
 | 
				
			||||||
- [#2109](https://github.com/TokTok/c-toxcore/issues/2109) Assimilate `messenger_test.c`: replace with public API test
 | 
					- [#2109](https://github.com/TokTok/c-toxcore/issues/2109) Assimilate `messenger_test.c`: replace with public API test
 | 
				
			||||||
- [#2012](https://github.com/TokTok/c-toxcore/issues/2012) Support building a DLL on Windows
 | 
					- [#2012](https://github.com/TokTok/c-toxcore/issues/2012) Support building a DLL on Windows
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								external/toxcore/c-toxcore/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								external/toxcore/c-toxcore/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							@@ -44,7 +44,7 @@ set_source_files_properties(
 | 
				
			|||||||
# versions in a synchronised way.
 | 
					# versions in a synchronised way.
 | 
				
			||||||
set(PROJECT_VERSION_MAJOR "0")
 | 
					set(PROJECT_VERSION_MAJOR "0")
 | 
				
			||||||
set(PROJECT_VERSION_MINOR "2")
 | 
					set(PROJECT_VERSION_MINOR "2")
 | 
				
			||||||
set(PROJECT_VERSION_PATCH "18")
 | 
					set(PROJECT_VERSION_PATCH "19")
 | 
				
			||||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
 | 
					set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# set .so library version / following libtool scheme
 | 
					# set .so library version / following libtool scheme
 | 
				
			||||||
@@ -136,18 +136,22 @@ if(MIN_LOGGER_LEVEL)
 | 
				
			|||||||
  endif()
 | 
					  endif()
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(EXPERIMENTAL_API "Install experimental header file with unstable API" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_IPV6 "Use IPv6 in tests" ON)
 | 
					option(USE_IPV6 "Use IPv6 in tests" ON)
 | 
				
			||||||
if(NOT USE_IPV6)
 | 
					if(NOT USE_IPV6)
 | 
				
			||||||
  add_definitions(-DUSE_IPV6=0)
 | 
					  add_definitions(-DUSE_IPV6=0)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(BUILD_MISC_TESTS "Build additional tests and utilities" OFF)
 | 
					option(BUILD_MISC_TESTS "Build additional tests" OFF)
 | 
				
			||||||
option(BUILD_FUN_UTILS "Build additional just for fun utilities" OFF)
 | 
					option(BUILD_FUN_UTILS "Build additional just for fun utilities" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(UNITTEST "Enable unit tests (disable if you don't have a working gmock or gtest)" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(AUTOTEST "Enable autotests (mainly for CI)" OFF)
 | 
					option(AUTOTEST "Enable autotests (mainly for CI)" OFF)
 | 
				
			||||||
if(AUTOTEST)
 | 
					if(AUTOTEST)
 | 
				
			||||||
  option(NON_HERMETIC_TESTS "Whether to build and run tests that depend on an internet connection" OFF)
 | 
					  option(NON_HERMETIC_TESTS "Whether to build and run tests that depend on an internet connection" OFF)
 | 
				
			||||||
  option(PROXY_TEST "Enable proxy test (needs HTTP/SOCKS5 proxy on port 8080/8081)" OFF)
 | 
					  option(PROXY_TEST "Enable proxy test (requires other/proxy/proxy_server.go to be running)" OFF)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(BUILD_TOXAV "Whether to build the tox AV library" ON)
 | 
					option(BUILD_TOXAV "Whether to build the tox AV library" ON)
 | 
				
			||||||
@@ -223,6 +227,8 @@ set(toxcore_SOURCES
 | 
				
			|||||||
  toxcore/ccompat.h
 | 
					  toxcore/ccompat.h
 | 
				
			||||||
  toxcore/crypto_core.c
 | 
					  toxcore/crypto_core.c
 | 
				
			||||||
  toxcore/crypto_core.h
 | 
					  toxcore/crypto_core.h
 | 
				
			||||||
 | 
					  toxcore/crypto_core_pack.c
 | 
				
			||||||
 | 
					  toxcore/crypto_core_pack.h
 | 
				
			||||||
  toxcore/DHT.c
 | 
					  toxcore/DHT.c
 | 
				
			||||||
  toxcore/DHT.h
 | 
					  toxcore/DHT.h
 | 
				
			||||||
  toxcore/events/conference_connected.c
 | 
					  toxcore/events/conference_connected.c
 | 
				
			||||||
@@ -231,6 +237,7 @@ set(toxcore_SOURCES
 | 
				
			|||||||
  toxcore/events/conference_peer_list_changed.c
 | 
					  toxcore/events/conference_peer_list_changed.c
 | 
				
			||||||
  toxcore/events/conference_peer_name.c
 | 
					  toxcore/events/conference_peer_name.c
 | 
				
			||||||
  toxcore/events/conference_title.c
 | 
					  toxcore/events/conference_title.c
 | 
				
			||||||
 | 
					  toxcore/events/dht_get_nodes_response.c
 | 
				
			||||||
  toxcore/events/events_alloc.c
 | 
					  toxcore/events/events_alloc.c
 | 
				
			||||||
  toxcore/events/events_alloc.h
 | 
					  toxcore/events/events_alloc.h
 | 
				
			||||||
  toxcore/events/file_chunk_request.c
 | 
					  toxcore/events/file_chunk_request.c
 | 
				
			||||||
@@ -356,8 +363,11 @@ set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} libsodium)
 | 
				
			|||||||
set(toxcore_API_HEADERS
 | 
					set(toxcore_API_HEADERS
 | 
				
			||||||
  ${toxcore_SOURCE_DIR}/toxcore/tox.h^tox
 | 
					  ${toxcore_SOURCE_DIR}/toxcore/tox.h^tox
 | 
				
			||||||
  ${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox
 | 
					  ${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox
 | 
				
			||||||
  ${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox
 | 
					  ${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox)
 | 
				
			||||||
 | 
					if(EXPERIMENTAL_API)
 | 
				
			||||||
 | 
					  set(toxcore_API_HEADERS ${toxcore_API_HEADERS}
 | 
				
			||||||
    ${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox)
 | 
					    ${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################################################################
 | 
					################################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@@ -446,7 +456,7 @@ elseif(TARGET Threads::Threads)
 | 
				
			|||||||
  set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
 | 
					  set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
if(WIN32)
 | 
					if(WIN32)
 | 
				
			||||||
  set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi wsock32 ws2_32)
 | 
					  set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi ws2_32)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################################################################
 | 
					################################################################################
 | 
				
			||||||
@@ -526,7 +536,7 @@ endfunction()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# The actual unit tests follow.
 | 
					# The actual unit tests follow.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
if(GTEST_FOUND)
 | 
					if(UNITTEST AND TARGET GTest::gtest AND TARGET GTest::gmock)
 | 
				
			||||||
  unit_test(toxav ring_buffer)
 | 
					  unit_test(toxav ring_buffer)
 | 
				
			||||||
  unit_test(toxav rtp)
 | 
					  unit_test(toxav rtp)
 | 
				
			||||||
  unit_test(toxcore DHT)
 | 
					  unit_test(toxcore DHT)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										274
									
								
								external/toxcore/c-toxcore/INSTALL.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										274
									
								
								external/toxcore/c-toxcore/INSTALL.md
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,8 @@
 | 
				
			|||||||
# Installation instructions
 | 
					# Installation instructions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These instructions will guide you through the process of building and installing the toxcore library and its components, as well as getting already pre-built binaries.
 | 
					These instructions will guide you through the process of building and installing
 | 
				
			||||||
 | 
					the toxcore library and its components, as well as getting already pre-built
 | 
				
			||||||
 | 
					binaries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Table of contents
 | 
					## Table of contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,10 +32,15 @@ These instructions will guide you through the process of building and installing
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#### Main
 | 
					#### Main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This repository, although called `toxcore`, in fact contains several libraries besides `toxcore` which complement it, as well as several executables. However, note that although these are separate libraries, at the moment, when building the libraries, they are all merged into a single `toxcore` library. Here is the full list of the main components that can be built using the CMake, their dependencies and descriptions.
 | 
					This repository, although called `toxcore`, in fact contains several libraries
 | 
				
			||||||
 | 
					besides `toxcore` which complement it, as well as several executables. However,
 | 
				
			||||||
 | 
					note that although these are separate libraries, at the moment, when building
 | 
				
			||||||
 | 
					the libraries, they are all merged into a single `toxcore` library. Here is the
 | 
				
			||||||
 | 
					full list of the main components that can be built using the CMake, their
 | 
				
			||||||
 | 
					dependencies and descriptions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name             | Type       | Dependencies                       | Platform       | Description                                                                                                                |
 | 
					| Name             | Type       | Dependencies                       | Platform       | Description                                                                                                                |
 | 
				
			||||||
|------------------|------------|------------------------------------|----------------|----------------------------------------------------------------------------|
 | 
					| ---------------- | ---------- | ---------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
 | 
				
			||||||
| `toxcore`        | Library    | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality.                                                            |
 | 
					| `toxcore`        | Library    | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality.                                                            |
 | 
				
			||||||
| `toxav`          | Library    | libtoxcore, libopus, libvpx        | Cross-platform | Provides audio/video functionality.                                                                                        |
 | 
					| `toxav`          | Library    | libtoxcore, libopus, libvpx        | Cross-platform | Provides audio/video functionality.                                                                                        |
 | 
				
			||||||
| `toxencryptsave` | Library    | libtoxcore, libsodium              | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data.                                                 |
 | 
					| `toxencryptsave` | Library    | libtoxcore, libsodium              | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data.                                                 |
 | 
				
			||||||
@@ -43,24 +50,26 @@ This repository, although called `toxcore`, in fact contains several libraries b
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#### Secondary
 | 
					#### Secondary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There are some programs that are not built by default which you might find interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them.
 | 
					There are some programs that are not built by default which you might find
 | 
				
			||||||
 | 
					interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Vanity key generators
 | 
					##### Vanity key generators
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Can be used to generate vanity Tox Ids or DHT bootstrap node public keys.
 | 
					Can be used to generate vanity Tox Ids or DHT bootstrap node public keys.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name             | Type       | Dependencies      | Platform       | Description                                                                                                                                                                   |
 | 
					| Name             | Type       | Dependencies      | Platform       | Description                                                                                                                                                                   |
 | 
				
			||||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 | 
					| ---------------- | ---------- | ----------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | 
				
			||||||
| `cracker`        | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded.                                     |
 | 
					| `cracker`        | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded.                                     |
 | 
				
			||||||
| `cracker_simple` | Executable | libsodium         | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded.                                    |
 | 
					| `cracker_simple` | Executable | libsodium         | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded.                                    |
 | 
				
			||||||
| `strkey`         | Executable | libsodium         | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. |
 | 
					| `strkey`         | Executable | libsodium         | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Key file generators
 | 
					##### Key file generators
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Useful for generating Tox profiles from the output of the vanity key generators, as well as generating random Tox profiles.
 | 
					Useful for generating Tox profiles from the output of the vanity key generators,
 | 
				
			||||||
 | 
					as well as generating random Tox profiles.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name                      | Type       | Dependencies          | Platform       | Description                                                                                                                                                                     |
 | 
					| Name                      | Type       | Dependencies          | Platform       | Description                                                                                                                                                                     |
 | 
				
			||||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 | 
					| ------------------------- | ---------- | --------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | 
				
			||||||
| `make-funny-savefile`     | Script     | python                | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair.                                                                                                        |
 | 
					| `make-funny-savefile`     | Script     | python                | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair.                                                                                                        |
 | 
				
			||||||
| `create_bootstrap_keys`   | Executable | libsodium             | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair.                                                                                         |
 | 
					| `create_bootstrap_keys`   | Executable | libsodium             | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair.                                                                                         |
 | 
				
			||||||
| `create_minimal_savedata` | Executable | libsodium             | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information.          |
 | 
					| `create_minimal_savedata` | Executable | libsodium             | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information.          |
 | 
				
			||||||
@@ -70,7 +79,7 @@ Useful for generating Tox profiles from the output of the vanity key generators,
 | 
				
			|||||||
##### Other
 | 
					##### Other
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name                  | Type       | Dependencies | Platform       | Description                                                                                                                               |
 | 
					| Name                  | Type       | Dependencies | Platform       | Description                                                                                                                               |
 | 
				
			||||||
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 | 
					| --------------------- | ---------- | ------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
 | 
				
			||||||
| `bootstrap_node_info` | Script     | python3      | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. |
 | 
					| `bootstrap_node_info` | Script     | python3      | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. |
 | 
				
			||||||
| `sign`                | Executable | libsodium    | Cross-platform | Signs a file with a ed25519 key.                                                                                                          |
 | 
					| `sign`                | Executable | libsodium    | Cross-platform | Signs a file with a ed25519 key.                                                                                                          |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -80,56 +89,79 @@ Useful for generating Tox profiles from the output of the vanity key generators,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#### Library dependencies
 | 
					#### Library dependencies
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Library dependencies are listed in the [components](#components) table. The dependencies need to be satisfied for the components to be built. Note that if you don't have a dependency for some component, e.g. you don't have `libopus` installed required for building `toxav` component, building of that component is silently disabled.
 | 
					Library dependencies are listed in the [components](#components) table. The
 | 
				
			||||||
 | 
					dependencies need to be satisfied for the components to be built. Note that if
 | 
				
			||||||
 | 
					you don't have a dependency for some component, e.g. you don't have `libopus`
 | 
				
			||||||
 | 
					installed required for building `toxav` component, building of that component is
 | 
				
			||||||
 | 
					silently disabled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Be advised that due to the addition of `cmp` as a submodule, you now also need
 | 
				
			||||||
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the addition of `--recurse-submodules` or by running `git submodule update --init` in the root directory of the repo.
 | 
					to initialize the git submodules required by toxcore. This can be done by
 | 
				
			||||||
 | 
					cloning the repo with the addition of `--recurse-submodules` or by running
 | 
				
			||||||
 | 
					`git submodule update --init` in the root directory of the repo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Compiler requirements
 | 
					#### Compiler requirements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The supported compilers are GCC, Clang and MinGW.
 | 
					The supported compilers are GCC, Clang and MinGW.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In theory, any compiler that fully supports C99 and accepts GCC flags should work.
 | 
					In theory, any compiler that fully supports C99 and accepts GCC flags should
 | 
				
			||||||
 | 
					work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There is a partial and experimental support of Microsoft Visual C++ compiler. We welcome any patches that help improve it.
 | 
					There is a partial and experimental support of Microsoft Visual C++ compiler. We
 | 
				
			||||||
 | 
					welcome any patches that help improve it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You should have a C99 compatible compiler in order to build the main components. The secondary components might require the compiler to support GNU extensions.
 | 
					You should have a C99 compatible compiler in order to build the main components.
 | 
				
			||||||
 | 
					The secondary components might require the compiler to support GNU extensions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Build system requirements
 | 
					#### Build system requirements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To build the main components you need to have CMake of at least 2.8.6 version installed. You also need to have pkg-config installed, the build system uses it to find dependency libraries.
 | 
					To build the main components you need to have CMake of at least 2.8.6 version
 | 
				
			||||||
 | 
					installed. You also need to have pkg-config installed, the build system uses it
 | 
				
			||||||
 | 
					to find dependency libraries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There is some experimental accommodation for building natively on Windows, i.e. without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded paths for finding libraries and supports building only of some of toxcore components, so your mileage might vary.
 | 
					There is some experimental accommodation for building natively on Windows, i.e.
 | 
				
			||||||
 | 
					without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded
 | 
				
			||||||
 | 
					paths for finding libraries and supports building only of some of toxcore
 | 
				
			||||||
 | 
					components, so your mileage might vary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### CMake options
 | 
					### CMake options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There are some options that are available to configure the build.
 | 
					There are some options that are available to configure the build.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name                    | Description                                                                                   | Expected Value                                                            | Default Value                                     |
 | 
					| Name                    | Description                                                                                   | Expected Value                                                            | Default Value                                     |
 | 
				
			||||||
|------------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------|
 | 
					| ----------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------- |
 | 
				
			||||||
| `AUTOTEST`              | Enable autotests (mainly for CI).                                                             | ON or OFF                                                                 | OFF                                               |
 | 
					| `AUTOTEST`              | Enable autotests (mainly for CI).                                                             | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `BOOTSTRAP_DAEMON`      | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF                                                                 | ON                                                |
 | 
					| `BOOTSTRAP_DAEMON`      | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
 | 
					| `BUILD_FUN_UTILS`       | Build additional just for fun utilities.                                                      | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `BUILD_FUZZ_TESTS`      | Build fuzzing harnesses.                                                                      | ON or OFF                                                                 | OFF                                               |
 | 
					| `BUILD_FUZZ_TESTS`      | Build fuzzing harnesses.                                                                      | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `BUILD_MISC_TESTS`      | Build additional tests.                                                                       | ON or OFF                                                                 | OFF                                               |
 | 
					| `BUILD_MISC_TESTS`      | Build additional tests.                                                                       | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `BUILD_FUN_UTILS`      | Build additional funny utilities.                                                             | ON or OFF                                                                 | OFF                                               |
 | 
					 | 
				
			||||||
| `BUILD_TOXAV`           | Whether to build the toxav library.                                                           | ON or OFF                                                                 | ON                                                |
 | 
					| `BUILD_TOXAV`           | Whether to build the toxav library.                                                           | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed.                                                 | Directory path.                                                           | Platform-dependent. Refer to CMake documentation. |
 | 
					 | 
				
			||||||
| `CMAKE_BUILD_TYPE`      | Specifies the build type on single-configuration generators (e.g. make or ninja).             | Debug, Release, RelWithDebInfo, MinSizeRel                                | Empty string.                                     |
 | 
					| `CMAKE_BUILD_TYPE`      | Specifies the build type on single-configuration generators (e.g. make or ninja).             | Debug, Release, RelWithDebInfo, MinSizeRel                                | Empty string.                                     |
 | 
				
			||||||
| `DHT_BOOTSTRAP`        | Enable building of `DHT_bootstrap`                                                            | ON or OFF                                                                 | ON                                                |
 | 
					| `CMAKE_INSTALL_PREFIX`  | Path to where everything should be installed.                                                 | Directory path.                                                           | Platform-dependent. Refer to CMake documentation. |
 | 
				
			||||||
 | 
					| `DHT_BOOTSTRAP`         | Enable building of `DHT_bootstrap`.                                                           | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
| `ENABLE_SHARED`         | Build shared (dynamic) libraries for all modules.                                             | ON or OFF                                                                 | ON                                                |
 | 
					| `ENABLE_SHARED`         | Build shared (dynamic) libraries for all modules.                                             | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
| `ENABLE_STATIC`         | Build static libraries for all modules.                                                       | ON or OFF                                                                 | ON                                                |
 | 
					| `ENABLE_STATIC`         | Build static libraries for all modules.                                                       | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
| `EXECUTION_TRACE`      | Print a function trace during execution (for debugging).                                      | ON or OFF                                                                 | OFF                                               |
 | 
					| `EXPERIMENTAL_API`      | Install experimental header file with unstable API.                                           | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
 | 
					| `FLAT_OUTPUT_STRUCTURE` | Whether to produce output artifacts in {bin,lib}.                                             | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `FULLY_STATIC`          | Build fully static executables.                                                               | ON or OFF                                                                 | OFF                                               |
 | 
					| `FULLY_STATIC`          | Build fully static executables.                                                               | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `MIN_LOGGER_LEVEL`      | Logging level to use.                                                                         | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string.                                     |
 | 
					| `MIN_LOGGER_LEVEL`      | Logging level to use.                                                                         | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string.                                     |
 | 
				
			||||||
| `MSVC_STATIC_SODIUM`    | Whether to link libsodium statically for MSVC.                                                | ON or OFF                                                                 | OFF                                               |
 | 
					| `MSVC_STATIC_SODIUM`    | Whether to link libsodium statically for MSVC.                                                | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `MUST_BUILD_TOXAV`      | Fail the build if toxav cannot be built.                                                      | ON or OFF                                                                 | OFF                                               |
 | 
					| `MUST_BUILD_TOXAV`      | Fail the build if toxav cannot be built.                                                      | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `NON_HERMETIC_TESTS`    | Whether to build and run tests that depend on an internet connection.                         | ON or OFF                                                                 | OFF                                               |
 | 
					| `NON_HERMETIC_TESTS`    | Whether to build and run tests that depend on an internet connection.                         | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
 | 
					| `PROXY_TEST`            | Enable proxy test (requires `other/proxy/proxy_server.go` to be running).                     | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `STRICT_ABI`            | Enforce strict ABI export in dynamic libraries.                                               | ON or OFF                                                                 | OFF                                               |
 | 
					| `STRICT_ABI`            | Enforce strict ABI export in dynamic libraries.                                               | ON or OFF                                                                 | OFF                                               |
 | 
				
			||||||
| `TEST_TIMEOUT_SECONDS`  | Limit runtime of each test to the number of seconds specified.                                | Positive number or nothing (empty string).                                | Empty string.                                     |
 | 
					| `TEST_TIMEOUT_SECONDS`  | Limit runtime of each test to the number of seconds specified.                                | Positive number or nothing (empty string).                                | Empty string.                                     |
 | 
				
			||||||
 | 
					| `UNITTEST`              | Enable unit tests (disable if you don't have a working gmock or gtest).                       | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
| `USE_IPV6`              | Use IPv6 in tests.                                                                            | ON or OFF                                                                 | ON                                                |
 | 
					| `USE_IPV6`              | Use IPv6 in tests.                                                                            | ON or OFF                                                                 | ON                                                |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can get this list of option using the following commands
 | 
					You can get this list of option using the following commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cmake -B _build -LAH
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```sh
 | 
					```sh
 | 
				
			||||||
grep "option(" CMakeLists.txt cmake/*
 | 
					grep "option(" CMakeLists.txt cmake/*
 | 
				
			||||||
grep "set(.* CACHE" CMakeLists.txt cmake/*
 | 
					grep "set(.* CACHE" CMakeLists.txt cmake/*
 | 
				
			||||||
@@ -150,11 +182,12 @@ cmake \
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Building tests
 | 
					### Building tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In addition to the integration tests ("autotests") and miscellaneous tests
 | 
					In addition to the integration tests ("autotests") and miscellaneous tests
 | 
				
			||||||
enabled by cmake variables described above, there are unit tests which will be
 | 
					enabled by cmake variables described above, there are unit tests which will be
 | 
				
			||||||
built if the source distribution of gtest (the Google Unit Test framework) is
 | 
					built if the source distribution of gtest (the Google Unit Test framework) is
 | 
				
			||||||
found by cmake in `c-toxcore/third_party`. This can be achieved by running
 | 
					found by cmake in `c-toxcore/third_party`. This can be achieved by running 'git
 | 
				
			||||||
'git clone https://github.com/google/googletest` from that directory.
 | 
					clone https://github.com/google/googletest` from that directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Build process
 | 
					### Build process
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -170,19 +203,33 @@ make
 | 
				
			|||||||
make install
 | 
					make install
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					or shorter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					cmake -B _build
 | 
				
			||||||
 | 
					cmake -B _build --target install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Windows
 | 
					#### Windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Building on Windows host
 | 
					##### Building on Windows host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###### Microsoft Visual Studio's Developer Command Prompt
 | 
					###### Microsoft Visual Studio's Developer Command Prompt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In addition to meeting the [requirements](#requirements), you need a version of Visual Studio (the [community edition](https://www.visualstudio.com/vs/visual-studio-express/) is enough) and a CMake version that's compatible with the Visual Studio version you're using.
 | 
					In addition to meeting the [requirements](#requirements), you need a version of
 | 
				
			||||||
 | 
					Visual Studio (the
 | 
				
			||||||
 | 
					[community edition](https://www.visualstudio.com/vs/visual-studio-express/) is
 | 
				
			||||||
 | 
					enough) and a CMake version that's compatible with the Visual Studio version
 | 
				
			||||||
 | 
					you're using.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You must also ensure that the msvc versions of dependencies you're using are placed in the correct folders.
 | 
					You must also ensure that the msvc versions of dependencies you're using are
 | 
				
			||||||
 | 
					placed in the correct folders.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32, it's `c-toxcore/third_party/pthreads-win32`
 | 
					For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32,
 | 
				
			||||||
 | 
					it's `c-toxcore/third_party/pthreads-win32`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Once all of this is done, from the **Developer Command Prompt for VS**, simply run
 | 
					Once all of this is done, from the **Developer Command Prompt for VS**, simply
 | 
				
			||||||
 | 
					run
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
mkdir _build
 | 
					mkdir _build
 | 
				
			||||||
@@ -193,22 +240,23 @@ msbuild ALL_BUILD.vcxproj
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
###### MSYS/Cygwin
 | 
					###### MSYS/Cygwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Download Cygwin ([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe))
 | 
					Download Cygwin
 | 
				
			||||||
 | 
					([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Search and select exactly these packages in Devel category:
 | 
					Search and select exactly these packages in Devel category:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - mingw64-i686-gcc-core (32-bit) / mingw64-x86_64-gcc-core (64-bit)
 | 
					- mingw64-i686-gcc-core (32-bit) / mingw64-x86_64-gcc-core (64-bit)
 | 
				
			||||||
  - mingw64-i686-gcc-g++ (32-bit) / mingw64-x86_64-gcc-g++ (64-bit)
 | 
					- mingw64-i686-gcc-g++ (32-bit) / mingw64-x86_64-gcc-g++ (64-bit)
 | 
				
			||||||
  - make
 | 
					- make
 | 
				
			||||||
  - cmake
 | 
					- cmake
 | 
				
			||||||
  - libtool
 | 
					- libtool
 | 
				
			||||||
  - autoconf
 | 
					- autoconf
 | 
				
			||||||
  - automake
 | 
					- automake
 | 
				
			||||||
  - tree
 | 
					- tree
 | 
				
			||||||
  - curl
 | 
					- curl
 | 
				
			||||||
  - perl
 | 
					- perl
 | 
				
			||||||
  - yasm
 | 
					- yasm
 | 
				
			||||||
  - pkg-config
 | 
					- pkg-config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To handle Windows EOL correctly run the following in the Cygwin Terminal:
 | 
					To handle Windows EOL correctly run the following in the Cygwin Terminal:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,18 +269,24 @@ set -o igncr
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Download toxcore source code and extract it to a folder.
 | 
					Download toxcore source code and extract it to a folder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Open Cygwin Terminal in the toxcore folder and run `./other/windows_build_script_toxcore.sh` to start the build process.
 | 
					Open Cygwin Terminal in the toxcore folder and run
 | 
				
			||||||
 | 
					`./other/windows_build_script_toxcore.sh` to start the build process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin folder (default `C:\cygwin64`).
 | 
					Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin
 | 
				
			||||||
 | 
					folder (default `C:\cygwin64`).
 | 
				
			||||||
Dependency versions can be customized in `./other/windows_build_script_toxcore.sh` and described in the section below.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dependency versions can be customized in
 | 
				
			||||||
 | 
					`./other/windows_build_script_toxcore.sh` and described in the section below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Cross-compiling from Linux
 | 
					##### Cross-compiling from Linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These cross-compilation instructions were tested on and written for 64-bit Ubuntu 16.04. You could generalize them for any Linux system, the only requirements are that you have Docker version of >= 1.9.0 and you are running 64-bit system.
 | 
					These cross-compilation instructions were tested on and written for 64-bit
 | 
				
			||||||
 | 
					Ubuntu 16.04. You could generalize them for any Linux system, the only
 | 
				
			||||||
 | 
					requirements are that you have Docker version of >= 1.9.0 and you are running
 | 
				
			||||||
 | 
					64-bit system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The cross-compilation is fully automated by a parameterized [Dockerfile](/other/docker/windows/Dockerfile).
 | 
					The cross-compilation is fully automated by a parameterized
 | 
				
			||||||
 | 
					[Dockerfile](/other/docker/windows/Dockerfile).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Install Docker
 | 
					Install Docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -243,17 +297,18 @@ apt-get install docker.io
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Get the toxcore source code and navigate to `other/docker/windows`.
 | 
					Get the toxcore source code and navigate to `other/docker/windows`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Build the container image based on the Dockerfile. The following options are available to customize the building of the container image.
 | 
					Build the container image based on the Dockerfile. The following options are
 | 
				
			||||||
 | 
					available to customize the building of the container image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name                       | Description                                           | Expected Value                      | Default Value |
 | 
					| Name                       | Description                                           | Expected Value                      | Default Value |
 | 
				
			||||||
|-----------------------|----------------------------------------------------------------|-------------------------------------|---------------|
 | 
					| -------------------------- | ----------------------------------------------------- | ----------------------------------- | ------------- |
 | 
				
			||||||
| `SUPPORT_ARCH_i686`        | Support building 32-bit toxcore.                      | "true" or "false" (case sensitive). | true          |
 | 
					| `SUPPORT_ARCH_i686`        | Support building 32-bit toxcore.                      | "true" or "false" (case sensitive). | true          |
 | 
				
			||||||
| `SUPPORT_ARCH_x86_64`      | Support building 64-bit toxcore.                      | "true" or "false" (case sensitive). | true          |
 | 
					| `SUPPORT_ARCH_x86_64`      | Support building 64-bit toxcore.                      | "true" or "false" (case sensitive). | true          |
 | 
				
			||||||
| `SUPPORT_TEST`             | Support running toxcore automated tests.              | "true" or "false" (case sensitive). | false         |
 | 
					| `SUPPORT_TEST`             | Support running toxcore automated tests.              | "true" or "false" (case sensitive). | false         |
 | 
				
			||||||
| `CROSS_COMPILE`       | Cross-compiling. True for Docker, false for Cygwin.            | "true" or "false" (case sensitive). | true          |
 | 
					| `VERSION_OPUS`             | Version of libopus to build toxcore with.             | Numeric version number.             | 1.4           |
 | 
				
			||||||
| `VERSION_OPUS`        | Version of libopus to build toxcore with.                      | Numeric version number.             | 1.3.1         |
 | 
					| `VERSION_SODIUM`           | Version of libsodium to build toxcore with.           | Numeric version number.             | 1.0.19        |
 | 
				
			||||||
| `VERSION_SODIUM`      | Version of libsodium to build toxcore with.                    | Numeric version number.             | 1.0.18        |
 | 
					| `VERSION_VPX`              | Version of libvpx to build toxcore with.              | Numeric version number.             | 1.14.0        |
 | 
				
			||||||
| `VERSION_VPX`         | Version of libvpx to build toxcore with.                       | Numeric version number.             | 1.11.0        |
 | 
					| `ENABLE_HASH_VERIFICATION` | Verify the hashes of the default dependency versions. | "true" or "false" (case sensitive). | true          |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example of building a container image with options
 | 
					Example of building a container image with options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -265,16 +320,16 @@ docker build \
 | 
				
			|||||||
  .
 | 
					  .
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Run the container to build toxcore. The following options are available to customize the running of the container image.
 | 
					Run the container to build toxcore. The following options are available to
 | 
				
			||||||
 | 
					customize the running of the container image.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Name                 | Description                                                                                | Expected Value                      | Default Value                              |
 | 
					| Name                 | Description                                                                                | Expected Value                      | Default Value                              |
 | 
				
			||||||
|----------------------|--------------------------------------------------------------------------------------------|-------------------------------------|--------------------------------------------------------------------|
 | 
					| -------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------- | ------------------------------------------ |
 | 
				
			||||||
| `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails.                                                          | "true" or "false" (case sensitive). | `false`                                    |
 | 
					| `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails.                                                          | "true" or "false" (case sensitive). | `false`                                    |
 | 
				
			||||||
| `ENABLE_ARCH_i686`   | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled.   | "true" or "false" (case sensitive). | `true`                                     |
 | 
					| `ENABLE_ARCH_i686`   | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled.   | "true" or "false" (case sensitive). | `true`                                     |
 | 
				
			||||||
| `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true`                                     |
 | 
					| `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true`                                     |
 | 
				
			||||||
| `ENABLE_TEST`        | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled.          | "true" or "false" (case sensitive). | `false`                                    |
 | 
					| `ENABLE_TEST`        | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled.          | "true" or "false" (case sensitive). | `false`                                    |
 | 
				
			||||||
| `EXTRA_CMAKE_FLAGS`  | Extra arguments to pass to the CMake command when building toxcore.                        | CMake options.                      | `-DTEST_TIMEOUT_SECONDS=90`                                        |
 | 
					| `EXTRA_CMAKE_FLAGS`  | Extra arguments to pass to the CMake command when building toxcore.                        | CMake options.                      | `-DTEST_TIMEOUT_SECONDS=90 -DUSE_IPV6=OFF` |
 | 
				
			||||||
| `CROSS_COMPILE`      | Cross-compiling. True for Docker, false for Cygwin.                                        | "true" or "false" (case sensitive). | `true`                                                             |
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example of running the container with options
 | 
					Example of running the container with options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -284,14 +339,117 @@ docker run \
 | 
				
			|||||||
  -e ALLOW_TEST_FAILURE=true \
 | 
					  -e ALLOW_TEST_FAILURE=true \
 | 
				
			||||||
  -v /path/to/toxcore/sourcecode:/toxcore \
 | 
					  -v /path/to/toxcore/sourcecode:/toxcore \
 | 
				
			||||||
  -v /path/to/where/output/build/result:/prefix \
 | 
					  -v /path/to/where/output/build/result:/prefix \
 | 
				
			||||||
 | 
					  -t \
 | 
				
			||||||
  --rm \
 | 
					  --rm \
 | 
				
			||||||
  toxcore
 | 
					  toxcore
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
After the build succeeds, you should see the built toxcore libraries in `/path/to/where/output/build/result`.
 | 
					After the build succeeds, you should see the built toxcore libraries in
 | 
				
			||||||
 | 
					`/path/to/where/output/build/result`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The file structure should look similar to the following
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					result
 | 
				
			||||||
 | 
					├── [4.0K]  i686
 | 
				
			||||||
 | 
					│   ├── [ 36K]  bin
 | 
				
			||||||
 | 
					│   │   ├── [636K]  DHT_bootstrap.exe
 | 
				
			||||||
 | 
					│   │   ├── [572K]  cracker.exe
 | 
				
			||||||
 | 
					│   │   ├── [359K]  cracker_simple.exe
 | 
				
			||||||
 | 
					│   │   ├── [378K]  create_bootstrap_keys.exe
 | 
				
			||||||
 | 
					│   │   ├── [378K]  create_minimal_savedata.exe
 | 
				
			||||||
 | 
					│   │   ├── [958K]  create_savedata.exe
 | 
				
			||||||
 | 
					│   │   ├── [ 18K]  libtoxcore.def
 | 
				
			||||||
 | 
					│   │   ├── [2.6M]  libtoxcore.dll
 | 
				
			||||||
 | 
					│   │   ├── [ 65K]  libtoxcore.exp
 | 
				
			||||||
 | 
					│   │   ├── [428K]  libtoxcore.lib
 | 
				
			||||||
 | 
					│   │   ├── [989K]  save-generator.exe
 | 
				
			||||||
 | 
					│   │   ├── [381K]  sign.exe
 | 
				
			||||||
 | 
					│   │   └── [408K]  strkey.exe
 | 
				
			||||||
 | 
					│   ├── [4.0K]  include
 | 
				
			||||||
 | 
					│   │   └── [4.0K]  tox
 | 
				
			||||||
 | 
					│   │       ├── [177K]  tox.h
 | 
				
			||||||
 | 
					│   │       ├── [ 10K]  tox_dispatch.h
 | 
				
			||||||
 | 
					│   │       ├── [ 26K]  tox_events.h
 | 
				
			||||||
 | 
					│   │       ├── [6.4K]  tox_private.h
 | 
				
			||||||
 | 
					│   │       ├── [ 26K]  toxav.h
 | 
				
			||||||
 | 
					│   │       └── [ 12K]  toxencryptsave.h
 | 
				
			||||||
 | 
					│   └── [4.0K]  lib
 | 
				
			||||||
 | 
					│       ├── [577K]  libopus.a
 | 
				
			||||||
 | 
					│       ├── [660K]  libsodium.a
 | 
				
			||||||
 | 
					│       ├── [ 10K]  libssp.a
 | 
				
			||||||
 | 
					│       ├── [1016K]  libtoxcore.a
 | 
				
			||||||
 | 
					│       ├── [456K]  libtoxcore.dll.a
 | 
				
			||||||
 | 
					│       ├── [2.7M]  libvpx.a
 | 
				
			||||||
 | 
					│       ├── [ 72K]  libwinpthread.a
 | 
				
			||||||
 | 
					│       └── [4.0K]  pkgconfig
 | 
				
			||||||
 | 
					│           ├── [ 250]  libsodium.pc
 | 
				
			||||||
 | 
					│           ├── [ 357]  opus.pc
 | 
				
			||||||
 | 
					│           ├── [ 247]  toxcore.pc
 | 
				
			||||||
 | 
					│           └── [ 309]  vpx.pc
 | 
				
			||||||
 | 
					└── [4.0K]  x86_64
 | 
				
			||||||
 | 
					    ├── [ 36K]  bin
 | 
				
			||||||
 | 
					    │   ├── [504K]  DHT_bootstrap.exe
 | 
				
			||||||
 | 
					    │   ├── [474K]  cracker.exe
 | 
				
			||||||
 | 
					    │   ├── [277K]  cracker_simple.exe
 | 
				
			||||||
 | 
					    │   ├── [287K]  create_bootstrap_keys.exe
 | 
				
			||||||
 | 
					    │   ├── [288K]  create_minimal_savedata.exe
 | 
				
			||||||
 | 
					    │   ├── [769K]  create_savedata.exe
 | 
				
			||||||
 | 
					    │   ├── [ 18K]  libtoxcore.def
 | 
				
			||||||
 | 
					    │   ├── [2.4M]  libtoxcore.dll
 | 
				
			||||||
 | 
					    │   ├── [ 64K]  libtoxcore.exp
 | 
				
			||||||
 | 
					    │   ├── [420K]  libtoxcore.lib
 | 
				
			||||||
 | 
					    │   ├── [800K]  save-generator.exe
 | 
				
			||||||
 | 
					    │   ├── [289K]  sign.exe
 | 
				
			||||||
 | 
					    │   └── [317K]  strkey.exe
 | 
				
			||||||
 | 
					    ├── [4.0K]  include
 | 
				
			||||||
 | 
					    │   └── [4.0K]  tox
 | 
				
			||||||
 | 
					    │       ├── [177K]  tox.h
 | 
				
			||||||
 | 
					    │       ├── [ 10K]  tox_dispatch.h
 | 
				
			||||||
 | 
					    │       ├── [ 26K]  tox_events.h
 | 
				
			||||||
 | 
					    │       ├── [6.4K]  tox_private.h
 | 
				
			||||||
 | 
					    │       ├── [ 26K]  toxav.h
 | 
				
			||||||
 | 
					    │       └── [ 12K]  toxencryptsave.h
 | 
				
			||||||
 | 
					    └── [4.0K]  lib
 | 
				
			||||||
 | 
					        ├── [697K]  libopus.a
 | 
				
			||||||
 | 
					        ├── [575K]  libsodium.a
 | 
				
			||||||
 | 
					        ├── [ 11K]  libssp.a
 | 
				
			||||||
 | 
					        ├── [905K]  libtoxcore.a
 | 
				
			||||||
 | 
					        ├── [449K]  libtoxcore.dll.a
 | 
				
			||||||
 | 
					        ├── [2.9M]  libvpx.a
 | 
				
			||||||
 | 
					        ├── [ 68K]  libwinpthread.a
 | 
				
			||||||
 | 
					        └── [4.0K]  pkgconfig
 | 
				
			||||||
 | 
					            ├── [ 252]  libsodium.pc
 | 
				
			||||||
 | 
					            ├── [ 359]  opus.pc
 | 
				
			||||||
 | 
					            ├── [ 249]  toxcore.pc
 | 
				
			||||||
 | 
					            └── [ 311]  vpx.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					12 directories, 60 files
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- `libtoxcore.dll` is the shared library. It is fully self-contained, with no
 | 
				
			||||||
 | 
					  additional dependencies aside from the Windows OS dlls, and can be used in
 | 
				
			||||||
 | 
					  MSVC, MinGW, Clang, etc. projects. Despite its name, it provides toxcore,
 | 
				
			||||||
 | 
					  toxav, toxencryptsave -- all of Tox.
 | 
				
			||||||
 | 
					- `libtoxcore.a` is the static library. In order to use it, it needs to be
 | 
				
			||||||
 | 
					  linked against the other provided .a libraries (but not the .dll.a!) and
 | 
				
			||||||
 | 
					  additionally -liphlpapi and -lws2_32 Windows dlls. It similarly provides all
 | 
				
			||||||
 | 
					  of Tox APIs.
 | 
				
			||||||
 | 
					- `libtoxcore.dll.a` is the MinGW import library for `libtoxcore.dll`.
 | 
				
			||||||
 | 
					- `libtoxcore.lib` is the MSVC import library for `libtoxcore.dll`.
 | 
				
			||||||
 | 
					- `libtoxcore.exp` and `libtoxcore.def` are the exported by `libtoxcore`
 | 
				
			||||||
 | 
					  symbols.
 | 
				
			||||||
 | 
					- `*.exe` are statically compiled executables -- `DHT_bootstrap` and
 | 
				
			||||||
 | 
					  [the fun utils](#secondary).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Pre-built binaries
 | 
					## Pre-built binaries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Linux
 | 
					### Linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Toxcore is packaged by at least by the following distributions: ALT Linux, [Arch Linux](https://www.archlinux.org/packages/?q=toxcore), [Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE, PCLinuxOS, ROSA and Slackware, [according to the information from pkgs.org](https://pkgs.org/download/toxcore). Note that this list might be incomplete and some other distributions might package it too.
 | 
					Toxcore is packaged by at least by the following distributions: ALT Linux,
 | 
				
			||||||
 | 
					[Arch Linux](https://www.archlinux.org/packages/?q=toxcore),
 | 
				
			||||||
 | 
					[Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE,
 | 
				
			||||||
 | 
					PCLinuxOS, ROSA and Slackware,
 | 
				
			||||||
 | 
					[according to the information from pkgs.org](https://pkgs.org/download/toxcore).
 | 
				
			||||||
 | 
					Note that this list might be incomplete and some other distributions might
 | 
				
			||||||
 | 
					package it too.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										67
									
								
								external/toxcore/c-toxcore/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								external/toxcore/c-toxcore/README.md
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +1,14 @@
 | 
				
			|||||||
# 
 | 
					# 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Current Coverage:** [](https://codecov.io/gh/TokTok/c-toxcore)
 | 
					**Current Coverage:**
 | 
				
			||||||
 | 
					[](https://codecov.io/gh/TokTok/c-toxcore)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[**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://tox.chat/download.html) **|** [**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|** [**Compiling**](/INSTALL.md)
 | 
					[**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://tox.chat/download.html) **|**
 | 
				
			||||||
 | 
					[**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|**
 | 
				
			||||||
 | 
					[**Compiling**](/INSTALL.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## What is Tox
 | 
					## What is Tox
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,20 +22,20 @@ and privacy easy to obtain for regular users. It uses
 | 
				
			|||||||
### 
 | 
					### 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is an **experimental** cryptographic network library. It has not been
 | 
					This is an **experimental** cryptographic network library. It has not been
 | 
				
			||||||
formally audited by an independent third party that specializes in
 | 
					formally audited by an independent third party that specializes in cryptography
 | 
				
			||||||
cryptography or cryptanalysis. **Use this library at your own risk.**
 | 
					or cryptanalysis. **Use this library at your own risk.**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The underlying crypto library [libsodium](https://doc.libsodium.org/) provides
 | 
					The underlying crypto library [libsodium](https://doc.libsodium.org/) provides
 | 
				
			||||||
reliable encryption, but the security model has not yet been fully specified.
 | 
					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
 | 
					See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for a discussion
 | 
				
			||||||
discussion on developing a threat model. See other issues for known weaknesses
 | 
					on developing a threat model. See other issues for known weaknesses (e.g.
 | 
				
			||||||
(e.g. [issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes
 | 
					[issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes what can
 | 
				
			||||||
what can happen if your secret key is stolen).
 | 
					happen if your secret key is stolen).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Toxcore Development Roadmap
 | 
					## Toxcore Development Roadmap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The roadmap and changelog are generated from GitHub issues. You may view them
 | 
					The roadmap and changelog are generated from GitHub issues. You may view them on
 | 
				
			||||||
on the website, where they are updated at least once every 24 hours:
 | 
					the website, where they are updated at least once every 24 hours:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Changelog: https://toktok.ltd/changelog/c-toxcore
 | 
					- Changelog: https://toktok.ltd/changelog/c-toxcore
 | 
				
			||||||
- Roadmap: https://toktok.ltd/roadmap/c-toxcore
 | 
					- Roadmap: https://toktok.ltd/roadmap/c-toxcore
 | 
				
			||||||
@@ -38,7 +44,11 @@ on the website, where they are updated at least once every 24 hours:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
 | 
					Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the following command: `git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by running `git submodule update --init` in the root directory of the repo.
 | 
					Be advised that due to the addition of `cmp` as a submodule, you now also need
 | 
				
			||||||
 | 
					to initialize the git submodules required by toxcore. This can be done by
 | 
				
			||||||
 | 
					cloning the repo with the following command:
 | 
				
			||||||
 | 
					`git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by
 | 
				
			||||||
 | 
					running `git submodule update --init` in the root directory of the repo.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
 | 
					In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
 | 
				
			||||||
installed, run:
 | 
					installed, run:
 | 
				
			||||||
@@ -74,17 +84,17 @@ if (err_new != TOX_ERR_NEW_OK) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here, we simply exit the program, but in a real client you will probably want
 | 
					Here, we simply exit the program, but in a real client you will probably want to
 | 
				
			||||||
to do some error handling and proper error reporting to the user. The `NULL`
 | 
					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
 | 
					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
 | 
					contains various write-once network settings and allows you to load a previously
 | 
				
			||||||
previously serialised instance. See [toxcore/tox.h](tox.h) for details.
 | 
					serialised instance. See [toxcore/tox.h](tox.h) for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Setting up callbacks
 | 
					### Setting up callbacks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Toxcore works with callbacks that you can register to listen for certain
 | 
					Toxcore works with callbacks that you can register to listen for certain events.
 | 
				
			||||||
events. Examples of such events are "friend request received" or "friend sent
 | 
					Examples of such events are "friend request received" or "friend sent a
 | 
				
			||||||
a message". Search the API for `tox_callback_*` to find all of them.
 | 
					message". Search the API for `tox_callback_*` to find all of them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here, we will set up callbacks for receiving friend requests and receiving
 | 
					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
 | 
					messages. We will always accept any friend request (because we're a bot), and
 | 
				
			||||||
@@ -172,3 +182,24 @@ the API documentation in [toxcore/tox.h](toxcore/tox.h) for more information.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
 | 
					- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
 | 
				
			||||||
- [minitox](https://github.com/hqwrong/minitox) (A minimal tox client)
 | 
					- [minitox](https://github.com/hqwrong/minitox) (A minimal tox client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## SAST Tools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project uses various tools supporting Static Application Security Testing:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [clang-tidy](https://clang.llvm.org/extra/clang-tidy/): A clang-based C++
 | 
				
			||||||
 | 
					  "linter" tool.
 | 
				
			||||||
 | 
					- [Coverity](https://scan.coverity.com/): A cloud-based static analyzer service
 | 
				
			||||||
 | 
					  for Java, C/C++, C#, JavaScript, Ruby, or Python that is free for open source
 | 
				
			||||||
 | 
					  projects.
 | 
				
			||||||
 | 
					- [cppcheck](https://cppcheck.sourceforge.io/): A static analyzer for C/C++
 | 
				
			||||||
 | 
					  code.
 | 
				
			||||||
 | 
					- [cpplint](https://github.com/cpplint/cpplint): Static code checker for C++
 | 
				
			||||||
 | 
					- [goblint](https://goblint.in.tum.de/): A static analyzer for multi-threaded C
 | 
				
			||||||
 | 
					  programs, specializing in finding concurrency bugs.
 | 
				
			||||||
 | 
					- [infer](https://github.com/facebook/infer): A static analyzer for Java, C,
 | 
				
			||||||
 | 
					  C++, and Objective-C.
 | 
				
			||||||
 | 
					- [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source):
 | 
				
			||||||
 | 
					  A static analyzer for C, C++, C#, and Java code.
 | 
				
			||||||
 | 
					- [tokstyle](https://github.com/TokTok/hs-tokstyle): A style checker for TokTok
 | 
				
			||||||
 | 
					  C projects.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,8 @@ cc_library(
 | 
				
			|||||||
        "//c-toxcore/toxcore:Messenger",
 | 
					        "//c-toxcore/toxcore:Messenger",
 | 
				
			||||||
        "//c-toxcore/toxcore:mono_time",
 | 
					        "//c-toxcore/toxcore:mono_time",
 | 
				
			||||||
        "//c-toxcore/toxcore:tox",
 | 
					        "//c-toxcore/toxcore:tox",
 | 
				
			||||||
 | 
					        "//c-toxcore/toxcore:tox_dispatch",
 | 
				
			||||||
 | 
					        "//c-toxcore/toxcore:tox_events",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -240,6 +240,7 @@ endif
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXTRA_DIST += \
 | 
					EXTRA_DIST += \
 | 
				
			||||||
	$(top_srcdir)/auto_tests/data/save.tox \
 | 
						$(top_srcdir)/auto_tests/data/save.tox.big \
 | 
				
			||||||
 | 
						$(top_srcdir)/auto_tests/data/save.tox.little \
 | 
				
			||||||
	$(top_srcdir)/auto_tests/check_compat.h \
 | 
						$(top_srcdir)/auto_tests/check_compat.h \
 | 
				
			||||||
	$(top_srcdir)/auto_tests/auto_test_support.h
 | 
						$(top_srcdir)/auto_tests/auto_test_support.h
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										50
									
								
								external/toxcore/c-toxcore/auto_tests/TCP_test.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								external/toxcore/c-toxcore/auto_tests/TCP_test.c
									
									
									
									
										vendored
									
									
								
							@@ -45,11 +45,11 @@ static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_basic(void)
 | 
					static void test_basic(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
@@ -266,13 +266,14 @@ static void kill_tcp_con(struct sec_TCP_con *con)
 | 
				
			|||||||
static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
 | 
					static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
 | 
				
			||||||
        uint16_t length)
 | 
					        uint16_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE);
 | 
					    const uint16_t packet_size = sizeof(uint16_t) + length + CRYPTO_MAC_SIZE;
 | 
				
			||||||
 | 
					    VLA(uint8_t, packet, packet_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
 | 
					    uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
 | 
				
			||||||
    memcpy(packet, &c_length, sizeof(uint16_t));
 | 
					    memcpy(packet, &c_length, sizeof(uint16_t));
 | 
				
			||||||
    int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + 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))) {
 | 
					    if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -282,7 +283,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP
 | 
				
			|||||||
    localhost.ip = get_loopback();
 | 
					    localhost.ip = get_loopback();
 | 
				
			||||||
    localhost.port = 0;
 | 
					    localhost.port = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &localhost) == SIZEOF_VLA(packet),
 | 
					    ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost) == packet_size,
 | 
				
			||||||
                  "Failed to send a packet.");
 | 
					                  "Failed to send a packet.");
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -303,11 +304,11 @@ static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, ui
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_some(void)
 | 
					static void test_some(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
@@ -498,11 +499,11 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_client(void)
 | 
					static void test_client(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Logger *logger = logger_new();
 | 
					    Logger *logger = logger_new();
 | 
				
			||||||
@@ -524,8 +525,9 @@ static void test_client(void)
 | 
				
			|||||||
    ip_port_tcp_s.ip = get_loopback();
 | 
					    ip_port_tcp_s.ip = get_loopback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr);
 | 
					    TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr);
 | 
				
			||||||
    do_tcp_connection(logger, mono_time, conn, nullptr);
 | 
					    // TCP sockets might need a moment before they can be written to.
 | 
				
			||||||
    c_sleep(50);
 | 
					    c_sleep(50);
 | 
				
			||||||
 | 
					    do_tcp_connection(logger, mono_time, conn, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The connection status should be unconfirmed here because we have finished
 | 
					    // The connection status should be unconfirmed here because we have finished
 | 
				
			||||||
    // sending our data and are awaiting a response.
 | 
					    // sending our data and are awaiting a response.
 | 
				
			||||||
@@ -559,6 +561,7 @@ static void test_client(void)
 | 
				
			|||||||
    ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
 | 
					    ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
 | 
				
			||||||
    TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
 | 
					    TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
 | 
				
			||||||
                                   f2_secret_key, nullptr);
 | 
					                                   f2_secret_key, nullptr);
 | 
				
			||||||
 | 
					    c_sleep(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The client should call this function (defined earlier) during the routing process.
 | 
					    // The client should call this function (defined earlier) during the routing process.
 | 
				
			||||||
    routing_response_handler(conn, response_callback, (char *)conn + 2);
 | 
					    routing_response_handler(conn, response_callback, (char *)conn + 2);
 | 
				
			||||||
@@ -581,7 +584,7 @@ static void test_client(void)
 | 
				
			|||||||
    do_tcp_connection(logger, mono_time, conn2, nullptr);
 | 
					    do_tcp_connection(logger, mono_time, conn2, nullptr);
 | 
				
			||||||
    c_sleep(50);
 | 
					    c_sleep(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t data[5] = {1, 2, 3, 4, 5};
 | 
					    const uint8_t data[5] = {1, 2, 3, 4, 5};
 | 
				
			||||||
    memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE);
 | 
					    memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE);
 | 
				
			||||||
    send_oob_packet(logger, conn2, f_public_key, data, 5);
 | 
					    send_oob_packet(logger, conn2, f_public_key, data, 5);
 | 
				
			||||||
    send_routing_request(logger, conn, f2_public_key);
 | 
					    send_routing_request(logger, conn, f2_public_key);
 | 
				
			||||||
@@ -632,11 +635,11 @@ static void test_client(void)
 | 
				
			|||||||
// Test how the client handles servers that don't respond.
 | 
					// Test how the client handles servers that don't respond.
 | 
				
			||||||
static void test_client_invalid(void)
 | 
					static void test_client_invalid(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
@@ -708,14 +711,13 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void test_tcp_connection(void)
 | 
					static void test_tcp_connection(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
@@ -824,11 +826,11 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_tcp_connection2(void)
 | 
					static void test_tcp_connection2(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_bucketnum(void)
 | 
					static void test_bucketnum(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE];
 | 
					    uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    random_bytes(rng, key1, sizeof(key1));
 | 
					    random_bytes(rng, key1, sizeof(key1));
 | 
				
			||||||
@@ -50,11 +50,11 @@ static void test_announce_data(void *object, const uint8_t *data, uint16_t lengt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_store_data(void)
 | 
					static void test_store_data(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Logger *log = logger_new();
 | 
					    Logger *log = logger_new();
 | 
				
			||||||
@@ -120,7 +120,6 @@ static void basic_announce_tests(void)
 | 
				
			|||||||
    test_store_data();
 | 
					    test_store_data();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
					    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include "../testing/misc_tools.h"
 | 
					#include "../testing/misc_tools.h"
 | 
				
			||||||
#include "../toxcore/Messenger.h"
 | 
					#include "../toxcore/Messenger.h"
 | 
				
			||||||
#include "../toxcore/mono_time.h"
 | 
					#include "../toxcore/mono_time.h"
 | 
				
			||||||
 | 
					#include "../toxcore/tox_dispatch.h"
 | 
				
			||||||
 | 
					#include "../toxcore/tox_events.h"
 | 
				
			||||||
#include "../toxcore/tox_struct.h"
 | 
					#include "../toxcore/tox_struct.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
@@ -23,6 +25,7 @@ Run_Auto_Options default_run_auto_options(void)
 | 
				
			|||||||
        .graph = GRAPH_COMPLETE,
 | 
					        .graph = GRAPH_COMPLETE,
 | 
				
			||||||
        .init_autotox = nullptr,
 | 
					        .init_autotox = nullptr,
 | 
				
			||||||
        .tcp_port = 33188,
 | 
					        .tcp_port = 33188,
 | 
				
			||||||
 | 
					        .events = true,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,7 +134,15 @@ void iterate_all_wait(AutoTox *autotoxes, uint32_t tox_count, uint32_t wait)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < tox_count; ++i) {
 | 
					    for (uint32_t i = 0; i < tox_count; ++i) {
 | 
				
			||||||
        if (autotoxes[i].alive) {
 | 
					        if (autotoxes[i].alive) {
 | 
				
			||||||
 | 
					            if (autotoxes[i].events) {
 | 
				
			||||||
 | 
					                Tox_Err_Events_Iterate err;
 | 
				
			||||||
 | 
					                Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
 | 
				
			||||||
 | 
					                ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					                tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
 | 
				
			||||||
 | 
					                tox_events_free(events);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
                tox_iterate(autotoxes[i].tox, &autotoxes[i]);
 | 
					                tox_iterate(autotoxes[i].tox, &autotoxes[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            autotoxes[i].clock += wait;
 | 
					            autotoxes[i].clock += wait;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -181,6 +192,7 @@ void kill_autotox(AutoTox *autotox)
 | 
				
			|||||||
    ck_assert(autotox->alive);
 | 
					    ck_assert(autotox->alive);
 | 
				
			||||||
    fprintf(stderr, "Killing #%u\n", autotox->index);
 | 
					    fprintf(stderr, "Killing #%u\n", autotox->index);
 | 
				
			||||||
    autotox->alive = false;
 | 
					    autotox->alive = false;
 | 
				
			||||||
 | 
					    tox_dispatch_free(autotox->dispatch);
 | 
				
			||||||
    tox_kill(autotox->tox);
 | 
					    tox_kill(autotox->tox);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -202,6 +214,11 @@ void reload(AutoTox *autotox)
 | 
				
			|||||||
    tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
 | 
					    tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
 | 
				
			||||||
    autotox->tox = tox_new_log(options, nullptr, &autotox->index);
 | 
					    autotox->tox = tox_new_log(options, nullptr, &autotox->index);
 | 
				
			||||||
    ck_assert(autotox->tox != nullptr);
 | 
					    ck_assert(autotox->tox != nullptr);
 | 
				
			||||||
 | 
					    autotox->dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(autotox->dispatch != nullptr);
 | 
				
			||||||
 | 
					    if (autotox->events) {
 | 
				
			||||||
 | 
					        tox_events_init(autotox->tox);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    tox_options_free(options);
 | 
					    tox_options_free(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_mono_time_callback(autotox);
 | 
					    set_mono_time_callback(autotox);
 | 
				
			||||||
@@ -212,6 +229,7 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
 | 
				
			|||||||
                               Run_Auto_Options *autotest_opts)
 | 
					                               Run_Auto_Options *autotest_opts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    autotox->index = index;
 | 
					    autotox->index = index;
 | 
				
			||||||
 | 
					    autotox->events = autotest_opts->events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_New err = TOX_ERR_NEW_OK;
 | 
					    Tox_Err_New err = TOX_ERR_NEW_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -259,6 +277,12 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    set_mono_time_callback(autotox);
 | 
					    set_mono_time_callback(autotox);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    autotox->dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(autotox->dispatch != nullptr);
 | 
				
			||||||
 | 
					    if (autotox->events) {
 | 
				
			||||||
 | 
					        tox_events_init(autotox->tox);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    autotox->alive = true;
 | 
					    autotox->alive = true;
 | 
				
			||||||
    autotox->save_state = nullptr;
 | 
					    autotox->save_state = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -311,7 +335,7 @@ static void initialise_friend_graph(Graph_Type graph, uint32_t num_toxes, AutoTo
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
 | 
					static void bootstrap_autotoxes(const Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
 | 
				
			||||||
                                AutoTox *autotoxes)
 | 
					                                AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true;
 | 
					    const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true;
 | 
				
			||||||
@@ -339,7 +363,9 @@ static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(AutoTox *autotoxes),
 | 
					typedef void autotox_test_cb(AutoTox *autotoxes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void run_auto_test(struct Tox_Options *options, uint32_t tox_count, autotox_test_cb *test,
 | 
				
			||||||
                   uint32_t state_size, Run_Auto_Options *autotest_opts)
 | 
					                   uint32_t state_size, Run_Auto_Options *autotest_opts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    printf("initialising %u toxes\n", tox_count);
 | 
					    printf("initialising %u toxes\n", tox_count);
 | 
				
			||||||
@@ -371,6 +397,7 @@ void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(Au
 | 
				
			|||||||
    test(autotoxes);
 | 
					    test(autotoxes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < tox_count; ++i) {
 | 
					    for (uint32_t i = 0; i < tox_count; ++i) {
 | 
				
			||||||
 | 
					        tox_dispatch_free(autotoxes[i].dispatch);
 | 
				
			||||||
        tox_kill(autotoxes[i].tox);
 | 
					        tox_kill(autotoxes[i].tox);
 | 
				
			||||||
        free(autotoxes[i].state);
 | 
					        free(autotoxes[i].state);
 | 
				
			||||||
        free(autotoxes[i].save_state);
 | 
					        free(autotoxes[i].save_state);
 | 
				
			||||||
@@ -417,7 +444,6 @@ void print_debug_log(Tox *m, Tox_Log_Level level, const char *file, uint32_t lin
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
void print_debug_logger(void *context, Logger_Level level, const char *file, int line, const char *func, const char *message, void *userdata)
 | 
					void print_debug_logger(void *context, Logger_Level level, const char *file, int line, const char *func, const char *message, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    print_debug_log(nullptr, (Tox_Log_Level) level, file, (uint32_t) line, func, message, userdata);
 | 
					    print_debug_log(nullptr, (Tox_Log_Level) level, file, (uint32_t) line, func, message, userdata);
 | 
				
			||||||
@@ -455,4 +481,3 @@ Tox *tox_new_log(struct Tox_Options *options, Tox_Err_New *err, void *log_user_d
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    return tox_new_log_lan(options, err, log_user_data, false);
 | 
					    return tox_new_log_lan(options, err, log_user_data, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,11 @@
 | 
				
			|||||||
#include "../testing/misc_tools.h"
 | 
					#include "../testing/misc_tools.h"
 | 
				
			||||||
#include "../toxcore/Messenger.h"
 | 
					#include "../toxcore/Messenger.h"
 | 
				
			||||||
#include "../toxcore/mono_time.h"
 | 
					#include "../toxcore/mono_time.h"
 | 
				
			||||||
 | 
					#include "../toxcore/tox_dispatch.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AutoTox {
 | 
					typedef struct AutoTox {
 | 
				
			||||||
    Tox *tox;
 | 
					    Tox *tox;
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t index;
 | 
					    uint32_t index;
 | 
				
			||||||
    uint64_t clock;
 | 
					    uint64_t clock;
 | 
				
			||||||
@@ -17,6 +19,7 @@ typedef struct AutoTox {
 | 
				
			|||||||
    size_t save_size;
 | 
					    size_t save_size;
 | 
				
			||||||
    uint8_t *save_state;
 | 
					    uint8_t *save_state;
 | 
				
			||||||
    bool alive;
 | 
					    bool alive;
 | 
				
			||||||
 | 
					    bool events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void *state;
 | 
					    void *state;
 | 
				
			||||||
} AutoTox;
 | 
					} AutoTox;
 | 
				
			||||||
@@ -42,6 +45,7 @@ typedef struct Run_Auto_Options {
 | 
				
			|||||||
    Graph_Type graph;
 | 
					    Graph_Type graph;
 | 
				
			||||||
    void (*init_autotox)(AutoTox *autotox, uint32_t n);
 | 
					    void (*init_autotox)(AutoTox *autotox, uint32_t n);
 | 
				
			||||||
    uint16_t tcp_port;
 | 
					    uint16_t tcp_port;
 | 
				
			||||||
 | 
					    bool events;
 | 
				
			||||||
} Run_Auto_Options;
 | 
					} Run_Auto_Options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Run_Auto_Options default_run_auto_options(void);
 | 
					Run_Auto_Options default_run_auto_options(void);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,10 +23,11 @@ typedef struct State {
 | 
				
			|||||||
} State;
 | 
					} State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_self_connection_status(
 | 
					static void handle_self_connection_status(
 | 
				
			||||||
    Tox *tox, Tox_Connection connection_status, void *user_data)
 | 
					    const Tox_Event_Self_Connection_Status *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
 | 
				
			||||||
    if (connection_status != TOX_CONNECTION_NONE) {
 | 
					    if (connection_status != TOX_CONNECTION_NONE) {
 | 
				
			||||||
        printf("tox #%u: is now connected\n", autotox->index);
 | 
					        printf("tox #%u: is now connected\n", autotox->index);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -35,10 +36,13 @@ static void handle_self_connection_status(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_friend_connection_status(
 | 
					static void handle_friend_connection_status(
 | 
				
			||||||
    Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data)
 | 
					    const Tox_Event_Friend_Connection_Status *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friendnumber = tox_event_friend_connection_status_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (connection_status != TOX_CONNECTION_NONE) {
 | 
					    if (connection_status != TOX_CONNECTION_NONE) {
 | 
				
			||||||
        printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber);
 | 
					        printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -70,28 +74,33 @@ static void audio_callback(void *tox, uint32_t groupnumber, uint32_t peernumber,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_invite(
 | 
					static void handle_conference_invite(
 | 
				
			||||||
    Tox *tox, uint32_t friendnumber, Tox_Conference_Type type,
 | 
					    const Tox_Event_Conference_Invite *event, void *user_data)
 | 
				
			||||||
    const uint8_t *data, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_invite_get_cookie_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type);
 | 
					    ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(toxav_join_av_groupchat(tox, friendnumber, data, length, audio_callback, user_data) == 0,
 | 
					    ck_assert_msg(toxav_join_av_groupchat(autotox->tox, friend_number, cookie, length, audio_callback, user_data) == 0,
 | 
				
			||||||
                  "tox #%u: failed to join group", autotox->index);
 | 
					                  "tox #%u: failed to join group", autotox->index);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_connected(
 | 
					static void handle_conference_connected(
 | 
				
			||||||
    Tox *tox, uint32_t conference_number, void *user_data)
 | 
					    const Tox_Event_Conference_Connected *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) {
 | 
					    if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Invite err;
 | 
					    Tox_Err_Conference_Invite err;
 | 
				
			||||||
    tox_conference_invite(tox, 1, 0, &err);
 | 
					    tox_conference_invite(autotox->tox, 1, 0, &err);
 | 
				
			||||||
    ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
 | 
					    ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
 | 
				
			||||||
                  err);
 | 
					                  err);
 | 
				
			||||||
    printf("tox #%u: invited next friend\n", autotox->index);
 | 
					    printf("tox #%u: invited next friend\n", autotox->index);
 | 
				
			||||||
@@ -99,7 +108,7 @@ static void handle_conference_connected(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
 | 
					static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
 | 
				
			||||||
        bool *disconnected)
 | 
					        const bool *disconnected)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t num_disconnected = 0;
 | 
					    uint32_t num_disconnected = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,7 +147,10 @@ static void disconnect_toxes(uint32_t tox_count, AutoTox *autotoxes,
 | 
				
			|||||||
        do {
 | 
					        do {
 | 
				
			||||||
            for (uint32_t i = 0; i < tox_count; ++i) {
 | 
					            for (uint32_t i = 0; i < tox_count; ++i) {
 | 
				
			||||||
                if (!disconnect_now[i]) {
 | 
					                if (!disconnect_now[i]) {
 | 
				
			||||||
                    tox_iterate(autotoxes[i].tox, &autotoxes[i]);
 | 
					                    Tox_Err_Events_Iterate err;
 | 
				
			||||||
 | 
					                    Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
 | 
				
			||||||
 | 
					                    tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
 | 
				
			||||||
 | 
					                    tox_events_free(events);
 | 
				
			||||||
                    autotoxes[i].clock += 1000;
 | 
					                    autotoxes[i].clock += 1000;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -165,7 +177,7 @@ static bool all_connected_to_group(uint32_t tox_count, AutoTox *autotoxes)
 | 
				
			|||||||
 * returns a random index at which a list of booleans is false
 | 
					 * returns a random index at which a list of booleans is false
 | 
				
			||||||
 * (some such index is required to exist)
 | 
					 * (some such index is required to exist)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length)
 | 
					static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t index;
 | 
					    uint32_t index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -185,7 +197,7 @@ static bool all_got_audio(AutoTox *autotoxes, const bool *disabled)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (const State *)autotoxes[i].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (disabled[i] ^ (state->received_audio_num
 | 
					        if (disabled[i] ^ (state->received_audio_num
 | 
				
			||||||
                           != NUM_AV_GROUP_TOX - num_disabled - 1)) {
 | 
					                           != NUM_AV_GROUP_TOX - num_disabled - 1)) {
 | 
				
			||||||
@@ -291,7 +303,7 @@ static void do_audio(AutoTox *autotoxes, uint32_t iterations)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void run_conference_tests(AutoTox *autotoxes)
 | 
					static void run_conference_tests(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    bool disabled[NUM_AV_GROUP_TOX] = {0};
 | 
					    bool disabled[NUM_AV_GROUP_TOX] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -402,10 +414,10 @@ static void test_groupav(AutoTox *autotoxes)
 | 
				
			|||||||
    const time_t test_start_time = time(nullptr);
 | 
					    const time_t test_start_time = time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
 | 
				
			||||||
        tox_callback_self_connection_status(autotoxes[i].tox, &handle_self_connection_status);
 | 
					        tox_events_callback_self_connection_status(autotoxes[i].dispatch, handle_self_connection_status);
 | 
				
			||||||
        tox_callback_friend_connection_status(autotoxes[i].tox, &handle_friend_connection_status);
 | 
					        tox_events_callback_friend_connection_status(autotoxes[i].dispatch, handle_friend_connection_status);
 | 
				
			||||||
        tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite);
 | 
					        tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
 | 
				
			||||||
        tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected);
 | 
					        tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX,
 | 
					    ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX,
 | 
				
			||||||
@@ -414,7 +426,6 @@ static void test_groupav(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend");
 | 
					    ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend");
 | 
				
			||||||
    ((State *)autotoxes[0].state)->invited_next = true;
 | 
					    ((State *)autotoxes[0].state)->invited_next = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    printf("waiting for invitations to be made\n");
 | 
					    printf("waiting for invitations to be made\n");
 | 
				
			||||||
    uint32_t invited_count = 0;
 | 
					    uint32_t invited_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,12 +12,16 @@ typedef struct State {
 | 
				
			|||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_invite(
 | 
					static void handle_conference_invite(
 | 
				
			||||||
    Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
 | 
					    const Tox_Event_Conference_Invite *event, void *user_data)
 | 
				
			||||||
    const uint8_t *cookie, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_invite_get_cookie_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
					    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
				
			||||||
            autotox->index, friend_number, type, (unsigned)length);
 | 
					            autotox->index, friend_number, type, (unsigned)length);
 | 
				
			||||||
    fprintf(stderr, "tox%u joining conference\n", autotox->index);
 | 
					    fprintf(stderr, "tox%u joining conference\n", autotox->index);
 | 
				
			||||||
@@ -26,7 +30,7 @@ static void handle_conference_invite(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (friend_number != -1) {
 | 
					    if (friend_number != -1) {
 | 
				
			||||||
        Tox_Err_Conference_Join err;
 | 
					        Tox_Err_Conference_Join err;
 | 
				
			||||||
        state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
 | 
					        state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
				
			||||||
                      "attempting to join the conference returned with an error: %d", err);
 | 
					                      "attempting to join the conference returned with an error: %d", err);
 | 
				
			||||||
        fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
 | 
					        fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
 | 
				
			||||||
@@ -37,8 +41,8 @@ static void handle_conference_invite(
 | 
				
			|||||||
static void conference_double_invite_test(AutoTox *autotoxes)
 | 
					static void conference_double_invite_test(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Conference callbacks.
 | 
					    // Conference callbacks.
 | 
				
			||||||
    tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite);
 | 
					    tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
 | 
				
			||||||
    tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite);
 | 
					    tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state[2];
 | 
					    State *state[2];
 | 
				
			||||||
    state[0] = (State *)autotoxes[0].state;
 | 
					    state[0] = (State *)autotoxes[0].state;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,15 +12,18 @@ typedef struct State {
 | 
				
			|||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_invite(
 | 
					static void handle_conference_invite(
 | 
				
			||||||
    Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
 | 
					    const Tox_Event_Conference_Invite *event, void *user_data)
 | 
				
			||||||
    const uint8_t *cookie, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_invite_get_cookie_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (friend_number != -1) {
 | 
					    if (friend_number != -1) {
 | 
				
			||||||
        Tox_Err_Conference_Join err;
 | 
					        Tox_Err_Conference_Join err;
 | 
				
			||||||
        state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
 | 
					        state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
				
			||||||
                      "attempting to join the conference returned with an error: %d", err);
 | 
					                      "attempting to join the conference returned with an error: %d", err);
 | 
				
			||||||
        fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference);
 | 
					        fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference);
 | 
				
			||||||
@@ -28,7 +31,7 @@ static void handle_conference_invite(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_connected(
 | 
					static void handle_conference_connected(
 | 
				
			||||||
    Tox *tox, uint32_t conference_number, void *user_data)
 | 
					    const Tox_Event_Conference_Connected *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
@@ -37,7 +40,7 @@ static void handle_conference_connected(
 | 
				
			|||||||
    state->connected = true;
 | 
					    state->connected = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void wait_connected(AutoTox *autotoxes, AutoTox *autotox, uint32_t friendnumber)
 | 
					static void wait_connected(AutoTox *autotoxes, const AutoTox *autotox, uint32_t friendnumber)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        iterate_all_wait(autotoxes, NUM_INVITE_MERGE_TOX, ITERATION_INTERVAL);
 | 
					        iterate_all_wait(autotoxes, NUM_INVITE_MERGE_TOX, ITERATION_INTERVAL);
 | 
				
			||||||
@@ -95,8 +98,8 @@ static void conference_invite_merge_test(AutoTox *autotoxes)
 | 
				
			|||||||
    // components will cause a split group to merge
 | 
					    // components will cause a split group to merge
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
 | 
					    for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
 | 
				
			||||||
        tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite);
 | 
					        tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
 | 
				
			||||||
        tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected);
 | 
					        tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state2 = (State *)autotoxes[2].state;
 | 
					    State *state2 = (State *)autotoxes[2].state;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,34 +13,39 @@ typedef struct State {
 | 
				
			|||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_invite(
 | 
					static void handle_conference_invite(
 | 
				
			||||||
    Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
 | 
					    const Tox_Event_Conference_Invite *event, void *user_data)
 | 
				
			||||||
    const uint8_t *cookie, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_invite_get_cookie_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
					    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
				
			||||||
            autotox->index, friend_number, type, (unsigned)length);
 | 
					            autotox->index, friend_number, type, (unsigned)length);
 | 
				
			||||||
    fprintf(stderr, "tox%u joining conference\n", autotox->index);
 | 
					    fprintf(stderr, "tox%u joining conference\n", autotox->index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Join err;
 | 
					    Tox_Err_Conference_Join err;
 | 
				
			||||||
    state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
 | 
					    state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
 | 
				
			||||||
    ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
					    ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
 | 
				
			||||||
                  "attempting to join the conference returned with an error: %d", err);
 | 
					                  "attempting to join the conference returned with an error: %d", err);
 | 
				
			||||||
    fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
 | 
					    fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
 | 
				
			||||||
    state->joined = true;
 | 
					    state->joined = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
 | 
					static void handle_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
 | 
				
			||||||
    fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n",
 | 
					    fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n",
 | 
				
			||||||
            autotox->index, conference_number);
 | 
					            autotox->index, conference_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Peer_Query err;
 | 
					    Tox_Err_Conference_Peer_Query err;
 | 
				
			||||||
    uint32_t const count = tox_conference_peer_count(tox, conference_number, &err);
 | 
					    uint32_t const count = tox_conference_peer_count(autotox->tox, conference_number, &err);
 | 
				
			||||||
    ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK,
 | 
					    ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK,
 | 
				
			||||||
                  "failed to get conference peer count: err = %d", err);
 | 
					                  "failed to get conference peer count: err = %d", err);
 | 
				
			||||||
    printf("tox%u has %u peers\n", autotox->index, count);
 | 
					    printf("tox%u has %u peers\n", autotox->index, count);
 | 
				
			||||||
@@ -75,10 +80,10 @@ static void rebuild_peer_list(Tox *tox)
 | 
				
			|||||||
static void conference_peer_nick_test(AutoTox *autotoxes)
 | 
					static void conference_peer_nick_test(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Conference callbacks.
 | 
					    // Conference callbacks.
 | 
				
			||||||
    tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite);
 | 
					    tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
 | 
				
			||||||
    tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite);
 | 
					    tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
 | 
				
			||||||
    tox_callback_conference_peer_list_changed(autotoxes[0].tox, handle_peer_list_changed);
 | 
					    tox_events_callback_conference_peer_list_changed(autotoxes[0].dispatch, handle_peer_list_changed);
 | 
				
			||||||
    tox_callback_conference_peer_list_changed(autotoxes[1].tox, handle_peer_list_changed);
 | 
					    tox_events_callback_conference_peer_list_changed(autotoxes[1].dispatch, handle_peer_list_changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set the names of the toxes.
 | 
					    // Set the names of the toxes.
 | 
				
			||||||
    tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr);
 | 
					    tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,11 +3,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "../testing/misc_tools.h"
 | 
					#include "../testing/misc_tools.h"
 | 
				
			||||||
#include "../toxcore/tox.h"
 | 
					#include "../toxcore/tox.h"
 | 
				
			||||||
 | 
					#include "../toxcore/tox_dispatch.h"
 | 
				
			||||||
 | 
					#include "../toxcore/tox_events.h"
 | 
				
			||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
#include "check_compat.h"
 | 
					#include "check_compat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct State {
 | 
					typedef struct State {
 | 
				
			||||||
    uint32_t id;
 | 
					    uint32_t id;
 | 
				
			||||||
 | 
					    Tox *tox;
 | 
				
			||||||
    bool self_online;
 | 
					    bool self_online;
 | 
				
			||||||
    bool friend_online;
 | 
					    bool friend_online;
 | 
				
			||||||
    bool invited_next;
 | 
					    bool invited_next;
 | 
				
			||||||
@@ -20,46 +23,57 @@ typedef struct State {
 | 
				
			|||||||
    uint32_t peers;
 | 
					    uint32_t peers;
 | 
				
			||||||
} State;
 | 
					} State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_self_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data)
 | 
					static void handle_self_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
 | 
				
			||||||
    fprintf(stderr, "self_connection_status(#%u, %d, _)\n", state->id, connection_status);
 | 
					    fprintf(stderr, "self_connection_status(#%u, %d, _)\n", state->id, connection_status);
 | 
				
			||||||
    state->self_online = connection_status != TOX_CONNECTION_NONE;
 | 
					    state->self_online = connection_status != TOX_CONNECTION_NONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_friend_connection_status(Tox *tox, uint32_t friend_number, Tox_Connection connection_status,
 | 
					static void handle_friend_connection_status(const Tox_Event_Friend_Connection_Status *event,
 | 
				
			||||||
        void *user_data)
 | 
					        void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_friend_connection_status_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
 | 
				
			||||||
    fprintf(stderr, "handle_friend_connection_status(#%u, %u, %d, _)\n", state->id, friend_number, connection_status);
 | 
					    fprintf(stderr, "handle_friend_connection_status(#%u, %u, %d, _)\n", state->id, friend_number, connection_status);
 | 
				
			||||||
    state->friend_online = connection_status != TOX_CONNECTION_NONE;
 | 
					    state->friend_online = connection_status != TOX_CONNECTION_NONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_invite(Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie,
 | 
					static void handle_conference_invite(const Tox_Event_Conference_Invite *event, void *user_data)
 | 
				
			||||||
                                     size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_invite_get_cookie_length(event);
 | 
				
			||||||
    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
					    fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
 | 
				
			||||||
            state->id, friend_number, type, (unsigned)length);
 | 
					            state->id, friend_number, type, (unsigned)length);
 | 
				
			||||||
    fprintf(stderr, "tox%u joining conference\n", state->id);
 | 
					    fprintf(stderr, "tox%u joining conference\n", state->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Tox_Err_Conference_Join err;
 | 
					        Tox_Err_Conference_Join err;
 | 
				
			||||||
        state->conference = tox_conference_join(tox, friend_number, cookie, length, &err);
 | 
					        state->conference = tox_conference_join(state->tox, friend_number, cookie, length, &err);
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "failed to join a conference: err = %d", err);
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "failed to join a conference: err = %d", err);
 | 
				
			||||||
        fprintf(stderr, "tox%u Joined conference %u\n", state->id, state->conference);
 | 
					        fprintf(stderr, "tox%u Joined conference %u\n", state->id, state->conference);
 | 
				
			||||||
        state->joined = true;
 | 
					        state->joined = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_message(Tox *tox, uint32_t conference_number, uint32_t peer_number,
 | 
					static void handle_conference_message(const Tox_Event_Conference_Message *event, void *user_data)
 | 
				
			||||||
                                      Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t conference_number = tox_event_conference_message_get_conference_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_number = tox_event_conference_message_get_peer_number(event);
 | 
				
			||||||
 | 
					    const Tox_Message_Type type = tox_event_conference_message_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_conference_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_conference_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "handle_conference_message(#%u, %u, %u, %d, uint8_t[%u], _)\n",
 | 
					    fprintf(stderr, "handle_conference_message(#%u, %u, %u, %d, uint8_t[%u], _)\n",
 | 
				
			||||||
            state->id, conference_number, peer_number, type, (unsigned)length);
 | 
					            state->id, conference_number, peer_number, type, (unsigned)length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,15 +81,16 @@ static void handle_conference_message(Tox *tox, uint32_t conference_number, uint
 | 
				
			|||||||
    state->received = true;
 | 
					    state->received = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
 | 
					static void handle_conference_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
 | 
				
			||||||
    fprintf(stderr, "handle_conference_peer_list_changed(#%u, %u, _)\n",
 | 
					    fprintf(stderr, "handle_conference_peer_list_changed(#%u, %u, _)\n",
 | 
				
			||||||
            state->id, conference_number);
 | 
					            state->id, conference_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Peer_Query err;
 | 
					    Tox_Err_Conference_Peer_Query err;
 | 
				
			||||||
    uint32_t count = tox_conference_peer_count(tox, conference_number, &err);
 | 
					    uint32_t count = tox_conference_peer_count(state->tox, conference_number, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
 | 
					    if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
 | 
				
			||||||
        fprintf(stderr, "ERROR: %d\n", err);
 | 
					        fprintf(stderr, "ERROR: %d\n", err);
 | 
				
			||||||
@@ -86,14 +101,14 @@ static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_nu
 | 
				
			|||||||
    state->peers = count;
 | 
					    state->peers = count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_conference_connected(Tox *tox, uint32_t conference_number, void *user_data)
 | 
					static void handle_conference_connected(const Tox_Event_Conference_Connected *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    State *state = (State *)user_data;
 | 
					    State *state = (State *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We're tox2, so now we invite tox3.
 | 
					    // We're tox2, so now we invite tox3.
 | 
				
			||||||
    if (state->id == 2 && !state->invited_next) {
 | 
					    if (state->id == 2 && !state->invited_next) {
 | 
				
			||||||
        Tox_Err_Conference_Invite err;
 | 
					        Tox_Err_Conference_Invite err;
 | 
				
			||||||
        tox_conference_invite(tox, 1, state->conference, &err);
 | 
					        tox_conference_invite(state->tox, 1, state->conference, &err);
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox2 failed to invite tox3: err = %d", err);
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox2 failed to invite tox3: err = %d", err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state->invited_next = true;
 | 
					        state->invited_next = true;
 | 
				
			||||||
@@ -101,6 +116,27 @@ static void handle_conference_connected(Tox *tox, uint32_t conference_number, vo
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void iterate_one(
 | 
				
			||||||
 | 
					    Tox *tox, State *state, const Tox_Dispatch *dispatch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Tox_Err_Events_Iterate err;
 | 
				
			||||||
 | 
					    Tox_Events *events = tox_events_iterate(tox, true, &err);
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					    tox_dispatch_invoke(dispatch, events, state);
 | 
				
			||||||
 | 
					    tox_events_free(events);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void iterate3_wait(
 | 
				
			||||||
 | 
					    State *state1, State *state2, State *state3,
 | 
				
			||||||
 | 
					    const Tox_Dispatch *dispatch, int interval)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    iterate_one(state1->tox, state1, dispatch);
 | 
				
			||||||
 | 
					    iterate_one(state2->tox, state2, dispatch);
 | 
				
			||||||
 | 
					    iterate_one(state3->tox, state3, dispatch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c_sleep(interval);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
					    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
				
			||||||
@@ -110,64 +146,51 @@ int main(void)
 | 
				
			|||||||
    State state3 = {3};
 | 
					    State state3 = {3};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create toxes.
 | 
					    // Create toxes.
 | 
				
			||||||
    Tox *tox1 = tox_new_log(nullptr, nullptr, &state1.id);
 | 
					    state1.tox = tox_new_log(nullptr, nullptr, &state1.id);
 | 
				
			||||||
    Tox *tox2 = tox_new_log(nullptr, nullptr, &state2.id);
 | 
					    state2.tox = tox_new_log(nullptr, nullptr, &state2.id);
 | 
				
			||||||
    Tox *tox3 = tox_new_log(nullptr, nullptr, &state3.id);
 | 
					    state3.tox = tox_new_log(nullptr, nullptr, &state3.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_init(state1.tox);
 | 
				
			||||||
 | 
					    tox_events_init(state2.tox);
 | 
				
			||||||
 | 
					    tox_events_init(state3.tox);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox1 <-> tox2, tox2 <-> tox3
 | 
					    // tox1 <-> tox2, tox2 <-> tox3
 | 
				
			||||||
    uint8_t key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    tox_self_get_public_key(tox2, key);
 | 
					    tox_self_get_public_key(state2.tox, key);
 | 
				
			||||||
    tox_friend_add_norequest(tox1, key, nullptr);  // tox1 -> tox2
 | 
					    tox_friend_add_norequest(state1.tox, key, nullptr);  // tox1 -> tox2
 | 
				
			||||||
    tox_self_get_public_key(tox1, key);
 | 
					    tox_self_get_public_key(state1.tox, key);
 | 
				
			||||||
    tox_friend_add_norequest(tox2, key, nullptr);  // tox2 -> tox1
 | 
					    tox_friend_add_norequest(state2.tox, key, nullptr);  // tox2 -> tox1
 | 
				
			||||||
    tox_self_get_public_key(tox3, key);
 | 
					    tox_self_get_public_key(state3.tox, key);
 | 
				
			||||||
    tox_friend_add_norequest(tox2, key, nullptr);  // tox2 -> tox3
 | 
					    tox_friend_add_norequest(state2.tox, key, nullptr);  // tox2 -> tox3
 | 
				
			||||||
    tox_self_get_public_key(tox2, key);
 | 
					    tox_self_get_public_key(state2.tox, key);
 | 
				
			||||||
    tox_friend_add_norequest(tox3, key, nullptr);  // tox3 -> tox2
 | 
					    tox_friend_add_norequest(state3.tox, key, nullptr);  // tox3 -> tox2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("bootstrapping tox2 and tox3 off tox1\n");
 | 
					    printf("bootstrapping tox2 and tox3 off tox1\n");
 | 
				
			||||||
    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    tox_self_get_dht_id(tox1, dht_key);
 | 
					    tox_self_get_dht_id(state1.tox, dht_key);
 | 
				
			||||||
    const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr);
 | 
					    const uint16_t dht_port = tox_self_get_udp_port(state1.tox, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
 | 
					    tox_bootstrap(state2.tox, "localhost", dht_port, dht_key, nullptr);
 | 
				
			||||||
    tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
 | 
					    tox_bootstrap(state3.tox, "localhost", dht_port, dht_key, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Connection callbacks.
 | 
					    // Connection callbacks.
 | 
				
			||||||
    tox_callback_self_connection_status(tox1, handle_self_connection_status);
 | 
					    tox_events_callback_self_connection_status(dispatch, handle_self_connection_status);
 | 
				
			||||||
    tox_callback_self_connection_status(tox2, handle_self_connection_status);
 | 
					    tox_events_callback_friend_connection_status(dispatch, handle_friend_connection_status);
 | 
				
			||||||
    tox_callback_self_connection_status(tox3, handle_self_connection_status);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tox_callback_friend_connection_status(tox1, handle_friend_connection_status);
 | 
					 | 
				
			||||||
    tox_callback_friend_connection_status(tox2, handle_friend_connection_status);
 | 
					 | 
				
			||||||
    tox_callback_friend_connection_status(tox3, handle_friend_connection_status);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Conference callbacks.
 | 
					    // Conference callbacks.
 | 
				
			||||||
    tox_callback_conference_invite(tox1, handle_conference_invite);
 | 
					    tox_events_callback_conference_invite(dispatch, handle_conference_invite);
 | 
				
			||||||
    tox_callback_conference_invite(tox2, handle_conference_invite);
 | 
					    tox_events_callback_conference_connected(dispatch, handle_conference_connected);
 | 
				
			||||||
    tox_callback_conference_invite(tox3, handle_conference_invite);
 | 
					    tox_events_callback_conference_message(dispatch, handle_conference_message);
 | 
				
			||||||
 | 
					    tox_events_callback_conference_peer_list_changed(dispatch, handle_conference_peer_list_changed);
 | 
				
			||||||
    tox_callback_conference_connected(tox1, handle_conference_connected);
 | 
					 | 
				
			||||||
    tox_callback_conference_connected(tox2, handle_conference_connected);
 | 
					 | 
				
			||||||
    tox_callback_conference_connected(tox3, handle_conference_connected);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tox_callback_conference_message(tox1, handle_conference_message);
 | 
					 | 
				
			||||||
    tox_callback_conference_message(tox2, handle_conference_message);
 | 
					 | 
				
			||||||
    tox_callback_conference_message(tox3, handle_conference_message);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tox_callback_conference_peer_list_changed(tox1, handle_conference_peer_list_changed);
 | 
					 | 
				
			||||||
    tox_callback_conference_peer_list_changed(tox2, handle_conference_peer_list_changed);
 | 
					 | 
				
			||||||
    tox_callback_conference_peer_list_changed(tox3, handle_conference_peer_list_changed);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Wait for self connection.
 | 
					    // Wait for self connection.
 | 
				
			||||||
    fprintf(stderr, "Waiting for toxes to come online\n");
 | 
					    fprintf(stderr, "Waiting for toxes to come online\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, &state1);
 | 
					        iterate3_wait(&state1, &state2, &state3, dispatch, 100);
 | 
				
			||||||
        tox_iterate(tox2, &state2);
 | 
					 | 
				
			||||||
        tox_iterate(tox3, &state3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(100);
 | 
					 | 
				
			||||||
    } while (!state1.self_online || !state2.self_online || !state3.self_online);
 | 
					    } while (!state1.self_online || !state2.self_online || !state3.self_online);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Toxes are online\n");
 | 
					    fprintf(stderr, "Toxes are online\n");
 | 
				
			||||||
@@ -176,11 +199,7 @@ int main(void)
 | 
				
			|||||||
    fprintf(stderr, "Waiting for friends to connect\n");
 | 
					    fprintf(stderr, "Waiting for friends to connect\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, &state1);
 | 
					        iterate3_wait(&state1, &state2, &state3, dispatch, 100);
 | 
				
			||||||
        tox_iterate(tox2, &state2);
 | 
					 | 
				
			||||||
        tox_iterate(tox3, &state3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(100);
 | 
					 | 
				
			||||||
    } while (!state1.friend_online || !state2.friend_online || !state3.friend_online);
 | 
					    } while (!state1.friend_online || !state2.friend_online || !state3.friend_online);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Friends are connected\n");
 | 
					    fprintf(stderr, "Friends are connected\n");
 | 
				
			||||||
@@ -188,7 +207,7 @@ int main(void)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        // Create new conference, tox1 is the founder.
 | 
					        // Create new conference, tox1 is the founder.
 | 
				
			||||||
        Tox_Err_Conference_New err;
 | 
					        Tox_Err_Conference_New err;
 | 
				
			||||||
        state1.conference = tox_conference_new(tox1, &err);
 | 
					        state1.conference = tox_conference_new(state1.tox, &err);
 | 
				
			||||||
        state1.joined = true;
 | 
					        state1.joined = true;
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "failed to create a conference: err = %d", err);
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "failed to create a conference: err = %d", err);
 | 
				
			||||||
        fprintf(stderr, "Created conference: id = %u\n", state1.conference);
 | 
					        fprintf(stderr, "Created conference: id = %u\n", state1.conference);
 | 
				
			||||||
@@ -197,7 +216,7 @@ int main(void)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        // Invite friend.
 | 
					        // Invite friend.
 | 
				
			||||||
        Tox_Err_Conference_Invite err;
 | 
					        Tox_Err_Conference_Invite err;
 | 
				
			||||||
        tox_conference_invite(tox1, 0, state1.conference, &err);
 | 
					        tox_conference_invite(state1.tox, 0, state1.conference, &err);
 | 
				
			||||||
        ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "failed to invite a friend: err = %d", err);
 | 
					        ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "failed to invite a friend: err = %d", err);
 | 
				
			||||||
        state1.invited_next = true;
 | 
					        state1.invited_next = true;
 | 
				
			||||||
        fprintf(stderr, "tox1 invited tox2\n");
 | 
					        fprintf(stderr, "tox1 invited tox2\n");
 | 
				
			||||||
@@ -206,11 +225,7 @@ int main(void)
 | 
				
			|||||||
    fprintf(stderr, "Waiting for invitation to arrive\n");
 | 
					    fprintf(stderr, "Waiting for invitation to arrive\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, &state1);
 | 
					        iterate3_wait(&state1, &state2, &state3, dispatch, 100);
 | 
				
			||||||
        tox_iterate(tox2, &state2);
 | 
					 | 
				
			||||||
        tox_iterate(tox3, &state3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(100);
 | 
					 | 
				
			||||||
    } while (!state1.joined || !state2.joined || !state3.joined);
 | 
					    } while (!state1.joined || !state2.joined || !state3.joined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Invitations accepted\n");
 | 
					    fprintf(stderr, "Invitations accepted\n");
 | 
				
			||||||
@@ -218,11 +233,7 @@ int main(void)
 | 
				
			|||||||
    fprintf(stderr, "Waiting for peers to come online\n");
 | 
					    fprintf(stderr, "Waiting for peers to come online\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, &state1);
 | 
					        iterate3_wait(&state1, &state2, &state3, dispatch, 100);
 | 
				
			||||||
        tox_iterate(tox2, &state2);
 | 
					 | 
				
			||||||
        tox_iterate(tox3, &state3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(100);
 | 
					 | 
				
			||||||
    } while (state1.peers == 0 || state2.peers == 0 || state3.peers == 0);
 | 
					    } while (state1.peers == 0 || state2.peers == 0 || state3.peers == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "All peers are online\n");
 | 
					    fprintf(stderr, "All peers are online\n");
 | 
				
			||||||
@@ -230,7 +241,7 @@ int main(void)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        fprintf(stderr, "tox1 sends a message to the group: \"hello!\"\n");
 | 
					        fprintf(stderr, "tox1 sends a message to the group: \"hello!\"\n");
 | 
				
			||||||
        Tox_Err_Conference_Send_Message err;
 | 
					        Tox_Err_Conference_Send_Message err;
 | 
				
			||||||
        tox_conference_send_message(tox1, state1.conference, TOX_MESSAGE_TYPE_NORMAL,
 | 
					        tox_conference_send_message(state1.tox, state1.conference, TOX_MESSAGE_TYPE_NORMAL,
 | 
				
			||||||
                                    (const uint8_t *)"hello!", 7, &err);
 | 
					                                    (const uint8_t *)"hello!", 7, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (err != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
 | 
					        if (err != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
 | 
				
			||||||
@@ -242,18 +253,16 @@ int main(void)
 | 
				
			|||||||
    fprintf(stderr, "Waiting for messages to arrive\n");
 | 
					    fprintf(stderr, "Waiting for messages to arrive\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, &state1);
 | 
					        iterate3_wait(&state1, &state2, &state3, dispatch, 100);
 | 
				
			||||||
        tox_iterate(tox2, &state2);
 | 
					 | 
				
			||||||
        tox_iterate(tox3, &state3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(100);
 | 
					        c_sleep(100);
 | 
				
			||||||
    } while (!state2.received || !state3.received);
 | 
					    } while (!state2.received || !state3.received);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Messages received. Test complete.\n");
 | 
					    fprintf(stderr, "Messages received. Test complete.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_kill(tox3);
 | 
					    tox_dispatch_free(dispatch);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(state3.tox);
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(state2.tox);
 | 
				
			||||||
 | 
					    tox_kill(state1.tox);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,13 +56,13 @@ static void handle_conference_invite(
 | 
				
			|||||||
    ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type);
 | 
					    ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Join err;
 | 
					    Tox_Err_Conference_Join err;
 | 
				
			||||||
    uint32_t g_num = tox_conference_join(tox, friendnumber, data, length, &err);
 | 
					    uint32_t g_num = tox_conference_join(autotox->tox, friendnumber, data, length, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err);
 | 
					    ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err);
 | 
				
			||||||
    ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index);
 | 
					    ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Try joining again. We should only be allowed to join once.
 | 
					    // Try joining again. We should only be allowed to join once.
 | 
				
			||||||
    tox_conference_join(tox, friendnumber, data, length, &err);
 | 
					    tox_conference_join(autotox->tox, friendnumber, data, length, &err);
 | 
				
			||||||
    ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK,
 | 
					    ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK,
 | 
				
			||||||
                  "tox #%u: joining groupchat twice should be impossible.", autotox->index);
 | 
					                  "tox #%u: joining groupchat twice should be impossible.", autotox->index);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -73,12 +73,12 @@ static void handle_conference_connected(
 | 
				
			|||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) {
 | 
					    if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Conference_Invite err;
 | 
					    Tox_Err_Conference_Invite err;
 | 
				
			||||||
    tox_conference_invite(tox, 1, 0, &err);
 | 
					    tox_conference_invite(autotox->tox, 1, 0, &err);
 | 
				
			||||||
    ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
 | 
					    ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
 | 
				
			||||||
                  err);
 | 
					                  err);
 | 
				
			||||||
    printf("tox #%u: invited next friend\n", autotox->index);
 | 
					    printf("tox #%u: invited next friend\n", autotox->index);
 | 
				
			||||||
@@ -97,7 +97,7 @@ static void handle_conference_message(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
 | 
					static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
 | 
				
			||||||
        bool *disconnected)
 | 
					        const bool *disconnected)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t num_disconnected = 0;
 | 
					    uint32_t num_disconnected = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,12 +174,11 @@ static bool names_propagated(uint32_t tox_count, AutoTox *autotoxes)
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * returns a random index at which a list of booleans is false
 | 
					 * returns a random index at which a list of booleans is false
 | 
				
			||||||
 * (some such index is required to exist)
 | 
					 * (some such index is required to exist)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length)
 | 
					static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t index;
 | 
					    uint32_t index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -192,7 +191,7 @@ static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void run_conference_tests(AutoTox *autotoxes)
 | 
					static void run_conference_tests(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    /* disabling name change propagation check for now, as it occasionally
 | 
					    /* disabling name change propagation check for now, as it occasionally
 | 
				
			||||||
     * fails due to disconnections too short to trigger freezing */
 | 
					     * fails due to disconnections too short to trigger freezing */
 | 
				
			||||||
@@ -357,7 +356,6 @@ static void test_many_group(AutoTox *autotoxes)
 | 
				
			|||||||
                                           nullptr) != 0,
 | 
					                                           nullptr) != 0,
 | 
				
			||||||
                  "failed to set group title");
 | 
					                  "failed to set group title");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    printf("waiting for invitations to be made\n");
 | 
					    printf("waiting for invitations to be made\n");
 | 
				
			||||||
    uint32_t invited_count = 0;
 | 
					    uint32_t invited_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -435,6 +433,7 @@ int main(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Run_Auto_Options options = default_run_auto_options();
 | 
					    Run_Auto_Options options = default_run_auto_options();
 | 
				
			||||||
    options.graph = GRAPH_LINEAR;
 | 
					    options.graph = GRAPH_LINEAR;
 | 
				
			||||||
 | 
					    options.events = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options);
 | 
					    run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -125,7 +125,7 @@ static void test_fast_known(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_endtoend(void)
 | 
					static void test_endtoend(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Test 100 random messages and keypairs
 | 
					    // Test 100 random messages and keypairs
 | 
				
			||||||
@@ -192,7 +192,7 @@ static void test_endtoend(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_large_data(void)
 | 
					static void test_large_data(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    uint8_t k[CRYPTO_SHARED_KEY_SIZE];
 | 
					    uint8_t k[CRYPTO_SHARED_KEY_SIZE];
 | 
				
			||||||
    uint8_t n[CRYPTO_NONCE_SIZE];
 | 
					    uint8_t n[CRYPTO_NONCE_SIZE];
 | 
				
			||||||
@@ -236,7 +236,7 @@ static void test_large_data(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_large_data_symmetric(void)
 | 
					static void test_large_data_symmetric(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    uint8_t k[CRYPTO_SYMMETRIC_KEY_SIZE];
 | 
					    uint8_t k[CRYPTO_SYMMETRIC_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -271,10 +271,10 @@ static void test_large_data_symmetric(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_very_large_data(void)
 | 
					static void test_very_large_data(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
 | 
					    const uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
 | 
				
			||||||
    uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE];
 | 
					    uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    uint8_t sk[CRYPTO_SECRET_KEY_SIZE];
 | 
					    uint8_t sk[CRYPTO_SECRET_KEY_SIZE];
 | 
				
			||||||
    crypto_new_keypair(rng, pk, sk);
 | 
					    crypto_new_keypair(rng, pk, sk);
 | 
				
			||||||
@@ -316,7 +316,7 @@ static void increment_nonce_number_cmp(uint8_t *nonce, uint32_t num)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_increment_nonce(void)
 | 
					static void test_increment_nonce(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t n[CRYPTO_NONCE_SIZE];
 | 
					    uint8_t n[CRYPTO_NONCE_SIZE];
 | 
				
			||||||
 
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								external/toxcore/c-toxcore/auto_tests/data/save.tox.little
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								external/toxcore/c-toxcore/auto_tests/data/save.tox.little
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -72,12 +72,16 @@ static bool all_nodes_crawled(const AutoTox *autotoxes, uint32_t num_toxes, uint
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, void *user_data)
 | 
					static void getnodes_response_cb(const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert(user_data != nullptr);
 | 
					    ck_assert(user_data != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotoxes = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotoxes->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_dht_get_nodes_response_get_public_key(event);
 | 
				
			||||||
 | 
					    const char *ip = (const char *)tox_event_dht_get_nodes_response_get_ip(event);
 | 
				
			||||||
 | 
					    const uint16_t port = tox_event_dht_get_nodes_response_get_port(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (node_crawled(state->nodes, state->num_nodes, public_key)) {
 | 
					    if (node_crawled(state->nodes, state->num_nodes, public_key)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@@ -97,7 +101,7 @@ static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // ask new node to give us their close nodes to every public key
 | 
					    // ask new node to give us their close nodes to every public key
 | 
				
			||||||
    for (size_t i = 0; i < NUM_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_TOXES; ++i) {
 | 
				
			||||||
        tox_dht_get_nodes(tox, public_key, ip, port, state->public_key_list[i], nullptr);
 | 
					        tox_dht_get_nodes(autotox->tox, public_key, ip, port, state->public_key_list[i], nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,13 +125,12 @@ static void test_dht_getnodes(AutoTox *autotoxes)
 | 
				
			|||||||
        ck_assert(public_key_list[i] != nullptr);
 | 
					        ck_assert(public_key_list[i] != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_self_get_dht_id(autotoxes[i].tox, public_key_list[i]);
 | 
					        tox_self_get_dht_id(autotoxes[i].tox, public_key_list[i]);
 | 
				
			||||||
        tox_callback_dht_get_nodes_response(autotoxes[i].tox, getnodes_response_cb);
 | 
					        tox_events_callback_dht_get_nodes_response(autotoxes[i].dispatch, getnodes_response_cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        printf("Peer %zu dht closenode count total/announce-capable: %d/%d\n",
 | 
					        printf("Peer %zu dht closenode count total/announce-capable: %d/%d\n",
 | 
				
			||||||
               i,
 | 
					               i,
 | 
				
			||||||
               tox_dht_get_num_closelist(autotoxes[i].tox),
 | 
					               tox_dht_get_num_closelist(autotoxes[i].tox),
 | 
				
			||||||
            tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox)
 | 
					               tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox));
 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (!all_nodes_crawled(autotoxes, NUM_TOXES, public_key_list)) {
 | 
					    while (!all_nodes_crawled(autotoxes, NUM_TOXES, public_key_list)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -168,7 +168,7 @@ static void test_keys(void)
 | 
				
			|||||||
    ck_assert(encrypted2a != nullptr);
 | 
					    ck_assert(encrypted2a != nullptr);
 | 
				
			||||||
    uint8_t *in_plaintext2a = (uint8_t *)malloc(plaintext_length2a);
 | 
					    uint8_t *in_plaintext2a = (uint8_t *)malloc(plaintext_length2a);
 | 
				
			||||||
    ck_assert(in_plaintext2a != nullptr);
 | 
					    ck_assert(in_plaintext2a != nullptr);
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    random_bytes(rng, in_plaintext2a, plaintext_length2a);
 | 
					    random_bytes(rng, in_plaintext2a, plaintext_length2a);
 | 
				
			||||||
    ret = tox_pass_encrypt(in_plaintext2a, plaintext_length2a, key_char, 12, encrypted2a, &encerr);
 | 
					    ret = tox_pass_encrypt(in_plaintext2a, plaintext_length2a, key_char, 12, encrypted2a, &encerr);
 | 
				
			||||||
@@ -184,7 +184,6 @@ static void test_keys(void)
 | 
				
			|||||||
    free(in_plaintext2a);
 | 
					    free(in_plaintext2a);
 | 
				
			||||||
    free(out_plaintext2a);
 | 
					    free(out_plaintext2a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
 | 
					    uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
 | 
				
			||||||
    ret = tox_pass_encrypt(string, 44, key_char, 12, encrypted2, &encerr);
 | 
					    ret = tox_pass_encrypt(string, 44, key_char, 12, encrypted2, &encerr);
 | 
				
			||||||
    ck_assert_msg(ret, "generic failure 3: %d", encerr);
 | 
					    ck_assert_msg(ret, "generic failure 3: %d", encerr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
 | 
					    ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
 | 
					    const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
 | 
					    ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,7 +126,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
 | 
				
			|||||||
    Tox_Err_File_Send_Chunk error;
 | 
					    Tox_Err_File_Send_Chunk error;
 | 
				
			||||||
    tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
 | 
					    tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
 | 
					    ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
 | 
				
			||||||
                  "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
 | 
					                  "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -134,7 +133,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
 | 
				
			|||||||
    sending_pos += length;
 | 
					    sending_pos += length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static uint8_t num;
 | 
					static uint8_t num;
 | 
				
			||||||
static bool file_recv;
 | 
					static bool file_recv;
 | 
				
			||||||
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
 | 
					static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
 | 
				
			||||||
@@ -209,7 +207,6 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    file_accepted = file_size = sendf_ok = size_recv = 0;
 | 
					    file_accepted = file_size = sendf_ok = size_recv = 0;
 | 
				
			||||||
    file_recv = 0;
 | 
					    file_recv = 0;
 | 
				
			||||||
    max_sending = UINT64_MAX;
 | 
					    max_sending = UINT64_MAX;
 | 
				
			||||||
    uint64_t totalf_size = 100 * 1024 * 1024;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Starting file streaming transfer test.\n");
 | 
					    printf("Starting file streaming transfer test.\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -224,7 +221,7 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
 | 
					    tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
 | 
				
			||||||
    tox_callback_file_recv_control(tox3, file_print_control);
 | 
					    tox_callback_file_recv_control(tox3, file_print_control);
 | 
				
			||||||
    tox_callback_file_recv(tox3, tox_file_receive);
 | 
					    tox_callback_file_recv(tox3, tox_file_receive);
 | 
				
			||||||
    totalf_size = UINT64_MAX;
 | 
					    const uint64_t totalf_size = UINT64_MAX;
 | 
				
			||||||
    Tox_File_Number fnum = tox_file_send(
 | 
					    Tox_File_Number fnum = tox_file_send(
 | 
				
			||||||
                               tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
 | 
					                               tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
 | 
				
			||||||
                               (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
 | 
					                               (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,10 +26,16 @@
 | 
				
			|||||||
#define TOX_LOCALHOST "127.0.0.1"
 | 
					#define TOX_LOCALHOST "127.0.0.1"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Tox *tox = (Tox *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
 | 
					    if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
 | 
				
			||||||
        tox_friend_add_norequest(m, public_key, nullptr);
 | 
					        tox_friend_add_norequest(tox, public_key, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,9 +45,17 @@ static uint64_t sending_pos;
 | 
				
			|||||||
static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
 | 
					static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
 | 
				
			||||||
static uint32_t file_accepted;
 | 
					static uint32_t file_accepted;
 | 
				
			||||||
static uint64_t file_size;
 | 
					static uint64_t file_size;
 | 
				
			||||||
static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize,
 | 
					static void tox_file_receive(const Tox_Event_File_Recv *event, void *userdata)
 | 
				
			||||||
                             const uint8_t *filename, size_t filename_length, void *userdata)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Tox *state_tox = (Tox *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_file_recv_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint32_t file_number = tox_event_file_recv_get_file_number(event);
 | 
				
			||||||
 | 
					    const uint32_t kind = tox_event_file_recv_get_kind(event);
 | 
				
			||||||
 | 
					    const uint64_t filesize = tox_event_file_recv_get_file_size(event);
 | 
				
			||||||
 | 
					    const uint8_t *filename = tox_event_file_recv_get_filename(event);
 | 
				
			||||||
 | 
					    const size_t filename_length = tox_event_file_recv_get_filename_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind");
 | 
					    ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(filename_length == sizeof("Gentoo.exe")
 | 
					    ck_assert_msg(filename_length == sizeof("Gentoo.exe")
 | 
				
			||||||
@@ -49,11 +63,11 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint8_t file_id[TOX_FILE_ID_LENGTH];
 | 
					    uint8_t file_id[TOX_FILE_ID_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox_file_get_file_id(tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
 | 
					    ck_assert_msg(tox_file_get_file_id(state_tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
 | 
					    ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
 | 
					    const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
 | 
					    ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,7 +78,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Tox_Err_File_Seek err_s;
 | 
					        Tox_Err_File_Seek err_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ck_assert_msg(tox_file_seek(tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
 | 
					        ck_assert_msg(tox_file_seek(state_tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
 | 
					        ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,21 +88,24 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Tox_Err_File_Control error;
 | 
					    Tox_Err_File_Control error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
 | 
					    ck_assert_msg(tox_file_control(state_tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
 | 
				
			||||||
                  "tox_file_control failed. %i", error);
 | 
					                  "tox_file_control failed. %i", error);
 | 
				
			||||||
    ++file_accepted;
 | 
					    ++file_accepted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_File_Seek err_s;
 | 
					    Tox_Err_File_Seek err_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(!tox_file_seek(tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
 | 
					    ck_assert_msg(!tox_file_seek(state_tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
 | 
					    ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint32_t sendf_ok;
 | 
					static uint32_t sendf_ok;
 | 
				
			||||||
static void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control,
 | 
					static void file_print_control(const Tox_Event_File_Recv_Control *event,
 | 
				
			||||||
                               void *userdata)
 | 
					                               void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint32_t file_number = tox_event_file_recv_control_get_file_number(event);
 | 
				
			||||||
 | 
					    const Tox_File_Control control = tox_event_file_recv_control_get_control(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* First send file num is 0.*/
 | 
					    /* First send file num is 0.*/
 | 
				
			||||||
    if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
 | 
					    if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
 | 
				
			||||||
        sendf_ok = 1;
 | 
					        sendf_ok = 1;
 | 
				
			||||||
@@ -99,12 +116,18 @@ static uint64_t max_sending;
 | 
				
			|||||||
static bool m_send_reached;
 | 
					static bool m_send_reached;
 | 
				
			||||||
static uint8_t sending_num;
 | 
					static uint8_t sending_num;
 | 
				
			||||||
static bool file_sending_done;
 | 
					static bool file_sending_done;
 | 
				
			||||||
static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position,
 | 
					static void tox_file_chunk_request(const Tox_Event_File_Chunk_Request *event, void *user_data)
 | 
				
			||||||
                                   size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Tox *state_tox = (Tox *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_file_chunk_request_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint32_t file_number = tox_event_file_chunk_request_get_file_number(event);
 | 
				
			||||||
 | 
					    const uint64_t position = tox_event_file_chunk_request_get_position(event);
 | 
				
			||||||
 | 
					    size_t length = tox_event_file_chunk_request_get_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(sendf_ok, "didn't get resume control");
 | 
					    ck_assert_msg(sendf_ok, "didn't get resume control");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(sending_pos == position, "bad position %lu", (unsigned long)position);
 | 
					    ck_assert_msg(sending_pos == position, "bad position %lu (should be %lu)", (unsigned long)position, (unsigned long)sending_pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == 0) {
 | 
					    if (length == 0) {
 | 
				
			||||||
        ck_assert_msg(!file_sending_done, "file sending already done");
 | 
					        ck_assert_msg(!file_sending_done, "file sending already done");
 | 
				
			||||||
@@ -124,8 +147,7 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
 | 
				
			|||||||
    memset(f_data, sending_num, length);
 | 
					    memset(f_data, sending_num, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_File_Send_Chunk error;
 | 
					    Tox_Err_File_Send_Chunk error;
 | 
				
			||||||
    tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
 | 
					    tox_file_send_chunk(state_tox, friend_number, file_number, position, f_data, length, &error);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
 | 
					    ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
 | 
				
			||||||
                  "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
 | 
					                  "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
 | 
				
			||||||
@@ -134,12 +156,14 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
 | 
				
			|||||||
    sending_pos += length;
 | 
					    sending_pos += length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static uint8_t num;
 | 
					static uint8_t num;
 | 
				
			||||||
static bool file_recv;
 | 
					static bool file_recv;
 | 
				
			||||||
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
 | 
					static void write_file(const Tox_Event_File_Recv_Chunk *event, void *user_data)
 | 
				
			||||||
                       size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint64_t position = tox_event_file_recv_chunk_get_position(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_file_recv_chunk_get_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_file_recv_chunk_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(size_recv == position, "bad position");
 | 
					    ck_assert_msg(size_recv == position, "bad position");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == 0) {
 | 
					    if (length == 0) {
 | 
				
			||||||
@@ -156,6 +180,17 @@ static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uin
 | 
				
			|||||||
    size_recv += length;
 | 
					    size_recv += length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void iterate_and_dispatch(const Tox_Dispatch *dispatch, Tox *tox)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Tox_Err_Events_Iterate err;
 | 
				
			||||||
 | 
					    Tox_Events *events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    events = tox_events_iterate(tox, true, &err);
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					    tox_dispatch_invoke(dispatch, events, tox);
 | 
				
			||||||
 | 
					    tox_events_free(events);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void file_transfer_test(void)
 | 
					static void file_transfer_test(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    printf("Starting test: few_clients\n");
 | 
					    printf("Starting test: few_clients\n");
 | 
				
			||||||
@@ -171,7 +206,19 @@ static void file_transfer_test(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
 | 
					    ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_friend_request(tox2, accept_friend_request);
 | 
					    tox_events_init(tox1);
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					    tox_events_init(tox3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch1 != nullptr);
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch2 != nullptr);
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch3 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch3 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_callback_friend_request(dispatch2, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t address[TOX_ADDRESS_SIZE];
 | 
					    uint8_t address[TOX_ADDRESS_SIZE];
 | 
				
			||||||
    tox_self_get_address(tox2, address);
 | 
					    tox_self_get_address(tox2, address);
 | 
				
			||||||
    uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
 | 
					    uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
 | 
				
			||||||
@@ -187,9 +234,9 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    printf("Waiting for toxes to come online\n");
 | 
					    printf("Waiting for toxes to come online\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        iterate_and_dispatch(dispatch1, tox1);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					        iterate_and_dispatch(dispatch2, tox2);
 | 
				
			||||||
        tox_iterate(tox3, nullptr);
 | 
					        iterate_and_dispatch(dispatch3, tox3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        printf("Connections: self (%d, %d, %d), friends (%d, %d)\n",
 | 
					        printf("Connections: self (%d, %d, %d), friends (%d, %d)\n",
 | 
				
			||||||
               tox_self_get_connection_status(tox1),
 | 
					               tox_self_get_connection_status(tox1),
 | 
				
			||||||
@@ -210,11 +257,11 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    file_recv = 0;
 | 
					    file_recv = 0;
 | 
				
			||||||
    max_sending = UINT64_MAX;
 | 
					    max_sending = UINT64_MAX;
 | 
				
			||||||
    uint64_t f_time = time(nullptr);
 | 
					    uint64_t f_time = time(nullptr);
 | 
				
			||||||
    tox_callback_file_recv_chunk(tox3, write_file);
 | 
					    tox_events_callback_file_recv_chunk(dispatch3, write_file);
 | 
				
			||||||
    tox_callback_file_recv_control(tox2, file_print_control);
 | 
					    tox_events_callback_file_recv_control(dispatch2, file_print_control);
 | 
				
			||||||
    tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
 | 
					    tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
 | 
				
			||||||
    tox_callback_file_recv_control(tox3, file_print_control);
 | 
					    tox_events_callback_file_recv_control(dispatch3, file_print_control);
 | 
				
			||||||
    tox_callback_file_recv(tox3, tox_file_receive);
 | 
					    tox_events_callback_file_recv(dispatch3, tox_file_receive);
 | 
				
			||||||
    uint64_t totalf_size = 100 * 1024 * 1024;
 | 
					    uint64_t totalf_size = 100 * 1024 * 1024;
 | 
				
			||||||
    uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, (const uint8_t *)"Gentoo.exe",
 | 
					    uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, (const uint8_t *)"Gentoo.exe",
 | 
				
			||||||
                                  sizeof("Gentoo.exe"), nullptr);
 | 
					                                  sizeof("Gentoo.exe"), nullptr);
 | 
				
			||||||
@@ -231,9 +278,9 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    const size_t max_iterations = INT16_MAX;
 | 
					    const size_t max_iterations = INT16_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < max_iterations; i++) {
 | 
					    for (size_t i = 0; i < max_iterations; i++) {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        iterate_and_dispatch(dispatch1, tox1);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					        iterate_and_dispatch(dispatch2, tox2);
 | 
				
			||||||
        tox_iterate(tox3, nullptr);
 | 
					        iterate_and_dispatch(dispatch3, tox3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (file_sending_done) {
 | 
					        if (file_sending_done) {
 | 
				
			||||||
            ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
 | 
					            ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
 | 
				
			||||||
@@ -274,11 +321,11 @@ static void file_transfer_test(void)
 | 
				
			|||||||
    sendf_ok = 0;
 | 
					    sendf_ok = 0;
 | 
				
			||||||
    size_recv = 0;
 | 
					    size_recv = 0;
 | 
				
			||||||
    file_recv = 0;
 | 
					    file_recv = 0;
 | 
				
			||||||
    tox_callback_file_recv_chunk(tox3, write_file);
 | 
					    tox_events_callback_file_recv_chunk(dispatch3, write_file);
 | 
				
			||||||
    tox_callback_file_recv_control(tox2, file_print_control);
 | 
					    tox_events_callback_file_recv_control(dispatch2, file_print_control);
 | 
				
			||||||
    tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
 | 
					    tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
 | 
				
			||||||
    tox_callback_file_recv_control(tox3, file_print_control);
 | 
					    tox_events_callback_file_recv_control(dispatch3, file_print_control);
 | 
				
			||||||
    tox_callback_file_recv(tox3, tox_file_receive);
 | 
					    tox_events_callback_file_recv(dispatch3, tox_file_receive);
 | 
				
			||||||
    totalf_size = 0;
 | 
					    totalf_size = 0;
 | 
				
			||||||
    fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
 | 
					    fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
 | 
				
			||||||
                         (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
 | 
					                         (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
 | 
				
			||||||
@@ -298,9 +345,9 @@ static void file_transfer_test(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
 | 
					        c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        iterate_and_dispatch(dispatch1, tox1);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					        iterate_and_dispatch(dispatch2, tox2);
 | 
				
			||||||
        tox_iterate(tox3, nullptr);
 | 
					        iterate_and_dispatch(dispatch3, tox3);
 | 
				
			||||||
    } while (!file_sending_done);
 | 
					    } while (!file_sending_done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size
 | 
					    ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size
 | 
				
			||||||
@@ -312,9 +359,12 @@ static void file_transfer_test(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time);
 | 
					    printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_dispatch_free(dispatch3);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_dispatch_free(dispatch2);
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch1);
 | 
				
			||||||
    tox_kill(tox3);
 | 
					    tox_kill(tox3);
 | 
				
			||||||
 | 
					    tox_kill(tox2);
 | 
				
			||||||
 | 
					    tox_kill(tox1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,8 +47,8 @@ static void test_forwarded_request_cb(void *object, const IP_Port *forwarder,
 | 
				
			|||||||
                                      const uint8_t *sendback, uint16_t sendback_length,
 | 
					                                      const uint8_t *sendback, uint16_t sendback_length,
 | 
				
			||||||
                                      const uint8_t *data, uint16_t length, void *userdata)
 | 
					                                      const uint8_t *data, uint16_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Test_Data *test_data = (Test_Data *)object;
 | 
					    const Test_Data *test_data = (const Test_Data *)object;
 | 
				
			||||||
    uint8_t *index = (uint8_t *)userdata;
 | 
					    const uint8_t *index = (const uint8_t *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length != 12 || memcmp("hello:  ", data, 8) != 0) {
 | 
					    if (length != 12 || memcmp("hello:  ", data, 8) != 0) {
 | 
				
			||||||
        printf("[%u] got unexpected data of length %d\n", *index, length);
 | 
					        printf("[%u] got unexpected data of length %d\n", *index, length);
 | 
				
			||||||
@@ -66,7 +66,7 @@ static void test_forwarded_response_cb(void *object,
 | 
				
			|||||||
                                       const uint8_t *data, uint16_t length, void *userdata)
 | 
					                                       const uint8_t *data, uint16_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Test_Data *test_data = (Test_Data *)object;
 | 
					    Test_Data *test_data = (Test_Data *)object;
 | 
				
			||||||
    uint8_t *index = (uint8_t *)userdata;
 | 
					    const uint8_t *index = (const uint8_t *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length != 12 || memcmp("reply:  ", data, 8) != 0) {
 | 
					    if (length != 12 || memcmp("reply:  ", data, 8) != 0) {
 | 
				
			||||||
        printf("[%u] got unexpected data of length %d\n", *index, length);
 | 
					        printf("[%u] got unexpected data of length %d\n", *index, length);
 | 
				
			||||||
@@ -104,9 +104,9 @@ typedef struct Forwarding_Subtox {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp, uint32_t *index, uint16_t port)
 | 
					static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp, uint32_t *index, uint16_t port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox));
 | 
					    Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox));
 | 
				
			||||||
@@ -152,11 +152,11 @@ static void kill_forwarding_subtox(const Memory *mem, Forwarding_Subtox *subtox)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_forwarding(void)
 | 
					static void test_forwarding(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t index[NUM_FORWARDER];
 | 
					    uint32_t index[NUM_FORWARDER];
 | 
				
			||||||
@@ -317,7 +317,6 @@ static void test_forwarding(void)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_FORWARDER; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_FORWARDER; ++i) {
 | 
				
			||||||
        kill_forwarding_subtox(mem, subtoxes[i]);
 | 
					        kill_forwarding_subtox(mem, subtoxes[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -325,7 +324,6 @@ static void test_forwarding(void)
 | 
				
			|||||||
    tox_kill(relay);
 | 
					    tox_kill(relay);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
					    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,12 +22,18 @@ typedef struct State {
 | 
				
			|||||||
    bool unused;
 | 
					    bool unused;
 | 
				
			||||||
} State;
 | 
					} State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length,
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event,
 | 
				
			||||||
                                  void *userdata)
 | 
					                                  void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
 | 
					    ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
 | 
				
			||||||
                  "unexpected friend request message");
 | 
					                  "unexpected friend request message");
 | 
				
			||||||
    tox_friend_add_norequest(tox, public_key, nullptr);
 | 
					    tox_friend_add_norequest(autotox->tox, public_key, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_friend_request(AutoTox *autotoxes)
 | 
					static void test_friend_request(AutoTox *autotoxes)
 | 
				
			||||||
@@ -35,7 +41,7 @@ static void test_friend_request(AutoTox *autotoxes)
 | 
				
			|||||||
    const time_t con_time = time(nullptr);
 | 
					    const time_t con_time = time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("All toxes add tox1 as friend.\n");
 | 
					    printf("All toxes add tox1 as friend.\n");
 | 
				
			||||||
    tox_callback_friend_request(autotoxes[0].tox, accept_friend_request);
 | 
					    tox_events_callback_friend_request(autotoxes[0].dispatch, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t address[TOX_ADDRESS_SIZE];
 | 
					    uint8_t address[TOX_ADDRESS_SIZE];
 | 
				
			||||||
    tox_self_get_address(autotoxes[0].tox, address);
 | 
					    tox_self_get_address(autotoxes[0].tox, address);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,12 +15,36 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define FR_MESSAGE "Gentoo"
 | 
					#define FR_MESSAGE "Gentoo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length,
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event,
 | 
				
			||||||
                                  void *userdata)
 | 
					                                  void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Tox *state_tox = (Tox *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
 | 
					    ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
 | 
				
			||||||
                  "unexpected friend request message");
 | 
					                  "unexpected friend request message");
 | 
				
			||||||
    tox_friend_add_norequest(tox, public_key, nullptr);
 | 
					    tox_friend_add_norequest(state_tox, public_key, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void iterate2_wait(const Tox_Dispatch *dispatch, Tox *tox1, Tox *tox2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Tox_Err_Events_Iterate err;
 | 
				
			||||||
 | 
					    Tox_Events *events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    events = tox_events_iterate(tox1, true, &err);
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					    tox_dispatch_invoke(dispatch, events, tox1);
 | 
				
			||||||
 | 
					    tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					    tox_dispatch_invoke(dispatch, events, tox2);
 | 
				
			||||||
 | 
					    tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_friend_request(void)
 | 
					static void test_friend_request(void)
 | 
				
			||||||
@@ -33,6 +57,9 @@ static void test_friend_request(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
					    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_init(tox1);
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Bootstrapping tox2 off tox1.\n");
 | 
					    printf("Bootstrapping tox2 off tox1.\n");
 | 
				
			||||||
    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    tox_self_get_dht_id(tox1, dht_key);
 | 
					    tox_self_get_dht_id(tox1, dht_key);
 | 
				
			||||||
@@ -40,11 +67,11 @@ static void test_friend_request(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
 | 
					    tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					    ck_assert(dispatch != nullptr);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					    do {
 | 
				
			||||||
 | 
					        iterate2_wait(dispatch, tox1, tox2);
 | 
				
			||||||
    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
					    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
				
			||||||
             tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
 | 
					             tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +79,7 @@ static void test_friend_request(void)
 | 
				
			|||||||
    const time_t con_time = time(nullptr);
 | 
					    const time_t con_time = time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Tox1 adds tox2 as friend, tox2 accepts.\n");
 | 
					    printf("Tox1 adds tox2 as friend, tox2 accepts.\n");
 | 
				
			||||||
    tox_callback_friend_request(tox2, accept_friend_request);
 | 
					    tox_events_callback_friend_request(dispatch, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t address[TOX_ADDRESS_SIZE];
 | 
					    uint8_t address[TOX_ADDRESS_SIZE];
 | 
				
			||||||
    tox_self_get_address(tox2, address);
 | 
					    tox_self_get_address(tox2, address);
 | 
				
			||||||
@@ -61,16 +88,14 @@ static void test_friend_request(void)
 | 
				
			|||||||
    ck_assert_msg(test == 0, "failed to add friend error code: %u", test);
 | 
					    ck_assert_msg(test == 0, "failed to add friend error code: %u", test);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        iterate2_wait(dispatch, tox1, tox2);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					 | 
				
			||||||
    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
					    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
				
			||||||
             tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
 | 
					             tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Tox clients connected took %lu seconds.\n", (unsigned long)(time(nullptr) - con_time));
 | 
					    printf("Tox clients connected took %lu seconds.\n", (unsigned long)(time(nullptr) - con_time));
 | 
				
			||||||
    printf("friend_request_test succeeded, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time));
 | 
					    printf("friend_request_test succeeded, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch);
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(tox1);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(tox2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ typedef struct State {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define PEER_LIMIT 20
 | 
					#define PEER_LIMIT 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_ip(Tox *tox, uint32_t groupnumber, uint32_t peer_id)
 | 
					static void print_ip(const Tox *tox, uint32_t groupnumber, uint32_t peer_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_Peer_Query err;
 | 
					    Tox_Err_Group_Peer_Query err;
 | 
				
			||||||
    size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
 | 
					    size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
 | 
				
			||||||
@@ -81,32 +81,35 @@ static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, ui
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_peer_join_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // we do a connection test here for fun
 | 
					    // we do a connection test here for fun
 | 
				
			||||||
    Tox_Err_Group_Peer_Query pq_err;
 | 
					    Tox_Err_Group_Peer_Query pq_err;
 | 
				
			||||||
    TOX_CONNECTION connection_status = tox_group_peer_get_connection_status(tox, groupnumber, peer_id, &pq_err);
 | 
					    Tox_Connection connection_status = tox_group_peer_get_connection_status(autotox->tox, groupnumber, peer_id, &pq_err);
 | 
				
			||||||
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(connection_status != TOX_CONNECTION_NONE);
 | 
					    ck_assert(connection_status != TOX_CONNECTION_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Role role = tox_group_peer_get_role(tox, groupnumber, peer_id, &pq_err);
 | 
					    Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, groupnumber, peer_id, &pq_err);
 | 
				
			||||||
    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
 | 
					    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_User_Status status = tox_group_peer_get_status(tox, groupnumber, peer_id, &pq_err);
 | 
					    Tox_User_Status status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &pq_err);
 | 
				
			||||||
    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
 | 
					    ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &pq_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &pq_err);
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &pq_err);
 | 
					    tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &pq_err);
 | 
				
			||||||
    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
@@ -137,35 +140,37 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "%s joined with IP: ", peer_name);
 | 
					    fprintf(stderr, "%s joined with IP: ", peer_name);
 | 
				
			||||||
    print_ip(tox, groupnumber, peer_id);
 | 
					    print_ip(autotox->tox, groupnumber, peer_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state->peer_id = peer_id;
 | 
					    state->peer_id = peer_id;
 | 
				
			||||||
    ++state->peer_joined_count;
 | 
					    ++state->peer_joined_count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *user_data)
 | 
					static void group_peer_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_self_join_get_group_number(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // make sure we see our own correct peer state on join callback
 | 
					    // make sure we see our own correct peer state on join callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Self_Query sq_err;
 | 
					    Tox_Err_Group_Self_Query sq_err;
 | 
				
			||||||
    size_t self_length = tox_group_self_get_name_size(tox, groupnumber, &sq_err);
 | 
					    size_t self_length = tox_group_self_get_name_size(autotox->tox, groupnumber, &sq_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t self_name[TOX_MAX_NAME_LENGTH];
 | 
					    uint8_t self_name[TOX_MAX_NAME_LENGTH];
 | 
				
			||||||
    tox_group_self_get_name(tox, groupnumber, self_name, &sq_err);
 | 
					    tox_group_self_get_name(autotox->tox, groupnumber, self_name, &sq_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TOX_USER_STATUS self_status = tox_group_self_get_status(tox, groupnumber, &sq_err);
 | 
					    Tox_User_Status self_status = tox_group_self_get_status(autotox->tox, groupnumber, &sq_err);
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Role self_role = tox_group_self_get_role(tox, groupnumber, &sq_err);
 | 
					    Tox_Group_Role self_role = tox_group_self_get_role(autotox->tox, groupnumber, &sq_err);
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (state->is_founder) {
 | 
					    if (state->is_founder) {
 | 
				
			||||||
@@ -185,36 +190,37 @@ static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *u
 | 
				
			|||||||
    uint8_t group_name[GROUP_NAME_LEN];
 | 
					    uint8_t group_name[GROUP_NAME_LEN];
 | 
				
			||||||
    uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
					    uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(tox_group_get_peer_limit(tox, groupnumber, nullptr) == PEER_LIMIT);
 | 
					    ck_assert(tox_group_get_peer_limit(autotox->tox, groupnumber, nullptr) == PEER_LIMIT);
 | 
				
			||||||
    ck_assert(tox_group_get_name_size(tox, groupnumber, nullptr) == GROUP_NAME_LEN);
 | 
					    ck_assert(tox_group_get_name_size(autotox->tox, groupnumber, nullptr) == GROUP_NAME_LEN);
 | 
				
			||||||
    ck_assert(tox_group_get_topic_size(tox, groupnumber, nullptr) == TOPIC_LEN);
 | 
					    ck_assert(tox_group_get_topic_size(autotox->tox, groupnumber, nullptr) == TOPIC_LEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
    tox_group_get_name(tox, groupnumber, group_name, &query_err);
 | 
					    tox_group_get_name(autotox->tox, groupnumber, group_name, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
 | 
				
			||||||
    ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0);
 | 
					    ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_get_topic(tox, groupnumber, topic, &query_err);
 | 
					    tox_group_get_topic(autotox->tox, groupnumber, topic, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
 | 
				
			||||||
    ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
 | 
					    ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr);
 | 
					    uint32_t peer_id = tox_group_self_get_peer_id(autotox->tox, groupnumber, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "self joined with IP: ");
 | 
					    fprintf(stderr, "self joined with IP: ");
 | 
				
			||||||
    print_ip(tox, groupnumber, peer_id);
 | 
					    print_ip(autotox->tox, groupnumber, peer_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++state->self_joined_count;
 | 
					    ++state->self_joined_count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type,
 | 
					static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
 | 
				
			||||||
                                    const uint8_t *name, size_t name_length, const uint8_t *part_message,
 | 
					 | 
				
			||||||
                                    size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *part_message = tox_event_group_peer_exit_get_part_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_peer_exit_get_part_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++state->peer_exit_count;
 | 
					    ++state->peer_exit_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // first exit is a disconnect. second is a real exit with a part message
 | 
					    // first exit is a disconnect. second is a real exit with a part message
 | 
				
			||||||
@@ -224,14 +230,16 @@ static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *name,
 | 
					static void group_peer_name_handler(const Tox_Event_Group_Peer_Name *event, void *user_data)
 | 
				
			||||||
                                    size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *name = tox_event_group_peer_name_get_name(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_peer_name_get_name_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // note: we already test the name_get api call elsewhere
 | 
					    // note: we already test the name_get api call elsewhere
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(length == PEER0_NICK2_LEN);
 | 
					    ck_assert(length == PEER0_NICK2_LEN);
 | 
				
			||||||
@@ -240,7 +248,7 @@ static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
 | 
				
			|||||||
    state->peer_nick = true;
 | 
					    state->peer_nick = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_USER_STATUS status,
 | 
					static void group_peer_status_handler(const Tox_Event_Group_Peer_Status *event,
 | 
				
			||||||
                                      void *user_data)
 | 
					                                      void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
@@ -248,8 +256,12 @@ static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t p
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_peer_status_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_status_get_peer_id(event);
 | 
				
			||||||
 | 
					    const Tox_User_Status status = tox_event_group_peer_status_get_status(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query err;
 | 
					    Tox_Err_Group_Peer_Query err;
 | 
				
			||||||
    TOX_USER_STATUS cur_status = tox_group_peer_get_status(tox, groupnumber, peer_id, &err);
 | 
					    Tox_User_Status cur_status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(cur_status == status, "%d, %d", cur_status, status);
 | 
					    ck_assert_msg(cur_status == status, "%d, %d", cur_status, status);
 | 
				
			||||||
    ck_assert(status == TOX_USER_STATUS_BUSY);
 | 
					    ck_assert(status == TOX_USER_STATUS_BUSY);
 | 
				
			||||||
@@ -264,15 +276,15 @@ static void group_announce_test(AutoTox *autotoxes)
 | 
				
			|||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
    Tox *tox1 = autotoxes[1].tox;
 | 
					    Tox *tox1 = autotoxes[1].tox;
 | 
				
			||||||
    State *state0 = (State *)autotoxes[0].state;
 | 
					    State *state0 = (State *)autotoxes[0].state;
 | 
				
			||||||
    State *state1 = (State *)autotoxes[1].state;
 | 
					    const State *state1 = (const State *)autotoxes[1].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_group_peer_join(tox0, group_peer_join_handler);
 | 
					    tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
 | 
				
			||||||
    tox_callback_group_peer_join(tox1, group_peer_join_handler);
 | 
					    tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
 | 
				
			||||||
    tox_callback_group_self_join(tox0, group_peer_self_join_handler);
 | 
					    tox_events_callback_group_self_join(autotoxes[0].dispatch, group_peer_self_join_handler);
 | 
				
			||||||
    tox_callback_group_self_join(tox1, group_peer_self_join_handler);
 | 
					    tox_events_callback_group_self_join(autotoxes[1].dispatch, group_peer_self_join_handler);
 | 
				
			||||||
    tox_callback_group_peer_name(tox1, group_peer_name_handler);
 | 
					    tox_events_callback_group_peer_name(autotoxes[1].dispatch, group_peer_name_handler);
 | 
				
			||||||
    tox_callback_group_peer_status(tox1, group_peer_status_handler);
 | 
					    tox_events_callback_group_peer_status(autotoxes[1].dispatch, group_peer_status_handler);
 | 
				
			||||||
    tox_callback_group_peer_exit(tox1, group_peer_exit_handler);
 | 
					    tox_events_callback_group_peer_exit(autotoxes[1].dispatch, group_peer_exit_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox0 makes new group.
 | 
					    // tox0 makes new group.
 | 
				
			||||||
    Tox_Err_Group_New err_new;
 | 
					    Tox_Err_Group_New err_new;
 | 
				
			||||||
@@ -286,19 +298,19 @@ static void group_announce_test(AutoTox *autotoxes)
 | 
				
			|||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // changes the state (for sync check purposes)
 | 
					    // changes the state (for sync check purposes)
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
 | 
					    Tox_Err_Group_Set_Peer_Limit limit_set_err;
 | 
				
			||||||
    tox_group_founder_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
 | 
					    tox_group_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
 | 
				
			||||||
    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
 | 
					    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Topic_Set tp_err;
 | 
					    Tox_Err_Group_Topic_Set tp_err;
 | 
				
			||||||
    tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err);
 | 
					    tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err);
 | 
				
			||||||
    ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK);
 | 
					    ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // get the chat id of the new group.
 | 
					    // get the chat id of the new group.
 | 
				
			||||||
    Tox_Err_Group_State_Queries err_id;
 | 
					    Tox_Err_Group_State_Query err_id;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
    tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id);
 | 
					    tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id);
 | 
				
			||||||
    ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox1 joins it.
 | 
					    // tox1 joins it.
 | 
				
			||||||
    Tox_Err_Group_Join err_join;
 | 
					    Tox_Err_Group_Join err_join;
 | 
				
			||||||
@@ -343,7 +355,7 @@ static void group_announce_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TOX_USER_STATUS self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
 | 
					    Tox_User_Status self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(self_status == TOX_USER_STATUS_BUSY);
 | 
					    ck_assert(self_status == TOX_USER_STATUS_BUSY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -429,10 +441,12 @@ static void group_announce_test(AutoTox *autotoxes)
 | 
				
			|||||||
    tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit);
 | 
					    tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit);
 | 
				
			||||||
    ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
 | 
					    ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (num_groups1 != 0 || num_groups2 != 0) {
 | 
				
			||||||
        num_groups1 = tox_group_get_number_groups(tox0);
 | 
					        num_groups1 = tox_group_get_number_groups(tox0);
 | 
				
			||||||
        num_groups2 = tox_group_get_number_groups(tox1);
 | 
					        num_groups2 = tox_group_get_number_groups(tox1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(num_groups1 == num_groups2 && num_groups2 == 0);
 | 
					        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("All tests passed!\n");
 | 
					    printf("All tests passed!\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,13 +51,15 @@ static bool group_has_full_graph(const AutoTox *autotoxes, uint32_t group_number
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data)
 | 
					static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (fail_type) {
 | 
					    switch (fail_type) {
 | 
				
			||||||
        case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
 | 
					        case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
 | 
				
			||||||
            state->peer_limit_fail = true;
 | 
					            state->peer_limit_fail = true;
 | 
				
			||||||
@@ -79,7 +81,7 @@ static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_J
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_data)
 | 
					static void group_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
@@ -89,7 +91,7 @@ static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_
 | 
				
			|||||||
    state->connected = true;
 | 
					    state->connected = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
@@ -105,9 +107,9 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(NUM_GROUP_TOXES > 7, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
					    ck_assert_msg(NUM_GROUP_TOXES > 7, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
        tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler);
 | 
					        tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
 | 
				
			||||||
        tox_callback_group_self_join(autotoxes[i].tox, group_self_join_handler);
 | 
					        tox_events_callback_group_self_join(autotoxes[i].dispatch, group_self_join_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
@@ -118,12 +120,12 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    Tox *tox5 = autotoxes[5].tox;
 | 
					    Tox *tox5 = autotoxes[5].tox;
 | 
				
			||||||
    Tox *tox6 = autotoxes[6].tox;
 | 
					    Tox *tox6 = autotoxes[6].tox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state0 = (State *)autotoxes[0].state;
 | 
					    const State *state0 = (const State *)autotoxes[0].state;
 | 
				
			||||||
    State *state2 = (State *)autotoxes[2].state;
 | 
					    const State *state2 = (const State *)autotoxes[2].state;
 | 
				
			||||||
    State *state3 = (State *)autotoxes[3].state;
 | 
					    const State *state3 = (const State *)autotoxes[3].state;
 | 
				
			||||||
    State *state4 = (State *)autotoxes[4].state;
 | 
					    const State *state4 = (const State *)autotoxes[4].state;
 | 
				
			||||||
    State *state5 = (State *)autotoxes[5].state;
 | 
					    const State *state5 = (const State *)autotoxes[5].state;
 | 
				
			||||||
    State *state6 = (State *)autotoxes[6].state;
 | 
					    const State *state6 = (const State *)autotoxes[6].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_New new_err;
 | 
					    Tox_Err_Group_New new_err;
 | 
				
			||||||
    uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
 | 
					    uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
 | 
				
			||||||
@@ -132,11 +134,11 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // peer 1 joins public group with no password
 | 
					    // peer 1 joins public group with no password
 | 
				
			||||||
    Tox_Err_Group_Join join_err;
 | 
					    Tox_Err_Group_Join join_err;
 | 
				
			||||||
@@ -150,9 +152,9 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("Peer 1 joined group\n");
 | 
					    printf("Peer 1 joined group\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // founder sets a password
 | 
					    // founder sets a password
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Password pass_set_err;
 | 
					    Tox_Err_Group_Set_Password pass_set_err;
 | 
				
			||||||
    tox_group_founder_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
 | 
					    tox_group_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
 | 
				
			||||||
    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err);
 | 
					    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,9 +179,9 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("Peer 3 successfully blocked with invalid password\n");
 | 
					    printf("Peer 3 successfully blocked with invalid password\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // founder sets peer limit to 1
 | 
					    // founder sets peer limit to 1
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
 | 
					    Tox_Err_Group_Set_Peer_Limit limit_set_err;
 | 
				
			||||||
    tox_group_founder_set_peer_limit(tox0, groupnumber, 1, &limit_set_err);
 | 
					    tox_group_set_peer_limit(tox0, groupnumber, 1, &limit_set_err);
 | 
				
			||||||
    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err);
 | 
					    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -194,11 +196,11 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("Peer 4 successfully blocked from joining full group\n");
 | 
					    printf("Peer 4 successfully blocked from joining full group\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // founder removes password and increases peer limit to 100
 | 
					    // founder removes password and increases peer limit to 100
 | 
				
			||||||
    tox_group_founder_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err);
 | 
					    tox_group_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err);
 | 
				
			||||||
    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err);
 | 
					    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_founder_set_peer_limit(tox0, groupnumber, 100, &limit_set_err);
 | 
					    tox_group_set_peer_limit(tox0, groupnumber, 100, &limit_set_err);
 | 
				
			||||||
    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err);
 | 
					    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -213,9 +215,9 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("Peer 5 successfully joined the group\n");
 | 
					    printf("Peer 5 successfully joined the group\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // founder makes group private
 | 
					    // founder makes group private
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Privacy_State priv_err;
 | 
					    Tox_Err_Group_Set_Privacy_State priv_err;
 | 
				
			||||||
    tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err);
 | 
					    tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err);
 | 
				
			||||||
    ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err);
 | 
					    ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -231,8 +233,8 @@ static void group_invite_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("Peer 6 failed to join private group via chat ID\n");
 | 
					    printf("Peer 6 failed to join private group via chat ID\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // founder makes group public again
 | 
					    // founder makes group public again
 | 
				
			||||||
    tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err);
 | 
					    tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err);
 | 
				
			||||||
    ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err);
 | 
					    ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ typedef struct State {
 | 
				
			|||||||
    bool peer_joined;
 | 
					    bool peer_joined;
 | 
				
			||||||
    bool message_sent;
 | 
					    bool message_sent;
 | 
				
			||||||
    bool message_received;
 | 
					    bool message_received;
 | 
				
			||||||
    uint32_t pseudo_msg_id;
 | 
					    Tox_Group_Message_Id pseudo_msg_id;
 | 
				
			||||||
    bool private_message_received;
 | 
					    bool private_message_received;
 | 
				
			||||||
    size_t custom_packets_received;
 | 
					    size_t custom_packets_received;
 | 
				
			||||||
    size_t custom_private_packets_received;
 | 
					    size_t custom_private_packets_received;
 | 
				
			||||||
@@ -71,28 +71,37 @@ static uint16_t get_message_checksum(const uint8_t *message, uint16_t length)
 | 
				
			|||||||
    return sum;
 | 
					    return sum;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
 | 
					static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
 | 
				
			||||||
                                 const uint8_t *group_name, size_t group_name_length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_invite_get_invite_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("invite arrived; accepting\n");
 | 
					    printf("invite arrived; accepting\n");
 | 
				
			||||||
    Tox_Err_Group_Invite_Accept err_accept;
 | 
					    Tox_Err_Group_Invite_Accept err_accept;
 | 
				
			||||||
    tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
 | 
					    tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
 | 
				
			||||||
                            nullptr, 0, &err_accept);
 | 
					                            nullptr, 0, &err_accept);
 | 
				
			||||||
    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
					    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_join_fail_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Join_Fail fail_type, void *user_data)
 | 
					static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
 | 
				
			||||||
    printf("join failed: %d\n", fail_type);
 | 
					    printf("join failed: %d\n", fail_type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(state->peer_joined == false, "Peer timedout");
 | 
					    ck_assert_msg(state->peer_joined == false, "Peer timedout");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("peer %u joined, sending message\n", peer_id);
 | 
					    printf("peer %u joined, sending message\n", peer_id);
 | 
				
			||||||
@@ -100,9 +109,16 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
 | 
				
			|||||||
    state->peer_id = peer_id;
 | 
					    state->peer_id = peer_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
 | 
					static void group_custom_private_packet_handler(const Tox_Event_Group_Custom_Private_Packet *event, void *user_data)
 | 
				
			||||||
        size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_custom_private_packet_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_custom_private_packet_get_peer_id(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_group_custom_private_packet_get_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_custom_private_packet_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == TEST_CUSTOM_PRIVATE_PACKET_LEN,
 | 
					    ck_assert_msg(length == TEST_CUSTOM_PRIVATE_PACKET_LEN,
 | 
				
			||||||
                  "Failed to receive custom private packet. Invalid length: %zu\n", length);
 | 
					                  "Failed to receive custom private packet. Invalid length: %zu\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,25 +127,25 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
 | 
				
			|||||||
    message_buf[length] = 0;
 | 
					    message_buf[length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
					    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Self_Query s_err;
 | 
					    Tox_Err_Group_Self_Query s_err;
 | 
				
			||||||
    size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
 | 
					    size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
 | 
					    tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
 | 
				
			||||||
    self_name[self_name_len] = 0;
 | 
					    self_name[self_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
@@ -138,17 +154,21 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
 | 
				
			|||||||
    printf("%s sent custom private packet to %s: %s\n", peer_name, self_name, message_buf);
 | 
					    printf("%s sent custom private packet to %s: %s\n", peer_name, self_name, message_buf);
 | 
				
			||||||
    ck_assert(memcmp(message_buf, TEST_CUSTOM_PRIVATE_PACKET, length) == 0);
 | 
					    ck_assert(memcmp(message_buf, TEST_CUSTOM_PRIVATE_PACKET, length) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++state->custom_private_packets_received;
 | 
					    ++state->custom_private_packets_received;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
 | 
					static void group_custom_packet_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
 | 
				
			||||||
                                        size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_custom_packet_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_custom_packet_get_peer_id(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_group_custom_packet_get_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_custom_packet_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == TEST_CUSTOM_PACKET_LEN, "Failed to receive custom packet. Invalid length: %zu\n", length);
 | 
					    ck_assert_msg(length == TEST_CUSTOM_PACKET_LEN, "Failed to receive custom packet. Invalid length: %zu\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char message_buf[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
 | 
					    char message_buf[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
 | 
				
			||||||
@@ -156,25 +176,25 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
 | 
				
			|||||||
    message_buf[length] = 0;
 | 
					    message_buf[length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
					    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Self_Query s_err;
 | 
					    Tox_Err_Group_Self_Query s_err;
 | 
				
			||||||
    size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
 | 
					    size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
 | 
					    tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
 | 
				
			||||||
    self_name[self_name_len] = 0;
 | 
					    self_name[self_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
@@ -183,32 +203,39 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
 | 
				
			|||||||
    printf("%s sent custom packet to %s: %s\n", peer_name, self_name, message_buf);
 | 
					    printf("%s sent custom packet to %s: %s\n", peer_name, self_name, message_buf);
 | 
				
			||||||
    ck_assert(memcmp(message_buf, TEST_CUSTOM_PACKET, length) == 0);
 | 
					    ck_assert(memcmp(message_buf, TEST_CUSTOM_PACKET, length) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++state->custom_packets_received;
 | 
					    ++state->custom_packets_received;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_custom_packet_large_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data,
 | 
					static void group_custom_packet_large_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
 | 
				
			||||||
                                        size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_group_custom_packet_get_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_custom_packet_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == TEST_CUSTOM_PACKET_LARGE_LEN, "Failed to receive large custom packet. Invalid length: %zu\n", length);
 | 
					    ck_assert_msg(length == TEST_CUSTOM_PACKET_LARGE_LEN, "Failed to receive large custom packet. Invalid length: %zu\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(memcmp(data, TEST_CUSTOM_PACKET_LARGE, length) == 0);
 | 
					    ck_assert(memcmp(data, TEST_CUSTOM_PACKET_LARGE, length) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++state->custom_packets_received;
 | 
					    ++state->custom_packets_received;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
					static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
 | 
				
			||||||
                                  const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_message_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_message_get_peer_id(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_message_get_message_length(event);
 | 
				
			||||||
 | 
					    const uint32_t pseudo_msg_id = tox_event_group_message_get_message_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(!(length == IGNORE_MESSAGE_LEN && memcmp(message, IGNORE_MESSAGE, length) == 0));
 | 
					    ck_assert(!(length == IGNORE_MESSAGE_LEN && memcmp(message, IGNORE_MESSAGE, length) == 0));
 | 
				
			||||||
    ck_assert_msg(length == TEST_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
 | 
					    ck_assert_msg(length == TEST_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -217,25 +244,25 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
 | 
				
			|||||||
    message_buf[length] = 0;
 | 
					    message_buf[length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
					    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Self_Query s_err;
 | 
					    Tox_Err_Group_Self_Query s_err;
 | 
				
			||||||
    size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
 | 
					    size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
 | 
					    tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
 | 
				
			||||||
    self_name[self_name_len] = 0;
 | 
					    self_name[self_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
@@ -244,19 +271,24 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
 | 
				
			|||||||
    printf("%s sent message to %s:(id:%u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
 | 
					    printf("%s sent message to %s:(id:%u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
 | 
				
			||||||
    ck_assert(memcmp(message_buf, TEST_MESSAGE, length) == 0);
 | 
					    ck_assert(memcmp(message_buf, TEST_MESSAGE, length) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state->message_received = true;
 | 
					    state->message_received = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    state->pseudo_msg_id = pseudo_msg_id;
 | 
					    state->pseudo_msg_id = pseudo_msg_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
					static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
 | 
				
			||||||
        const uint8_t *message, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t groupnumber = tox_event_group_private_message_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_private_message_get_peer_id(event);
 | 
				
			||||||
 | 
					    const Tox_Message_Type type = tox_event_group_private_message_get_message_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_private_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_private_message_get_message_length(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Message_Id pseudo_msg_id = tox_event_group_private_message_get_message_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
 | 
					    ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char message_buf[TOX_GROUP_MAX_MESSAGE_LENGTH + 1];
 | 
					    char message_buf[TOX_GROUP_MAX_MESSAGE_LENGTH + 1];
 | 
				
			||||||
@@ -264,46 +296,46 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
 | 
				
			|||||||
    message_buf[length] = 0;
 | 
					    message_buf[length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
					    ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Self_Query s_err;
 | 
					    Tox_Err_Group_Self_Query s_err;
 | 
				
			||||||
    size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err);
 | 
					    size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err);
 | 
					    tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
 | 
				
			||||||
    self_name[self_name_len] = 0;
 | 
					    self_name[self_name_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
    ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0);
 | 
					    ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("%s sent private action to %s: %s\n", peer_name, self_name, message_buf);
 | 
					    printf("%s sent private action to %s:(id: %u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
 | 
				
			||||||
    ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0);
 | 
					    ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(type == TOX_MESSAGE_TYPE_ACTION);
 | 
					    ck_assert(type == TOX_MESSAGE_TYPE_ACTION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state->private_message_received = true;
 | 
					    state->private_message_received = true;
 | 
				
			||||||
 | 
					    state->pseudo_msg_id = pseudo_msg_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
					static void group_message_handler_lossless_test(const Tox_Event_Group_Message *event, void *user_data)
 | 
				
			||||||
        const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -325,10 +357,11 @@ static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber,
 | 
				
			|||||||
        state->lossless_check = true;
 | 
					        state->lossless_check = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static void group_message_handler_wraparound_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id,
 | 
					static void group_message_handler_wraparound_test(const Tox_Event_Group_Message *event, void *user_data)
 | 
				
			||||||
        TOX_MESSAGE_TYPE type,
 | 
					 | 
				
			||||||
        const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -352,11 +385,11 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert_msg(NUM_GROUP_TOXES >= 2, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
					    ck_assert_msg(NUM_GROUP_TOXES >= 2, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
    Tox *tox1 = autotoxes[1].tox;
 | 
					    const Tox *tox1 = autotoxes[1].tox;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state0 = (State *)autotoxes[0].state;
 | 
					    State *state0 = (State *)autotoxes[0].state;
 | 
				
			||||||
    State *state1 = (State *)autotoxes[1].state;
 | 
					    State *state1 = (State *)autotoxes[1].state;
 | 
				
			||||||
@@ -365,15 +398,15 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
    state0->pseudo_msg_id = 0;
 | 
					    state0->pseudo_msg_id = 0;
 | 
				
			||||||
    state1->pseudo_msg_id = 1;
 | 
					    state1->pseudo_msg_id = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_group_invite(tox1, group_invite_handler);
 | 
					    tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
 | 
				
			||||||
    tox_callback_group_join_fail(tox1, group_join_fail_handler);
 | 
					    tox_events_callback_group_join_fail(autotoxes[1].dispatch, group_join_fail_handler);
 | 
				
			||||||
    tox_callback_group_peer_join(tox1, group_peer_join_handler);
 | 
					    tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
 | 
				
			||||||
    tox_callback_group_join_fail(tox0, group_join_fail_handler);
 | 
					    tox_events_callback_group_join_fail(autotoxes[0].dispatch, group_join_fail_handler);
 | 
				
			||||||
    tox_callback_group_peer_join(tox0, group_peer_join_handler);
 | 
					    tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
 | 
				
			||||||
    tox_callback_group_message(tox0, group_message_handler);
 | 
					    tox_events_callback_group_message(autotoxes[0].dispatch, group_message_handler);
 | 
				
			||||||
    tox_callback_group_custom_packet(tox0, group_custom_packet_handler);
 | 
					    tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_handler);
 | 
				
			||||||
    tox_callback_group_custom_private_packet(tox0, group_custom_private_packet_handler);
 | 
					    tox_events_callback_group_custom_private_packet(autotoxes[0].dispatch, group_custom_private_packet_handler);
 | 
				
			||||||
    tox_callback_group_private_message(tox0, group_private_message_handler);
 | 
					    tox_events_callback_group_private_message(autotoxes[0].dispatch, group_private_message_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Send_Message err_send;
 | 
					    Tox_Err_Group_Send_Message err_send;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -403,7 +436,8 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", state0->pseudo_msg_id, state1->pseudo_msg_id);
 | 
					    ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
 | 
				
			||||||
 | 
					                  state0->pseudo_msg_id, state1->pseudo_msg_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Make sure we're still connected to each friend
 | 
					    // Make sure we're still connected to each friend
 | 
				
			||||||
    Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr);
 | 
					    Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr);
 | 
				
			||||||
@@ -428,14 +462,23 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
    tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err);
 | 
					    tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err);
 | 
				
			||||||
    ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err);
 | 
					    ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Sending private message...\n");
 | 
					    fprintf(stderr, "Sending private action...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox0 sends a private action to tox1
 | 
					    // tox1 sends a private action to tox0
 | 
				
			||||||
    Tox_Err_Group_Send_Private_Message m_err;
 | 
					    Tox_Err_Group_Send_Private_Message m_err;
 | 
				
			||||||
    tox_group_send_private_message(tox1, group_number, state1->peer_id, TOX_MESSAGE_TYPE_ACTION,
 | 
					    state1->pseudo_msg_id = tox_group_send_private_message(tox1, group_number, state1->peer_id,
 | 
				
			||||||
                                   (const uint8_t *)TEST_PRIVATE_MESSAGE, TEST_PRIVATE_MESSAGE_LEN, &m_err);
 | 
					                            TOX_MESSAGE_TYPE_ACTION, (const uint8_t *)TEST_PRIVATE_MESSAGE,
 | 
				
			||||||
 | 
					                            TEST_PRIVATE_MESSAGE_LEN, &m_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err);
 | 
					    ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (!state0->private_message_received) {
 | 
				
			||||||
 | 
					        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
 | 
				
			||||||
 | 
					                  state0->pseudo_msg_id, state1->pseudo_msg_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Sending custom packets...\n");
 | 
					    fprintf(stderr, "Sending custom packets...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox0 sends a lossless and lossy custom packet to tox1
 | 
					    // tox0 sends a lossless and lossy custom packet to tox1
 | 
				
			||||||
@@ -464,15 +507,14 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr);
 | 
					    ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (!state0->private_message_received || state0->custom_packets_received < 2
 | 
					    while (state0->custom_packets_received < 2 || state0->custom_private_packets_received < 2) {
 | 
				
			||||||
            || state0->custom_private_packets_received < 2) {
 | 
					 | 
				
			||||||
        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					        iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // tox0 sends a large max sized lossy custom packet
 | 
					    // tox0 sends a large max sized lossy custom packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // overwrite callback for larger packet
 | 
					    // overwrite callback for larger packet
 | 
				
			||||||
    tox_callback_group_custom_packet(tox0, group_custom_packet_large_handler);
 | 
					    tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_large_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_send_custom_packet(tox1, group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET_LARGE, TEST_CUSTOM_PACKET_LARGE_LEN,
 | 
					    tox_group_send_custom_packet(tox1, group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET_LARGE, TEST_CUSTOM_PACKET_LARGE_LEN,
 | 
				
			||||||
                                 &c_err);
 | 
					                                 &c_err);
 | 
				
			||||||
@@ -486,7 +528,7 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Doing lossless packet test...\n");
 | 
					    fprintf(stderr, "Doing lossless packet test...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_group_message(tox1, group_message_handler_lossless_test);
 | 
					    tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_lossless_test);
 | 
				
			||||||
    state1->last_msg_recv = -1;
 | 
					    state1->last_msg_recv = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // lossless and packet splitting/reassembly test
 | 
					    // lossless and packet splitting/reassembly test
 | 
				
			||||||
@@ -517,7 +559,7 @@ static void group_message_test(AutoTox *autotoxes)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state1->last_msg_recv = -1;
 | 
					    state1->last_msg_recv = -1;
 | 
				
			||||||
    tox_callback_group_message(tox1, group_message_handler_wraparound_test);
 | 
					    tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_wraparound_test);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Doing wraparound test...\n");
 | 
					    fprintf(stderr, "Doing wraparound test...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,13 +19,13 @@
 | 
				
			|||||||
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
 | 
					#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct Peer {
 | 
					typedef struct Peer {
 | 
				
			||||||
    char name[TOX_MAX_NAME_LENGTH];
 | 
					    char name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    size_t name_length;
 | 
					    size_t name_length;
 | 
				
			||||||
    uint32_t peer_id;
 | 
					    uint32_t peer_id;
 | 
				
			||||||
} Peer;
 | 
					} Peer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct State {
 | 
					typedef struct State {
 | 
				
			||||||
    char self_name[TOX_MAX_NAME_LENGTH];
 | 
					    char self_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
    size_t self_name_length;
 | 
					    size_t self_name_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t group_number;
 | 
					    uint32_t group_number;
 | 
				
			||||||
@@ -38,7 +38,6 @@ typedef struct State {
 | 
				
			|||||||
    char mod_name1[TOX_MAX_NAME_LENGTH];
 | 
					    char mod_name1[TOX_MAX_NAME_LENGTH];
 | 
				
			||||||
    char mod_name2[TOX_MAX_NAME_LENGTH];
 | 
					    char mod_name2[TOX_MAX_NAME_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool observer_check;
 | 
					    bool observer_check;
 | 
				
			||||||
    size_t observer_event_count;
 | 
					    size_t observer_event_count;
 | 
				
			||||||
    char observer_name1[TOX_MAX_NAME_LENGTH];
 | 
					    char observer_name1[TOX_MAX_NAME_LENGTH];
 | 
				
			||||||
@@ -53,7 +52,7 @@ typedef struct State {
 | 
				
			|||||||
static bool all_peers_connected(AutoTox *autotoxes)
 | 
					static bool all_peers_connected(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (const State *)autotoxes[i].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (state->num_peers != NUM_GROUP_TOXES - 1) {
 | 
					        if (state->num_peers != NUM_GROUP_TOXES - 1) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -146,7 +145,7 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
 | 
				
			|||||||
    ck_assert(name != nullptr && name_length <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(name != nullptr && name_length <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < num_peers; ++i) {
 | 
					    for (size_t i = 0; i < num_peers; ++i) {
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (const State *)autotoxes[i].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (memcmp(state->self_name, name, name_length) == 0) {
 | 
					        if (memcmp(state->self_name, name, name_length) == 0) {
 | 
				
			||||||
            return i;
 | 
					            return i;
 | 
				
			||||||
@@ -156,29 +155,33 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
 | 
				
			|||||||
    ck_assert_msg(0, "Failed to find index");
 | 
					    ck_assert_msg(0, "Failed to find index");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data)
 | 
					static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
 | 
				
			||||||
    fprintf(stderr, "Failed to join group: %d", fail_type);
 | 
					    fprintf(stderr, "Failed to join group: %d", fail_type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(state->group_number == group_number);
 | 
					    ck_assert(state->group_number == group_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_peer_get_name(tox, group_number, peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, group_number, peer_id, (uint8_t *) peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -193,7 +196,7 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
 | 
				
			|||||||
    ck_assert(state->num_peers < NUM_GROUP_TOXES);
 | 
					    ck_assert(state->num_peers < NUM_GROUP_TOXES);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_mod(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
 | 
					static void handle_mod(State *state, const char *peer_name, size_t peer_name_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (state->mod_event_count == 0) {
 | 
					    if (state->mod_event_count == 0) {
 | 
				
			||||||
        ck_assert(memcmp(peer_name, state->mod_name1, peer_name_len) == 0);
 | 
					        ck_assert(memcmp(peer_name, state->mod_name1, peer_name_len) == 0);
 | 
				
			||||||
@@ -205,10 +208,9 @@ static void handle_mod(State *state, const char *peer_name, size_t peer_name_len
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ++state->mod_event_count;
 | 
					    ++state->mod_event_count;
 | 
				
			||||||
    state->mod_check = true;
 | 
					    state->mod_check = true;
 | 
				
			||||||
    ck_assert(role == TOX_GROUP_ROLE_MODERATOR);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_observer(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
 | 
					static void handle_observer(State *state, const char *peer_name, size_t peer_name_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (state->observer_event_count == 0) {
 | 
					    if (state->observer_event_count == 0) {
 | 
				
			||||||
        ck_assert(memcmp(peer_name, state->observer_name1, peer_name_len) == 0);
 | 
					        ck_assert(memcmp(peer_name, state->observer_name1, peer_name_len) == 0);
 | 
				
			||||||
@@ -220,10 +222,9 @@ static void handle_observer(State *state, const char *peer_name, size_t peer_nam
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ++state->observer_event_count;
 | 
					    ++state->observer_event_count;
 | 
				
			||||||
    state->observer_check = true;
 | 
					    state->observer_check = true;
 | 
				
			||||||
    ck_assert(role == TOX_GROUP_ROLE_OBSERVER);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_user(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role)
 | 
					static void handle_user(State *state, const char *peer_name, size_t peer_name_len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // event 1: observer1 gets promoted back to user
 | 
					    // event 1: observer1 gets promoted back to user
 | 
				
			||||||
    // event 2: observer2 gets promoted to moderator
 | 
					    // event 2: observer2 gets promoted to moderator
 | 
				
			||||||
@@ -243,23 +244,25 @@ static void handle_user(State *state, const char *peer_name, size_t peer_name_le
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ++state->user_event_count;
 | 
					    ++state->user_event_count;
 | 
				
			||||||
    state->user_check = true;
 | 
					    state->user_check = true;
 | 
				
			||||||
    ck_assert(role == TOX_GROUP_ROLE_USER);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id,
 | 
					static void group_mod_event_handler(const Tox_Event_Group_Moderation *event, void *user_data)
 | 
				
			||||||
                                    Tox_Group_Mod_Event mod_type, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t group_number = tox_event_group_moderation_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t target_peer_id = tox_event_group_moderation_get_target_peer_id(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Mod_Event mod_type = tox_event_group_moderation_get_mod_type(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(state->group_number == group_number);
 | 
					    ck_assert(state->group_number == group_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
					    char peer_name[TOX_MAX_NAME_LENGTH + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Peer_Query q_err;
 | 
					    Tox_Err_Group_Peer_Query q_err;
 | 
				
			||||||
    size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, target_peer_id, &q_err);
 | 
					    size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, target_peer_id, &q_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (q_err == TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND) {  // may occurr on sync attempts
 | 
					    if (q_err == TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND) {  // may occurr on sync attempts
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@@ -268,12 +271,13 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
 | 
				
			|||||||
    ck_assert_msg(q_err == TOX_ERR_GROUP_PEER_QUERY_OK, "error %d", q_err);
 | 
					    ck_assert_msg(q_err == TOX_ERR_GROUP_PEER_QUERY_OK, "error %d", q_err);
 | 
				
			||||||
    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
					    ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_peer_get_name(tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err);
 | 
					    tox_group_peer_get_name(autotox->tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err);
 | 
				
			||||||
    peer_name[peer_name_len] = 0;
 | 
					    peer_name[peer_name_len] = 0;
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Role role = tox_group_peer_get_role(tox, group_number, target_peer_id, &q_err);
 | 
					    Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, group_number, target_peer_id, &q_err);
 | 
				
			||||||
    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
					    ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
 | 
				
			||||||
 | 
					    ck_assert(role <= TOX_GROUP_ROLE_OBSERVER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n",
 | 
					    fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n",
 | 
				
			||||||
            autotox->index, mod_type, tox_group_mod_event_to_string(mod_type),
 | 
					            autotox->index, mod_type, tox_group_mod_event_to_string(mod_type),
 | 
				
			||||||
@@ -281,17 +285,17 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (mod_type) {
 | 
					    switch (mod_type) {
 | 
				
			||||||
        case TOX_GROUP_MOD_EVENT_MODERATOR: {
 | 
					        case TOX_GROUP_MOD_EVENT_MODERATOR: {
 | 
				
			||||||
            handle_mod(state, peer_name, peer_name_len, role);
 | 
					            handle_mod(state, peer_name, peer_name_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case TOX_GROUP_MOD_EVENT_OBSERVER: {
 | 
					        case TOX_GROUP_MOD_EVENT_OBSERVER: {
 | 
				
			||||||
            handle_observer(state, peer_name, peer_name_len, role);
 | 
					            handle_observer(state, peer_name, peer_name_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case TOX_GROUP_MOD_EVENT_USER: {
 | 
					        case TOX_GROUP_MOD_EVENT_USER: {
 | 
				
			||||||
            handle_user(state, peer_name, peer_name_len, role);
 | 
					            handle_user(state, peer_name, peer_name_len);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -314,7 +318,7 @@ static void check_self_role(AutoTox *autotoxes, uint32_t peer_id, Tox_Group_Role
 | 
				
			|||||||
    Tox_Err_Group_Self_Query sq_err;
 | 
					    Tox_Err_Group_Self_Query sq_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (const State *)autotoxes[i].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint32_t self_peer_id = tox_group_self_get_peer_id(autotoxes[i].tox, state->group_number, &sq_err);
 | 
					        uint32_t self_peer_id = tox_group_self_get_peer_id(autotoxes[i].tox, state->group_number, &sq_err);
 | 
				
			||||||
        ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					        ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
@@ -378,13 +382,13 @@ static void voice_state_message_test(AutoTox *autotox, Tox_Group_Voice_State voi
 | 
				
			|||||||
static bool all_peers_got_voice_state_change(AutoTox *autotoxes, uint32_t num_toxes,
 | 
					static bool all_peers_got_voice_state_change(AutoTox *autotoxes, uint32_t num_toxes,
 | 
				
			||||||
        Tox_Group_Voice_State expected_voice_state)
 | 
					        Tox_Group_Voice_State expected_voice_state)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
					    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
				
			||||||
        const State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (State *)autotoxes[i].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Tox_Group_Voice_State voice_state = tox_group_get_voice_state(autotoxes[i].tox, state->group_number, &query_err);
 | 
					        Tox_Group_Voice_State voice_state = tox_group_get_voice_state(autotoxes[i].tox, state->group_number, &query_err);
 | 
				
			||||||
        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (voice_state != expected_voice_state) {
 | 
					        if (voice_state != expected_voice_state) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -398,10 +402,10 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    // founder sets voice state to Moderator
 | 
					    // founder sets voice state to Moderator
 | 
				
			||||||
    const State *state = (State *)autotoxes[0].state;
 | 
					    const State *state = (State *)autotoxes[0].state;
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Voice_State voice_set_err;
 | 
					    Tox_Err_Group_Set_Voice_State voice_set_err;
 | 
				
			||||||
    tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR,
 | 
					    tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR,
 | 
				
			||||||
                              &voice_set_err);
 | 
					                              &voice_set_err);
 | 
				
			||||||
    ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
 | 
					    ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
					    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
@@ -411,8 +415,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
 | 
				
			|||||||
        voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_MODERATOR);
 | 
					        voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_MODERATOR);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err);
 | 
					    tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err);
 | 
				
			||||||
    ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
 | 
					    ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
					    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
@@ -422,8 +426,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
 | 
				
			|||||||
        voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_FOUNDER);
 | 
					        voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_FOUNDER);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err);
 | 
					    tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err);
 | 
				
			||||||
    ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK);
 | 
					    ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
					    for (uint32_t i = 0; i < num_toxes; ++i) {
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
@@ -447,9 +451,9 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
        snprintf(state->self_name, sizeof(state->self_name), "peer_%zu", i);
 | 
					        snprintf(state->self_name, sizeof(state->self_name), "peer_%zu", i);
 | 
				
			||||||
        state->self_name[name_length] = 0;
 | 
					        state->self_name[name_length] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler);
 | 
					        tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
        tox_callback_group_moderation(autotoxes[i].tox, group_mod_event_handler);
 | 
					        tox_events_callback_group_moderation(autotoxes[i].dispatch, group_mod_event_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
@@ -468,11 +472,11 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(err_new == TOX_ERR_GROUP_NEW_OK, "Failed to create group. error: %d\n", err_new);
 | 
					    ck_assert_msg(err_new == TOX_ERR_GROUP_NEW_OK, "Failed to create group. error: %d\n", err_new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Founder gets chat ID */
 | 
					    /* Founder gets chat ID */
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
    tox_group_get_chat_id(tox0, state0->group_number, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, state0->group_number, chat_id, &id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get chat ID. error: %d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get chat ID. error: %d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Peers attemping to join DHT group via the chat ID\n");
 | 
					    fprintf(stderr, "Peers attemping to join DHT group via the chat ID\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -512,7 +516,7 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* all peers should be user role except founder */
 | 
					    /* all peers should be user role except founder */
 | 
				
			||||||
    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        const State *state = (const State *)autotoxes[i].state;
 | 
				
			||||||
        self_role = tox_group_self_get_role(autotoxes[i].tox, state->group_number, &sq_err);
 | 
					        self_role = tox_group_self_get_role(autotoxes[i].tox, state->group_number, &sq_err);
 | 
				
			||||||
        ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					        ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
        ck_assert(self_role == TOX_GROUP_ROLE_USER);
 | 
					        ck_assert(self_role == TOX_GROUP_ROLE_USER);
 | 
				
			||||||
@@ -521,9 +525,9 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
    /* founder sets first peer to moderator */
 | 
					    /* founder sets first peer to moderator */
 | 
				
			||||||
    fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[0].name);
 | 
					    fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[0].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Mod_Set_Role role_err;
 | 
					    Tox_Err_Group_Set_Role role_err;
 | 
				
			||||||
    tox_group_mod_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
 | 
					    tox_group_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // manually flag the role setter because they don't get a callback
 | 
					    // manually flag the role setter because they don't get a callback
 | 
				
			||||||
    state0->mod_check = true;
 | 
					    state0->mod_check = true;
 | 
				
			||||||
@@ -537,8 +541,8 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
    /* founder sets second and third peer to observer */
 | 
					    /* founder sets second and third peer to observer */
 | 
				
			||||||
    fprintf(stderr, "Founder setting %s to observer\n", state0->peers[1].name);
 | 
					    fprintf(stderr, "Founder setting %s to observer\n", state0->peers[1].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_mod_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
					    tox_group_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state0->observer_check = true;
 | 
					    state0->observer_check = true;
 | 
				
			||||||
    ++state0->observer_event_count;
 | 
					    ++state0->observer_event_count;
 | 
				
			||||||
@@ -548,8 +552,8 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Founder setting %s to observer\n", state0->peers[2].name);
 | 
					    fprintf(stderr, "Founder setting %s to observer\n", state0->peers[2].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
					    tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state0->observer_check = true;
 | 
					    state0->observer_check = true;
 | 
				
			||||||
    ++state0->observer_event_count;
 | 
					    ++state0->observer_event_count;
 | 
				
			||||||
@@ -574,8 +578,8 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "%s is promoting %s back to user\n", state1->self_name, state0->peers[1].name);
 | 
					    fprintf(stderr, "%s is promoting %s back to user\n", state1->self_name, state0->peers[1].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_mod_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err);
 | 
					    tox_group_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to promote observer back to user. error: %d",
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to promote observer back to user. error: %d",
 | 
				
			||||||
                  role_err);
 | 
					                  role_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state1->user_check = true;
 | 
					    state1->user_check = true;
 | 
				
			||||||
@@ -587,8 +591,8 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
    /* founder assigns third peer to moderator (this triggers two events: user and moderator) */
 | 
					    /* founder assigns third peer to moderator (this triggers two events: user and moderator) */
 | 
				
			||||||
    fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[2].name);
 | 
					    fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[2].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
 | 
					    tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state0->mod_check = true;
 | 
					    state0->mod_check = true;
 | 
				
			||||||
    ++state0->mod_event_count;
 | 
					    ++state0->mod_event_count;
 | 
				
			||||||
@@ -600,18 +604,27 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* moderator attempts to demote and kick founder */
 | 
					    /* moderator attempts to demote and kick founder */
 | 
				
			||||||
    uint32_t founder_peer_id = get_peer_id_by_nick(state1->peers, NUM_GROUP_TOXES - 1, state0->self_name);
 | 
					    uint32_t founder_peer_id = get_peer_id_by_nick(state1->peers, NUM_GROUP_TOXES - 1, state0->self_name);
 | 
				
			||||||
    tox_group_mod_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
					    tox_group_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
 | 
				
			||||||
    ck_assert_msg(role_err != TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Mod set founder to observer");
 | 
					    ck_assert_msg(role_err != TOX_ERR_GROUP_SET_ROLE_OK, "Mod set founder to observer");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Mod_Kick_Peer k_err;
 | 
					    Tox_Err_Group_Kick_Peer k_err;
 | 
				
			||||||
    tox_group_mod_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err);
 | 
					    tox_group_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err);
 | 
				
			||||||
    ck_assert_msg(k_err != TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Mod kicked founder");
 | 
					    ck_assert_msg(k_err != TOX_ERR_GROUP_KICK_PEER_OK, "Mod kicked founder");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* the moderator about to be kicked changes the topic to trigger the founder to
 | 
				
			||||||
 | 
					     * re-sign and redistribute it after the kick.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    const State *state_x = (const State *)autotoxes[idx].state;
 | 
				
			||||||
 | 
					    Tox *tox_x = autotoxes[idx].tox;
 | 
				
			||||||
 | 
					    Tox_Err_Group_Topic_Set topic_err;
 | 
				
			||||||
 | 
					    tox_group_set_topic(tox_x, state_x->group_number, nullptr, 0, &topic_err);
 | 
				
			||||||
 | 
					    ck_assert(topic_err == TOX_ERR_GROUP_TOPIC_SET_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* founder kicks moderator (this triggers two events: user and kick) */
 | 
					    /* founder kicks moderator (this triggers two events: user and kick) */
 | 
				
			||||||
    fprintf(stderr, "Founder is kicking %s\n", state0->peers[0].name);
 | 
					    fprintf(stderr, "Founder is kicking %s\n", state0->peers[0].name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_mod_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err);
 | 
					    tox_group_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err);
 | 
				
			||||||
    ck_assert_msg(k_err == TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err);
 | 
					    ck_assert_msg(k_err == TOX_ERR_GROUP_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state0->kick_check = true;
 | 
					    state0->kick_check = true;
 | 
				
			||||||
    check_mod_event(autotoxes, NUM_GROUP_TOXES, TOX_GROUP_MOD_EVENT_KICK);
 | 
					    check_mod_event(autotoxes, NUM_GROUP_TOXES, TOX_GROUP_MOD_EVENT_KICK);
 | 
				
			||||||
@@ -619,9 +632,8 @@ static void group_moderation_test(AutoTox *autotoxes)
 | 
				
			|||||||
    fprintf(stderr, "All peers successfully received kick event\n");
 | 
					    fprintf(stderr, "All peers successfully received kick event\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Founder is demoting moderator to user\n");
 | 
					    fprintf(stderr, "Founder is demoting moderator to user\n");
 | 
				
			||||||
 | 
					    tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err);
 | 
				
			||||||
    tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err);
 | 
					    ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
 | 
				
			||||||
    ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state0->user_check = true;
 | 
					    state0->user_check = true;
 | 
				
			||||||
    ++state0->user_event_count;
 | 
					    ++state0->user_event_count;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,17 +26,23 @@ typedef struct State {
 | 
				
			|||||||
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1)
 | 
					#define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1)
 | 
				
			||||||
#define NEW_USER_STATUS TOX_USER_STATUS_BUSY
 | 
					#define NEW_USER_STATUS TOX_USER_STATUS_BUSY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
 | 
					static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
 | 
				
			||||||
                                 const uint8_t *group_name, size_t group_name_length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_invite_get_invite_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Invite_Accept err_accept;
 | 
					    Tox_Err_Group_Invite_Accept err_accept;
 | 
				
			||||||
    tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
 | 
					    tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
 | 
				
			||||||
                            nullptr, 0, &err_accept);
 | 
					                            nullptr, 0, &err_accept);
 | 
				
			||||||
    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
					    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
@@ -52,28 +58,28 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id)
 | 
					static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err);
 | 
					    Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (priv_state != NEW_PRIV_STATE) {
 | 
					    if (priv_state != NEW_PRIV_STATE) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
 | 
					    size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
 | 
					    uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
 | 
				
			||||||
    tox_group_get_password(tox, group_number, password, &query_err);
 | 
					    tox_group_get_password(tox, group_number, password, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) {
 | 
					    if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) {
 | 
				
			||||||
        return -2;
 | 
					        return -2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
 | 
					    size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
 | 
					    uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
 | 
				
			||||||
    tox_group_get_name(tox, group_number, group_name, &query_err);
 | 
					    tox_group_get_name(tox, group_number, group_name, &query_err);
 | 
				
			||||||
@@ -87,17 +93,17 @@ static int has_correct_group_state(const Tox *tox, uint32_t group_number, const
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err);
 | 
					    Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) {
 | 
					    if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) {
 | 
				
			||||||
        return -5;
 | 
					        return -5;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
    tox_group_get_chat_id(tox, group_number, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox, group_number, chat_id, &id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) {
 | 
					    if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) {
 | 
				
			||||||
        return -6;
 | 
					        return -6;
 | 
				
			||||||
@@ -120,7 +126,7 @@ static int has_correct_self_state(const Tox *tox, uint32_t group_number, const u
 | 
				
			|||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TOX_USER_STATUS self_status = tox_group_self_get_status(tox, group_number, &sq_err);
 | 
					    Tox_User_Status self_status = tox_group_self_get_status(tox, group_number, &sq_err);
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (self_status != NEW_USER_STATUS) {
 | 
					    if (self_status != NEW_USER_STATUS) {
 | 
				
			||||||
@@ -151,8 +157,8 @@ static void group_save_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
					    ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_invite(autotoxes[i].tox, group_invite_handler);
 | 
					        tox_events_callback_group_invite(autotoxes[i].dispatch, group_invite_handler);
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
@@ -168,9 +174,9 @@ static void group_save_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    tox_group_get_chat_id(tox0, group_number, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, group_number, chat_id, &id_err);
 | 
				
			||||||
    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
 | 
					    uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -178,7 +184,6 @@ static void group_save_test(AutoTox *autotoxes)
 | 
				
			|||||||
    tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err);
 | 
					    tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err);
 | 
				
			||||||
    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
					    ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    Tox_Err_Group_Invite_Friend err_invite;
 | 
					    Tox_Err_Group_Invite_Friend err_invite;
 | 
				
			||||||
    tox_group_invite_friend(tox0, group_number, 0, &err_invite);
 | 
					    tox_group_invite_friend(tox0, group_number, 0, &err_invite);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -195,21 +200,21 @@ static void group_save_test(AutoTox *autotoxes)
 | 
				
			|||||||
    tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err);
 | 
					    tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err);
 | 
				
			||||||
    ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK);
 | 
					    ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
 | 
					    Tox_Err_Group_Set_Topic_Lock lock_set_err;
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
				
			||||||
    ck_assert(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK);
 | 
					    ck_assert(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Privacy_State priv_err;
 | 
					    Tox_Err_Group_Set_Privacy_State priv_err;
 | 
				
			||||||
    tox_group_founder_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
 | 
					    tox_group_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
 | 
				
			||||||
    ck_assert(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK);
 | 
					    ck_assert(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Password pass_set_err;
 | 
					    Tox_Err_Group_Set_Password pass_set_err;
 | 
				
			||||||
    tox_group_founder_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
 | 
					    tox_group_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
 | 
				
			||||||
    ck_assert(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK);
 | 
					    ck_assert(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
 | 
					    Tox_Err_Group_Set_Peer_Limit limit_set_err;
 | 
				
			||||||
    tox_group_founder_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
 | 
					    tox_group_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
 | 
				
			||||||
    ck_assert(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK);
 | 
					    ck_assert(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // change self state
 | 
					    // change self state
 | 
				
			||||||
    Tox_Err_Group_Self_Name_Set n_err;
 | 
					    Tox_Err_Group_Self_Name_Set n_err;
 | 
				
			||||||
@@ -241,8 +246,8 @@ static void group_save_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert(options != nullptr);
 | 
					    ck_assert(options != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
 | 
					    tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    tox_options_set_savedata_data(options, save, save_length);
 | 
					    tox_options_set_savedata_data(options, save, save_length);
 | 
				
			||||||
 | 
					    tox_options_set_experimental_groups_persistence(options, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *new_tox = tox_new_log(options, nullptr, nullptr);
 | 
					    Tox *new_tox = tox_new_log(options, nullptr, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -278,7 +283,11 @@ int main(void)
 | 
				
			|||||||
    Run_Auto_Options autotest_opts = default_run_auto_options();
 | 
					    Run_Auto_Options autotest_opts = default_run_auto_options();
 | 
				
			||||||
    autotest_opts.graph = GRAPH_COMPLETE;
 | 
					    autotest_opts.graph = GRAPH_COMPLETE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    run_auto_test(nullptr, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
 | 
					    Tox_Options *opts = tox_options_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(opts != nullptr);
 | 
				
			||||||
 | 
					    tox_options_set_experimental_groups_persistence(opts, true);
 | 
				
			||||||
 | 
					    run_auto_test(opts, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
 | 
				
			||||||
 | 
					    tox_options_free(opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,66 +60,97 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock,
 | 
					static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event,
 | 
				
			||||||
                                     void *user_data)
 | 
					                                     void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    const AutoTox *autotox = (const AutoTox *)user_data;
 | 
				
			||||||
    Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t groupnumber = tox_event_group_topic_lock_get_group_number(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(autotox->tox, groupnumber, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(current_topic_lock == topic_lock, "topic locks don't match in callback: %d %d",
 | 
					    ck_assert_msg(current_topic_lock == topic_lock, "topic locks don't match in callback: %d %d",
 | 
				
			||||||
                  topic_lock, current_topic_lock);
 | 
					                  topic_lock, current_topic_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_voice_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Voice_State voice_state,
 | 
					static void group_voice_state_handler(const Tox_Event_Group_Voice_State *event,
 | 
				
			||||||
                                      void *user_data)
 | 
					                                      void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    const AutoTox *autotox = (const AutoTox *)user_data;
 | 
				
			||||||
    Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t groupnumber = tox_event_group_voice_state_get_group_number(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Voice_State voice_state = tox_event_group_voice_state_get_voice_state(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(autotox->tox, groupnumber, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(current_voice_state == voice_state, "voice states don't match in callback: %d %d",
 | 
					    ck_assert_msg(current_voice_state == voice_state, "voice states don't match in callback: %d %d",
 | 
				
			||||||
                  voice_state, current_voice_state);
 | 
					                  voice_state, current_voice_state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_privacy_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Privacy_State privacy_state,
 | 
					static void group_privacy_state_handler(const Tox_Event_Group_Privacy_State *event,
 | 
				
			||||||
                                        void *user_data)
 | 
					                                        void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    const AutoTox *autotox = (const AutoTox *)user_data;
 | 
				
			||||||
    Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t groupnumber = tox_event_group_privacy_state_get_group_number(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Privacy_State privacy_state = tox_event_group_privacy_state_get_privacy_state(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(autotox->tox, groupnumber, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(current_pstate == privacy_state, "privacy states don't match in callback");
 | 
					    ck_assert_msg(current_pstate == privacy_state, "privacy states don't match in callback");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_limit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_limit, void *user_data)
 | 
					static void group_peer_limit_handler(const Tox_Event_Group_Peer_Limit *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    const AutoTox *autotox = (const AutoTox *)user_data;
 | 
				
			||||||
    uint32_t current_plimit = tox_group_get_peer_limit(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t groupnumber = tox_event_group_peer_limit_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_limit = tox_event_group_peer_limit_get_peer_limit(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    uint32_t current_plimit = tox_group_get_peer_limit(autotox->tox, groupnumber, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(peer_limit == current_plimit,
 | 
					    ck_assert_msg(peer_limit == current_plimit,
 | 
				
			||||||
                  "Peer limits don't match in callback: %u, %u\n", peer_limit, current_plimit);
 | 
					                  "Peer limits don't match in callback: %u, %u\n", peer_limit, current_plimit);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_password_handler(Tox *tox, uint32_t groupnumber, const uint8_t *password, size_t length,
 | 
					static void group_password_handler(const Tox_Event_Group_Password *event,
 | 
				
			||||||
                                   void *user_data)
 | 
					                                   void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    size_t curr_pwlength = tox_group_get_password_size(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t groupnumber = tox_event_group_password_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *password = tox_event_group_password_get_password(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_password_get_password_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    size_t curr_pwlength = tox_group_get_password_size(autotox->tox, groupnumber, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert(length == curr_pwlength);
 | 
					    ck_assert(length == curr_pwlength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t current_password[TOX_GROUP_MAX_PASSWORD_SIZE];
 | 
					    uint8_t current_password[TOX_GROUP_MAX_PASSWORD_SIZE];
 | 
				
			||||||
    tox_group_get_password(tox, groupnumber, current_password, &err);
 | 
					    tox_group_get_password(autotox->tox, groupnumber, current_password, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(memcmp(current_password, password, length) == 0,
 | 
					    ck_assert_msg(memcmp(current_password, password, length) == 0,
 | 
				
			||||||
                  "Passwords don't match: %s, %s", password, current_password);
 | 
					                  "Passwords don't match: %s, %s", password, current_password);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
@@ -137,24 +168,24 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
 | 
				
			|||||||
                             Tox_Group_Privacy_State priv_state, Tox_Group_Voice_State voice_state,
 | 
					                             Tox_Group_Privacy_State priv_state, Tox_Group_Voice_State voice_state,
 | 
				
			||||||
                             const uint8_t *password, size_t pass_len, Tox_Group_Topic_Lock topic_lock)
 | 
					                             const uint8_t *password, size_t pass_len, Tox_Group_Topic_Lock topic_lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Privacy_State my_priv_state = tox_group_get_privacy_state(tox, groupnumber, &query_err);
 | 
					    Tox_Group_Privacy_State my_priv_state = tox_group_get_privacy_state(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get privacy state: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get privacy state: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (my_priv_state != priv_state) {
 | 
					    if (my_priv_state != priv_state) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t my_peer_limit = tox_group_get_peer_limit(tox, groupnumber, &query_err);
 | 
					    uint32_t my_peer_limit = tox_group_get_peer_limit(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get peer limit: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get peer limit: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (my_peer_limit != peer_limit) {
 | 
					    if (my_peer_limit != peer_limit) {
 | 
				
			||||||
        return -2;
 | 
					        return -2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t my_pass_len = tox_group_get_password_size(tox, groupnumber, &query_err);
 | 
					    size_t my_pass_len = tox_group_get_password_size(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password size: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password size: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (my_pass_len != pass_len) {
 | 
					    if (my_pass_len != pass_len) {
 | 
				
			||||||
        return -5;
 | 
					        return -5;
 | 
				
			||||||
@@ -163,10 +194,10 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
 | 
				
			|||||||
    if (password != nullptr && my_pass_len > 0) {
 | 
					    if (password != nullptr && my_pass_len > 0) {
 | 
				
			||||||
        ck_assert(my_pass_len <= TOX_GROUP_MAX_PASSWORD_SIZE);
 | 
					        ck_assert(my_pass_len <= TOX_GROUP_MAX_PASSWORD_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE];
 | 
					        uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE + 1];
 | 
				
			||||||
        tox_group_get_password(tox, groupnumber, my_pass, &query_err);
 | 
					        tox_group_get_password(tox, groupnumber, my_pass, &query_err);
 | 
				
			||||||
        my_pass[my_pass_len] = 0;
 | 
					        my_pass[my_pass_len] = 0;
 | 
				
			||||||
        ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password: %d", query_err);
 | 
					        ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (memcmp(my_pass, password, my_pass_len) != 0) {
 | 
					        if (memcmp(my_pass, password, my_pass_len) != 0) {
 | 
				
			||||||
            return -6;
 | 
					            return -6;
 | 
				
			||||||
@@ -175,7 +206,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* Group name should never change */
 | 
					    /* Group name should never change */
 | 
				
			||||||
    size_t my_gname_len = tox_group_get_name_size(tox, groupnumber, &query_err);
 | 
					    size_t my_gname_len = tox_group_get_name_size(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get group name size: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get group name size: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (my_gname_len != GROUP_NAME_LEN) {
 | 
					    if (my_gname_len != GROUP_NAME_LEN) {
 | 
				
			||||||
        return -7;
 | 
					        return -7;
 | 
				
			||||||
@@ -183,7 +214,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert(my_gname_len <= TOX_GROUP_MAX_GROUP_NAME_LENGTH);
 | 
					    ck_assert(my_gname_len <= TOX_GROUP_MAX_GROUP_NAME_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
 | 
					    uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH + 1];
 | 
				
			||||||
    tox_group_get_name(tox, groupnumber, my_gname, &query_err);
 | 
					    tox_group_get_name(tox, groupnumber, my_gname, &query_err);
 | 
				
			||||||
    my_gname[my_gname_len] = 0;
 | 
					    my_gname[my_gname_len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -192,14 +223,14 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &query_err);
 | 
					    Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get topic lock: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get topic lock: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (current_topic_lock != topic_lock) {
 | 
					    if (current_topic_lock != topic_lock) {
 | 
				
			||||||
        return -9;
 | 
					        return -9;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &query_err);
 | 
					    Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &query_err);
 | 
				
			||||||
    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get voice state: %d", query_err);
 | 
					    ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get voice state: %d", query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (current_voice_state != voice_state) {
 | 
					    if (current_voice_state != voice_state) {
 | 
				
			||||||
        return -10;
 | 
					        return -10;
 | 
				
			||||||
@@ -213,26 +244,26 @@ static void set_group_state(Tox *tox, uint32_t groupnumber, uint32_t peer_limit,
 | 
				
			|||||||
                            Tox_Group_Topic_Lock topic_lock)
 | 
					                            Tox_Group_Topic_Lock topic_lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err;
 | 
					    Tox_Err_Group_Set_Peer_Limit limit_set_err;
 | 
				
			||||||
    tox_group_founder_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err);
 | 
					    tox_group_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err);
 | 
				
			||||||
    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
 | 
					    ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Privacy_State priv_err;
 | 
					    Tox_Err_Group_Set_Privacy_State priv_err;
 | 
				
			||||||
    tox_group_founder_set_privacy_state(tox, groupnumber, priv_state, &priv_err);
 | 
					    tox_group_set_privacy_state(tox, groupnumber, priv_state, &priv_err);
 | 
				
			||||||
    ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err);
 | 
					    ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Password pass_set_err;
 | 
					    Tox_Err_Group_Set_Password pass_set_err;
 | 
				
			||||||
    tox_group_founder_set_password(tox, groupnumber, password, pass_len, &pass_set_err);
 | 
					    tox_group_set_password(tox, groupnumber, password, pass_len, &pass_set_err);
 | 
				
			||||||
    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err);
 | 
					    ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
 | 
					    Tox_Err_Group_Set_Topic_Lock lock_set_err;
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err);
 | 
				
			||||||
    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d",
 | 
					    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d",
 | 
				
			||||||
                  lock_set_err);
 | 
					                  lock_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Voice_State voice_set_err;
 | 
					    Tox_Err_Group_Set_Voice_State voice_set_err;
 | 
				
			||||||
    tox_group_founder_set_voice_state(tox, groupnumber, voice_state, &voice_set_err);
 | 
					    tox_group_set_voice_state(tox, groupnumber, voice_state, &voice_set_err);
 | 
				
			||||||
    ck_assert_msg(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK, "failed to set voice state: %d",
 | 
					    ck_assert_msg(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK, "failed to set voice state: %d",
 | 
				
			||||||
                  voice_set_err);
 | 
					                  voice_set_err);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -241,12 +272,12 @@ static void group_state_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
					    ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_privacy_state(autotoxes[i].tox, group_privacy_state_handler);
 | 
					        tox_events_callback_group_privacy_state(autotoxes[i].dispatch, group_privacy_state_handler);
 | 
				
			||||||
        tox_callback_group_peer_limit(autotoxes[i].tox, group_peer_limit_handler);
 | 
					        tox_events_callback_group_peer_limit(autotoxes[i].dispatch, group_peer_limit_handler);
 | 
				
			||||||
        tox_callback_group_password(autotoxes[i].tox, group_password_handler);
 | 
					        tox_events_callback_group_password(autotoxes[i].dispatch, group_password_handler);
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
        tox_callback_group_voice_state(autotoxes[i].tox, group_voice_state_handler);
 | 
					        tox_events_callback_group_voice_state(autotoxes[i].dispatch, group_voice_state_handler);
 | 
				
			||||||
        tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler);
 | 
					        tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
@@ -263,11 +294,11 @@ static void group_state_test(AutoTox *autotoxes)
 | 
				
			|||||||
                    (const uint8_t *)PASSWORD, PASS_LEN, TOX_GROUP_TOPIC_LOCK_ENABLED);
 | 
					                    (const uint8_t *)PASSWORD, PASS_LEN, TOX_GROUP_TOPIC_LOCK_ENABLED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Founder gets the Chat ID and implicitly shares it publicly */
 | 
					    /* Founder gets the Chat ID and implicitly shares it publicly */
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
    tox_group_get_chat_id(tox0, groupnum, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, groupnum, chat_id, &id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* All other peers join the group using the Chat ID and password */
 | 
					    /* All other peers join the group using the Chat ID and password */
 | 
				
			||||||
    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,38 +96,42 @@ static void peers_cleanup(Peers *peers)
 | 
				
			|||||||
    free(peers);
 | 
					    free(peers);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(add_peer(state->peers, peer_id) == 0);
 | 
					    ck_assert(add_peer(state->peers, peer_id) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type,
 | 
					static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
 | 
				
			||||||
                                    const uint8_t *name, size_t name_length, const uint8_t *part_message,
 | 
					 | 
				
			||||||
                                    size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_exit_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(del_peer(state->peers, peer_id) == 0);
 | 
					    ck_assert(del_peer(state->peers, peer_id) == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic,
 | 
					static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
 | 
				
			||||||
                                size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *topic = tox_event_group_topic_get_topic(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_topic_get_topic_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
 | 
					    ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memcpy(state->callback_topic, (const char *)topic, length);
 | 
					    memcpy(state->callback_topic, (const char *)topic, length);
 | 
				
			||||||
@@ -201,7 +205,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
 | 
				
			|||||||
        int64_t peer_id = state0->peers->peer_ids[idx];
 | 
					        int64_t peer_id = state0->peers->peer_ids[idx];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (peer_id >= 0) {
 | 
					        if (peer_id >= 0) {
 | 
				
			||||||
            tox_group_mod_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr);
 | 
					            tox_group_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // mods randomly promote or demote one of the non-mods
 | 
					        // mods randomly promote or demote one of the non-mods
 | 
				
			||||||
@@ -218,7 +222,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
 | 
				
			|||||||
                peer_id = state_j->peers->peer_ids[i];
 | 
					                peer_id = state_j->peers->peer_ids[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (peer_id >= 0) {
 | 
					                if (peer_id >= 0) {
 | 
				
			||||||
                    tox_group_mod_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr);
 | 
					                    tox_group_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -260,14 +264,14 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t expected_topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
					    uint8_t expected_topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
    size_t expected_topic_length = tox_group_get_topic_size(autotoxes[0].tox, groupnumber, &query_err);
 | 
					    size_t expected_topic_length = tox_group_get_topic_size(autotoxes[0].tox, groupnumber, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_get_topic(autotoxes[0].tox, groupnumber, expected_topic, &query_err);
 | 
					    tox_group_get_topic(autotoxes[0].tox, groupnumber, expected_topic, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const State *state0 = (const State *)autotoxes[0].state;
 | 
					    const State *state0 = (const State *)autotoxes[0].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -282,7 +286,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
 | 
				
			|||||||
    for (size_t i = 1; i < num_peers; ++i) {
 | 
					    for (size_t i = 1; i < num_peers; ++i) {
 | 
				
			||||||
        size_t topic_length = tox_group_get_topic_size(autotoxes[i].tox, groupnumber, &query_err);
 | 
					        size_t topic_length = tox_group_get_topic_size(autotoxes[i].tox, groupnumber, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (topic_length != expected_topic_length) {
 | 
					        if (topic_length != expected_topic_length) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -291,7 +295,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
 | 
				
			|||||||
        uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
					        uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
				
			||||||
        tox_group_get_topic(autotoxes[i].tox, groupnumber, topic, &query_err);
 | 
					        tox_group_get_topic(autotoxes[i].tox, groupnumber, topic, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					        ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (memcmp(expected_topic, (const char *)topic, topic_length) != 0) {
 | 
					        if (memcmp(expected_topic, (const char *)topic, topic_length) != 0) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
@@ -331,13 +335,13 @@ static void topic_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers
 | 
				
			|||||||
static void group_sync_test(AutoTox *autotoxes)
 | 
					static void group_sync_test(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert(NUM_GROUP_TOXES >= 5);
 | 
					    ck_assert(NUM_GROUP_TOXES >= 5);
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
        tox_callback_group_topic(autotoxes[i].tox, group_topic_handler);
 | 
					        tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
 | 
				
			||||||
        tox_callback_group_peer_exit(autotoxes[i].tox, group_peer_exit_handler);
 | 
					        tox_events_callback_group_peer_exit(autotoxes[i].dispatch, group_peer_exit_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        State *state = (State *)autotoxes[i].state;
 | 
					        State *state = (State *)autotoxes[i].state;
 | 
				
			||||||
        state->peers = (Peers *)calloc(1, sizeof(Peers));
 | 
					        state->peers = (Peers *)calloc(1, sizeof(Peers));
 | 
				
			||||||
@@ -356,11 +360,11 @@ static void group_sync_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "tox0 creats new group and invites all his friends");
 | 
					    fprintf(stderr, "tox0 creats new group and invites all his friends");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        Tox_Err_Group_Join join_err;
 | 
					        Tox_Err_Group_Join join_err;
 | 
				
			||||||
@@ -375,9 +379,9 @@ static void group_sync_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "%d peers joined the group\n", NUM_GROUP_TOXES);
 | 
					    fprintf(stderr, "%d peers joined the group\n", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
 | 
					    Tox_Err_Group_Set_Topic_Lock lock_set_err;
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
				
			||||||
    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
 | 
					    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
 | 
				
			||||||
                  lock_set_err);
 | 
					                  lock_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
@@ -388,8 +392,8 @@ static void group_sync_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
					    iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
 | 
				
			||||||
    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
 | 
					    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
 | 
				
			||||||
                  lock_set_err);
 | 
					                  lock_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
@@ -398,12 +402,12 @@ static void group_sync_test(AutoTox *autotoxes)
 | 
				
			|||||||
             && !all_peers_see_same_roles(autotoxes, NUM_GROUP_TOXES, groupnumber)
 | 
					             && !all_peers_see_same_roles(autotoxes, NUM_GROUP_TOXES, groupnumber)
 | 
				
			||||||
             && state0->peers->num_peers != NUM_GROUP_TOXES - 1);
 | 
					             && state0->peers->num_peers != NUM_GROUP_TOXES - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Mod_Set_Role role_err;
 | 
					    Tox_Err_Group_Set_Role role_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < state0->peers->num_peers; ++i) {
 | 
					    for (size_t i = 0; i < state0->peers->num_peers; ++i) {
 | 
				
			||||||
        tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR,
 | 
					        tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR,
 | 
				
			||||||
                           &role_err);
 | 
					                           &role_err);
 | 
				
			||||||
        ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
					        ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "founder enabled topic lock and set all peers to moderator role\n");
 | 
					    fprintf(stderr, "founder enabled topic lock and set all peers to moderator role\n");
 | 
				
			||||||
@@ -419,9 +423,9 @@ static void group_sync_test(AutoTox *autotoxes)
 | 
				
			|||||||
    fprintf(stderr, "founder demoting %u moderators to user\n", num_demoted);
 | 
					    fprintf(stderr, "founder demoting %u moderators to user\n", num_demoted);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < num_demoted; ++i) {
 | 
					    for (size_t i = 0; i < num_demoted; ++i) {
 | 
				
			||||||
        tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER,
 | 
					        tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER,
 | 
				
			||||||
                           &role_err);
 | 
					                           &role_err);
 | 
				
			||||||
        ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set user. error: %d", role_err);
 | 
					        ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set user. error: %d", role_err);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,32 +19,43 @@ typedef struct State {
 | 
				
			|||||||
    uint32_t peer_id[NUM_GROUP_TOXES - 1];
 | 
					    uint32_t peer_id[NUM_GROUP_TOXES - 1];
 | 
				
			||||||
} State;
 | 
					} State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length,
 | 
					static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
 | 
				
			||||||
                                 const uint8_t *group_name, size_t group_name_length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_invite_get_invite_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Accepting friend invite\n");
 | 
					    printf("Accepting friend invite\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_Invite_Accept err_accept;
 | 
					    Tox_Err_Group_Invite_Accept err_accept;
 | 
				
			||||||
    tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test", 4,
 | 
					    tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test", 4,
 | 
				
			||||||
                            nullptr, 0, &err_accept);
 | 
					                            nullptr, 0, &err_accept);
 | 
				
			||||||
    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
					    ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "joined: %zu, %u\n", state->num_peers, peer_id);
 | 
					    fprintf(stderr, "joined: %zu, %u\n", state->num_peers, peer_id);
 | 
				
			||||||
    ck_assert_msg(state->num_peers < NUM_GROUP_TOXES - 1, "%zu", state->num_peers);
 | 
					    ck_assert_msg(state->num_peers < NUM_GROUP_TOXES - 1, "%zu", state->num_peers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state->peer_id[state->num_peers++] = peer_id;
 | 
					    state->peer_id[state->num_peers++] = peer_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
					static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
 | 
				
			||||||
        const uint8_t *message, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_private_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_private_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,9 +69,11 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
 | 
				
			|||||||
    state->got_code = true;
 | 
					    state->got_code = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
 | 
					static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
 | 
				
			||||||
                                  const uint8_t *message, size_t length, uint32_t message_id, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_group_message_get_message(event);
 | 
				
			||||||
 | 
					    const size_t length = tox_event_group_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,12 +146,12 @@ static void group_tcp_test(AutoTox *autotoxes)
 | 
				
			|||||||
    State *state1 = (State *)autotoxes[1].state;
 | 
					    State *state1 = (State *)autotoxes[1].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler);
 | 
					        tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
 | 
				
			||||||
        tox_callback_group_private_message(autotoxes[i].tox, group_private_message_handler);
 | 
					        tox_events_callback_group_private_message(autotoxes[i].dispatch, group_private_message_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_group_message(autotoxes[1].tox, group_message_handler);
 | 
					    tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler);
 | 
				
			||||||
    tox_callback_group_invite(autotoxes[1].tox, group_invite_handler);
 | 
					    tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_New new_err;
 | 
					    Tox_Err_Group_New new_err;
 | 
				
			||||||
    uint32_t groupnumber = tox_group_new(autotoxes[0].tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
 | 
					    uint32_t groupnumber = tox_group_new(autotoxes[0].tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
 | 
				
			||||||
@@ -147,11 +160,11 @@ static void group_tcp_test(AutoTox *autotoxes)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    iterate_group(autotoxes, NUM_GROUP_TOXES, GROUP_ITERATION_INTERVAL);
 | 
					    iterate_group(autotoxes, NUM_GROUP_TOXES, GROUP_ITERATION_INTERVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_group_get_chat_id(autotoxes[0].tox, groupnumber, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(autotoxes[0].tox, groupnumber, chat_id, &id_err);
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("Tox 0 created new group...\n");
 | 
					    printf("Tox 0 created new group...\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -168,7 +181,6 @@ static void group_tcp_test(AutoTox *autotoxes)
 | 
				
			|||||||
    printf("%d peers successfully joined. Waiting for code...\n", NUM_GROUP_TOXES);
 | 
					    printf("%d peers successfully joined. Waiting for code...\n", NUM_GROUP_TOXES);
 | 
				
			||||||
    printf("Tox 0 sending secret code to all peers\n");
 | 
					    printf("Tox 0 sending secret code to all peers\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES - 1; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES - 1; ++i) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Tox_Err_Group_Send_Private_Message perr;
 | 
					        Tox_Err_Group_Send_Private_Message perr;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,8 +55,11 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data)
 | 
					static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
 | 
				
			||||||
 | 
					    const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AutoTox *autotox = (AutoTox *)user_data;
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    ck_assert(autotox != nullptr);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,28 +68,41 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
 | 
				
			|||||||
    state->peer_id = peer_id;
 | 
					    state->peer_id = peer_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic,
 | 
					static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
 | 
				
			||||||
                                size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
 | 
					    AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    const uint32_t group_number = tox_event_group_topic_get_group_number(event);
 | 
				
			||||||
 | 
					    //const uint32_t peer_id = tox_event_group_topic_get_peer_id(event);
 | 
				
			||||||
 | 
					    const uint8_t *topic = tox_event_group_topic_get_topic(event);
 | 
				
			||||||
 | 
					    const uint32_t topic_length = tox_event_group_topic_get_topic_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(topic_length <= TOX_GROUP_MAX_TOPIC_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
    uint8_t topic2[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
					    uint8_t topic2[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
				
			||||||
    tox_group_get_topic(tox, groupnumber, topic2, &query_err);
 | 
					    tox_group_get_topic(autotox->tox, group_number, topic2, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
 | 
					    size_t topic_length_getter = tox_group_get_topic_size(autotox->tox, group_number, &query_err);
 | 
				
			||||||
    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(topic_length == length && memcmp(topic, topic2, length) == 0,
 | 
					    ck_assert_msg(topic_length_getter == topic_length && memcmp(topic, topic2, topic_length) == 0,
 | 
				
			||||||
                  "topic differs in callback: %s, %s", topic, topic2);
 | 
					                  "topic differs in callback: %s, %s", topic, topic2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock, void *user_data)
 | 
					static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries err;
 | 
					    const AutoTox *autotox = (const AutoTox *)user_data;
 | 
				
			||||||
    Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(tox, groupnumber, &err);
 | 
					    ck_assert(autotox != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					    const uint32_t group_number = tox_event_group_topic_lock_get_group_number(event);
 | 
				
			||||||
 | 
					    const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Err_Group_State_Query err;
 | 
				
			||||||
 | 
					    Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(autotox->tox, group_number, &err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
    ck_assert_msg(topic_lock == current_lock, "topic locks differ in callback");
 | 
					    ck_assert_msg(topic_lock == current_lock, "topic locks differ in callback");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,10 +123,10 @@ static bool set_topic(Tox *tox, uint32_t groupnumber, const char *topic, size_t
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expected_topic, size_t expected_length)
 | 
					static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expected_topic, size_t expected_length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Tox_Err_Group_State_Queries query_err;
 | 
					    Tox_Err_Group_State_Query query_err;
 | 
				
			||||||
    size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
 | 
					    size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
 | 
					    if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,7 +137,7 @@ static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expecte
 | 
				
			|||||||
    uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
					    uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
 | 
				
			||||||
    tox_group_get_topic(tox, groupnumber, topic, &query_err);
 | 
					    tox_group_get_topic(tox, groupnumber, topic, &query_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
 | 
					    if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
 | 
				
			||||||
        return -3;
 | 
					        return -3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -140,9 +156,9 @@ static void wait_topic_lock(AutoTox *autotoxes, uint32_t groupnumber, Tox_Group_
 | 
				
			|||||||
        uint32_t count = 0;
 | 
					        uint32_t count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					        for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
            Tox_Err_Group_State_Queries err;
 | 
					            Tox_Err_Group_State_Query err;
 | 
				
			||||||
            Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(autotoxes[i].tox, groupnumber, &err);
 | 
					            Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(autotoxes[i].tox, groupnumber, &err);
 | 
				
			||||||
            ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK);
 | 
					            ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (topic_lock == expected_lock) {
 | 
					            if (topic_lock == expected_lock) {
 | 
				
			||||||
                ++count;
 | 
					                ++count;
 | 
				
			||||||
@@ -205,17 +221,18 @@ static void group_topic_test(AutoTox *autotoxes)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
					    ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Tox *tox0 = autotoxes[0].tox;
 | 
					    Tox *tox0 = autotoxes[0].tox;
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch0 = autotoxes[0].dispatch;
 | 
				
			||||||
    const State *state0 = (const State *)autotoxes[0].state;
 | 
					    const State *state0 = (const State *)autotoxes[0].state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_group_peer_join(tox0, group_peer_join_handler);
 | 
					    tox_events_callback_group_peer_join(dispatch0, group_peer_join_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
        tox_callback_group_topic(autotoxes[i].tox, group_topic_handler);
 | 
					        tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
 | 
				
			||||||
        tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler);
 | 
					        tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Tox1 creates a group and is the founder of a newly created group */
 | 
					    /* Tox1 creates a group and is the founder of a newly created group */
 | 
				
			||||||
@@ -233,11 +250,11 @@ static void group_topic_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(s_ret, "Founder failed to set topic");
 | 
					    ck_assert_msg(s_ret, "Founder failed to set topic");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Founder gets the Chat ID and implicitly shares it publicly */
 | 
					    /* Founder gets the Chat ID and implicitly shares it publicly */
 | 
				
			||||||
    Tox_Err_Group_State_Queries id_err;
 | 
					    Tox_Err_Group_State_Query id_err;
 | 
				
			||||||
    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
					    uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
 | 
				
			||||||
    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
					    tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err);
 | 
					    ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* All other peers join the group using the Chat ID */
 | 
					    /* All other peers join the group using the Chat ID */
 | 
				
			||||||
    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
					    for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
 | 
				
			||||||
@@ -257,9 +274,9 @@ static void group_topic_test(AutoTox *autotoxes)
 | 
				
			|||||||
    wait_state_topic(autotoxes, groupnumber, TOPIC, TOPIC_LEN);
 | 
					    wait_state_topic(autotoxes, groupnumber, TOPIC, TOPIC_LEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Founder disables topic lock */
 | 
					    /* Founder disables topic lock */
 | 
				
			||||||
    Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err;
 | 
					    Tox_Err_Group_Set_Topic_Lock lock_set_err;
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
 | 
				
			||||||
    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
 | 
					    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
 | 
				
			||||||
                  lock_set_err);
 | 
					                  lock_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Topic lock disabled\n");
 | 
					    fprintf(stderr, "Topic lock disabled\n");
 | 
				
			||||||
@@ -273,9 +290,9 @@ static void group_topic_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(change_count == NUM_GROUP_TOXES, "%u peers changed the topic with topic lock disabled", change_count);
 | 
					    ck_assert_msg(change_count == NUM_GROUP_TOXES, "%u peers changed the topic with topic lock disabled", change_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* founder silences the last peer he saw join */
 | 
					    /* founder silences the last peer he saw join */
 | 
				
			||||||
    Tox_Err_Group_Mod_Set_Role merr;
 | 
					    Tox_Err_Group_Set_Role merr;
 | 
				
			||||||
    tox_group_mod_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr);
 | 
					    tox_group_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr);
 | 
				
			||||||
    ck_assert_msg(merr == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr);
 | 
					    ck_assert_msg(merr == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Random peer is set to observer\n");
 | 
					    fprintf(stderr, "Random peer is set to observer\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -287,8 +304,8 @@ static void group_topic_test(AutoTox *autotoxes)
 | 
				
			|||||||
    ck_assert_msg(change_count == NUM_GROUP_TOXES - 1, "%u peers changed the topic with a silenced peer", change_count);
 | 
					    ck_assert_msg(change_count == NUM_GROUP_TOXES - 1, "%u peers changed the topic with a silenced peer", change_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Founder enables topic lock and sets topic back to original */
 | 
					    /* Founder enables topic lock and sets topic back to original */
 | 
				
			||||||
    tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
 | 
					    tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
 | 
				
			||||||
    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
 | 
					    ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
 | 
				
			||||||
                  lock_set_err);
 | 
					                  lock_set_err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fprintf(stderr, "Topic lock enabled\n");
 | 
					    fprintf(stderr, "Topic lock enabled\n");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,13 +18,17 @@ typedef struct State {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define LOSSLESS_PACKET_FILLER 160
 | 
					#define LOSSLESS_PACKET_FILLER 160
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data)
 | 
					static void handle_lossless_packet(const Tox_Event_Friend_Lossless_Packet *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_lossless_packet_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_friend_lossless_packet_get_data(event);
 | 
				
			||||||
 | 
					    const uint32_t data_length = tox_event_friend_lossless_packet_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
 | 
					    uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
 | 
				
			||||||
    ck_assert(cmp_packet != nullptr);
 | 
					    ck_assert(cmp_packet != nullptr);
 | 
				
			||||||
    memset(cmp_packet, LOSSLESS_PACKET_FILLER, tox_max_custom_packet_size());
 | 
					    memset(cmp_packet, LOSSLESS_PACKET_FILLER, tox_max_custom_packet_size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
 | 
					    if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
 | 
				
			||||||
        const AutoTox *autotox = (AutoTox *)user_data;
 | 
					        const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
        State *state = (State *)autotox->state;
 | 
					        State *state = (State *)autotox->state;
 | 
				
			||||||
        state->custom_packet_received = true;
 | 
					        state->custom_packet_received = true;
 | 
				
			||||||
@@ -35,7 +39,7 @@ static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_lossless_packet(AutoTox *autotoxes)
 | 
					static void test_lossless_packet(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tox_callback_friend_lossless_packet(autotoxes[1].tox, &handle_lossless_packet);
 | 
					    tox_events_callback_friend_lossless_packet(autotoxes[1].dispatch, &handle_lossless_packet);
 | 
				
			||||||
    const size_t packet_size = tox_max_custom_packet_size() + 1;
 | 
					    const size_t packet_size = tox_max_custom_packet_size() + 1;
 | 
				
			||||||
    uint8_t *packet = (uint8_t *)malloc(packet_size);
 | 
					    uint8_t *packet = (uint8_t *)malloc(packet_size);
 | 
				
			||||||
    ck_assert(packet != nullptr);
 | 
					    ck_assert(packet != nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,13 +18,17 @@ typedef struct State {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define LOSSY_PACKET_FILLER 200
 | 
					#define LOSSY_PACKET_FILLER 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data)
 | 
					static void handle_lossy_packet(const Tox_Event_Friend_Lossy_Packet *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_lossy_packet_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *data = tox_event_friend_lossy_packet_get_data(event);
 | 
				
			||||||
 | 
					    const uint32_t data_length = tox_event_friend_lossy_packet_get_data_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
 | 
					    uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
 | 
				
			||||||
    ck_assert(cmp_packet != nullptr);
 | 
					    ck_assert(cmp_packet != nullptr);
 | 
				
			||||||
    memset(cmp_packet, LOSSY_PACKET_FILLER, tox_max_custom_packet_size());
 | 
					    memset(cmp_packet, LOSSY_PACKET_FILLER, tox_max_custom_packet_size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
 | 
					    if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
 | 
				
			||||||
        const AutoTox *autotox = (AutoTox *)user_data;
 | 
					        const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
        State *state = (State *)autotox->state;
 | 
					        State *state = (State *)autotox->state;
 | 
				
			||||||
        state->custom_packet_received = true;
 | 
					        state->custom_packet_received = true;
 | 
				
			||||||
@@ -35,7 +39,7 @@ static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_lossy_packet(AutoTox *autotoxes)
 | 
					static void test_lossy_packet(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tox_callback_friend_lossy_packet(autotoxes[1].tox, &handle_lossy_packet);
 | 
					    tox_events_callback_friend_lossy_packet(autotoxes[1].dispatch, &handle_lossy_packet);
 | 
				
			||||||
    const size_t packet_size = tox_max_custom_packet_size() + 1;
 | 
					    const size_t packet_size = tox_max_custom_packet_size() + 1;
 | 
				
			||||||
    uint8_t *packet = (uint8_t *)malloc(packet_size);
 | 
					    uint8_t *packet = (uint8_t *)malloc(packet_size);
 | 
				
			||||||
    ck_assert(packet != nullptr);
 | 
					    ck_assert(packet != nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@ static void test_addr_resolv_localhost(void)
 | 
				
			|||||||
    errno = 0;
 | 
					    errno = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const char localhost[] = "localhost";
 | 
					    const char localhost[] = "localhost";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ static void do_onion(Mono_Time *mono_time, Onion *onion)
 | 
				
			|||||||
static int handled_test_1;
 | 
					static int handled_test_1;
 | 
				
			||||||
static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
					static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Onion *onion = (Onion *)object;
 | 
					    const Onion *onion = (const Onion *)object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const char req_message[] = "Install Gentoo";
 | 
					    const char req_message[] = "Install Gentoo";
 | 
				
			||||||
    uint8_t req_packet[1 + sizeof(req_message)];
 | 
					    uint8_t req_packet[1 + sizeof(req_message)];
 | 
				
			||||||
@@ -99,7 +99,7 @@ static uint8_t test_3_pub_key[CRYPTO_PUBLIC_KEY_SIZE];
 | 
				
			|||||||
static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE];
 | 
					static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE];
 | 
				
			||||||
static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
					static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Onion *onion = (Onion *)object;
 | 
					    const Onion *onion = (const Onion *)object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
 | 
					    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@@ -118,7 +118,6 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
 | 
				
			|||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
 | 
					    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -135,7 +134,7 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
 | 
				
			|||||||
static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
 | 
					static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
 | 
				
			||||||
                             void *userdata)
 | 
					                             void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Onion *onion = (Onion *)object;
 | 
					    const Onion *onion = (const Onion *)object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
 | 
					    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@@ -154,7 +153,6 @@ static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t
 | 
				
			|||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
 | 
					    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -171,7 +169,7 @@ static uint8_t nonce[CRYPTO_NONCE_SIZE];
 | 
				
			|||||||
static int handled_test_4;
 | 
					static int handled_test_4;
 | 
				
			||||||
static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
					static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Onion *onion = (Onion *)object;
 | 
					    const Onion *onion = (const Onion *)object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") +
 | 
					    if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") +
 | 
				
			||||||
                   CRYPTO_MAC_SIZE)) {
 | 
					                   CRYPTO_MAC_SIZE)) {
 | 
				
			||||||
@@ -223,11 +221,11 @@ static Networking_Core *new_networking(const Logger *log, const Memory *mem, con
 | 
				
			|||||||
static void test_basic(void)
 | 
					static void test_basic(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t index[] = { 1, 2, 3 };
 | 
					    uint32_t index[] = { 1, 2, 3 };
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    ck_assert(ns != nullptr);
 | 
					    ck_assert(ns != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Logger *log1 = logger_new();
 | 
					    Logger *log1 = logger_new();
 | 
				
			||||||
@@ -288,7 +286,7 @@ static void test_basic(void)
 | 
				
			|||||||
    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
 | 
					    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
 | 
				
			||||||
    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1);
 | 
					    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1);
 | 
				
			||||||
    ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
 | 
					    ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
 | 
				
			||||||
    uint8_t zeroes[64] = {0};
 | 
					    const uint8_t zeroes[64] = {0};
 | 
				
			||||||
    random_bytes(rng, sb_data, sizeof(sb_data));
 | 
					    random_bytes(rng, sb_data, sizeof(sb_data));
 | 
				
			||||||
    uint64_t s;
 | 
					    uint64_t s;
 | 
				
			||||||
    memcpy(&s, sb_data, sizeof(uint64_t));
 | 
					    memcpy(&s, sb_data, sizeof(uint64_t));
 | 
				
			||||||
@@ -407,7 +405,7 @@ static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, u
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    IP ip = get_loopback();
 | 
					    IP ip = get_loopback();
 | 
				
			||||||
    ip.ip.v6.uint8[15] = 1;
 | 
					    ip.ip.v6.uint8[15] = 1;
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    Onions *on = (Onions *)malloc(sizeof(Onions));
 | 
					    Onions *on = (Onions *)malloc(sizeof(Onions));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!on) {
 | 
					    if (!on) {
 | 
				
			||||||
@@ -576,9 +574,9 @@ static void test_announce(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t index[NUM_ONIONS];
 | 
					    uint32_t index[NUM_ONIONS];
 | 
				
			||||||
    Onions *onions[NUM_ONIONS];
 | 
					    Onions *onions[NUM_ONIONS];
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
    ck_assert(mem != nullptr);
 | 
					    ck_assert(mem != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,9 +11,13 @@ typedef struct State {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define NUM_MSGS 40000
 | 
					#define NUM_MSGS 40000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type,
 | 
					static void handle_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
 | 
				
			||||||
                                  const uint8_t *message, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_message_get_friend_number(event);
 | 
				
			||||||
 | 
					    //const Tox_Message_Type type = tox_event_friend_message_get_type(event);
 | 
				
			||||||
 | 
					    //const uint8_t *message = tox_event_friend_message_get_message(event);
 | 
				
			||||||
 | 
					    //const uint32_t message_length = tox_event_friend_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
    state->recv_count++;
 | 
					    state->recv_count++;
 | 
				
			||||||
@@ -21,7 +25,7 @@ static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void net_crypto_overflow_test(AutoTox *autotoxes)
 | 
					static void net_crypto_overflow_test(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tox_callback_friend_message(autotoxes[0].tox, handle_friend_message);
 | 
					    tox_events_callback_friend_message(autotoxes[0].dispatch, handle_friend_message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("sending many messages to tox0\n");
 | 
					    printf("sending many messages to tox0\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,7 +51,7 @@ static bool all_disconnected_from(uint32_t tox_count, AutoTox *autotoxes, uint32
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_reconnect(AutoTox *autotoxes)
 | 
					static void test_reconnect(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    const time_t test_start_time = time(nullptr);
 | 
					    const time_t test_start_time = time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,7 +67,12 @@ static void test_reconnect(AutoTox *autotoxes)
 | 
				
			|||||||
    do {
 | 
					    do {
 | 
				
			||||||
        for (uint16_t i = 0; i < TOX_COUNT; ++i) {
 | 
					        for (uint16_t i = 0; i < TOX_COUNT; ++i) {
 | 
				
			||||||
            if (i != disconnect) {
 | 
					            if (i != disconnect) {
 | 
				
			||||||
                tox_iterate(autotoxes[i].tox, &autotoxes[i]);
 | 
					                Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					                Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
 | 
				
			||||||
 | 
					                ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					                tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
 | 
				
			||||||
 | 
					                tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                autotoxes[i].clock += 1000;
 | 
					                autotoxes[i].clock += 1000;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,8 @@
 | 
				
			|||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOADED_SAVE_FILE "../auto_tests/data/save.tox"
 | 
					#define LOADED_SAVE_FILE_BIG    "../auto_tests/data/save.tox.big"
 | 
				
			||||||
 | 
					#define LOADED_SAVE_FILE_LITTLE "../auto_tests/data/save.tox.little"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Information from the save file
 | 
					// Information from the save file
 | 
				
			||||||
#define EXPECTED_NAME "name"
 | 
					#define EXPECTED_NAME "name"
 | 
				
			||||||
@@ -18,7 +19,7 @@
 | 
				
			|||||||
#define EXPECTED_STATUS_MESSAGE_SIZE strlen(EXPECTED_STATUS_MESSAGE)
 | 
					#define EXPECTED_STATUS_MESSAGE_SIZE strlen(EXPECTED_STATUS_MESSAGE)
 | 
				
			||||||
#define EXPECTED_NUM_FRIENDS 1
 | 
					#define EXPECTED_NUM_FRIENDS 1
 | 
				
			||||||
#define EXPECTED_NOSPAM "4C762C7D"
 | 
					#define EXPECTED_NOSPAM "4C762C7D"
 | 
				
			||||||
#define EXPECTED_TOX_ID "B70E97D41F69B7F4C42A5BC7BD7A76B95B8030BE1B7C0E9E6FC19FC4ABEB195B4C762C7D800B"
 | 
					#define EXPECTED_TOX_ID "E776E9A993EE3CAE04F5946D9AC66FBBAA8C63A95A94B41942353C6DC1739B4B4C762C7DA7B9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t get_file_size(const char *save_path)
 | 
					static size_t get_file_size(const char *save_path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -135,6 +136,13 @@ static void test_save_compatibility(const char *save_path)
 | 
				
			|||||||
    tox_kill(tox);
 | 
					    tox_kill(tox);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool is_little_endian(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t x = 1;
 | 
				
			||||||
 | 
					    return ((uint8_t *)&x)[0] == 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// cppcheck-suppress constParameter
 | 
				
			||||||
int main(int argc, char *argv[])
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char base_path[4096] = {0};
 | 
					    char base_path[4096] = {0};
 | 
				
			||||||
@@ -152,10 +160,15 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
        base_path[strrchr(base_path, '/') - base_path] = '\0';
 | 
					        base_path[strrchr(base_path, '/') - base_path] = '\0';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char save_path[4096 + sizeof(LOADED_SAVE_FILE)];
 | 
					    if (is_little_endian()) {
 | 
				
			||||||
    snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE);
 | 
					        char save_path[4096 + sizeof(LOADED_SAVE_FILE_LITTLE)];
 | 
				
			||||||
 | 
					        snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_LITTLE);
 | 
				
			||||||
        test_save_compatibility(save_path);
 | 
					        test_save_compatibility(save_path);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        char save_path[4096 + sizeof(LOADED_SAVE_FILE_BIG)];
 | 
				
			||||||
 | 
					        snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_BIG);
 | 
				
			||||||
 | 
					        test_save_compatibility(save_path);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,12 @@ struct test_data {
 | 
				
			|||||||
static void set_random(Tox *m, const Random *rng, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length)
 | 
					static void set_random(Tox *m, const Random *rng, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VLA(uint8_t, text, length);
 | 
					    VLA(uint8_t, text, length);
 | 
				
			||||||
    uint32_t i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < length; ++i) {
 | 
					    for (uint32_t i = 0; i < length; ++i) {
 | 
				
			||||||
        text[i] = random_u08(rng);
 | 
					        text[i] = random_u08(rng);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setter(m, text, SIZEOF_VLA(text), nullptr);
 | 
					    setter(m, text, length, nullptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void alloc_string(uint8_t **to, size_t length)
 | 
					static void alloc_string(uint8_t **to, size_t length)
 | 
				
			||||||
@@ -44,18 +43,25 @@ static void set_string(uint8_t **to, const uint8_t *from, size_t length)
 | 
				
			|||||||
    memcpy(*to, from, length);
 | 
					    memcpy(*to, from, length);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void namechange_callback(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data)
 | 
					static void namechange_callback(const Tox_Event_Friend_Name *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *name = tox_event_friend_name_get_name(event);
 | 
				
			||||||
 | 
					    const uint32_t name_length = tox_event_friend_name_get_name_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct test_data *to_compare = (struct test_data *)user_data;
 | 
					    struct test_data *to_compare = (struct test_data *)user_data;
 | 
				
			||||||
    set_string(&to_compare->name, name, length);
 | 
					    set_string(&to_compare->name, name, name_length);
 | 
				
			||||||
    to_compare->received_name = true;
 | 
					    to_compare->received_name = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void statuschange_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length,
 | 
					static void statuschange_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
 | 
				
			||||||
                                  void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_friend_status_message_get_message(event);
 | 
				
			||||||
 | 
					    const uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct test_data *to_compare = (struct test_data *)user_data;
 | 
					    struct test_data *to_compare = (struct test_data *)user_data;
 | 
				
			||||||
    set_string(&to_compare->status_message, message, length);
 | 
					    set_string(&to_compare->status_message, message, message_length);
 | 
				
			||||||
    to_compare->received_status_message = true;
 | 
					    to_compare->received_status_message = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,6 +71,12 @@ int main(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr);
 | 
					    Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr);
 | 
				
			||||||
    Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr);
 | 
					    Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr);
 | 
				
			||||||
 | 
					    ck_assert(tox1 != nullptr);
 | 
				
			||||||
 | 
					    ck_assert(tox2 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_init(tox1);
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch1 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("bootstrapping tox2 off tox1\n");
 | 
					    printf("bootstrapping tox2 off tox1\n");
 | 
				
			||||||
    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
@@ -86,7 +98,7 @@ int main(void)
 | 
				
			|||||||
    ck_assert(reference_name != nullptr);
 | 
					    ck_assert(reference_name != nullptr);
 | 
				
			||||||
    ck_assert(reference_status != nullptr);
 | 
					    ck_assert(reference_status != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    set_random(tox1, rng, tox_self_set_name, tox_max_name_length());
 | 
					    set_random(tox1, rng, tox_self_set_name, tox_max_name_length());
 | 
				
			||||||
    set_random(tox2, rng, tox_self_set_name, tox_max_name_length());
 | 
					    set_random(tox2, rng, tox_self_set_name, tox_max_name_length());
 | 
				
			||||||
@@ -96,8 +108,8 @@ int main(void)
 | 
				
			|||||||
    tox_self_get_name(tox2, reference_name);
 | 
					    tox_self_get_name(tox2, reference_name);
 | 
				
			||||||
    tox_self_get_status_message(tox2, reference_status);
 | 
					    tox_self_get_status_message(tox2, reference_status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_friend_name(tox1, namechange_callback);
 | 
					    tox_events_callback_friend_name(dispatch1, namechange_callback);
 | 
				
			||||||
    tox_callback_friend_status_message(tox1, statuschange_callback);
 | 
					    tox_events_callback_friend_status_message(dispatch1, statuschange_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
        if (tox_self_get_connection_status(tox1) &&
 | 
					        if (tox_self_get_connection_status(tox1) &&
 | 
				
			||||||
@@ -107,7 +119,12 @@ int main(void)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_iterate(tox1, &to_compare);
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox1, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        tox_dispatch_invoke(dispatch1, events, &to_compare);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					        tox_iterate(tox2, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(tox_iteration_interval(tox1));
 | 
					        c_sleep(tox_iteration_interval(tox1));
 | 
				
			||||||
@@ -119,7 +136,12 @@ int main(void)
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_iterate(tox1, &to_compare);
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox1, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        tox_dispatch_invoke(dispatch1, events, &to_compare);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					        tox_iterate(tox2, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(tox_iteration_interval(tox1));
 | 
					        c_sleep(tox_iteration_interval(tox1));
 | 
				
			||||||
@@ -146,6 +168,7 @@ int main(void)
 | 
				
			|||||||
                  "incorrect status message: should be all zeroes");
 | 
					                  "incorrect status message: should be all zeroes");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_options_free(options);
 | 
					    tox_options_free(options);
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch1);
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(tox1);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(tox2);
 | 
				
			||||||
    tox_kill(tox_to_compare);
 | 
					    tox_kill(tox_to_compare);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,16 +32,24 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#define TCP_RELAY_PORT 33431
 | 
					#define TCP_RELAY_PORT 33431
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
 | 
					    Tox *tox = (Tox *)userdata;
 | 
				
			||||||
        tox_friend_add_norequest(m, public_key, nullptr);
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    uint32_t message_length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
 | 
				
			||||||
 | 
					        tox_friend_add_norequest(tox, public_key, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static unsigned int connected_t1;
 | 
					static unsigned int connected_t1;
 | 
				
			||||||
static void tox_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data)
 | 
					static void tox_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (connected_t1 && !connection_status) {
 | 
					    if (connected_t1 && !connection_status) {
 | 
				
			||||||
        ck_abort_msg("Tox went offline");
 | 
					        ck_abort_msg("Tox went offline");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -147,6 +155,9 @@ static void test_few_clients(void)
 | 
				
			|||||||
    Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]);
 | 
					    Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]);
 | 
				
			||||||
    ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
 | 
					    ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
 | 
				
			||||||
    tox_options_free(opts1);
 | 
					    tox_options_free(opts1);
 | 
				
			||||||
 | 
					    tox_events_init(tox1);
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch1 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct Tox_Options *opts2 = tox_options_new(nullptr);
 | 
					    struct Tox_Options *opts2 = tox_options_new(nullptr);
 | 
				
			||||||
    tox_options_set_ipv6_enabled(opts2, USE_IPV6);
 | 
					    tox_options_set_ipv6_enabled(opts2, USE_IPV6);
 | 
				
			||||||
@@ -154,6 +165,9 @@ static void test_few_clients(void)
 | 
				
			|||||||
    tox_options_set_local_discovery_enabled(opts2, false);
 | 
					    tox_options_set_local_discovery_enabled(opts2, false);
 | 
				
			||||||
    Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]);
 | 
					    Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]);
 | 
				
			||||||
    ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
 | 
					    ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch2 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct Tox_Options *opts3 = tox_options_new(nullptr);
 | 
					    struct Tox_Options *opts3 = tox_options_new(nullptr);
 | 
				
			||||||
    tox_options_set_ipv6_enabled(opts3, USE_IPV6);
 | 
					    tox_options_set_ipv6_enabled(opts3, USE_IPV6);
 | 
				
			||||||
@@ -163,7 +177,6 @@ static void test_few_clients(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
 | 
					    ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    Time_Data time_data;
 | 
					    Time_Data time_data;
 | 
				
			||||||
    ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex");
 | 
					    ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex");
 | 
				
			||||||
    time_data.clock = current_time_monotonic(tox1->mono_time);
 | 
					    time_data.clock = current_time_monotonic(tox1->mono_time);
 | 
				
			||||||
@@ -183,8 +196,8 @@ static void test_few_clients(void)
 | 
				
			|||||||
    tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
 | 
					    tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    connected_t1 = 0;
 | 
					    connected_t1 = 0;
 | 
				
			||||||
    tox_callback_self_connection_status(tox1, tox_connection_status);
 | 
					    tox_events_callback_self_connection_status(dispatch1, tox_connection_status);
 | 
				
			||||||
    tox_callback_friend_request(tox2, accept_friend_request);
 | 
					    tox_events_callback_friend_request(dispatch2, accept_friend_request);
 | 
				
			||||||
    uint8_t address[TOX_ADDRESS_SIZE];
 | 
					    uint8_t address[TOX_ADDRESS_SIZE];
 | 
				
			||||||
    tox_self_get_address(tox2, address);
 | 
					    tox_self_get_address(tox2, address);
 | 
				
			||||||
    uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
 | 
					    uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
 | 
				
			||||||
@@ -193,8 +206,20 @@ static void test_few_clients(void)
 | 
				
			|||||||
    uint8_t off = 1;
 | 
					    uint8_t off = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        {
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(tox1, true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch1, events, tox1);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch2, events, tox2);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        tox_iterate(tox3, nullptr);
 | 
					        tox_iterate(tox3, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
 | 
					        if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
 | 
				
			||||||
@@ -220,9 +245,10 @@ static void test_few_clients(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // We're done with this callback, so unset it to ensure we don't fail the
 | 
					    // We're done with this callback, so unset it to ensure we don't fail the
 | 
				
			||||||
    // test if tox1 goes offline while tox2 and 3 are reloaded.
 | 
					    // test if tox1 goes offline while tox2 and 3 are reloaded.
 | 
				
			||||||
    tox_callback_self_connection_status(tox1, nullptr);
 | 
					    tox_events_callback_self_connection_status(dispatch1, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reload_tox(&tox2, opts2, &index[1]);
 | 
					    reload_tox(&tox2, opts2, &index[1]);
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reload_tox(&tox3, opts3, &index[2]);
 | 
					    reload_tox(&tox3, opts3, &index[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -231,8 +257,20 @@ static void test_few_clients(void)
 | 
				
			|||||||
    off = 1;
 | 
					    off = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (true) {
 | 
					    while (true) {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        {
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(tox1, true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch1, events, tox1);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch2, events, tox2);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        tox_iterate(tox3, nullptr);
 | 
					        tox_iterate(tox3, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
 | 
					        if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
 | 
				
			||||||
@@ -257,6 +295,9 @@ static void test_few_clients(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    printf("test_few_clients succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
					    printf("test_few_clients succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch1);
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(tox1);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(tox2);
 | 
				
			||||||
    tox_kill(tox3);
 | 
					    tox_kill(tox3);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,12 +14,15 @@ typedef struct State {
 | 
				
			|||||||
#define MESSAGE_FILLER 'G'
 | 
					#define MESSAGE_FILLER 'G'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void message_callback(
 | 
					static void message_callback(
 | 
				
			||||||
    Tox *m, uint32_t friendnumber, Tox_Message_Type type,
 | 
					    const Tox_Event_Friend_Message *event, void *user_data)
 | 
				
			||||||
    const uint8_t *string, size_t length, void *user_data)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const Tox_Message_Type type = tox_event_friend_message_get_type(event);
 | 
				
			||||||
 | 
					    const uint8_t *string = tox_event_friend_message_get_message(event);
 | 
				
			||||||
 | 
					    const uint32_t length = tox_event_friend_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type != TOX_MESSAGE_TYPE_NORMAL) {
 | 
					    if (type != TOX_MESSAGE_TYPE_NORMAL) {
 | 
				
			||||||
        ck_abort_msg("Bad type");
 | 
					        ck_abort_msg("Bad type");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -38,7 +41,7 @@ static void message_callback(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void send_message_test(AutoTox *autotoxes)
 | 
					static void send_message_test(AutoTox *autotoxes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tox_callback_friend_message(autotoxes[1].tox, &message_callback);
 | 
					    tox_events_callback_friend_message(autotoxes[1].dispatch, &message_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const size_t msgs_len = tox_max_message_length() + 1;
 | 
					    const size_t msgs_len = tox_max_message_length() + 1;
 | 
				
			||||||
    uint8_t *msgs = (uint8_t *)malloc(msgs_len);
 | 
					    uint8_t *msgs = (uint8_t *)malloc(msgs_len);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,12 +15,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define NICKNAME "Gentoo"
 | 
					#define NICKNAME "Gentoo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nickchange_callback(Tox *tox, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
 | 
					static void nickchange_callback(const Tox_Event_Friend_Name *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert_msg(length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)length,
 | 
					    //const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *name = tox_event_friend_name_get_name(event);
 | 
				
			||||||
 | 
					    const uint32_t name_length = tox_event_friend_name_get_name_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert_msg(name_length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)name_length,
 | 
				
			||||||
                  (uint16_t)sizeof(NICKNAME));
 | 
					                  (uint16_t)sizeof(NICKNAME));
 | 
				
			||||||
    ck_assert_msg(memcmp(string, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)string);
 | 
					    ck_assert_msg(memcmp(name, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)name);
 | 
				
			||||||
    bool *nickname_updated = (bool *)userdata;
 | 
					    bool *nickname_updated = (bool *)user_data;
 | 
				
			||||||
    *nickname_updated = true;
 | 
					    *nickname_updated = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,6 +38,12 @@ static void test_set_name(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
					    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // we only run events on tox2 in this test case
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch2 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
 | 
					    printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
 | 
				
			||||||
    uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    tox_self_get_public_key(tox2, public_key);
 | 
					    tox_self_get_public_key(tox2, public_key);
 | 
				
			||||||
@@ -50,7 +60,13 @@ static void test_set_name(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        //tox_dispatch_invoke(dispatch2, events, nullptr);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
					    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
				
			||||||
             tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
 | 
					             tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
 | 
				
			||||||
@@ -60,14 +76,20 @@ static void test_set_name(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        //tox_dispatch_invoke(dispatch2, events, nullptr);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
					    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
				
			||||||
             tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
 | 
					             tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
 | 
					    printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_friend_name(tox2, nickchange_callback);
 | 
					    tox_events_callback_friend_name(dispatch2, nickchange_callback);
 | 
				
			||||||
    Tox_Err_Set_Info err_n;
 | 
					    Tox_Err_Set_Info err_n;
 | 
				
			||||||
    bool ret = tox_self_set_name(tox1, (const uint8_t *)NICKNAME, sizeof(NICKNAME), &err_n);
 | 
					    bool ret = tox_self_set_name(tox1, (const uint8_t *)NICKNAME, sizeof(NICKNAME), &err_n);
 | 
				
			||||||
    ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %d\n", err_n);
 | 
					    ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %d\n", err_n);
 | 
				
			||||||
@@ -76,7 +98,13 @@ static void test_set_name(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, &nickname_updated);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        tox_dispatch_invoke(dispatch2, events, &nickname_updated);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (!nickname_updated);
 | 
					    } while (!nickname_updated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,6 +115,8 @@ static void test_set_name(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    printf("test_set_name succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
					    printf("test_set_name succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(tox1);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(tox2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,9 +15,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define STATUS_MESSAGE "Installing Gentoo"
 | 
					#define STATUS_MESSAGE "Installing Gentoo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void status_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, void *user_data)
 | 
					static void status_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ck_assert_msg(length == sizeof(STATUS_MESSAGE) &&
 | 
					    //uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_friend_status_message_get_message(event);
 | 
				
			||||||
 | 
					    uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ck_assert_msg(message_length == sizeof(STATUS_MESSAGE) &&
 | 
				
			||||||
                  memcmp(message, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0,
 | 
					                  memcmp(message, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0,
 | 
				
			||||||
                  "incorrect data in status callback");
 | 
					                  "incorrect data in status callback");
 | 
				
			||||||
    bool *status_updated = (bool *)user_data;
 | 
					    bool *status_updated = (bool *)user_data;
 | 
				
			||||||
@@ -34,6 +38,12 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
					    ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // we only run events on tox2 in this test case
 | 
				
			||||||
 | 
					    tox_events_init(tox2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch2 != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
 | 
					    printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
 | 
				
			||||||
    uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
 | 
					    uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
    tox_self_get_public_key(tox2, public_key);
 | 
					    tox_self_get_public_key(tox2, public_key);
 | 
				
			||||||
@@ -50,7 +60,12 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        //tox_dispatch_invoke(dispatch2, events, nullptr);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
					    } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
 | 
				
			||||||
@@ -61,7 +76,12 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, nullptr);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        //tox_dispatch_invoke(dispatch2, events, nullptr);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
					    } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
 | 
				
			||||||
@@ -69,8 +89,8 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
 | 
					    printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_callback_friend_status_message(dispatch2, status_callback);
 | 
				
			||||||
    Tox_Err_Set_Info err_n;
 | 
					    Tox_Err_Set_Info err_n;
 | 
				
			||||||
    tox_callback_friend_status_message(tox2, status_callback);
 | 
					 | 
				
			||||||
    bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE),
 | 
					    bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE),
 | 
				
			||||||
                                           &err_n);
 | 
					                                           &err_n);
 | 
				
			||||||
    ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %d\n", err_n);
 | 
					    ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %d\n", err_n);
 | 
				
			||||||
@@ -79,7 +99,13 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(tox1, nullptr);
 | 
					        tox_iterate(tox1, nullptr);
 | 
				
			||||||
        tox_iterate(tox2, &status_updated);
 | 
					
 | 
				
			||||||
 | 
					        Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					        Tox_Events *events = tox_events_iterate(tox2, true, &err);
 | 
				
			||||||
 | 
					        ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					        tox_dispatch_invoke(dispatch2, events, &status_updated);
 | 
				
			||||||
 | 
					        tox_events_free(events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(ITERATION_INTERVAL);
 | 
					        c_sleep(ITERATION_INTERVAL);
 | 
				
			||||||
    } while (!status_updated);
 | 
					    } while (!status_updated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,6 +118,8 @@ static void test_set_status_message(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    printf("test_set_status_message succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
					    printf("test_set_status_message succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_kill(tox1);
 | 
					    tox_kill(tox1);
 | 
				
			||||||
    tox_kill(tox2);
 | 
					    tox_kill(tox2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@
 | 
				
			|||||||
// Set to true to produce an msgpack file at /tmp/test.mp.
 | 
					// Set to true to produce an msgpack file at /tmp/test.mp.
 | 
				
			||||||
static const bool want_dump_events = false;
 | 
					static const bool want_dump_events = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_events_friend_message(Tox *tox, const Tox_Event_Friend_Message *event, void *user_data)
 | 
					static void handle_events_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool *success = (bool *)user_data;
 | 
					    bool *success = (bool *)user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,7 +84,7 @@ static bool await_message(Tox **toxes, const Tox_Dispatch *dispatch)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool success = false;
 | 
					        bool success = false;
 | 
				
			||||||
        tox_dispatch_invoke(dispatch, events, toxes[1], &success);
 | 
					        tox_dispatch_invoke(dispatch, events, &success);
 | 
				
			||||||
        print_events(sys, events);
 | 
					        print_events(sys, events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (success) {
 | 
					        if (success) {
 | 
				
			||||||
@@ -169,22 +169,9 @@ static void test_tox_events(void)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void fake_test_unpack(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // TODO(Green-Sky): add proper unpack tests and/or implement ngc events
 | 
					 | 
				
			||||||
    (void)tox_group_privacy_state_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_privacy_state_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_voice_state_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_topic_lock_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_join_fail_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_mod_event_unpack;
 | 
					 | 
				
			||||||
    (void)tox_group_exit_type_unpack;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int main(void)
 | 
					int main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
					    setvbuf(stdout, nullptr, _IONBF, 0);
 | 
				
			||||||
    test_tox_events();
 | 
					    test_tox_events();
 | 
				
			||||||
    fake_test_unpack();
 | 
					 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,16 +26,27 @@
 | 
				
			|||||||
#define TOX_LOCALHOST "127.0.0.1"
 | 
					#define TOX_LOCALHOST "127.0.0.1"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct State {
 | 
				
			||||||
 | 
					    uint32_t to_comp;
 | 
				
			||||||
 | 
					    Tox *tox;
 | 
				
			||||||
 | 
					} State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool enable_broken_tests = false;
 | 
					static bool enable_broken_tests = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (*((uint32_t *)userdata) != 974536) {
 | 
					    State *state = (State *)userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    const uint32_t message_length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (state->to_comp != 974536) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
 | 
					    if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
 | 
				
			||||||
        tox_friend_add_norequest(m, public_key, nullptr);
 | 
					        tox_friend_add_norequest(state->tox, public_key, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,7 +57,7 @@ static uint16_t tcp_relay_port = 33448;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_many_clients_tcp(void)
 | 
					static void test_many_clients_tcp(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    long long unsigned int cur_time = time(nullptr);
 | 
					    long long unsigned int cur_time = time(nullptr);
 | 
				
			||||||
    Tox *toxes[NUM_TOXES_TCP];
 | 
					    Tox *toxes[NUM_TOXES_TCP];
 | 
				
			||||||
@@ -73,7 +84,7 @@ static void test_many_clients_tcp(void)
 | 
				
			|||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
 | 
					        ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
 | 
				
			||||||
        tox_callback_friend_request(toxes[i], accept_friend_request);
 | 
					        tox_events_init(toxes[i]);
 | 
				
			||||||
        uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
 | 
					        uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
        tox_self_get_dht_id(toxes[0], dpk);
 | 
					        tox_self_get_dht_id(toxes[0], dpk);
 | 
				
			||||||
        Tox_Err_Bootstrap error;
 | 
					        Tox_Err_Bootstrap error;
 | 
				
			||||||
@@ -85,6 +96,11 @@ static void test_many_clients_tcp(void)
 | 
				
			|||||||
        tox_options_free(opts);
 | 
					        tox_options_free(opts);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_callback_friend_request(dispatch, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint16_t tox1;
 | 
					        uint16_t tox1;
 | 
				
			||||||
        uint16_t tox2;
 | 
					        uint16_t tox2;
 | 
				
			||||||
@@ -131,12 +147,18 @@ loop_top:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
					        for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
				
			||||||
            tox_iterate(toxes[i], &to_comp);
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            State state = {to_comp, toxes[i]};
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch, events, &state);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(50);
 | 
					        c_sleep(50);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch);
 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
				
			||||||
        tox_kill(toxes[i]);
 | 
					        tox_kill(toxes[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -148,7 +170,7 @@ loop_top:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void test_many_clients_tcp_b(void)
 | 
					static void test_many_clients_tcp_b(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    long long unsigned int cur_time = time(nullptr);
 | 
					    long long unsigned int cur_time = time(nullptr);
 | 
				
			||||||
    Tox *toxes[NUM_TOXES_TCP];
 | 
					    Tox *toxes[NUM_TOXES_TCP];
 | 
				
			||||||
@@ -167,7 +189,7 @@ static void test_many_clients_tcp_b(void)
 | 
				
			|||||||
        index[i] = i + 1;
 | 
					        index[i] = i + 1;
 | 
				
			||||||
        toxes[i] = tox_new_log(opts, nullptr, &index[i]);
 | 
					        toxes[i] = tox_new_log(opts, nullptr, &index[i]);
 | 
				
			||||||
        ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
 | 
					        ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
 | 
				
			||||||
        tox_callback_friend_request(toxes[i], accept_friend_request);
 | 
					        tox_events_init(toxes[i]);
 | 
				
			||||||
        uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
 | 
					        uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
 | 
				
			||||||
        tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
 | 
					        tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
 | 
				
			||||||
        ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr),
 | 
					        ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr),
 | 
				
			||||||
@@ -179,6 +201,11 @@ static void test_many_clients_tcp_b(void)
 | 
				
			|||||||
        tox_options_free(opts);
 | 
					        tox_options_free(opts);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_callback_friend_request(dispatch, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint16_t tox1;
 | 
					        uint16_t tox1;
 | 
				
			||||||
        uint16_t tox2;
 | 
					        uint16_t tox2;
 | 
				
			||||||
@@ -232,12 +259,18 @@ loop_top:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
					        for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
				
			||||||
            tox_iterate(toxes[i], &to_comp);
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            State state = {to_comp, toxes[i]};
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch, events, &state);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(30);
 | 
					        c_sleep(30);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch);
 | 
				
			||||||
    for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
					    for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
 | 
				
			||||||
        tox_kill(toxes[i]);
 | 
					        tox_kill(toxes[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -245,7 +278,6 @@ loop_top:
 | 
				
			|||||||
    printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time);
 | 
					    printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void tox_suite(void)
 | 
					static void tox_suite(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Each tox connects to a single tox TCP    */
 | 
					    /* Each tox connects to a single tox TCP    */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,20 +13,25 @@
 | 
				
			|||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
#include "check_compat.h"
 | 
					#include "check_compat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
 | 
					static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
 | 
					    Tox *tox = (Tox *)userdata;
 | 
				
			||||||
        tox_friend_add_norequest(m, public_key, nullptr);
 | 
					
 | 
				
			||||||
 | 
					    const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
 | 
				
			||||||
 | 
					    const uint8_t *message = tox_event_friend_request_get_message(event);
 | 
				
			||||||
 | 
					    const uint32_t message_length = tox_event_friend_request_get_message_length(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
 | 
				
			||||||
 | 
					        tox_friend_add_norequest(tox, public_key, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define TCP_TEST_NUM_TOXES 90
 | 
					#define TCP_TEST_NUM_TOXES 90
 | 
				
			||||||
#define TCP_TEST_NUM_FRIENDS 50
 | 
					#define TCP_TEST_NUM_FRIENDS 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_many_clients(void)
 | 
					static void test_many_clients(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    ck_assert(rng != nullptr);
 | 
					    ck_assert(rng != nullptr);
 | 
				
			||||||
    time_t cur_time = time(nullptr);
 | 
					    time_t cur_time = time(nullptr);
 | 
				
			||||||
    Tox *toxes[TCP_TEST_NUM_TOXES];
 | 
					    Tox *toxes[TCP_TEST_NUM_TOXES];
 | 
				
			||||||
@@ -36,9 +41,14 @@ static void test_many_clients(void)
 | 
				
			|||||||
        index[i] = i + 1;
 | 
					        index[i] = i + 1;
 | 
				
			||||||
        toxes[i] = tox_new_log(nullptr, nullptr, &index[i]);
 | 
					        toxes[i] = tox_new_log(nullptr, nullptr, &index[i]);
 | 
				
			||||||
        ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i);
 | 
					        ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i);
 | 
				
			||||||
        tox_callback_friend_request(toxes[i], accept_friend_request);
 | 
					        tox_events_init(toxes[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
 | 
				
			||||||
 | 
					    ck_assert(dispatch != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_events_callback_friend_request(dispatch, accept_friend_request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint16_t tox1;
 | 
					        uint16_t tox1;
 | 
				
			||||||
        uint16_t tox2;
 | 
					        uint16_t tox2;
 | 
				
			||||||
@@ -112,12 +122,17 @@ loop_top:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
 | 
					        for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
 | 
				
			||||||
            tox_iterate(toxes[i], nullptr);
 | 
					            Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
 | 
				
			||||||
 | 
					            Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
 | 
				
			||||||
 | 
					            ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
 | 
				
			||||||
 | 
					            tox_dispatch_invoke(dispatch, events, toxes[i]);
 | 
				
			||||||
 | 
					            tox_events_free(events);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        c_sleep(50);
 | 
					        c_sleep(50);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tox_dispatch_free(dispatch);
 | 
				
			||||||
    for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
 | 
					    for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
 | 
				
			||||||
        tox_kill(toxes[i]);
 | 
					        tox_kill(toxes[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								external/toxcore/c-toxcore/auto_tests/tox_new_test.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								external/toxcore/c-toxcore/auto_tests/tox_new_test.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					#include "../toxcore/tox.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../toxcore/ccompat.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    tox_kill(tox_new(nullptr, nullptr));
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -23,7 +23,6 @@
 | 
				
			|||||||
#define TEST_STOP_RESUME_PAYLOAD 1
 | 
					#define TEST_STOP_RESUME_PAYLOAD 1
 | 
				
			||||||
#define TEST_PAUSE_RESUME_SEND 1
 | 
					#define TEST_PAUSE_RESUME_SEND 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ck_assert_call_control(a, b, c) do { \
 | 
					#define ck_assert_call_control(a, b, c) do { \
 | 
				
			||||||
    Toxav_Err_Call_Control cc_err; \
 | 
					    Toxav_Err_Call_Control cc_err; \
 | 
				
			||||||
    bool ok = toxav_call_control(a, b, c, &cc_err); \
 | 
					    bool ok = toxav_call_control(a, b, c, &cc_err); \
 | 
				
			||||||
@@ -34,7 +33,6 @@
 | 
				
			|||||||
    ck_assert(cc_err == TOXAV_ERR_CALL_CONTROL_OK); \
 | 
					    ck_assert(cc_err == TOXAV_ERR_CALL_CONTROL_OK); \
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    bool incoming;
 | 
					    bool incoming;
 | 
				
			||||||
    uint32_t state;
 | 
					    uint32_t state;
 | 
				
			||||||
@@ -46,7 +44,6 @@ static void clear_call_control(CallControl *cc)
 | 
				
			|||||||
    *cc = empty;
 | 
					    *cc = empty;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Callbacks
 | 
					 * Callbacks
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -89,7 +86,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Iterate helper
 | 
					 * Iterate helper
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -207,7 +203,6 @@ static void test_av_flows(void)
 | 
				
			|||||||
        c_sleep(20);
 | 
					        c_sleep(20);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Toxav_Err_New error;
 | 
					        Toxav_Err_New error;
 | 
				
			||||||
        alice_av = toxav_new(alice, &error);
 | 
					        alice_av = toxav_new(alice, &error);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,7 +74,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Iterate helper
 | 
					 * Iterate helper
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -299,7 +298,6 @@ static void test_av_three_calls(void)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        tox_iterate(bootstrap, nullptr);
 | 
					        tox_iterate(bootstrap, nullptr);
 | 
				
			||||||
        tox_iterate(alice, nullptr);
 | 
					        tox_iterate(alice, nullptr);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,14 @@ typedef struct State {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "auto_test_support.h"
 | 
					#include "auto_test_support.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void typing_callback(Tox *m, uint32_t friendnumber, bool typing, void *user_data)
 | 
					static void typing_callback(const Tox_Event_Friend_Typing *event, void *user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const AutoTox *autotox = (AutoTox *)user_data;
 | 
					    const AutoTox *autotox = (AutoTox *)user_data;
 | 
				
			||||||
    State *state = (State *)autotox->state;
 | 
					    State *state = (State *)autotox->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //const uint32_t friend_number = tox_event_friend_typing_get_friend_number(event);
 | 
				
			||||||
 | 
					    const bool typing = tox_event_friend_typing_get_typing(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state->friend_is_typing = typing;
 | 
					    state->friend_is_typing = typing;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,7 +32,7 @@ static void test_typing(AutoTox *autotoxes)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    time_t cur_time = time(nullptr);
 | 
					    time_t cur_time = time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tox_callback_friend_typing(autotoxes[1].tox, &typing_callback);
 | 
					    tox_events_callback_friend_typing(autotoxes[1].dispatch, &typing_callback);
 | 
				
			||||||
    tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr);
 | 
					    tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,8 +48,8 @@ function(_make_version_script target)
 | 
				
			|||||||
endfunction()
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF)
 | 
					option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF)
 | 
				
			||||||
if(WIN32 OR APPLE)
 | 
					if((WIN32 AND NOT MINGW) OR APPLE)
 | 
				
			||||||
  # Windows and OSX don't have this linker functionality.
 | 
					  # Windows and macOS don't have this linker functionality.
 | 
				
			||||||
  set(STRICT_ABI OFF)
 | 
					  set(STRICT_ABI OFF)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								external/toxcore/c-toxcore/configure.ac
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								external/toxcore/c-toxcore/configure.ac
									
									
									
									
										vendored
									
									
								
							@@ -2,7 +2,7 @@
 | 
				
			|||||||
# Process this file with autoconf to produce a configure script.
 | 
					# Process this file with autoconf to produce a configure script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AC_PREREQ([2.65])
 | 
					AC_PREREQ([2.65])
 | 
				
			||||||
AC_INIT([tox], [0.2.18])
 | 
					AC_INIT([tox], [0.2.19])
 | 
				
			||||||
AC_CONFIG_AUX_DIR(configure_aux)
 | 
					AC_CONFIG_AUX_DIR(configure_aux)
 | 
				
			||||||
AC_CONFIG_SRCDIR([toxcore/net_crypto.c])
 | 
					AC_CONFIG_SRCDIR([toxcore/net_crypto.c])
 | 
				
			||||||
AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Werror subdir-objects tar-ustar])
 | 
					AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Werror subdir-objects tar-ustar])
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								external/toxcore/c-toxcore/docs/Doxyfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								external/toxcore/c-toxcore/docs/Doxyfile
									
									
									
									
										vendored
									
									
								
							@@ -1295,15 +1295,6 @@ HTML_COLORSTYLE_SAT    = 100
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
HTML_COLORSTYLE_GAMMA  = 80
 | 
					HTML_COLORSTYLE_GAMMA  = 80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
 | 
					 | 
				
			||||||
# page will contain the date and time when the page was generated. Setting this
 | 
					 | 
				
			||||||
# to YES can help to show when doxygen was last run and thus if the
 | 
					 | 
				
			||||||
# documentation is up to date.
 | 
					 | 
				
			||||||
# The default value is: NO.
 | 
					 | 
				
			||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
HTML_TIMESTAMP         = NO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
 | 
					# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
 | 
				
			||||||
# documentation will contain a main index with vertical navigation menus that
 | 
					# documentation will contain a main index with vertical navigation menus that
 | 
				
			||||||
# are dynamically created via JavaScript. If disabled, the navigation index will
 | 
					# are dynamically created via JavaScript. If disabled, the navigation index will
 | 
				
			||||||
@@ -1950,14 +1941,6 @@ LATEX_HIDE_INDICES     = NO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LATEX_BIB_STYLE        = plain
 | 
					LATEX_BIB_STYLE        = plain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
 | 
					 | 
				
			||||||
# page will contain the date and time when the page was generated. Setting this
 | 
					 | 
				
			||||||
# to NO can help when comparing the output of multiple runs.
 | 
					 | 
				
			||||||
# The default value is: NO.
 | 
					 | 
				
			||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LATEX_TIMESTAMP        = NO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
 | 
					# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
 | 
				
			||||||
# path from which the emoji images will be read. If a relative path is entered,
 | 
					# path from which the emoji images will be read. If a relative path is entered,
 | 
				
			||||||
# it will be relative to the LATEX_OUTPUT directory. If left blank the
 | 
					# it will be relative to the LATEX_OUTPUT directory. If left blank the
 | 
				
			||||||
@@ -2587,3 +2570,19 @@ GENERATE_LEGEND        = YES
 | 
				
			|||||||
# The default value is: YES.
 | 
					# The default value is: YES.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DOT_CLEANUP            = YES
 | 
					DOT_CLEANUP            = YES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
 | 
				
			||||||
 | 
					# clang parser for more accurate parsing at the cost of reduced performance.
 | 
				
			||||||
 | 
					# This can be particularly helpful with template rich C++ code for which
 | 
				
			||||||
 | 
					# doxygen's built-in parser lacks the necessary type information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CLANG_ASSISTED_PARSING = NO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If clang assisted parsing is enabled you can provide the clang parser with
 | 
				
			||||||
 | 
					# the path to the directory containing a file called compile_commands.json.
 | 
				
			||||||
 | 
					# This file is the compilation database containing the options used when the
 | 
				
			||||||
 | 
					# source files were built. This is equivalent to specifying the -p option to a
 | 
				
			||||||
 | 
					# clang tool, such as clang-check. These options will then be passed to the
 | 
				
			||||||
 | 
					# parser. Any options specified with CLANG_OPTIONS will be added as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CLANG_DATABASE_PATH    = _build
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										107
									
								
								external/toxcore/c-toxcore/docs/Group-Chats.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										107
									
								
								external/toxcore/c-toxcore/docs/Group-Chats.md
									
									
									
									
										vendored
									
									
								
							@@ -2,77 +2,122 @@ Group chats.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Note: we assume everyone in the chat trusts each other.
 | 
					Note: we assume everyone in the chat trusts each other.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These group chats work by temporarily adding the 4 "closest" people defined by a distance function 
 | 
					These group chats work by temporarily adding the 4 "closest" people defined by a
 | 
				
			||||||
in group.c in order to form a circle of connected peers. These peers then relay messages to each other.
 | 
					distance function in group.c in order to form a circle of connected peers. These
 | 
				
			||||||
 | 
					peers then relay messages to each other.
 | 
				
			||||||
A friend invites another friend to a group chat by sending them an invite packet. The friend either ignores 
 | 
					 | 
				
			||||||
the invite or responds with a response packet if he wants to join the chat. The friend invite contains the type
 | 
					 | 
				
			||||||
of groupchat (text only, A/V) the friend is being invited to.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A friend invites another friend to a group chat by sending them an invite
 | 
				
			||||||
 | 
					packet. The friend either ignores the invite or responds with a response packet
 | 
				
			||||||
 | 
					if he wants to join the chat. The friend invite contains the type of groupchat
 | 
				
			||||||
 | 
					(text only, A/V) the friend is being invited to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TODO(irungentoo): write more of this.
 | 
					TODO(irungentoo): write more of this.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Protocol
 | 
					## Protocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Invite packets:
 | 
					Invite packets:
 | 
				
			||||||
Invite packet:
 | 
					
 | 
				
			||||||
 | 
					### Invite packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 96][uint8_t id 0][uint16_t group chat number][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
					[uint8_t id 96][uint8_t id 0][uint16_t group chat number][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Response packet
 | 
					### Response packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 96][uint8_t id 1][uint16_t group chat number(local)][uint16_t group chat number to join][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
					[uint8_t id 96][uint8_t id 1][uint16_t group chat number(local)][uint16_t group chat number to join][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Peer online packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Peer online packet:
 | 
					```
 | 
				
			||||||
[uint8_t id 97][uint16_t group chat number (local)][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
					[uint8_t id 97][uint16_t group chat number (local)][33 bytes group chat identifier[1 byte type][32 bytes id]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Peer leave packet:
 | 
					### Peer leave packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 98][uint16_t group chat number][uint8_t id 1]
 | 
					[uint8_t id 98][uint16_t group chat number][uint8_t id 1]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Peer query packet:
 | 
					### Peer query packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 98][uint16_t group chat number][uint8_t id 8]
 | 
					[uint8_t id 98][uint16_t group chat number][uint8_t id 8]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Peer response packet:
 | 
					### Peer response packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 98][uint16_t group chat number][uint8_t id 9][Repeated times number of peers: [uint16_t peer num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key][uint8_t name length][name]]
 | 
					[uint8_t id 98][uint16_t group chat number][uint8_t id 9][Repeated times number of peers: [uint16_t peer num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key][uint8_t name length][name]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Title response packet:
 | 
					### Title response packet:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 98][uint16_t group chat number][uint8_t id 10][title]
 | 
					[uint8_t id 98][uint16_t group chat number][uint8_t id 10][title]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Message packets:
 | 
					### Message packets:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 99][uint16_t group chat number][uint16_t peer number][uint32_t message number][uint8_t with a value representing id of message][data]
 | 
					[uint8_t id 99][uint16_t group chat number][uint16_t peer number][uint32_t message number][uint8_t with a value representing id of message][data]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Lossy Message packets:
 | 
					### Lossy Message packets:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t id 199][uint16_t group chat number][uint16_t peer number][uint16_t message number][uint8_t with a value representing id of message][data]
 | 
					[uint8_t id 199][uint16_t group chat number][uint16_t peer number][uint16_t message number][uint8_t with a value representing id of message][data]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Group chat types:
 | 
					## Group chat types:
 | 
				
			||||||
0: text
 | 
					 | 
				
			||||||
1: AV
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- 0: text
 | 
				
			||||||
 | 
					- 1: AV
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note: the message number is increased by 1 for each sent message.
 | 
					Note: the message number is increased by 1 for each sent message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message ids:
 | 
					## message ids:
 | 
				
			||||||
0 - ping
 | 
					
 | 
				
			||||||
sent every ~60 seconds by every peer.
 | 
					### 0 - ping
 | 
				
			||||||
No data.
 | 
					
 | 
				
			||||||
 | 
					sent every ~60 seconds by every peer. No data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 16 - new_peer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
16 - new_peer
 | 
					 | 
				
			||||||
Tell everyone about a new peer in the chat.
 | 
					Tell everyone about a new peer in the chat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint16_t peer_num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key]
 | 
					[uint16_t peer_num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
17 - kill_peer
 | 
					### 17 - kill_peer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint16_t peer_num]
 | 
					[uint16_t peer_num]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
48 - name change
 | 
					### 48 - name change
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t name[namelen]]
 | 
					[uint8_t name[namelen]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
49 - groupchat title change
 | 
					### 49 - groupchat title change
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t title[titlelen]]
 | 
					[uint8_t title[titlelen]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
64 - chat message
 | 
					### 64 - chat message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t message[messagelen]]
 | 
					[uint8_t message[messagelen]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
65 - action (/me)
 | 
					### 65 - action (/me)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
[uint8_t message[messagelen]]
 | 
					[uint8_t message[messagelen]]
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								external/toxcore/c-toxcore/docs/apidsl.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								external/toxcore/c-toxcore/docs/apidsl.md
									
									
									
									
										vendored
									
									
								
							@@ -1,51 +0,0 @@
 | 
				
			|||||||
This folder contains the input file (``tox.in.h``) that has to be used to generate the ``tox.h`` api with: https://github.com/TokTok/apidsl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Minimal requirements
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
There are some minimal requirements to contribute to ``tox.h``:
 | 
					 | 
				
			||||||
* unix environment
 | 
					 | 
				
			||||||
* ``astyle`` ``>=2.03``
 | 
					 | 
				
			||||||
* [``apidsl``](https://github.com/TokTok/apidsl) (you can use provided service with curl instead)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Quick way
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If you want to do it quickly and you don't have time for anything other than copypasting commands, you should have ``curl`` installed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Make sure that you have ``curl`` and ``>=astyle-2.03`` installed
 | 
					 | 
				
			||||||
2. Modify [``tox.api.h``](/toxcore/tox.api.h)
 | 
					 | 
				
			||||||
3. Run command below ↓
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Command to run from ``toxcore`` directory (quick way, involves using curl):
 | 
					 | 
				
			||||||
```bash
 | 
					 | 
				
			||||||
# For tox.h:
 | 
					 | 
				
			||||||
curl -X POST --data-binary @- https://apidsl.herokuapp.com/apidsl \
 | 
					 | 
				
			||||||
  < toxcore/tox.api.h \
 | 
					 | 
				
			||||||
  | astyle --options=other/astyle/astylerc \
 | 
					 | 
				
			||||||
  > toxcore/tox.h
 | 
					 | 
				
			||||||
# For toxav.h:
 | 
					 | 
				
			||||||
curl -X POST --data-binary @- https://apidsl.herokuapp.com/apidsl \
 | 
					 | 
				
			||||||
  < toxav/toxav.api.h \
 | 
					 | 
				
			||||||
  | astyle --options=other/astyle/astylerc \
 | 
					 | 
				
			||||||
  > toxav/toxav.h
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
You may want to make sure with ``git diff`` that changes made in ``tox.h`` reflect changes in ``tox.in.h``.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
And you're done.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Manually
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If you prefer to have more control over what is happening, there are steps below:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Install [``apidsl``](https://github.com/TokTok/apidsl)
 | 
					 | 
				
			||||||
2. Install ``astyle``, version 2.03 or later.
 | 
					 | 
				
			||||||
3. Modify [``tox.api.h``](/toxcore/tox.api.h)
 | 
					 | 
				
			||||||
4. Use ``apidsl`` ``??``
 | 
					 | 
				
			||||||
5. Parse generated ``tox.h`` with astyle, minimal command for it would be:
 | 
					 | 
				
			||||||
```bash
 | 
					 | 
				
			||||||
astyle --options=other/astyle/astylerc toxcore/tox.h
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Always pass output from ``apidsl`` through astyle.**
 | 
					 | 
				
			||||||
							
								
								
									
										127
									
								
								external/toxcore/c-toxcore/docs/av_api.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										127
									
								
								external/toxcore/c-toxcore/docs/av_api.md
									
									
									
									
										vendored
									
									
								
							@@ -8,38 +8,36 @@
 | 
				
			|||||||
phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port);
 | 
					phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function initializes sample phone. _listen_port and _send_port are variables only meant
 | 
					function initializes sample phone. `_listen_port` and `_send_port` are variables
 | 
				
			||||||
for local testing. You will not have to do anything regarding to that since
 | 
					only meant for local testing. You will not have to do anything regarding to that
 | 
				
			||||||
everything will be started within a messenger.
 | 
					since everything will be started within a messenger.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Phone requires one msi session and two rtp sessions (one for audio and one for
 | 
				
			||||||
Phone requires one msi session and two rtp sessions ( one for audio and one for
 | 
					video).
 | 
				
			||||||
video ). 
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent );
 | 
					msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
initializes msi session.
 | 
					initializes msi session. Params:
 | 
				
			||||||
Params:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void* _core_handler - pointer to an object handling networking,
 | 
					void* _core_handler - pointer to an object handling networking,
 | 
				
			||||||
const uint8_t* _user_agent - string describing phone client version.
 | 
					const uint8_t* _user_agent - string describing phone client version.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Return value:
 | 
					Return value: `msi_session_t*` - pointer to a newly created msi session handler.
 | 
				
			||||||
msi_session_t* - pointer to a newly created msi session handler.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
### msi_session_t reference:
 | 
					### `msi_session_t` reference:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
How to handle msi session:
 | 
					How to handle msi session: Controlling is done via callbacks and action
 | 
				
			||||||
Controlling is done via callbacks and action handlers.
 | 
					handlers. First register callbacks for every state/action received and make sure
 | 
				
			||||||
First register callbacks for every state/action received and make sure
 | 
					NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every
 | 
				
			||||||
NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called 
 | 
					callback is being called directly from event loop. You can find examples in
 | 
				
			||||||
directly from event loop. You can find examples in phone.c.
 | 
					phone.c.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Register callbacks:
 | 
					Register callbacks:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void msi_register_callback_call_started ( MCALLBACK );
 | 
					void msi_register_callback_call_started ( MCALLBACK );
 | 
				
			||||||
void msi_register_callback_call_canceled ( MCALLBACK );
 | 
					void msi_register_callback_call_canceled ( MCALLBACK );
 | 
				
			||||||
@@ -55,10 +53,9 @@ void msi_register_callback_recv_error ( MCALLBACK );
 | 
				
			|||||||
void msi_register_callback_requ_timeout ( MCALLBACK );
 | 
					void msi_register_callback_requ_timeout ( MCALLBACK );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MCALLBACK is defined as: void (*callback) (void* _arg)
 | 
					MCALLBACK is defined as: `void (*callback) (void* _arg)` `msi_session_t*`
 | 
				
			||||||
msi_session_t* handler is being thrown as \_arg so you can use that and \_agent_handler to get to your own phone handler
 | 
					handler is being thrown as `_arg` so you can use that and `_agent_handler` to
 | 
				
			||||||
directly from callback.
 | 
					get to your own phone handler directly from callback.
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Actions:
 | 
					Actions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,80 +63,93 @@ Actions:
 | 
				
			|||||||
int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms );
 | 
					int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else
 | 
					Sends call invite. Before calling/sending invite `msi_session_t::_friend_id` is
 | 
				
			||||||
it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long 
 | 
					needed to be set or else it will not work. `_call_type` is type of the call (
 | 
				
			||||||
will poll wait until request is terminated.
 | 
					Audio/Video ) and `_timeoutms` is how long will poll wait until request is
 | 
				
			||||||
 | 
					terminated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int msi_hangup ( msi_session_t* _session );
 | 
					int msi_hangup ( msi_session_t* _session );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Hangs up active call
 | 
					Hangs up active call
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int msi_answer ( msi_session_t* _session, call_type _call_type );
 | 
					int msi_answer ( msi_session_t* _session, call_type _call_type );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Answer incoming call. _call_type set's callee call type.
 | 
					
 | 
				
			||||||
 | 
					Answer incoming call. `_call_type` set's callee call type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int msi_cancel ( msi_session_t* _session );
 | 
					int msi_cancel ( msi_session_t* _session );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cancel current request.
 | 
					Cancel current request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int msi_reject ( msi_session_t* _session );
 | 
					int msi_reject ( msi_session_t* _session );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Reject incoming call.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Reject incoming call.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Now for rtp:
 | 
					### Now for rtp:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You will need 2 sessions; one for audio one for video.
 | 
					You will need 2 sessions; one for audio one for video. You start them with:
 | 
				
			||||||
You start them with:
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
 | 
					rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Params:
 | 
					Params:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int _max_users - max users. -1 if undefined
 | 
					int _max_users - max users. -1 if undefined
 | 
				
			||||||
int _multi_session - any positive number means uses multi session; -1 if not.
 | 
					int _multi_session - any positive number means uses multi session; -1 if not.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Return value:
 | 
					Return value:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
rtp_session_t* - pointer to a newly created rtp session handler.
 | 
					rtp_session_t* - pointer to a newly created rtp session handler.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### How to handle rtp session:
 | 
					### How to handle rtp session:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Take a look at
 | 
					Take a look at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c
 | 
					void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
on example. Basically what you do is just receive a message via:
 | 
					on example. Basically what you do is just receive a message via:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
 | 
					struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with:
 | 
					and then you use payload within the `rtp_msg_s` struct. Don't forget to
 | 
				
			||||||
void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );
 | 
					deallocate it with:
 | 
				
			||||||
 | 
					`void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );`
 | 
				
			||||||
Receiving should be thread safe so don't worry about that.
 | 
					Receiving should be thread safe so don't worry about that.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When you capture and encode a payload you want to send it ( obviously ).
 | 
					When you capture and encode a payload you want to send it ( obviously ).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
first create a new message with:
 | 
					first create a new message with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
 | 
					struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
and then send it with:
 | 
					and then send it with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
 | 
					int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_core_handler is the same network handler as in msi_session_s struct.
 | 
					`_core_handler` is the same network handler as in `msi_session_s` struct.
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## A/V initialization:
 | 
					## A/V initialization:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int init_receive_audio(codec_state *cs);
 | 
					int init_receive_audio(codec_state *cs);
 | 
				
			||||||
int init_receive_video(codec_state *cs);
 | 
					int init_receive_video(codec_state *cs);
 | 
				
			||||||
@@ -156,39 +166,62 @@ In the future, VP8 should be used directly and ffmpeg should be dropped from the
 | 
				
			|||||||
The variable bps is the required bitrate in bits per second.
 | 
					The variable bps is the required bitrate in bits per second.
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
### A/V encoding/decoding:
 | 
					### A/V encoding/decoding:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void *encode_video_thread(void *arg);
 | 
					void *encode_video_thread(void *arg);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Spawns the video encoding thread. The argument should hold a pointer to a codec_state.
 | 
					
 | 
				
			||||||
This function should only be called if video encoding is supported (when init_send_video returns 1).
 | 
					Spawns the video encoding thread. The argument should hold a pointer to a
 | 
				
			||||||
Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded.
 | 
					`codec_state`. This function should only be called if video encoding is
 | 
				
			||||||
 | 
					supported (when `init_send_video` returns 1). Each video frame gets encoded into
 | 
				
			||||||
 | 
					a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe
 | 
				
			||||||
 | 
					is encoded.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void *encode_audio_thread(void *arg);
 | 
					void *encode_audio_thread(void *arg);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Spawns the audio encoding thread. The argument should hold a pointer to a codec_state.
 | 
					
 | 
				
			||||||
This function should only be called if audio encoding is supported (when init_send_audio returns 1).
 | 
					Spawns the audio encoding thread. The argument should hold a pointer to a
 | 
				
			||||||
Audio frames are read from the selected audio capture device during initialisation. This audio capturing can be rerouted to a different device on the fly.
 | 
					`codec_state`. This function should only be called if audio encoding is
 | 
				
			||||||
Each audio frame is encoded into a packet, and sent via RTP. All audio frames have the same amount of samples, which is defined in AV_codec.h.
 | 
					supported (when `init_send_audio` returns 1). Audio frames are read from the
 | 
				
			||||||
 | 
					selected audio capture device during initialisation. This audio capturing can be
 | 
				
			||||||
 | 
					rerouted to a different device on the fly. Each audio frame is encoded into a
 | 
				
			||||||
 | 
					packet, and sent via RTP. All audio frames have the same amount of samples,
 | 
				
			||||||
 | 
					which is defined in `AV_codec.h`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
int video_decoder_refresh(codec_state *cs, int width, int height);
 | 
					int video_decoder_refresh(codec_state *cs, int width, int height);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Sets the SDL window dimensions and creates a pixel buffer with the requested size. It also creates a scaling context, which will be used to convert the input image format to YUV420P.
 | 
					
 | 
				
			||||||
 | 
					Sets the SDL window dimensions and creates a pixel buffer with the requested
 | 
				
			||||||
 | 
					size. It also creates a scaling context, which will be used to convert the input
 | 
				
			||||||
 | 
					image format to YUV420P.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void *decode_video_thread(void *arg);
 | 
					void *decode_video_thread(void *arg);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Spawns a video decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised video decoder.
 | 
					
 | 
				
			||||||
This function reads video packets and feeds them to the video decoder. If the video frame's resolution has changed, video_decoder_refresh() is called. Afterwards, the frame is displayed on the SDL window.
 | 
					Spawns a video decoding thread. The argument should hold a pointer to a
 | 
				
			||||||
 | 
					`codec_state`. The `codec_state` is assumed to contain a successfully
 | 
				
			||||||
 | 
					initialised video decoder. This function reads video packets and feeds them to
 | 
				
			||||||
 | 
					the video decoder. If the video frame's resolution has changed,
 | 
				
			||||||
 | 
					`video_decoder_refresh()` is called. Afterwards, the frame is displayed on the
 | 
				
			||||||
 | 
					SDL window.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
void *decode_audio_thread(void *arg);
 | 
					void *decode_audio_thread(void *arg);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Spawns an audio decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised audio decoder.
 | 
					 | 
				
			||||||
All received audio packets are pushed into a jitter buffer and are reordered. If there is a missing packet, or a packet has arrived too late, it is treated as a lost packet and the audio decoder is informed of the packet loss. The audio decoder will then try to reconstruct the lost packet, based on information from previous packets.
 | 
					 | 
				
			||||||
Audio is played on the default OpenAL output device.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Spawns an audio decoding thread. The argument should hold a pointer to a
 | 
				
			||||||
 | 
					`codec_state`. The `codec_state` is assumed to contain a successfully
 | 
				
			||||||
 | 
					initialised audio decoder. All received audio packets are pushed into a jitter
 | 
				
			||||||
 | 
					buffer and are reordered. If there is a missing packet, or a packet has arrived
 | 
				
			||||||
 | 
					too late, it is treated as a lost packet and the audio decoder is informed of
 | 
				
			||||||
 | 
					the packet loss. The audio decoder will then try to reconstruct the lost packet,
 | 
				
			||||||
 | 
					based on information from previous packets. Audio is played on the default
 | 
				
			||||||
 | 
					OpenAL output device.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net:
 | 
					If you have any more qustions/bug reports/feature request contact the following
 | 
				
			||||||
For RTP and MSI: mannol
 | 
					users on the irc channel #tox-dev on irc.freenode.net: For RTP and MSI: mannol
 | 
				
			||||||
For audio and video: Martijnvdc
 | 
					For audio and video: Martijnvdc
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										101
									
								
								external/toxcore/c-toxcore/docs/minpgc.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										101
									
								
								external/toxcore/c-toxcore/docs/minpgc.md
									
									
									
									
										vendored
									
									
								
							@@ -3,29 +3,29 @@
 | 
				
			|||||||
This document describes the "minpgc" simple persistent conferences
 | 
					This document describes the "minpgc" simple persistent conferences
 | 
				
			||||||
implementation of PR #1069.
 | 
					implementation of PR #1069.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Many of the ideas derive from isotoxin's persistent conferences
 | 
					Many of the ideas derive from isotoxin's persistent conferences implementation,
 | 
				
			||||||
implementation, PR #826.
 | 
					PR #826.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Specification of changes from pre-existing conference specification
 | 
					## Specification of changes from pre-existing conference specification
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We add one new packet type:
 | 
					We add one new packet type:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Rejoin Conference packet
 | 
					Rejoin Conference packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Length | Contents              |
 | 
					| Length | Contents              |
 | 
				
			||||||
|:-------|:--------------------------------|
 | 
					| :----- | :-------------------- |
 | 
				
			||||||
| `1`    | `uint8_t` (0x64)      |
 | 
					| `1`    | `uint8_t` (0x64)      |
 | 
				
			||||||
| `33`   | Group chat identifier |
 | 
					| `33`   | Group chat identifier |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A peer times out from a group if it has been inactive for 60s. When a peer times
 | 
				
			||||||
 | 
					out, we flag it as _frozen_. Frozen peers are disregarded for all purposes
 | 
				
			||||||
 | 
					except those discussed below - in particular no packets are sent to them except
 | 
				
			||||||
 | 
					as described below, they are omitted from the peer lists sent to the client or
 | 
				
			||||||
 | 
					in a Peer Response packet, and they are not considered when determining closest
 | 
				
			||||||
 | 
					peers for establishing direct connections.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A peer times out from a group if it has been inactive for 60s. When a peer
 | 
					A peer is considered to be active if we receive a group message or Rejoin packet
 | 
				
			||||||
times out, we flag it as _frozen_. Frozen peers are disregarded for all
 | 
					from it, or a New Peer message for it.
 | 
				
			||||||
purposes except those discussed below - in particular no packets are sent to
 | 
					 | 
				
			||||||
them except as described below, they are omitted from the peer lists sent to
 | 
					 | 
				
			||||||
the client or in a Peer Response packet, and they are not considered when
 | 
					 | 
				
			||||||
determining closest peers for establishing direct connections.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A peer is considered to be active if we receive a group message or Rejoin
 | 
					 | 
				
			||||||
packet from it, or a New Peer message for it.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
If a frozen peer is seen to be active, we remove its 'frozen' flag and send a
 | 
					If a frozen peer is seen to be active, we remove its 'frozen' flag and send a
 | 
				
			||||||
Name group message. (We can hold off on sending this message until the next
 | 
					Name group message. (We can hold off on sending this message until the next
 | 
				
			||||||
@@ -40,77 +40,83 @@ message. (This is current behaviour; it's mentioned here because it's important
 | 
				
			|||||||
and not currently mentioned in the spec.)
 | 
					and not currently mentioned in the spec.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If we receive a Rejoin packet from a peer we update its DHT pubkey, add a
 | 
					If we receive a Rejoin packet from a peer we update its DHT pubkey, add a
 | 
				
			||||||
temporary groupchat connection for the peer, and, once the connection is
 | 
					temporary groupchat connection for the peer, and, once the connection is online,
 | 
				
			||||||
online, send out a New Peer message announcing the peer, and a Name message.
 | 
					send out a New Peer message announcing the peer, and a Name message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Whenever we make a new friend connection, we check if the public key is that 
 | 
					Whenever we make a new friend connection, we check if the public key is that of
 | 
				
			||||||
of any frozen peer. If so, we send it a Rejoin packet, add a temporary
 | 
					any frozen peer. If so, we send it a Rejoin packet, add a temporary groupchat
 | 
				
			||||||
groupchat connection for it, and, once the connection is online, send the
 | 
					connection for it, and, once the connection is online, send the peer a Peer
 | 
				
			||||||
peer a Peer Query packet.
 | 
					Query packet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We do the same with a peer when we are setting it as frozen if we have a
 | 
					We do the same with a peer when we are setting it as frozen if we have a friend
 | 
				
			||||||
friend connection to it.
 | 
					connection to it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The temporary groupchat connections established in sending and handling Rejoin
 | 
					The temporary groupchat connections established in sending and handling Rejoin
 | 
				
			||||||
packets are not immediately operational (because group numbers are not known);
 | 
					packets are not immediately operational (because group numbers are not known);
 | 
				
			||||||
rather, an Online packet is sent when we handle a Rejoin packet.
 | 
					rather, an Online packet is sent when we handle a Rejoin packet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When a connection is set as online as a result of an Online packet, we ping
 | 
					When a connection is set as online as a result of an Online packet, we ping the
 | 
				
			||||||
the group.
 | 
					group.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When processing the reply to a Peer Query, we update the DHT pubkey of an
 | 
					When processing the reply to a Peer Query, we update the DHT pubkey of an
 | 
				
			||||||
existing peer if and only if it is frozen or has not had its DHT pubkey
 | 
					existing peer if and only if it is frozen or has not had its DHT pubkey updated
 | 
				
			||||||
updated since it last stopped being frozen.
 | 
					since it last stopped being frozen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When we receive a Title Response packet, we set the title if it has never been
 | 
					When we receive a Title Response packet, we set the title if it has never been
 | 
				
			||||||
set or if at some point since it was last set, there were no unfrozen peers
 | 
					set or if at some point since it was last set, there were no unfrozen peers
 | 
				
			||||||
(except us).
 | 
					(except us).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Discussion
 | 
					## Discussion
 | 
				
			||||||
### Overview
 | 
					 | 
				
			||||||
The intention is to recover seamlessly from splits in the group, the most 
 | 
					 | 
				
			||||||
common form of which is a single peer temporarily losing all connectivity.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
To see how this works, first note that groups (even before the changes
 | 
					### Overview
 | 
				
			||||||
discussed here) have the property that for a group to be connected in the
 | 
					
 | 
				
			||||||
sense that any peer will receive the messages of any other peer and have them
 | 
					The intention is to recover seamlessly from splits in the group, the most common
 | 
				
			||||||
in their peerlist, it is necessary and sufficient that there is a path of
 | 
					form of which is a single peer temporarily losing all connectivity.
 | 
				
			||||||
direct group connections between any two peers.
 | 
					
 | 
				
			||||||
 | 
					To see how this works, first note that groups (even before the changes discussed
 | 
				
			||||||
 | 
					here) have the property that for a group to be connected in the sense that any
 | 
				
			||||||
 | 
					peer will receive the messages of any other peer and have them in their
 | 
				
			||||||
 | 
					peerlist, it is necessary and sufficient that there is a path of direct group
 | 
				
			||||||
 | 
					connections between any two peers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Now suppose the group is split into two connected components, with each member
 | 
					Now suppose the group is split into two connected components, with each member
 | 
				
			||||||
of one component frozen according to the members of the other. Suppose there
 | 
					of one component frozen according to the members of the other. Suppose there are
 | 
				
			||||||
are two peers, one in each component, which are using the above protocol, and
 | 
					two peers, one in each component, which are using the above protocol, and
 | 
				
			||||||
suppose they establish a friend connection. Then each will rejoin the other,
 | 
					suppose they establish a friend connection. Then each will rejoin the other,
 | 
				
			||||||
forming a direct group connection. Hence the whole group will become connected
 | 
					forming a direct group connection. Hence the whole group will become connected
 | 
				
			||||||
(even if all other peers are using the unmodified protocol).
 | 
					(even if all other peers are using the unmodified protocol).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The Peer Query packet sent on rejoining hastens this process.
 | 
					The Peer Query packet sent on rejoining hastens this process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Peers who leave the group during a split will not be deleted by all peers
 | 
					Peers who leave the group during a split will not be deleted by all peers after
 | 
				
			||||||
after the merge - but they will be set as frozen due to ping timeouts, which
 | 
					the merge - but they will be set as frozen due to ping timeouts, which is
 | 
				
			||||||
is sufficient.
 | 
					sufficient.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Titles
 | 
					### Titles
 | 
				
			||||||
If we have a split into components each containing multiple peers, and the
 | 
					
 | 
				
			||||||
title is changed in one component, then peers will continue to disagree on the
 | 
					If we have a split into components each containing multiple peers, and the title
 | 
				
			||||||
title after the split. Short of a complicated voting system, this seems the
 | 
					is changed in one component, then peers will continue to disagree on the title
 | 
				
			||||||
only reasonable behaviour.
 | 
					after the split. Short of a complicated voting system, this seems the only
 | 
				
			||||||
 | 
					reasonable behaviour.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Implementation notes
 | 
					### Implementation notes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Although I've described the logic in terms of an 'frozen' flag, it might
 | 
					Although I've described the logic in terms of an 'frozen' flag, it might
 | 
				
			||||||
actually make more sense in the implementation to have a separate list for
 | 
					actually make more sense in the implementation to have a separate list for
 | 
				
			||||||
frozen peers.
 | 
					frozen peers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Saving
 | 
					## Saving
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Saving is implemented by simply saving all live groups with their group numbers
 | 
					Saving is implemented by simply saving all live groups with their group numbers
 | 
				
			||||||
and full peer info for all peers. On reload, all peers are set as frozen.
 | 
					and full peer info for all peers. On reload, all peers are set as frozen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Clients needs to support this by understanding that groups may exist on
 | 
					Clients needs to support this by understanding that groups may exist on
 | 
				
			||||||
start-up. Clients should call `tox_conference_get_chatlist` to obtain them. A
 | 
					start-up. Clients should call `tox_conference_get_chatlist` to obtain them. A
 | 
				
			||||||
group which is deleted (with `tox_conference_delete`) is removed permanently
 | 
					group which is deleted (with `tox_conference_delete`) is removed permanently and
 | 
				
			||||||
and will not be saved.
 | 
					will not be saved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Limitations
 | 
					## Limitations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If a peer disconnects from the group for a period short enough that group
 | 
					If a peer disconnects from the group for a period short enough that group
 | 
				
			||||||
timeouts do not occur, and a name change occurs during this period, then the
 | 
					timeouts do not occur, and a name change occurs during this period, then the
 | 
				
			||||||
name change will never be propagated.
 | 
					name change will never be propagated.
 | 
				
			||||||
@@ -120,9 +126,8 @@ requesting missed group messages. But this is considered out of scope of this
 | 
				
			|||||||
PR.
 | 
					PR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If a peer changes its DHT pubkey, the change might not be properly propagated
 | 
					If a peer changes its DHT pubkey, the change might not be properly propagated
 | 
				
			||||||
under various circumstances - in particular, if connections do not go down
 | 
					under various circumstances - in particular, if connections do not go down long
 | 
				
			||||||
long enough for the peer to become frozen.
 | 
					enough for the peer to become frozen.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
One way to deal with this would be to add a group message announcing the
 | 
					One way to deal with this would be to add a group message announcing the sending
 | 
				
			||||||
sending peer's current DHT pubkey, and treat it analogously to the Name
 | 
					peer's current DHT pubkey, and treat it analogously to the Name message.
 | 
				
			||||||
message.
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								external/toxcore/c-toxcore/other/DHT_bootstrap.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								external/toxcore/c-toxcore/other/DHT_bootstrap.c
									
									
									
									
										vendored
									
									
								
							@@ -50,7 +50,6 @@ static const char *motd_str = ""; //Change this to anything within 256 bytes(but
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define PORT 33445
 | 
					#define PORT 33445
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool manage_keys(DHT *dht)
 | 
					static bool manage_keys(DHT *dht)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
 | 
					    enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
 | 
				
			||||||
@@ -61,7 +60,7 @@ static bool manage_keys(DHT *dht)
 | 
				
			|||||||
    if (keys_file != nullptr) {
 | 
					    if (keys_file != nullptr) {
 | 
				
			||||||
        /* If file was opened successfully -- load keys,
 | 
					        /* If file was opened successfully -- load keys,
 | 
				
			||||||
           otherwise save new keys */
 | 
					           otherwise save new keys */
 | 
				
			||||||
        size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
 | 
					        const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (read_size != KEYS_SIZE) {
 | 
					        if (read_size != KEYS_SIZE) {
 | 
				
			||||||
            printf("Error while reading the key file\nExiting.\n");
 | 
					            printf("Error while reading the key file\nExiting.\n");
 | 
				
			||||||
@@ -126,7 +125,7 @@ static void print_log(void *context, Logger_Level level, const char *file, int l
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[])
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (argc == 2 && !tox_strncasecmp(argv[1], "-h", 3)) {
 | 
					    if (argc == 2 && tox_strncasecmp(argv[1], "-h", 3) == 0) {
 | 
				
			||||||
        printf("Usage (connected)  : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]);
 | 
					        printf("Usage (connected)  : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]);
 | 
				
			||||||
        printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]);
 | 
					        printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]);
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
@@ -134,7 +133,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* let user override default by cmdline */
 | 
					    /* let user override default by cmdline */
 | 
				
			||||||
    bool ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
 | 
					    bool ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
 | 
				
			||||||
    int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
 | 
					    const int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (argvoffset < 0) {
 | 
					    if (argvoffset < 0) {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@@ -151,9 +150,9 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
        logger_callback_log(logger, print_log, nullptr, nullptr);
 | 
					        logger_callback_log(logger, print_log, nullptr, nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const Random *rng = system_random();
 | 
					    const Random *rng = os_random();
 | 
				
			||||||
    const Network *ns = system_network();
 | 
					    const Network *ns = os_network();
 | 
				
			||||||
    const Memory *mem = system_memory();
 | 
					    const Memory *mem = os_memory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
					    Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
 | 
				
			||||||
    const uint16_t start_port = PORT;
 | 
					    const uint16_t start_port = PORT;
 | 
				
			||||||
@@ -165,11 +164,12 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
    Onion_Announce *onion_a = new_onion_announce(logger, mem, rng, mono_time, dht);
 | 
					    Onion_Announce *onion_a = new_onion_announce(logger, mem, rng, mono_time, dht);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DHT_NODE_EXTRA_PACKETS
 | 
					#ifdef DHT_NODE_EXTRA_PACKETS
 | 
				
			||||||
    bootstrap_set_callbacks(dht_get_net(dht), (uint32_t)DAEMON_VERSION_NUMBER, (const uint8_t *) motd_str, strlen(motd_str)+1);
 | 
					    bootstrap_set_callbacks(dht_get_net(dht), (uint32_t)DAEMON_VERSION_NUMBER, (const uint8_t *) motd_str, strlen(motd_str) + 1);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(onion && forwarding && onion_a)) {
 | 
					    if (onion == nullptr || forwarding == nullptr || onion_a == nullptr) {
 | 
				
			||||||
        printf("Something failed to initialize.\n");
 | 
					        printf("Something failed to initialize.\n");
 | 
				
			||||||
 | 
					        // cppcheck-suppress resourceLeak
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -178,17 +178,19 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
    perror("Initialization");
 | 
					    perror("Initialization");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!manage_keys(dht)) {
 | 
					    if (!manage_keys(dht)) {
 | 
				
			||||||
 | 
					        // cppcheck-suppress resourceLeak
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    printf("Public key: ");
 | 
					    printf("Public key: ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TCP_RELAY_ENABLED
 | 
					#ifdef TCP_RELAY_ENABLED
 | 
				
			||||||
#define NUM_PORTS 3
 | 
					#define NUM_PORTS 3
 | 
				
			||||||
    uint16_t ports[NUM_PORTS] = {443, 3389, PORT};
 | 
					    const uint16_t ports[NUM_PORTS] = {443, 3389, PORT};
 | 
				
			||||||
    TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, ipv6enabled, NUM_PORTS, ports, dht_get_self_secret_key(dht), onion, forwarding);
 | 
					    TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, ipv6enabled, NUM_PORTS, ports, dht_get_self_secret_key(dht), onion, forwarding);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (tcp_s == nullptr) {
 | 
					    if (tcp_s == nullptr) {
 | 
				
			||||||
        printf("TCP server failed to initialize.\n");
 | 
					        printf("TCP server failed to initialize.\n");
 | 
				
			||||||
 | 
					        // cppcheck-suppress resourceLeak
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -199,6 +201,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (file == nullptr) {
 | 
					    if (file == nullptr) {
 | 
				
			||||||
        printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename);
 | 
					        printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename);
 | 
				
			||||||
 | 
					        // cppcheck-suppress resourceLeak
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -226,7 +229,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
        const uint16_t port = net_htons((uint16_t)port_conv);
 | 
					        const uint16_t port = net_htons((uint16_t)port_conv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
 | 
					        uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
 | 
				
			||||||
        int res = dht_bootstrap_from_address(dht, argv[argvoffset + 1],
 | 
					        const bool res = dht_bootstrap_from_address(dht, argv[argvoffset + 1],
 | 
				
			||||||
                         ipv6enabled, port, bootstrap_key);
 | 
					                         ipv6enabled, port, bootstrap_key);
 | 
				
			||||||
        free(bootstrap_key);
 | 
					        free(bootstrap_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -236,17 +239,17 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int is_waiting_for_dht_connection = 1;
 | 
					    bool is_waiting_for_dht_connection = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint64_t last_lan_discovery = 0;
 | 
					    uint64_t last_lan_discovery = 0;
 | 
				
			||||||
    const Broadcast_Info *broadcast = lan_discovery_init(ns);
 | 
					    const Broadcast_Info *broadcast = lan_discovery_init(ns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (1) {
 | 
					    while (true) {
 | 
				
			||||||
        mono_time_update(mono_time);
 | 
					        mono_time_update(mono_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_waiting_for_dht_connection && dht_isconnected(dht)) {
 | 
					        if (is_waiting_for_dht_connection && dht_isconnected(dht)) {
 | 
				
			||||||
            printf("Connected to other bootstrap node successfully.\n");
 | 
					            printf("Connected to other bootstrap node successfully.\n");
 | 
				
			||||||
            is_waiting_for_dht_connection = 0;
 | 
					            is_waiting_for_dht_connection = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do_dht(dht);
 | 
					        do_dht(dht);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,17 +3,20 @@
 | 
				
			|||||||
CHECKS="*"
 | 
					CHECKS="*"
 | 
				
			||||||
ERRORS="*"
 | 
					ERRORS="*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Can't fix this, because winsock has different HANDLE type than posix.
 | 
				
			||||||
 | 
					# Still good to occasionally look at.
 | 
				
			||||||
 | 
					ERRORS="$ERRORS,-google-readability-casting"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Need to investigate or disable and document these.
 | 
					# Need to investigate or disable and document these.
 | 
				
			||||||
# =========================================================
 | 
					# =========================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(iphydf): Fix these.
 | 
					# TODO(iphydf): Fix these.
 | 
				
			||||||
ERRORS="$ERRORS,-cert-err34-c"
 | 
					ERRORS="$ERRORS,-cert-err34-c"
 | 
				
			||||||
ERRORS="$ERRORS,-readability-suspicious-call-argument"
 | 
					ERRORS="$ERRORS,-readability-suspicious-call-argument"
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto"
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-bugprone-incorrect-roundings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(iphydf): Fix once cimple 0.0.19 is released.
 | 
					# TODO(iphydf): Fix this by making more functions set error code enums.
 | 
				
			||||||
CHECKS="$CHECKS,-google-readability-casting"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# TODO(iphydf): Fix these.
 | 
					 | 
				
			||||||
CHECKS="$CHECKS,-bugprone-switch-missing-default-case"
 | 
					CHECKS="$CHECKS,-bugprone-switch-missing-default-case"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(iphydf): We might want some of these. For the ones we don't want, add a
 | 
					# TODO(iphydf): We might want some of these. For the ones we don't want, add a
 | 
				
			||||||
@@ -30,17 +33,22 @@ CHECKS="$CHECKS,-misc-no-recursion"
 | 
				
			|||||||
CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables"
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO(iphydf): Probably fix these.
 | 
					# TODO(iphydf): Probably fix these.
 | 
				
			||||||
CHECKS="$CHECKS,-cert-err33-c"
 | 
					CHECKS="$CHECKS,-cert-err33-c,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers"
 | 
				
			||||||
CHECKS="$CHECKS,-cppcoreguidelines-avoid-magic-numbers"
 | 
					 | 
				
			||||||
CHECKS="$CHECKS,-readability-magic-numbers"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# TODO(iphydf): We're using a lot of macros for constants. Should we convert
 | 
					 | 
				
			||||||
# all of them to enum?
 | 
					 | 
				
			||||||
CHECKS="$CHECKS,-modernize-macro-to-enum"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Documented disabled checks. We don't want these for sure.
 | 
					# Documented disabled checks. We don't want these for sure.
 | 
				
			||||||
# =========================================================
 | 
					# =========================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# We want to decay many arrays to pointers. In C, we do that all the time.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# enum{} breaks comparisons and arithmetic in C++.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-modernize-macro-to-enum"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For most things, we do want this, but for some we want to ensure (with msan)
 | 
				
			||||||
 | 
					# that struct members are actually initialised with useful non-zero values.
 | 
				
			||||||
 | 
					# Initialising them by default takes away that validation.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-type-member-init,-hicpp-member-init"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument
 | 
					# https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument
 | 
				
			||||||
CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized"
 | 
					CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,8 +123,7 @@ CHECKS="$CHECKS,-readability-redundant-control-flow"
 | 
				
			|||||||
#                                      ^
 | 
					#                                      ^
 | 
				
			||||||
# Trip the checker, which is true, because of integer promotion, but also not
 | 
					# Trip the checker, which is true, because of integer promotion, but also not
 | 
				
			||||||
# very helpful as a diagnostic.
 | 
					# very helpful as a diagnostic.
 | 
				
			||||||
CHECKS="$CHECKS,-bugprone-narrowing-conversions"
 | 
					CHECKS="$CHECKS,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions"
 | 
				
			||||||
CHECKS="$CHECKS,-cppcoreguidelines-narrowing-conversions"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Mistakenly thinks that
 | 
					# Mistakenly thinks that
 | 
				
			||||||
#   const int a = 0, b = 1;
 | 
					#   const int a = 0, b = 1;
 | 
				
			||||||
@@ -135,9 +142,51 @@ CHECKS="$CHECKS,-cppcoreguidelines-narrowing-conversions"
 | 
				
			|||||||
# - Turning 'a' and 'b' into pre-processor macros is the only option left, but
 | 
					# - Turning 'a' and 'b' into pre-processor macros is the only option left, but
 | 
				
			||||||
#   #defines and #undefs in the middle of a function hurt the readability and
 | 
					#   #defines and #undefs in the middle of a function hurt the readability and
 | 
				
			||||||
#   are less idiomatic than simply using 'const int'.
 | 
					#   are less idiomatic than simply using 'const int'.
 | 
				
			||||||
CHECKS="$CHECKS,-cert-dcl03-c"
 | 
					CHECKS="$CHECKS,-cert-dcl03-c,-hicpp-static-assert,-misc-static-assert"
 | 
				
			||||||
CHECKS="$CHECKS,-hicpp-static-assert"
 | 
					
 | 
				
			||||||
CHECKS="$CHECKS,-misc-static-assert"
 | 
					# Doesn't consider use of preprocessor macros as needing a header, breaking
 | 
				
			||||||
 | 
					# struct definitions that depend on size macros from e.g. crypto_core.h.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-misc-include-cleaner"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A bunch of checks only valid for C++, we turn off for C.
 | 
				
			||||||
 | 
					# =========================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# We don't use Google's int typedefs.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-google-runtime-int"
 | 
				
			||||||
 | 
					# We write C code, so we use C arrays.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays"
 | 
				
			||||||
 | 
					# C loops are ok. This one tells us to use range-for.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-modernize-loop-convert"
 | 
				
			||||||
 | 
					# No auto in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-hicpp-use-auto,-modernize-use-auto"
 | 
				
			||||||
 | 
					# Only C style casts in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-type-cstyle-cast"
 | 
				
			||||||
 | 
					# We use malloc (for now), and MISRA checks this too.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-no-malloc,-hicpp-no-malloc"
 | 
				
			||||||
 | 
					# No owning_ptr<> in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-owning-memory"
 | 
				
			||||||
 | 
					# void foo(void) is good in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-modernize-redundant-void-arg"
 | 
				
			||||||
 | 
					# No using-typedefs in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-modernize-use-using"
 | 
				
			||||||
 | 
					# No namespaces in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-misc-use-anonymous-namespace"
 | 
				
			||||||
 | 
					# No trailing return type in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-modernize-use-trailing-return-type"
 | 
				
			||||||
 | 
					# No <cstdint> and friends in C.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-hicpp-deprecated-headers,-modernize-deprecated-headers"
 | 
				
			||||||
 | 
					# We use varargs for logging (we could reconsider, but right now we do).
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-cert-dcl50-cpp"
 | 
				
			||||||
 | 
					# We do want to use the array index operator, even when the index is non-constant.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-constant-array-index"
 | 
				
			||||||
 | 
					# We don't want to use pointer arithmetic, but this one includes array index
 | 
				
			||||||
 | 
					# operators, which we do want to use.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-pointer-arithmetic"
 | 
				
			||||||
 | 
					# Can't use constexpr, yet. C will have it eventually, but it'll be years
 | 
				
			||||||
 | 
					# until we can use it across all the compilers.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-cppcoreguidelines-macro-usage"
 | 
				
			||||||
 | 
					# These are all very C++ and/or LLVM specific.
 | 
				
			||||||
 | 
					CHECKS="$CHECKS,-llvmlibc-*"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set -eux
 | 
					set -eux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -154,7 +203,7 @@ copy_files() {
 | 
				
			|||||||
  find "${DIRS[@]}" \
 | 
					  find "${DIRS[@]}" \
 | 
				
			||||||
    -maxdepth 1 -type d -exec mkdir -p "$1/{}" \;
 | 
					    -maxdepth 1 -type d -exec mkdir -p "$1/{}" \;
 | 
				
			||||||
  find "${DIRS[@]}" \
 | 
					  find "${DIRS[@]}" \
 | 
				
			||||||
    -maxdepth 1 -name "*.c" -exec cp "{}" "$1/{}" \;
 | 
					    -maxdepth 1 -name "*.[ch]" -exec cp "{}" "$1/{}" \;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
run() {
 | 
					run() {
 | 
				
			||||||
@@ -166,7 +215,7 @@ run() {
 | 
				
			|||||||
  ls .clang-tidy
 | 
					  ls .clang-tidy
 | 
				
			||||||
  copy_files a
 | 
					  copy_files a
 | 
				
			||||||
  if ! find "${DIRS[@]}" \
 | 
					  if ! find "${DIRS[@]}" \
 | 
				
			||||||
    -maxdepth 1 -name "*.c" -print0 \
 | 
					    -maxdepth 1 -name "*.[ch]" -print0 \
 | 
				
			||||||
    | xargs -0 -n15 -P"$(nproc)" clang-tidy \
 | 
					    | xargs -0 -n15 -P"$(nproc)" clang-tidy \
 | 
				
			||||||
      -p="$PWD/_build" \
 | 
					      -p="$PWD/_build" \
 | 
				
			||||||
      --extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \
 | 
					      --extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \
 | 
				
			||||||
@@ -184,5 +233,6 @@ run() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
 | 
					cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
 | 
				
			||||||
 | 
					sed -i -e 's/-std=c11/-xc++/' _build/compile_commands.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
. other/analysis/variants.sh
 | 
					. other/analysis/variants.sh
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								external/toxcore/c-toxcore/other/astyle/astylerc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								external/toxcore/c-toxcore/other/astyle/astylerc
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
# Bracket Style Options
 | 
					# Bracket Style Options
 | 
				
			||||||
--style=kr
 | 
					--style=kr
 | 
				
			||||||
 | 
					--attach-namespaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Tab Options
 | 
					# Tab Options
 | 
				
			||||||
--indent=spaces=4
 | 
					--indent=spaces=4
 | 
				
			||||||
@@ -9,15 +10,21 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Padding Options
 | 
					# Padding Options
 | 
				
			||||||
--pad-header
 | 
					--pad-header
 | 
				
			||||||
--break-blocks
 | 
					 | 
				
			||||||
--pad-oper
 | 
					--pad-oper
 | 
				
			||||||
 | 
					# Not supported in restyled's astyle.
 | 
				
			||||||
 | 
					#--unpad-brackets
 | 
				
			||||||
--unpad-paren
 | 
					--unpad-paren
 | 
				
			||||||
--align-pointer=name
 | 
					--align-pointer=name
 | 
				
			||||||
--align-reference=name
 | 
					--align-reference=name
 | 
				
			||||||
 | 
					# Disabled because it causes very large changes and it's unclear whether we
 | 
				
			||||||
 | 
					# want all of those.
 | 
				
			||||||
 | 
					#--squeeze-ws
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Formatting Options
 | 
					# Formatting Options
 | 
				
			||||||
 | 
					--add-braces
 | 
				
			||||||
--convert-tabs
 | 
					--convert-tabs
 | 
				
			||||||
--max-code-length=120
 | 
					--max-code-length=200
 | 
				
			||||||
 | 
					--attach-return-type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Other Options
 | 
					# Other Options
 | 
				
			||||||
--preserve-date
 | 
					--preserve-date
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,36 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
set -ex
 | 
					set -ex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SOURCE_DIR="$1"
 | 
					 | 
				
			||||||
ASTYLE="$2"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Go to the source root.
 | 
					 | 
				
			||||||
if [ -z "$SOURCE_DIR" ]; then
 | 
					 | 
				
			||||||
  SOURCE_DIR=.
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
cd "$SOURCE_DIR"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if [ -z "$ASTYLE" ] || ! which "$ASTYLE"; then
 | 
					 | 
				
			||||||
  ASTYLE=astyle
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if ! which "$ASTYLE"; then
 | 
					 | 
				
			||||||
  # If we couldn't find or install an astyle binary, don't do anything.
 | 
					 | 
				
			||||||
  echo "Could not find an astyle binary; please install astyle."
 | 
					 | 
				
			||||||
  exit 1
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
readarray -t CC_SOURCES <<<"$(find . '(' -name '*.cc' ')')"
 | 
					 | 
				
			||||||
CC_SOURCES+=(toxcore/crypto_core.c)
 | 
					 | 
				
			||||||
CC_SOURCES+=(toxcore/ping_array.c)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
for bin in clang-format-11 clang-format-7 clang-format-6.0 clang-format-5.0 clang-format; do
 | 
					 | 
				
			||||||
  if which "$bin"; then
 | 
					 | 
				
			||||||
    "$bin" -i -style='{BasedOnStyle: Google, ColumnLimit: 100}' "${CC_SOURCES[@]}"
 | 
					 | 
				
			||||||
    break
 | 
					 | 
				
			||||||
  fi
 | 
					 | 
				
			||||||
done
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FIND="find ."
 | 
					FIND="find ."
 | 
				
			||||||
FIND="$FIND '(' -name '*.[ch]' ')'"
 | 
					FIND="$FIND '(' -name '*.[ch]' ')'"
 | 
				
			||||||
FIND="$FIND -and -not -name '*.api.h'"
 | 
					FIND="$FIND -and -not -name '*.api.h'"
 | 
				
			||||||
@@ -40,7 +10,15 @@ FIND="$FIND -and -not -wholename './third_party/*'"
 | 
				
			|||||||
FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'"
 | 
					FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
readarray -t C_SOURCES <<<"$(eval "$FIND")"
 | 
					readarray -t C_SOURCES <<<"$(eval "$FIND")"
 | 
				
			||||||
 | 
					readarray -t CC_SOURCES <<<"$(find . '(' -name '*.cc' -or -name '*.hh' ')')"
 | 
				
			||||||
 | 
					#CC_SOURCES+=(toxcore/crypto_core.c)
 | 
				
			||||||
 | 
					#CC_SOURCES+=(toxcore/ping_array.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"$ASTYLE" -n --options=other/astyle/astylerc "${C_SOURCES[@]}"
 | 
					# Format C++ sources with clang-format.
 | 
				
			||||||
 | 
					clang-format -i "${CC_SOURCES[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Format C sources with astyle. We can't use clang-format, because it strongly
 | 
				
			||||||
 | 
					# messes up formatting of non_null annotations.
 | 
				
			||||||
 | 
					astyle -n --options=other/astyle/astylerc "${C_SOURCES[@]}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
git diff --color=always --exit-code
 | 
					git diff --color=always --exit-code
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,8 +48,9 @@ RUN CC=clang cmake -B_build -H. \
 | 
				
			|||||||
# Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't
 | 
					# Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't
 | 
				
			||||||
# mess with your binaries.
 | 
					# mess with your binaries.
 | 
				
			||||||
COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/
 | 
					COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/
 | 
				
			||||||
RUN SHA256="$(sha256sum /usr/local/bin/tox-bootstrapd)" && \
 | 
					ARG CHECK=sha256sum
 | 
				
			||||||
    (sha256sum -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 || \
 | 
					RUN SHA256="$("$CHECK" /usr/local/bin/tox-bootstrapd)" && \
 | 
				
			||||||
 | 
					    ("$CHECK" -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 || \
 | 
				
			||||||
    (echo "::error file=other/bootstrap_daemon/docker/tox-bootstrapd.sha256,line=1::$SHA256" && \
 | 
					    (echo "::error file=other/bootstrap_daemon/docker/tox-bootstrapd.sha256,line=1::$SHA256" && \
 | 
				
			||||||
     false))
 | 
					     false))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user