diff --git a/CMakeLists.txt b/CMakeLists.txt index 81f2fdd..4933e1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if (DEFINED ENV{IDF_PATH}) INCLUDE_DIRS "./src" ${HTTP_INCLUDE_PUBLIC_DIRS} ${MQTT_INCLUDE_PUBLIC_DIRS} REQUIRES mbedtls srtp json esp_netif ) - add_definitions("-DESP32 -DHTTP_DO_NOT_USE_CUSTOM_CONFIG -DMQTT_DO_NOT_USE_CUSTOM_CONFIG") + add_definitions("-DCONFIG_USE_LWIP=1" "-DCONFIG_USE_USRSCTP=0" "-DCONFIG_AUDIO_BUFFER_SIZE=8096" "-DCONFIG_DATA_BUFFER_SIZE=102400" "-DHTTP_DO_NOT_USE_CUSTOM_CONFIG" "-DMQTT_DO_NOT_USE_CUSTOM_CONFIG") return() endif() diff --git a/README.md b/README.md index ad00fcc..9dd0bc9 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,5 @@ $ ./generic/sample/sample ### Examples for Platforms - [ESP32](https://github.com/sepfy/libpeer/tree/main/examples/esp32): MJPEG over datachannel +- [PICO](https://github.com/sepfy/libpeer/tree/main/examples/pico): Ping pong with datachannel - [Raspberry Pi](https://github.com/sepfy/libpeer/tree/main/examples/raspberrypi): Video and two-way audio stream diff --git a/examples/esp32/main/app_main.c b/examples/esp32/main/app_main.c index a45377f..da2685a 100644 --- a/examples/esp32/main/app_main.c +++ b/examples/esp32/main/app_main.c @@ -130,8 +130,6 @@ void app_main(void) { peer_signaling_set_config(&service_config); peer_signaling_join_channel(); - peer_signaling_join_channel(deviceid, g_pc); - #if defined(CONFIG_ESP32S3_XIAO_SENSE) StackType_t* stack_memory = (StackType_t*)heap_caps_malloc(8192 * sizeof(StackType_t), MALLOC_CAP_SPIRAM); StaticTask_t task_buffer; diff --git a/examples/esp32/main/idf_component.yml b/examples/esp32/main/idf_component.yml index a885894..d1cfb88 100644 --- a/examples/esp32/main/idf_component.yml +++ b/examples/esp32/main/idf_component.yml @@ -1,6 +1,8 @@ ## IDF Component Manager Manifest File dependencies: - sepfy/libpeer: ">=0.0.2" + sepfy/libpeer: + path: ../../../ + version: ">=0.0.2" espressif/esp_audio_codec: "^2.0.0" espressif/esp32-camera: "^2.0.4" protocol_examples_common: diff --git a/examples/esp32/sdkconfig.defaults b/examples/esp32/sdkconfig.defaults index 531431e..3c991cf 100644 --- a/examples/esp32/sdkconfig.defaults +++ b/examples/esp32/sdkconfig.defaults @@ -1,13 +1,9 @@ # This file was generated using idf.py save-defconfig. It can be edited manually. # Espressif IoT Development Framework (ESP-IDF) 5.2.2 Project Minimal Configuration # -CONFIG_IDF_TARGET="esp32s3" CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_ESP32S3_XIAO_SENSE=y -CONFIG_EXAMPLE_WIFI_SSID="myssid" -CONFIG_EXAMPLE_WIFI_PASSWORD="mypassword" CONFIG_EXAMPLE_CONNECT_IPV6=n CONFIG_ESP_PHY_REDUCE_TX_POWER=y CONFIG_SPIRAM=y @@ -17,9 +13,7 @@ CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048 CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n CONFIG_ESP_IPC_TASK_STACK_SIZE=2048 -CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=16 CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=32 -CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=64 CONFIG_LWIP_IPV6_AUTOCONFIG=y CONFIG_LWIP_IPV6_DHCP6=y CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 diff --git a/examples/pico/.gitignore b/examples/pico/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/examples/pico/.gitignore @@ -0,0 +1 @@ +build diff --git a/examples/pico/CMakeLists.txt b/examples/pico/CMakeLists.txt new file mode 100644 index 0000000..5381860 --- /dev/null +++ b/examples/pico/CMakeLists.txt @@ -0,0 +1,126 @@ +cmake_minimum_required(VERSION 3.13) + +set(PICO_BOARD pico_w) + +include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake) + +project(pico-peer) +pico_sdk_init() + +include(FreeRTOS_Kernel_import.cmake) + +include(${CMAKE_CURRENT_LIST_DIR}/../../third_party/coreHTTP/httpFilePaths.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../../third_party/coreMQTT/mqttFilePaths.cmake) +include_directories( + ${CMAKE_CURRENT_LIST_DIR}/ + ${CMAKE_BINARY_DIR}/ + ${CMAKE_CURRENT_LIST_DIR}/../../third_party/libsrtp/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../third_party/libsrtp/crypto/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../third_party/cJSON/ + ${CMAKE_CURRENT_LIST_DIR}/../../src/ + ${HTTP_INCLUDE_PUBLIC_DIRS} + ${MQTT_INCLUDE_PUBLIC_DIRS} +) + +set(PICO_SDK_LIBS + pico_stdlib + pico_cyw43_arch_lwip_sys_freertos + pico_mbedtls + FreeRTOS-Kernel-Heap4 +) + +# Build libsrtp +file(GLOB LIBSRTP_SRC + ../../third_party/libsrtp/srtp/srtp.c + ../../third_party/libsrtp/crypto/cipher/cipher.c + ../../third_party/libsrtp/crypto/cipher/null_cipher.c + ../../third_party/libsrtp/crypto/cipher/aes.c + ../../third_party/libsrtp/crypto/cipher/aes_icm.c + ../../third_party/libsrtp/crypto/cipher/cipher_test_cases.c + ../../third_party/libsrtp/crypto/hash/auth.c + ../../third_party/libsrtp/crypto/hash/null_auth.c + ../../third_party/libsrtp/crypto/hash/hmac.c + ../../third_party/libsrtp/crypto/hash/sha1.c + ../../third_party/libsrtp/crypto/hash/auth_test_cases.c + ../../third_party/libsrtp/crypto/kernel/alloc.c + ../../third_party/libsrtp/crypto/kernel/crypto_kernel.c + ../../third_party/libsrtp/crypto/kernel/err.c + ../../third_party/libsrtp/crypto/kernel/key.c + ../../third_party/libsrtp/crypto/math/datatypes.c + ../../third_party/libsrtp/crypto/math/stat.c + ../../third_party/libsrtp/crypto/replay/rdb.c + ../../third_party/libsrtp/crypto/replay/rdbx.c + ../../third_party/libsrtp/crypto/replay/ut_sim.c +) + +add_library(srtp STATIC + ${LIBSRTP_SRC} +) + +target_compile_definitions(srtp PRIVATE + HAVE_CONFIG_H + PRIx64=PRIx32 +) + +target_link_libraries(srtp + ${PICO_SDK_LIBS} +) + +add_custom_command(TARGET srtp + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/srtp2/ + COMMAND ${CMAKE_COMMAND} -E copy + ../../../third_party/libsrtp/include/srtp.h + ${CMAKE_BINARY_DIR}/srtp2/ +) + +# Build cJSON +add_library(cjson STATIC + ../../third_party/cJSON/cJSON.c +) + +# Build peer +file(GLOB LIBPEER_SRC "../../src/*.c") +add_library(peer STATIC + ${LIBPEER_SRC} + ${HTTP_SOURCES} + ${MQTT_SOURCES} + ${MQTT_SERIALIZER_SOURCES} +) + +target_compile_definitions(peer PRIVATE + __BYTE_ORDER=__LITTLE_ENDIAN + CONFIG_USE_LWIP=1 + CONFIG_USE_USRSCTP=0 + CONFIG_MBEDTLS_2_X=1 + CONFIG_DATA_BUFFER_SIZE=4096 + HTTP_DO_NOT_USE_CUSTOM_CONFIG + MQTT_DO_NOT_USE_CUSTOM_CONFIG +) + +target_link_libraries(peer + ${PICO_SDK_LIBS} + srtp + cjson +) + +# Build pico_peer +add_executable(pico_peer + main.c +) + +target_compile_definitions(pico_peer PRIVATE + WIFI_SSID="$ENV{WIFI_SSID}" + WIFI_PASSWORD="$ENV{WIFI_PASSWORD}" + PICO_HEAP_SIZE=0x20000 + #PICO_DEBUG_MALLOC=1 +) + +target_link_libraries(pico_peer + ${PICO_SDK_LIBS} + peer +) + +pico_enable_stdio_usb(pico_peer 1) +pico_enable_stdio_uart(pico_peer 0) +pico_add_extra_outputs(pico_peer) diff --git a/examples/pico/FreeRTOSConfig.h b/examples/pico/FreeRTOSConfig.h new file mode 100644 index 0000000..2f5fee9 --- /dev/null +++ b/examples/pico/FreeRTOSConfig.h @@ -0,0 +1,113 @@ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/* Scheduler Related */ +#define configUSE_PREEMPTION 1 +#define configUSE_TICKLESS_IDLE 0 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMAX_PRIORITIES 32 +#define configMINIMAL_STACK_SIZE (configSTACK_DEPTH_TYPE)512 +#define configUSE_16_BIT_TICKS 0 + +#define configIDLE_SHOULD_YIELD 1 + +/* Synchronization Related */ +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_NEWLIB_REENTRANT 0 +// todo need this for lwip FreeRTOS sys_arch to compile +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5 + +/* System */ +#define configSTACK_DEPTH_TYPE uint32_t +#define configMESSAGE_BUFFER_LENGTH_TYPE size_t + +/* Memory allocation related definitions. */ +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#define configTOTAL_HEAP_SIZE (48 * 1024) +#define configAPPLICATION_ALLOCATED_HEAP 0 + +/* Hook function related definitions. */ +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine related definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 1 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH 1024 + +/* Interrupt nesting behaviour configuration. */ +/* +#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor] +#define configMAX_SYSCALL_INTERRUPT_PRIORITY [dependent on processor and application] +#define configMAX_API_CALL_INTERRUPT_PRIORITY [dependent on processor and application] +*/ + +#define configNUMBER_OF_CORES 2 +/* SMP (configNUMBER_OF_CORES > 1) only */ +#define configTICK_CORE 0 +#define configRUN_MULTIPLE_PRIORITIES 1 +#if configNUMBER_OF_CORES > 1 +#define configUSE_CORE_AFFINITY 1 +#endif +#define configUSE_PASSIVE_IDLE_HOOK 0 + +/* Armv8-M */ + +/* Not currently supported */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +/* Not currently supported */ +#define configENABLE_TRUSTZONE 0 +#define configRUN_FREERTOS_SECURE_ONLY 1 +// see https://www.freertos.org/RTOS-Cortex-M3-M4.html +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16 + +/* RP2xxx specific */ +#define configSUPPORT_PICO_SYNC_INTEROP 1 +#define configSUPPORT_PICO_TIME_INTEROP 1 + +#include +/* Define to trap errors during development. */ +#define configASSERT(x) assert(x) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xTaskResumeFromISR 1 +#define INCLUDE_xQueueGetMutexHolder 1 + +#endif // FREERTOS_CONFIG_H diff --git a/examples/pico/FreeRTOS_Kernel_import.cmake b/examples/pico/FreeRTOS_Kernel_import.cmake new file mode 100644 index 0000000..15d8e77 --- /dev/null +++ b/examples/pico/FreeRTOS_Kernel_import.cmake @@ -0,0 +1,91 @@ +# This is a copy of /portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake + +# This can be dropped into an external project to help locate the FreeRTOS kernel +# It should be include()ed prior to project(). Alternatively this file may +# or the CMakeLists.txt in this directory may be included or added via add_subdirectory +# respectively. + +if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH)) + set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH}) + message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')") +endif () + +# first pass we look in old tree; second pass we look in new tree +foreach(SEARCH_PASS RANGE 0 1) + if (SEARCH_PASS) + # ports may be moving to submodule in the future + set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC") + set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..") + else() + set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC") + set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..") + endif() + + if(PICO_PLATFORM STREQUAL "rp2040") + set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040") + else() + if (PICO_PLATFORM STREQUAL "rp2350-riscv") + set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V") + else() + set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ") + endif() + endif() + + if (NOT FREERTOS_KERNEL_PATH) + # check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly) + get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH) + get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH) + if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH) + get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH) + endif() + if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH) + get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH) + message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake") + break() + elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel") + set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel) + message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}") + break() + endif() + endif () + + if (NOT FREERTOS_KERNEL_PATH) + foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source) + # check if FreeRTOS-Kernel exists under directory that included us + set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) + get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH) + if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt) + get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH) + message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project") + break() + endif() + endforeach() + if (FREERTOS_KERNEL_PATH) + break() + endif() + endif() + + # user must have specified + if (FREERTOS_KERNEL_PATH) + if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}") + break() + endif() + endif() +endforeach () + +if (NOT FREERTOS_KERNEL_PATH) + message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.") +endif() + +set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel") + +get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${FREERTOS_KERNEL_PATH}) + message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found") +endif() +if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt) + message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}") +endif() +set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE) + +add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL) diff --git a/examples/pico/README.md b/examples/pico/README.md new file mode 100644 index 0000000..fb49b6c --- /dev/null +++ b/examples/pico/README.md @@ -0,0 +1,50 @@ +# RP2040 PICO W +Establish a DataChannel connection between PICO and the web + +## Supported Devices +| Device |Image| +|---|---| +| [PICO W](https://www.raspberrypi.com/products/raspberry-pi-pico/) || + +## Setup Instructions +### Download Required Libraries +``` +$ git clone --recursive https://github.com/sepfy/libpeer +$ git clone --recurisve https://github.com/raspberrypi/pico-sdk +$ git clone --recursive https://github.com/FreeRTOS/FreeRTOS-Kernel +``` +### Apply a patch +Modify `libpeer/third_party/libsrtp/include/srtp.h` + +```patch +@@ -614,7 +614,7 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy); + * - [other] otherwise. + * + */ +-srtp_err_status_t srtp_remove_stream(srtp_t session, unsigned int ssrc); ++srtp_err_status_t srtp_remove_stream(srtp_t session, uint32_t ssrc); + + /** + * @brief srtp_update() updates all streams in the session. +``` + +### Configure Your Build +``` +$ export PICO_SDK_PATH=/pico-sdk +$ export FREERTOS_KERNEL_PATH=/FreeRTOS-Kernel +$ export WIFI_SSID= +$ export WIFI_PASSWORD= +``` + +### Build the Project +``` +$ cd libpeer/examples/pico +$ mkdir build +$ cd build +$ cmake .. +``` + +### Flash and Test +``` +$ sudo picotool load -f pico_peer.uf2 +``` diff --git a/examples/pico/config.h b/examples/pico/config.h new file mode 100644 index 0000000..b7f1ecd --- /dev/null +++ b/examples/pico/config.h @@ -0,0 +1,115 @@ +/* clang-format off */ + +/* Define to the full name and version of this package. */ +#define PACKAGE_VERSION "2.3.0" + +/* Define to the version of this package. */ +#define PACKAGE_STRING "pico 2.3.0" + +/* Define to enabled debug logging for all mudules. */ +/* #undef ENABLE_DEBUG_LOGGING */ + +/* Logging statments will be writen to this file. */ +/* #undef ERR_REPORTING_FILE */ + +/* Define to redirect logging to stdout. */ +/* #undef ERR_REPORTING_STDOUT */ + +/* Define this to use OpenSSL crypto. */ +/* #undef OPENSSL */ + +/* Define this to use AES-GCM. */ +/* #undef GCM */ + +/* Define if building for a CISC machine (e.g. Intel). */ +#define CPU_CISC 1 + +/* Define if building for a RISC machine (assume slow byte access). */ +/* #undef CPU_RISC */ + +/* Define to use X86 inlined assembly code */ +/* #undef HAVE_X86 */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_BYTESWAP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MACHINE_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_INT_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if you have the `sigaction' function. */ +/* #undef HAVE_SIGACTION */ + +/* Define to 1 if you have the `usleep' function. */ +#define HAVE_USLEEP 1 + +/* Define to 1 if the system has the type `uint8_t'. */ +#define HAVE_UINT8_T 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if the system has the type `uint32_t'. */ +#define HAVE_UINT32_T 1 + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if the system has the type `int32_t'. */ +#define HAVE_INT32_T 1 + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The size of `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* Define inline to what is supported by compiler */ +#define HAVE_INLINE 1 +/* #undef HAVE___INLINE */ +#ifndef HAVE_INLINE + #ifdef HAVE___INLINE + #define inline __inline + #else + #define inline + #endif +#endif diff --git a/examples/pico/lwipopts.h b/examples/pico/lwipopts.h new file mode 100644 index 0000000..af3847d --- /dev/null +++ b/examples/pico/lwipopts.h @@ -0,0 +1,61 @@ +#ifndef LWIPOPTS_H +#define LWIPOPTS_H + +#define NO_SYS 0 +#define LWIP_SOCKET 1 +#if PICO_CYW43_ARCH_POLL +#define MEM_LIBC_MALLOC 1 +#else +// MEM_LIBC_MALLOC is incompatible with non polling versions +#define MEM_LIBC_MALLOC 0 +#endif +#define MEM_ALIGNMENT 4 +#define MEM_SIZE 4000 +#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_ARP_QUEUE 10 +#define PBUF_POOL_SIZE 24 +#define LWIP_ARP 1 +#define LWIP_ETHERNET 1 +#define LWIP_ICMP 1 +#define LWIP_RAW 1 +#define TCP_WND (4 * TCP_MSS) +#define TCP_MSS 1460 +#define TCP_SND_BUF (4 * TCP_MSS) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define LWIP_NETIF_HOSTNAME 1 +#define LWIP_NETCONN 0 +#define MEM_STATS 0 +#define SYS_STATS 0 +#define MEMP_STATS 0 +#define LINK_STATS 0 +#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_DHCP 1 +#define LWIP_IPV4 1 +#define LWIP_IPV6 1 +#define LWIP_IGMP 1 +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_DNS 1 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#define DHCP_DOES_ARP_CHECK 0 +#define LWIP_DHCP_DOES_ACD_CHECK 0 + +#if !NO_SYS +#define TCPIP_THREAD_STACKSIZE 1024 +#define DEFAULT_THREAD_STACKSIZE 1024 +#define DEFAULT_RAW_RECVMBOX_SIZE 8 +#define DEFAULT_UDP_RECVMBOX_SIZE 8 +#define DEFAULT_TCP_RECVMBOX_SIZE 8 +#define TCPIP_MBOX_SIZE 8 +#define LWIP_TIMEVAL_PRIVATE 0 + +// not necessary, can be done either way +#define LWIP_TCPIP_CORE_LOCKING_INPUT 1 + +#define LWIP_SO_RCVTIMEO 1 +#endif + +#endif // LWIPOPTS_H diff --git a/examples/pico/main.c b/examples/pico/main.c new file mode 100644 index 0000000..cf966d6 --- /dev/null +++ b/examples/pico/main.c @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "FreeRTOS.h" +#include "hardware/clocks.h" +#include "pico/cyw43_arch.h" +#include "pico/multicore.h" +#include "pico/stdlib.h" +#include "task.h" + +#include "peer.h" + +#define TEST_TASK_PRIORITY (tskIDLE_PRIORITY + 1UL) + +TaskHandle_t xPcTaskHandle; +PeerConnection* g_pc; +PeerConnectionState eState = PEER_CONNECTION_CLOSED; +int gDataChannelOpened = 0; + +static void oniceconnectionstatechange(PeerConnectionState state, void* user_data) { + eState = state; + printf("state = %d\n", state); +} + +static void onmessage(char* msg, size_t len, void* userdata, uint16_t sid) { + if (strncmp(msg, "ping", 4) == 0) { + printf("Got ping, send pong\n"); + peer_connection_datachannel_send(g_pc, "pong", 4); + } +} + +void onopen(void* userdata) { + gDataChannelOpened = 1; +} + +static void onclose(void* userdata) { +} + +void peer_connection_task() { + printf("Run peer connection task on the core: %d\n", portGET_CORE_ID()); + while (1) { + peer_connection_loop(g_pc); + vTaskDelay(pdMS_TO_TICKS(1)); + } +} + +void main_task(__unused void* params) { + if (cyw43_arch_init()) { + printf("failed to initialise\n"); + vTaskDelete(NULL); + } + cyw43_arch_enable_sta_mode(); + printf("Connecting to Wi-Fi...\n"); + + while (1) { + if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 100000)) { + printf("failed to connect.\n"); + vTaskDelay(1000); + } else { + printf("Connected.\n"); + break; + } + } + + PeerConfiguration config = { + .ice_servers = { + {.urls = "stun:stun.l.google.com:19302"}}, + .datachannel = DATA_CHANNEL_STRING, + }; + + peer_init(); + g_pc = peer_connection_create(&config); + peer_connection_oniceconnectionstatechange(g_pc, oniceconnectionstatechange); + peer_connection_ondatachannel(g_pc, onmessage, onopen, onclose); + + ServiceConfiguration service_config = SERVICE_CONFIG_DEFAULT(); + service_config.client_id = "mypico"; + service_config.pc = g_pc; + peer_signaling_set_config(&service_config); + peer_signaling_join_channel(); + + xTaskCreate(peer_connection_task, "PeerConnectionTask", 4096, NULL, TEST_TASK_PRIORITY, &xPcTaskHandle); + + printf("Run main task on the core: %d\n", portGET_CORE_ID()); + printf("open https://sepfy.github.io/webrtc?deviceId=mypico\n"); + while (true) { + peer_signaling_loop(); + vTaskDelay(pdMS_TO_TICKS(10)); + } + + cyw43_arch_deinit(); +} + +void vLaunch(void) { + TaskHandle_t task; + xTaskCreate(main_task, "TestMainThread", 4096, NULL, TEST_TASK_PRIORITY, &task); + vTaskCoreAffinitySet(task, 1); + vTaskStartScheduler(); +} + +int main(void) { + stdio_init_all(); + // set_sys_clock_khz(200000, true); + vLaunch(); + return 0; +} diff --git a/examples/pico/mbedtls_config.h b/examples/pico/mbedtls_config.h new file mode 100644 index 0000000..35663c6 --- /dev/null +++ b/examples/pico/mbedtls_config.h @@ -0,0 +1,87 @@ +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* Workaround for some mbedtls source files using INT_MAX without including limits.h */ +#include + +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_ENTROPY_HARDWARE_ALT + +#define MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_HAVE_TIME + +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_SSL_SERVER_NAME_INDICATION +#define MBEDTLS_AES_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA224_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_SRV_C +#define MBEDTLS_SSL_TLS_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_USE_C +#define MBEDTLS_AES_FEWER_TABLES + +/* TLS 1.2 */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +#define MBEDTLS_DHM_C +#define MBEDTLS_GCM_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ASN1_WRITE_C + +// The following is needed to parse a certificate +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_BASE64_C + +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define MBEDTLS_SSL_DTLS_SRTP +#define MBEDTLS_SSL_EXPORT_KEYS + +#define MBEDTLS_DEBUG_C +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define MBEDTLS_PEM_WRITE_C +#define MBEDTLS_X509_CRT_WRITE_C +#define MBEDTLS_SSL_PROTO_DTLS +#define MBEDTLS_X509_CREATE_C +#define MBEDTLS_GENPRIME +#define MBEDTLS_SSL_COOKIE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_TIMING_C +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#define __unix__ + +#endif // MBEDTLS_CONFIG_H diff --git a/examples/pico/netinet/in.h b/examples/pico/netinet/in.h new file mode 100644 index 0000000..b994c1a --- /dev/null +++ b/examples/pico/netinet/in.h @@ -0,0 +1,5 @@ +#ifndef NETINET_INET_H +#define NETINET_INET_H + +#include "lwip/sockets.h" +#endif // NETINET_INET_H diff --git a/src/address.c b/src/address.c index 34db93d..1618ede 100644 --- a/src/address.c +++ b/src/address.c @@ -1,10 +1,6 @@ -#include -#include -#include #include #include #include -#include #include "address.h" #include "utils.h" diff --git a/src/address.h b/src/address.h index 8dbbbf8..6f8eb78 100644 --- a/src/address.h +++ b/src/address.h @@ -1,9 +1,14 @@ #ifndef ADDRESS_H_ #define ADDRESS_H_ -#include -#include +#include "config.h" +#if CONFIG_USE_LWIP +#include +#else +#include #include +#endif +#include #define ADDRSTRLEN INET6_ADDRSTRLEN diff --git a/src/agent.c b/src/agent.c index 5f1745a..c0942ac 100644 --- a/src/agent.c +++ b/src/agent.c @@ -1,12 +1,9 @@ -#include #include #include #include #include -#include #include -#include #include "agent.h" #include "base64.h" #include "ice.h" @@ -16,7 +13,7 @@ #include "utils.h" #define AGENT_POLL_TIMEOUT 1 -#define AGENT_CONNCHECK_MAX 300 +#define AGENT_CONNCHECK_MAX 1000 #define AGENT_CONNCHECK_PERIOD 100 #define AGENT_STUN_RECV_MAXTIMES 1000 @@ -61,18 +58,24 @@ void agent_destroy(Agent* agent) { static int agent_socket_recv(Agent* agent, Address* addr, uint8_t* buf, int len) { int ret = -1; int i = 0; - int maxfd = 0; + int maxfd = -1; fd_set rfds; struct timeval tv; + int addr_type[] = { AF_INET, +#if CONFIG_IPV6 + AF_INET6, +#endif + }; + tv.tv_sec = 0; tv.tv_usec = AGENT_POLL_TIMEOUT * 1000; FD_ZERO(&rfds); - for (i = 0; i < 2; i++) { + for (i = 0; i < sizeof(addr_type) / sizeof(addr_type[0]); i++) { if (agent->udp_sockets[i].fd > maxfd) { maxfd = agent->udp_sockets[i].fd; } - if (agent->udp_sockets[i].fd > 0) { + if (agent->udp_sockets[i].fd >= 0) { FD_SET(agent->udp_sockets[i].fd, &rfds); } } diff --git a/src/agent.h b/src/agent.h index 027303a..86da0e5 100644 --- a/src/agent.h +++ b/src/agent.h @@ -1,15 +1,11 @@ #ifndef AGENT_H_ #define AGENT_H_ -#include #include #include #include -#include #include -#include - #include "base64.h" #include "ice.h" #include "socket.h" diff --git a/src/config.h b/src/config.h index 7b7cdf9..83de727 100644 --- a/src/config.h +++ b/src/config.h @@ -3,17 +3,39 @@ #define SCTP_MTU (1200) #define CONFIG_MTU (1300) -#define RSA_KEY_LENGTH 1024 -#ifdef ESP32 -#define VIDEO_RB_DATA_LENGTH (CONFIG_MTU * 64) -#define AUDIO_RB_DATA_LENGTH (CONFIG_MTU * 64) -#define DATA_RB_DATA_LENGTH (SCTP_MTU * 128) +#ifndef CONFIG_USE_LWIP +#define CONFIG_USE_LWIP 0 +#endif + +#ifndef CONFIG_MBEDTLS_DEBUG +#define CONFIG_MBEDTLS_DEBUG 0 +#endif + +#ifndef CONFIG_MBEDTLS_2_X +#define CONFIG_MBEDTLS_2_X 0 +#endif + +#if CONFIG_MBEDTLS_2_X +#define RSA_KEY_LENGTH 512 #else -#define HAVE_USRSCTP -#define VIDEO_RB_DATA_LENGTH (CONFIG_MTU * 256) -#define AUDIO_RB_DATA_LENGTH (CONFIG_MTU * 256) -#define DATA_RB_DATA_LENGTH (SCTP_MTU * 128) +#define RSA_KEY_LENGTH 1024 +#endif + +#ifndef CONFIG_USE_USRSCTP +#define CONFIG_USE_USRSCTP 1 +#endif + +#ifndef CONFIG_VIDEO_BUFFER_SIZE +#define CONFIG_VIDEO_BUFFER_SIZE (CONFIG_MTU * 256) +#endif + +#ifndef CONFIG_AUDIO_BUFFER_SIZE +#define CONFIG_AUDIO_BUFFER_SIZE (CONFIG_MTU * 256) +#endif + +#ifndef CONFIG_DATA_BUFFER_SIZE +#define CONFIG_DATA_BUFFER_SIZE (SCTP_MTU * 128) #endif #define AUDIO_LATENCY 20 // ms diff --git a/src/dtls_srtp.c b/src/dtls_srtp.c index 49f012d..65b5bd1 100644 --- a/src/dtls_srtp.c +++ b/src/dtls_srtp.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,7 +6,12 @@ #include "address.h" #include "config.h" #include "dtls_srtp.h" +#if CONFIG_MBEDTLS_DEBUG +#include "mbedtls/debug.h" +#endif +#include "mbedtls/sha256.h" #include "mbedtls/ssl.h" +#include "ports.h" #include "socket.h" #include "utils.h" @@ -29,7 +33,7 @@ int dtls_srtp_udp_recv(void* ctx, uint8_t* buf, size_t len) { int ret; while ((ret = udp_socket_recvfrom(udp_socket, &udp_socket->bind_addr, buf, len)) <= 0) { - usleep(1000); + ports_sleep_ms(1); } LOGD("dtls_srtp_udp_recv (%d)", ret); @@ -68,7 +72,11 @@ static int dtls_srtp_selfsign_cert(DtlsSrtp* dtls_srtp) { mbedtls_x509write_cert crt; unsigned char* cert_buf = NULL; +#if CONFIG_MBEDTLS_2_X + mbedtls_mpi serial; +#else const char* serial = "peer"; +#endif const char* pers = "dtls_srtp"; cert_buf = (unsigned char*)malloc(RSA_KEY_LENGTH * 2); @@ -99,14 +107,23 @@ static int dtls_srtp_selfsign_cert(DtlsSrtp* dtls_srtp) { mbedtls_x509write_crt_set_issuer_name(&crt, "CN=dtls_srtp"); +#if CONFIG_MBEDTLS_2_X + mbedtls_mpi_init(&serial); + mbedtls_mpi_fill_random(&serial, 16, mbedtls_ctr_drbg_random, &dtls_srtp->ctr_drbg); + ret = mbedtls_x509write_crt_set_serial(&crt, &serial); + if (ret < 0) { + LOGE("mbedtls_x509write_crt_set_serial failed -0x%.4x", (unsigned int)-ret); + } +#else mbedtls_x509write_crt_set_serial_raw(&crt, (unsigned char*)serial, strlen(serial)); +#endif mbedtls_x509write_crt_set_validity(&crt, "20180101000000", "20280101000000"); ret = mbedtls_x509write_crt_pem(&crt, cert_buf, 2 * RSA_KEY_LENGTH, mbedtls_ctr_drbg_random, &dtls_srtp->ctr_drbg); if (ret < 0) { - LOGE("mbedtls_x509write_crt_pem failed"); + LOGE("mbedtls_x509write_crt_pem failed -0x%.4x", (unsigned int)-ret); } mbedtls_x509_crt_parse(&dtls_srtp->cert, cert_buf, 2 * RSA_KEY_LENGTH); @@ -118,6 +135,12 @@ static int dtls_srtp_selfsign_cert(DtlsSrtp* dtls_srtp) { return ret; } +#if CONFIG_MBEDTLS_DEBUG +static void dtls_srtp_debug(void* ctx, int level, const char* file, int line, const char* str) { + LOGD("%s:%04d: %s", file, line, str); +} +#endif + int dtls_srtp_init(DtlsSrtp* dtls_srtp, DtlsSrtpRole role, void* user_data) { static const mbedtls_ssl_srtp_profile default_profiles[] = { MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80, @@ -139,7 +162,10 @@ int dtls_srtp_init(DtlsSrtp* dtls_srtp, DtlsSrtpRole role, void* user_data) { mbedtls_pk_init(&dtls_srtp->pkey); mbedtls_entropy_init(&dtls_srtp->entropy); mbedtls_ctr_drbg_init(&dtls_srtp->ctr_drbg); - +#if CONFIG_MBEDTLS_DEBUG + mbedtls_debug_set_threshold(3); + mbedtls_ssl_conf_dbg(&dtls_srtp->conf, dtls_srtp_debug, NULL); +#endif dtls_srtp_selfsign_cert(dtls_srtp); mbedtls_ssl_conf_verify(&dtls_srtp->conf, dtls_srtp_cert_verify, NULL); @@ -207,25 +233,15 @@ void dtls_srtp_deinit(DtlsSrtp* dtls_srtp) { } } -static void dtls_srtp_key_derivation(void* context, mbedtls_ssl_key_export_type secret_type, const unsigned char* secret, size_t secret_len, const unsigned char client_random[32], const unsigned char server_random[32], mbedtls_tls_prf_types tls_prf_type) { - DtlsSrtp* dtls_srtp = (DtlsSrtp*)context; - +static int dtls_srtp_key_derivation(DtlsSrtp* dtls_srtp, const unsigned char* master_secret, const unsigned char* randbytes, mbedtls_tls_prf_types tls_prf_type) { int ret; - const char* dtls_srtp_label = "EXTRACTOR-dtls_srtp"; - - unsigned char randbytes[64]; - uint8_t key_material[DTLS_SRTP_KEY_MATERIAL_LENGTH]; - - memcpy(randbytes, client_random, 32); - memcpy(randbytes + 32, server_random, 32); - // Export keying material - if ((ret = mbedtls_ssl_tls_prf(tls_prf_type, secret, secret_len, dtls_srtp_label, + if ((ret = mbedtls_ssl_tls_prf(tls_prf_type, master_secret, sizeof(master_secret), dtls_srtp_label, randbytes, sizeof(randbytes), key_material, sizeof(key_material))) != 0) { LOGE("mbedtls_ssl_tls_prf failed(%d)", ret); - return; + return ret; } #if 0 @@ -266,7 +282,7 @@ static void dtls_srtp_key_derivation(void* context, mbedtls_ssl_key_export_type if (srtp_create(&dtls_srtp->srtp_in, &dtls_srtp->remote_policy) != srtp_err_status_ok) { LOGD("Error creating inbound SRTP session for component"); - return; + return -1; } LOGI("Created inbound SRTP session"); @@ -286,11 +302,48 @@ static void dtls_srtp_key_derivation(void* context, mbedtls_ssl_key_export_type if (srtp_create(&dtls_srtp->srtp_out, &dtls_srtp->local_policy) != srtp_err_status_ok) { LOGE("Error creating outbound SRTP session"); - return; + return -1; } LOGI("Created outbound SRTP session"); dtls_srtp->state = DTLS_SRTP_STATE_CONNECTED; + return 0; +} + +#if CONFIG_MBEDTLS_2_X +static int dtls_srtp_key_derivation_cb(void* context, + const unsigned char* ms, + const unsigned char* kb, + size_t maclen, + size_t keylen, + size_t ivlen, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type) { +#else +static void dtls_srtp_key_derivation_cb(void* context, + mbedtls_ssl_key_export_type secret_type, + const unsigned char* secret, + size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type) { +#endif + DtlsSrtp* dtls_srtp = (DtlsSrtp*)context; + + unsigned char master_secret[48]; + unsigned char randbytes[64]; + + memcpy(randbytes, client_random, 32); + memcpy(randbytes + 32, server_random, 32); + +#if CONFIG_MBEDTLS_2_X + memcpy(master_secret, ms, sizeof(master_secret)); + return dtls_srtp_key_derivation(dtls_srtp, master_secret, randbytes, tls_prf_type); +#else + memcpy(master_secret, secret, sizeof(master_secret)); + dtls_srtp_key_derivation(dtls_srtp, master_secret, randbytes, tls_prf_type); +#endif } static int dtls_srtp_do_handshake(DtlsSrtp* dtls_srtp) { @@ -300,7 +353,11 @@ static int dtls_srtp_do_handshake(DtlsSrtp* dtls_srtp) { mbedtls_ssl_set_timer_cb(&dtls_srtp->ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); - mbedtls_ssl_set_export_keys_cb(&dtls_srtp->ssl, dtls_srtp_key_derivation, dtls_srtp); +#if CONFIG_MBEDTLS_2_X + mbedtls_ssl_conf_export_keys_ext_cb(&dtls_srtp->conf, dtls_srtp_key_derivation_cb, dtls_srtp); +#else + mbedtls_ssl_set_export_keys_cb(&dtls_srtp->ssl, dtls_srtp_key_derivation_cb, dtls_srtp); +#endif mbedtls_ssl_set_bio(&dtls_srtp->ssl, dtls_srtp, dtls_srtp->udp_send, dtls_srtp->udp_recv, NULL); @@ -424,9 +481,9 @@ int dtls_srtp_probe(uint8_t* buf) { if (buf == NULL) return 0; - // LOGD("DTLS content type: %d, version: %d, epoch: %d, sequence: %d, length: %d (%.4x)", header->content_type, header->version, header->epoch, ntohs(header->seqnum_hi), ntohs(header->length), header->length); - - return ((*buf >= 20) && (*buf <= 64)); + LOGD("DTLS content type: %d", buf[0]); + // only handle application data + return (buf[0] == 0x17); } void dtls_srtp_decrypt_rtp_packet(DtlsSrtp* dtls_srtp, uint8_t* packet, int* bytes) { diff --git a/src/ice.c b/src/ice.c index a54ea57..4e33c46 100644 --- a/src/ice.c +++ b/src/ice.c @@ -1,10 +1,8 @@ -#include #include #include #include #include #include -#include #include #include "ice.h" diff --git a/src/mdns.c b/src/mdns.c index fd019a2..090ea88 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -1,11 +1,8 @@ -#include #include -#include #include #include #include #include -#include #include #include "address.h" #include "socket.h" diff --git a/src/peer_connection.c b/src/peer_connection.c index 808aaaa..1c1289c 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -172,13 +172,17 @@ PeerConnection* peer_connection_create(PeerConfiguration* config) { memset(&pc->sctp, 0, sizeof(pc->sctp)); if (pc->config.datachannel) { - LOGI("Datachannel allocates heap size: %d", DATA_RB_DATA_LENGTH); - pc->data_rb = buffer_new(DATA_RB_DATA_LENGTH); +#if (CONFIG_DATA_BUFFER_SIZE) > 0 + LOGI("Datachannel allocates heap size: %d", CONFIG_DATA_BUFFER_SIZE); + pc->data_rb = buffer_new(CONFIG_DATA_BUFFER_SIZE); +#endif } if (pc->config.audio_codec) { - LOGI("Audio allocates heap size: %d", AUDIO_RB_DATA_LENGTH); - pc->audio_rb = buffer_new(AUDIO_RB_DATA_LENGTH); +#if (CONFIG_AUDIO_BUFFER_SIZE) > 0 + LOGI("Audio allocates heap size: %d", CONFIG_AUDIO_BUFFER_SIZE); + pc->audio_rb = buffer_new(CONFIG_AUDIO_BUFFER_SIZE); +#endif rtp_encoder_init(&pc->artp_encoder, pc->config.audio_codec, peer_connection_outgoing_rtp_packet, (void*)pc); @@ -188,9 +192,10 @@ PeerConnection* peer_connection_create(PeerConfiguration* config) { } if (pc->config.video_codec) { - LOGI("Video allocates heap size: %d", VIDEO_RB_DATA_LENGTH); - pc->video_rb = buffer_new(VIDEO_RB_DATA_LENGTH); - +#if (CONFIG_VIDEO_BUFFER_SIZE) > 0 + LOGI("Video allocates heap size: %d", CONFIG_VIDEO_BUFFER_SIZE); + pc->video_rb = buffer_new(CONFIG_VIDEO_BUFFER_SIZE); +#endif rtp_encoder_init(&pc->vrtp_encoder, pc->config.video_codec, peer_connection_outgoing_rtp_packet, (void*)pc); @@ -222,8 +227,11 @@ int peer_connection_send_audio(PeerConnection* pc, const uint8_t* buf, size_t le // LOGE("dtls_srtp not connected"); return -1; } - +#if (CONFIG_AUDIO_BUFFER_SIZE) > 0 return buffer_push_tail(pc->audio_rb, buf, len); +#else + return rtp_encoder_encode(&pc->artp_encoder, data, bytes); +#endif } int peer_connection_send_video(PeerConnection* pc, const uint8_t* buf, size_t len) { @@ -231,8 +239,11 @@ int peer_connection_send_video(PeerConnection* pc, const uint8_t* buf, size_t le // LOGE("dtls_srtp not connected"); return -1; } - +#if (CONFIG_VIDEO_BUFFER_SIZE) > 0 return buffer_push_tail(pc->video_rb, buf, len); +#else + return rtp_encoder_encode(&pc->vrtp_encoder, data, bytes); +#endif } int peer_connection_datachannel_send(PeerConnection* pc, char* message, size_t len) { @@ -245,10 +256,14 @@ int peer_connection_datachannel_send_sid(PeerConnection* pc, char* message, size return -1; } +#if (CONFIG_DATA_BUFFER_SIZE) > 0 + return buffer_push_tail(pc->data_rb, (uint8_t*)message, len); +#else if (pc->config.datachannel == DATA_CHANNEL_STRING) return sctp_outgoing_data(&pc->sctp, message, len, PPID_STRING, sid); else return sctp_outgoing_data(&pc->sctp, message, len, PPID_BINARY, sid); +#endif } static char* peer_connection_dtls_role_setup_value(DtlsSrtpRole d) { @@ -378,18 +393,23 @@ int peer_connection_loop(PeerConnection* pc) { break; case PEER_CONNECTION_COMPLETED: +#if (CONFIG_VIDEO_BUFFER_SIZE) > 0 data = buffer_peak_head(pc->video_rb, &bytes); if (data) { rtp_encoder_encode(&pc->vrtp_encoder, data, bytes); buffer_pop_head(pc->video_rb); } +#endif +#if (CONFIG_AUDIO_BUFFER_SIZE) > 0 data = buffer_peak_head(pc->audio_rb, &bytes); if (data) { rtp_encoder_encode(&pc->artp_encoder, data, bytes); buffer_pop_head(pc->audio_rb); } +#endif +#if (CONFIG_DATA_BUFFER_SIZE) > 0 data = buffer_peak_head(pc->data_rb, &bytes); if (data) { if (pc->config.datachannel == DATA_CHANNEL_STRING) @@ -398,6 +418,7 @@ int peer_connection_loop(PeerConnection* pc) { sctp_outgoing_data(&pc->sctp, (char*)data, bytes, PPID_BINARY, 0); buffer_pop_head(pc->data_rb); } +#endif if ((pc->agent_ret = agent_recv(&pc->agent, pc->agent_buf, sizeof(pc->agent_buf))) > 0) { LOGD("agent_recv %d", pc->agent_ret); diff --git a/src/peer_signaling.c b/src/peer_signaling.c index 4813e3e..5e0176d 100644 --- a/src/peer_signaling.c +++ b/src/peer_signaling.c @@ -19,7 +19,7 @@ #define CONNACK_RECV_TIMEOUT_MS 1000 #ifndef BUF_SIZE -#define BUF_SIZE 4096 +#define BUF_SIZE 2048 #endif #define TOPIC_SIZE 128 diff --git a/src/ports.c b/src/ports.c index 71f87ca..2346f60 100644 --- a/src/ports.c +++ b/src/ports.c @@ -1,16 +1,20 @@ -#include -#include -#include +#include #include #include #include #include -#ifdef ESP32 -#include +#include "config.h" + +#if CONFIG_USE_LWIP +#include "lwip/ip_addr.h" +#include "lwip/netdb.h" +#include "lwip/netif.h" +#include "lwip/sys.h" #else -#include #include +#include +#include #include #endif @@ -20,28 +24,32 @@ int ports_get_host_addr(Address* addr, const char* iface_prefix) { int ret = 0; -#ifdef ESP32 - esp_netif_t* netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); - esp_netif_ip_info_t ip_info; - esp_ip6_addr_t ip6_info; - - switch (addr->family) { - case AF_INET6: - if (esp_netif_get_ip6_global(netif, &ip6_info) == ESP_OK) { - memcpy(&addr->sin6.sin6_addr, &ip6_info.addr, 16); - ret = 1; - } else if (esp_netif_get_ip6_linklocal(netif, &ip6_info) == ESP_OK) { - memcpy(&addr->sin6.sin6_addr, &ip6_info.addr, 16); - ret = 1; - } - break; - case AF_INET: - default: - if (esp_netif_get_ip_info(netif, &ip_info) == ESP_OK) { - memcpy(&addr->sin.sin_addr, &ip_info.ip.addr, 4); - ret = 1; - } +#if CONFIG_USE_LWIP + struct netif* netif; + int i; + for (netif = netif_list; netif != NULL; netif = netif->next) { + switch (addr->family) { + case AF_INET6: + for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + if (!ip6_addr_isany(netif_ip6_addr(netif, i))) { + memcpy(&addr->sin6.sin6_addr, netif_ip6_addr(netif, i), 16); + ret = 1; + break; + } + } + break; + case AF_INET: + default: + if (!ip_addr_isany(&netif->ip_addr)) { + memcpy(&addr->sin.sin_addr, &netif->ip_addr.u_addr.ip4, 4); + ret = 1; + } + break; + } + + if (ret) { break; + } } #else @@ -139,3 +147,11 @@ uint32_t ports_get_epoch_time() { gettimeofday(&tv, NULL); return (uint32_t)tv.tv_sec * 1000 + tv.tv_usec / 1000; } + +void ports_sleep_ms(int ms) { +#if CONFIG_USE_LWIP + sys_msleep(ms); +#else + usleep(ms * 1000); +#endif +} diff --git a/src/ports.h b/src/ports.h index 9ca5d60..3c2c84d 100644 --- a/src/ports.h +++ b/src/ports.h @@ -12,4 +12,6 @@ int ports_get_host_addr(Address* addr, const char* iface_prefix); uint32_t ports_get_epoch_time(); +void ports_sleep_ms(int ms); + #endif // PORTS_H_ diff --git a/src/rtcp.c b/src/rtcp.c index 49fafe4..117b58c 100644 --- a/src/rtcp.c +++ b/src/rtcp.c @@ -1,7 +1,7 @@ -#include #include #include +#include "address.h" #include "rtcp.h" #include "rtp.h" diff --git a/src/rtcp.h b/src/rtcp.h index d3bbbb7..f888d05 100644 --- a/src/rtcp.h +++ b/src/rtcp.h @@ -1,8 +1,10 @@ #ifndef RTCP_H_ #define RTCP_H_ -#include -#ifdef __APPLE__ +#ifdef __BYTE_ORDER +#define __BIG_ENDIAN 4321 +#define __LITTLE_ENDIAN 1234 +#elif __APPLE__ #include #else #include diff --git a/src/rtp.c b/src/rtp.c index b1edb1b..3898b84 100644 --- a/src/rtp.c +++ b/src/rtp.c @@ -1,7 +1,7 @@ -#include #include #include +#include "address.h" #include "peer_connection.h" #include "rtp.h" #include "utils.h" diff --git a/src/rtp.h b/src/rtp.h index 12ab068..2df6657 100644 --- a/src/rtp.h +++ b/src/rtp.h @@ -2,7 +2,11 @@ #define RTP_H_ #include -#ifdef __APPLE__ + +#ifdef __BYTE_ORDER +#define __BIG_ENDIAN 4321 +#define __LITTLE_ENDIAN 1234 +#elif __APPLE__ #include #else #include @@ -11,12 +15,6 @@ #include "config.h" #include "peer_connection.h" -#ifdef ESP32 -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif - typedef enum RtpPayloadType { PT_PCMU = 0, diff --git a/src/sctp.c b/src/sctp.c index c684f2d..301b4e5 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -1,9 +1,8 @@ -#include #include #include #include "sctp.h" -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP #include #endif @@ -104,7 +103,7 @@ static int sctp_outgoing_data_cb(void* userdata, void* buf, size_t len, uint8_t } int sctp_outgoing_data(Sctp* sctp, char* buf, size_t len, SctpDataPpid ppid, uint16_t sid) { -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP int res; struct sctp_sendv_spa spa = {0}; @@ -223,7 +222,7 @@ void sctp_incoming_data(Sctp* sctp, char* buf, size_t len) { if (!sctp) return; -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP sctp_handle_sctp_packet(sctp, buf, len); usrsctp_conninput(sctp, buf, len, 0); #else @@ -389,7 +388,7 @@ void sctp_incoming_data(Sctp* sctp, char* buf, size_t len) { } static int sctp_handle_incoming_data(Sctp* sctp, char* data, size_t len, uint32_t ppid, uint16_t sid, int flags) { -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP switch (ppid) { case DATA_CHANNEL_PPID_CONTROL: break; @@ -412,7 +411,7 @@ static int sctp_handle_incoming_data(Sctp* sctp, char* data, size_t len, uint32_ return 0; } -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP static void sctp_process_notification(Sctp* sctp, union sctp_notification* notification, size_t len) { if (notification->sn_header.sn_length != (uint32_t)len) { @@ -470,7 +469,7 @@ int sctp_create_socket(Sctp* sctp, DtlsSrtp* dtls_srtp) { sctp->local_port = 5000; sctp->remote_port = 5000; sctp->tsn = 1234; -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP int ret = -1; usrsctp_init(0, sctp_outgoing_data_cb, NULL); usrsctp_sysctl_set_sctp_ecn_enable(0); @@ -579,7 +578,7 @@ int sctp_is_connected(Sctp* sctp) { } void sctp_destroy(Sctp* sctp) { -#ifdef HAVE_USRSCTP +#if CONFIG_USE_USRSCTP if (sctp) { if (sctp->sock) { usrsctp_shutdown(sctp->sock, SHUT_RDWR); diff --git a/src/sctp.h b/src/sctp.h index 6489603..5956bba 100644 --- a/src/sctp.h +++ b/src/sctp.h @@ -6,7 +6,7 @@ #include "dtls_srtp.h" #include "utils.h" -#ifndef HAVE_USRSCTP +#if !CONFIG_USE_USRSCTP typedef enum DecpMsgType { diff --git a/src/socket.c b/src/socket.c index 2d5efaa..6f7d8ef 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1,13 +1,5 @@ -#include #include -#include -#include -#include -#include #include -#include -#include -#include #include #include "socket.h" @@ -70,8 +62,7 @@ int udp_socket_open(UdpSocket* udp_socket, int family, int port) { do { if ((ret = setsockopt(udp_socket->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) < 0) { - LOGE("reuse failed"); - break; + LOGW("reuse failed. ignore"); } if ((ret = bind(udp_socket->fd, sa, sock_len)) < 0) { diff --git a/src/ssl_transport.c b/src/ssl_transport.c index 1db239c..909f9e9 100644 --- a/src/ssl_transport.c +++ b/src/ssl_transport.c @@ -29,10 +29,14 @@ static int ssl_transport_mbedtls_recv_timeout(void* ctx, unsigned char* buf, siz if (ret < 0) { return -1; } else if (ret == 0) { - return MBEDTLS_ERR_SSL_TIMEOUT; + // timeout + } else { + if (FD_ISSET(((TcpSocket*)ctx)->fd, &read_fds)) { + ret = tcp_socket_recv((TcpSocket*)ctx, buf, len); + } } - return tcp_socket_recv((TcpSocket*)ctx, buf, len); + return ret; } static int ssl_transport_mbedlts_send(void* ctx, const uint8_t* buf, size_t len) { @@ -135,7 +139,7 @@ int32_t ssl_transport_send(NetworkContext_t* net_ctx, const void* buf, size_t le while ((ret = mbedtls_ssl_write(&net_ctx->ssl, buf, len)) <= 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - LOGE(""); + LOGE("ssl write error: -0x%x", (unsigned int)-ret); } } diff --git a/src/utils.c b/src/utils.c index f4060b1..020b8ac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,14 +1,10 @@ -#include -#include +#include "utils.h" +#include #include #include -#include -#include - -#include #include +#include #include "mbedtls/md.h" -#include "utils.h" void utils_random_string(char* s, const int len) { int i;