summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP
diff options
context:
space:
mode:
authorlundinc <lundinc@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-08-12 19:11:51 +0000
committerlundinc <lundinc@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>2020-08-12 19:11:51 +0000
commit42255af1e27a3157d541f0812eaca447c569ca49 (patch)
tree5c8702c2f0dc1cb9be1a4d5ff285897d96b97dd2 /FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP
parentf5221dff43de249079c2da081723cb7a456f981f (diff)
downloadfreertos-master.tar.gz
commit 70dcbe4527a45ab4fea6d58c016e7d3032f31e8cHEADmaster
Author: Ming Yue <mingyue86010@gmail.com> Date: Tue Aug 11 17:06:59 2020 -0700 Remove unused wolfSSL files. (#197) * Remove unused wolfSSL files. * Add back some removed ciphers. * Update VS project file. commit 0e0edd96e8236b2ea4a6e6018812807be828c77f Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Tue Aug 11 10:50:30 2020 -0700 Use new QEMU test project to improve stream/message buffer tests (#168) * Add Eclipse/GCC project that targets the LM3S8962 QEMU model. * Get the Cortex-M QEMU project working. * Continue working on making stream buffer demo more robust and QEMU project. * Rename directory CORTEX_LM3S8986_QEMU to CORTEX_LM3S6965_QEMU. Work on making the Stream Buffer tests more robust. Check in before adding in the trace recorder. * Rename CORTEX_LM3S6969_QEMU to CORTEX_LM3S6969_GCC_QEMU. * Make the StreamBufferDemo.c common demo file (test file) more robust to other test tasks running at an equally high priority. * Work in progress checkin only - comments in main.c are incorrect. * Correct comments at the top of FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/main.c Make the message buffer tests more robust in the case the a message buffer becomes full when prvSenderTask() has a higher priority than the reader task. * Disable trace recorder in the LM3S6965 QEMU demo. * I'm dropping FreeRTOS-Kernel reference update, since this seems to break the CMBC CI. Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 157a7fc39f19583ac8481e93fa3e1c91b1e1860c Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Sun Aug 9 22:21:44 2020 -0700 Use chacheable RAM in IAR project for MPU_M7_NUCLEO_H743ZI2 project (#193) This change updates the IAR project for Nucleo H743ZI2 to use the cacheable DTC RAM and enables L1 cache. In order to ensure the correct functioning of cache, the project sets configTEX_S_C_B_SRAM in FreeRTOSConfig.h to not mark the RAM as shareable. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit f3e43556f90f01b82918ad533b0c616489331919 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Sun Aug 9 16:23:53 2020 -0700 Add MPU demo projects for NUCLEO-H743ZI2 board (#155) * Add MPU demo projects for NUCLEO-H743ZI2 board It contains projects for Keil uVision, STM32CubeIDE and IAR EW. This demo shows the use of newly added support for 16 MPU regions. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> * Delete not needed CMSIS files Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit 94aa31c3cbae7c929b8a412768b74631f4a6b461 Author: TakayukiMatsuo <62984531+TakayukiMatsuo@users.noreply.github.com> Date: Sat Aug 8 07:58:14 2020 +0900 Update wolfSSL to the latest version(v.4.4.0) (#186) * deleted old version wolfSSL before updating * updated wolfSSL to the latest version(v4.4.0) * updated wolfSSL to the latest version(v4.4.0) * added macros for timing resistance Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Co-authored-by: Ming Yue <mingyue86010@gmail.com> commit 68518f5866aac58793c737d9a46dd07a6a816aaf Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Fri Aug 7 14:59:24 2020 -0700 Removed a 16MByte flash image file that was checked in by mistake (several years ago). (#173) Remove the copies of lwIP that are no longer reference from demo projects. Co-authored-by: Carl Lundin <53273776+lundinc2@users.noreply.github.com> commit d4bf09480a2c77b1a25cce35b32293be61ab586f Author: m17336 <45935231+m17336@users.noreply.github.com> Date: Thu Aug 6 22:37:08 2020 +0300 Update previous AVR ATmega0 and AVR Dx projecs + addition of equivalent projects in MPLAB.X and IAR (#180) * Updated indentation in AVR_ATMega4809_Atmel_Studio and AVR_Dx_Atmel_Studio projects, plus small fixes in their readme files. * Added AVR_ATMega4809_IAR, AVR_ATMega4809_MPLAB.X, AVR_Dx_IAR and AVR_Dx_MPLAB.X demo projects. * Removed build artefacts and added .gitignore files in AVR_ATMega4809_MPLAB.X and AVR_Dx_MPLAB.X projects. Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit f32a0647c8228ddd066f5d69a85b2e49086e4c95 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Aug 3 16:45:10 2020 -0700 Remove CBMC patch which is not used anymore (#187) * Delete 0002-Change-FreeRTOS_IP_Private.h-union-to-struct.patch * Delete 0002-Change-FreeRTOS_IP_Private.h-union-to-struct.patch commit 08af68ef9049279b265c3d00e9c48fb9594129a8 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Sat Aug 1 16:38:23 2020 -0700 Remove dependency of CBMC on Patches (#181) * Changes to DHCP * CBMC DNS changes * Changes for TCP_IP * Changes to TCP_WIN * Define away static to nothing * Remove patches * Changes after Mark's comments v1 * Update MakefileCommon.json * Correction! commit a7fec906a415363338449447daf10d7517b78848 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 17:39:36 2020 -0700 Misc changes (#183) commit 07cf5e07e4a05d6775a2f9e753269f43f82cf6ba Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 16:15:38 2020 -0700 MISRA compliance changes for FreeRTOS+TCP headers (#165) * misra changes * Update FreeRTOS_IP_Private.h * Update FreeRTOS_IP_Private.h commit e903ac0fed7ce59916899e404f3e5ae5b08d1478 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 16:03:14 2020 -0700 UPD MISRA changes (#164) Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 97551bf44e7dc7dc1e4484a8fd30f699255e8569 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 15:52:00 2020 -0700 MISRA changes in FreeRTOS_TCP_WIN.c (#162) commit f2611cc5e5999c4c87e040a8c2d2e6b5e77a16a6 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 15:38:37 2020 -0700 MISRA compliance changes in FreeRTOS_Sockets{.c/.h} (#161) * MISRA changes Sockets * add other changes * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * Update FreeRTOSIPConfig.h * correction * Add 'U' * Update FreeRTOS_Sockets.h * Update FreeRTOS_Sockets.h * Update FreeRTOS_Sockets.c * Update FreeRTOS_Sockets.h * Update after Gary's comments * Correction reverted commit ae4d4d38d9b2685bae159b4c87619cdb157c0bf7 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 29 13:56:57 2020 -0700 MISRA compliance changes for FreeRTOS_TCP_IP.c (#160) * MISRA tcp-ip changes * Changes after Hein's comments on original PR * Update FreeRTOS_TCP_IP.c Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit a457f43c66eb0f4be9d8f8678c0e3fb8d7ebd57b Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Tue Jul 28 13:01:38 2020 -0700 Add missing error state assignment. (#166) commit 915af50524e15a78ceb6c62b3d33f6562621ee46 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Mon Jul 27 17:30:53 2020 -0700 Add Atmel Studio projects for ATMega4809 and AVR128DA48 (#159) * Added explicit cast to allow roll over and avoid integer promotion during cycles counters comparison in recmutex.c. * Fixed type mismatch between declaration and definition of function xAreSemaphoreTasksStillRunning( void ). * Added Atmel Studio demo projects for ATMega4809 and AVR128DA48. * Per https://www.freertos.org/upgrading-to-FreeRTOS-V8.html, I'm updating portBASE_TYPE to BaseType_t. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Update register test for ATmega4809 - to cover r28, r29, r31. - call public API taskYIELD() instead of portYIELD(). * Update ATmega4809 readme.md to include info for serial port setup, and minor wording fix. Co-authored-by: Alexandru Niculae - M17336 <alexandru.niculae@microchip.com> commit 4a7a48790d64127f85cc763721b575c51c452833 Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Jul 23 10:22:33 2020 -0700 Add Uncrustify file used for Kernel. (#163) commit e0d62163b08769fd74f020709c398f994088ca96 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 22 18:06:23 2020 -0700 Sync with +TCP amazon-FreeRTOS (#158) * DNS.c commit * IP.c commit * Add various source & header files commit 8e36bee30eef2107e128edb58e83ee46e8241a91 Author: Nathan Chong <52972368+nchong-at-aws@users.noreply.github.com> Date: Tue Jul 21 12:51:20 2020 -0400 Prove buffer lemmas (#124) * Prove buffer lemmas * Update queue proofs to latest kernel source All changes were syntactic due to uncrustify code-formatting * Strengthen prvCopyDataToQueue proof * Add extract script for diff comparison Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit c720c18ada40b502436ea811e8d03dca919726d8 Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Tue Jul 14 05:35:44 2020 +0800 FreeRTOS+TCP Adding the combined driver for SAM4E and SAME70 v2 (#78) * Adding a combined +TCP driver for SAM4E and SAME70 * Changes after review from Aniruddha Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> commit 4237049b12d9bb6b03694fecf6ea26a353e637c8 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Jul 13 12:07:56 2020 -0700 Add changes from 2225-2227 amazon-FreeRTOS (#134) commit 7caa32863458c4470d3c620945c30824199f524c Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jul 10 23:32:30 2020 -0700 Add Full TCP test suite - not using secure sockets (#131) * Add Full-TCP suite * delete unnecessary files * Change after Joshua's comments commit d7667a0034841f2968f9f9f805030cc608bfbce1 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Fri Jul 3 15:45:44 2020 -0700 Remove unnecessary semicolon from the linker file (#121) This was creating problem with the onboard LPCLink debug probe. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit 529c481c39506d0b331bfd0cdea35e5d1aeaaad0 Author: Nathan Chong <52972368+nchong-at-aws@users.noreply.github.com> Date: Thu Jul 2 15:55:20 2020 -0400 Add VeriFast kernel queue proofs (#117) commit d5fedeaa96b5b1d3c0f6b9b52a8064ab72ff2821 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jul 1 13:56:27 2020 -0700 Add checks in FreeRTOS_Socket.c (#104) * Add fail-safes to FreeRTOS_Socket.c * Use all 'pd' errors * Correction after Hein's comments * Correction after Hein's comments v2 * Changes after Hein's comments * Update after Gary's comments commit a9b2aac4e9fda2a259380156df9cc0af51384d2d Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jun 26 12:09:36 2020 -0700 Folder structure change + Fix broken Projects (#103) * Update folder structure * Correct project files * Move test folder * Some changes after Yuki's comments commit 98bfc38bf3404414878dc68ea41753bea4e24c8e Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Thu Jun 25 13:01:45 2020 +0800 FreeRTOS+TCP : add memory statistics and dump packets, v3 (#83) * FreeRTOS+TCP : add memory statistics and dump packets, v3 * Two changes as requested by Aniruddha Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> commit 072a173c9df31c75ff64bde440f3f316cedb9033 Author: S.Burch <8697966+wholl0p@users.noreply.github.com> Date: Mon Jun 22 23:39:26 2020 +0200 Fixed Imports for Infineon XMC1100 Board (#88) Co-authored-by: RichardBarry <3073890+RichardBarry@users.noreply.github.com> commit 2df5eeef5763045c4c74ff0e2a4091b7d19bea89 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Mon Jun 8 14:22:46 2020 -0700 Feature/multiple direct to task notifications (#73) * Add TaskNotifyArray.c with the single task tests updated to use the task notification array up to the point where the timer is created. * Continue working on TaskNotifyArray.c to test the new task notification indexes. Next TaskNotifyArray.c will be refactored to break the tests up a bit. * Refactor and update the comments in TaskNotifyArray.c - no functional changes. * Change from the task notify "array" to task notification "indexed" nomenclature in the new task notification API functions that work on one particular task notification with the array of task notifications. * Update the implementation of the taskNOTIFY_TAKE() and taskNOTIFY_WAIT() trace macros to take the array index of the task notification they are acting on. Rename configNUMBER_OF_TASK_NOTIFICATIONS to configTASK_NOTIFICATION_ARRAY_ENTRIES. Add FreeRTOS/Demo/Common/Minimal/TaskNotifyArray.c to the Visual Studio project - the file implements tests specific to the behaviour of the indexed task notification functions and should be used in addition to the tests already provided in FreeRTOS/Demo/Common/Minimal/TaskNotify.c. commit b9e4ecfaf7286d8493d4a96a93fbb325534ad97b Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Jun 5 11:10:58 2020 -0700 Remove Empty and Un-referenced folder from Demo (#86) commit f11bcc8acc57a23fb03603762e758c25b9d0efb7 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Jun 3 16:52:31 2020 -0700 Fix a Bug and corresponding CBMC patch (#84) * Update remove-static-in-freertos-tcp-ip.patch * Update FreeRTOS_TCP_IP.c * Update remove-static-in-freertos-tcp-ip.patch * Update remove-static-in-freertos-tcp-ip.patch Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit bb9f92f771e5f6ea2b9b09c7e89130a75e562eb7 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Wed Jun 3 10:46:55 2020 -0700 Submodule FreeRTOS/Source 10bbbcf0b..6199b72fb (#82) commit 6efc39f44be5b269168836e95aebbdb8ae77dce3 Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue Jun 2 15:09:25 2020 -0700 Add Project for running integration tests v2 (#80) * Project for integration tests * relative paths in project files * relative paths in project files-1 * relative paths in project files-2 * addressed comments * addressed comments v2 Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 0eb5909fb02bac9dc074ff1bc2fe338d77f73764 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu May 28 17:05:24 2020 -0700 readme.md for ATmega328PB Xplained Mini. (#76) readme.md to get users jump started. commit cb7edd2323a77f3dbea144c1f48f95582becc99e Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu May 28 10:11:58 2020 -0700 Sync with a:FR (#75) * AFR sync * AFR sync: CBMC * AFR sync: CBMC: remove .bak files * AFR sync: CBMC: more cleanup * Corrected CBMC proofs * Corrected CBMC patches * Corrected CBMC patches-1 * Corrected CBMC patches-2 * remove .bak files (3) Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 6557291e5407ca7ec6beca53fced1aaa620c5c02 Author: alfred gedeon <alfred2g@hotmail.com> Date: Wed May 27 14:44:33 2020 -0700 Test: Add Linux Networking support with demo application (#71) * Test: Add Linux Networking support with demo application * Test: revert files affected by uncrustify * Test: revert files affected by uncrustify Co-authored-by: Alfred Gedeon <gedeonag@amazon.com> Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 8b079bc394e7b205d72210ce9e052404d782938f Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Wed May 27 10:44:03 2020 -0700 ATmega328PB Xplained Mini -- demo project for ATmega port. (#70) * Bootstrap a demo from START. No driver is added in this commit. * Add FreeRTOS source code to project. Remove unnecessary folder nesting. Heap_4 is used here. * Copy over main.c, FreeRTOSConfig.h, and regtest.{c, h}. This commit compiles, but will need some work on timer used. * This port has 2KB RAM. We are using 1KB for heap. Further decreasing minimum stack size, and also use stack overflow check 1 to save some stack space. * Preserve EEPROM set to false. * End of the line. * Reduce register test stack size. 32 8-bit register + 10 bytes for stack frame cost. Round up to 50. * Adding Queue test in Integer test. - g3 to easy debugging. - mainCHECK_PERIOD is set to 1000 ticks. Note that this port for now use WDT as tick timer, and period is set to 15ms. - vErrorChecks, is of highest priority. So if this task gets run before other tasks, the very first check will fail. * Avoid false alarm. Since we don't know in which order the tasks are scheduled, clearing any error for the first entry of vErrorChecks. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * ParTest.c to init, set, toggle onboard user LED at PB5. * Added a task to blink onboard user LED. Need a magic number for stack size. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Explicitly setting timing slicing to 0. This is to avoid unecessary context switch when multiple tasks are of the same priority. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * Add taskYIELD() at the end of the loop in each register test task. This is to give other tasks of the same priority a chance to run, regardless of scheduling algorithm. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> * minor, update comment in main.c. commit 95a3a02f95749fb7a600723076e291f9dee7426c Author: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri May 22 16:26:59 2020 -0700 FreeRTOS-Plus: Unit testing Infrastructure and examples (#72) * Added CMock as submodule * Makefile added * Removed TEMP from Makefile * Added configuration files and header files * Update Makefile * Test runner working * make clean * Example added with README * Update README.md * Restored +TCP files * Cleared +TCP changes * removed comments from Makefile * Update README.md * Update README.md * Update README.md * Updated Test/Unit-test/readme.md commit 5003d17feda25490e655c0f1c15d2b13e395c9f7 Author: Hein Tibosch <hein_tibosch@yahoo.es> Date: Wed May 6 14:16:56 2020 -0400 FreeRTOS+TCP : renewing DHCP lease while network is down (#53) Co-authored-by: Hein Tibosch <hein@htibosch.net> Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> commit d95624c5d6ba95ec0474867d7165de2c28ed41b7 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue May 5 09:57:18 2020 -0700 Move CBMC proofs to FreeRTOS+ directory (#64) * move CBMC proofs to FreeRTOS+ directory * Failing proofs corrected * ParseDNSReply proof added back * removed queue_init.h from -Plus/Test Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 95ae7c65758a9473ea16ab08182f056f72331de2 Author: markrtuttle <tuttle@acm.org> Date: Wed Apr 29 04:27:45 2020 +0000 Change cbmc-viewer invocation in CBMC makefile (#63) * Exclude FreeRTOS/Demo from CBMC proof reports. The script cbmc-viewer generates the CBMC proof reports. The script searches source files for symbol definitions and annotates source files with coverage information. This patch causes cbmc-viewer to ignore the directory FreeRTOS/Demo containing 348M of data. The script now terminates in a few seconds. * Make report default target for CBMC Makefile. Modify the Makefile for CBMC proofs to generate the report by default (and not just property checking) and modify property checking to ignore failures (due to property assertions failing) and terminating report generation. Co-authored-by: Mark R. Tuttle <mrtuttle@amazon.com> commit d421ccc89f6f6473dfdd566a00567b0e1fd4cfc3 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Sat Apr 25 16:57:35 2020 -0700 Reword readme.md under ./Test. (#61) commit 38412865985235b90dbd9da9708b68c4de5918f5 Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Sat Apr 25 16:56:54 2020 -0700 Removed a:FR reference. (#60) commit 4db195c916c7b13c82ab3a34a499fe606f266810 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue Apr 21 15:40:08 2020 -0700 Adding FreeRTOS+TCP CBMC proofs to FreeRTOS/FreeRTOS (#56) ParseDNSReply is to be added in the next PR. commit 40a31b6d35a866a3a6c551d95bf08dae855da5bd Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Apr 13 13:58:33 2020 -0700 'uL' -> 'UL' commit 5b3a289b69fc92089aa8bd4d1b44ab816f326f73 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Apr 13 13:50:53 2020 -0700 Changes after Gary's comments commit edf68637dd22470a8d4f59fecc15b51379bcfeda Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 16:26:03 2020 -0700 Update FreeRTOS_ARP.c commit 35f3ac32a8899dd714a8a48952a4224fbcebc4aa Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 15:56:18 2020 -0700 correct debug output commit 5e12a70db4b6a8e68a434489683306f040252efa Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Apr 10 15:44:45 2020 -0700 Debugging flag check added commit 4e8ac8de25ac4088b9c789b88a77cd39df4d9167 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:57:19 2020 -0700 Comment style consistency and Yuhui's suggestions commit e43f7cd086096ad60491fedba69927a1e1a82f20 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:47:41 2020 -0700 Cleanup commit ab3b51c7a0d880a6bf453ec63ae604e15050f310 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Thu Apr 9 16:33:03 2020 -0700 Update after Gary's comments commit 97f7009699ffb972c0745dfdb526d1fa4e0faf84 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 14:30:15 2020 -0700 Update after richard's comments commit a9fcafc074cec559dd67961ef44273df6180c2db Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 14:07:39 2020 -0700 Corrected the formatting - visual studio had messed up the formatting commit c381861014a8043ce30723fc5a8cf5107719c8df Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 13:01:12 2020 -0700 commit 2 after gary's comments commit 75677a8d85fa802cca9058d6e23796d5043a0982 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 12:51:10 2020 -0700 Commit after Gary's comments commit 666c0da366030109db2c0c5e7253cebb2f899db7 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 8 10:56:01 2020 -0700 Update after Yuhui's comments - removed (void) from before memcpy, memset etc. - corrected memcpy style as suggested by Yuhui - Added logging for xNetworkInterfaceOutput. No need to configASSERT commit 4a1148d15b6b8169d2412f8179f734683b179795 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Apr 1 16:05:36 2020 -0700 Coverity + MISRA compliance Modified code to conform to the MISRA directives more closely. commit fa74f7dccf6b1a356993c6a894f8e1173b8c8157 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu Apr 2 20:26:10 2020 -0700 Removing writes to read-only PLIC interrupt pending registers. Signed-off-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> commit 5b9777e11e16609648fb98d2f9a47553ab238950 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 31 10:45:23 2020 -0700 A readme file to introduce what ./Test directory is about. commit 211bb4cbd9ae6dfa95e8d8501f37d272bde5ab26 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 24 15:14:24 2020 -0700 Ignore whitespace when working with patches. commit 8156f64d1c45dd59ef12279f19a99f03e79e1f8a Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 25 18:04:23 2020 -0800 Copying CBMC proofs from aws/amazon-freertos repo ./tools/cbmc to this repo ./FreeRTOS/Test/CBMC as is. The commit ID in aws/amazon-freertos is 0c8e0217f2a43bdeb364b58ae01c6c259e03ef1b. commit 9f316c246baafa15c542a5aea81a94f26e3d6507 Author: David Vrabel <david.vrabel@cambridgeconsultants.com> Date: Mon Mar 16 11:21:46 2020 +0000 Demo/Posix_GCC: add demo application for Posix port using GCC This is largely a copy of the Windows demo application with a few key changes: - heap_3 (use malloc()/free()) so tools like valgrind "just work". - printf() wrapped in a mutex to prevent deadlocks on the internal pthread mutexes inside printf(). SCons (https://scons.org/) is used as the build system. This will be built as a 64-bit application, but note that the memory allocation trace points only record the lower 32-bits of the address. commit f78f919b3e2f0d707531a301a8ca07cd02bc4778 Author: Markus Rinne <markus.ka.rinne@gmail.com> Date: Thu Mar 19 21:00:24 2020 +0200 Fix function comments commit 1cd2d38d960a3576addb224582c88489bade5141 Author: David Chalco <david@chalco.io> Date: Fri Mar 20 10:29:05 2020 -0700 unix separators for path and remove .exe suffix from risc compiler (works on windows/mac) commit 938b19419eded12817737ab0644e94ed2ba7e95d Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Thu Mar 19 18:23:09 2020 -0700 Removing ./FreeRTOS-Labs directory, since: - IoT libraries are now in LTS branch. - FAT/POSIX/Light-weight MQTT are in https://github.com/FreeRTOS/FreeRTOS-Labs. commit 1a4abbc9e91b13fd6394464ade59d5e048320c7c Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 19:30:02 2020 -0700 Maintenance -- clean up readme.txt and add url to GitHub. (#38) * Removing readme.txt, as now we have README.md in place. The only information missing from README.md is about FAQ. * Adding FAQ information in README.md. * Adding a .url to root to redict user to FreeRTOS github home page. commit 47bb466aa19395b7785bcb830e2e4dd35f6bafc5 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 13:07:44 2020 -0700 Update issue templates Template maintenance. - adding title prefix. - adding examples to "additional context" section. commit f506290041f56867765f8efa70ed2862125bdb7c Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 17 10:15:07 2020 -0700 Create SECURITY.md Apply the recommended SECURITY.md from AWS to our repo. commit 8982a2f80a80a2a0a47cf82de07b52101bd9d606 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 13 12:50:10 2020 -0700 Add ./lib directory to make sure Zynq project compiles. commit ecf0f12aa14ad6fdafe1ef37257cbb4e03e2abd5 Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed Mar 11 10:19:48 2020 -0700 Sync up with Amazon-freertos repo (10th March 2020) (#34) * Sync up with amazon-freertos * Sync up with amazon-freertos * Sync up with amazon-freertos commit 0acffef047973e2e61c2201fd69cd9bbd317f674 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Mar 10 10:20:48 2020 -0700 GitHub PR template. (#29) commit c40a6da2e4cb8042b56d1b174051cbbe9813781a Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Mon Mar 9 11:18:48 2020 -0700 pass payload length when calling UDP callback (#30) * pass payload length when calling UDP callback commit 12d580e93d4d9074b9a867632f0681a511b4ad12 Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 18:16:51 2020 -0800 Update issue templates Initial issue template. Created following https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser. If change is needed, we could go another round. commit 9debffb5e0e42ff716f58b2270b3af09652294af Author: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 17:27:46 2020 -0800 Update README.md to remove dead link. See the conversation https://github.com/FreeRTOS/FreeRTOS/commit/42c627b2b88cb3b487fea983d8b566a8bbae54fa#comments . Linkage for both ```./FreeRTOS/Source``` and ```./FreeRTOS/Demo``` are removed, since it looks weird to only provide linkage to Demo. commit 7e1a4bf563240501fc45167aee9d929c533939dd Author: AniruddhaKanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri Mar 6 15:18:09 2020 -0800 Fix DHCP option Client-identifier (#28) commit 42c627b2b88cb3b487fea983d8b566a8bbae54fa Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Mar 6 09:15:11 2020 -0800 Update readme and revert relative URL. (#27) * Reordering: bumping cloning instruction up. * Rewording readme.md to be clear kernel code is a submodule of this repository. * Reverting relative URL, since user cannot click through on GitHub page. (With URL, user could still download the correct version of the code. Reverting simply due to UI issue.) commit 5751ae9b60e248ebd0b4dd7c58df54364d2bb9d5 Author: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Date: Fri Mar 6 09:11:42 2020 -0800 Update CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso project (#26) This commit updates the project for LPC55S69 so that it works with the latest version of MCUXpresso and SDK. Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> commit a9ffffe1f01f45f79e127c15727784984077932f Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Mar 5 17:16:13 2020 -0800 Using Relative URL For Submoduling. (#24) commit 52c82076b38fe73d1dc46c97abf74ae9b803696c Author: Carl Lundin <53273776+lundinc2@users.noreply.github.com> Date: Thu Mar 5 09:16:31 2020 -0800 use relative path to point to bundled toolchain instead (#25) commit b877e4ec478de2c24d07ab46241070d7c66f375c Author: lundinc2 <53273776+lundinc2@users.noreply.github.com> Date: Tue Feb 25 13:18:38 2020 -0800 Moved vulnerability reporting and code of conduct to top of CONTRIBUTING.md (#20) commit bef165d46799fb8faa58aaa224f80c16b6538e69 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 18 22:06:38 2020 -0800 Linking test source file from relative path. (#19) commit 89e7bbe292afd3912d1f0b2402cc506878bad869 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Tue Feb 18 17:47:55 2020 -0800 A preliminary .gitignore file, to prevent us checking in files unnecessary. (#18) https://github.com/github/gitignore. commit c2a98127acb48c4562233230e66ca5c282688579 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Sun Feb 16 13:19:53 2020 -0800 Minor wording changes in the 'previous releases' section of the readme.me file. (#17) commit 24c772d1439e5c291c0a29fce0a46996ca8afaa9 Author: Yuhui.Zheng <10982575+yuhui-zheng@users.noreply.github.com> Date: Fri Feb 14 12:47:01 2020 -0800 Submodule kernel directory. (#16) * Removing FreeRTOS/Source in readiness for submoduling. * Submoduling kernel. * README.md update due to submoduling. When releasing, please follow these steps: 1. in local directory, clean directory and check "git status" shows "nothing to commit, working tree clean" for ALL subdirectories. 2. copy source code and instructions only to an empty folder. Git related should not be in this folder -- this covers .git, .gitignore, .github, .gitmodules, gitmessages, ...... 3. zip the folder from step 2. (create both .zip and .7z) 4. attach .zip and .7z to the release. (e.g. attach these two in new release -- https://github.com/FreeRTOS/FreeRTOS/releases/new) 5. PLEASE download both, unzip, diff with your local git repo. (should not see any difference other than git related.) And, sanity check a couple of projects. commit c3f8b91652392dc55e0d7067b90a40de5f5f0837 Author: Rashed Talukder <9218468+rashedtalukder@users.noreply.github.com> Date: Thu Feb 13 17:47:14 2020 -0800 Update readme. Fixed typos and cli commands (#14) commit 4723b825f2989213c1cdb2ebf4d6793e0292e363 Author: Julian Poidevin <julian-poidevin@users.noreply.github.com> Date: Fri Feb 14 02:43:36 2020 +0100 Fixed wrong git clone SSH command (#13) Replaced bad https URL with proper SSH URL commit fc819b821715c42602819e58499846147a6394f5 Author: RichardBarry <3073890+RichardBarry@users.noreply.github.com> Date: Thu Feb 13 17:42:22 2020 -0800 Correct the xTimerCreate() documentation which said NULL was returned if the timer period was passed into the function as 0, whereas that is not the case. (#15) Add a note to the documentation for both the xTimerCreate() and xTimerCreateStatic() functions that the timer period must be greater than 0. commit 1c711ab530b5f0dbd811d7d62e0a3763706ffff4 Author: Rashed Talukder <9218468+rashedtalukder@users.noreply.github.com> Date: Wed Feb 12 23:00:18 2020 -0800 Updated contributions guidelines (#12) commit 84fcc0d5317d96c6b086034093c8c1c83e050819 Author: Cobus van Eeden <35851496+cobusve@users.noreply.github.com> Date: Wed Feb 12 15:05:06 2020 -0800 Updates to Markdown files and readme.txt (#11) git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2826 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c218
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c650
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c1185
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c1408
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c1992
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c25
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c1801
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c431
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c100
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h85
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h28
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h76
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h53
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h171
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h137
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h197
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h23
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h12
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h28
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h11
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h42
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h4
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h10
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h89
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h77
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c59
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c22
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c14
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c102
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c928
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c924
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h1418
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c6
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c12
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c10
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c45
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt5
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c16
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c8
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c889
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c2
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.c658
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.md72
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.c425
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.md45
62 files changed, 10970 insertions, 3577 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
index decd17338..9104a7236 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
@@ -43,8 +43,8 @@
#if( ipconfigUSE_LLMNR == 1 )
#include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */
-#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
/* When the age of an entry in the ARP table reaches this value (it counts down
@@ -54,7 +54,7 @@ entry is still valid and can therefore be refreshed. */
/* The time between gratuitous ARPs. */
#ifndef arpGRATUITOUS_ARP_PERIOD
- #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000 ) )
+ #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000U ) )
#endif
/*-----------------------------------------------------------*/
@@ -85,24 +85,6 @@ static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;
MACAddress_t xARPClashMacAddress;
#endif /* ipconfigARP_USE_CLASH_DETECTION */
-/* Part of the Ethernet and ARP headers are always constant when sending an IPv4
-ARP packet. This array defines the constant parts, allowing this part of the
-packet to be filled in using a simple memcpy() instead of individual writes. */
-static const uint8_t xDefaultPartARPPacketHeader[] =
-{
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source address. */
- 0x08, 0x06, /* Ethernet frame type (ipARP_FRAME_TYPE). */
- 0x00, 0x01, /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */
- 0x08, 0x00, /* usProtocolType. */
- ipMAC_ADDRESS_LENGTH_BYTES, /* ucHardwareAddressLength. */
- ipIP_ADDRESS_LENGTH_BYTES, /* ucProtocolAddressLength. */
- 0x00, 0x01, /* usOperation (ipARP_REQUEST). */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* xSenderHardwareAddress. */
- 0x00, 0x00, 0x00, 0x00, /* ulSenderProtocolAddress. */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
-};
-
/*-----------------------------------------------------------*/
eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
@@ -114,7 +96,7 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
pxARPHeader = &( pxARPFrame->xARPHeader );
/* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
- memcpy( ( void *)&( ulSenderProtocolAddress ), ( void * )pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
+ ( void ) memcpy( &( ulSenderProtocolAddress ), pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
/* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */
ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;
@@ -144,17 +126,17 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
{
/* A double IP address is detected! */
/* Give the sources MAC address the value of the broadcast address, will be swapped later */
- memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
- memset( pxARPHeader->xTargetHardwareAddress.ucBytes, '\0', sizeof( MACAddress_t ) );
+ ( void ) memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
+ ( void ) memset( pxARPHeader->xTargetHardwareAddress.ucBytes, 0, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = 0UL;
}
else
{
- memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
+ ( void ) memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
}
- memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
- memcpy( ( void* )pxARPHeader->ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
+ ( void ) memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
+ ( void ) memcpy( pxARPHeader->ucSenderProtocolAddress, ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
eReturn = eReturnEthernetFrame;
}
@@ -169,7 +151,8 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
xARPHadIPClash = pdTRUE;
- memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
+ /* Remember the MAC-address of the other device which has the same IP-address. */
+ ( void ) memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
}
}
#endif /* ipconfigARP_USE_CLASH_DETECTION */
@@ -198,7 +181,7 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
if( ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
{
lResult = xARPCache[ x ].ulIPAddress;
- memset( &xARPCache[ x ], '\0', sizeof( xARPCache[ x ] ) );
+ ( void ) memset( &xARPCache[ x ], 0, sizeof( xARPCache[ x ] ) );
break;
}
}
@@ -217,21 +200,22 @@ BaseType_t xMacEntry = -1;
BaseType_t xUseEntry = 0;
uint8_t ucMinAgeFound = 0U;
- #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )
- /* Only process the IP address if it is on the local network.
- Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address
- and netmask are still unknown. */
- if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||
- ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )
- #else
+#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )
+ /* Only process the IP address if it is on the local network.
+ Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address
+ and netmask are still unknown. */
+ if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||
+ ( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) )
+#else
/* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with
a different netmask will also be stored. After when replying to a UDP
message from a different netmask, the IP address can be looped up and a
reply sent. This option is useful for systems with multiple gateways,
the reply will surely arrive. If ipconfigARP_STORES_REMOTE_ADDRESSES is
zero the the gateway address is the only option. */
- if( pdTRUE )
- #endif
+
+ if( pdTRUE )
+#endif
{
/* Start with the maximum possible number. */
ucMinAgeFound--;
@@ -239,6 +223,23 @@ uint8_t ucMinAgeFound = 0U;
/* For each entry in the ARP cache table. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
+ BaseType_t xMatchingMAC;
+
+ if( pxMACAddress != NULL )
+ {
+ if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
+ {
+ xMatchingMAC = pdTRUE;
+ }
+ else
+ {
+ xMatchingMAC = pdFALSE;
+ }
+ }
+ else
+ {
+ xMatchingMAC = pdFALSE;
+ }
/* Does this line in the cache table hold an entry for the IP
address being queried? */
if( xARPCache[ x ].ulIPAddress == ulIPAddress )
@@ -253,7 +254,7 @@ uint8_t ucMinAgeFound = 0U;
}
/* See if the MAC-address also matches. */
- if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
+ if( xMatchingMAC != pdFALSE )
{
/* This function will be called for each received packet
As this is by far the most common path the coding standard
@@ -271,7 +272,7 @@ uint8_t ucMinAgeFound = 0U;
must be cleared. */
xIpEntry = x;
}
- else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
+ else if( xMatchingMAC != pdFALSE )
{
/* Found an entry with the given MAC-address, but the IP-address
is different. Continue looping to find a possible match with
@@ -302,6 +303,10 @@ uint8_t ucMinAgeFound = 0U;
ucMinAgeFound = xARPCache[ x ].ucAge;
xUseEntry = x;
}
+ else
+ {
+ /* Nothing happes to this cache entry for now. */
+ }
}
if( xMacEntry >= 0 )
@@ -313,7 +318,7 @@ uint8_t ucMinAgeFound = 0U;
/* Both the MAC address as well as the IP address were found in
different locations: clear the entry which matches the
IP-address */
- memset( &xARPCache[ xIpEntry ], '\0', sizeof( xARPCache[ xIpEntry ] ) );
+ ( void ) memset( &( xARPCache[ xIpEntry ] ), 0, sizeof( ARPCacheRow_t ) );
}
}
else if( xIpEntry >= 0 )
@@ -321,13 +326,17 @@ uint8_t ucMinAgeFound = 0U;
/* An entry containing the IP-address was found, but it had a different MAC address */
xUseEntry = xIpEntry;
}
+ else
+ {
+ /* No matching entry found. */
+ }
/* If the entry was not found, we use the oldest entry and set the IPaddress */
xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;
if( pxMACAddress != NULL )
{
- memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
+ ( void ) memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );
/* And this entry does not need immediate attention */
@@ -339,6 +348,10 @@ uint8_t ucMinAgeFound = 0U;
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdFALSE;
}
+ else
+ {
+ /* Nothing will be stored. */
+ }
}
}
/*-----------------------------------------------------------*/
@@ -372,21 +385,29 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * con
{
eARPLookupResult_t eReturn;
uint32_t ulAddressToLookup;
+ulAddressToLookup = *pulIPAddress;
#if( ipconfigUSE_LLMNR == 1 )
- if( *pulIPAddress == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
+ if( ulAddressToLookup == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
{
/* The LLMNR IP-address has a fixed virtual MAC address. */
- memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
+ ( void ) memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
else
#endif
- if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
+ if( xIsIPv4Multicast( ulAddressToLookup ) != 0 )
+ {
+ /* Get the lowest 23 bits of the IP-address. */
+ vSetMultiCastIPv4MacAddress( ulAddressToLookup, pxMACAddress );
+
+ eReturn = eARPCacheHit;
+ }
+ else if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
{
- /* This is a broadcast so uses the broadcast MAC address. */
- memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
+ /* This is a broadcast so it uses the broadcast MAC address. */
+ ( void ) memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )
@@ -401,6 +422,7 @@ uint32_t ulAddressToLookup;
if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )
{
+ /* No matching end-point is found, look for a gateway. */
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );
@@ -408,14 +430,14 @@ uint32_t ulAddressToLookup;
{
/* The stack is configured to store 'remote IP addresses', i.e. addresses
belonging to a different the netmask. prvCacheLookup() returned a hit, so
- the MAC address is known */
+ the MAC address is known. */
}
else
#endif
{
/* The IP address is off the local network, so look up the
hardware address of the router, if any. */
- if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u )
+ if( xNetworkAddressing.ulGatewayAddress != ( uint32_t ) 0U )
{
ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;
}
@@ -432,7 +454,11 @@ uint32_t ulAddressToLookup;
ulAddressToLookup = *pulIPAddress;
}
- if( eReturn == eARPCacheMiss )
+ #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
+ if( eReturn == eARPCacheMiss ) /*lint !e774: (Info -- Boolean within 'if' always evaluates to True, depending on configuration. */
+ #else
+ /* No cache look-up was done, so the result is still 'eARPCacheMiss'. */
+ #endif
{
if( ulAddressToLookup == 0UL )
{
@@ -479,7 +505,7 @@ eARPLookupResult_t eReturn = eARPCacheMiss;
else
{
/* A valid entry was found. */
- memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
+ ( void ) memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit;
}
break;
@@ -523,7 +549,7 @@ TickType_t xTimeNow;
/* The age has just ticked down, with nothing to do. */
}
- if( xARPCache[ x ].ucAge == 0u )
+ if( xARPCache[ x ].ucAge == 0U )
{
/* The entry is no longer valid. Wipe it out. */
iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );
@@ -549,7 +575,7 @@ void vARPSendGratuitous( void )
xLastGratuitousARPTime = ( TickType_t ) 0;
/* Let the IP-task call vARPAgeCache(). */
- xSendEventToIPTask( eARPTimerEvent );
+ ( void ) xSendEventToIPTask( eARPTimerEvent );
}
/*-----------------------------------------------------------*/
@@ -559,7 +585,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/* This is called from the context of the IP event task, so a block time
must not be used. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0 );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0U );
if( pxNetworkBuffer != NULL )
{
@@ -574,16 +600,17 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
- pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
+ pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
}
#endif
+
if( xIsCallingFromIPTask() != 0 )
{
/* Only the IP-task is allowed to call this function directly. */
- xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
+ ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
else
{
@@ -591,7 +618,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/* Send a message to the IP-task to send this ARP packet. */
xSendEvent.eEventType = eNetworkTxEvent;
- xSendEvent.pvData = ( void * ) pxNetworkBuffer;
+ xSendEvent.pvData = pxNetworkBuffer;
if( xSendEventStructToIPTask( &xSendEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
{
/* Failed to send the message, so release the network buffer. */
@@ -603,15 +630,33 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
+/* Part of the Ethernet and ARP headers are always constant when sending an IPv4
+ARP packet. This array defines the constant parts, allowing this part of the
+packet to be filled in using a simple memcpy() instead of individual writes. */
+static const uint8_t xDefaultPartARPPacketHeader[] =
+{
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source address. */
+ 0x08, 0x06, /* Ethernet frame type (ipARP_FRAME_TYPE). */
+ 0x00, 0x01, /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */
+ 0x08, 0x00, /* usProtocolType. */
+ ipMAC_ADDRESS_LENGTH_BYTES, /* ucHardwareAddressLength. */
+ ipIP_ADDRESS_LENGTH_BYTES, /* ucProtocolAddressLength. */
+ 0x00, 0x01, /* usOperation (ipARP_REQUEST). */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* xSenderHardwareAddress. */
+ 0x00, 0x00, 0x00, 0x00, /* ulSenderProtocolAddress. */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
+};
+
ARPPacket_t *pxARPPacket;
/* Buffer allocation ensures that buffers always have space
for an ARP packet. See buffer allocation implementations 1
and 2 under portable/BufferManagement. */
- configASSERT( pxNetworkBuffer );
+ configASSERT( pxNetworkBuffer != NULL );
configASSERT( pxNetworkBuffer->xDataLength >= sizeof(ARPPacket_t) );
- pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
+ pxARPPacket = ipPOINTER_CAST( ARPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
/* memcpy the const part of the header information into the correct
location in the packet. This copies:
@@ -624,11 +669,11 @@ ARPPacket_t *pxARPPacket;
xARPHeader.usOperation;
xARPHeader.xTargetHardwareAddress;
*/
- memcpy( ( void * ) pxARPPacket, ( void * ) xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
- memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
- memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( pxARPPacket, xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
+ ( void ) memcpy( pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
- memcpy( ( void* )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
+ ( void ) memcpy( pxARPPacket->xARPHeader.ucSenderProtocolAddress, ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
@@ -639,8 +684,53 @@ ARPPacket_t *pxARPPacket;
void FreeRTOS_ClearARP( void )
{
- memset( xARPCache, '\0', sizeof( xARPCache ) );
+ ( void ) memset( xARPCache, 0, sizeof( xARPCache ) );
+}
+/*-----------------------------------------------------------*/
+
+#if 1
+BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
+{
+BaseType_t xResult = pdFALSE;
+NetworkBufferDescriptor_t * pxUseDescriptor = pxDescriptor;
+const IPPacket_t *pxIPPacket = ipPOINTER_CAST( IPPacket_t *, pxUseDescriptor->pucEthernetBuffer );
+
+ /* This function will check if the target IP-address belongs to this device.
+ * If so, the packet will be passed to the IP-stack, who will answer it.
+ * The function is to be called within the function xNetworkInterfaceOutput().
+ */
+
+ if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
+ {
+ if( memcmp( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
+ {
+ xResult = pdTRUE;
+ if( bReleaseAfterSend == pdFALSE )
+ {
+ /* Driver is not allowed to transfer the ownership
+ of descriptor, so make a copy of it */
+ pxUseDescriptor =
+ pxDuplicateNetworkBufferWithDescriptor( pxDescriptor, pxDescriptor->xDataLength );
+ }
+ if( pxUseDescriptor != NULL )
+ {
+ IPStackEvent_t xRxEvent;
+
+ xRxEvent.eEventType = eNetworkRxEvent;
+ xRxEvent.pvData = pxUseDescriptor;
+ if( xSendEventStructToIPTask( &xRxEvent, 0U ) != pdTRUE )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxUseDescriptor );
+ iptraceETHERNET_RX_EVENT_LOST();
+ FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
+ }
+
+ }
+ }
+ }
+ return xResult;
}
+#endif /* 0 */
/*-----------------------------------------------------------*/
#if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
@@ -652,7 +742,7 @@ void FreeRTOS_ClearARP( void )
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
- if( ( xARPCache[ x ].ulIPAddress != 0ul ) && ( xARPCache[ x ].ucAge > 0U ) )
+ if( ( xARPCache[ x ].ulIPAddress != 0UL ) && ( xARPCache[ x ].ucAge > ( uint8_t ) 0U ) )
{
/* See if the MAC-address also matches, and we're all happy */
FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
index 59d55dea4..e12db9162 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
@@ -36,16 +36,18 @@
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "FreeRTOS_ARP.h"
-#include "NetworkInterface.h"
-#include "NetworkBufferManagement.h"
+
+#include "FreeRTOSIPConfigDefaults.h"
/* Exclude the entire file if DHCP is not enabled. */
#if( ipconfigUSE_DHCP != 0 )
-#if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586u )
+#include "NetworkInterface.h"
+#include "NetworkBufferManagement.h"
+
+#if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586U )
/* DHCP must be able to receive an options field of 312 bytes, the fixed
part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */
#error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP
@@ -58,22 +60,22 @@
/* Timer parameters */
#ifndef dhcpINITIAL_DHCP_TX_PERIOD
- #define dhcpINITIAL_TIMER_PERIOD ( pdMS_TO_TICKS( 250 ) )
- #define dhcpINITIAL_DHCP_TX_PERIOD ( pdMS_TO_TICKS( 5000 ) )
+ #define dhcpINITIAL_TIMER_PERIOD ( pdMS_TO_TICKS( 250U ) )
+ #define dhcpINITIAL_DHCP_TX_PERIOD ( pdMS_TO_TICKS( 5000U ) )
#endif
/* Codes of interest found in the DHCP options field. */
-#define dhcpZERO_PAD_OPTION_CODE ( 0u )
-#define dhcpSUBNET_MASK_OPTION_CODE ( 1u )
-#define dhcpGATEWAY_OPTION_CODE ( 3u )
-#define dhcpDNS_SERVER_OPTIONS_CODE ( 6u )
-#define dhcpDNS_HOSTNAME_OPTIONS_CODE ( 12u )
-#define dhcpREQUEST_IP_ADDRESS_OPTION_CODE ( 50u )
-#define dhcpLEASE_TIME_OPTION_CODE ( 51u )
-#define dhcpMESSAGE_TYPE_OPTION_CODE ( 53u )
-#define dhcpSERVER_IP_ADDRESS_OPTION_CODE ( 54u )
-#define dhcpPARAMETER_REQUEST_OPTION_CODE ( 55u )
-#define dhcpCLIENT_IDENTIFIER_OPTION_CODE ( 61u )
+#define dhcpIPv4_ZERO_PAD_OPTION_CODE ( 0U )
+#define dhcpIPv4_SUBNET_MASK_OPTION_CODE ( 1U )
+#define dhcpIPv4_GATEWAY_OPTION_CODE ( 3U )
+#define dhcpIPv4_DNS_SERVER_OPTIONS_CODE ( 6U )
+#define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE ( 12U )
+#define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE ( 50U )
+#define dhcpIPv4_LEASE_TIME_OPTION_CODE ( 51U )
+#define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE ( 53U )
+#define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE ( 54U )
+#define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE ( 55U )
+#define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE ( 61U )
/* The four DHCP message types of interest. */
#define dhcpMESSAGE_TYPE_DISCOVER ( 1 )
@@ -84,15 +86,21 @@
/* Offsets into the transmitted DHCP options fields at which various parameters
are located. */
-#define dhcpCLIENT_IDENTIFIER_OFFSET ( 6 )
-#define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 14 )
-#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 20 )
+#define dhcpCLIENT_IDENTIFIER_OFFSET ( 6U )
+#define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 14U )
+#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 20U )
/* Values used in the DHCP packets. */
-#define dhcpREQUEST_OPCODE ( 1 )
-#define dhcpREPLY_OPCODE ( 2 )
-#define dhcpADDRESS_TYPE_ETHERNET ( 1 )
-#define dhcpETHERNET_ADDRESS_LENGTH ( 6 )
+#define dhcpREQUEST_OPCODE ( 1U )
+#define dhcpREPLY_OPCODE ( 2U )
+#define dhcpADDRESS_TYPE_ETHERNET ( 1U )
+#define dhcpETHERNET_ADDRESS_LENGTH ( 6U )
+
+/* The following define is temporary and serves to make the /single source
+code more similar to the /multi version. */
+
+#define EP_DHCPData xDHCPData
+#define EP_IPv4_SETTINGS xNetworkAddressing
/* If a lease time is not received, use the default of two days. */
/* 48 hours in ticks. Can not use pdMS_TO_TICKS() as integer overflow can occur. */
@@ -106,23 +114,25 @@ are located. */
/* Offset into a DHCP message at which the first byte of the options is
located. */
-#define dhcpFIRST_OPTION_BYTE_OFFSET ( 0xf0 )
+#define dhcpFIRST_OPTION_BYTE_OFFSET ( 0xf0U )
-/* Standard DHCP port numbers and magic cookie value. */
+/* Standard DHCP port numbers and magic cookie value.
+DHCPv4 uses UDP port number 68 for clients and port number 67 for servers.
+*/
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
- #define dhcpCLIENT_PORT 0x4400u
- #define dhcpSERVER_PORT 0x4300u
- #define dhcpCOOKIE 0x63538263ul
- #define dhcpBROADCAST 0x0080u
+ #define dhcpCLIENT_PORT_IPv4 0x4400U
+ #define dhcpSERVER_PORT_IPv4 0x4300U
+ #define dhcpCOOKIE 0x63538263UL
+ #define dhcpBROADCAST 0x0080U
#else
- #define dhcpCLIENT_PORT 0x0044u
- #define dhcpSERVER_PORT 0x0043u
- #define dhcpCOOKIE 0x63825363ul
- #define dhcpBROADCAST 0x8000u
-#endif /* ipconfigBYTE_ORDER */
+ #define dhcpCLIENT_PORT_IPv4 0x0044U
+ #define dhcpSERVER_PORT_IPv4 0x0043U
+ #define dhcpCOOKIE 0x63825363UL
+ #define dhcpBROADCAST 0x8000U
+#endif /* ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) */
#include "pack_struct_start.h"
-struct xDHCPMessage
+struct xDHCPMessage_IPv4
{
uint8_t ucOpcode;
uint8_t ucAddressType;
@@ -139,43 +149,13 @@ struct xDHCPMessage
uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ];
uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ];
uint32_t ulDHCPCookie;
- uint8_t ucFirstOptionByte;
+ /* Option bytes from here on. */
}
#include "pack_struct_end.h"
-typedef struct xDHCPMessage DHCPMessage_t;
-
-/* DHCP state machine states. */
-typedef enum
-{
- eWaitingSendFirstDiscover = 0, /* Initial state. Send a discover the first time it is called, and reset all timers. */
- eWaitingOffer, /* Either resend the discover, or, if the offer is forthcoming, send a request. */
- eWaitingAcknowledge, /* Either resend the request. */
- #if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
- eGetLinkLayerAddress, /* When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */
- #endif
- eLeasedAddress, /* Resend the request at the appropriate time to renew the lease. */
- eNotUsingLeasedAddress /* DHCP failed, and a default IP address is being used. */
-} eDHCPState_t;
-
-/* Hold information in between steps in the DHCP state machine. */
-struct xDHCP_DATA
-{
- uint32_t ulTransactionId;
- uint32_t ulOfferedIPAddress;
- uint32_t ulDHCPServerAddress;
- uint32_t ulLeaseTime;
- /* Hold information on the current timer state. */
- TickType_t xDHCPTxTime;
- TickType_t xDHCPTxPeriod;
- /* Try both without and with the broadcast flag */
- BaseType_t xUseBroadcast;
- /* Maintains the DHCP state machine state. */
- eDHCPState_t eDHCPState;
- /* The UDP socket used for all incoming and outgoing DHCP traffic. */
- Socket_t xDHCPSocket;
-};
+typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t;
-typedef struct xDHCP_DATA DHCPData_t;
+/* The UDP socket used for all incoming and outgoing DHCP traffic. */
+_static Socket_t xDHCPSocket;
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
/* Define the Link Layer IP address: 169.254.x.x */
@@ -198,7 +178,7 @@ static void prvSendDHCPDiscover( void );
/*
* Interpret message received on the DHCP socket.
*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+_static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
@@ -215,12 +195,20 @@ static void prvInitialiseDHCP( void );
* Creates the part of outgoing DHCP messages that are common to all outgoing
* DHCP messages.
*/
-static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, BaseType_t xOpcode, const uint8_t * const pucOptionsArray, size_t *pxOptionsArraySize );
+static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress,
+ BaseType_t xOpcode,
+ const uint8_t * const pucOptionsArray,
+ size_t *pxOptionsArraySize );
/*
* Create the DHCP socket, if it has not been created already.
*/
-static void prvCreateDHCPSocket( void );
+_static void prvCreateDHCPSocket( void );
+
+/*
+ * Close the DHCP socket.
+ */
+static void prvCloseDHCPSocket( void );
/*
* After DHCP has failed to answer, prepare everything to start searching
@@ -233,8 +221,8 @@ static void prvCreateDHCPSocket( void );
/*-----------------------------------------------------------*/
-/* The next DHCP transaction Id to be used. */
-static DHCPData_t xDHCPData;
+/* Hold information in between steps in the DHCP state machine. */
+_static DHCPData_t xDHCPData;
/*-----------------------------------------------------------*/
@@ -242,7 +230,7 @@ BaseType_t xIsDHCPSocket( Socket_t xSocket )
{
BaseType_t xReturn;
- if( xDHCPData.xDHCPSocket == xSocket )
+ if( xDHCPSocket == xSocket )
{
xReturn = pdTRUE;
}
@@ -265,10 +253,10 @@ BaseType_t xGivingUp = pdFALSE;
/* Is DHCP starting over? */
if( xReset != pdFALSE )
{
- xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
+ EP_DHCPData.eDHCPState = eWaitingSendFirstDiscover;
}
- switch( xDHCPData.eDHCPState )
+ switch( EP_DHCPData.eDHCPState )
{
case eWaitingSendFirstDiscover :
/* Ask the user if a DHCP discovery is required. */
@@ -282,20 +270,19 @@ BaseType_t xGivingUp = pdFALSE;
prvInitialiseDHCP();
/* See if prvInitialiseDHCP() has creates a socket. */
- if( xDHCPData.xDHCPSocket == NULL )
+ if( xDHCPSocket == NULL )
{
xGivingUp = pdTRUE;
- break;
}
+ else
+ {
- *ipLOCAL_IP_ADDRESS_POINTER = 0UL;
+ *ipLOCAL_IP_ADDRESS_POINTER = 0UL;
- /* Send the first discover request. */
- if( xDHCPData.xDHCPSocket != NULL )
- {
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();
- prvSendDHCPDiscover( );
- xDHCPData.eDHCPState = eWaitingOffer;
+ /* Send the first discover request. */
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
+ prvSendDHCPDiscover();
+ EP_DHCPData.eDHCPState = eWaitingOffer;
}
}
#if( ipconfigUSE_DHCP_HOOK != 0 )
@@ -303,7 +290,7 @@ BaseType_t xGivingUp = pdFALSE;
{
if( eAnswer == eDHCPUseDefaults )
{
- memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );
+ ( void ) memcpy( &( xNetworkAddressing ), &( xDefaultAddressing ), sizeof( xNetworkAddressing ) );
}
/* The user indicates that the DHCP process does not continue. */
@@ -321,45 +308,54 @@ BaseType_t xGivingUp = pdFALSE;
{
#if( ipconfigUSE_DHCP_HOOK != 0 )
/* Ask the user if a DHCP request is required. */
- eAnswer = xApplicationDHCPHook( eDHCPPhasePreRequest, xDHCPData.ulOfferedIPAddress );
+ eAnswer = xApplicationDHCPHook( eDHCPPhasePreRequest, EP_DHCPData.ulOfferedIPAddress );
if( eAnswer == eDHCPContinue )
#endif /* ipconfigUSE_DHCP_HOOK */
{
/* An offer has been made, the user wants to continue,
generate the request. */
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();
- xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
- prvSendDHCPRequest( );
- xDHCPData.eDHCPState = eWaitingAcknowledge;
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
+ EP_DHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
+ prvSendDHCPRequest();
+ EP_DHCPData.eDHCPState = eWaitingAcknowledge;
break;
}
#if( ipconfigUSE_DHCP_HOOK != 0 )
if( eAnswer == eDHCPUseDefaults )
{
- memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );
+ ( void ) memcpy( &( xNetworkAddressing ), &( xDefaultAddressing ), sizeof( xNetworkAddressing ) );
}
/* The user indicates that the DHCP process does not continue. */
xGivingUp = pdTRUE;
#endif /* ipconfigUSE_DHCP_HOOK */
}
- else if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
+
+ /* Is it time to send another Discover? */
+ else if( ( xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod )
{
/* It is time to send another Discover. Increase the time
period, and if it has not got to the point of giving up - send
another discovery. */
- xDHCPData.xDHCPTxPeriod <<= 1;
+ EP_DHCPData.xDHCPTxPeriod <<= 1;
- if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
+ if( EP_DHCPData.xDHCPTxPeriod <= ( TickType_t ) ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
- if( xApplicationGetRandomNumber( &( xDHCPData.ulTransactionId ) ) != pdFALSE )
+ if( xApplicationGetRandomNumber( &( EP_DHCPData.ulTransactionId ) ) != pdFALSE )
{
- xDHCPData.xDHCPTxTime = xTaskGetTickCount( );
- xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast;
- prvSendDHCPDiscover( );
- FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", xDHCPData.xDHCPTxPeriod ) );
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
+ if( EP_DHCPData.xUseBroadcast != pdFALSE )
+ {
+ EP_DHCPData.xUseBroadcast = pdFALSE;
+ }
+ else
+ {
+ EP_DHCPData.xUseBroadcast = pdTRUE;
+ }
+ prvSendDHCPDiscover();
+ FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", EP_DHCPData.xDHCPTxPeriod ) );
}
else
{
@@ -368,7 +364,7 @@ BaseType_t xGivingUp = pdFALSE;
}
else
{
- FreeRTOS_debug_printf( ( "vDHCPProcess: giving up %lu > %lu ticks\n", xDHCPData.xDHCPTxPeriod, ipconfigMAXIMUM_DISCOVER_TX_PERIOD ) );
+ FreeRTOS_debug_printf( ( "vDHCPProcess: giving up %lu > %lu ticks\n", EP_DHCPData.xDHCPTxPeriod, ipconfigMAXIMUM_DISCOVER_TX_PERIOD ) );
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
{
@@ -380,7 +376,7 @@ BaseType_t xGivingUp = pdFALSE;
/* Setting an IP address manually so set to not using
leased address mode. */
- xDHCPData.eDHCPState = eGetLinkLayerAddress;
+ EP_DHCPData.eDHCPState = eGetLinkLayerAddress;
}
#else
{
@@ -389,6 +385,10 @@ BaseType_t xGivingUp = pdFALSE;
#endif /* ipconfigDHCP_FALL_BACK_AUTO_IP */
}
}
+ else
+ {
+ /* There was no DHCP reply, there was no time-out, just keep on waiting. */
+ }
break;
case eWaitingAcknowledge :
@@ -396,35 +396,34 @@ BaseType_t xGivingUp = pdFALSE;
/* Look for acks coming in. */
if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_ACK ) == pdPASS )
{
- FreeRTOS_debug_printf( ( "vDHCPProcess: acked %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );
+ FreeRTOS_debug_printf( ( "vDHCPProcess: acked %lxip\n", FreeRTOS_ntohl( EP_DHCPData.ulOfferedIPAddress ) ) );
/* DHCP completed. The IP address can now be used, and the
timer set to the lease timeout time. */
- *ipLOCAL_IP_ADDRESS_POINTER = xDHCPData.ulOfferedIPAddress;
+ *ipLOCAL_IP_ADDRESS_POINTER = EP_DHCPData.ulOfferedIPAddress;
/* Setting the 'local' broadcast address, something like
'192.168.1.255'. */
- xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
- xDHCPData.eDHCPState = eLeasedAddress;
+ EP_IPv4_SETTINGS.ulBroadcastAddress = ( EP_DHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
+ EP_DHCPData.eDHCPState = eLeasedAddress;
- iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );
+ iptraceDHCP_SUCCEDEED( EP_DHCPData.ulOfferedIPAddress );
/* DHCP failed, the default configured IP-address will be used
Now call vIPNetworkUpCalls() to send the network-up event and
start the ARP timer. */
- vIPNetworkUpCalls( );
+ vIPNetworkUpCalls();
/* Close socket to ensure packets don't queue on it. */
- vSocketClose( xDHCPData.xDHCPSocket );
- xDHCPData.xDHCPSocket = NULL;
+ prvCloseDHCPSocket();
- if( xDHCPData.ulLeaseTime == 0UL )
+ if( EP_DHCPData.ulLeaseTime == 0UL )
{
- xDHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME;
+ EP_DHCPData.ulLeaseTime = ( uint32_t ) dhcpDEFAULT_LEASE_TIME;
}
- else if( xDHCPData.ulLeaseTime < dhcpMINIMUM_LEASE_TIME )
+ else if( EP_DHCPData.ulLeaseTime < dhcpMINIMUM_LEASE_TIME )
{
- xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME;
+ EP_DHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME;
}
else
{
@@ -433,26 +432,26 @@ BaseType_t xGivingUp = pdFALSE;
/* Check for clashes. */
vARPSendGratuitous();
- vIPReloadDHCPTimer( xDHCPData.ulLeaseTime );
+ vIPReloadDHCPTimer( EP_DHCPData.ulLeaseTime );
}
else
{
/* Is it time to send another Discover? */
- if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
+ if( ( xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod )
{
/* Increase the time period, and if it has not got to the
point of giving up - send another request. */
- xDHCPData.xDHCPTxPeriod <<= 1;
+ EP_DHCPData.xDHCPTxPeriod <<= 1;
- if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
+ if( EP_DHCPData.xDHCPTxPeriod <= ( TickType_t ) ipconfigMAXIMUM_DISCOVER_TX_PERIOD )
{
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();
- prvSendDHCPRequest( );
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
+ prvSendDHCPRequest();
}
else
{
/* Give up, start again. */
- xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
+ EP_DHCPData.eDHCPState = eWaitingSendFirstDiscover;
}
}
}
@@ -460,18 +459,18 @@ BaseType_t xGivingUp = pdFALSE;
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
case eGetLinkLayerAddress:
- if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )
+ if( ( xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod )
{
if( xARPHadIPClash == pdFALSE )
{
/* ARP OK. proceed. */
- iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );
+ iptraceDHCP_SUCCEDEED( EP_DHCPData.ulOfferedIPAddress );
/* Auto-IP succeeded, the default configured IP-address will
be used. Now call vIPNetworkUpCalls() to send the
network-up event and start the ARP timer. */
- vIPNetworkUpCalls( );
- xDHCPData.eDHCPState = eNotUsingLeasedAddress;
+ vIPNetworkUpCalls();
+ EP_DHCPData.eDHCPState = eNotUsingLeasedAddress;
}
else
{
@@ -480,7 +479,7 @@ BaseType_t xGivingUp = pdFALSE;
/* Setting an IP address manually so set to not using leased
address mode. */
- xDHCPData.eDHCPState = eGetLinkLayerAddress;
+ EP_DHCPData.eDHCPState = eGetLinkLayerAddress;
}
}
break;
@@ -488,18 +487,27 @@ BaseType_t xGivingUp = pdFALSE;
case eLeasedAddress :
- /* Resend the request at the appropriate time to renew the lease. */
- prvCreateDHCPSocket();
-
- if( xDHCPData.xDHCPSocket != NULL )
+ if( FreeRTOS_IsNetworkUp() != 0 )
{
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();
- xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
- prvSendDHCPRequest( );
- xDHCPData.eDHCPState = eWaitingAcknowledge;
+ /* Resend the request at the appropriate time to renew the lease. */
+ prvCreateDHCPSocket();
+
+ if( xDHCPSocket != NULL )
+ {
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
+ EP_DHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
+ prvSendDHCPRequest();
+ EP_DHCPData.eDHCPState = eWaitingAcknowledge;
- /* From now on, we should be called more often */
- vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
+ /* From now on, we should be called more often */
+ vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );
+ }
+ }
+ else
+ {
+ /* See PR #53 on github/freertos/freertos */
+ FreeRTOS_printf( ( "DHCP: lease time finished but network is down\n" ) );
+ vIPReloadDHCPTimer( pdMS_TO_TICKS( 5000U ) );
}
break;
@@ -509,6 +517,7 @@ BaseType_t xGivingUp = pdFALSE;
break;
default:
+ /* Lint: all options are included. */
break;
}
@@ -516,7 +525,7 @@ BaseType_t xGivingUp = pdFALSE;
{
/* xGivingUp became true either because of a time-out, or because
xApplicationDHCPHook() returned another value than 'eDHCPContinue',
- meaning that the conversion is canceled from here. */
+ meaning that the conversion is cancelled from here. */
/* Revert to static IP address. */
taskENTER_CRITICAL();
@@ -526,21 +535,27 @@ BaseType_t xGivingUp = pdFALSE;
}
taskEXIT_CRITICAL();
- xDHCPData.eDHCPState = eNotUsingLeasedAddress;
+ EP_DHCPData.eDHCPState = eNotUsingLeasedAddress;
vIPSetDHCPTimerEnableState( pdFALSE );
/* DHCP failed, the default configured IP-address will be used. Now
call vIPNetworkUpCalls() to send the network-up event and start the ARP
timer. */
- vIPNetworkUpCalls( );
+ vIPNetworkUpCalls();
- /* Test if socket was indeed created. */
- if( xDHCPData.xDHCPSocket != NULL )
- {
- /* Close socket to ensure packets don't queue on it. */
- vSocketClose( xDHCPData.xDHCPSocket );
- xDHCPData.xDHCPSocket = NULL;
- }
+ prvCloseDHCPSocket();
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvCloseDHCPSocket( void )
+{
+ if( xDHCPSocket != NULL )
+ {
+ /* This modules runs from the IP-task. Use the internal
+ function 'vSocketClose()` to close the socket. */
+ ( void ) vSocketClose( xDHCPSocket );
+ xDHCPSocket = NULL;
}
}
/*-----------------------------------------------------------*/
@@ -552,31 +567,30 @@ BaseType_t xReturn;
TickType_t xTimeoutTime = ( TickType_t ) 0;
/* Create the socket, if it has not already been created. */
- if( xDHCPData.xDHCPSocket == NULL )
+ if( xDHCPSocket == NULL )
{
- xDHCPData.xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
- if( xDHCPData.xDHCPSocket != FREERTOS_INVALID_SOCKET )
+ xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
+ if( xDHCPSocket != FREERTOS_INVALID_SOCKET )
{
/* Ensure the Rx and Tx timeouts are zero as the DHCP executes in the
context of the IP task. */
- FreeRTOS_setsockopt( xDHCPData.xDHCPSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );
- FreeRTOS_setsockopt( xDHCPData.xDHCPSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );
+ ( void ) FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_RCVTIMEO, &( xTimeoutTime ), sizeof( TickType_t ) );
+ ( void ) FreeRTOS_setsockopt( xDHCPSocket, 0, FREERTOS_SO_SNDTIMEO, &( xTimeoutTime ), sizeof( TickType_t ) );
/* Bind to the standard DHCP client port. */
- xAddress.sin_port = ( uint16_t ) dhcpCLIENT_PORT;
- xReturn = vSocketBind( xDHCPData.xDHCPSocket, &xAddress, sizeof( xAddress ), pdFALSE );
+ xAddress.sin_port = ( uint16_t ) dhcpCLIENT_PORT_IPv4;
+ xReturn = vSocketBind( xDHCPSocket, &xAddress, sizeof( xAddress ), pdFALSE );
if( xReturn != 0 )
{
/* Binding failed, close the socket again. */
- vSocketClose( xDHCPData.xDHCPSocket );
- xDHCPData.xDHCPSocket = NULL;
+ prvCloseDHCPSocket();
}
}
else
{
/* Change to NULL for easier testing. */
- xDHCPData.xDHCPSocket = NULL;
+ xDHCPSocket = NULL;
}
}
}
@@ -589,12 +603,12 @@ static void prvInitialiseDHCP( void )
value chosen by the client. */
/* Check for random number generator API failure. */
- if( xApplicationGetRandomNumber( &( xDHCPData.ulTransactionId ) ) != pdFALSE )
+ if( xApplicationGetRandomNumber( &( EP_DHCPData.ulTransactionId ) ) != pdFALSE )
{
- xDHCPData.xUseBroadcast = 0;
- xDHCPData.ulOfferedIPAddress = 0UL;
- xDHCPData.ulDHCPServerAddress = 0UL;
- xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
+ EP_DHCPData.xUseBroadcast = 0;
+ EP_DHCPData.ulOfferedIPAddress = 0UL;
+ EP_DHCPData.ulDHCPServerAddress = 0UL;
+ EP_DHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;
/* Create the DHCP socket if it has not already been created. */
prvCreateDHCPSocket();
@@ -608,156 +622,182 @@ static void prvInitialiseDHCP( void )
}
/*-----------------------------------------------------------*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+_static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
{
-uint8_t *pucUDPPayload, *pucLastByte;
-struct freertos_sockaddr xClient;
-uint32_t xClientLength = sizeof( xClient );
+uint8_t *pucUDPPayload;
int32_t lBytes;
-DHCPMessage_t *pxDHCPMessage;
-uint8_t *pucByte, ucOptionCode, ucLength;
+const DHCPMessage_IPv4_t *pxDHCPMessage;
+const uint8_t *pucByte;
+uint8_t ucOptionCode;
uint32_t ulProcessed, ulParameter;
BaseType_t xReturn = pdFALSE;
-const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct DHCP message type must be present in the options. */
+const uint32_t ulMandatoryOptions = 2UL; /* DHCP server address, and the correct DHCP message type must be present in the options. */
- lBytes = FreeRTOS_recvfrom( xDHCPData.xDHCPSocket, ( void * ) &pucUDPPayload, 0ul, FREERTOS_ZERO_COPY, &xClient, &xClientLength );
+ /* Passing the address of a pointer (pucUDPPayload) because FREERTOS_ZERO_COPY is used. */
+ lBytes = FreeRTOS_recvfrom( xDHCPSocket, &pucUDPPayload, 0UL, FREERTOS_ZERO_COPY, NULL, NULL );
if( lBytes > 0 )
{
/* Map a DHCP structure onto the received data. */
- pxDHCPMessage = ( DHCPMessage_t * ) ( pucUDPPayload );
+ pxDHCPMessage = ipPOINTER_CAST( const DHCPMessage_IPv4_t *, pucUDPPayload );
/* Sanity check. */
- if( ( lBytes >= sizeof( DHCPMessage_t ) ) &&
- ( pxDHCPMessage->ulDHCPCookie == ( uint32_t ) dhcpCOOKIE ) &&
- ( pxDHCPMessage->ucOpcode == ( uint8_t ) dhcpREPLY_OPCODE ) &&
- ( pxDHCPMessage->ulTransactionID == FreeRTOS_htonl( xDHCPData.ulTransactionId ) ) )
+ if( lBytes < ( int32_t ) sizeof( DHCPMessage_IPv4_t ) )
+ {
+ /* Not enough bytes. */
+ }
+ else if( ( pxDHCPMessage->ulDHCPCookie != ( uint32_t ) dhcpCOOKIE ) ||
+ ( pxDHCPMessage->ucOpcode != ( uint8_t ) dhcpREPLY_OPCODE ) )
{
- if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ),
- ( void * ) ipLOCAL_MAC_ADDRESS,
- sizeof( MACAddress_t ) ) == 0 )
+ /* Invalid cookie or unexpected opcode. */
+ }
+ else if( ( pxDHCPMessage->ulTransactionID != FreeRTOS_htonl( EP_DHCPData.ulTransactionId ) ) )
+ {
+ /* Transaction ID does not match. */
+ }
+ else /* Looks like a valid DHCP response, with the same transaction ID. */
+ {
+ if( memcmp( pxDHCPMessage->ucClientHardwareAddress,
+ ipLOCAL_MAC_ADDRESS,
+ sizeof( MACAddress_t ) ) != 0 )
{
+ /* Target MAC address doesn't match. */
+ }
+ else
+ {
+ size_t uxIndex, uxPayloadDataLength, uxLength;
+
/* None of the essential options have been processed yet. */
- ulProcessed = 0ul;
+ ulProcessed = 0UL;
/* Walk through the options until the dhcpOPTION_END_BYTE byte
is found, taking care not to walk off the end of the options. */
- pucByte = &( pxDHCPMessage->ucFirstOptionByte );
- /* Maintain a pointer to the last valid byte (i.e. not the first
- invalid byte). */
- pucLastByte = pucUDPPayload + lBytes - 1;
+ pucByte = &( pucUDPPayload[ sizeof( DHCPMessage_IPv4_t ) ] );
+ uxIndex = 0;
+ uxPayloadDataLength = ( ( size_t ) lBytes ) - sizeof( DHCPMessage_IPv4_t );
- while( pucByte <= pucLastByte )
+ while( uxIndex < uxPayloadDataLength )
{
- ucOptionCode = pucByte[ 0 ];
- if( ucOptionCode == dhcpOPTION_END_BYTE )
+ ucOptionCode = pucByte[ uxIndex ];
+ if( ucOptionCode == ( uint8_t ) dhcpOPTION_END_BYTE )
{
/* Ready, the last byte has been seen. */
+ /* coverity[break_stmt] : Break statement terminating the loop */
break;
}
- if( ucOptionCode == dhcpZERO_PAD_OPTION_CODE )
+ if( ucOptionCode == ( uint8_t ) dhcpIPv4_ZERO_PAD_OPTION_CODE )
{
/* The value zero is used as a pad byte,
it is not followed by a length byte. */
- pucByte += 1;
+ uxIndex = uxIndex + 1U;
continue;
}
/* Stop if the response is malformed. */
- if( pucByte < pucLastByte )
+ if( ( uxIndex + 1U ) < uxPayloadDataLength )
{
- /* There are at least two bytes left. */
- ucLength = pucByte[ 1 ];
- pucByte += 2;
+ /* Fetch the length byte. */
+ uxLength = ( size_t ) pucByte[ uxIndex + 1U ];
+ uxIndex = uxIndex + 2U;
- if( pucByte + ucLength > pucLastByte )
+ if( !( ( ( uxIndex + uxLength ) - 1U ) < uxPayloadDataLength ) )
{
+ /* There are not as many bytes left as there should be. */
break;
}
}
else
{
+ /* The length byte is missing. */
break;
}
/* In most cases, a 4-byte network-endian parameter follows,
just get it once here and use later. */
- if( ucLength >= sizeof( ulParameter ) )
+ if( uxLength >= sizeof( ulParameter ) )
{
- memcpy( ( void * ) &( ulParameter ),
- ( void * ) pucByte,
- ( size_t ) sizeof( ulParameter ) );
+ ( void ) memcpy( &( ulParameter ),
+ &( pucByte[ uxIndex ] ),
+ ( size_t ) sizeof( ulParameter ) );
+ /* 'uxIndex' will be increased at the end of this loop. */
}
else
{
ulParameter = 0;
}
+ /* Confirm uxIndex is still a valid index after adjustments to uxIndex above */
+ if( !( uxIndex < uxPayloadDataLength ) )
+ {
+ break;
+ }
+
/* Option-specific handling. */
switch( ucOptionCode )
{
- case dhcpMESSAGE_TYPE_OPTION_CODE :
+ case dhcpIPv4_MESSAGE_TYPE_OPTION_CODE :
- if( *pucByte == ( uint8_t ) xExpectedMessageType )
+ if( pucByte[ uxIndex ] == ( uint8_t ) xExpectedMessageType )
{
/* The message type is the message type the
state machine is expecting. */
ulProcessed++;
}
- else if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
+ else
{
- if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )
+ if( pucByte[ uxIndex ] == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )
{
- /* Start again. */
- xDHCPData.eDHCPState = eWaitingSendFirstDiscover;
+ if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )
+ {
+ /* Start again. */
+ EP_DHCPData.eDHCPState = eWaitingSendFirstDiscover;
+ }
}
- }
- else
- {
- /* Don't process other message types. */
+ /* Stop processing further options. */
+ uxLength = 0;
}
break;
- case dhcpSUBNET_MASK_OPTION_CODE :
+ case dhcpIPv4_SUBNET_MASK_OPTION_CODE :
- if( ucLength == sizeof( uint32_t ) )
+ if( uxLength == sizeof( uint32_t ) )
{
- xNetworkAddressing.ulNetMask = ulParameter;
+ EP_IPv4_SETTINGS.ulNetMask = ulParameter;
}
break;
- case dhcpGATEWAY_OPTION_CODE :
-
- if( ucLength == sizeof( uint32_t ) )
+ case dhcpIPv4_GATEWAY_OPTION_CODE :
+ /* The DHCP server may send more than 1 gateway addresses. */
+ if( uxLength >= sizeof( uint32_t ) )
{
/* ulProcessed is not incremented in this case
because the gateway is not essential. */
- xNetworkAddressing.ulGatewayAddress = ulParameter;
+ EP_IPv4_SETTINGS.ulGatewayAddress = ulParameter;
}
break;
- case dhcpDNS_SERVER_OPTIONS_CODE :
+ case dhcpIPv4_DNS_SERVER_OPTIONS_CODE :
/* ulProcessed is not incremented in this case
because the DNS server is not essential. Only the
first DNS server address is taken. */
- xNetworkAddressing.ulDNSServerAddress = ulParameter;
+ EP_IPv4_SETTINGS.ulDNSServerAddress = ulParameter;
break;
- case dhcpSERVER_IP_ADDRESS_OPTION_CODE :
+ case dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE :
- if( ucLength == sizeof( uint32_t ) )
+ if( uxLength == sizeof( uint32_t ) )
{
if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_OFFER )
{
/* Offers state the replying server. */
ulProcessed++;
- xDHCPData.ulDHCPServerAddress = ulParameter;
+ EP_DHCPData.ulDHCPServerAddress = ulParameter;
}
else
{
/* The ack must come from the expected server. */
- if( xDHCPData.ulDHCPServerAddress == ulParameter )
+ if( EP_DHCPData.ulDHCPServerAddress == ulParameter )
{
ulProcessed++;
}
@@ -765,24 +805,22 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct
}
break;
- case dhcpLEASE_TIME_OPTION_CODE :
+ case dhcpIPv4_LEASE_TIME_OPTION_CODE :
- if( ucLength == sizeof( xDHCPData.ulLeaseTime ) )
+ if( uxLength == sizeof( EP_DHCPData.ulLeaseTime ) )
{
/* ulProcessed is not incremented in this case
because the lease time is not essential. */
/* The DHCP parameter is in seconds, convert
to host-endian format. */
- xDHCPData.ulLeaseTime = FreeRTOS_ntohl( ulParameter );
+ EP_DHCPData.ulLeaseTime = FreeRTOS_ntohl( ulParameter );
- /* Divide the lease time by two to ensure a
- renew request is sent before the lease actually
- expires. */
- xDHCPData.ulLeaseTime >>= 1UL;
+ /* Divide the lease time by two to ensure a renew
+ request is sent before the lease actually expires. */
+ EP_DHCPData.ulLeaseTime >>= 1UL;
- /* Multiply with configTICK_RATE_HZ to get clock
- ticks. */
- xDHCPData.ulLeaseTime = configTICK_RATE_HZ * xDHCPData.ulLeaseTime;
+ /* Multiply with configTICK_RATE_HZ to get clock ticks. */
+ EP_DHCPData.ulLeaseTime = ( uint32_t ) configTICK_RATE_HZ * ( uint32_t ) EP_DHCPData.ulLeaseTime;
}
break;
@@ -794,46 +832,48 @@ const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct
}
/* Jump over the data to find the next option code. */
- if( ucLength == 0u )
+ if( uxLength == 0U )
{
break;
}
- else
- {
- pucByte += ucLength;
- }
+ uxIndex = uxIndex + uxLength;
}
/* Were all the mandatory options received? */
if( ulProcessed >= ulMandatoryOptions )
{
/* HT:endian: used to be network order */
- xDHCPData.ulOfferedIPAddress = pxDHCPMessage->ulYourIPAddress_yiaddr;
- FreeRTOS_printf( ( "vDHCPProcess: offer %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );
+ EP_DHCPData.ulOfferedIPAddress = pxDHCPMessage->ulYourIPAddress_yiaddr;
+ FreeRTOS_printf( ( "vDHCPProcess: offer %lxip\n", FreeRTOS_ntohl( EP_DHCPData.ulOfferedIPAddress ) ) );
xReturn = pdPASS;
}
}
}
- FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayload );
- }
+ FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayload );
+ } /* if( lBytes > 0 ) */
return xReturn;
}
/*-----------------------------------------------------------*/
-static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, BaseType_t xOpcode, const uint8_t * const pucOptionsArray, size_t *pxOptionsArraySize )
+static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress,
+ BaseType_t xOpcode,
+ const uint8_t * const pucOptionsArray,
+ size_t *pxOptionsArraySize )
{
-DHCPMessage_t *pxDHCPMessage;
-size_t xRequiredBufferSize = sizeof( DHCPMessage_t ) + *pxOptionsArraySize;
+DHCPMessage_IPv4_t *pxDHCPMessage;
+size_t uxRequiredBufferSize = sizeof( DHCPMessage_IPv4_t ) + *pxOptionsArraySize;
+const NetworkBufferDescriptor_t *pxNetworkBuffer;
uint8_t *pucUDPPayloadBuffer;
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
const char *pucHostName = pcApplicationHostnameHook ();
- size_t xNameLength = strlen( pucHostName );
+ size_t uxNameLength = strlen( pucHostName );
uint8_t *pucPtr;
- xRequiredBufferSize += ( 2 + xNameLength );
+ /* Two extra bytes for option code and length. */
+ uxRequiredBufferSize += ( 2U + uxNameLength );
#endif
/* Get a buffer. This uses a maximum delay, but the delay will be capped
@@ -841,32 +881,36 @@ uint8_t *pucUDPPayloadBuffer;
be test. */
do
{
- } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xRequiredBufferSize, portMAX_DELAY ) ) == NULL );
+ /* Obtain a network buffer with the required amount of storage. */
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + uxRequiredBufferSize, portMAX_DELAY );
+ } while( pxNetworkBuffer == NULL );
- pxDHCPMessage = ( DHCPMessage_t * ) pucUDPPayloadBuffer;
+ /* Leave space for the UPD header. */
+ pucUDPPayloadBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
+ pxDHCPMessage = ipPOINTER_CAST( DHCPMessage_IPv4_t *, pucUDPPayloadBuffer );
/* Most fields need to be zero. */
- memset( ( void * ) pxDHCPMessage, 0x00, sizeof( DHCPMessage_t ) );
+ ( void ) memset( pxDHCPMessage, 0x00, sizeof( DHCPMessage_IPv4_t ) );
/* Create the message. */
pxDHCPMessage->ucOpcode = ( uint8_t ) xOpcode;
pxDHCPMessage->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET;
pxDHCPMessage->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH;
- pxDHCPMessage->ulTransactionID = FreeRTOS_htonl( xDHCPData.ulTransactionId );
+ pxDHCPMessage->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId );
pxDHCPMessage->ulDHCPCookie = ( uint32_t ) dhcpCOOKIE;
- if( xDHCPData.xUseBroadcast != pdFALSE )
+ if( EP_DHCPData.xUseBroadcast != pdFALSE )
{
pxDHCPMessage->usFlags = ( uint16_t ) dhcpBROADCAST;
}
else
{
- pxDHCPMessage->usFlags = 0u;
+ pxDHCPMessage->usFlags = 0U;
}
- memcpy( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress[ 0 ] ), ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
+ ( void ) memcpy( &( pxDHCPMessage->ucClientHardwareAddress[ 0 ] ), ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
/* Copy in the const part of the options options. */
- memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET ] ), ( void * ) pucOptionsArray, *pxOptionsArraySize );
+ ( void ) memcpy( &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET ] ), pucOptionsArray, *pxOptionsArraySize );
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
{
@@ -874,22 +918,22 @@ uint8_t *pucUDPPayloadBuffer;
it easier to lookup a device in a router's list of DHCP clients. */
/* Point to where the OPTION_END was stored to add data. */
- pucPtr = &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + ( *pxOptionsArraySize - 1 ) ] );
- pucPtr[ 0 ] = dhcpDNS_HOSTNAME_OPTIONS_CODE;
- pucPtr[ 1 ] = ( uint8_t ) xNameLength;
- memcpy( ( void *) ( pucPtr + 2 ), pucHostName, xNameLength );
- pucPtr[ 2 + xNameLength ] = dhcpOPTION_END_BYTE;
- *pxOptionsArraySize += ( 2 + xNameLength );
+ pucPtr = &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + ( *pxOptionsArraySize - 1U ) ] );
+ pucPtr[ 0U ] = dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE;
+ pucPtr[ 1U ] = ( uint8_t ) uxNameLength;
+ ( void ) memcpy( &( pucPtr[ 2U ] ), pucHostName, uxNameLength );
+ pucPtr[ 2U + uxNameLength ] = ( uint8_t ) dhcpOPTION_END_BYTE;
+ *pxOptionsArraySize += ( size_t ) ( 2U + uxNameLength );
}
#endif
/* Map in the client identifier. */
- memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpCLIENT_IDENTIFIER_OFFSET ] ),
- ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
+ ( void ) memcpy( &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpCLIENT_IDENTIFIER_OFFSET ] ),
+ ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
/* Set the addressing. */
pxAddress->sin_addr = ipBROADCAST_IP_ADDRESS;
- pxAddress->sin_port = ( uint16_t ) dhcpSERVER_PORT;
+ pxAddress->sin_port = ( uint16_t ) dhcpSERVER_PORT_IPv4;
return pucUDPPayloadBuffer;
}
@@ -904,29 +948,33 @@ static const uint8_t ucDHCPRequestOptions[] =
/* Do not change the ordering without also changing
dhcpCLIENT_IDENTIFIER_OFFSET, dhcpREQUESTED_IP_ADDRESS_OFFSET and
dhcpDHCP_SERVER_IP_ADDRESS_OFFSET. */
- dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */
- dhcpCLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */
- dhcpREQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */
- dhcpSERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */
+ dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST, /* Message type option. */
+ dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */
+ dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address being requested. */
+ dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0, /* The IP address of the DHCP server. */
dhcpOPTION_END_BYTE
};
-size_t xOptionsLength = sizeof( ucDHCPRequestOptions );
+size_t uxOptionsLength = sizeof( ucDHCPRequestOptions );
- pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, dhcpREQUEST_OPCODE, ucDHCPRequestOptions, &xOptionsLength );
+ pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress,
+ ( BaseType_t ) dhcpREQUEST_OPCODE,
+ ucDHCPRequestOptions,
+ &( uxOptionsLength ) );
/* Copy in the IP address being requested. */
- memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpREQUESTED_IP_ADDRESS_OFFSET ] ),
- ( void * ) &( xDHCPData.ulOfferedIPAddress ), sizeof( xDHCPData.ulOfferedIPAddress ) );
+ ( void ) memcpy( &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpREQUESTED_IP_ADDRESS_OFFSET ] ),
+ &( EP_DHCPData.ulOfferedIPAddress ),
+ sizeof( EP_DHCPData.ulOfferedIPAddress ) );
/* Copy in the address of the DHCP server being used. */
- memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ] ),
- ( void * ) &( xDHCPData.ulDHCPServerAddress ), sizeof( xDHCPData.ulDHCPServerAddress ) );
+ ( void ) memcpy( &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ] ),
+ &( EP_DHCPData.ulDHCPServerAddress ),
+ sizeof( EP_DHCPData.ulDHCPServerAddress ) );
- FreeRTOS_debug_printf( ( "vDHCPProcess: reply %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );
+ FreeRTOS_debug_printf( ( "vDHCPProcess: reply %lxip\n", FreeRTOS_ntohl( EP_DHCPData.ulOfferedIPAddress ) ) );
iptraceSENDING_DHCP_REQUEST();
- /* 'ucFirstOptionByte' is part of DHCP message struct, so subtract one byte. */
- if( FreeRTOS_sendto( xDHCPData.xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( DHCPMessage_t ) + xOptionsLength - 1 ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )
+ if( FreeRTOS_sendto( xDHCPSocket, pucUDPPayloadBuffer, sizeof( DHCPMessage_IPv4_t ) + uxOptionsLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )
{
/* The packet was not successfully queued for sending and must be
returned to the stack. */
@@ -937,25 +985,32 @@ size_t xOptionsLength = sizeof( ucDHCPRequestOptions );
static void prvSendDHCPDiscover( void )
{
-uint8_t *pucUDPPayloadBuffer;
+uint8_t const * pucUDPPayloadBuffer;
struct freertos_sockaddr xAddress;
static const uint8_t ucDHCPDiscoverOptions[] =
{
/* Do not change the ordering without also changing dhcpCLIENT_IDENTIFIER_OFFSET. */
- dhcpMESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */
- dhcpCLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */
- dhcpPARAMETER_REQUEST_OPTION_CODE, 3, dhcpSUBNET_MASK_OPTION_CODE, dhcpGATEWAY_OPTION_CODE, dhcpDNS_SERVER_OPTIONS_CODE, /* Parameter request option. */
+ dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER, /* Message type option. */
+ dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 7, 1, 0, 0, 0, 0, 0, 0, /* Client identifier. */
+ dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE, 3, dhcpIPv4_SUBNET_MASK_OPTION_CODE, dhcpIPv4_GATEWAY_OPTION_CODE, dhcpIPv4_DNS_SERVER_OPTIONS_CODE, /* Parameter request option. */
dhcpOPTION_END_BYTE
};
-size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions );
+size_t uxOptionsLength = sizeof( ucDHCPDiscoverOptions );
- pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, dhcpREQUEST_OPCODE, ucDHCPDiscoverOptions, &xOptionsLength );
+ pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress,
+ ( BaseType_t ) dhcpREQUEST_OPCODE,
+ ucDHCPDiscoverOptions,
+ &( uxOptionsLength ) );
FreeRTOS_debug_printf( ( "vDHCPProcess: discover\n" ) );
iptraceSENDING_DHCP_DISCOVER();
- /* 'ucFirstOptionByte' is part of DHCP message struct, so subtract one byte. */
- if( FreeRTOS_sendto( xDHCPData.xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( DHCPMessage_t ) + xOptionsLength - 1 ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )
+ if( FreeRTOS_sendto( xDHCPSocket,
+ pucUDPPayloadBuffer,
+ sizeof( DHCPMessage_IPv4_t ) + uxOptionsLength,
+ FREERTOS_ZERO_COPY,
+ &( xAddress ),
+ sizeof( xAddress ) ) == 0 )
{
/* The packet was not successfully queued for sending and must be
returned to the stack. */
@@ -973,41 +1028,36 @@ size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions );
/* After DHCP has failed to answer, prepare everything to start
trying-out LinkLayer IP-addresses, using the random method. */
- xDHCPData.xDHCPTxTime = xTaskGetTickCount();
+ EP_DHCPData.xDHCPTxTime = xTaskGetTickCount();
xApplicationGetRandomNumber( &( ulNumbers[ 0 ] ) );
xApplicationGetRandomNumber( &( ulNumbers[ 1 ] ) );
- ucLinkLayerIPAddress[ 0 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 0 ] % 0xFDu ); /* get value 1..254 for IP-address 3rd byte of IP address to try. */
- ucLinkLayerIPAddress[ 1 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 1 ] % 0xFDu ); /* get value 1..254 for IP-address 4th byte of IP address to try. */
+ ucLinkLayerIPAddress[ 0 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 0 ] % 0xFDU ); /* get value 1..254 for IP-address 3rd byte of IP address to try. */
+ ucLinkLayerIPAddress[ 1 ] = ( uint8_t )1 + ( uint8_t )( ulNumbers[ 1 ] % 0xFDU ); /* get value 1..254 for IP-address 4th byte of IP address to try. */
- xNetworkAddressing.ulGatewayAddress = FreeRTOS_htonl( 0xA9FE0203 );
+ EP_IPv4_SETTINGS.ulGatewayAddress = 0UL;
/* prepare xDHCPData with data to test. */
- xDHCPData.ulOfferedIPAddress =
+ EP_DHCPData.ulOfferedIPAddress =
FreeRTOS_inet_addr_quick( LINK_LAYER_ADDRESS_0, LINK_LAYER_ADDRESS_1, ucLinkLayerIPAddress[ 0 ], ucLinkLayerIPAddress[ 1 ] );
- xDHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME; /* don't care about lease time. just put anything. */
+ EP_DHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME; /* don't care about lease time. just put anything. */
- xNetworkAddressing.ulNetMask =
+ EP_IPv4_SETTINGS.ulNetMask =
FreeRTOS_inet_addr_quick( LINK_LAYER_NETMASK_0, LINK_LAYER_NETMASK_1, LINK_LAYER_NETMASK_2, LINK_LAYER_NETMASK_3 );
/* DHCP completed. The IP address can now be used, and the
timer set to the lease timeout time. */
- *ipLOCAL_IP_ADDRESS_POINTER = xDHCPData.ulOfferedIPAddress;
+ *( ipLOCAL_IP_ADDRESS_POINTER ) = EP_DHCPData.ulOfferedIPAddress;
/* Setting the 'local' broadcast address, something like 192.168.1.255' */
- xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
+ EP_IPv4_SETTINGS.ulBroadcastAddress = ( EP_DHCPData.ulOfferedIPAddress & EP_IPv4_SETTINGS.ulNetMask ) | ~EP_IPv4_SETTINGS.ulNetMask;
/* Close socket to ensure packets don't queue on it. not needed anymore as DHCP failed. but still need timer for ARP testing. */
- if( xDHCPData.xDHCPSocket != NULL )
- {
- /* Close socket to ensure packets don't queue on it. */
- vSocketClose( xDHCPData.xDHCPSocket );
- xDHCPData.xDHCPSocket = NULL;
- }
+ prvCloseDHCPSocket();
xApplicationGetRandomNumber( &( ulNumbers[ 0 ] ) );
- xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 3000ul + ( ulNumbers[ 0 ] & 0x3ffuL ) ); /* do ARP test every (3 + 0-1024mS) seconds. */
+ EP_DHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 3000UL + ( ulNumbers[ 0 ] & 0x3ffUL ) ); /* do ARP test every (3 + 0-1024mS) seconds. */
xARPHadIPClash = pdFALSE; /* reset flag that shows if have ARP clash. */
vARPSendGratuitous();
@@ -1017,5 +1067,3 @@ size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions );
/*-----------------------------------------------------------*/
#endif /* ipconfigUSE_DHCP != 0 */
-
-
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
index ad0c3a4a0..c63ba537a 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
@@ -25,12 +25,11 @@
/* Standard includes. */
#include <stdint.h>
+#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
-#include "queue.h"
-#include "list.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
@@ -39,66 +38,84 @@
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
+#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
-#include "IPTraceMacroDefaults.h"
+
+#include "FreeRTOSIPConfigDefaults.h"
/* Exclude the entire file if DNS is not enabled. */
#if( ipconfigUSE_DNS != 0 )
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
- #define dnsDNS_PORT 0x3500u
- #define dnsONE_QUESTION 0x0100u
- #define dnsOUTGOING_FLAGS 0x0001u /* Standard query. */
- #define dnsRX_FLAGS_MASK 0x0f80u /* The bits of interest in the flags field of incoming DNS messages. */
- #define dnsEXPECTED_RX_FLAGS 0x0080u /* Should be a response, without any errors. */
+ #define dnsDNS_PORT 0x3500U
+ #define dnsONE_QUESTION 0x0100U
+ #define dnsOUTGOING_FLAGS 0x0001U /* Standard query. */
+ #define dnsRX_FLAGS_MASK 0x0f80U /* The bits of interest in the flags field of incoming DNS messages. */
+ #define dnsEXPECTED_RX_FLAGS 0x0080U /* Should be a response, without any errors. */
#else
- #define dnsDNS_PORT 0x0035u
- #define dnsONE_QUESTION 0x0001u
- #define dnsOUTGOING_FLAGS 0x0100u /* Standard query. */
- #define dnsRX_FLAGS_MASK 0x800fu /* The bits of interest in the flags field of incoming DNS messages. */
- #define dnsEXPECTED_RX_FLAGS 0x8000u /* Should be a response, without any errors. */
+ #define dnsDNS_PORT 0x0035U
+ #define dnsONE_QUESTION 0x0001U
+ #define dnsOUTGOING_FLAGS 0x0100U /* Standard query. */
+ #define dnsRX_FLAGS_MASK 0x800fU /* The bits of interest in the flags field of incoming DNS messages. */
+ #define dnsEXPECTED_RX_FLAGS 0x8000U /* Should be a response, without any errors. */
#endif /* ipconfigBYTE_ORDER */
/* The maximum number of times a DNS request should be sent out if a response
is not received, before giving up. */
#ifndef ipconfigDNS_REQUEST_ATTEMPTS
- #define ipconfigDNS_REQUEST_ATTEMPTS 5
+ #define ipconfigDNS_REQUEST_ATTEMPTS 5
#endif
/* If the top two bits in the first character of a name field are set then the
name field is an offset to the string, rather than the string itself. */
-#define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 )
+#define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 )
/* NBNS flags. */
-#define dnsNBNS_FLAGS_RESPONSE 0x8000u
-#define dnsNBNS_FLAGS_OPCODE_MASK 0x7800u
-#define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000u
-#define dnsNBNS_FLAGS_OPCODE_REGISTRATION 0x2800u
+#if( ipconfigUSE_NBNS == 1 )
+ #define dnsNBNS_FLAGS_RESPONSE 0x8000U
+ #define dnsNBNS_FLAGS_OPCODE_MASK 0x7800U
+ #define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000U
+#endif /* ( ipconfigUSE_NBNS == 1 ) */
/* Host types. */
-#define dnsTYPE_A_HOST 0x01u
-#define dnsCLASS_IN 0x01u
+#define dnsTYPE_A_HOST 0x01U
+#define dnsCLASS_IN 0x01U
-/* LLMNR constants. */
-#define dnsLLMNR_TTL_VALUE 300000uL
-#define dnsLLMNR_FLAGS_IS_REPONSE 0x8000u
+#ifndef _lint
+ /* LLMNR constants. */
+ #define dnsLLMNR_TTL_VALUE 300000UL
+ #define dnsLLMNR_FLAGS_IS_REPONSE 0x8000U
+#endif /* _lint */
/* NBNS constants. */
-#define dnsNBNS_TTL_VALUE 3600uL /* 1 hour valid */
-#define dnsNBNS_TYPE_NET_BIOS 0x0020u
-#define dnsNBNS_CLASS_IN 0x01u
-#define dnsNBNS_NAME_FLAGS 0x6000u
-#define dnsNBNS_ENCODED_NAME_LENGTH 32
-
-/* If the queried NBNS name matches with the device's name,
-the query will be responded to with these flags: */
-#define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500u )
+#if( ipconfigUSE_NBNS != 0 )
+ #define dnsNBNS_TTL_VALUE 3600UL /* 1 hour valid */
+ #define dnsNBNS_TYPE_NET_BIOS 0x0020U
+ #define dnsNBNS_CLASS_IN 0x01U
+ #define dnsNBNS_NAME_FLAGS 0x6000U
+ #define dnsNBNS_ENCODED_NAME_LENGTH 32
+
+ /* If the queried NBNS name matches with the device's name,
+ the query will be responded to with these flags: */
+ #define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500U )
+#endif /* ( ipconfigUSE_NBNS != 0 ) */
/* Flag DNS parsing errors in situations where an IPv4 address is the return
type. */
-#define dnsPARSE_ERROR 0uL
+#define dnsPARSE_ERROR 0UL
+
+#ifndef _lint
+ #if( ipconfigUSE_DNS_CACHE == 0 )
+ #if( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY != 1 )
+ #error When DNS caching is disabled, please make ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY equal to 1.
+ #endif
+ #endif
+#endif
+
+/* Define the ASCII value of '.' (Period/Full-stop). */
+#define ASCII_BASELINE_DOT 46U
/*
* Create a socket and bind it to the standard DNS port number. Return the
@@ -109,26 +126,39 @@ static Socket_t prvCreateDNSSocket( void );
/*
* Create the DNS message in the zero copy buffer passed in the first parameter.
*/
-static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+_static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
const char *pcHostName,
TickType_t uxIdentifier );
/*
* Simple routine that jumps over the NAME field of a resource record.
+ * It returns the number of bytes read.
*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
- size_t uxSourceLen );
+_static size_t prvSkipNameField( const uint8_t *pucByte,
+ size_t uxLength );
/*
* Process a response packet from a DNS server.
* The parameter 'xExpected' indicates whether the identifier in the reply
* was expected, and thus if the DNS cache may be updated with the reply.
*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+_static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected );
/*
+ * Check if hostname is already known. If not, call prvGetHostByName() to send a DNS request.
+ */
+#if( ipconfigDNS_USE_CALLBACKS == 1 )
+ static uint32_t prvPrepareLookup( const char *pcHostName,
+ FOnDNSEvent pCallback,
+ void *pvSearchID,
+ TickType_t uxTimeout );
+#else
+ static uint32_t prvPrepareLookup( const char *pcHostName );
+#endif
+
+/*
* Prepare and send a message to a DNS server. 'uxReadTimeOut_ticks' will be passed as
* zero, in case the user has supplied a call-back function.
*/
@@ -136,6 +166,20 @@ static uint32_t prvGetHostByName( const char *pcHostName,
TickType_t uxIdentifier,
TickType_t uxReadTimeOut_ticks );
+#if( ipconfigDNS_USE_CALLBACKS != 0 )
+ static void vDNSSetCallBack( const char *pcHostName,
+ void *pvSearchID,
+ FOnDNSEvent pCallbackFunction,
+ TickType_t uxTimeout,
+ TickType_t uxIdentifier );
+#endif /* ipconfigDNS_USE_CALLBACKS */
+
+#if( ipconfigDNS_USE_CALLBACKS != 0 )
+ static BaseType_t xDNSDoCallback( TickType_t uxIdentifier,
+ const char *pcName,
+ uint32_t ulIPAddress );
+#endif /* ipconfigDNS_USE_CALLBACKS */
+
/*
* The NBNS and the LLMNR protocol share this reply function.
*/
@@ -145,38 +189,43 @@ static uint32_t prvGetHostByName( const char *pcHostName,
#endif
#if( ipconfigUSE_NBNS == 1 )
- static portINLINE void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer,
+ static portINLINE void prvTreatNBNS( uint8_t *pucPayload,
size_t uxBufferLength,
uint32_t ulIPAddress );
#endif /* ipconfigUSE_NBNS */
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
- size_t uxSourceLen,
- char *pcName,
- size_t uxLen );
-#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
+ _static size_t prvReadNameField( const uint8_t *pucByte,
+ size_t uxRemainingBytes,
+ char *pcName,
+ size_t uxDestLen );
+#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
#if( ipconfigUSE_DNS_CACHE == 1 )
- static void prvProcessDNSCache( const char *pcName,
- uint32_t *pulIP,
- uint32_t ulTTL,
- BaseType_t xLookUp );
+ static BaseType_t prvProcessDNSCache( const char *pcName,
+ uint32_t *pulIP,
+ uint32_t ulTTL,
+ BaseType_t xLookUp );
typedef struct xDNS_CACHE_TABLE_ROW
{
- uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */
+ uint32_t ulIPAddresses[ ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ]; /* The IP address(es) of an ARP cache entry. */
char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /* The name of the host */
uint32_t ulTTL; /* Time-to-Live (in seconds) from the DNS server. */
uint32_t ulTimeWhenAddedInSeconds;
+#if( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 )
+ uint8_t ucNumIPAddresses;
+ uint8_t ucCurrentIPAddress;
+#endif
} DNSCacheRow_t;
static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ];
- void FreeRTOS_dnsclear()
+ /* Utility function: Clear DNS cache by calling this function. */
+ void FreeRTOS_dnsclear( void )
{
- memset( xDNSCache, 0x0, sizeof( xDNSCache ) );
+ ( void ) memset( xDNSCache, 0x0, sizeof( xDNSCache ) );
}
#endif /* ipconfigUSE_DNS_CACHE == 1 */
@@ -186,6 +235,8 @@ static uint32_t prvGetHostByName( const char *pcHostName,
/*-----------------------------------------------------------*/
+/* Below #include just tells the compiler to pack the structure.
+ * It is included in to make the code more readable */
#include "pack_struct_start.h"
struct xDNSMessage
{
@@ -282,9 +333,9 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
#if( ipconfigUSE_DNS_CACHE == 1 )
uint32_t FreeRTOS_dnslookup( const char *pcHostName )
{
- uint32_t ulIPAddress = 0uL;
+ uint32_t ulIPAddress = 0UL;
- prvProcessDNSCache( pcHostName, &ulIPAddress, 0, pdTRUE );
+ ( void ) prvProcessDNSCache( pcHostName, &ulIPAddress, 0, pdTRUE );
return ulIPAddress;
}
#endif /* ipconfigUSE_DNS_CACHE == 1 */
@@ -307,12 +358,11 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
/* Define FreeRTOS_gethostbyname() as a normal blocking call. */
uint32_t FreeRTOS_gethostbyname( const char *pcHostName )
{
- return FreeRTOS_gethostbyname_a( pcHostName, ( FOnDNSEvent ) NULL, ( void * ) NULL, 0 );
+ return FreeRTOS_gethostbyname_a( pcHostName, NULL, ( void * ) NULL, 0 );
}
/*-----------------------------------------------------------*/
/* Initialise the list of call-back structures. */
- void vDNSInitialise( void );
void vDNSInitialise( void )
{
vListInitialise( &xCallbackList );
@@ -324,39 +374,40 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
As soon as the list hase become empty, the DNS timer will be stopped
In case pvSearchID is supplied, the user wants to cancel a DNS request
*/
- void vDNSCheckCallBack( void *pvSearchID );
void vDNSCheckCallBack( void *pvSearchID )
{
- const ListItem_t *pxIterator;
- const MiniListItem_t * xEnd = ( const MiniListItem_t * ) listGET_END_MARKER( &xCallbackList );
+ const ListItem_t * pxIterator;
+ const ListItem_t * xEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xCallbackList ) );
vTaskSuspendAll();
{
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( xEnd );
- pxIterator != ( const ListItem_t * ) xEnd;
+ pxIterator != xEnd;
)
{
- DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
-
+ DNSCallback_t *pxCallback = ipPOINTER_CAST( DNSCallback_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* Move to the next item because we might remove this item */
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
-
if( ( pvSearchID != NULL ) && ( pvSearchID == pxCallback->pvSearchID ) )
{
- uxListRemove( &pxCallback->xListItem );
+ ( void ) uxListRemove( &( pxCallback->xListItem ) );
vPortFree( pxCallback );
}
else if( xTaskCheckForTimeOut( &pxCallback->uxTimeoutState, &pxCallback->uxRemaningTime ) != pdFALSE )
{
pxCallback->pCallbackFunction( pxCallback->pcName, pxCallback->pvSearchID, 0 );
- uxListRemove( &pxCallback->xListItem );
- vPortFree( ( void * ) pxCallback );
+ ( void ) uxListRemove( &( pxCallback->xListItem ) );
+ vPortFree( pxCallback );
+ }
+ else
+ {
+ /* This call-back is still waiting for a reply or a time-out. */
}
}
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
- if( listLIST_IS_EMPTY( &xCallbackList ) )
+ if( listLIST_IS_EMPTY( &xCallbackList ) != pdFALSE )
{
vIPSetDnsTimerEnableState( pdFALSE );
}
@@ -376,39 +427,34 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
void *pvSearchID,
FOnDNSEvent pCallbackFunction,
TickType_t uxTimeout,
- TickType_t uxIdentifier );
- static void vDNSSetCallBack( const char *pcHostName,
- void *pvSearchID,
- FOnDNSEvent pCallbackFunction,
- TickType_t uxTimeout,
TickType_t uxIdentifier )
{
size_t lLength = strlen( pcHostName );
- DNSCallback_t *pxCallback = ( DNSCallback_t * ) pvPortMalloc( sizeof( *pxCallback ) + lLength );
+ DNSCallback_t *pxCallback = ipPOINTER_CAST( DNSCallback_t *, pvPortMalloc( sizeof( *pxCallback ) + lLength ) );
/* Translate from ms to number of clock ticks. */
uxTimeout /= portTICK_PERIOD_MS;
if( pxCallback != NULL )
{
- if( listLIST_IS_EMPTY( &xCallbackList ) )
+ if( listLIST_IS_EMPTY( &xCallbackList ) != pdFALSE )
{
/* This is the first one, start the DNS timer to check for timeouts */
vIPReloadDNSTimer( FreeRTOS_min_uint32( 1000U, uxTimeout ) );
}
- strcpy( pxCallback->pcName, pcHostName );
+ ( void ) strcpy( pxCallback->pcName, pcHostName );
pxCallback->pCallbackFunction = pCallbackFunction;
pxCallback->pvSearchID = pvSearchID;
pxCallback->uxRemaningTime = uxTimeout;
vTaskSetTimeOutState( &pxCallback->uxTimeoutState );
- listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ( void * ) pxCallback );
+ listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ipPOINTER_CAST( void *, pxCallback ) );
listSET_LIST_ITEM_VALUE( &( pxCallback->xListItem ), uxIdentifier );
vTaskSuspendAll();
{
vListInsertEnd( &xCallbackList, &pxCallback->xListItem );
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
}
}
/*-----------------------------------------------------------*/
@@ -417,14 +463,11 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
call the handler. Returns pdTRUE if uxIdentifier was recognised. */
static BaseType_t xDNSDoCallback( TickType_t uxIdentifier,
const char *pcName,
- uint32_t ulIPAddress );
- static BaseType_t xDNSDoCallback( TickType_t uxIdentifier,
- const char *pcName,
uint32_t ulIPAddress )
{
BaseType_t xResult = pdFALSE;
- const ListItem_t *pxIterator;
- const MiniListItem_t * xEnd = ( const MiniListItem_t * ) listGET_END_MARKER( &xCallbackList );
+ const ListItem_t * pxIterator;
+ const ListItem_t * xEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xCallbackList ) );
vTaskSuspendAll();
{
@@ -432,16 +475,15 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
pxIterator != ( const ListItem_t * ) xEnd;
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
{
- /* The cast will take away the 'configLIST_VOLATILE' */
- if( uxIdentifier == ( TickType_t ) listGET_LIST_ITEM_VALUE( pxIterator ) )
+ if( listGET_LIST_ITEM_VALUE( pxIterator ) == uxIdentifier )
{
- DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ DNSCallback_t *pxCallback = ipPOINTER_CAST( DNSCallback_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
pxCallback->pCallbackFunction( pcName, pxCallback->pvSearchID, ulIPAddress );
- uxListRemove( &pxCallback->xListItem );
+ ( void ) uxListRemove( &pxCallback->xListItem );
vPortFree( pxCallback );
- if( listLIST_IS_EMPTY( &xCallbackList ) )
+ if( listLIST_IS_EMPTY( &xCallbackList ) != pdFALSE )
{
/* The list of outstanding requests is empty. No need for periodic polling. */
vIPSetDnsTimerEnableState( pdFALSE );
@@ -452,7 +494,7 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
}
}
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
return xResult;
}
@@ -461,19 +503,61 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
#if( ipconfigDNS_USE_CALLBACKS == 0 )
uint32_t FreeRTOS_gethostbyname( const char *pcHostName )
+ {
+ return prvPrepareLookup( pcHostName );
+ }
#else
uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName,
FOnDNSEvent pCallback,
void *pvSearchID,
TickType_t uxTimeout )
+ {
+ return prvPrepareLookup( pcHostName, pCallback, pvSearchID, uxTimeout );
+ }
+#endif
+
+#if( ipconfigDNS_USE_CALLBACKS == 1 )
+ static uint32_t prvPrepareLookup( const char *pcHostName,
+ FOnDNSEvent pCallback,
+ void *pvSearchID,
+ TickType_t uxTimeout )
+#else
+ static uint32_t prvPrepareLookup( const char *pcHostName )
#endif
{
-uint32_t ulIPAddress = 0uL;
+uint32_t ulIPAddress = 0UL;
TickType_t uxReadTimeOut_ticks = ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS;
-TickType_t uxIdentifier = 0u;
+/* Generate a unique identifier for this query. Keep it in a local variable
+ as gethostbyname() may be called from different threads */
BaseType_t xHasRandom = pdFALSE;
+TickType_t uxIdentifier = 0U;
+#if( ipconfigUSE_DNS_CACHE != 0 )
+ BaseType_t xLengthOk = pdFALSE;
+#endif
+
+ #if( ipconfigUSE_DNS_CACHE != 0 )
+ {
+ if( pcHostName != NULL )
+ {
+ size_t xLength = strlen( pcHostName ) + 1U;
+ if( xLength <= ipconfigDNS_CACHE_NAME_LENGTH )
+ {
+ /* The name is not too long. */
+ xLengthOk = pdTRUE;
+ }
+ else
+ {
+ FreeRTOS_printf( ( "prvPrepareLookup: name is too long ( %lu > %lu )\n",
+ ( unsigned long ) xLength,
+ ( unsigned long ) ipconfigDNS_CACHE_NAME_LENGTH ) );
+ }
+ }
+ }
+ if( ( pcHostName != NULL ) && ( xLengthOk != pdFALSE ) )
+ #else
if( pcHostName != NULL )
+ #endif /* ( ipconfigUSE_DNS_CACHE != 0 ) */
{
/* If the supplied hostname is IP address, convert it to uint32_t
and return. */
@@ -487,11 +571,11 @@ BaseType_t xHasRandom = pdFALSE;
request. */
#if( ipconfigUSE_DNS_CACHE == 1 )
{
- if( ulIPAddress == 0uL )
+ if( ulIPAddress == 0UL )
{
ulIPAddress = FreeRTOS_dnslookup( pcHostName );
- if( ulIPAddress != 0 )
+ if( ulIPAddress != 0UL )
{
FreeRTOS_debug_printf( ( "FreeRTOS_gethostbyname: found '%s' in cache: %lxip\n", pcHostName, ulIPAddress ) );
}
@@ -504,26 +588,25 @@ BaseType_t xHasRandom = pdFALSE;
#endif /* ipconfigUSE_DNS_CACHE == 1 */
/* Generate a unique identifier. */
- if( ulIPAddress == 0uL )
+ if( ulIPAddress == 0UL )
{
uint32_t ulNumber;
xHasRandom = xApplicationGetRandomNumber( &( ulNumber ) );
/* DNS identifiers are 16-bit. */
- uxIdentifier = ( TickType_t ) ( ulNumber & 0xffffu );
- /* ipconfigRAND32() may not return a non-zero value. */
+ uxIdentifier = ( TickType_t ) ( ulNumber & 0xffffU );
}
#if( ipconfigDNS_USE_CALLBACKS == 1 )
{
if( pCallback != NULL )
{
- if( ulIPAddress == 0uL )
+ if( ulIPAddress == 0UL )
{
/* The user has provided a callback function, so do not block on recvfrom() */
if( xHasRandom != pdFALSE )
{
- uxReadTimeOut_ticks = 0u;
+ uxReadTimeOut_ticks = 0U;
vDNSSetCallBack( pcHostName, pvSearchID, pCallback, uxTimeout, uxIdentifier );
}
}
@@ -536,7 +619,7 @@ BaseType_t xHasRandom = pdFALSE;
}
#endif /* if ( ipconfigDNS_USE_CALLBACKS == 1 ) */
- if( ( ulIPAddress == 0uL ) && ( xHasRandom != pdFALSE ) )
+ if( ( ulIPAddress == 0UL ) && ( xHasRandom != pdFALSE ) )
{
ulIPAddress = prvGetHostByName( pcHostName, uxIdentifier, uxReadTimeOut_ticks );
}
@@ -551,8 +634,7 @@ static uint32_t prvGetHostByName( const char *pcHostName,
{
struct freertos_sockaddr xAddress;
Socket_t xDNSSocket;
-uint32_t ulIPAddress = 0uL;
-uint8_t *pucUDPPayloadBuffer;
+uint32_t ulIPAddress = 0UL;
uint32_t ulAddressLength = sizeof( struct freertos_sockaddr );
BaseType_t xAttempt;
int32_t lBytes;
@@ -569,7 +651,7 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
{
const char *pucPtr;
- for( pucPtr = pcHostName; *pucPtr; pucPtr++ )
+ for( pucPtr = pcHostName; *pucPtr != ( char ) 0; pucPtr++ )
{
if( *pucPtr == '.' )
{
@@ -582,21 +664,35 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
/* Two is added at the end for the count of characters in the first
subdomain part and the string end byte. */
- uxExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u;
+ uxExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2U;
xDNSSocket = prvCreateDNSSocket();
if( xDNSSocket != NULL )
{
- FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &uxWriteTimeOut_ticks, sizeof( TickType_t ) );
- FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &uxReadTimeOut_ticks, sizeof( TickType_t ) );
+ /* Ideally we should check for the return value. But since we are passing
+ correct parameters, and xDNSSocket is != NULL, the return value is
+ going to be '0' i.e. success. Thus, return value is discarded */
+ ( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, &( uxWriteTimeOut_ticks ), sizeof( TickType_t ) );
+ ( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, &( uxReadTimeOut_ticks ), sizeof( TickType_t ) );
for( xAttempt = 0; xAttempt < ipconfigDNS_REQUEST_ATTEMPTS; xAttempt++ )
{
+ size_t uxHeaderBytes;
+ NetworkBufferDescriptor_t *pxNetworkBuffer;
+ uint8_t *pucUDPPayloadBuffer = NULL, *pucReceiveBuffer;
+
/* Get a buffer. This uses a maximum delay, but the delay will be
capped to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value
still needs to be tested. */
- pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( uxExpectedPayloadLength, portMAX_DELAY );
+
+ uxHeaderBytes = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER;
+
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxHeaderBytes + uxExpectedPayloadLength, 0UL );
+ if( pxNetworkBuffer != NULL )
+ {
+ pucUDPPayloadBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderBytes ] );
+ }
if( pucUDPPayloadBuffer != NULL )
{
@@ -613,9 +709,10 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
if( bHasDot == pdFALSE )
{
/* Use LLMNR addressing. */
- ( ( DNSMessage_t * ) pucUDPPayloadBuffer )->usFlags = 0;
+ ( ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer ) )->usFlags = 0;
xAddress.sin_addr = ipLLMNR_IP_ADDR; /* Is in network byte order. */
- xAddress.sin_port = FreeRTOS_ntohs( ipLLMNR_PORT );
+ xAddress.sin_port = ipLLMNR_PORT;
+ xAddress.sin_port = FreeRTOS_ntohs( xAddress.sin_port );
}
else
#endif
@@ -625,17 +722,17 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
xAddress.sin_port = dnsDNS_PORT;
}
- ulIPAddress = 0uL;
+ ulIPAddress = 0UL;
if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, uxPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 )
{
/* Wait for the reply. */
- lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength );
+ lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucReceiveBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength );
if( lBytes > 0 )
{
BaseType_t xExpected;
- DNSMessage_t *pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;
+ const DNSMessage_t *pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucReceiveBuffer );
/* See if the identifiers match. */
if( uxIdentifier == ( TickType_t ) pxDNSMessageHeader->usIdentifier )
@@ -655,17 +752,18 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
if( xExpected != pdFALSE )
#endif /* ipconfigDNS_USE_CALLBACKS == 0 */
{
- ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, ( size_t ) lBytes, xExpected );
+ ulIPAddress = prvParseDNSReply( pucReceiveBuffer, ( size_t ) lBytes, xExpected );
}
/* Finished with the buffer. The zero copy interface
is being used, so the buffer must be freed by the
task. */
- FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
+ FreeRTOS_ReleaseUDPPayloadBuffer( pucReceiveBuffer );
- if( ulIPAddress != 0uL )
+ if( ulIPAddress != 0UL )
{
/* All done. */
+ /* coverity[break_stmt] : Break statement terminating the loop */
break;
}
}
@@ -674,11 +772,11 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
{
/* The message was not sent so the stack will not be
releasing the zero copy - it must be released here. */
- FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
}
- if( uxReadTimeOut_ticks == 0u )
+ if( uxReadTimeOut_ticks == 0U )
{
/* This DNS lookup is asynchronous, using a call-back:
send the request only once. */
@@ -687,20 +785,20 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
}
/* Finished with the socket. */
- FreeRTOS_closesocket( xDNSSocket );
+ ( void ) FreeRTOS_closesocket( xDNSSocket );
}
return ulIPAddress;
}
/*-----------------------------------------------------------*/
-static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+_static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
const char *pcHostName,
TickType_t uxIdentifier )
{
DNSMessage_t *pxDNSMessageHeader;
uint8_t *pucStart, *pucByte;
-DNSTail_t *pxTail;
+DNSTail_t const * pxTail;
static const DNSMessage_t xDefaultPartDNSHeader =
{
0, /* The identifier will be overwritten. */
@@ -711,26 +809,28 @@ static const DNSMessage_t xDefaultPartDNSHeader =
0 /* No additional authorities. */
};
- /* Copy in the const part of the header. */
- memcpy( ( void * ) pucUDPPayloadBuffer, ( void * ) &xDefaultPartDNSHeader, sizeof( xDefaultPartDNSHeader ) );
+ /* Copy in the const part of the header. Intentionally using different
+ * pointers with memcpy() to put the information in to correct place. */
+ ( void ) memcpy( pucUDPPayloadBuffer, &( xDefaultPartDNSHeader ), sizeof( xDefaultPartDNSHeader ) );
- /* Write in a unique identifier. */
- pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;
+ /* Write in a unique identifier. Cast the Payload Buffer to DNSMessage_t
+ * to easily access fields of the DNS Message. */
+ pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
pxDNSMessageHeader->usIdentifier = ( uint16_t ) uxIdentifier;
/* Create the resource record at the end of the header. First
find the end of the header. */
- pucStart = pucUDPPayloadBuffer + sizeof( xDefaultPartDNSHeader );
+ pucStart = &( pucUDPPayloadBuffer[ sizeof( xDefaultPartDNSHeader ) ] );
/* Leave a gap for the first length bytes. */
- pucByte = pucStart + 1;
+ pucByte = &( pucStart[ 1 ] );
/* Copy in the host name. */
- strcpy( ( char * ) pucByte, pcHostName );
+ ( void ) strcpy( ( char * ) pucByte, pcHostName );
/* Mark the end of the string. */
- pucByte += strlen( pcHostName );
- *pucByte = 0x00u;
+ pucByte = &( pucByte[ strlen( pcHostName ) ] );
+ *pucByte = 0x00U;
/* Walk the string to replace the '.' characters with byte counts.
pucStart holds the address of the byte count. Walking the string
@@ -741,7 +841,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
{
pucByte++;
- while( ( *pucByte != 0x00 ) && ( *pucByte != '.' ) )
+ while( ( *pucByte != ( uint8_t ) 0U ) && ( *pucByte != ( uint8_t ) ASCII_BASELINE_DOT ) )
{
pucByte++;
}
@@ -752,159 +852,183 @@ static const DNSMessage_t xDefaultPartDNSHeader =
( *pucStart )--;
pucStart = pucByte;
- } while( *pucByte != 0x00 );
+ } while( *pucByte != ( uint8_t ) 0U );
- /* Finish off the record. */
+ /* Finish off the record. Cast the record onto DNSTail_t stucture to easily
+ * access the fields of the DNS Message. */
+ pxTail = ipPOINTER_CAST(DNSTail_t *, &( pucByte[ 1 ] ) );
- pxTail = ( DNSTail_t * ) ( pucByte + 1 );
-
- vSetField16( pxTail, DNSTail_t, usType, dnsTYPE_A_HOST ); /* Type A: host */
- vSetField16( pxTail, DNSTail_t, usClass, dnsCLASS_IN ); /* 1: Class IN */
+ #if defined( _lint ) || defined( __COVERITY__ )
+ ( void ) pxTail;
+ #else
+ vSetField16( pxTail, DNSTail_t, usType, dnsTYPE_A_HOST );
+ vSetField16( pxTail, DNSTail_t, usClass, dnsCLASS_IN );
+ #endif
/* Return the total size of the generated message, which is the space from
the last written byte to the beginning of the buffer. */
- return ( ( uint32_t ) pucByte - ( uint32_t ) pucUDPPayloadBuffer + 1 ) + sizeof( *pxTail );
+ return ( ( uint32_t ) pucByte - ( uint32_t ) pucUDPPayloadBuffer + 1U ) + sizeof( DNSTail_t );
}
/*-----------------------------------------------------------*/
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
- size_t uxSourceLen,
- char *pcName,
- size_t uxDestLen )
+ _static size_t prvReadNameField( const uint8_t *pucByte,
+ size_t uxRemainingBytes,
+ char *pcName,
+ size_t uxDestLen )
{
- size_t uxNameLen = 0;
- BaseType_t xCount;
+ size_t uxNameLen = 0U;
+ size_t uxIndex = 0U;
+ size_t uxSourceLen = uxRemainingBytes;
+
+ /* uxCount gets the valus from pucByte and counts down to 0.
+ No need to have a different type than that of pucByte */
+ size_t uxCount;
- if( 0 == uxSourceLen )
+ if( uxSourceLen == ( size_t ) 0U )
{
- return NULL;
+ /* Return 0 value in case of error. */
+ uxIndex = 0U;
}
-
/* Determine if the name is the fully coded name, or an offset to the name
elsewhere in the message. */
- if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )
+ else if( ( pucByte[ uxIndex ] & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )
{
/* Jump over the two byte offset. */
if( uxSourceLen > sizeof( uint16_t ) )
{
- pucByte += sizeof( uint16_t );
+ uxIndex += sizeof( uint16_t );
}
else
{
- pucByte = NULL;
+ uxIndex = 0U;
}
}
else
{
- /* pucByte points to the full name. Walk over the string. */
- while( ( NULL != pucByte ) && ( *pucByte != 0x00u ) && ( uxSourceLen > 1u ) )
+ /* 'uxIndex' points to the full name. Walk over the string. */
+ while( ( uxIndex < uxSourceLen ) && ( pucByte[ uxIndex ] != ( uint8_t )0x00U ) )
{
/* If this is not the first time through the loop, then add a
separator in the output. */
- if( ( uxNameLen > 0 ) && ( uxNameLen < ( uxDestLen - 1u ) ) )
+ if( ( uxNameLen > 0U ) )
{
- pcName[ uxNameLen++ ] = '.';
+ if( uxNameLen >= uxDestLen )
+ {
+ uxIndex = 0U;
+ /* coverity[break_stmt] : Break statement terminating the loop */
+ break;
+ }
+ pcName[ uxNameLen ] = '.';
+ uxNameLen++;
}
/* Process the first/next sub-string. */
- for( xCount = *( pucByte++ ), uxSourceLen--;
- xCount-- && uxSourceLen > 1u;
- pucByte++, uxSourceLen-- )
+ uxCount = ( size_t ) pucByte[ uxIndex ];
+ uxIndex++;
+ if( ( uxIndex + uxCount ) > uxSourceLen )
{
- if( uxNameLen < uxDestLen - 1u )
- {
- pcName[ uxNameLen++ ] = *( ( char * ) pucByte );
- }
- else
+ uxIndex = 0U;
+ break;
+ }
+
+ while( ( uxCount-- != 0U ) && ( uxIndex < uxSourceLen ) )
+ {
+ if( uxNameLen >= uxDestLen )
{
- /* DNS name is too big for the provided buffer. */
- pucByte = NULL;
+ uxIndex = 0U;
break;
+ /* break out of inner loop here
+ break out of outer loop at the test uxNameLen >= uxDestLen. */
}
+ pcName[ uxNameLen ] = ( char ) pucByte[ uxIndex ];
+ uxNameLen++;
+ uxIndex++;
}
}
/* Confirm that a fully formed name was found. */
- if( NULL != pucByte )
+ if( uxIndex > 0U )
{
- if( 0x00 == *pucByte )
+ if( ( uxNameLen < uxDestLen ) && ( uxIndex < uxSourceLen ) && ( pucByte[ uxIndex ] == 0U ) )
{
- pucByte++;
- uxSourceLen--;
- pcName[ uxNameLen++ ] = '\0';
+ pcName[ uxNameLen ] = '\0';
+ uxIndex++;
}
else
{
- pucByte = NULL;
+ uxIndex = 0U;
}
}
}
- return pucByte;
+ return uxIndex;
}
-#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
+#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
/*-----------------------------------------------------------*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
- size_t uxSourceLen )
+_static size_t prvSkipNameField( const uint8_t *pucByte,
+ size_t uxLength )
{
size_t uxChunkLength;
+size_t uxSourceLenCpy = uxLength;
+size_t uxIndex = 0U;
- if( 0u == uxSourceLen )
+ if( uxSourceLenCpy == 0U )
{
- return NULL;
+ uxIndex = 0U;
}
-
/* Determine if the name is the fully coded name, or an offset to the name
elsewhere in the message. */
- if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )
+ else if( ( pucByte[ uxIndex ] & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )
{
/* Jump over the two byte offset. */
- if( uxSourceLen > sizeof( uint16_t ) )
+ if( uxSourceLenCpy > sizeof( uint16_t ) )
{
- pucByte += sizeof( uint16_t );
+ uxIndex += sizeof( uint16_t );
}
else
{
- pucByte = NULL;
+ uxIndex = 0U;
}
}
else
{
/* pucByte points to the full name. Walk over the string. */
- while( ( *pucByte != 0x00u ) && ( uxSourceLen > 1u ) )
+ while( ( pucByte[ uxIndex ] != 0U ) && ( uxSourceLenCpy > 1U ) )
{
- uxChunkLength = *pucByte + 1u;
+ /* Conversion to size_t causes addition to be done
+ in size_t */
+ uxChunkLength = ( ( size_t ) pucByte[ uxIndex ] ) + 1U;
- if( uxSourceLen > uxChunkLength )
+ if( uxSourceLenCpy > uxChunkLength )
{
- uxSourceLen -= uxChunkLength;
- pucByte += uxChunkLength;
+ uxSourceLenCpy -= uxChunkLength;
+ uxIndex += uxChunkLength;
}
else
{
- pucByte = NULL;
+ uxIndex = 0U;
break;
}
}
/* Confirm that a fully formed name was found. */
- if( NULL != pucByte )
+ if( uxIndex > 0U )
{
- if( 0x00u == *pucByte )
+ if( pucByte[ uxIndex ] == 0U )
{
- pucByte++;
+ uxIndex++;
}
else
{
- pucByte = NULL;
+ uxIndex = 0U;
}
}
}
- return pucByte;
+ return uxIndex;
}
/*-----------------------------------------------------------*/
@@ -913,28 +1037,28 @@ when ipconfigDNS_USE_CALLBACKS == 1
when ipconfigUSE_LLMNR == 1
for testing purposes, by the module iot_test_freertos_tcp.c
*/
-uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer )
+uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t *pxNetworkBuffer )
{
DNSMessage_t *pxDNSMessageHeader;
size_t uxPayloadSize;
- /* Only proceed if the payload length indicated in the header
- appears to be valid. */
- if( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) )
- {
- uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
+ /* Only proceed if the payload length indicated in the header
+ appears to be valid. */
+ if( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) )
+ {
+ uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
- if( uxPayloadSize >= sizeof( DNSMessage_t ) )
- {
- pxDNSMessageHeader =
- ( DNSMessage_t * ) ( pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ) );
+ if( uxPayloadSize >= sizeof( DNSMessage_t ) )
+ {
+ pxDNSMessageHeader =
+ ipPOINTER_CAST( DNSMessage_t *, &( pxNetworkBuffer->pucEthernetBuffer [ sizeof( UDPPacket_t ) ] ) );
- /* The parameter pdFALSE indicates that the reply was not expected. */
- prvParseDNSReply( ( uint8_t * ) pxDNSMessageHeader,
- uxPayloadSize,
- pdFALSE );
- }
- }
+ /* The parameter pdFALSE indicates that the reply was not expected. */
+ ( void ) prvParseDNSReply( ( uint8_t * ) pxDNSMessageHeader,
+ uxPayloadSize,
+ pdFALSE );
+ }
+ }
/* The packet was not consumed. */
return pdFAIL;
@@ -945,14 +1069,11 @@ size_t uxPayloadSize;
uint32_t ulNBNSHandlePacket( NetworkBufferDescriptor_t * pxNetworkBuffer )
{
- UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
- uint8_t *pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t );
- size_t uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
+ UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ uint8_t *pucUDPPayloadBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( *pxUDPPacket ) ] );
- /* The network buffer data length has already been set to the
- length of the UDP payload. */
prvTreatNBNS( pucUDPPayloadBuffer,
- uxPayloadSize,
+ pxNetworkBuffer->xDataLength,
pxUDPPacket->xIPHeader.ulSourceIPAddress );
/* The packet was not consumed. */
@@ -962,296 +1083,381 @@ size_t uxPayloadSize;
#endif /* ipconfigUSE_NBNS */
/*-----------------------------------------------------------*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+_static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected )
{
DNSMessage_t *pxDNSMessageHeader;
-DNSAnswerRecord_t *pxDNSAnswerRecord;
-uint32_t ulIPAddress = 0uL;
+/* This pointer is not used to modify anything */
+const DNSAnswerRecord_t *pxDNSAnswerRecord;
+uint32_t ulIPAddress = 0UL;
#if( ipconfigUSE_LLMNR == 1 )
char *pcRequestedName = NULL;
#endif
uint8_t *pucByte;
size_t uxSourceBytesRemaining;
uint16_t x, usDataLength, usQuestions;
-BaseType_t xDoStore = xExpected;
+uint16_t usType = 0U;
+BaseType_t xReturn = pdTRUE;
+
#if( ipconfigUSE_LLMNR == 1 )
- uint16_t usType = 0, usClass = 0;
+ uint16_t usClass = 0U;
#endif
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+ BaseType_t xDoStore = xExpected;
char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ] = "";
#endif
/* Ensure that the buffer is of at least minimal DNS message length. */
if( uxBufferLength < sizeof( DNSMessage_t ) )
{
- return dnsPARSE_ERROR;
+ xReturn = pdFALSE;
}
+ else
+ {
+ uxSourceBytesRemaining = uxBufferLength;
- uxSourceBytesRemaining = uxBufferLength;
+ /* Parse the DNS message header. Map the byte stream onto a structure
+ * for easier access. */
+ pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
- /* Parse the DNS message header. */
- pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;
+ /* Introduce a do {} while (0) to allow the use of breaks. */
+ do
+ {
+ size_t uxBytesRead = 0U;
+ size_t uxResult;
- /* Introduce a do {} while (0) to allow the use of breaks. */
- do
- {
- /* Start at the first byte after the header. */
- pucByte = pucUDPPayloadBuffer + sizeof( DNSMessage_t );
- uxSourceBytesRemaining -= sizeof( DNSMessage_t );
+ /* Start at the first byte after the header. */
+ pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] );
+ uxSourceBytesRemaining -= sizeof( DNSMessage_t );
- /* Skip any question records. */
- usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
+ /* Skip any question records. */
+ usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
- for( x = 0; x < usQuestions; x++ )
- {
- #if( ipconfigUSE_LLMNR == 1 )
+ for( x = 0U; x < usQuestions; x++ )
{
- if( x == 0 )
+ #if( ipconfigUSE_LLMNR == 1 )
{
- pcRequestedName = ( char * ) pucByte;
+ if( x == 0U )
+ {
+ pcRequestedName = ( char * ) pucByte;
+ }
}
- }
- #endif
+ #endif
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- if( x == 0 )
- {
- pucByte = prvReadNameField( pucByte,
- uxSourceBytesRemaining,
- pcName,
- sizeof( pcName ) );
-
- /* Check for a malformed response. */
- if( NULL == pucByte )
+ if( x == 0U )
{
- return dnsPARSE_ERROR;
- }
+ uxResult = prvReadNameField( pucByte,
+ uxSourceBytesRemaining,
+ pcName,
+ sizeof( pcName ) );
- uxSourceBytesRemaining = ( pucUDPPayloadBuffer + uxBufferLength ) - pucByte;
- }
- else
+ /* Check for a malformed response. */
+ if( uxResult == 0U )
+ {
+ xReturn = pdFALSE;
+ break;
+ }
+ uxBytesRead += uxResult;
+ pucByte = &( pucByte[ uxResult ] );
+ uxSourceBytesRemaining -= uxResult;
+ }
+ else
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
- {
- /* Skip the variable length pcName field. */
- pucByte = prvSkipNameField( pucByte,
- uxSourceBytesRemaining );
-
- /* Check for a malformed response. */
- if( NULL == pucByte )
{
- return dnsPARSE_ERROR;
+ /* Skip the variable length pcName field. */
+ uxResult = prvSkipNameField( pucByte,
+ uxSourceBytesRemaining );
+
+ /* Check for a malformed response. */
+ if( uxResult == 0U )
+ {
+ xReturn = pdFALSE;
+ break;
+ }
+ uxBytesRead += uxResult;
+ pucByte = &( pucByte[ uxResult ] );
+ uxSourceBytesRemaining -= uxResult;
}
- uxSourceBytesRemaining = ( size_t )
- ( pucUDPPayloadBuffer + uxBufferLength - pucByte );
- }
+ /* Check the remaining buffer size. */
+ if( uxSourceBytesRemaining >= sizeof( uint32_t ) )
+ {
+ #if( ipconfigUSE_LLMNR == 1 )
+ {
+ /* usChar2u16 returns value in host endianness. */
+ usType = usChar2u16( pucByte );
+ usClass = usChar2u16( &( pucByte[ 2 ] ) );
+ }
+ #endif /* ipconfigUSE_LLMNR */
- /* Check the remaining buffer size. */
- if( uxSourceBytesRemaining >= sizeof( uint32_t ) )
- {
- #if( ipconfigUSE_LLMNR == 1 )
+ /* Skip the type and class fields. */
+ pucByte = &( pucByte[ sizeof( uint32_t ) ] );
+ uxSourceBytesRemaining -= sizeof( uint32_t );
+ }
+ else
{
- /* usChar2u16 returns value in host endianness. */
- usType = usChar2u16( pucByte );
- usClass = usChar2u16( pucByte + 2 );
+ xReturn = pdFALSE;
+ break;
}
- #endif /* ipconfigUSE_LLMNR */
-
- /* Skip the type and class fields. */
- pucByte += sizeof( uint32_t );
- uxSourceBytesRemaining -= sizeof( uint32_t );
}
- else
+
+ if( xReturn == pdFALSE )
{
- /* Malformed response. */
- return dnsPARSE_ERROR;
+ /* No need to proceed. Break out of the do-while loop. */
+ break;
}
- }
- /* Search through the answer records. */
- pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );
+ /* Search through the answer records. */
+ pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );
- if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )
- {
- for( x = 0; x < pxDNSMessageHeader->usAnswers; x++ )
+ if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )
{
- pucByte = prvSkipNameField( pucByte,
- uxSourceBytesRemaining );
-
- /* Check for a malformed response. */
- if( NULL == pucByte )
+ const uint16_t usCount = ( uint16_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY;
+ uint16_t usNumARecordsStored = 0;
+
+ for( x = 0U; ( x < pxDNSMessageHeader->usAnswers ) && ( usNumARecordsStored < usCount ); x++ )
{
- return dnsPARSE_ERROR;
- }
-
- uxSourceBytesRemaining = ( size_t )
- ( pucUDPPayloadBuffer + uxBufferLength - pucByte );
+ BaseType_t xDoAccept;
+
+ uxResult = prvSkipNameField( pucByte,
+ uxSourceBytesRemaining );
+
+ /* Check for a malformed response. */
+ if( uxResult == 0U )
+ {
+ xReturn = pdFALSE;
+ break;
+ }
- /* Is there enough data for an IPv4 A record answer and, if so,
- is this an A record? */
- if( ( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ) ) &&
- ( usChar2u16( pucByte ) == dnsTYPE_A_HOST ) )
- {
- /* This is the required record type and is of sufficient size. */
- pxDNSAnswerRecord = ( DNSAnswerRecord_t * ) pucByte;
+ uxBytesRead += uxResult;
+ pucByte = &( pucByte[ uxResult ] );
+ uxSourceBytesRemaining -= uxResult;
- /* Sanity check the data length of an IPv4 answer. */
- if( FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ) == sizeof( uint32_t ) )
+ /* Is there enough data for an IPv4 A record answer and, if so,
+ is this an A record? */
+ if( uxSourceBytesRemaining < sizeof( uint16_t ) )
{
- /* Copy the IP address out of the record. */
- memcpy( &ulIPAddress,
- pucByte + sizeof( DNSAnswerRecord_t ),
- sizeof( uint32_t ) );
+ xReturn = pdFALSE;
+ break;
+ }
+ usType = usChar2u16( pucByte );
- #if( ipconfigDNS_USE_CALLBACKS == 1 )
+ if( usType == ( uint16_t ) dnsTYPE_A_HOST )
+ {
+ if( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + ipSIZE_OF_IPv4_ADDRESS ) )
{
- /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */
- if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE )
- {
- /* This device has requested this DNS look-up.
- The result may be stored in the DNS cache. */
- xDoStore = pdTRUE;
- }
+ xDoAccept = pdTRUE;
}
- #endif /* ipconfigDNS_USE_CALLBACKS == 1 */
- #if( ipconfigUSE_DNS_CACHE == 1 )
+ else
{
- /* The reply will only be stored in the DNS cache when the
- request was issued by this device. */
- if( xDoStore != pdFALSE )
- {
- prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE );
- }
-
- /* Show what has happened. */
- FreeRTOS_printf( ( "DNS[0x%04X]: The answer to '%s' (%xip) will%s be stored\n",
- ( unsigned ) pxDNSMessageHeader->usIdentifier,
- pcName,
- ( unsigned ) FreeRTOS_ntohl( ulIPAddress ),
- ( xDoStore != 0 ) ? "" : " NOT" ) );
+ xDoAccept = pdFALSE;
}
- #endif /* ipconfigUSE_DNS_CACHE */
- }
-
- pucByte += sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t );
- uxSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) );
- break;
- }
- else if( uxSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) )
- {
- /* It's not an A record, so skip it. Get the header location
- and then jump over the header. */
- pxDNSAnswerRecord = ( DNSAnswerRecord_t * ) pucByte;
- pucByte += sizeof( DNSAnswerRecord_t );
- uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t );
-
- /* Determine the length of the answer data from the header. */
- usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength );
-
- /* Jump over the answer. */
- if( uxSourceBytesRemaining >= usDataLength )
- {
- pucByte += usDataLength;
- uxSourceBytesRemaining -= usDataLength;
}
else
{
- /* Malformed response. */
- return dnsPARSE_ERROR;
+ /* Unknown host type. */
+ xDoAccept = pdFALSE;
}
- }
- }
- }
-#if( ipconfigUSE_LLMNR == 1 )
- else if( usQuestions && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) )
- {
- /* If this is not a reply to our DNS request, it might an LLMNR
- request. */
- if( xApplicationDNSQueryHook( ( pcRequestedName + 1 ) ) )
- {
- int16_t usLength;
- NetworkBufferDescriptor_t *pxNewBuffer = NULL;
- NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
- LLMNRAnswer_t *pxAnswer;
+ if( xDoAccept != pdFALSE )
+ {
+ /* This is the required record type and is of sufficient size. */
+ /* Mapping pucByte to a DNSAnswerRecord allows easy access of the
+ * fields of the structure. */
+ pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
- if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )
- {
- BaseType_t xDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );
+ /* Sanity check the data length of an IPv4 answer. */
+ if( FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ) == ( uint16_t ) sizeof( uint32_t ) )
+ {
+ /* Copy the IP address out of the record. Using different pointers
+ * to copy only the portion we want is intentional here. */
+ ( void ) memcpy( &( ulIPAddress ),
+ &( pucByte[ sizeof( DNSAnswerRecord_t ) ] ),
+ sizeof( uint32_t ) );
- /* Set the size of the outgoing packet. */
- pxNetworkBuffer->xDataLength = xDataLength;
- pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + sizeof( LLMNRAnswer_t ) );
+ #if( ipconfigDNS_USE_CALLBACKS == 1 )
+ {
+ /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */
+ if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE )
+ {
+ /* This device has requested this DNS look-up.
+ The result may be stored in the DNS cache. */
+ xDoStore = pdTRUE;
+ }
+ }
+ #endif /* ipconfigDNS_USE_CALLBACKS == 1 */
+ #if( ipconfigUSE_DNS_CACHE == 1 )
+ {
+ char cBuffer[ 16 ];
+
+ /* The reply will only be stored in the DNS cache when the
+ request was issued by this device. */
+ if( xDoStore != pdFALSE )
+ {
+ ( void ) prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE );
+ usNumARecordsStored++; /* Track # of A records stored */
+ }
+
+ ( void ) FreeRTOS_inet_ntop( FREERTOS_AF_INET, ( const void * ) &( ulIPAddress ), cBuffer, sizeof( cBuffer ) );
+ /* Show what has happened. */
+ FreeRTOS_printf( ( "DNS[0x%04lX]: The answer to '%s' (%s) will%s be stored\n",
+ ( UBaseType_t ) pxDNSMessageHeader->usIdentifier,
+ pcName,
+ cBuffer,
+ ( xDoStore != 0 ) ? "" : " NOT" ) );
+ }
+ #endif /* ipconfigUSE_DNS_CACHE */
+ }
- if( pxNewBuffer != NULL )
+ pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ] );
+ uxSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) );
+ }
+ else if( uxSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) )
{
- BaseType_t xOffset1, xOffset2;
+ /* It's not an A record, so skip it. Get the header location
+ and then jump over the header. */
+ /* Cast the response to DNSAnswerRecord for easy access to fields of the DNS response. */
+ pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
- xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer );
- xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer );
+ pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) ] );
+ uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t );
- pxNetworkBuffer = pxNewBuffer;
- pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + ipUDP_PAYLOAD_OFFSET_IPv4;
+ /* Determine the length of the answer data from the header. */
+ usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength );
- pucByte = pucUDPPayloadBuffer + xOffset1;
- pcRequestedName = ( char * ) ( pucUDPPayloadBuffer + xOffset2 );
- pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;
+ /* Jump over the answer. */
+ if( uxSourceBytesRemaining >= usDataLength )
+ {
+ pucByte = &( pucByte[ usDataLength ] );
+ uxSourceBytesRemaining -= usDataLength;
+ }
+ else
+ {
+ /* Malformed response. */
+ xReturn = pdFALSE;
+ break;
+ }
}
else
{
- /* Just to indicate that the message may not be answered. */
- pxNetworkBuffer = NULL;
+ /* Do nothing */
}
}
+ }
- if( pxNetworkBuffer != NULL )
+#if( ipconfigUSE_LLMNR == 1 )
+ else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) && ( pcRequestedName != NULL ) )
+ {
+ /* If this is not a reply to our DNS request, it might an LLMNR
+ request. */
+ if( xApplicationDNSQueryHook( &( pcRequestedName[ 1 ] ) ) != pdFALSE )
{
- pxAnswer = ( LLMNRAnswer_t * ) pucByte;
+ int16_t usLength;
+ NetworkBufferDescriptor_t *pxNewBuffer = NULL;
+ NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
+ LLMNRAnswer_t *pxAnswer;
+ uint8_t *pucNewBuffer = NULL;
- /* We leave 'usIdentifier' and 'usQuestions' untouched */
- vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */
- vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */
- vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */
- vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */
+ if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )
+ {
+ size_t uxDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );
- pxAnswer->ucNameCode = dnsNAME_IS_OFFSET;
- pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucUDPPayloadBuffer );
+ /* Set the size of the outgoing packet. */
+ pxNetworkBuffer->xDataLength = uxDataLength;
+ pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, uxDataLength + sizeof( LLMNRAnswer_t ) );
- vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */
- vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */
- vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE );
- vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 );
- vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );
+ if( pxNewBuffer != NULL )
+ {
+ BaseType_t xOffset1, xOffset2;
- usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucUDPPayloadBuffer ) );
+ xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer );
+ xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer );
- prvReplyDNSMessage( pxNetworkBuffer, usLength );
+ pxNetworkBuffer = pxNewBuffer;
+ pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
- if( pxNewBuffer != NULL )
+ pucByte = &( pucNewBuffer[ xOffset1 ] );
+ pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] );
+ pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucNewBuffer );
+ }
+ else
+ {
+ /* Just to indicate that the message may not be answered. */
+ pxNetworkBuffer = NULL;
+ }
+ }
+
+ /* The test on 'pucNewBuffer' is only to satisfy lint. */
+ if( ( pxNetworkBuffer != NULL ) && ( pucNewBuffer != NULL ) )
{
- vReleaseNetworkBufferAndDescriptor( pxNewBuffer );
+ pxAnswer = ipPOINTER_CAST( LLMNRAnswer_t *, pucByte );
+
+ /* We leave 'usIdentifier' and 'usQuestions' untouched */
+ #ifndef _lint
+ vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */
+ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */
+ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */
+ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */
+ #endif /* lint */
+
+ pxAnswer->ucNameCode = dnsNAME_IS_OFFSET;
+ pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucNewBuffer );
+
+ #ifndef _lint
+ vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */
+ vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */
+ vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE );
+ vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 );
+ vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );
+ #endif /* lint */
+ usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucNewBuffer ) );
+
+ prvReplyDNSMessage( pxNetworkBuffer, usLength );
+
+ if( pxNewBuffer != NULL )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxNewBuffer );
+ }
}
}
}
- }
+ else
+ {
+ /* Not an expected reply. */
+ }
#endif /* ipconfigUSE_LLMNR == 1 */
- } while( 0 );
+ ( void ) uxBytesRead;
+ } while( ipFALSE_BOOL );
+ }
- if( xExpected == pdFALSE )
+ if( xReturn == pdFALSE )
+ {
+ /* There was an error while parsing the DNS response. Return error code. */
+ ulIPAddress = dnsPARSE_ERROR;
+ }
+ else if( xExpected == pdFALSE )
{
/* Do not return a valid IP-address in case the reply was not expected. */
- ulIPAddress = 0uL;
+ ulIPAddress = 0UL;
+ }
+ else
+ {
+ /* The IP-address found will be returned. */
}
+ #if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+ ( void ) xDoStore;
+ #endif
+
return ulIPAddress;
}
/*-----------------------------------------------------------*/
#if( ipconfigUSE_NBNS == 1 )
- static void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer,
+ static void prvTreatNBNS( uint8_t *pucPayload,
size_t uxBufferLength,
uint32_t ulIPAddress )
{
@@ -1259,40 +1465,45 @@ BaseType_t xDoStore = xExpected;
uint8_t *pucSource, *pucTarget;
uint8_t ucByte;
uint8_t ucNBNSName[ 17 ];
+ uint8_t *pucUDPPayloadBuffer = pucPayload;
+ NetworkBufferDescriptor_t *pxNetworkBuffer;
+ size_t uxBytesNeeded = sizeof( UDPPacket_t ) + sizeof( NBNSRequest_t );
/* Check for minimum buffer size. */
- if( uxBufferLength < sizeof( NBNSRequest_t ) )
+ if( uxBufferLength < uxBytesNeeded )
{
return;
}
/* Read the request flags in host endianness. */
- usFlags = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usFlags ) );
+ usFlags = usChar2u16( &( pucUDPPayloadBuffer[ offsetof( NBNSRequest_t, usFlags ) ] ) );
if( ( usFlags & dnsNBNS_FLAGS_OPCODE_MASK ) == dnsNBNS_FLAGS_OPCODE_QUERY )
{
- usType = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) );
- usClass = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usClass ) );
+ usType = usChar2u16( &( pucUDPPayloadBuffer[ offsetof( NBNSRequest_t, usType ) ] ) );
+ usClass = usChar2u16( &( pucUDPPayloadBuffer[ offsetof( NBNSRequest_t, usClass ) ] ) );
/* Not used for now */
( void ) usClass;
/* For NBNS a name is 16 bytes long, written with capitals only.
Make sure that the copy is terminated with a zero. */
- pucTarget = ucNBNSName + sizeof( ucNBNSName ) - 2;
- pucTarget[ 1 ] = '\0';
+ pucTarget = &( ucNBNSName[ sizeof( ucNBNSName ) - 2U ] );
+ pucTarget[ 1 ] = ( uint8_t ) 0U;
/* Start with decoding the last 2 bytes. */
- pucSource = pucUDPPayloadBuffer + ( offsetof( NBNSRequest_t, ucName ) + ( dnsNBNS_ENCODED_NAME_LENGTH - 2 ) );
+ pucSource = &( pucUDPPayloadBuffer[ ( dnsNBNS_ENCODED_NAME_LENGTH - 2 ) + offsetof( NBNSRequest_t, ucName ) ] );
for( ;; )
{
- ucByte = ( uint8_t ) ( ( ( pucSource[ 0 ] - 0x41 ) << 4 ) | ( pucSource[ 1 ] - 0x41 ) );
+ const uint8_t ucCharA = ( uint8_t ) 0x41U;
+
+ ucByte = ( ( uint8_t ) ( ( pucSource[ 0 ] - ucCharA ) << 4 ) ) | ( pucSource[ 1 ] - ucCharA );
/* Make sure there are no trailing spaces in the name. */
- if( ( ucByte == ' ' ) && ( pucTarget[ 1 ] == '\0' ) )
+ if( ( ucByte == ( uint8_t ) ' ' ) && ( pucTarget[ 1 ] == 0U ) )
{
- ucByte = '\0';
+ ucByte = 0U;
}
*pucTarget = ucByte;
@@ -1308,11 +1519,11 @@ BaseType_t xDoStore = xExpected;
#if( ipconfigUSE_DNS_CACHE == 1 )
{
- if( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) != 0 )
+ if( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) != 0U )
{
/* If this is a response from another device,
add the name to the DNS cache */
- prvProcessDNSCache( ( char * ) ucNBNSName, &ulIPAddress, 0, pdFALSE );
+ ( void ) prvProcessDNSCache( ( char * ) ucNBNSName, &( ulIPAddress ), 0, pdFALSE );
}
}
#else
@@ -1322,7 +1533,7 @@ BaseType_t xDoStore = xExpected;
}
#endif /* ipconfigUSE_DNS_CACHE */
- if( ( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) == 0 ) &&
+ if( ( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) == 0U ) &&
( usType == dnsNBNS_TYPE_NET_BIOS ) &&
( xApplicationDNSQueryHook( ( const char * ) ucNBNSName ) != pdFALSE ) )
{
@@ -1332,7 +1543,7 @@ BaseType_t xDoStore = xExpected;
/* Someone is looking for a device with ucNBNSName,
prepare a positive reply. */
- NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
+ pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )
{
@@ -1344,7 +1555,7 @@ BaseType_t xDoStore = xExpected;
if( pxNewBuffer != NULL )
{
- pucUDPPayloadBuffer = pxNewBuffer->pucEthernetBuffer + sizeof( UDPPacket_t );
+ pucUDPPayloadBuffer = &( pxNewBuffer->pucEthernetBuffer[ sizeof( UDPPacket_t ) ] );
pxNetworkBuffer = pxNewBuffer;
}
else
@@ -1357,28 +1568,36 @@ BaseType_t xDoStore = xExpected;
/* Should not occur: pucUDPPayloadBuffer is part of a xNetworkBufferDescriptor */
if( pxNetworkBuffer != NULL )
{
- pxMessage = ( DNSMessage_t * ) pucUDPPayloadBuffer;
+ pxMessage = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
/* As the fields in the structures are not word-aligned, we have to
copy the values byte-by-byte using macro's vSetField16() and vSetField32() */
+ #ifndef _lint
vSetField16( pxMessage, DNSMessage_t, usFlags, dnsNBNS_QUERY_RESPONSE_FLAGS ); /* 0x8500 */
vSetField16( pxMessage, DNSMessage_t, usQuestions, 0 );
vSetField16( pxMessage, DNSMessage_t, usAnswers, 1 );
vSetField16( pxMessage, DNSMessage_t, usAuthorityRRs, 0 );
vSetField16( pxMessage, DNSMessage_t, usAdditionalRRs, 0 );
+ #else
+ ( void ) pxMessage;
+ #endif
- pxAnswer = ( NBNSAnswer_t * ) ( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) );
+ pxAnswer = ipPOINTER_CAST( NBNSAnswer_t *, &( pucUDPPayloadBuffer[ offsetof( NBNSRequest_t, usType ) ] ) );
+ #ifndef _lint
vSetField16( pxAnswer, NBNSAnswer_t, usType, usType ); /* Type */
vSetField16( pxAnswer, NBNSAnswer_t, usClass, dnsNBNS_CLASS_IN ); /* Class */
vSetField32( pxAnswer, NBNSAnswer_t, ulTTL, dnsNBNS_TTL_VALUE );
vSetField16( pxAnswer, NBNSAnswer_t, usDataLength, 6 ); /* 6 bytes including the length field */
vSetField16( pxAnswer, NBNSAnswer_t, usNbFlags, dnsNBNS_NAME_FLAGS );
vSetField32( pxAnswer, NBNSAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );
+ #else
+ ( void ) pxAnswer;
+ #endif
- usLength = ( uint16_t ) ( offsetof( NBNSRequest_t, usType ) + sizeof( NBNSAnswer_t ) );
+ usLength = ( uint16_t ) ( sizeof( NBNSAnswer_t ) + ( size_t ) offsetof( NBNSRequest_t, usType ) );
- prvReplyDNSMessage( pxNetworkBuffer, usLength );
+ prvReplyDNSMessage( pxNetworkBuffer, ( BaseType_t ) usLength );
}
}
}
@@ -1389,27 +1608,34 @@ BaseType_t xDoStore = xExpected;
static Socket_t prvCreateDNSSocket( void )
{
-Socket_t xSocket = NULL;
+Socket_t xSocket;
struct freertos_sockaddr xAddress;
BaseType_t xReturn;
/* This must be the first time this function has been called. Create
the socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
-
- /* Auto bind the port. */
- xAddress.sin_port = 0u;
- xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
-
- /* Check the bind was successful, and clean up if not. */
- if( xReturn != 0 )
+ if( ( xSocket == FREERTOS_INVALID_SOCKET ) || ( xSocket == NULL ) )
{
- FreeRTOS_closesocket( xSocket );
+ /* There was an error, return NULL. */
xSocket = NULL;
}
else
{
- /* The send and receive timeouts will be set later on. */
+ /* Auto bind the port. */
+ xAddress.sin_port = 0U;
+ xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
+
+ /* Check the bind was successful, and clean up if not. */
+ if( xReturn != 0 )
+ {
+ ( void ) FreeRTOS_closesocket( xSocket );
+ xSocket = NULL;
+ }
+ else
+ {
+ /* The send and receive timeouts will be set later on. */
+ }
}
return xSocket;
@@ -1424,36 +1650,40 @@ BaseType_t xReturn;
UDPPacket_t *pxUDPPacket;
IPHeader_t *pxIPHeader;
UDPHeader_t *pxUDPHeader;
+ size_t uxDataLength;
- pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
+ pxUDPPacket = ipPOINTER_CAST( UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
pxIPHeader = &pxUDPPacket->xIPHeader;
pxUDPHeader = &pxUDPPacket->xUDPHeader;
/* HT: started using defines like 'ipSIZE_OF_xxx' */
- pxIPHeader->usLength = FreeRTOS_htons( lNetLength + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER );
+ pxIPHeader->usLength = FreeRTOS_htons( ( uint16_t ) lNetLength + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER );
/* HT:endian: should not be translated, copying from packet to packet */
pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;
pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;
pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE;
pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier );
usPacketIdentifier++;
- pxUDPHeader->usLength = FreeRTOS_htons( lNetLength + ipSIZE_OF_UDP_HEADER );
- vFlip_16( pxUDPPacket->xUDPHeader.usSourcePort, pxUDPPacket->xUDPHeader.usDestinationPort );
+ pxUDPHeader->usLength = FreeRTOS_htons( ( uint32_t ) lNetLength + ipSIZE_OF_UDP_HEADER );
+ vFlip_16( pxUDPHeader->usSourcePort, pxUDPHeader->usDestinationPort );
/* Important: tell NIC driver how many bytes must be sent */
- pxNetworkBuffer->xDataLength = ( size_t ) ( lNetLength + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER + ipSIZE_OF_ETH_HEADER );
+ uxDataLength = ( ( size_t ) lNetLength ) + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER + ipSIZE_OF_ETH_HEADER;
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
/* calculate the IP header checksum */
- pxIPHeader->usHeaderChecksum = 0x00;
- pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0uL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = 0U;
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
/* calculate the UDP checksum for outgoing package */
- usGenerateProtocolChecksum( ( uint8_t* ) pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
+ ( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxUDPPacket, uxDataLength, pdTRUE );
}
#endif
+ /* Important: tell NIC driver how many bytes must be sent */
+ pxNetworkBuffer->xDataLength = uxDataLength;
+
/* This function will fill in the eth addresses and send the packet */
vReturnEthernetFrame( pxNetworkBuffer, pdFALSE );
}
@@ -1463,26 +1693,28 @@ BaseType_t xReturn;
#if( ipconfigUSE_DNS_CACHE == 1 )
- static void prvProcessDNSCache( const char *pcName,
+ static BaseType_t prvProcessDNSCache( const char *pcName,
uint32_t *pulIP,
uint32_t ulTTL,
BaseType_t xLookUp )
{
BaseType_t x;
BaseType_t xFound = pdFALSE;
- uint32_t ulCurrentTimeSeconds = ( xTaskGetTickCount() / portTICK_PERIOD_MS ) / 1000;
+ uint32_t ulCurrentTimeSeconds = ( xTaskGetTickCount() / portTICK_PERIOD_MS ) / 1000U;
+ uint32_t ulIPAddressIndex = 0;
static BaseType_t xFreeEntry = 0;
- configASSERT(pcName);
+
+ configASSERT( ( pcName != NULL ) );
/* For each entry in the DNS cache table. */
for( x = 0; x < ipconfigDNS_CACHE_ENTRIES; x++ )
{
- if( xDNSCache[ x ].pcName[ 0 ] == 0 )
+ if( xDNSCache[ x ].pcName[ 0 ] == ( char ) 0 )
{
continue;
}
- if( 0 == strcmp( xDNSCache[ x ].pcName, pcName ) )
+ if( strcmp( xDNSCache[ x ].pcName, pcName ) == 0 )
{
/* Is this function called for a lookup or to add/update an IP address? */
if( xLookUp != pdFALSE )
@@ -1490,17 +1722,40 @@ BaseType_t xReturn;
/* Confirm that the record is still fresh. */
if( ulCurrentTimeSeconds < ( xDNSCache[ x ].ulTimeWhenAddedInSeconds + FreeRTOS_ntohl( xDNSCache[ x ].ulTTL ) ) )
{
- *pulIP = xDNSCache[ x ].ulIPAddress;
+#if( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 )
+ uint8_t ucIndex;
+ /* The ucCurrentIPAddress value increments without bound and will rollover, */
+ /* modulo it by the number of IP addresses to keep it in range. */
+ /* Also perform a final modulo by the max number of IP addresses */
+ /* per DNS cache entry to prevent out-of-bounds access in the event */
+ /* that ucNumIPAddresses has been corrupted. */
+ ucIndex = xDNSCache[ x ].ucCurrentIPAddress % xDNSCache[ x ].ucNumIPAddresses;
+ ucIndex = ucIndex % ( uint8_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY;
+ ulIPAddressIndex = ucIndex;
+
+ xDNSCache[ x ].ucCurrentIPAddress++;
+#endif
+ *pulIP = xDNSCache[ x ].ulIPAddresses[ ulIPAddressIndex ];
}
else
{
/* Age out the old cached record. */
- xDNSCache[ x ].pcName[ 0 ] = 0;
+ xDNSCache[ x ].pcName[ 0 ] = ( char ) 0;
}
}
else
{
- xDNSCache[ x ].ulIPAddress = *pulIP;
+#if( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 )
+ if ( xDNSCache[ x ].ucNumIPAddresses < ( uint8_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY )
+ {
+ /* If more answers exist than there are IP address storage slots */
+ /* they will overwrite entry 0 */
+
+ ulIPAddressIndex = xDNSCache[ x ].ucNumIPAddresses;
+ xDNSCache[ x ].ucNumIPAddresses++;
+ }
+#endif
+ xDNSCache[ x ].ulIPAddresses[ ulIPAddressIndex ] = *pulIP;
xDNSCache[ x ].ulTTL = ulTTL;
xDNSCache[ x ].ulTimeWhenAddedInSeconds = ulCurrentTimeSeconds;
}
@@ -1514,18 +1769,28 @@ BaseType_t xReturn;
{
if( xLookUp != pdFALSE )
{
- *pulIP = 0;
+ *pulIP = 0UL;
}
else
{
/* Add or update the item. */
- if( strlen( pcName ) < ipconfigDNS_CACHE_NAME_LENGTH )
+ if( strlen( pcName ) < ( size_t ) ipconfigDNS_CACHE_NAME_LENGTH )
{
- strcpy( xDNSCache[ xFreeEntry ].pcName, pcName );
+ ( void ) strcpy( xDNSCache[ xFreeEntry ].pcName, pcName );
- xDNSCache[ xFreeEntry ].ulIPAddress = *pulIP;
+ xDNSCache[ xFreeEntry ].ulIPAddresses[ 0 ] = *pulIP;
xDNSCache[ xFreeEntry ].ulTTL = ulTTL;
xDNSCache[ xFreeEntry ].ulTimeWhenAddedInSeconds = ulCurrentTimeSeconds;
+#if( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 )
+ xDNSCache[ xFreeEntry ].ucNumIPAddresses = 1;
+ xDNSCache[ xFreeEntry ].ucCurrentIPAddress = 0;
+
+ /* Initialize all remaining IP addresses in this entry to 0 */
+ ( void ) memset( &xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ],
+ 0,
+ sizeof( xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ] ) *
+ ( ( uint32_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY - 1U ) );
+#endif
xFreeEntry++;
@@ -1537,10 +1802,11 @@ BaseType_t xReturn;
}
}
- if( ( xLookUp == 0 ) || ( *pulIP != 0 ) )
+ if( ( xLookUp == 0 ) || ( *pulIP != 0UL ) )
{
- FreeRTOS_debug_printf( ( "prvProcessDNSCache: %s: '%s' @ %lxip\n", xLookUp ? "look-up" : "add", pcName, FreeRTOS_ntohl( *pulIP ) ) );
+ FreeRTOS_debug_printf( ( "prvProcessDNSCache: %s: '%s' @ %lxip\n", ( xLookUp != 0 ) ? "look-up" : "add", pcName, FreeRTOS_ntohl( *pulIP ) ) );
}
+ return xFound;
}
#endif /* ipconfigUSE_DNS_CACHE */
@@ -1550,7 +1816,6 @@ BaseType_t xReturn;
/*-----------------------------------------------------------*/
/* Provide access to private members for testing. */
-#ifdef AMAZON_FREERTOS_ENABLE_UNIT_TESTS
- #include "iot_freertos_tcp_test_access_dns_define.h"
+#ifdef FREERTOS_ENABLE_UNIT_TESTS
+ #include "freertos_tcp_test_access_dns_define.h"
#endif
-
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
index 707c99dc6..bfd2a9c15 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
@@ -40,7 +40,6 @@
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
@@ -50,43 +49,52 @@
/* Used to ensure the structure packing is having the desired effect. The
'volatile' is used to prevent compiler warnings about comparing a constant with
a constant. */
-#define ipEXPECTED_EthernetHeader_t_SIZE ( ( size_t ) 14 )
-#define ipEXPECTED_ARPHeader_t_SIZE ( ( size_t ) 28 )
-#define ipEXPECTED_IPHeader_t_SIZE ( ( size_t ) 20 )
-#define ipEXPECTED_IGMPHeader__SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_ICMPHeader_t_SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_UDPHeader_t_SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_TCPHeader_t_SIZE ( ( size_t ) 20 )
-
+#ifndef _lint
+ #define ipEXPECTED_EthernetHeader_t_SIZE ( ( size_t ) 14 )
+ #define ipEXPECTED_ARPHeader_t_SIZE ( ( size_t ) 28 )
+ #define ipEXPECTED_IPHeader_t_SIZE ( ( size_t ) 20 )
+ #define ipEXPECTED_IGMPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_ICMPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_UDPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_TCPHeader_t_SIZE ( ( size_t ) 20 )
+#endif
/* ICMP protocol definitions. */
#define ipICMP_ECHO_REQUEST ( ( uint8_t ) 8 )
#define ipICMP_ECHO_REPLY ( ( uint8_t ) 0 )
+/* IPv4 multi-cast addresses range from 224.0.0.0.0 to 240.0.0.0. */
+#define ipFIRST_MULTI_CAST_IPv4 0xE0000000UL
+#define ipLAST_MULTI_CAST_IPv4 0xF0000000UL
+/* The first byte in the IPv4 header combines the IP version (4) with
+with the length of the IP header. */
+#define ipIPV4_VERSION_HEADER_LENGTH_MIN 0x45U
+#define ipIPV4_VERSION_HEADER_LENGTH_MAX 0x4FU
+
/* Time delay between repeated attempts to initialise the network hardware. */
#ifndef ipINITIALISATION_RETRY_DELAY
- #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000 ) )
+ #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000U ) )
#endif
/* Defines how often the ARP timer callback function is executed. The time is
shorted in the Windows simulator as simulated time is not real time. */
#ifndef ipARP_TIMER_PERIOD_MS
#ifdef _WINDOWS_
- #define ipARP_TIMER_PERIOD_MS ( 500 ) /* For windows simulator builds. */
+ #define ipARP_TIMER_PERIOD_MS ( 500U ) /* For windows simulator builds. */
#else
- #define ipARP_TIMER_PERIOD_MS ( 10000 )
+ #define ipARP_TIMER_PERIOD_MS ( 10000U )
#endif
#endif
#ifndef iptraceIP_TASK_STARTING
- #define iptraceIP_TASK_STARTING() do {} while( 0 )
+ #define iptraceIP_TASK_STARTING() do {} while( ipFALSE_BOOL )
#endif
#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
/* When initialising the TCP timer,
give it an initial time-out of 1 second. */
- #define ipTCP_TIMER_PERIOD_MS ( 1000 )
+ #define ipTCP_TIMER_PERIOD_MS ( 1000U )
#endif
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
@@ -102,17 +110,15 @@ needs to call eConsiderFrameForProcessing. */
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#endif
-/* The character used to fill ICMP echo requests, and therefore also the
-character expected to fill ICMP echo replies. */
-#define ipECHO_DATA_FILL_BYTE 'x'
-
-#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
- /* The bits in the two byte IP header field that make up the fragment offset value. */
- #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f )
-#else
- /* The bits in the two byte IP header field that make up the fragment offset value. */
- #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff )
-#endif /* ipconfigBYTE_ORDER */
+#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )
+ #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
+ /* The bits in the two byte IP header field that make up the fragment offset value. */
+ #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f )
+ #else
+ /* The bits in the two byte IP header field that make up the fragment offset value. */
+ #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff )
+ #endif /* ipconfigBYTE_ORDER */
+#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
/* The maximum time the IP task is allowed to remain in the Blocked state if no
events are posted to the network event queue. */
@@ -120,39 +126,22 @@ events are posted to the network event queue. */
#define ipconfigMAX_IP_TASK_SLEEP_TIME ( pdMS_TO_TICKS( 10000UL ) )
#endif
-/* When a new TCP connection is established, the value of
-'ulNextInitialSequenceNumber' will be used as the initial sequence number. It
-is very important that at start-up, 'ulNextInitialSequenceNumber' contains a
-random value. Also its value must be increased continuously in time, to prevent
-a third party guessing the next sequence number and take-over a TCP connection.
-It is advised to increment it by 1 ever 4us, which makes about 256 times
-per ms: */
-#define ipINITIAL_SEQUENCE_NUMBER_FACTOR 256UL
-
/* Returned as the (invalid) checksum when the protocol being checked is not
handled. The value is chosen simply to be easy to spot when debugging. */
-#define ipUNHANDLED_PROTOCOL 0x4321u
+#define ipUNHANDLED_PROTOCOL 0x4321U
-/* Returned to indicate a valid checksum when the checksum does not need to be
-calculated. */
-#define ipCORRECT_CRC 0xffffu
+/* Returned to indicate a valid checksum. */
+#define ipCORRECT_CRC 0xffffU
+
+/* Returned to indicate incorrect checksum. */
+#define ipWRONG_CRC 0x0000U
/* Returned as the (invalid) checksum when the length of the data being checked
had an invalid length. */
-#define ipINVALID_LENGTH 0x1234u
+#define ipINVALID_LENGTH 0x1234U
/*-----------------------------------------------------------*/
-typedef struct xIP_TIMER
-{
- uint32_t
- bActive : 1, /* This timer is running and must be processed. */
- bExpired : 1; /* Timer has expired and a task must be processed. */
- TimeOut_t xTimeOut;
- TickType_t ulRemainingTime;
- TickType_t ulReloadTime;
-} IPTimer_t;
-
/* Used in checksum calculation. */
typedef union _xUnion32
{
@@ -186,7 +175,7 @@ static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetwor
/*
* Process incoming IP packets.
*/
-static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );
+static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/*
@@ -241,8 +230,16 @@ static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime );
static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer );
static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime );
+/* The function 'prvAllowIPPacket()' checks if a packets should be processed. */
static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
- NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength );
+ const NetworkBufferDescriptor_t * const pxNetworkBuffer,
+ UBaseType_t uxHeaderLength );
+
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
+ /* Even when the driver takes care of checksum calculations,
+ the IP-task will still check if the length fields are OK. */
+ static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength );
+#endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
/*-----------------------------------------------------------*/
@@ -261,12 +258,14 @@ NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 };
/* Default values for the above struct in case DHCP
does not lead to a confirmed request. */
+/* coverity[misra_c_2012_rule_8_9_violation] */
+/* "xDefaultAddressing" should be defined at block scope. */
NetworkAddressingParameters_t xDefaultAddressing = { 0, 0, 0, 0, 0 };
/* Used to ensure network down events cannot be missed when they cannot be
posted to the network event queue because the network event queue is already
full. */
-static BaseType_t xNetworkDownEventPending = pdFALSE;
+static volatile BaseType_t xNetworkDownEventPending = pdFALSE;
/* Stores the handle of the task that handles the stack. The handle is used
(indirectly) by some utility function to determine if the utility function is
@@ -304,6 +303,8 @@ static IPTimer_t xARPTimer;
#endif
/* Set to pdTRUE when the IP task is ready to start processing packets. */
+/* coverity[misra_c_2012_rule_8_9_violation] */
+/* "xIPTaskInitialised" should be defined at block scope. */
static BaseType_t xIPTaskInitialised = pdFALSE;
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
@@ -313,6 +314,8 @@ static BaseType_t xIPTaskInitialised = pdFALSE;
/*-----------------------------------------------------------*/
+/* Coverity want to make pvParameters const, which would make it incompatible. */
+/* coverity[misra_c_2012_rule_8_13_violation] */
static void prvIPTask( void *pvParameters )
{
IPStackEvent_t xReceivedEvent;
@@ -359,7 +362,7 @@ struct freertos_sockaddr xAddress;
/* Wait until there is something to do. If the following call exits
* due to a time out rather than a message being received, set a
* 'NoEvent' value. */
- if ( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE )
+ if ( xQueueReceive( xNetworkEventQueue, ipPOINTER_CAST( void *, &xReceivedEvent ), xNextIPSleep ) == pdFALSE )
{
xReceivedEvent.eEventType = eNoEvent;
}
@@ -393,13 +396,13 @@ struct freertos_sockaddr xAddress;
/* The network hardware driver has received a new packet. A
pointer to the received buffer is located in the pvData member
of the received event structure. */
- prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
+ prvHandleEthernetPacket( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ) );
break;
case eNetworkTxEvent:
/* Send a network packet. The ownership will be transferred to
the driver, which will release it after delivery. */
- xNetworkInterfaceOutput( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ), pdTRUE );
+ ( void ) xNetworkInterfaceOutput( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ), pdTRUE );
break;
case eARPTimerEvent :
@@ -413,16 +416,16 @@ struct freertos_sockaddr xAddress;
usLocalPort. vSocketBind() will actually bind the socket and the
API will unblock as soon as the eSOCKET_BOUND event is
triggered. */
- pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
- xAddress.sin_addr = 0u; /* For the moment. */
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData );
+ xAddress.sin_addr = 0U; /* For the moment. */
xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );
- pxSocket->usLocalPort = 0u;
- vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
+ pxSocket->usLocalPort = 0U;
+ ( void ) vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
/* Before 'eSocketBindEvent' was sent it was tested that
( xEventGroup != NULL ) so it can be used now to wake up the
user. */
- pxSocket->xEventBits |= eSOCKET_BOUND;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_BOUND;
vSocketWakeUpUser( pxSocket );
break;
@@ -431,20 +434,21 @@ struct freertos_sockaddr xAddress;
IP-task to actually close a socket. This is handled in
vSocketClose(). As the socket gets closed, there is no way to
report back to the API, so the API won't wait for the result */
- vSocketClose( ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData ) );
+ ( void ) vSocketClose( ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData ) );
break;
case eStackTxEvent :
/* The network stack has generated a packet to send. A
pointer to the generated buffer is located in the pvData
member of the received event structure. */
- vProcessGeneratedUDPPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
+ vProcessGeneratedUDPPacket( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ) );
break;
case eDHCPEvent:
/* The DHCP state machine needs processing. */
#if( ipconfigUSE_DHCP == 1 )
{
+ /* Process DHCP messages for a given end-point. */
vDHCPProcess( pdFALSE );
}
#endif /* ipconfigUSE_DHCP */
@@ -456,7 +460,17 @@ struct freertos_sockaddr xAddress;
and update the socket field xSocketBits. */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
- vSocketSelect( ( SocketSelect_t * ) ( xReceivedEvent.pvData ) );
+ #if( ipconfigSELECT_USES_NOTIFY != 0 )
+ {
+ SocketSelectMessage_t *pxMessage = ipPOINTER_CAST( SocketSelectMessage_t *, xReceivedEvent.pvData );
+ vSocketSelect( pxMessage->pxSocketSet );
+ ( void ) xTaskNotifyGive( pxMessage->xTaskhandle );
+ }
+ #else
+ {
+ vSocketSelect( ipPOINTER_CAST( SocketSelect_t *, xReceivedEvent.pvData ) );
+ }
+ #endif /* ( ipconfigSELECT_USES_NOTIFY != 0 ) */
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
break;
@@ -466,7 +480,7 @@ struct freertos_sockaddr xAddress;
{
/* Some task wants to signal the user of this socket in
order to interrupt a call to recv() or a call to select(). */
- FreeRTOS_SignalSocket( ( Socket_t ) xReceivedEvent.pvData );
+ ( void ) FreeRTOS_SignalSocket( ipPOINTER_CAST( Socket_t, xReceivedEvent.pvData ) );
}
#endif /* ipconfigSUPPORT_SIGNALS */
break;
@@ -487,11 +501,11 @@ struct freertos_sockaddr xAddress;
received a new connection. */
#if( ipconfigUSE_TCP == 1 )
{
- pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData );
if( xTCPCheckNewClient( pxSocket ) != pdFALSE )
{
- pxSocket->xEventBits |= eSOCKET_ACCEPT;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT;
vSocketWakeUpUser( pxSocket );
}
}
@@ -508,6 +522,10 @@ struct freertos_sockaddr xAddress;
#endif /* ipconfigUSE_TCP */
break;
+ case eNoEvent:
+ /* xQueueReceive() returned because of a normal time-out. */
+ break;
+
default :
/* Should not get here. */
break;
@@ -516,8 +534,10 @@ struct freertos_sockaddr xAddress;
if( xNetworkDownEventPending != pdFALSE )
{
/* A network down event could not be posted to the network event
- queue because the queue was full. Try posting again. */
- FreeRTOS_NetworkDown();
+ queue because the queue was full.
+ As this code runs in the IP-task, it can be done directly by
+ calling prvProcessNetworkDownEvent(). */
+ prvProcessNetworkDownEvent();
}
}
}
@@ -616,7 +636,7 @@ TickType_t xMaximumSleepTime;
#if( ipconfigDNS_USE_CALLBACKS != 0 )
{
- if( xDNSTimer.bActive != pdFALSE )
+ if( xDNSTimer.bActive != pdFALSE_UNSIGNED )
{
if( xDNSTimer.ulRemainingTime < xMaximumSleepTime )
{
@@ -635,7 +655,7 @@ static void prvCheckNetworkTimers( void )
/* Is it time for ARP processing? */
if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
{
- xSendEventToIPTask( eARPTimerEvent );
+ ( void ) xSendEventToIPTask( eARPTimerEvent );
}
#if( ipconfigUSE_DHCP == 1 )
@@ -643,15 +663,13 @@ static void prvCheckNetworkTimers( void )
/* Is it time for DHCP processing? */
if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )
{
- xSendEventToIPTask( eDHCPEvent );
+ ( void ) xSendEventToIPTask( eDHCPEvent );
}
}
#endif /* ipconfigUSE_DHCP */
#if( ipconfigDNS_USE_CALLBACKS != 0 )
{
- extern void vDNSCheckCallBack( void *pvSearchID );
-
/* Is it time for DNS processing? */
if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
{
@@ -666,7 +684,9 @@ static void prvCheckNetworkTimers( void )
TickType_t xNextTime;
BaseType_t xCheckTCPSockets;
- if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0u )
+ /* If the IP task has messages waiting to be processed then
+ it will not sleep in any case. */
+ if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
{
xWillSleep = pdTRUE;
}
@@ -736,8 +756,14 @@ BaseType_t xReturn;
{
/* The timer might have set the bExpired flag already, if not, check the
value of xTimeOut against ulRemainingTime. */
- if( ( pxTimer->bExpired != pdFALSE_UNSIGNED ) ||
- ( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE ) )
+ if( pxTimer->bExpired == pdFALSE_UNSIGNED )
+ {
+ if( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE )
+ {
+ pxTimer->bExpired = pdTRUE_UNSIGNED;
+ }
+ }
+ if( pxTimer->bExpired != pdFALSE_UNSIGNED )
{
prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
xReturn = pdTRUE;
@@ -772,7 +798,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
iptraceNETWORK_DOWN();
}
/*-----------------------------------------------------------*/
-
+/* Utility function. Process Network Down event from ISR. */
BaseType_t FreeRTOS_NetworkDownFromISR( void )
{
static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
@@ -794,29 +820,29 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
}
/*-----------------------------------------------------------*/
-void *FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
+void *FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes, TickType_t uxBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
void *pvReturn;
+TickType_t uxBlockTime = uxBlockTimeTicks;
/* Cap the block time. The reason for this is explained where
ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined (assuming an official
FreeRTOSIPConfig.h header file is being used). */
- if( xBlockTimeTicks > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
+ if( uxBlockTime > ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ) )
{
- xBlockTimeTicks = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
+ uxBlockTime = ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS );
}
/* Obtain a network buffer with the required amount of storage. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + xRequestedSizeBytes, xBlockTimeTicks );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + uxRequestedSizeBytes, uxBlockTime );
if( pxNetworkBuffer != NULL )
{
/* Set the actual packet size in case a bigger buffer was returned. */
- pxNetworkBuffer->xDataLength = sizeof( UDPPacket_t ) + xRequestedSizeBytes;
-
- /* Leave space for the UPD header. */
- pvReturn = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
+ pxNetworkBuffer->xDataLength = sizeof( UDPPacket_t ) + uxRequestedSizeBytes;
+ /* Skip 3 headers. */
+ pvReturn = &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( UDPPacket_t ) ] );
}
else
{
@@ -827,7 +853,7 @@ void *pvReturn;
}
/*-----------------------------------------------------------*/
-NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
+NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer,
size_t uxNewLength )
{
NetworkBufferDescriptor_t * pxNewBuffer;
@@ -847,7 +873,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
pxNewBuffer->ulIPAddress = pxNetworkBuffer->ulIPAddress;
pxNewBuffer->usPort = pxNetworkBuffer->usPort;
pxNewBuffer->usBoundPort = pxNetworkBuffer->usBoundPort;
- memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
+ ( void ) memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
}
return pxNewBuffer;
@@ -858,7 +884,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer )
{
- uint8_t *pucBuffer;
+ const uint8_t *pucBuffer;
NetworkBufferDescriptor_t *pxResult;
if( pvBuffer == NULL )
@@ -868,7 +894,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
else
{
/* Obtain the network buffer from the zero copy pointer. */
- pucBuffer = ( uint8_t * ) pvBuffer;
+ pucBuffer = ipPOINTER_CAST( const uint8_t *, pvBuffer );
/* The input here is a pointer to a payload buffer. Subtract the
size of the header in the network buffer, usually 8 + 2 bytes. */
@@ -876,9 +902,9 @@ NetworkBufferDescriptor_t * pxNewBuffer;
/* Here a pointer was placed to the network descriptor. As a
pointer is dereferenced, make sure it is well aligned. */
- if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - ( size_t ) 1 ) ) == ( uint32_t ) 0 )
+ if( ( ( ( size_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1U ) ) == ( size_t ) 0U )
{
- pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
+ pxResult = * ( ipPOINTER_CAST( NetworkBufferDescriptor_t **, pucBuffer ) );
}
else
{
@@ -892,9 +918,9 @@ NetworkBufferDescriptor_t * pxNewBuffer;
#endif /* ipconfigZERO_COPY_TX_DRIVER != 0 */
/*-----------------------------------------------------------*/
-NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )
+NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( const void * pvBuffer )
{
-uint8_t *pucBuffer;
+const uint8_t *pucBuffer;
NetworkBufferDescriptor_t *pxResult;
if( pvBuffer == NULL )
@@ -904,21 +930,21 @@ NetworkBufferDescriptor_t *pxResult;
else
{
/* Obtain the network buffer from the zero copy pointer. */
- pucBuffer = ( uint8_t * ) pvBuffer;
+ pucBuffer = ipPOINTER_CAST( const uint8_t *, pvBuffer );
/* The input here is a pointer to a payload buffer. Subtract
the total size of a UDP/IP header plus the size of the header in
the network buffer, usually 8 + 2 bytes. */
- pucBuffer -= ( sizeof( UDPPacket_t ) + ipBUFFER_PADDING );
+ pucBuffer -= ( sizeof( UDPPacket_t ) + ( ( size_t ) ipBUFFER_PADDING ) );
/* Here a pointer was placed to the network descriptor,
As a pointer is dereferenced, make sure it is well aligned */
- if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 )
+ if( ( ( ( size_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1U ) ) == 0U )
{
/* The following statement may trigger a:
warning: cast increases required alignment of target type [-Wcast-align].
It has been confirmed though that the alignment is suitable. */
- pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
+ pxResult = * ( ipPOINTER_CAST( NetworkBufferDescriptor_t **, pucBuffer ) );
}
else
{
@@ -930,7 +956,7 @@ NetworkBufferDescriptor_t *pxResult;
}
/*-----------------------------------------------------------*/
-void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer )
+void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer )
{
vReleaseNetworkBufferAndDescriptor( pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer ) );
}
@@ -949,16 +975,21 @@ BaseType_t xReturn = pdFALSE;
configASSERT( xNetworkEventQueue == NULL );
configASSERT( xIPTaskHandle == NULL );
- /* Check structure packing is correct. */
- configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );
- configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );
- configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );
- configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );
- configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );
-
+ #ifndef _lint
+ {
+ /* Check if MTU is big enough. */
+ configASSERT( ( ( size_t ) ipconfigNETWORK_MTU ) >= ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + ipconfigTCP_MSS ) );
+ /* Check structure packing is correct. */
+ configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );
+ configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );
+ configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );
+ configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );
+ configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );
+ }
+ #endif
/* Attempt to create the queue used to communicate with the IP task. */
xNetworkEventQueue = xQueueCreate( ( UBaseType_t ) ipconfigEVENT_QUEUE_LENGTH, ( UBaseType_t ) sizeof( IPStackEvent_t ) );
- configASSERT( xNetworkEventQueue );
+ configASSERT( xNetworkEventQueue != NULL );
if( xNetworkEventQueue != NULL )
{
@@ -980,7 +1011,7 @@ BaseType_t xReturn = pdFALSE;
xNetworkAddressing.ulDNSServerAddress = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );
xNetworkAddressing.ulBroadcastAddress = ( xNetworkAddressing.ulDefaultIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
- memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
+ ( void ) memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
#if ipconfigUSE_DHCP == 1
{
@@ -994,7 +1025,7 @@ BaseType_t xReturn = pdFALSE;
/* Added to prevent ARP flood to gateway. Ensure the
gateway is on the same subnet as the IP address. */
- if( xNetworkAddressing.ulGatewayAddress != 0ul )
+ if( xNetworkAddressing.ulGatewayAddress != 0UL )
{
configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) );
}
@@ -1003,16 +1034,18 @@ BaseType_t xReturn = pdFALSE;
/* The MAC address is stored in the start of the default packet
header fragment, which is used when sending UDP packets. */
- memcpy( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
/* Prepare the sockets interface. */
- xReturn = vNetworkSocketsInit();
-
- if( pdTRUE == xReturn )
- {
- /* Create the task that processes Ethernet and stack events. */
- xReturn = xTaskCreate( prvIPTask, "IP-task", ( uint16_t )ipconfigIP_TASK_STACK_SIZE_WORDS, NULL, ( UBaseType_t )ipconfigIP_TASK_PRIORITY, &xIPTaskHandle );
- }
+ vNetworkSocketsInit();
+
+ /* Create the task that processes Ethernet and stack events. */
+ xReturn = xTaskCreate( prvIPTask,
+ "IP-task",
+ ( uint16_t )ipconfigIP_TASK_STACK_SIZE_WORDS,
+ NULL,
+ ( UBaseType_t )ipconfigIP_TASK_PRIORITY,
+ &( xIPTaskHandle ) );
}
else
{
@@ -1032,7 +1065,10 @@ BaseType_t xReturn = pdFALSE;
}
/*-----------------------------------------------------------*/
-void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress )
+void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress,
+ uint32_t *pulNetMask,
+ uint32_t *pulGatewayAddress,
+ uint32_t *pulDNSServerAddress )
{
/* Return the address configuration to the caller. */
@@ -1058,7 +1094,10 @@ void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetM
}
/*-----------------------------------------------------------*/
-void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress )
+void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress,
+ const uint32_t *pulNetMask,
+ const uint32_t *pulGatewayAddress,
+ const uint32_t *pulDNSServerAddress )
{
/* Update the address configuration. */
@@ -1086,22 +1125,39 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
- BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks )
+ BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t uxNumberOfBytesToSend, TickType_t uxBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
ICMPHeader_t *pxICMPHeader;
+ EthernetHeader_t *pxEthernetHeader;
BaseType_t xReturn = pdFAIL;
static uint16_t usSequenceNumber = 0;
uint8_t *pucChar;
+ size_t uxTotalLength;
IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
- if( (xNumberOfBytesToSend >= 1 ) && ( xNumberOfBytesToSend < ( ( ipconfigNETWORK_MTU - sizeof( IPHeader_t ) ) - sizeof( ICMPHeader_t ) ) ) && ( uxGetNumberOfFreeNetworkBuffers() >= 3 ) )
+ uxTotalLength = uxNumberOfBytesToSend + sizeof( ICMPPacket_t );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxTotalLength, uxBlockTimeTicks );
+
+ if( pxNetworkBuffer != NULL )
{
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xNumberOfBytesToSend + sizeof( ICMPPacket_t ), xBlockTimeTicks );
+ BaseType_t xEnoughSpace;
- if( pxNetworkBuffer != NULL )
+ if( uxNumberOfBytesToSend < ( ipconfigNETWORK_MTU - ( sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) ) ) )
+ {
+ xEnoughSpace = pdTRUE;
+ }
+ else
+ {
+ xEnoughSpace = pdFALSE;
+ }
+ if( ( uxGetNumberOfFreeNetworkBuffers() >= 3U ) && ( uxNumberOfBytesToSend >= 1U ) && ( xEnoughSpace != pdFALSE ) )
{
- pxICMPHeader = ( ICMPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] );
+ pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
+ pxEthernetHeader->usFrameType = ipIPv4_FRAME_TYPE;
+
+
+ pxICMPHeader = ipPOINTER_CAST( ICMPHeader_t *, &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] ) );
usSequenceNumber++;
/* Fill in the basic header information. */
@@ -1112,10 +1168,10 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
/* Find the start of the data. */
pucChar = ( uint8_t * ) pxICMPHeader;
- pucChar += sizeof( ICMPHeader_t );
+ pucChar = &(pucChar[ sizeof( ICMPHeader_t ) ] );
/* Just memset the data to a fixed value. */
- memset( ( void * ) pucChar, ( int ) ipECHO_DATA_FILL_BYTE, xNumberOfBytesToSend );
+ ( void ) memset( pucChar, ( int ) ipECHO_DATA_FILL_BYTE, uxNumberOfBytesToSend );
/* The message is complete, IP and checksum's are handled by
vProcessGeneratedUDPPacket */
@@ -1123,19 +1179,19 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
pxNetworkBuffer->ulIPAddress = ulIPAddress;
pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA;
/* xDataLength is the size of the total packet, including the Ethernet header. */
- pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPPacket_t );
+ pxNetworkBuffer->xDataLength = uxTotalLength;
/* Send to the stack. */
xStackTxEvent.pvData = pxNetworkBuffer;
- if( xSendEventStructToIPTask( &xStackTxEvent, xBlockTimeTicks) != pdPASS )
+ if( xSendEventStructToIPTask( &( xStackTxEvent ), uxBlockTimeTicks ) != pdPASS )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
}
else
{
- xReturn = usSequenceNumber;
+ xReturn = ( BaseType_t ) usSequenceNumber;
}
}
}
@@ -1163,9 +1219,10 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
}
/*-----------------------------------------------------------*/
-BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout )
+BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t uxTimeout )
{
BaseType_t xReturn, xSendMessage;
+TickType_t uxUseTimeout = uxTimeout;
if( ( xIPIsNetworkTaskReady() == pdFALSE ) && ( pxEvent->eEventType != eNetworkDownEvent ) )
{
@@ -1186,7 +1243,7 @@ BaseType_t xReturn, xSendMessage;
IP task is already awake processing other message. */
xTCPTimer.bExpired = pdTRUE_UNSIGNED;
- if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0u )
+ if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U )
{
/* Not actually going to send the message but this is not a
failure as the message didn't need to be sent. */
@@ -1200,12 +1257,12 @@ BaseType_t xReturn, xSendMessage;
{
/* The IP task cannot block itself while waiting for itself to
respond. */
- if( ( xIsCallingFromIPTask() == pdTRUE ) && ( xTimeout > ( TickType_t ) 0 ) )
+ if( ( xIsCallingFromIPTask() == pdTRUE ) && ( uxUseTimeout > ( TickType_t ) 0U ) )
{
- xTimeout = ( TickType_t ) 0;
+ uxUseTimeout = ( TickType_t ) 0;
}
- xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, xTimeout );
+ xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout );
if( xReturn == pdFAIL )
{
@@ -1231,21 +1288,22 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
eFrameProcessingResult_t eReturn;
const EthernetHeader_t *pxEthernetHeader;
- pxEthernetHeader = ( const EthernetHeader_t * ) pucEthernetBuffer;
+ /* Map the buffer onto Ethernet Header struct for easy access to fields. */
+ pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
- if( memcmp( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) &( pxEthernetHeader->xDestinationAddress ), sizeof( MACAddress_t ) ) == 0 )
+ if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
- /* The packet was directed to this node directly - process it. */
+ /* The packet was directed to this node - process it. */
eReturn = eProcessBuffer;
}
- else if( memcmp( ( void * ) xBroadcastMACAddress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
+ else if( memcmp( xBroadcastMACAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
/* The packet was a broadcast - process it. */
eReturn = eProcessBuffer;
}
else
#if( ipconfigUSE_LLMNR == 1 )
- if( memcmp( ( void * ) xLLMNR_MacAdress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
+ if( memcmp( xLLMNR_MacAdress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
/* The packet is a request for LLMNR - process it. */
eReturn = eProcessBuffer;
@@ -1323,7 +1381,7 @@ static void prvProcessNetworkDownEvent( void )
{
/* The network is not up until DHCP has completed. */
vDHCPProcess( pdTRUE );
- xSendEventToIPTask( eDHCPEvent );
+ ( void ) xSendEventToIPTask( eDHCPEvent );
}
#else
{
@@ -1361,18 +1419,23 @@ void vIPNetworkUpCalls( void )
static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
-EthernetHeader_t *pxEthernetHeader;
+const EthernetHeader_t *pxEthernetHeader;
eFrameProcessingResult_t eReturned = eReleaseBuffer;
- configASSERT( pxNetworkBuffer );
+ configASSERT( pxNetworkBuffer != NULL );
/* Interpret the Ethernet frame. */
if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
{
eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
- pxEthernetHeader = ( EthernetHeader_t * )( pxNetworkBuffer->pucEthernetBuffer );
+ /* Map the buffer onto the Ethernet Header struct for easy access to the fields. */
+ pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
+
+ /* The condition "eReturned == eProcessBuffer" must be true. */
+ #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
if( eReturned == eProcessBuffer )
+ #endif
{
/* Interpret the received Ethernet packet. */
switch( pxEthernetHeader->usFrameType )
@@ -1381,7 +1444,7 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
/* The Ethernet frame contains an ARP packet. */
if( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) )
{
- eReturned = eARPProcessPacket( ( ARPPacket_t * )pxNetworkBuffer->pucEthernetBuffer );
+ eReturned = eARPProcessPacket( ipPOINTER_CAST( ARPPacket_t *, pxNetworkBuffer->pucEthernetBuffer ) );
}
else
{
@@ -1393,7 +1456,7 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
/* The Ethernet frame contains an IP packet. */
if( pxNetworkBuffer->xDataLength >= sizeof( IPPacket_t ) )
{
- eReturned = prvProcessIPPacket( ( IPPacket_t * )pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer );
+ eReturned = prvProcessIPPacket( ipPOINTER_CAST( IPPacket_t *, pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer );
}
else
{
@@ -1426,6 +1489,8 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
yet. */
break;
+ case eReleaseBuffer :
+ case eProcessBuffer :
default :
/* The frame is not being used anywhere, and the
NetworkBufferDescriptor_t structure containing the frame should
@@ -1436,8 +1501,38 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
}
/*-----------------------------------------------------------*/
+BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress )
+{
+BaseType_t xReturn;
+uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress );
+
+ if( ( ulIP >= ipFIRST_MULTI_CAST_IPv4 ) && ( ulIP < ipLAST_MULTI_CAST_IPv4 ) )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress, MACAddress_t *pxMACAddress )
+{
+uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress );
+
+ pxMACAddress->ucBytes[ 0 ] = ( uint8_t ) 0x01U;
+ pxMACAddress->ucBytes[ 1 ] = ( uint8_t ) 0x00U;
+ pxMACAddress->ucBytes[ 2 ] = ( uint8_t ) 0x5EU;
+ pxMACAddress->ucBytes[ 3 ] = ( uint8_t ) ( ( ulIP >> 16 ) & 0x7fU ); /* Use 7 bits. */
+ pxMACAddress->ucBytes[ 4 ] = ( uint8_t ) ( ( ulIP >> 8 ) & 0xffU ); /* Use 8 bits. */
+ pxMACAddress->ucBytes[ 5 ] = ( uint8_t ) ( ( ulIP ) & 0xffU ); /* Use 8 bits. */
+}
+/*-----------------------------------------------------------*/
+
static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
- NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )
+ const NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )
{
eFrameProcessingResult_t eReturn = eProcessBuffer;
@@ -1464,9 +1559,10 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Can not handle, fragmented packet. */
eReturn = eReleaseBuffer;
}
- /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
- * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
- else if( ( pxIPHeader->ucVersionHeaderLength < 0x45u ) || ( pxIPHeader->ucVersionHeaderLength > 0x4Fu ) )
+ /* Test if the length of the IP-header is between 20 and 60 bytes,
+ and if the IP-version is 4. */
+ else if( ( pxIPHeader->ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
+ ( pxIPHeader->ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
{
/* Can not handle, unknown or invalid header version. */
eReturn = eReleaseBuffer;
@@ -1487,6 +1583,10 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Packet is not for this node, release it */
eReturn = eReleaseBuffer;
}
+ else
+ {
+ /* Packet is not fragemented, destination is this device. */
+ }
}
#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
@@ -1498,7 +1598,7 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
{
/* Is the IP header checksum correct? */
if( ( pxIPHeader->ucProtocol != ( uint8_t ) ipPROTOCOL_ICMP ) &&
- ( usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )
+ ( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )
{
/* Check sum in IP-header not correct. */
eReturn = eReleaseBuffer;
@@ -1509,12 +1609,66 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Protocol checksum not accepted. */
eReturn = eReleaseBuffer;
}
+ else
+ {
+ /* The checksum of the received packet is OK. */
+ }
}
}
#else
{
+
+ if (eReturn == eProcessBuffer )
+ {
+ if( xCheckSizeFields( ( uint8_t * )( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength ) != pdPASS )
+ {
+ /* Some of the length checks were not successful. */
+ eReturn = eReleaseBuffer;
+ }
+ }
+
+ #if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
+ {
+ /* Check if this is a UDP packet without a checksum. */
+ if (eReturn == eProcessBuffer )
+ {
+ /* ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is defined as 0,
+ and so UDP packets carrying a protocol checksum of 0, will
+ be dropped. */
+
+ /* Identify the next protocol. */
+ if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ ProtocolPacket_t *pxProtPack;
+ const uint16_t *pusChecksum;
+
+ /* pxProtPack will point to the offset were the protocols begin. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+ pusChecksum = ( const uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
+ if( *pusChecksum == ( uint16_t ) 0U )
+ {
+ #if( ipconfigHAS_PRINTF != 0 )
+ {
+ static BaseType_t xCount = 0;
+
+ if( xCount < 5 )
+ {
+ FreeRTOS_printf( ( "prvAllowIPPacket: UDP packet from %xip without CRC dropped\n",
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
+ xCount++;
+ }
+ }
+ #endif /* ( ipconfigHAS_PRINTF != 0 ) */
+
+ /* Protocol checksum not accepted. */
+ eReturn = eReleaseBuffer;
+ }
+ }
+ }
+ }
+ #endif /* ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 ) */
+
/* to avoid warning unused parameters */
- ( void ) pxNetworkBuffer;
( void ) uxHeaderLength;
}
#endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */
@@ -1523,11 +1677,12 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
}
/*-----------------------------------------------------------*/
-static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )
+static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
eFrameProcessingResult_t eReturn;
IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
-UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( pxIPHeader->ucVersionHeaderLength & 0x0Fu ) << 2 );
+size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
+UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( uxLength & 0x0FU ) << 2 );
uint8_t ucProtocol;
/* Bound the calculated header length: take away the Ethernet header size,
@@ -1536,142 +1691,166 @@ uint8_t ucProtocol;
if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
{
- return eReleaseBuffer;
+ eReturn = eReleaseBuffer;
}
-
- ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
- /* Check if the IP headers are acceptable and if it has our destination. */
- eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
-
- if( eReturn == eProcessBuffer )
+ else
{
- if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
- {
- /* All structs of headers expect a IP header size of 20 bytes
- * IP header options were included, we'll ignore them and cut them out
- * Note: IP options are mostly use in Multi-cast protocols */
- const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
- /* From: the previous start of UDP/ICMP/TCP data */
- uint8_t *pucSource = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + uxHeaderLength);
- /* To: the usual start of UDP/ICMP/TCP data at offset 20 from IP header */
- uint8_t *pucTarget = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER);
- /* How many: total length minus the options and the lower headers */
- const size_t xMoveLen = pxNetworkBuffer->xDataLength - optlen - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_ETH_HEADER;
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+ /* Check if the IP headers are acceptable and if it has our destination. */
+ eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
- memmove( pucTarget, pucSource, xMoveLen );
- pxNetworkBuffer->xDataLength -= optlen;
-
- /* Fix-up new version/header length field in IP packet. */
- pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0 ) | /* High nibble is the version. */
- ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0F ); /* Low nibble is the header size, in bytes, divided by four. */
- }
-
- /* Add the IP and MAC addresses to the ARP table if they are not
- already there - otherwise refresh the age of the existing
- entry. */
- if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
- {
- /* Refresh the ARP cache with the IP/MAC-address of the received packet
- * For UDP packets, this will be done later in xProcessReceivedUDPPacket()
- * as soon as know that the message will be handled by someone
- * This will prevent that the ARP cache will get overwritten
- * with the IP-address of useless broadcast packets
- */
- vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
- }
- switch( ucProtocol )
+ if( eReturn == eProcessBuffer )
{
- case ipPROTOCOL_ICMP :
- /* The IP packet contained an ICMP frame. Don't bother
- checking the ICMP checksum, as if it is wrong then the
- wrong data will also be returned, and the source of the
- ping will know something went wrong because it will not
- be able to validate what it receives. */
- #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
+ /* Are there IP-options. */
+ if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
+ {
+ /* The size of the IP-header is larger than 20 bytes.
+ The extra space is used for IP-options. */
+ #if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
{
- if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
- {
- ICMPPacket_t *pxICMPPacket = ( ICMPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer );
- if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
- {
- eReturn = prvProcessICMPPacket( pxICMPPacket );
- }
- }
- else
- {
- eReturn = eReleaseBuffer;
- }
+ /* All structs of headers expect a IP header size of 20 bytes
+ * IP header options were included, we'll ignore them and cut them out. */
+ const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
+ /* From: the previous start of UDP/ICMP/TCP data. */
+ const uint8_t *pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
+ /* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
+ uint8_t *pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
+ /* How many: total length minus the options and the lower headers. */
+ const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
+
+ ( void ) memmove( pucTarget, pucSource, xMoveLen );
+ pxNetworkBuffer->xDataLength -= optlen;
+
+ /* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
+ pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
+ ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
}
- #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
- break;
-
- case ipPROTOCOL_UDP :
+ #else
{
- /* The IP packet contained a UDP frame. */
- UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+ /* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
+ IP-options will be dropped. */
+ eReturn = eReleaseBuffer;
+ }
+ #endif
+ }
- /* Only proceed if the payload length indicated in the header
- appears to be valid. */
- if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) && ( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) >= sizeof( UDPHeader_t ) ) )
- {
- size_t uxPayloadSize_1, uxPayloadSize_2;
- /* The UDP payload size can be calculated by subtracting the
- * header size from `xDataLength`.
- * However, the `xDataLength` may be longer that expected,
- * e.g. when a small packet is padded with zero's.
- * The UDP header contains a field `usLength` reflecting
- * the payload size plus the UDP header ( 8 bytes ).
- * Set `xDataLength` to the size of the headers,
- * plus the lower of the two calculated payload sizes.
- */
-
- uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
- uxPayloadSize_2 = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t );
- if( uxPayloadSize_1 > uxPayloadSize_2 )
+ if( eReturn != eReleaseBuffer )
+ {
+ /* Add the IP and MAC addresses to the ARP table if they are not
+ already there - otherwise refresh the age of the existing
+ entry. */
+ if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ /* Refresh the ARP cache with the IP/MAC-address of the received
+ packet. For UDP packets, this will be done later in
+ xProcessReceivedUDPPacket(), as soon as it's know that the message
+ will be handled. This will prevent the ARP cache getting
+ overwritten with the IP address of useless broadcast packets. */
+ vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
+ }
+ switch( ucProtocol )
+ {
+ case ipPROTOCOL_ICMP :
+ /* The IP packet contained an ICMP frame. Don't bother checking
+ the ICMP checksum, as if it is wrong then the wrong data will
+ also be returned, and the source of the ping will know something
+ went wrong because it will not be able to validate what it
+ receives. */
+ #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
{
- pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
+ if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
+ {
+ /* Map the buffer onto a ICMP-Packet struct to easily access the
+ * fields of ICMP packet. */
+ ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
+ {
+ eReturn = prvProcessICMPPacket( pxICMPPacket );
+ }
+ }
+ else
+ {
+ eReturn = eReleaseBuffer;
+ }
}
+ #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
+ break;
- /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
- pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
- pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
-
- /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
- * In some cases, the upper-layer checksum has been calculated
- * by the NIC driver.
- *
- * Pass the packet payload to the UDP sockets implementation. */
- if( xProcessReceivedUDPPacket( pxNetworkBuffer,
- pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
+ case ipPROTOCOL_UDP :
{
- eReturn = eFrameConsumed;
+ /* The IP packet contained a UDP frame. */
+
+ /* Map the buffer onto a UDP-Packet struct to easily access the
+ * fields of UDP packet. */
+ const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ uint16_t usLength;
+
+ /* Note the header values required prior to the checksum
+ generation as the checksum pseudo header may clobber some of
+ these values. */
+ usLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength );
+ if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) &&
+ ( ( ( size_t ) usLength ) >= sizeof( UDPHeader_t ) ) )
+ {
+ size_t uxPayloadSize_1, uxPayloadSize_2;
+ /* Ensure that downstream UDP packet handling has the lesser
+ of: the actual network buffer Ethernet frame length, or
+ the sender's UDP packet header payload length, minus the
+ size of the UDP header.
+
+ The size of the UDP packet structure in this implementation
+ includes the size of the Ethernet header, the size of
+ the IP header, and the size of the UDP header. */
+ uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
+ uxPayloadSize_2 = ( ( size_t ) usLength ) - sizeof( UDPHeader_t );
+ if( uxPayloadSize_1 > uxPayloadSize_2 )
+ {
+ pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
+ }
+
+ /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
+ pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
+ pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
+
+ /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
+ In some cases, the upper-layer checksum has been calculated
+ by the NIC driver. */
+
+ /* Pass the packet payload to the UDP sockets
+ implementation. */
+ if( xProcessReceivedUDPPacket( pxNetworkBuffer,
+ pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
+ {
+ eReturn = eFrameConsumed;
+ }
+ }
+ else
+ {
+ eReturn = eReleaseBuffer;
+ }
}
- }
- else
- {
- eReturn = eReleaseBuffer;
- }
- }
- break;
+ break;
#if ipconfigUSE_TCP == 1
- case ipPROTOCOL_TCP :
- {
+ case ipPROTOCOL_TCP :
+ {
- if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
- {
- eReturn = eFrameConsumed;
- }
+ if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
+ {
+ eReturn = eFrameConsumed;
+ }
- /* Setting this variable will cause xTCPTimerCheck()
- to be called just before the IP-task blocks. */
- xProcessedTCPMessage++;
- }
- break;
+ /* Setting this variable will cause xTCPTimerCheck()
+ to be called just before the IP-task blocks. */
+ xProcessedTCPMessage++;
+ }
+ break;
#endif
- default :
- /* Not a supported frame type. */
- break;
+ default :
+ /* Not a supported frame type. */
+ break;
+ }
+ }
}
}
@@ -1703,12 +1882,12 @@ uint8_t ucProtocol;
/* Find the first byte of the data within the ICMP packet. */
pucByte = ( uint8_t * ) pxICMPPacket;
- pucByte += sizeof( ICMPPacket_t );
+ pucByte = &( pucByte[ sizeof( ICMPPacket_t ) ] );
/* Check each byte. */
for( usCount = 0; usCount < usDataLength; usCount++ )
{
- if( *pucByte != ipECHO_DATA_FILL_BYTE )
+ if( *pucByte != ( uint8_t ) ipECHO_DATA_FILL_BYTE )
{
eStatus = eInvalidData;
break;
@@ -1754,17 +1933,13 @@ uint8_t ucProtocol;
usRequest = ( uint16_t ) ( ( uint16_t )ipICMP_ECHO_REQUEST << 8 );
- if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFu - usRequest ) )
+ if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFU - usRequest ) )
{
- pxICMPHeader->usChecksum = ( uint16_t )
- ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
- FreeRTOS_htons( usRequest + 1UL ) );
+ pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest + 1U );
}
else
{
- pxICMPHeader->usChecksum = ( uint16_t )
- ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
- FreeRTOS_htons( usRequest ) );
+ pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest );
}
return eReturnEthernetFrame;
}
@@ -1798,6 +1973,7 @@ uint8_t ucProtocol;
break;
default :
+ /* Only ICMP echo packets are handled. */
break;
}
@@ -1807,6 +1983,126 @@ uint8_t ucProtocol;
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
/*-----------------------------------------------------------*/
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
+ /* Although the driver will take care of checksum calculations,
+ the IP-task will still check if the length fields are OK. */
+ static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength )
+ {
+ size_t uxLength;
+ const IPPacket_t * pxIPPacket;
+ UBaseType_t uxIPHeaderLength;
+ ProtocolPacket_t *pxProtPack;
+ uint8_t ucProtocol;
+ uint16_t usLength;
+ uint16_t ucVersionHeaderLength;
+ BaseType_t xLocation = 0;
+ size_t uxMinimumLength;
+ BaseType_t xResult = pdFAIL;
+
+ do
+ {
+ /* Check for minimum packet size: Ethernet header and an IP-header, 34 bytes */
+ if( uxBufferLength < sizeof( IPPacket_t ) )
+ {
+ xLocation = 1;
+ break;
+ }
+
+ /* Map the buffer onto a IP-Packet struct to easily access the
+ * fields of the IP packet. */
+ pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
+
+ ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
+ /* Test if the length of the IP-header is between 20 and 60 bytes,
+ and if the IP-version is 4. */
+ if( ( ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
+ ( ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
+ {
+ xLocation = 2;
+ break;
+ }
+ ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
+ uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
+
+ /* Check if the complete IP-header is transferred. */
+ if( uxBufferLength < ( ipSIZE_OF_ETH_HEADER + uxIPHeaderLength ) )
+ {
+ xLocation = 3;
+ break;
+ }
+ /* Check if the complete IP-header plus protocol data have been transferred: */
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
+ {
+ xLocation = 4;
+ break;
+ }
+
+ /* Identify the next protocol. */
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+
+ /* If this IP packet header includes Options, then the following
+ assignment results in a pointer into the protocol packet with the Ethernet
+ and IP headers incorrectly aligned. However, either way, the "third"
+ protocol (Layer 3 or 4) header will be aligned, which is the convenience
+ of this calculation. */
+ /* Map the Buffer onto the Protocol Packet struct for easy access to the
+ * struct fields. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+
+ /* Switch on the Layer 3/4 protocol. */
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ /* Expect at least a complete UDP header. */
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER;
+ }
+ else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
+ {
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER;
+ }
+ else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
+ ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
+ {
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER;
+ }
+ else
+ {
+ /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
+ xLocation = 5;
+ break;
+ }
+ if( uxBufferLength < uxMinimumLength )
+ {
+ xLocation = 6;
+ break;
+ }
+
+ uxLength = ( size_t ) usLength;
+ uxLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally, minus 20. */
+
+ if( ( uxLength < ( ( size_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
+ ( uxLength > ( ( size_t ) ipconfigNETWORK_MTU - ( size_t ) uxIPHeaderLength ) ) )
+ {
+ /* For incoming packets, the length is out of bound: either
+ too short or too long. For outgoing packets, there is a
+ serious problem with the format/length. */
+ xLocation = 7;
+ break;
+ }
+ xResult = pdPASS;
+ } while( ipFALSE_BOOL );
+
+ if( xResult != pdPASS )
+ {
+ FreeRTOS_printf( ( "xCheckSizeFields: location %ld\n", xLocation ) );
+ }
+
+ return xResult;
+ }
+#endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
+/*-----------------------------------------------------------*/
+
uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength, BaseType_t xOutgoingPacket )
{
uint32_t ulLength;
@@ -1818,193 +2114,263 @@ uint8_t ucProtocol;
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
const char *pcType;
#endif
+uint16_t usLength;
+uint16_t ucVersionHeaderLength;
- /* Check for minimum packet size. */
- if( uxBufferLength < sizeof( IPPacket_t ) )
- {
- return ipINVALID_LENGTH;
- }
-
- /* Parse the packet length. */
- pxIPPacket = ( const IPPacket_t * ) pucEthernetBuffer;
- /* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
- Length field contains the length of the internet header in 32-bit words. */
- uxIPHeaderLength = ( UBaseType_t ) ( sizeof( uint32_t ) * ( pxIPPacket->xIPHeader.ucVersionHeaderLength & 0x0Fu ) );
+BaseType_t location = 0;
- /* Check for minimum packet size. */
- if( uxBufferLength < sizeof( IPPacket_t ) + uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER )
+ /* Introduce a do-while loop to allow use of break statements.
+ * Note: MISRA prohibits use of 'goto', thus replaced with breaks. */
+ do
{
- return ipINVALID_LENGTH;
- }
- if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) ) )
- {
- return ipINVALID_LENGTH;
- }
+ /* Check for minimum packet size. */
+ if( uxBufferLength < sizeof( IPPacket_t ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 1;
+ break;
+ }
- /* Identify the next protocol. */
- ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+ /* Parse the packet length. */
+ pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
- /* N.B., if this IP packet header includes Options, then the following
- assignment results in a pointer into the protocol packet with the Ethernet
- and IP headers incorrectly aligned. However, either way, the "third"
- protocol (Layer 3 or 4) header will be aligned, which is the convenience
- of this calculation. */
- pxProtPack = ( ProtocolPacket_t * ) ( pucEthernetBuffer + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) );
+ /* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
+ Length field contains the length of the internet header in 32-bit words. */
+ ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
+ ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
+ uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
- /* Switch on the Layer 3/4 protocol. */
- if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
+ /* Check for minimum packet size. */
+ if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
- return ipINVALID_LENGTH;
+ usChecksum = ipINVALID_LENGTH;
+ location = 2;
+ break;
}
-
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
- pcType = "UDP";
+ usChecksum = ipINVALID_LENGTH;
+ location = 3;
+ break;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
+
+ /* Identify the next protocol. */
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+
+ /* N.B., if this IP packet header includes Options, then the following
+ assignment results in a pointer into the protocol packet with the Ethernet
+ and IP headers incorrectly aligned. However, either way, the "third"
+ protocol (Layer 3 or 4) header will be aligned, which is the convenience
+ of this calculation. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+
+ /* Switch on the Layer 3/4 protocol. */
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
{
- return ipINVALID_LENGTH;
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 4;
+ break;
+ }
+
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ pcType = "UDP";
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
+ else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
+ {
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 5;
+ break;
+ }
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ pcType = "TCP";
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ }
+ else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
+ ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
{
- pcType = "TCP";
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 6;
+ break;
+ }
+
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+ {
+ pcType = "ICMP";
+ }
+ else
+ {
+ pcType = "IGMP";
+ }
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
- ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
+ else
{
- return ipINVALID_LENGTH;
+ /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
+ usChecksum = ipUNHANDLED_PROTOCOL;
+ location = 7;
+ break;
}
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ /* The protocol and checksum field have been identified. Check the direction
+ of the packet. */
+ if( xOutgoingPacket != pdFALSE )
+ {
+ /* This is an outgoing packet. Before calculating the checksum, set it
+ to zero. */
+ *( pusChecksum ) = 0U;
+ }
+ else if( ( *pusChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
- if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+ #if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
- pcType = "ICMP";
+ /* Sender hasn't set the checksum, drop the packet because
+ ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is not set. */
+ usChecksum = ipWRONG_CRC;
+ #if( ipconfigHAS_PRINTF != 0 )
+ {
+ static BaseType_t xCount = 0;
+
+ if( xCount < 5 )
+ {
+ FreeRTOS_printf( ( "usGenerateProtocolChecksum: UDP packet from %xip without CRC dropped\n",
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
+ xCount++;
+ }
+ }
+ #endif /* ( ipconfigHAS_PRINTF != 0 ) */
}
- else
+ #else
{
- pcType = "IGMP";
+ /* Sender hasn't set the checksum, no use to calculate it. */
+ usChecksum = ipCORRECT_CRC;
}
+ #endif
+ location = 8;
+ break;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else
- {
- /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
- return ipUNHANDLED_PROTOCOL;
- }
-
- /* The protocol and checksum field have been identified. Check the direction
- of the packet. */
- if( xOutgoingPacket != pdFALSE )
- {
- /* This is an outgoing packet. Before calculating the checksum, set it
- to zero. */
- *( pusChecksum ) = 0u;
- }
- else if( ( *pusChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
- {
- /* Sender hasn't set the checksum, no use to calculate it. */
- return ipCORRECT_CRC;
- }
-
- ulLength = ( uint32_t )
- ( FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) - ( ( uint16_t ) uxIPHeaderLength ) ); /* normally minus 20 */
-
- if( ( ulLength < sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ||
- ( ulLength > ( uint32_t )( ipconfigNETWORK_MTU - uxIPHeaderLength ) ) )
- {
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ else
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
+ /* Other incoming packet than UDP. */
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- /* Again, in a 16-bit return value there is no space to indicate an
- error. For incoming packets, 0x1234 will cause dropping of the packet.
- For outgoing packets, there is a serious problem with the
- format/length */
- return ipINVALID_LENGTH;
- }
- if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
- {
- /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
- usChecksum = ( uint16_t )
- ( ~usGenerateChecksum( 0UL,
- ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
- }
- else
- {
- /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
- fields */
- usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ ulLength = ( uint32_t ) usLength;
+ ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
- /* And then continue at the IPv4 source and destination addresses. */
- usChecksum = ( uint16_t )
- ( ~usGenerateChecksum( ( uint32_t ) usChecksum, ( uint8_t * )&( pxIPPacket->xIPHeader.ulSourceIPAddress ),
- ( 2u * sizeof( pxIPPacket->xIPHeader.ulSourceIPAddress ) + ulLength ) ) );
+ if( ( ulLength < ( ( uint32_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
+ ( ulLength > ( ( uint32_t ) ipconfigNETWORK_MTU - ( uint32_t ) uxIPHeaderLength ) ) )
+ {
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- /* Sum TCP header and data. */
- }
+ /* Again, in a 16-bit return value there is no space to indicate an
+ error. For incoming packets, 0x1234 will cause dropping of the packet.
+ For outgoing packets, there is a serious problem with the
+ format/length */
+ usChecksum = ipINVALID_LENGTH;
+ location = 9;
+ break;
+ }
+ if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
+ {
+ /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
+ usChecksum = ( uint16_t )
+ ( ~usGenerateChecksum( 0U,
+ ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
+ }
+ else
+ {
+ /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
+ fields */
+ usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
+
+ /* And then continue at the IPv4 source and destination addresses. */
+ usChecksum = ( uint16_t )
+ ( ~usGenerateChecksum( usChecksum,
+ ipPOINTER_CAST( const uint8_t *, &( pxIPPacket->xIPHeader.ulSourceIPAddress ) ),
+ ( size_t )( ( 2U * ipSIZE_OF_IPv4_ADDRESS ) + ulLength ) ) );
+ /* Sum TCP header and data. */
+ }
- if( xOutgoingPacket == pdFALSE )
- {
- /* This is in incoming packet. If the CRC is correct, it should be zero. */
- if( usChecksum == 0u )
+ if( xOutgoingPacket == pdFALSE )
{
- usChecksum = ( uint16_t )ipCORRECT_CRC;
+ /* This is in incoming packet. If the CRC is correct, it should be zero. */
+ if( usChecksum == 0U )
+ {
+ usChecksum = ( uint16_t )ipCORRECT_CRC;
+ }
}
- }
- else
- {
- if( ( usChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
+ else
{
- /* In case of UDP, a calculated checksum of 0x0000 is transmitted
- as 0xffff. A value of zero would mean that the checksum is not used. */
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
- if( xOutgoingPacket != pdFALSE )
+ /* In case of UDP, a calculated checksum of 0x0000 is transmitted
+ as 0xffff. A value of zero would mean that the checksum is not used. */
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
+ if( xOutgoingPacket != pdFALSE )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
+ }
}
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+
+ usChecksum = ( uint16_t )0xffffu;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ }
+ usChecksum = FreeRTOS_htons( usChecksum );
- usChecksum = ( uint16_t )0xffffu;
+ if( xOutgoingPacket != pdFALSE )
+ {
+ *( pusChecksum ) = usChecksum;
}
- }
- usChecksum = FreeRTOS_htons( usChecksum );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
+ pcType,
+ FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
+ FreeRTOS_ntohs( *pusChecksum ) ) );
+ }
+ else
+ {
+ /* Nothing. */
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ } while( ipFALSE_BOOL );
- if( xOutgoingPacket != pdFALSE )
- {
- *( pusChecksum ) = usChecksum;
- }
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
- else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
+ if( ( usChecksum == ipUNHANDLED_PROTOCOL ) ||
+ ( usChecksum == ipINVALID_LENGTH ) )
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
- pcType,
- FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
- FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
- FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
- FreeRTOS_ntohs( *pusChecksum ) ) );
+ FreeRTOS_printf( ( "CRC error: %04x location %ld\n", usChecksum, location ) );
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
return usChecksum;
}
@@ -2043,44 +2409,51 @@ uint8_t ucProtocol;
* uxDataLengthBytes: This argument contains the number of bytes that this method
* should process.
*/
-uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes )
+uint16_t usGenerateChecksum( uint16_t usSum, const uint8_t * pucNextData, size_t uxByteCount )
{
+/* MISRA/PC-lint doesn't like the use of unions. Here, they are a great
+aid though to optimise the calculations. */
xUnion32 xSum2, xSum, xTerm;
-xUnionPtr xSource; /* Points to first byte */
-xUnionPtr xLastSource; /* Points to last byte plus one */
-uint32_t ulAlignBits, ulCarry = 0ul;
+xUnionPtr xSource;
+xUnionPtr xLastSource;
+uint32_t ulAlignBits, ulCarry = 0UL;
+uint16_t usTemp;
+size_t uxDataLengthBytes = uxByteCount;
/* Small MCUs often spend up to 30% of the time doing checksum calculations
This function is optimised for 32-bit CPUs; Each time it will try to fetch
32-bits, sums it with an accumulator and counts the number of carries. */
/* Swap the input (little endian platform only). */
- xSum.u32 = FreeRTOS_ntohs( ulSum );
- xTerm.u32 = 0ul;
+ usTemp = FreeRTOS_ntohs( usSum );
+ xSum.u32 = ( uint32_t ) usTemp;
+ xTerm.u32 = 0UL;
- xSource.u8ptr = ( uint8_t * ) pucNextData;
- ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03u ); /* gives 0, 1, 2, or 3 */
+ xSource.u8ptr = ipPOINTER_CAST( uint8_t *, pucNextData );
+ /* coverity[misra_c_2012_rule_11_4_violation] */
+ /* The object pointer expression "pucNextData" of type "uint8_t const *" is cast to an integer type "unsigned int". */
+ ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03U ); /*lint !e9078 !e923*/ /* gives 0, 1, 2, or 3 */
/* If byte (8-bit) aligned... */
- if( ( ( ulAlignBits & 1ul ) != 0ul ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )
+ if( ( ( ulAlignBits & 1UL ) != 0UL ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )
{
xTerm.u8[ 1 ] = *( xSource.u8ptr );
- ( xSource.u8ptr )++;
+ xSource.u8ptr++;
uxDataLengthBytes--;
/* Now xSource is word (16-bit) aligned. */
}
/* If half-word (16-bit) aligned... */
- if( ( ( ulAlignBits == 1u ) || ( ulAlignBits == 2u ) ) && ( uxDataLengthBytes >= 2u ) )
+ if( ( ( ulAlignBits == 1U ) || ( ulAlignBits == 2U ) ) && ( uxDataLengthBytes >= 2U ) )
{
xSum.u32 += *(xSource.u16ptr);
- ( xSource.u16ptr )++;
- uxDataLengthBytes -= 2u;
+ xSource.u16ptr++;
+ uxDataLengthBytes -= 2U;
/* Now xSource is word (32-bit) aligned. */
}
/* Word (32-bit) aligned, do the most part. */
- xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4u ) ) - 3u;
+ xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4U ) ) - 3U;
/* In this loop, four 32-bit additions will be done, in total 16 bytes.
Indexing with constants (0,1,2,3) gives faster code than using
@@ -2118,16 +2491,19 @@ uint32_t ulAlignBits, ulCarry = 0ul;
}
/* And finally advance the pointer 4 * 4 = 16 bytes. */
- xSource.u32ptr += 4;
+ xSource.u32ptr = &( xSource.u32ptr[ 4 ] );
}
/* Now add all carries. */
xSum.u32 = ( uint32_t )xSum.u16[ 0 ] + xSum.u16[ 1 ] + ulCarry;
- uxDataLengthBytes %= 16u;
+ uxDataLengthBytes %= 16U;
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
/* Half-word aligned. */
+ /* Coverity does not like Unions. Warning issued here: "The operator "<"
+ * is being applied to the pointers "xSource.u16ptr" and "xLastSource.u16ptr",
+ * which do not point into the same object." */
while( xSource.u16ptr < xLastSource.u16ptr )
{
/* At least one more short. */
@@ -2135,23 +2511,25 @@ uint32_t ulAlignBits, ulCarry = 0ul;
xSource.u16ptr++;
}
- if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0u ) /* Maybe one more ? */
+ if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0U ) /* Maybe one more ? */
{
xTerm.u8[ 0 ] = xSource.u8ptr[ 0 ];
}
xSum.u32 += xTerm.u32;
/* Now add all carries again. */
+ /* Assigning value from "xTerm.u32" to "xSum.u32" here, but that stored value is overwritten before it can be used.
+ Coverity doesn't understand about union variables. */
xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
- /* The previous summation might have given a 16-bit carry. */
+ /* coverity[value_overwrite] */
xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
- if( ( ulAlignBits & 1u ) != 0u )
+ if( ( ulAlignBits & 1U ) != 0U )
{
/* Quite unlikely, but pucNextData might be non-aligned, which would
mean that a checksum is calculated starting at an odd position. */
- xSum.u32 = ( ( xSum.u32 & 0xffu ) << 8 ) | ( ( xSum.u32 & 0xff00u ) >> 8 );
+ xSum.u32 = ( ( xSum.u32 & 0xffU ) << 8 ) | ( ( xSum.u32 & 0xff00U ) >> 8 );
}
/* swap the output (little endian platform only). */
@@ -2159,6 +2537,8 @@ uint32_t ulAlignBits, ulCarry = 0ul;
}
/*-----------------------------------------------------------*/
+/* This function is used in other files, has external linkage e.g. in
+ * FreeRTOS_DNS.c. Not to be made static. */
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
EthernetHeader_t *pxEthernetHeader;
@@ -2173,10 +2553,10 @@ EthernetHeader_t *pxEthernetHeader;
{
BaseType_t xIndex;
- FreeRTOS_printf( ( "vReturnEthernetFrame: length %lu\n", ( uint32_t )pxNetworkBuffer->xDataLength ) );
+ FreeRTOS_printf( ( "vReturnEthernetFrame: length %u\n", ( unsigned ) pxNetworkBuffer->xDataLength ) );
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
- pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
+ pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
@@ -2187,26 +2567,110 @@ EthernetHeader_t *pxEthernetHeader;
if( xReleaseAfterSend == pdFALSE )
{
- pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );
+ pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength );
xReleaseAfterSend = pdTRUE;
+ /* Want no rounding up. */
+ pxNewBuffer->xDataLength = pxNetworkBuffer->xDataLength;
pxNetworkBuffer = pxNewBuffer;
}
if( pxNetworkBuffer != NULL )
#endif
{
- pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+ /* Map the Buffer to Ethernet Header struct for easy access to fields. */
+ pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
/* Swap source and destination MAC addresses. */
- memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );
- memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ), &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );
+ ( void ) memcpy( &( pxEthernetHeader->xSourceAddress) , ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
/* Send! */
- xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
+ ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
}
}
/*-----------------------------------------------------------*/
+
+#if ( ipconfigHAS_PRINTF != 0 )
+
+ #ifndef ipMONITOR_MAX_HEAP
+ /* As long as the heap has more space than e.g. 1 MB, there
+ will be no messages. */
+ #define ipMONITOR_MAX_HEAP ( 1024U * 1024U )
+ #endif /* ipMONITOR_MAX_HEAP */
+
+ #ifndef ipMONITOR_PERCENTAGE_90
+ /* Make this number lower to get less logging messages. */
+ #define ipMONITOR_PERCENTAGE_90 ( 90U )
+ #endif
+
+ #define ipMONITOR_PERCENTAGE_100 ( 100U )
+
+ void vPrintResourceStats( void )
+ {
+ static UBaseType_t uxLastMinBufferCount = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
+ static size_t uxMinLastSize = 0u;
+ UBaseType_t uxCurrentBufferCount;
+ size_t uxMinSize;
+
+ /* When setting up and testing a project with FreeRTOS+TCP, it is
+ can be helpful to monitor a few resources: the number of network
+ buffers and the amount of available heap.
+ This function will issue some logging when a minimum value has
+ changed. */
+ uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
+
+ if( uxLastMinBufferCount > uxCurrentBufferCount )
+ {
+ /* The logging produced below may be helpful
+ * while tuning +TCP: see how many buffers are in use. */
+ uxLastMinBufferCount = uxCurrentBufferCount;
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
+ uxGetNumberOfFreeNetworkBuffers(),
+ uxCurrentBufferCount ) );
+ }
+
+ uxMinSize = xPortGetMinimumEverFreeHeapSize();
+ if( uxMinLastSize == 0U )
+ {
+ /* Probably the first time this function is called. */
+ uxMinLastSize = uxMinSize;
+ }
+ else if( uxMinSize >= ipMONITOR_MAX_HEAP )
+ {
+ /* There is more than enough heap space. No need for logging. */
+ }
+ /* Write logging if there is a 10% decrease since the last time logging was written. */
+ else if( ( uxMinLastSize * ipMONITOR_PERCENTAGE_90 ) > ( uxMinSize * ipMONITOR_PERCENTAGE_100 ) )
+ {
+ uxMinLastSize = uxMinSize;
+ FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );
+ }
+ else
+ {
+ /* Nothing to log. */
+ }
+
+ #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ {
+ static UBaseType_t uxLastMinQueueSpace = 0;
+ UBaseType_t uxCurrentCount = 0u;
+
+ uxCurrentCount = uxGetMinimumIPQueueSpace();
+
+ if( uxLastMinQueueSpace != uxCurrentCount )
+ {
+ /* The logging produced below may be helpful
+ * while tuning +TCP: see how many buffers are in use. */
+ uxLastMinQueueSpace = uxCurrentCount;
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
+ }
+ }
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
+ }
+#endif /* ( ipconfigHAS_PRINTF != 0 ) */
+/*-----------------------------------------------------------*/
+
uint32_t FreeRTOS_GetIPAddress( void )
{
/* Returns the IP address of the NIC. */
@@ -2242,7 +2706,7 @@ uint32_t FreeRTOS_GetNetmask( void )
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] )
{
/* Copy the MAC address at the start of the default packet header fragment. */
- memcpy( ( void * )ipLOCAL_MAC_ADDRESS, ( void * )ucMACAddress, ( size_t )ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
}
/*-----------------------------------------------------------*/
@@ -2329,6 +2793,48 @@ BaseType_t FreeRTOS_IsNetworkUp( void )
}
#endif
/*-----------------------------------------------------------*/
+/* Utility function: Convert error number to a human readable
+ * string. Decalartion in FreeRTOS_errno_TCP.h. */
+const char *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength )
+{
+const char *pcName;
+
+ switch( xErrnum )
+ {
+ case pdFREERTOS_ERRNO_EADDRINUSE: pcName = "EADDRINUSE"; break;
+ case pdFREERTOS_ERRNO_ENOMEM: pcName = "ENOMEM"; break;
+ case pdFREERTOS_ERRNO_EADDRNOTAVAIL: pcName = "EADDRNOTAVAIL"; break;
+ case pdFREERTOS_ERRNO_ENOPROTOOPT: pcName = "ENOPROTOOPT"; break;
+ case pdFREERTOS_ERRNO_EBADF: pcName = "EBADF"; break;
+ case pdFREERTOS_ERRNO_ENOSPC: pcName = "ENOSPC"; break;
+ case pdFREERTOS_ERRNO_ECANCELED: pcName = "ECANCELED"; break;
+ case pdFREERTOS_ERRNO_ENOTCONN: pcName = "ENOTCONN"; break;
+ case pdFREERTOS_ERRNO_EINPROGRESS: pcName = "EINPROGRESS"; break;
+ case pdFREERTOS_ERRNO_EOPNOTSUPP: pcName = "EOPNOTSUPP"; break;
+ case pdFREERTOS_ERRNO_EINTR: pcName = "EINTR"; break;
+ case pdFREERTOS_ERRNO_ETIMEDOUT: pcName = "ETIMEDOUT"; break;
+ case pdFREERTOS_ERRNO_EINVAL: pcName = "EINVAL"; break;
+ case pdFREERTOS_ERRNO_EWOULDBLOCK: pcName = "EWOULDBLOCK"; break; /* same as EAGAIN */
+ case pdFREERTOS_ERRNO_EISCONN: pcName = "EISCONN"; break;
+ default:
+ /* Using function "snprintf". */
+ ( void ) snprintf( pcBuffer, uxLength, "Errno %d", ( int32_t ) xErrnum );
+ pcName = NULL;
+ break;
+ }
+ if( pcName != NULL )
+ {
+ /* Using function "snprintf". */
+ ( void ) snprintf( pcBuffer, uxLength, "%s", pcName );
+ }
+ if( uxLength > 0U )
+ {
+ pcBuffer[ uxLength - 1U ] = '\0';
+ }
+
+ return pcBuffer;
+}
+/*-----------------------------------------------------------*/
/* Provide access to private members for verification. */
#ifdef FREERTOS_TCP_ENABLE_VERIFICATION
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
index bb68d2b38..25d1dbd75 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
@@ -41,6 +41,13 @@
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
+/* A tool to measure RAM usage. By default, it is disabled
+and it won't add any code.
+See also tools/tcp_mem_stats.md */
+
+/*lint -e766 Header files is sometimes not used, depending on the configuration. */
+#include "tcp_mem_stats.h"
+
/* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
port number. */
#define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
@@ -66,33 +73,19 @@ range 1024-65535" excluding those already in use (inbound or outbound). */
#define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xffff )
/* The number of octets that make up an IP address. */
-#define socketMAX_IP_ADDRESS_OCTETS 4u
+#define socketMAX_IP_ADDRESS_OCTETS 4U
/* A block time of 0 simply means "don't block". */
#define socketDONT_BLOCK ( ( TickType_t ) 0 )
#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
- #define ipTCP_TIMER_PERIOD_MS ( 1000 )
-#endif
-
-/* The next private port number to use when binding a client socket is stored in
-the usNextPortToUse[] array - which has either 1 or two indexes depending on
-whether TCP is being supported. */
-#if( ipconfigUSE_TCP == 1 )
- #define socketPROTOCOL_COUNT 2
-#else
- #define socketPROTOCOL_COUNT 1
+ #define ipTCP_TIMER_PERIOD_MS ( 1000U )
#endif
-/* Indexes into the usNextPortToUse[] array for UDP and TCP sockets
-respectively. */
-#define socketNEXT_UDP_PORT_NUMBER_INDEX 0
-#define socketNEXT_TCP_PORT_NUMBER_INDEX 1
-
/* Some helper macro's for defining the 20/80 % limits of uxLittleSpace / uxEnoughSpace. */
-#define sock20_PERCENT 20
-#define sock80_PERCENT 80
-#define sock100_PERCENT 100
+#define sock20_PERCENT 20U
+#define sock80_PERCENT 80U
+#define sock100_PERCENT 100U
/*-----------------------------------------------------------*/
@@ -114,7 +107,13 @@ static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, Tic
* Return pdTRUE only if pxSocket is valid and bound, as far as can be
* determined.
*/
-static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
+static BaseType_t prvValidSocket( const FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );
+
+/*
+ * Internal function prvSockopt_so_buffer(): sets FREERTOS_SO_SNDBUF or
+ * FREERTOS_SO_RCVBUF properties of a socket.
+ */
+static BaseType_t prvSockopt_so_buffer( FreeRTOS_Socket_t *pxSocket, int32_t lOptionName, const void *pvOptionValue );
/*
* Before creating a socket, check the validity of the parameters used
@@ -134,14 +133,14 @@ static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType,
* Called from FreeRTOS_send(): some checks which will be done before
* sending a TCP packed.
*/
- static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );
+ static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t uxDataLength );
#endif /* ipconfigUSE_TCP */
#if( ipconfigUSE_TCP == 1 )
/*
* When a child socket gets closed, make sure to update the child-count of the parent
*/
- static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );
+ static void prvTCPSetSocketCount( FreeRTOS_Socket_t const * pxSocketToDelete );
#endif /* ipconfigUSE_TCP == 1 */
#if( ipconfigUSE_TCP == 1 )
@@ -149,20 +148,28 @@ static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType,
* Called from FreeRTOS_connect(): make some checks and if allowed, send a
* message to the IP-task to start connecting to a remote socket
*/
- static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );
+ static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t * pxSocket, struct freertos_sockaddr const * pxAddress );
+#endif /* ipconfigUSE_TCP */
+
+#if( ipconfigUSE_TCP == 1 )
+ /*
+ * Check if it makes any sense to wait for a connect event.
+ * It may return: -EINPROGRESS, -EAGAIN, or 0 for OK.
+ */
+ static BaseType_t bMayConnect( FreeRTOS_Socket_t const * pxSocket );
#endif /* ipconfigUSE_TCP */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
/* Executed by the IP-task, it will check all sockets belonging to a set */
- static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
+ static void prvFindSelectedSocket( SocketSelect_t *pxSocketSet );
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
/*-----------------------------------------------------------*/
/* The list that contains mappings between sockets and port numbers. Accesses
to this list must be protected by critical sections of one kind or another. */
-List_t xBoundUDPSocketsList;
+static List_t xBoundUDPSocketsList;
#if ipconfigUSE_TCP == 1
List_t xBoundTCPSocketsList;
@@ -170,15 +177,15 @@ List_t xBoundUDPSocketsList;
/*-----------------------------------------------------------*/
-static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
+static BaseType_t prvValidSocket( const FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )
{
-BaseType_t xReturn = pdTRUE;
+BaseType_t xReturn;
if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
{
xReturn = pdFALSE;
}
- else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )
+ else if( ( xIsBound != pdFALSE ) && !socketSOCKET_IS_BOUND( pxSocket ) )
{
/* The caller expects the socket to be bound, but it isn't. */
xReturn = pdFALSE;
@@ -188,12 +195,16 @@ BaseType_t xReturn = pdTRUE;
/* Socket has a wrong type (UDP != TCP). */
xReturn = pdFALSE;
}
+ else
+ {
+ xReturn = pdTRUE;
+ }
return xReturn;
}
/*-----------------------------------------------------------*/
-BaseType_t vNetworkSocketsInit( void )
+void vNetworkSocketsInit( void )
{
vListInitialise( &xBoundUDPSocketsList );
@@ -202,15 +213,13 @@ BaseType_t vNetworkSocketsInit( void )
vListInitialise( &xBoundTCPSocketsList );
}
#endif /* ipconfigUSE_TCP == 1 */
-
- return pdTRUE;
}
/*-----------------------------------------------------------*/
static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )
{
BaseType_t xReturn = pdPASS;
-FreeRTOS_Socket_t *pxSocket;
+FreeRTOS_Socket_t const *pxSocket = NULL;
/* Asserts must not appear before it has been determined that the network
task is ready - otherwise the asserts will fail. */
@@ -237,7 +246,7 @@ FreeRTOS_Socket_t *pxSocket;
if( xType != FREERTOS_SOCK_DGRAM )
{
xReturn = pdFAIL;
- configASSERT( xReturn );
+ configASSERT( xReturn == pdPASS );
}
/* In case a UDP socket is created, do not allocate space for TCP data. */
*pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
@@ -248,7 +257,7 @@ FreeRTOS_Socket_t *pxSocket;
if( xType != FREERTOS_SOCK_STREAM )
{
xReturn = pdFAIL;
- configASSERT( xReturn );
+ configASSERT( xReturn == pdPASS );
}
*pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
@@ -257,11 +266,12 @@ FreeRTOS_Socket_t *pxSocket;
else
{
xReturn = pdFAIL;
- configASSERT( xReturn );
+ configASSERT( xReturn == pdPASS );
}
}
/* In case configASSERT() is not used */
( void )xDomain;
+ ( void )pxSocket; /* Was only use fot sizeof. */
return xReturn;
}
/*-----------------------------------------------------------*/
@@ -284,80 +294,93 @@ Socket_t xReturn;
size depends on the type of socket: UDP sockets need less space. A
define 'pvPortMallocSocket' will used to allocate the necessary space.
By default it points to the FreeRTOS function 'pvPortMalloc()'. */
- pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, pvPortMallocSocket( uxSocketSize ) );
if( pxSocket == NULL )
{
- pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+ xReturn = FREERTOS_INVALID_SOCKET;
iptraceFAILED_TO_CREATE_SOCKET();
}
- else if( ( xEventGroup = xEventGroupCreate() ) == NULL )
- {
- vPortFreeSocket( pxSocket );
- pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
- iptraceFAILED_TO_CREATE_EVENT_GROUP();
- }
else
{
- /* Clear the entire space to avoid nulling individual entries */
- memset( pxSocket, '\0', uxSocketSize );
-
- pxSocket->xEventGroup = xEventGroup;
-
- /* Initialise the socket's members. The semaphore will be created
- if the socket is bound to an address, for now the pointer to the
- semaphore is just set to NULL to show it has not been created. */
- if( xProtocol == FREERTOS_IPPROTO_UDP )
+ xEventGroup = xEventGroupCreate();
+ if( xEventGroup == NULL )
{
- vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
-
- #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
+ vPortFreeSocket( pxSocket );
+ xReturn = FREERTOS_INVALID_SOCKET;
+ iptraceFAILED_TO_CREATE_EVENT_GROUP();
+ }
+ else
+ {
+ if( xProtocol == FREERTOS_IPPROTO_UDP )
+ {
+ iptraceMEM_STATS_CREATE( tcpSOCKET_UDP, pxSocket, uxSocketSize + sizeof( StaticEventGroup_t ) );
+ }
+ else
{
- pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
+ /* Lint wants at least a comment, in case the macro is empty. */
+ iptraceMEM_STATS_CREATE( tcpSOCKET_TCP, pxSocket, uxSocketSize + sizeof( StaticEventGroup_t ) );
}
- #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
- }
- vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
- listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );
+ /* Clear the entire space to avoid nulling individual entries. */
+ ( void ) memset( pxSocket, 0, uxSocketSize );
- pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
- pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
- pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
- pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
+ pxSocket->xEventGroup = xEventGroup;
- #if( ipconfigUSE_TCP == 1 )
- {
- if( xProtocol == FREERTOS_IPPROTO_TCP )
+ /* Initialise the socket's members. The semaphore will be created
+ if the socket is bound to an address, for now the pointer to the
+ semaphore is just set to NULL to show it has not been created. */
+ if( xProtocol == FREERTOS_IPPROTO_UDP )
{
- /* StreamSize is expressed in number of bytes */
- /* Round up buffer sizes to nearest multiple of MSS */
- pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;
- pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
- pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
- /* Use half of the buffer size of the TCP windows */
- #if ( ipconfigUSE_TCP_WIN == 1 )
+ vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+ #if( ipconfigUDP_MAX_RX_PACKETS > 0U )
{
- pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );
- pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );
+ pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
}
- #else
- {
- pxSocket->u.xTCP.uxRxWinSize = 1u;
- pxSocket->u.xTCP.uxTxWinSize = 1u;
+ #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
+ }
+
+ vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
+ listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ipPOINTER_CAST( void *, pxSocket ) );
+
+ pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
+ pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
+ pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
+ pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
+
+ #if( ipconfigUSE_TCP == 1 )
+ {
+ if( xProtocol == FREERTOS_IPPROTO_TCP )
+ {
+ /* StreamSize is expressed in number of bytes */
+ /* Round up buffer sizes to nearest multiple of MSS */
+ pxSocket->u.xTCP.usCurMSS = ( uint16_t ) ipconfigTCP_MSS;
+ pxSocket->u.xTCP.usInitMSS = ( uint16_t ) ipconfigTCP_MSS;
+ pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
+ pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
+ /* Use half of the buffer size of the TCP windows */
+ #if ( ipconfigUSE_TCP_WIN == 1 )
+ {
+ pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2U ) / ipconfigTCP_MSS );
+ pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2U ) / ipconfigTCP_MSS );
+ }
+ #else
+ {
+ pxSocket->u.xTCP.uxRxWinSize = 1U;
+ pxSocket->u.xTCP.uxTxWinSize = 1U;
+ }
+ #endif
+ /* The above values are just defaults, and can be overridden by
+ calling FreeRTOS_setsockopt(). No buffers will be allocated until a
+ socket is connected and data is exchanged. */
}
- #endif
- /* The above values are just defaults, and can be overridden by
- calling FreeRTOS_setsockopt(). No buffers will be allocated until a
- socket is connected and data is exchanged. */
}
+ #endif /* ipconfigUSE_TCP == 1 */
+ xReturn = pxSocket;
}
- #endif /* ipconfigUSE_TCP == 1 */
}
-
- xReturn = ( Socket_t ) pxSocket;
}
-
/* Remove compiler warnings in the case the configASSERT() is not defined. */
( void ) xDomain;
@@ -371,18 +394,23 @@ Socket_t xReturn;
{
SocketSelect_t *pxSocketSet;
- pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );
+ pxSocketSet = ipPOINTER_CAST( SocketSelect_t *, pvPortMalloc( sizeof( *pxSocketSet ) ) );
if( pxSocketSet != NULL )
{
- memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );
+ ( void ) memset( pxSocketSet, 0, sizeof( *pxSocketSet ) );
pxSocketSet->xSelectGroup = xEventGroupCreate();
if( pxSocketSet->xSelectGroup == NULL )
{
- vPortFree( ( void* ) pxSocketSet );
+ vPortFree( pxSocketSet );
pxSocketSet = NULL;
}
+ else
+ {
+ /* Lint wants at least a comment, in case the macro is empty. */
+ iptraceMEM_STATS_CREATE( tcpSOCKET_SET, pxSocketSet, sizeof( *pxSocketSet ) + sizeof( StaticEventGroup_t ) );
+ }
}
return ( SocketSet_t ) pxSocketSet;
@@ -397,8 +425,10 @@ Socket_t xReturn;
{
SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
+ iptraceMEM_STATS_DELETE( pxSocketSet );
+
vEventGroupDelete( pxSocketSet->xSelectGroup );
- vPortFree( ( void* ) pxSocketSet );
+ vPortFree( pxSocketSet );
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
@@ -407,7 +437,7 @@ Socket_t xReturn;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
/* Add a socket to a set */
- void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
+ void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToSet )
{
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;
@@ -417,18 +447,15 @@ Socket_t xReturn;
/* Make sure we're not adding bits which are reserved for internal use,
such as eSELECT_CALL_IP */
- pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );
+ pxSocket->xSelectBits |= xBitsToSet & ( ( EventBits_t ) eSELECT_ALL );
- if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
+ if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_ALL ) ) != ( EventBits_t ) 0U )
{
/* Adding a socket to a socket set. */
pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
/* Now have the IP-task call vSocketSelect() to see if the set contains
- any sockets which are 'ready' and set the proper bits.
- By setting 'bApiCalled = false', vSocketSelect() knows that it was
- not called from a user API */
- pxSocketSet->bApiCalled = pdFALSE;
+ any sockets which are 'ready' and set the proper bits. */
prvFindSelectedSocket( pxSocketSet );
}
}
@@ -439,22 +466,22 @@ Socket_t xReturn;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
/* Clear select bits for a socket
If the mask becomes 0, remove the socket from the set */
- void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )
+ void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToClear )
{
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
configASSERT( pxSocket != NULL );
configASSERT( xSocketSet != NULL );
- pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );
- if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )
+ pxSocket->xSelectBits &= ~( xBitsToClear & ( ( EventBits_t ) eSELECT_ALL ) );
+ if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_ALL ) ) != ( EventBits_t ) 0U )
{
pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;
}
else
{
/* disconnect it from the socket set */
- pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;
+ pxSocket->pxSocketSet = NULL;
}
}
@@ -468,7 +495,7 @@ Socket_t xReturn;
EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )
{
EventBits_t xReturn;
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
configASSERT( pxSocket != NULL );
configASSERT( xSocketSet != NULL );
@@ -477,7 +504,7 @@ Socket_t xReturn;
{
/* Make sure we're not adding bits which are reserved for internal
use. */
- xReturn = pxSocket->xSocketBits & eSELECT_ALL;
+ xReturn = pxSocket->xSocketBits & ( ( EventBits_t ) eSELECT_ALL );
}
else
{
@@ -499,7 +526,7 @@ Socket_t xReturn;
TimeOut_t xTimeOut;
TickType_t xRemainingTime;
SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;
- BaseType_t xResult;
+ EventBits_t uxResult;
configASSERT( xSocketSet != NULL );
@@ -513,13 +540,13 @@ Socket_t xReturn;
{
/* Find a socket which might have triggered the bit
This function might return immediately or block for a limited time */
- xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );
+ uxResult = xEventGroupWaitBits( pxSocketSet->xSelectGroup, ( ( EventBits_t ) eSELECT_ALL ), pdFALSE, pdFALSE, xRemainingTime );
#if( ipconfigSUPPORT_SIGNALS != 0 )
{
- if( ( xResult & eSELECT_INTR ) != 0u )
+ if( ( uxResult & ( ( EventBits_t ) eSELECT_INTR ) ) != 0U )
{
- xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );
+ ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_INTR );
FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
break;
}
@@ -527,12 +554,11 @@ Socket_t xReturn;
#endif /* ipconfigSUPPORT_SIGNALS */
/* Have the IP-task find the socket which had an event */
- pxSocketSet->bApiCalled = pdTRUE;
prvFindSelectedSocket( pxSocketSet );
- xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );
+ uxResult = xEventGroupGetBits( pxSocketSet->xSelectGroup );
- if( xResult != 0 )
+ if( uxResult != 0U )
{
break;
}
@@ -544,7 +570,7 @@ Socket_t xReturn;
}
}
- return xResult;
+ return ( BaseType_t ) uxResult;
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
@@ -554,36 +580,51 @@ Socket_t xReturn;
/* Send a message to the IP-task to have it check all sockets belonging to
'pxSocketSet' */
- static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
+ static void prvFindSelectedSocket( SocketSelect_t *pxSocketSet )
{
IPStackEvent_t xSelectEvent;
- FreeRTOS_Socket_t *xReturn;
+ #if( ipconfigSELECT_USES_NOTIFY != 0 )
+ SocketSelectMessage_t xSelectMessage;
+ #endif
xSelectEvent.eEventType = eSocketSelectEvent;
- xSelectEvent.pvData = ( void * ) pxSocketSet;
+ #if( ipconfigSELECT_USES_NOTIFY != 0 )
+ {
+ xSelectMessage.pxSocketSet = pxSocketSet;
+ xSelectMessage.xTaskhandle = xTaskGetCurrentTaskHandle();
+ xSelectEvent.pvData = &( xSelectMessage );
+ }
+ #else
+ {
+ xSelectEvent.pvData = pxSocketSet;
+
+ /* while the IP-task works on the request, the API will block on
+ 'eSELECT_CALL_IP'. So clear it first. */
+ ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, ( BaseType_t ) eSELECT_CALL_IP );
+ }
+ #endif
- /* while the IP-task works on the request, the API will block on
- 'eSELECT_CALL_IP'. So clear it first. */
- xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );
/* Now send the socket select event */
if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
{
/* Oops, we failed to wake-up the IP task. No use to wait for it. */
FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
- xReturn = NULL;
}
else
{
/* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
wakeup the calling API */
- xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
-
- /* Return 'pxSocket' which is set by the IP-task */
- xReturn = pxSocketSet->pxSocket;
+ #if( ipconfigSELECT_USES_NOTIFY != 0 )
+ {
+ ( void ) ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
+ }
+ #else
+ {
+ ( void ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, ( BaseType_t ) eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
+ }
+ #endif
}
-
- return xReturn;
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
@@ -594,11 +635,11 @@ Socket_t xReturn;
* In this library, the function can only be used with connectionsless sockets
* (UDP)
*/
-int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
+int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )
{
-BaseType_t lPacketCount = 0;
+BaseType_t lPacketCount;
NetworkBufferDescriptor_t *pxNetworkBuffer;
-FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+FreeRTOS_Socket_t const * pxSocket = xSocket;
TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
BaseType_t xTimed = pdFALSE;
TimeOut_t xTimeOut;
@@ -607,167 +648,172 @@ EventBits_t xEventBits = ( EventBits_t ) 0;
if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
{
- return -pdFREERTOS_ERRNO_EINVAL;
+ lReturn = -pdFREERTOS_ERRNO_EINVAL;
}
+ else
+ {
+ lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
- lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+ /* The function prototype is designed to maintain the expected Berkeley
+ sockets standard, but this implementation does not use all the parameters. */
+ ( void ) pxSourceAddressLength;
- /* The function prototype is designed to maintain the expected Berkeley
- sockets standard, but this implementation does not use all the parameters. */
- ( void ) pxSourceAddressLength;
-
- while( lPacketCount == 0 )
- {
- if( xTimed == pdFALSE )
+ while( lPacketCount == 0 )
{
- /* Check to see if the socket is non blocking on the first
- iteration. */
- xRemainingTime = pxSocket->xReceiveBlockTime;
-
- if( xRemainingTime == ( TickType_t ) 0 )
+ if( xTimed == pdFALSE )
{
- #if( ipconfigSUPPORT_SIGNALS != 0 )
+ /* Check to see if the socket is non blocking on the first
+ iteration. */
+ xRemainingTime = pxSocket->xReceiveBlockTime;
+
+ if( xRemainingTime == ( TickType_t ) 0 )
{
- /* Just check for the interrupt flag. */
- xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
- pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
+ #if( ipconfigSUPPORT_SIGNALS != 0 )
+ {
+ /* Just check for the interrupt flag. */
+ xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR,
+ pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
+ }
+ #endif /* ipconfigSUPPORT_SIGNALS */
+ break;
}
- #endif /* ipconfigSUPPORT_SIGNALS */
- break;
- }
- if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
- {
- break;
- }
+ if( ( ( ( UBaseType_t ) xFlags ) & ( ( UBaseType_t ) FREERTOS_MSG_DONTWAIT ) ) != 0U )
+ {
+ break;
+ }
- /* To ensure this part only executes once. */
- xTimed = pdTRUE;
+ /* To ensure this part only executes once. */
+ xTimed = pdTRUE;
- /* Fetch the current time. */
- vTaskSetTimeOutState( &xTimeOut );
- }
+ /* Fetch the current time. */
+ vTaskSetTimeOutState( &xTimeOut );
+ }
- /* Wait for arrival of data. While waiting, the IP-task may set the
- 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
- socket, thus unblocking this API call. */
- xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,
- pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+ /* Wait for arrival of data. While waiting, the IP-task may set the
+ 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
+ socket, thus unblocking this API call. */
+ xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( ( EventBits_t ) eSOCKET_RECEIVE ) | ( ( EventBits_t ) eSOCKET_INTR ),
+ pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
- #if( ipconfigSUPPORT_SIGNALS != 0 )
- {
- if( ( xEventBits & eSOCKET_INTR ) != 0 )
+ #if( ipconfigSUPPORT_SIGNALS != 0 )
{
- if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )
+ if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
{
- /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
- xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
+ if( ( xEventBits & ( EventBits_t ) eSOCKET_RECEIVE ) != 0U )
+ {
+ /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
+ ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
+ }
+ break;
}
+ }
+ #else
+ {
+ ( void ) xEventBits;
+ }
+ #endif /* ipconfigSUPPORT_SIGNALS */
+
+ lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+
+ if( lPacketCount != 0 )
+ {
break;
}
- }
- #else
- {
- ( void ) xEventBits;
- }
- #endif /* ipconfigSUPPORT_SIGNALS */
- lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+ /* Has the timeout been reached ? */
+ if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
+ {
+ break;
+ }
+ } /* while( lPacketCount == 0 ) */
if( lPacketCount != 0 )
{
- break;
- }
+ taskENTER_CRITICAL();
+ {
+ /* The owner of the list item is the network buffer. */
+ pxNetworkBuffer = ipPOINTER_CAST( NetworkBufferDescriptor_t *, listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) );
- /* Has the timeout been reached ? */
- if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
- {
- break;
- }
- } /* while( lPacketCount == 0 ) */
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_PEEK ) == 0U )
+ {
+ /* Remove the network buffer from the list of buffers waiting to
+ be processed by the socket. */
+ ( void ) uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
+ }
+ }
+ taskEXIT_CRITICAL();
- if( lPacketCount != 0 )
- {
- taskENTER_CRITICAL();
- {
- /* The owner of the list item is the network buffer. */
- pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+ /* The returned value is the length of the payload data, which is
+ calculated at the total packet size minus the headers.
+ The validity of `xDataLength` prvProcessIPPacket has been confirmed
+ in 'prvProcessIPPacket()'. */
+ lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) );
- if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
+ if( pxSourceAddress != NULL )
{
- /* Remove the network buffer from the list of buffers waiting to
- be processed by the socket. */
- uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
+ pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
+ pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
}
- }
- taskEXIT_CRITICAL();
- /* The returned value is the length of the payload data, which is
- calculated at the total packet size minus the headers.
- The validity of `xDataLength` prvProcessIPPacket has been confirmed
- in 'prvProcessIPPacket()'. */
- lReturn = ( int32_t ) ( pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t ) );
-
- if( pxSourceAddress != NULL )
- {
- pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
- pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
- }
-
- if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
- {
- /* The zero copy flag is not set. Truncate the length if it won't
- fit in the provided buffer. */
- if( lReturn > ( int32_t ) xBufferLength )
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
{
- iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );
- lReturn = ( int32_t )xBufferLength;
- }
+ /* The zero copy flag is not set. Truncate the length if it won't
+ fit in the provided buffer. */
+ if( lReturn > ( int32_t ) uxBufferLength )
+ {
+ iptraceRECVFROM_DISCARDING_BYTES( ( uxBufferLength - lReturn ) );
+ lReturn = ( int32_t ) uxBufferLength;
+ }
- /* Copy the received data into the provided buffer, then release the
- network buffer. */
- memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
+ /* Copy the received data into the provided buffer, then release the
+ network buffer. */
+ ( void ) memcpy( pvBuffer, &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );
- if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_PEEK ) == 0U )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ }
+ }
+ else
{
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ /* The zero copy flag was set. pvBuffer is not a buffer into which
+ the received data can be copied, but a pointer that must be set to
+ point to the buffer in which the received data has already been
+ placed. */
+ *( ( void** ) pvBuffer ) = ipPOINTER_CAST( void *, &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
}
+
}
+ #if( ipconfigSUPPORT_SIGNALS != 0 )
+ else if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
+ {
+ lReturn = -pdFREERTOS_ERRNO_EINTR;
+ iptraceRECVFROM_INTERRUPTED();
+ }
+ #endif /* ipconfigSUPPORT_SIGNALS */
else
{
- /* The zero copy flag was set. pvBuffer is not a buffer into which
- the received data can be copied, but a pointer that must be set to
- point to the buffer in which the received data has already been
- placed. */
- *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
+ lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
+ iptraceRECVFROM_TIMEOUT();
}
-
- }
-#if( ipconfigSUPPORT_SIGNALS != 0 )
- else if( ( xEventBits & eSOCKET_INTR ) != 0 )
- {
- lReturn = -pdFREERTOS_ERRNO_EINTR;
- iptraceRECVFROM_INTERRUPTED();
- }
-#endif /* ipconfigSUPPORT_SIGNALS */
- else
- {
- lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
- iptraceRECVFROM_TIMEOUT();
}
return lReturn;
}
/*-----------------------------------------------------------*/
-int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
+int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t uxTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
TimeOut_t xTimeOut;
TickType_t xTicksToWait;
int32_t lReturn = 0;
-FreeRTOS_Socket_t *pxSocket;
+FreeRTOS_Socket_t const * pxSocket;
+const size_t uxMaxPayloadLength = ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH;
+const size_t uxPayloadOffset = ( size_t ) ipUDP_PAYLOAD_OFFSET_IPv4;
+
pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
@@ -775,15 +821,15 @@ FreeRTOS_Socket_t *pxSocket;
sockets standard, but this implementation does not use all the
parameters. */
( void ) xDestinationAddressLength;
- configASSERT( pvBuffer );
+ configASSERT( pvBuffer != NULL );
- if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )
+ if( uxTotalDataLength <= ( size_t ) uxMaxPayloadLength )
{
/* If the socket is not already bound to an address, bind it now.
Passing NULL as the address parameter tells FreeRTOS_bind() to select
the address to bind to. */
- if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||
- ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )
+ if( socketSOCKET_IS_BOUND( pxSocket ) ||
+ ( FreeRTOS_bind( xSocket, NULL, 0U ) == 0 ) )
{
xTicksToWait = pxSocket->xSendBlockTime;
@@ -799,12 +845,12 @@ FreeRTOS_Socket_t *pxSocket;
}
#endif /* ipconfigUSE_CALLBACKS */
- if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
{
xTicksToWait = ( TickType_t ) 0;
}
- if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
{
/* Zero copy is not set, so obtain a network buffer into
which the payload will be copied. */
@@ -812,11 +858,11 @@ FreeRTOS_Socket_t *pxSocket;
/* Block until a buffer becomes available, or until a
timeout has been reached */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxPayloadOffset + uxTotalDataLength, xTicksToWait );
if( pxNetworkBuffer != NULL )
{
- memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );
+ ( void ) memcpy( &( pxNetworkBuffer->pucEthernetBuffer[ uxPayloadOffset ] ), pvBuffer, uxTotalDataLength );
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
{
@@ -830,13 +876,13 @@ FreeRTOS_Socket_t *pxSocket;
/* When zero copy is used, pvBuffer is a pointer to the
payload of a buffer that has already been obtained from the
stack. Obtain the network buffer pointer from the buffer. */
- pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );
+ pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( ( void * ) pvBuffer );
}
if( pxNetworkBuffer != NULL )
{
/* xDataLength is the size of the total packet, including the Ethernet header. */
- pxNetworkBuffer->xDataLength = xTotalDataLength + sizeof( UDPPacket_t );
+ pxNetworkBuffer->xDataLength = uxTotalDataLength + sizeof( UDPPacket_t );
pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
@@ -852,12 +898,12 @@ FreeRTOS_Socket_t *pxSocket;
if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
{
/* The packet was successfully sent to the IP task. */
- lReturn = ( int32_t ) xTotalDataLength;
+ lReturn = ( int32_t ) uxTotalDataLength;
#if( ipconfigUSE_CALLBACKS == 1 )
{
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
{
- pxSocket->u.xUDP.pxHandleSent( ( Socket_t )pxSocket, xTotalDataLength );
+ pxSocket->u.xUDP.pxHandleSent( xSocket, uxTotalDataLength );
}
}
#endif /* ipconfigUSE_CALLBACKS */
@@ -866,7 +912,7 @@ FreeRTOS_Socket_t *pxSocket;
{
/* If the buffer was allocated in this function, release
it. */
- if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+ if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
@@ -884,6 +930,7 @@ FreeRTOS_Socket_t *pxSocket;
}
else
{
+ /* No comment. */
iptraceSENDTO_SOCKET_NOT_BOUND();
}
}
@@ -898,13 +945,13 @@ FreeRTOS_Socket_t *pxSocket;
/*-----------------------------------------------------------*/
/*
- * FreeRTOS_bind() : binds a sockt to a local port number. If port 0 is
+ * FreeRTOS_bind() : binds a socket to a local port number. If port 0 is
* provided, a system provided port number will be assigned. This function can
* be used for both UDP and TCP sockets. The actual binding will be performed
* by the IP-task to avoid mutual access to the bound-socket-lists
* (xBoundUDPSocketsList or xBoundTCPSocketsList).
*/
-BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )
+BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr const * pxAddress, socklen_t xAddressLength )
{
IPStackEvent_t xBindEvent;
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
@@ -912,13 +959,15 @@ BaseType_t xReturn = 0;
( void ) xAddressLength;
+ configASSERT( xIsCallingFromIPTask() == pdFALSE );
+
if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
{
xReturn = -pdFREERTOS_ERRNO_EINVAL;
}
/* Once a socket is bound to a port, it can not be bound to a different
port number */
- else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )
+ else if( socketSOCKET_IS_BOUND( pxSocket) )
{
/* The socket is already bound. */
FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
@@ -929,7 +978,7 @@ BaseType_t xReturn = 0;
/* Prepare a messages to the IP-task in order to perform the binding.
The desired port number will be passed in usLocalPort. */
xBindEvent.eEventType = eSocketBindEvent;
- xBindEvent.pvData = ( void * ) xSocket;
+ xBindEvent.pvData = xSocket;
if( pxAddress != NULL )
{
pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
@@ -937,7 +986,7 @@ BaseType_t xReturn = 0;
else
{
/* Caller wants to bind to a random port number. */
- pxSocket->usLocalPort = 0u;
+ pxSocket->usLocalPort = 0U;
}
/* portMAX_DELAY is used as a the time-out parameter, as binding *must*
@@ -953,8 +1002,8 @@ BaseType_t xReturn = 0;
{
/* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
job. */
- xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
- if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
+ ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
+ if( !socketSOCKET_IS_BOUND( pxSocket ) )
{
xReturn = -pdFREERTOS_ERRNO_EINVAL;
}
@@ -969,10 +1018,11 @@ BaseType_t xReturn = 0;
* 'xInternal' is used for TCP sockets only: it allows to have several
* (connected) child sockets bound to the same server port.
*/
-BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )
+BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxBindAddress, size_t uxAddressLength, BaseType_t xInternal )
{
BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
List_t *pxSocketList;
+struct freertos_sockaddr * pxAddress = pxBindAddress;
#if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
struct freertos_sockaddr xAddress;
#endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
@@ -992,89 +1042,102 @@ List_t *pxSocketList;
sockets standard, but this implementation does not use all the parameters. */
( void ) uxAddressLength;
- configASSERT( pxSocket );
+ configASSERT( pxSocket != NULL );
configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
#if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
{
/* pxAddress will be NULL if sendto() was called on a socket without the
socket being bound to an address. In this case, automatically allocate
- an address and port to the socket. */
+ an address to the socket. There is a small chance that the allocated
+ port will already be in use - if that is the case, then the check below
+ [pxListFindListItemWithValue()] will result in an error being returned. */
if( pxAddress == NULL )
{
pxAddress = &xAddress;
/* Put the port to zero to be assigned later. */
- pxAddress->sin_port = 0u;
+ pxAddress->sin_port = 0U;
}
}
#endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
/* Sockets must be bound before calling FreeRTOS_sendto() if
ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
- configASSERT( pxAddress );
+ configASSERT( pxAddress != NULL );
+ #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
+ /* pxAddress is not NULL, no testing needed. */
+ #else
if( pxAddress != NULL )
+ #endif
{
- if( pxAddress->sin_port == 0u )
+ /* Add a do-while loop to facilitate use of 'break' statements. */
+ do
{
- pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t )pxSocket->ucProtocol );
- if( 0 == pxAddress->sin_port )
+ if( pxAddress->sin_port == 0U )
{
- return -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
+ pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
+ if( pxAddress->sin_port == ( uint16_t ) 0U )
+ {
+ xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
+ break;
+ }
}
- }
- /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
- confirmed that the socket was not yet bound to a port. If it is called
- from the IP-task, no such check is necessary. */
+ /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
+ confirmed that the socket was not yet bound to a port. If it is called
+ from the IP-task, no such check is necessary. */
- /* Check to ensure the port is not already in use. If the bind is
- called internally, a port MAY be used by more than one socket. */
- if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
- ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
- {
- FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
- pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",
- FreeRTOS_ntohs( pxAddress->sin_port ) ) );
- xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
- }
- else
- {
- /* Allocate the port number to the socket.
- This macro will set 'xBoundSocketListItem->xItemValue' */
- socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
+ /* Check to ensure the port is not already in use. If the bind is
+ called internally, a port MAY be used by more than one socket. */
+ if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
+ ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
+ {
+ FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
+ ( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ) ? "TC" : "UD",
+ FreeRTOS_ntohs( pxAddress->sin_port ) ) );
+ xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
+ }
+ else
+ {
+ /* Allocate the port number to the socket.
+ This macro will set 'xBoundSocketListItem->xItemValue' */
+ socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
- /* And also store it in a socket field 'usLocalPort' in host-byte-order,
- mostly used for logging and debugging purposes */
- pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
+ /* And also store it in a socket field 'usLocalPort' in host-byte-order,
+ mostly used for logging and debugging purposes */
+ pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
- /* Add the socket to the list of bound ports. */
- {
- /* If the network driver can iterate through 'xBoundUDPSocketsList',
- by calling xPortHasUDPSocket() then the IP-task must temporarily
- suspend the scheduler to keep the list in a consistent state. */
- #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+ /* Add the socket to the list of bound ports. */
{
- vTaskSuspendAll();
- }
- #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
+ /* If the network driver can iterate through 'xBoundUDPSocketsList',
+ by calling xPortHasUDPSocket() then the IP-task must temporarily
+ suspend the scheduler to keep the list in a consistent state. */
+ #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+ {
+ vTaskSuspendAll();
+ }
+ #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
- /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
- vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
+ /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
+ vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
- #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
- {
- xTaskResumeAll();
+ #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+ {
+ ( void ) xTaskResumeAll();
+ }
+ #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
}
- #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
}
- }
+ } while( ipFALSE_BOOL );
}
+ #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 0 )
else
{
xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
}
+ #endif
if( xReturn != 0 )
{
@@ -1099,7 +1162,7 @@ BaseType_t xResult;
#endif
IPStackEvent_t xCloseEvent;
xCloseEvent.eEventType = eSocketCloseEvent;
-xCloseEvent.pvData = ( void * ) xSocket;
+xCloseEvent.pvData = xSocket;
if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
{
@@ -1165,11 +1228,13 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/* Free the input and output streams */
if( pxSocket->u.xTCP.rxStream != NULL )
{
+ iptraceMEM_STATS_DELETE( pxSocket->u.xTCP.rxStream );
vPortFreeLarge( pxSocket->u.xTCP.rxStream );
}
if( pxSocket->u.xTCP.txStream != NULL )
{
+ iptraceMEM_STATS_DELETE( pxSocket->u.xTCP.txStream );
vPortFreeLarge( pxSocket->u.xTCP.txStream );
}
@@ -1182,7 +1247,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/* Socket must be unbound first, to ensure no more packets are queued on
it. */
- if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )
+ if( socketSOCKET_IS_BOUND( pxSocket ) )
{
/* If the network driver can iterate through 'xBoundUDPSocketsList',
by calling xPortHasUDPSocket(), then the IP-task must temporarily
@@ -1193,11 +1258,11 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
}
#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
- uxListRemove( &( pxSocket->xBoundSocketListItem ) );
+ ( void ) uxListRemove( &( pxSocket->xBoundSocketListItem ) );
#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
{
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
}
#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
}
@@ -1208,13 +1273,13 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
{
while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
{
- pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
- uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
+ pxNetworkBuffer = ipPOINTER_CAST( NetworkBufferDescriptor_t *, listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) );
+ ( void ) uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
}
- if( pxSocket->xEventGroup )
+ if( pxSocket->xEventGroup != NULL )
{
vEventGroupDelete( pxSocket->xEventGroup );
}
@@ -1234,9 +1299,10 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
#endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
/* Anf finally, after all resources have been freed, free the socket space */
+ iptraceMEM_STATS_DELETE( pxSocket );
vPortFreeSocket( pxSocket );
- return 0;
+ return NULL;
} /* Tested */
/*-----------------------------------------------------------*/
@@ -1248,28 +1314,28 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
* parent. When a listening parent socket is closed, make sure no child-sockets
* keep a pointer to it.
*/
- static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )
+ static void prvTCPSetSocketCount( FreeRTOS_Socket_t const * pxSocketToDelete )
{
const ListItem_t *pxIterator;
- const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+ const ListItem_t *pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
FreeRTOS_Socket_t *pxOtherSocket;
uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
- for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( const ListItem_t * ) pxEnd;
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
- if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&
+ pxOtherSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
+ if( ( pxOtherSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN ) &&
( pxOtherSocket->usLocalPort == usLocalPort ) &&
- ( pxOtherSocket->u.xTCP.usChildCount ) )
+ ( pxOtherSocket->u.xTCP.usChildCount != 0U ) )
{
pxOtherSocket->u.xTCP.usChildCount--;
FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
pxOtherSocket->usLocalPort,
pxOtherSocket->u.xTCP.usChildCount,
pxOtherSocket->u.xTCP.usBacklog,
- pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
+ ( pxOtherSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
break;
}
}
@@ -1279,11 +1345,51 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/*-----------------------------------------------------------*/
-BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
+static BaseType_t prvSockopt_so_buffer( FreeRTOS_Socket_t *pxSocket, int32_t lOptionName, const void *pvOptionValue )
+{
+uint32_t ulNewValue;
+BaseType_t xReturn;
+
+ if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
+ {
+ FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
+ ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
+ xReturn = -pdFREERTOS_ERRNO_EINVAL;
+ }
+ else if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
+ ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
+ {
+ FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
+ ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
+ xReturn = -pdFREERTOS_ERRNO_EINVAL;
+ }
+ else
+ {
+ ulNewValue = *( ipPOINTER_CAST( const uint32_t *, pvOptionValue ) );
+
+ if( lOptionName == FREERTOS_SO_SNDBUF )
+ {
+ /* Round up to nearest MSS size */
+ ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
+ pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
+ }
+ else
+ {
+ pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
+ }
+ xReturn = 0;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+/* FreeRTOS_setsockopt calls itself, but in a very limited way,
+only when FREERTOS_SO_WIN_PROPERTIES is being set. */
+BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t uxOptionLength )
{
/* The standard Berkeley function returns 0 for success. */
BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
-BaseType_t lOptionValue;
FreeRTOS_Socket_t *pxSocket;
pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
@@ -1291,29 +1397,33 @@ FreeRTOS_Socket_t *pxSocket;
/* The function prototype is designed to maintain the expected Berkeley
sockets standard, but this implementation does not use all the parameters. */
( void ) lLevel;
- ( void ) xOptionLength;
-
- configASSERT( xSocket );
+ ( void ) uxOptionLength;
+
+ if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
+ {
+ xReturn = -pdFREERTOS_ERRNO_EINVAL;
+ return xReturn;
+ }
switch( lOptionName )
{
case FREERTOS_SO_RCVTIMEO :
/* Receive time out. */
- pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
+ pxSocket->xReceiveBlockTime = *( ipPOINTER_CAST( const TickType_t *, pvOptionValue ) );
xReturn = 0;
break;
case FREERTOS_SO_SNDTIMEO :
- pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
+ pxSocket->xSendBlockTime = *( ipPOINTER_CAST( const TickType_t *, pvOptionValue ) );
if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
{
/* The send time out is capped for the reason stated in the
comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
in FreeRTOSIPConfig.h (assuming an official configuration file
is being used. */
- if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
+ if( pxSocket->xSendBlockTime > ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ) )
{
- pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
+ pxSocket->xSendBlockTime = ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS );
}
}
else
@@ -1324,24 +1434,24 @@ FreeRTOS_Socket_t *pxSocket;
}
xReturn = 0;
break;
- #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
+ #if( ipconfigUDP_MAX_RX_PACKETS > 0U )
case FREERTOS_SO_UDP_MAX_RX_PACKETS:
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
- pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
+ pxSocket->u.xUDP.uxMaxPackets = *( ( const UBaseType_t * ) pvOptionValue );
xReturn = 0;
break;
#endif /* ipconfigUDP_MAX_RX_PACKETS */
case FREERTOS_SO_UDPCKSUM_OUT :
- /* Turn calculating of the UDP checksum on/off for this socket. */
- lOptionValue = ( BaseType_t ) pvOptionValue;
+ /* Turn calculating of the UDP checksum on/off for this socket. If pvOptionValue
+ * is anything else than NULL, the checksum generation will be turned on. */
- if( lOptionValue == 0 )
+ if( pvOptionValue == NULL )
{
- pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
+ pxSocket->ucSocketOptions &= ~( ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT );
}
else
{
@@ -1388,22 +1498,23 @@ FreeRTOS_Socket_t *pxSocket;
{
#if ipconfigUSE_TCP == 1
case FREERTOS_SO_TCP_CONN_HANDLER:
- pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
+ pxSocket->u.xTCP.pxHandleConnected = ipPOINTER_CAST( const F_TCP_UDP_Handler_t *, pvOptionValue )->pxOnTCPConnected;
break;
case FREERTOS_SO_TCP_RECV_HANDLER:
- pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
+ pxSocket->u.xTCP.pxHandleReceive = ipPOINTER_CAST( const F_TCP_UDP_Handler_t *, pvOptionValue )->pxOnTCPReceive;
break;
case FREERTOS_SO_TCP_SENT_HANDLER:
- pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
+ pxSocket->u.xTCP.pxHandleSent = ipPOINTER_CAST( const F_TCP_UDP_Handler_t *, pvOptionValue )->pxOnTCPSent;
break;
#endif /* ipconfigUSE_TCP */
case FREERTOS_SO_UDP_RECV_HANDLER:
- pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
+ pxSocket->u.xUDP.pxHandleReceive = ipPOINTER_CAST( const F_TCP_UDP_Handler_t *, pvOptionValue )->pxOnUDPReceive;
break;
case FREERTOS_SO_UDP_SENT_HANDLER:
- pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
+ pxSocket->u.xUDP.pxHandleSent = ipPOINTER_CAST( const F_TCP_UDP_Handler_t *, pvOptionValue )->pxOnUDPSent;
break;
default:
+ /* Should it throw an error here? */
break;
}
}
@@ -1418,9 +1529,9 @@ FreeRTOS_Socket_t *pxSocket;
sleeps. */
case FREERTOS_SO_SET_SEMAPHORE:
{
- pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
- xReturn = 0;
+ pxSocket->pxUserSemaphore = *( ipPOINTER_CAST( SemaphoreHandle_t *, pvOptionValue ) );
}
+ xReturn = 0;
break;
#endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
@@ -1430,7 +1541,8 @@ FreeRTOS_Socket_t *pxSocket;
/* Each socket can have a callback function that is executed
when there is an event the socket's owner might want to
process. */
- pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
+ /* The type cast of the pointer expression "A" to type "B" removes const qualifier from the pointed to type. */
+ pxSocket->pxUserWakeCallback = ( const SocketWakeupCallback_t ) pvOptionValue;
xReturn = 0;
}
break;
@@ -1438,7 +1550,7 @@ FreeRTOS_Socket_t *pxSocket;
case FREERTOS_SO_SET_LOW_HIGH_WATER:
{
- LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
+ const LowHighWater_t *pxLowHighWater = ipPOINTER_CAST( const LowHighWater_t *, pvOptionValue );
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
@@ -1464,42 +1576,13 @@ FreeRTOS_Socket_t *pxSocket;
case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
{
- uint32_t ulNewValue;
-
- if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
- {
- FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
- ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
- break; /* will return -pdFREERTOS_ERRNO_EINVAL */
- }
-
- if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
- ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
- {
- FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
- ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
- break; /* will return -pdFREERTOS_ERRNO_EINVAL */
- }
-
- ulNewValue = *( ( uint32_t * ) pvOptionValue );
-
- if( lOptionName == FREERTOS_SO_SNDBUF )
- {
- /* Round up to nearest MSS size */
- ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
- pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
- }
- else
- {
- pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
- }
+ xReturn = prvSockopt_so_buffer( pxSocket, lOptionName, pvOptionValue );
}
- xReturn = 0;
break;
case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
{
- WinProperties_t* pxProps;
+ const WinProperties_t* pxProps;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
@@ -1513,16 +1596,18 @@ FreeRTOS_Socket_t *pxSocket;
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
- pxProps = ( ( WinProperties_t * ) pvOptionValue );
+ pxProps = ipPOINTER_CAST( const WinProperties_t *, pvOptionValue );
- if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
+ xReturn = prvSockopt_so_buffer( pxSocket, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ) );
+ if ( xReturn != 0 )
{
- break; /* will return -pdFREERTOS_ERRNO_EINVAL */
+ break; /* will return an error. */
}
- if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
+ xReturn = prvSockopt_so_buffer( pxSocket, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ) );
+ if ( xReturn != 0 )
{
- break; /* will return -pdFREERTOS_ERRNO_EINVAL */
+ break; /* will return an error. */
}
#if( ipconfigUSE_TCP_WIN == 1 )
@@ -1532,8 +1617,8 @@ FreeRTOS_Socket_t *pxSocket;
}
#else
{
- pxSocket->u.xTCP.uxRxWinSize = 1u;
- pxSocket->u.xTCP.uxTxWinSize = 1u;
+ pxSocket->u.xTCP.uxRxWinSize = 1U;
+ pxSocket->u.xTCP.uxTxWinSize = 1U;
}
#endif
@@ -1555,13 +1640,13 @@ FreeRTOS_Socket_t *pxSocket;
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
- if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+ if( *( ipPOINTER_CAST( const BaseType_t *, pvOptionValue ) ) != 0 )
{
- pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE;
}
else
{
- pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE;
}
}
xReturn = 0;
@@ -1574,13 +1659,13 @@ FreeRTOS_Socket_t *pxSocket;
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
- if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+ if( *( ipPOINTER_CAST( const BaseType_t *, pvOptionValue ) ) != 0 )
{
- pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE;
}
else
{
- pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE;
}
}
xReturn = 0;
@@ -1593,21 +1678,21 @@ FreeRTOS_Socket_t *pxSocket;
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
- if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+ if( *( ipPOINTER_CAST( const BaseType_t *, pvOptionValue ) ) != 0 )
{
- pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE;
}
else
{
- pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
+ pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE;
}
if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
- ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
+ ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) &&
( FreeRTOS_outstanding( pxSocket ) != 0 ) )
{
- pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
- xSendEventToIPTask( eTCPTimerEvent );
+ pxSocket->u.xTCP.usTimeout = 1U; /* to set/clear bSendFullSize */
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
}
}
xReturn = 0;
@@ -1619,19 +1704,18 @@ FreeRTOS_Socket_t *pxSocket;
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
-
- if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
+ if( *( ipPOINTER_CAST( const BaseType_t *, pvOptionValue ) ) != 0 )
{
- pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bRxStopped = pdTRUE;
}
else
{
- pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bRxStopped = pdFALSE;
}
- pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
- pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
- xSendEventToIPTask( eTCPTimerEvent );
+ pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
+ pxSocket->u.xTCP.usTimeout = 1U; /* to set/clear bRxStopped */
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
}
xReturn = 0;
break;
@@ -1653,7 +1737,7 @@ FreeRTOS_Socket_t *pxSocket;
static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
{
const uint16_t usEphemeralPortCount =
- socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_START_NUMBER + 1;
+ socketAUTO_PORT_ALLOCATION_MAX_NUMBER - ( socketAUTO_PORT_ALLOCATION_START_NUMBER - 1U );
uint16_t usIterations = usEphemeralPortCount;
uint32_t ulRandomSeed = 0;
uint16_t usResult = 0;
@@ -1704,7 +1788,7 @@ const List_t *pxList;
usIterations--;
}
- while( usIterations > 0 );
+ while( usIterations > 0U );
return usResult;
}
@@ -1719,10 +1803,10 @@ const ListItem_t * pxResult = NULL;
if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
{
const ListItem_t *pxIterator;
- const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );
- for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( const ListItem_t * ) pxEnd;
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+ const ListItem_t *pxEnd = ipPOINTER_CAST( const ListItem_t*, listGET_END_MARKER( pxList ) );
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
{
@@ -1751,7 +1835,7 @@ FreeRTOS_Socket_t *pxSocket = NULL;
if( pxListItem != NULL )
{
/* The owner of the list item is the socket itself. */
- pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxListItem ) );
configASSERT( pxSocket != NULL );
}
return pxSocket;
@@ -1759,100 +1843,240 @@ FreeRTOS_Socket_t *pxSocket = NULL;
/*-----------------------------------------------------------*/
-#if ipconfigINCLUDE_FULL_INET_ADDR == 1
+const char *FreeRTOS_inet_ntoa( uint32_t ulIPAddress, char *pcBuffer )
+{
+socklen_t uxNibble;
+socklen_t uxIndex = 0;
+const uint8_t *pucAddress = ( const uint8_t * ) &( ulIPAddress );
+const char *pcResult = pcBuffer;
+const socklen_t uxSize = 16;
+
+/* Each nibble is expressed in at most 3 digits, like e.g. "192". */
+#define sockDIGIT_COUNT ( 3U )
- uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
+ for( uxNibble = 0; uxNibble < ipSIZE_OF_IPv4_ADDRESS; uxNibble++ )
{
- const uint32_t ulDecimalBase = 10u;
- uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
- const char *pcPointerOnEntering;
- uint32_t ulReturn = 0UL, ulValue;
- UBaseType_t uxOctetNumber;
- BaseType_t xResult = pdPASS;
+ uint8_t pucDigits[ sockDIGIT_COUNT ];
+ uint8_t ucValue = pucAddress[ uxNibble ];
+ socklen_t uxSource = sockDIGIT_COUNT - 1;
+ socklen_t uxNeeded;
- for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
+ for( ;; )
{
- ulValue = 0ul;
- pcPointerOnEntering = pcIPAddress;
-
- while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
+ pucDigits[ uxSource ] = ucValue % ( uint8_t ) 10U;
+ ucValue /= ( uint8_t ) 10U;
+ if( uxSource == 1U )
{
- /* Move previous read characters into the next decimal
- position. */
- ulValue *= ulDecimalBase;
-
- /* Add the binary value of the ascii character. */
- ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );
-
- /* Move to next character in the string. */
- pcIPAddress++;
+ break;
}
+ uxSource--;
+ }
+ pucDigits[ 0 ] = ucValue;
- /* Check characters were read. */
- if( pcIPAddress == pcPointerOnEntering )
+ /* Skip leading zeros. */
+ for( uxSource = 0; uxSource < ( socklen_t ) ( sockDIGIT_COUNT - 1 ); uxSource++ )
+ {
+ if( pucDigits[ uxSource ] != 0U )
{
- xResult = pdFAIL;
+ break;
}
+ }
+ /* Write e.g. "192.", which is 3 digits and a dot. */
+ uxNeeded = ( ( socklen_t ) sockDIGIT_COUNT - uxSource ) + 1U;
+ if( ( uxIndex + uxNeeded ) > uxSize )
+ {
+ /* The result won't fit. */
+ pcResult = NULL;
+ break;
+ }
+
+ for( ; uxSource < ( socklen_t ) sockDIGIT_COUNT; uxSource++ )
+ {
+ pcBuffer[ uxIndex ] = ( char ) ( pucDigits[ uxSource ] + ( char ) '0' );
+ uxIndex++;
+ }
+ if( uxNibble < ( ipSIZE_OF_IPv4_ADDRESS - 1U ) )
+ {
+ pcBuffer[ uxIndex ] = '.';
+ }
+ else
+ {
+ pcBuffer[ uxIndex ] = '\0';
+ }
+ uxIndex++;
+ }
- /* Check the value fits in an 8-bit number. */
- if( ulValue > 0xffUL )
- {
- xResult = pdFAIL;
- }
- else
- {
- ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
+ return pcResult;
+}
+/*-----------------------------------------------------------*/
- /* Check the next character is as expected. */
- if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )
- {
- if( *pcIPAddress != '.' )
- {
- xResult = pdFAIL;
- }
- else
- {
- /* Move past the dot. */
- pcIPAddress++;
- }
- }
- }
+BaseType_t FreeRTOS_inet_pton( BaseType_t xAddressFamily, const char *pcSource, void *pvDestination )
+{
+BaseType_t xResult;
- if( xResult == pdFAIL )
- {
- /* No point going on. */
- break;
- }
+ /* Printable string to struct sockaddr. */
+ switch( xAddressFamily )
+ {
+ case FREERTOS_AF_INET:
+ xResult = FreeRTOS_inet_pton4( pcSource, pvDestination );
+ break;
+ default:
+ xResult = -pdFREERTOS_ERRNO_EAFNOSUPPORT;
+ break;
+ }
+ return xResult;
+}
+/*-----------------------------------------------------------*/
+
+const char *FreeRTOS_inet_ntop( BaseType_t xAddressFamily, const void *pvSource, char *pcDestination, socklen_t uxSize )
+{
+const char *pcResult;
+
+ /* Printable struct sockaddr to string. */
+ switch( xAddressFamily )
+ {
+ case FREERTOS_AF_INET:
+ pcResult = FreeRTOS_inet_ntop4( pvSource, pcDestination, uxSize );
+ break;
+ default:
+ /* errno should be set to pdFREERTOS_ERRNO_EAFNOSUPPORT. */
+ pcResult = NULL;
+ break;
+ }
+ return pcResult;
+}
+/*-----------------------------------------------------------*/
+
+const char *FreeRTOS_inet_ntop4( const void *pvSource, char *pcDestination, socklen_t uxSize )
+{
+uint32_t ulIPAddress;
+const char *pcReturn;
+
+ if( uxSize < 16U )
+ {
+ /* There must be space for "255.255.255.255". */
+ pcReturn = NULL;
+ }
+ else
+ {
+ ( void ) memcpy( &( ulIPAddress ), pvSource, sizeof( ulIPAddress ) );
+ ( void ) FreeRTOS_inet_ntoa( ulIPAddress, pcDestination );
+ pcReturn = pcDestination;
+ }
+ return pcReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t FreeRTOS_inet_pton4( const char *pcSource, void *pvDestination )
+{
+const uint32_t ulDecimalBase = 10U;
+uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
+uint32_t ulReturn = 0UL, ulValue;
+UBaseType_t uxOctetNumber;
+BaseType_t xResult = pdPASS;
+const char *pcIPAddress = pcSource;
+
+ /* Translate "192.168.2.100" to a 32-bit number, network-endian. */
+ for( uxOctetNumber = 0U; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
+ {
+ ulValue = 0UL;
+
+ while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
+ {
+ BaseType_t xChar;
+ /* Move previous read characters into the next decimal
+ position. */
+ ulValue *= ulDecimalBase;
+
+ /* Add the binary value of the ascii character. */
+ xChar = ( BaseType_t ) pcIPAddress[ 0 ];
+ xChar = xChar - ( BaseType_t ) '0';
+ ulValue += ( uint32_t ) xChar;
+
+ /* Move to next character in the string. */
+ pcIPAddress++;
}
- if( *pcIPAddress != ( char ) 0 )
+ /* Check characters were read. */
+ if( pcIPAddress == pcSource )
{
- /* Expected the end of the string. */
xResult = pdFAIL;
}
- if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
+ /* Check the value fits in an 8-bit number. */
+ if( ulValue > 0xffUL )
{
- /* Didn't read enough octets. */
xResult = pdFAIL;
}
+ else
+ {
+ ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
+
+ /* Check the next character is as expected. */
+ if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1U ) )
+ {
+ if( *pcIPAddress != '.' )
+ {
+ xResult = pdFAIL;
+ }
+ else
+ {
+ /* Move past the dot. */
+ pcIPAddress++;
+ }
+ }
+ }
- if( xResult == pdPASS )
+ if( xResult == pdFAIL )
{
- ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
+ /* No point going on. */
+ break;
}
+ }
+
+ if( *pcIPAddress != ( char ) 0 )
+ {
+ /* Expected the end of the string. */
+ xResult = pdFAIL;
+ }
+
+ if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
+ {
+ /* Didn't read enough octets. */
+ xResult = pdFAIL;
+ }
- return ulReturn;
+ if( xResult == pdPASS )
+ {
+ /* lint: ucOctet has been set because xResult == pdPASS. */
+ ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
}
+ else
+ {
+ ulReturn = 0UL;
+ }
+ ( void ) memcpy( pvDestination, &( ulReturn ), sizeof( ulReturn ) );
-#endif /* ipconfigINCLUDE_FULL_INET_ADDR */
+ return xResult;
+}
+/*-----------------------------------------------------------*/
+
+uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
+{
+uint32_t ulReturn = 0UL;
+ /* inet_pton AF_INET target is a 4-byte 'struct in_addr'. */
+ ( void ) FreeRTOS_inet_pton4( pcIPAddress, &( ulReturn ) );
+
+ return ulReturn;
+}
/*-----------------------------------------------------------*/
+
/* Function to get the local address and IP port */
-size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
+size_t FreeRTOS_GetLocalAddress( ConstSocket_t xSocket, struct freertos_sockaddr *pxAddress )
{
-FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
/* IP address of local machine. */
pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
@@ -1873,7 +2097,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
if( pxSocket->pxUserSemaphore != NULL )
{
- xSemaphoreGive( pxSocket->pxUserSemaphore );
+ ( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
}
}
#endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
@@ -1885,30 +2109,30 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
pxSocket->pxUserWakeCallback( pxSocket );
}
}
- #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
+ #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
if( pxSocket->pxSocketSet != NULL )
{
- EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;
- if( xSelectBits != 0ul )
+ EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & ( ( EventBits_t ) eSELECT_ALL );
+ if( xSelectBits != 0UL )
{
pxSocket->xSocketBits |= xSelectBits;
- xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
+ ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
}
}
- pxSocket->xEventBits &= eSOCKET_ALL;
+ pxSocket->xEventBits &= ( EventBits_t ) eSOCKET_ALL;
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
- if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )
+ if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0U ) )
{
- xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
+ ( void ) xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
}
- pxSocket->xEventBits = 0ul;
+ pxSocket->xEventBits = 0UL;
}
/*-----------------------------------------------------------*/
@@ -1918,7 +2142,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* This define makes it possible for network-card drivers to inspect
* UDP message and see if there is any UDP socket bound to a given port
* number.
- * This is probably only usefull in systems with a minimum of RAM and
+ * This is probably only useful in systems with a minimum of RAM and
* when lots of anonymous broadcast messages come in
*/
BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
@@ -1932,7 +2156,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
xFound = pdTRUE;
}
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
return xFound;
}
@@ -1943,16 +2167,34 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );
- static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )
+ static BaseType_t bMayConnect( FreeRTOS_Socket_t const * pxSocket )
{
- switch( pxSocket->u.xTCP.ucTCPState )
+ BaseType_t xResult;
+ eIPTCPState_t eState = ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState );
+
+ switch( eState )
{
case eCLOSED:
- case eCLOSE_WAIT: return 0;
- case eCONNECT_SYN: return -pdFREERTOS_ERRNO_EINPROGRESS;
- default: return -pdFREERTOS_ERRNO_EAGAIN;
+ case eCLOSE_WAIT:
+ xResult = 0;
+ break;
+ case eCONNECT_SYN:
+ xResult = -pdFREERTOS_ERRNO_EINPROGRESS;
+ break;
+ case eTCP_LISTEN:
+ case eSYN_FIRST:
+ case eSYN_RECEIVED:
+ case eESTABLISHED:
+ case eFIN_WAIT_1:
+ case eFIN_WAIT_2:
+ case eCLOSING:
+ case eLAST_ACK:
+ case eTIME_WAIT:
+ default:
+ xResult = -pdFREERTOS_ERRNO_EAGAIN;
+ break;
}
+ return xResult;
}
#endif /* ipconfigUSE_TCP */
@@ -1960,11 +2202,16 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )
+ static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t * pxSocket, struct freertos_sockaddr const * pxAddress )
{
BaseType_t xResult = 0;
- if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
+ if( pxAddress == NULL )
+ {
+ /* NULL address passed to the function. Invalid value. */
+ xResult = -pdFREERTOS_ERRNO_EINVAL;
+ }
+ else if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
{
/* Not a valid socket or wrong type */
xResult = -pdFREERTOS_ERRNO_EBADF;
@@ -1974,11 +2221,15 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* The socket is already connected. */
xResult = -pdFREERTOS_ERRNO_EISCONN;
}
- else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )
+ else if( !socketSOCKET_IS_BOUND( pxSocket ) )
{
/* Bind the socket to the port that the client task will send from.
Non-standard, so the error returned is that returned by bind(). */
- xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );
+ xResult = FreeRTOS_bind( pxSocket, NULL, 0U );
+ }
+ else
+ {
+ /* The socket is valid, not yet connected, and already bound to a port number. */
}
if( xResult == 0 )
@@ -1990,8 +2241,8 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Start the connect procedure, kernel will start working on it */
if( xResult == 0 )
{
- pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;
- pxSocket->u.xTCP.ucRepCount = 0u;
+ pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE;
+ pxSocket->u.xTCP.ucRepCount = 0U;
FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
@@ -2006,7 +2257,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
vTCPStateChange( pxSocket, eCONNECT_SYN );
/* To start an active connect. */
- pxSocket->u.xTCP.usTimeout = 1u;
+ pxSocket->u.xTCP.usTimeout = 1U;
if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
{
@@ -2031,7 +2282,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;
TickType_t xRemainingTime;
BaseType_t xTimed = pdFALSE;
- BaseType_t xResult;
+ BaseType_t xResult = -pdFREERTOS_ERRNO_EINVAL;
TimeOut_t xTimeOut;
( void ) xAddressLength;
@@ -2079,14 +2330,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
/* Is it allowed to sleep more? */
- if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )
+ if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
{
xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
break;
}
/* Go sleeping until we get any down-stream event */
- xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+ ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
}
}
@@ -2115,13 +2366,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
{
/* Not a valid socket or wrong type */
- pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+ pxClientSocket = FREERTOS_INVALID_SOCKET;
}
else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
- ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )
+ ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eTCP_LISTEN ) )
{
/* Parent socket is not in listening mode */
- pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;
+ pxClientSocket = FREERTOS_INVALID_SOCKET;
}
else
{
@@ -2146,7 +2397,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Is it still not taken ? */
if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
{
- pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;
+ pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE;
}
else
{
@@ -2154,7 +2405,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
}
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
if( pxClientSocket != NULL )
{
@@ -2182,8 +2433,8 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Ask to set an event in 'xEventGroup' as soon as a new
client gets connected for this listening socket. */
xAskEvent.eEventType = eTCPAcceptEvent;
- xAskEvent.pvData = ( void * ) pxSocket;
- xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
+ xAskEvent.pvData = pxSocket;
+ ( void ) xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
}
if( pxClientSocket != NULL )
@@ -2214,11 +2465,11 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
/* Go sleeping until we get any down-stream event */
- xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
+ ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
}
}
- return ( Socket_t ) pxClientSocket;
+ return pxClientSocket;
}
#endif /* ipconfigUSE_TCP */
/*-----------------------------------------------------------*/
@@ -2229,7 +2480,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
* Read incoming data from a TCP socket
* Only after the last byte has been read, a close error might be returned
*/
- BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )
+ BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags )
{
BaseType_t xByteCount;
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
@@ -2244,6 +2495,12 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
xByteCount = -pdFREERTOS_ERRNO_EINVAL;
}
+ else if( ( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_ZERO_COPY ) != 0U ) &&
+ ( pvBuffer == NULL ) )
+ {
+ /* In zero-copy mode, pvBuffer is a pointer to a pointer ( not NULL ). */
+ xByteCount = -pdFREERTOS_ERRNO_EINVAL;
+ }
else
{
if( pxSocket->u.xTCP.rxStream != NULL )
@@ -2257,7 +2514,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
while( xByteCount == 0 )
{
- switch( pxSocket->u.xTCP.ucTCPState )
+ switch( ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState ) )
{
case eCLOSED:
case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
@@ -2272,10 +2529,23 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
}
- /* Call continue to break out of the switch and also the while
- loop. */
- continue;
+ break;
+
+ case eTCP_LISTEN:
+ case eCONNECT_SYN:
+ case eSYN_FIRST:
+ case eSYN_RECEIVED:
+ case eESTABLISHED:
+ case eFIN_WAIT_1:
+ case eFIN_WAIT_2:
+ case eLAST_ACK:
+ case eTIME_WAIT:
default:
+ /* Nothing. */
+ break;
+ }
+ if( xByteCount < 0 )
+ {
break;
}
@@ -2289,14 +2559,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigSUPPORT_SIGNALS != 0 )
{
/* Just check for the interrupt flag. */
- xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,
+ xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR,
pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
}
#endif /* ipconfigSUPPORT_SIGNALS */
break;
}
- if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+ if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
{
break;
}
@@ -2316,11 +2586,11 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Block until there is a down-stream event. */
xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
- eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,
+ ( EventBits_t ) eSOCKET_RECEIVE | ( EventBits_t ) eSOCKET_CLOSED | ( EventBits_t ) eSOCKET_INTR,
pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
#if( ipconfigSUPPORT_SIGNALS != 0 )
{
- if( ( xEventBits & eSOCKET_INTR ) != 0u )
+ if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
{
break;
}
@@ -2342,13 +2612,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
#if( ipconfigSUPPORT_SIGNALS != 0 )
- if( ( xEventBits & eSOCKET_INTR ) != 0 )
+ if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
{
- if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )
+ if( ( xEventBits & ( ( EventBits_t ) eSOCKET_RECEIVE | ( EventBits_t ) eSOCKET_CLOSED ) ) != 0U )
{
/* Shouldn't have cleared other flags. */
- xEventBits &= ~eSOCKET_INTR;
- xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
+ xEventBits &= ~( ( EventBits_t ) eSOCKET_INTR );
+ ( void ) xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
}
xByteCount = -pdFREERTOS_ERRNO_EINTR;
}
@@ -2356,9 +2626,16 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#endif /* ipconfigSUPPORT_SIGNALS */
if( xByteCount > 0 )
{
- if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )
+ if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_ZERO_COPY ) == 0U )
{
- xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );
+ BaseType_t xIsPeek = ( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_PEEK ) != 0U ) ? 1L : 0L;
+
+ xByteCount = ( BaseType_t )
+ uxStreamBufferGet( pxSocket->u.xTCP.rxStream,
+ 0UL,
+ ipPOINTER_CAST( uint8_t *, pvBuffer ),
+ ( size_t ) uxBufferLength,
+ xIsPeek );
if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
{
/* We had reached the low-water mark, now see if the flag
@@ -2367,19 +2644,23 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
{
- pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;
- pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
- pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */
- xSendEventToIPTask( eTCPTimerEvent );
+ pxSocket->u.xTCP.bits.bLowWater = pdFALSE;
+ pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
+ pxSocket->u.xTCP.usTimeout = 1U; /* because bLowWater is cleared. */
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
}
}
}
else
{
/* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
- xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );
+ xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, ipPOINTER_CAST( uint8_t **, pvBuffer ) );
}
}
+ else
+ {
+ /* Nothing. */
+ }
} /* prvValidSocket() */
return xByteCount;
@@ -2390,7 +2671,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )
+ static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t uxDataLength )
{
int32_t xResult = 1;
@@ -2403,9 +2684,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
xResult = -pdFREERTOS_ERRNO_ENOMEM;
}
- else if( pxSocket->u.xTCP.ucTCPState == eCLOSED ||
- pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ||
- pxSocket->u.xTCP.ucTCPState == eCLOSING )
+ else if( ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSED ) ||
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSE_WAIT ) ||
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSING ) )
{
xResult = -pdFREERTOS_ERRNO_ENOTCONN;
}
@@ -2416,7 +2697,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
Return OK in order not to get closed/deleted too quickly */
xResult = 0;
}
- else if( xDataLength == 0ul )
+ else if( uxDataLength == 0UL )
{
/* send() is being called to send zero bytes */
xResult = 0;
@@ -2424,13 +2705,17 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
else if( pxSocket->u.xTCP.txStream == NULL )
{
/* Create the outgoing stream only when it is needed */
- prvTCPCreateStream( pxSocket, pdFALSE );
+ ( void ) prvTCPCreateStream( pxSocket, pdFALSE );
if( pxSocket->u.xTCP.txStream == NULL )
{
xResult = -pdFREERTOS_ERRNO_ENOMEM;
}
}
+ else
+ {
+ /* Nothing. */
+ }
return xResult;
}
@@ -2442,10 +2727,10 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Get a direct pointer to the circular transmit buffer.
'*pxLength' will contain the number of bytes that may be written. */
- uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )
+ uint8_t *FreeRTOS_get_tx_head( ConstSocket_t xSocket, BaseType_t *pxLength )
{
uint8_t *pucReturn = NULL;
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
StreamBuffer_t *pxBuffer = NULL;
*pxLength = 0;
@@ -2455,14 +2740,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
{
pxBuffer = pxSocket->u.xTCP.txStream;
- if( pxBuffer != NULL )
- {
- BaseType_t xSpace = ( BaseType_t )uxStreamBufferGetSpace( pxBuffer );
- BaseType_t xRemain = ( BaseType_t )( pxBuffer->LENGTH - pxBuffer->uxHead );
+ if( pxBuffer != NULL )
+ {
+ BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
+ BaseType_t xRemain = ( BaseType_t ) pxBuffer->LENGTH - ( BaseType_t ) pxBuffer->uxHead;
- *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
- pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;
- }
+ *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
+ pucReturn = &( pxBuffer->ucArray[ pxBuffer->uxHead ] );
+ }
}
return pucReturn;
@@ -2478,19 +2763,23 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
*/
BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )
{
- BaseType_t xByteCount;
+ BaseType_t xByteCount = -pdFREERTOS_ERRNO_EINVAL;
BaseType_t xBytesLeft;
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
TickType_t xRemainingTime;
BaseType_t xTimed = pdFALSE;
TimeOut_t xTimeOut;
BaseType_t xCloseAfterSend;
+ const uint8_t *pucSource = ipPOINTER_CAST( const uint8_t *, pvBuffer );
/* Prevent compiler warnings about unused parameters. The parameter
may be used in future versions. */
( void ) xFlags;
-
- xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
+
+ if( pvBuffer != NULL )
+ {
+ xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
+ }
if( xByteCount > 0 )
{
@@ -2536,28 +2825,28 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* Now suspend the scheduler: sending the last data and
setting bCloseRequested must be done together */
vTaskSuspendAll();
- pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE;
}
- xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );
+ xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0UL, pucSource, ( size_t ) xByteCount );
if( xCloseAfterSend != pdFALSE )
{
/* Now when the IP-task transmits the data, it will also
see that bCloseRequested is true and include the FIN
flag to start closure of the connection. */
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
}
/* Send a message to the IP-task so it can work on this
socket. Data is sent, let the IP-task work on it. */
- pxSocket->u.xTCP.usTimeout = 1u;
+ pxSocket->u.xTCP.usTimeout = 1U;
if( xIsCallingFromIPTask() == pdFALSE )
{
/* Only send a TCP timer event when not called from the
IP-task. */
- xSendEventToIPTask( eTCPTimerEvent );
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
}
xBytesLeft -= xByteCount;
@@ -2569,7 +2858,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* As there are still bytes left to be sent, increase the
data pointer. */
- pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );
+ pucSource = &( pucSource [ xByteCount ] );
}
/* Not all bytes have been sent. In case the socket is marked as
@@ -2597,7 +2886,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
break;
}
- if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )
+ if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
{
break;
}
@@ -2618,7 +2907,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
/* Go sleeping until down-stream events are received. */
- xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,
+ ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_SEND | ( EventBits_t ) eSOCKET_CLOSED,
pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
@@ -2629,13 +2918,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
if( xByteCount == 0 )
{
- if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )
+ if( pxSocket->u.xTCP.ucTCPState > ( uint8_t ) eESTABLISHED )
{
xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
}
else
{
- if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
+ if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) )
{
FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
pxSocket->usLocalPort,
@@ -2672,7 +2961,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
}
- else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )
+ else if( ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCLOSE_WAIT ) )
{
/* Socket is in a wrong state. */
xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
@@ -2685,7 +2974,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* This cleaning is necessary only if a listening socket is being
reused as it might have had a previous connection. */
- if( pxSocket->u.xTCP.bits.bReuseSocket )
+ if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
{
if( pxSocket->u.xTCP.rxStream != NULL )
{
@@ -2697,13 +2986,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
vStreamBufferClear( pxSocket->u.xTCP.txStream );
}
- memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
- memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );
- memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );
+ ( void ) memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, 0, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
+ ( void ) memset( &pxSocket->u.xTCP.xTCPWindow, 0, sizeof( pxSocket->u.xTCP.xTCPWindow ) );
+ ( void ) memset( &pxSocket->u.xTCP.bits, 0, sizeof( pxSocket->u.xTCP.bits ) );
/* Now set the bReuseSocket flag again, because the bits have
just been cleared. */
- pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE;
}
vTCPStateChange( pxSocket, eTCP_LISTEN );
@@ -2729,7 +3018,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
supports the listen() operation. */
xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
}
- else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
+ else if ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eESTABLISHED )
{
/*_RB_ Is this comment correct? The socket is not of a type that
supports the listen() operation. */
@@ -2740,8 +3029,8 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
/* Let the IP-task perform the shutdown of the connection. */
- pxSocket->u.xTCP.usTimeout = 1u;
- xSendEventToIPTask( eTCPTimerEvent );
+ pxSocket->u.xTCP.usTimeout = 1U;
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
xResult = 0;
}
(void) xHow;
@@ -2767,25 +3056,25 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
FreeRTOS_Socket_t *pxSocket;
TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
TickType_t xNow = xTaskGetTickCount();
- static TickType_t xLastTime = 0u;
+ static TickType_t xLastTime = 0U;
TickType_t xDelta = xNow - xLastTime;
- ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
- ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
+ const ListItem_t* pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
+ const ListItem_t *pxIterator = ( const ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
xLastTime = xNow;
- if( xDelta == 0u )
+ if( xDelta == 0U )
{
- xDelta = 1u;
+ xDelta = 1U;
}
while( pxIterator != pxEnd )
{
- pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
/* Sockets with 'tmout == 0' do not need any regular attention. */
- if( pxSocket->u.xTCP.usTimeout == 0u )
+ if( pxSocket->u.xTCP.usTimeout == 0U )
{
continue;
}
@@ -2796,13 +3085,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
else
{
- int rc ;
- pxSocket->u.xTCP.usTimeout = 0u;
- rc = xTCPSocketCheck( pxSocket );
+ BaseType_t xRc;
+
+ pxSocket->u.xTCP.usTimeout = 0U;
+ xRc = xTCPSocketCheck( pxSocket );
/* Within this function, the socket might want to send a delayed
ack or send out data or whatever it needs to do. */
- if( rc < 0 )
+ if( xRc < 0 )
{
/* Continue because the socket was deleted. */
continue;
@@ -2812,7 +3102,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* In xEventBits the driver may indicate that the socket has
important events for the user. These are only done just before the
IP-task goes to sleep. */
- if( pxSocket->xEventBits != 0u )
+ if( pxSocket->xEventBits != 0U )
{
if( xWillSleep != pdFALSE )
{
@@ -2828,7 +3118,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
}
- if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
+ if( ( pxSocket->u.xTCP.usTimeout != 0U ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
{
xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
}
@@ -2850,22 +3140,22 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
*/
FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )
{
- ListItem_t *pxIterator;
+ const ListItem_t *pxIterator;
FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;
- MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+ const ListItem_t *pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
/* Parameter not yet supported. */
( void ) ulLocalIP;
- for( pxIterator = ( ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( ListItem_t * ) pxEnd;
- pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ FreeRTOS_Socket_t *pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
{
- if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
{
/* If this is a socket listening to uxLocalPort, remember it
in case there is no perfect match. */
@@ -2878,6 +3168,10 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
pxResult = pxSocket;
break;
}
+ else
+ {
+ /* This 'pxSocket' doesn't match. */
+ }
}
}
if( pxResult == NULL )
@@ -2894,11 +3188,12 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/*-----------------------------------------------------------*/
#if( ipconfigUSE_TCP == 1 )
-
- const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )
- {
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;
- struct xSTREAM_BUFFER *pxReturn = NULL;
+ /* For the web server: borrow the circular Rx buffer for inspection
+ * HTML driver wants to see if a sequence of 13/10/13/10 is available. */
+ const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( ConstSocket_t xSocket )
+ {
+ const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * )xSocket;
+ const struct xSTREAM_BUFFER *pxReturn = NULL;
/* Confirm that this is a TCP socket before dereferencing structure
member pointers. */
@@ -2908,7 +3203,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
return pxReturn;
- }
+ }
#endif /* ipconfigUSE_TCP */
/*-----------------------------------------------------------*/
@@ -2927,12 +3222,12 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
uxLength = pxSocket->u.xTCP.uxRxStreamSize;
- if( pxSocket->u.xTCP.uxLittleSpace == 0ul )
+ if( pxSocket->u.xTCP.uxLittleSpace == 0UL )
{
pxSocket->u.xTCP.uxLittleSpace = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
}
- if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )
+ if( pxSocket->u.xTCP.uxEnoughSpace == 0UL )
{
pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
}
@@ -2946,35 +3241,37 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
uxLength += sizeof( size_t );
/* And make the length a multiple of sizeof( size_t ). */
- uxLength &= ~( sizeof( size_t ) - 1u );
+ uxLength &= ~( sizeof( size_t ) - 1U );
- uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;
+ uxSize = ( sizeof( *pxBuffer ) + uxLength ) - sizeof( pxBuffer->ucArray );
- pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );
+ pxBuffer = ipPOINTER_CAST( StreamBuffer_t *, pvPortMallocLarge( uxSize ) );
if( pxBuffer == NULL )
{
FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
- pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bMallocError = pdTRUE;
vTCPStateChange( pxSocket, eCLOSE_WAIT );
}
else
{
/* Clear the markers of the stream */
- memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
+ ( void ) memset( pxBuffer, 0, sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
pxBuffer->LENGTH = ( size_t ) uxLength ;
if( xTCPWindowLoggingLevel != 0 )
{
- FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );
+ FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %u bytes (total %u)\n", ( xIsInputStream != 0 ) ? 'R' : 'T', uxLength, uxSize ) );
}
if( xIsInputStream != 0 )
{
+ iptraceMEM_STATS_CREATE( tcpRX_STREAM_BUFFER, pxBuffer, uxSize );
pxSocket->u.xTCP.rxStream = pxBuffer;
}
else
{
+ iptraceMEM_STATS_CREATE( tcpTX_STREAM_BUFFER, pxBuffer, uxSize );
pxSocket->u.xTCP.txStream = pxBuffer;
}
}
@@ -2994,9 +3291,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )
{
StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;
- int32_t xResult;
+ int32_t xResult = 0;
#if( ipconfigUSE_CALLBACKS == 1 )
- BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );
+ BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive ) ? pdTRUE : pdFALSE;
const uint8_t *pucBuffer = NULL;
#endif /* ipconfigUSE_CALLBACKS */
@@ -3010,44 +3307,46 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
if( pxStream == NULL )
{
- return -1;
+ xResult = -1;
}
}
- #if( ipconfigUSE_CALLBACKS == 1 )
+ if( xResult >= 0 )
{
- if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )
+ #if( ipconfigUSE_CALLBACKS == 1 )
{
- /* Data can be passed directly to the user */
- pucBuffer = pcData;
+ if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0U ) && ( uxOffset == 0UL ) && ( pcData != NULL ) )
+ {
+ /* Data can be passed directly to the user */
+ pucBuffer = pcData;
- /* Zero-copy for call-back: no need to add the bytes to the
- stream, only the pointer will be advanced by uxStreamBufferAdd(). */
- pcData = NULL;
+ pcData = NULL;
+ }
}
- }
- #endif /* ipconfigUSE_CALLBACKS */
+ #endif /* ipconfigUSE_CALLBACKS */
- xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
+ xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
- {
- if( xResult != ( int32_t ) ulByteCount )
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
- FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",
- uxOffset, xResult, ulByteCount,
- pxStream->uxTail,
- pxStream->uxHead,
- uxStreamBufferFrontSpace( pxStream ),
- pxStream->uxFront ) );
+ if( xResult != ( int32_t ) ulByteCount )
+ {
+ FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %u: %d/%u bytes (tail %u head %u space %u front %u)\n",
+ ( UBaseType_t ) uxOffset,
+ ( BaseType_t ) xResult,
+ ( UBaseType_t ) ulByteCount,
+ ( UBaseType_t ) pxStream->uxTail,
+ ( UBaseType_t ) pxStream->uxHead,
+ ( UBaseType_t ) uxStreamBufferFrontSpace( pxStream ),
+ ( UBaseType_t ) pxStream->uxFront ) );
+ }
}
- }
- #endif /* ipconfigHAS_DEBUG_PRINTF */
+ #endif /* ipconfigHAS_DEBUG_PRINTF */
- if( uxOffset == 0u )
- {
- /* Data is being added to rxStream at the head (offs = 0) */
- #if( ipconfigUSE_CALLBACKS == 1 )
+ if( uxOffset == 0U )
+ {
+ /* Data is being added to rxStream at the head (offs = 0) */
+ #if( ipconfigUSE_CALLBACKS == 1 )
if( bHasHandler != pdFALSE )
{
/* The socket owner has installed an OnReceive handler. Pass the
@@ -3058,7 +3357,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
uint32_t ulCount;
if( pucBuffer != NULL )
{
- ucReadPtr = ( uint8_t * )pucBuffer;
+ ucReadPtr = ipPOINTER_CAST( uint8_t *, pucBuffer );
ulCount = ulByteCount;
pucBuffer = NULL;
}
@@ -3067,44 +3366,45 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
}
- if( ulCount == 0ul )
+ if( ulCount == 0UL )
{
break;
}
- pxSocket->u.xTCP.pxHandleReceive( ( Socket_t )pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount );
- uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );
+ ( void ) pxSocket->u.xTCP.pxHandleReceive( pxSocket, ucReadPtr, ( size_t ) ulCount );
+ ( void ) uxStreamBufferGet( pxStream, 0UL, NULL, ( size_t ) ulCount, pdFALSE );
}
} else
- #endif /* ipconfigUSE_CALLBACKS */
- {
- /* See if running out of space. */
- if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
+ #endif /* ipconfigUSE_CALLBACKS */
{
- size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
- if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
+ /* See if running out of space. */
+ if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
{
- pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;
- pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
+ size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
+ if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
+ {
+ pxSocket->u.xTCP.bits.bLowWater = pdTRUE;
+ pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
- /* bLowWater was reached, send the changed window size. */
- pxSocket->u.xTCP.usTimeout = 1u;
- xSendEventToIPTask( eTCPTimerEvent );
+ /* bLowWater was reached, send the changed window size. */
+ pxSocket->u.xTCP.usTimeout = 1U;
+ ( void ) xSendEventToIPTask( eTCPTimerEvent );
+ }
}
- }
- /* New incoming data is available, wake up the user. User's
- semaphores will be set just before the IP-task goes asleep. */
- pxSocket->xEventBits |= eSOCKET_RECEIVE;
+ /* New incoming data is available, wake up the user. User's
+ semaphores will be set just before the IP-task goes asleep. */
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_RECEIVE;
- #if ipconfigSUPPORT_SELECT_FUNCTION == 1
- {
- if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
+ #if ipconfigSUPPORT_SELECT_FUNCTION == 1
{
- pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != 0U )
+ {
+ pxSocket->xEventBits |= ( ( ( EventBits_t ) eSELECT_READ ) << SOCKET_EVENT_BIT_COUNT );
+ }
}
+ #endif
}
- #endif
}
}
@@ -3117,9 +3417,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
/* Function to get the remote address and IP port */
- BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )
+ BaseType_t FreeRTOS_GetRemoteAddress( ConstSocket_t xSocket, struct freertos_sockaddr *pxAddress )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xResult;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3130,14 +3430,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
{
/* BSD style sockets communicate IP and port addresses in network
byte order.
-
IP address of remote machine. */
pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );
/* Port on remote machine. */
pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );
- xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );
+ xResult = ( BaseType_t ) sizeof( *pxAddress );
}
return xResult;
@@ -3150,18 +3449,18 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
/* Returns the number of bytes that may be added to txStream */
- BaseType_t FreeRTOS_maywrite( Socket_t xSocket )
+ BaseType_t FreeRTOS_maywrite( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xResult;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
xResult = -pdFREERTOS_ERRNO_EINVAL;
}
- else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )
+ else if( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eESTABLISHED )
{
- if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )
+ if( ( pxSocket->u.xTCP.ucTCPState < ( uint8_t ) eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > ( EventBits_t ) eESTABLISHED ) )
{
xResult = -1;
}
@@ -3185,11 +3484,11 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#endif /* ipconfigUSE_TCP */
/*-----------------------------------------------------------*/
-#if( ipconfigUSE_TCP ==1 )
+#if( ipconfigUSE_TCP == 1 )
- BaseType_t FreeRTOS_tx_space( Socket_t xSocket )
+ BaseType_t FreeRTOS_tx_space( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3216,9 +3515,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- BaseType_t FreeRTOS_tx_size( Socket_t xSocket )
+ BaseType_t FreeRTOS_tx_size( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3246,9 +3545,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
/* Returns pdTRUE if TCP socket is connected. */
- BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )
+ BaseType_t FreeRTOS_issocketconnected( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn = pdFALSE;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3257,9 +3556,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
else
{
- if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
+ if( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED )
{
- if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )
+ if( pxSocket->u.xTCP.ucTCPState < ( uint8_t ) eCLOSE_WAIT )
{
xReturn = pdTRUE;
}
@@ -3274,10 +3573,10 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- /* returns the actual size of MSS being used */
- BaseType_t FreeRTOS_mss( Socket_t xSocket )
+ /* Returns the actual size of MSS being used. */
+ BaseType_t FreeRTOS_mss( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3300,10 +3599,10 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigUSE_TCP == 1 )
- /* HT: for internal use only: return the connection status */
- BaseType_t FreeRTOS_connstatus( Socket_t xSocket )
+ /* For internal use only: return the connection status. */
+ BaseType_t FreeRTOS_connstatus( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3312,7 +3611,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
else
{
- /* Cast it to BaseType_t */
+ /* Cast it to BaseType_t. */
xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
}
@@ -3327,9 +3626,9 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/*
* Returns the number of bytes which can be read.
*/
- BaseType_t FreeRTOS_rx_size( Socket_t xSocket )
+ BaseType_t FreeRTOS_rx_size( ConstSocket_t xSocket )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
@@ -3351,6 +3650,24 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#endif /* ipconfigUSE_TCP */
/*-----------------------------------------------------------*/
+#if 0
+BaseType_t FreeRTOS_udp_rx_size( Socket_t xSocket )
+{
+ BaseType_t xReturn = 0;
+ const FreeRTOS_Socket_t *pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
+
+ if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
+ {
+ xReturn = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
+ }
+ else
+ {
+ xReturn = -pdFREERTOS_ERRNO_EINVAL;
+ }
+ return xReturn;
+}
+#endif /* 0 */
+
#if( ipconfigUSE_TCP == 1 )
void FreeRTOS_netstat( void )
@@ -3362,7 +3679,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
*/
xAskEvent.eEventType = eTCPNetStat;
xAskEvent.pvData = ( void * ) NULL;
- xSendEventStructToIPTask( &xAskEvent, 1000u );
+ ( void ) xSendEventStructToIPTask( &xAskEvent, pdMS_TO_TICKS( 1000U ) );
}
#endif /* ipconfigUSE_TCP */
@@ -3373,59 +3690,59 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
void vTCPNetStat( void )
{
/* Show a simple listing of all created sockets and their connections */
- ListItem_t *pxIterator;
+ const ListItem_t *pxIterator;
BaseType_t count = 0;
+ size_t uxMinimum = uxGetMinimumFreeNetworkBuffers();
+ size_t uxCurrent = uxGetNumberOfFreeNetworkBuffers();
- if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )
+ if( !listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) )
{
FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
}
else
{
- FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
- for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
- pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
- pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+ const ListItem_t *pxEndTCP = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
+ const ListItem_t *pxEndUDP = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundUDPSocketsList ) );
+ FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
+ for( pxIterator = listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
+ pxIterator != pxEndTCP;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ const FreeRTOS_Socket_t *pxSocket = ipPOINTER_CAST( const FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
#if( ipconfigTCP_KEEP_ALIVE == 1 )
TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
#else
- TickType_t age = 0u;
- #endif
- #if( ipconfigUSE_CALLBACKS == 1 )
- void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;
- #else
- void *pxHandleReceive = (void*)NULL;
+ TickType_t age = 0U;
#endif
+
char ucChildText[16] = "";
- if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)
+ if (pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN)
{
+ /* Using function "snprintf". */
const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
- ( int ) pxSocket->u.xTCP.usChildCount,
- ( int ) pxSocket->u.xTCP.usBacklog);
+ ( int32_t ) pxSocket->u.xTCP.usChildCount,
+ ( int32_t ) pxSocket->u.xTCP.usBacklog);
+ ( void )copied_len;
/* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
configASSERT( copied_len >= 0 );
- configASSERT( copied_len < sizeof( ucChildText ) );
+ configASSERT( copied_len < ( int32_t ) sizeof( ucChildText ) );
}
FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
pxSocket->usLocalPort, /* Local port on this machine */
pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
- pxSocket->u.xTCP.rxStream != NULL,
- pxSocket->u.xTCP.txStream != NULL,
+ ( pxSocket->u.xTCP.rxStream != NULL ) ? 1 : 0,
+ ( pxSocket->u.xTCP.txStream != NULL ) ? 1 : 0,
FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
- (age > 999999 ? 999999 : age), /* Format 'age' for printing */
+ ( age > 999999u ) ? 999999u : age, /* Format 'age' for printing */
pxSocket->u.xTCP.usTimeout,
ucChildText ) );
- /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */
- ( void ) pxHandleReceive;
count++;
}
- for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
- pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );
- pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
+ pxIterator != pxEndUDP;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
/* Local port on this machine */
FreeRTOS_printf( ( "UDP Port %5u\n",
@@ -3433,11 +3750,11 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
count++;
}
- FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",
- count,
- uxGetMinimumFreeNetworkBuffers( ),
- uxGetNumberOfFreeNetworkBuffers( ),
- ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
+ FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %ld buffers free\n",
+ ( UBaseType_t ) count,
+ ( UBaseType_t ) uxMinimum,
+ ( UBaseType_t ) uxCurrent,
+ ( BaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
}
}
@@ -3458,27 +3775,26 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
/* These flags will be switched on after checking the socket status. */
EventBits_t xGroupBits = 0;
- pxSocketSet->pxSocket = NULL;
for( xRound = 0; xRound <= xLastRound; xRound++ )
{
const ListItem_t *pxIterator;
- const MiniListItem_t *pxEnd;
+ const ListItem_t *pxEnd;
if( xRound == 0 )
{
- pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );
+ pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundUDPSocketsList ) );
}
#if ipconfigUSE_TCP == 1
else
{
- pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );
+ pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
}
#endif /* ipconfigUSE_TCP == 1 */
- for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );
- pxIterator != ( const ListItem_t * ) pxEnd;
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ FreeRTOS_Socket_t *pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
if( pxSocket->pxSocketSet != pxSocketSet )
{
/* Socket does not belong to this select group. */
@@ -3486,90 +3802,94 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
}
xSocketBits = 0;
- #if( ipconfigUSE_TCP == 1 )
- if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )
- {
- /* Check if the socket has already been accepted by the
- owner. If not, it is useless to return it from a
- select(). */
- BaseType_t bAccepted = pdFALSE;
+ #if( ipconfigUSE_TCP == 1 )
+ if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
+ {
+ /* Check if the socket has already been accepted by the
+ owner. If not, it is useless to return it from a
+ select(). */
+ BaseType_t bAccepted = pdFALSE;
- if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
+ if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
+ {
+ if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
{
- if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
- {
- bAccepted = pdTRUE;
- }
+ bAccepted = pdTRUE;
}
+ }
- /* Is the set owner interested in READ events? */
- if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )
+ /* Is the set owner interested in READ events? */
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != ( EventBits_t ) 0U )
+ {
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
{
- if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
- {
- if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )
- {
- xSocketBits |= eSELECT_READ;
- }
- }
- else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
- {
- /* This socket has the re-use flag. After connecting it turns into
- aconnected socket. Set the READ event, so that accept() will be called. */
- xSocketBits |= eSELECT_READ;
- }
- else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
+ if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
{
- xSocketBits |= eSELECT_READ;
+ xSocketBits |= ( EventBits_t ) eSELECT_READ;
}
}
- /* Is the set owner interested in EXCEPTION events? */
- if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
+ else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
{
- if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )
- {
- xSocketBits |= eSELECT_EXCEPT;
- }
+ /* This socket has the re-use flag. After connecting it turns into
+ aconnected socket. Set the READ event, so that accept() will be called. */
+ xSocketBits |= ( EventBits_t ) eSELECT_READ;
}
-
- /* Is the set owner interested in WRITE events? */
- if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
+ else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
{
- BaseType_t bMatch = pdFALSE;
+ xSocketBits |= ( EventBits_t ) eSELECT_READ;
+ }
+ else
+ {
+ /* Nothing. */
+ }
+ }
+ /* Is the set owner interested in EXCEPTION events? */
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_EXCEPT ) != 0U )
+ {
+ if( ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSED ) )
+ {
+ xSocketBits |= ( EventBits_t ) eSELECT_EXCEPT;
+ }
+ }
- if( bAccepted != 0 )
- {
- if( FreeRTOS_tx_space( pxSocket ) > 0 )
- {
- bMatch = pdTRUE;
- }
- }
+ /* Is the set owner interested in WRITE events? */
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_WRITE ) != 0U )
+ {
+ BaseType_t bMatch = pdFALSE;
- if( bMatch == pdFALSE )
+ if( bAccepted != 0 )
+ {
+ if( FreeRTOS_tx_space( pxSocket ) > 0 )
{
- if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
- ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
- ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
- {
- pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;
- bMatch = pdTRUE;
- }
+ bMatch = pdTRUE;
}
+ }
- if( bMatch != pdFALSE )
+ if( bMatch == pdFALSE )
+ {
+ if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
+ ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) &&
+ ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
{
- xSocketBits |= eSELECT_WRITE;
+ pxSocket->u.xTCP.bits.bConnPassed = pdTRUE;
+ bMatch = pdTRUE;
}
}
+
+ if( bMatch != pdFALSE )
+ {
+ xSocketBits |= ( EventBits_t ) eSELECT_WRITE;
+ }
}
- else
- #endif /* ipconfigUSE_TCP == 1 */
+ }
+ else
+ #endif /* ipconfigUSE_TCP == 1 */
{
/* Select events for UDP are simpler. */
- if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&
+ if( ( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != 0U ) &&
( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
{
- xSocketBits |= eSELECT_READ;
+ xSocketBits |= ( EventBits_t ) eSELECT_READ;
}
/* The WRITE and EXCEPT bits are not used for UDP */
} /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
@@ -3588,24 +3908,24 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
/* Now set the necessary bits. */
- xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;
+ xBitsToClear = ( xBitsToClear & ~xGroupBits ) & ( ( EventBits_t ) eSELECT_ALL );
#if( ipconfigSUPPORT_SIGNALS != 0 )
{
/* Maybe the socketset was signalled, but don't
clear the 'eSELECT_INTR' bit here, as it will be used
and cleared in FreeRTOS_select(). */
- xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;
+ xBitsToClear &= ~( ( EventBits_t ) eSELECT_INTR );
}
#endif /* ipconfigSUPPORT_SIGNALS */
- if( xBitsToClear != 0 )
+ if( xBitsToClear != 0U )
{
- xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
+ ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
}
/* Now include eSELECT_CALL_IP to wakeup the caller. */
- xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );
+ ( void ) xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | ( EventBits_t ) eSELECT_CALL_IP );
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
@@ -3627,14 +3947,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
{
- xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );
+ ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_INTR );
xReturn = 0;
}
else
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
if( pxSocket->xEventGroup != NULL )
{
- xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );
+ ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR );
xReturn = 0;
}
else
@@ -3656,14 +3976,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
BaseType_t xReturn;
IPStackEvent_t xEvent;
- extern QueueHandle_t xNetworkEventQueue;
configASSERT( pxSocket != NULL );
- configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );
- configASSERT( pxSocket->xEventGroup );
+ configASSERT( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP );
+ configASSERT( pxSocket->xEventGroup != NULL );
xEvent.eEventType = eSocketSignalEvent;
- xEvent.pvData = ( void * )pxSocket;
+ xEvent.pvData = pxSocket;
/* The IP-task will call FreeRTOS_SignalSocket for this socket. */
xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
@@ -3673,3 +3992,94 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )
#endif /* ipconfigSUPPORT_SIGNALS */
/*-----------------------------------------------------------*/
+
+#if 0
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+struct pollfd {
+ Socket_t fd; /* file descriptor */
+ EventBits_t events; /* requested events */
+ EventBits_t revents; /* returned events */
+};
+
+typedef BaseType_t nfds_t;
+
+BaseType_t poll(struct pollfd *fds, nfds_t nfds, BaseType_t timeout);
+BaseType_t poll(struct pollfd *fds, nfds_t nfds, BaseType_t timeout)
+{
+BaseType_t index;
+SocketSelect_t *pxSocketSet = NULL;
+BaseType_t xReturn = 0;
+
+ /* See which socket-sets have been created and bound to the sockets involved. */
+ for( index = 0; index < nfds; index++ )
+ {
+ FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )fds[ index ].fd;
+
+ if( pxSocket->pxSocketSet != NULL )
+ {
+ if( pxSocketSet == NULL )
+ {
+ /* Use this socket-set. */
+ pxSocketSet = pxSocket->pxSocketSet;
+ xReturn = 1;
+ }
+ else if( pxSocketSet == pxSocket->pxSocketSet )
+ {
+ /* Good: associated with the same socket-set. */
+ }
+ else
+ {
+ /* More than one socket-set is found: can not do a select on 2 sets. */
+ xReturn = -1;
+ break;
+ }
+ }
+ }
+ if( xReturn == 0 )
+ {
+ /* Create a new socket-set, and attach all sockets to it. */
+ pxSocketSet = FreeRTOS_CreateSocketSet();
+ if( pxSocketSet != NULL )
+ {
+ xReturn = 1;
+ }
+ else
+ {
+ xReturn = -2;
+ }
+ /* Memory leak: when the last socket closes, there is no more reference to
+ this socket-set. It should be marked as an automatic or anonymous socket-set,
+ so when closing the last member, its memory will be freed. */
+ }
+ if( xReturn > 0 )
+ {
+ /* Only one socket-set is found. Connect all sockets to this socket-set. */
+ for( index = 0; index < nfds; index++ )
+ {
+ FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )fds[ index ].fd;
+ EventBits_t xEventBits = fds[ index ].events;
+
+ FreeRTOS_FD_SET( pxSocket, pxSocketSet, xEventBits );
+ FreeRTOS_FD_CLR( pxSocket, pxSocketSet, ( EventBits_t ) ~xEventBits );
+ }
+ /* And sleep until an event happens or a time-out. */
+ xReturn = FreeRTOS_select( pxSocketSet, timeout );
+
+ /* Now set the return events, copying from the socked field 'xSocketBits'. */
+ for( index = 0; index < nfds; index++ )
+ {
+ FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )fds[ index ].fd;
+
+ fds[ index ].revents = pxSocket->xSocketBits & ( ( EventBits_t ) eSELECT_ALL );
+ }
+ }
+ else
+ {
+ /* -1: Sockets are connected to different socket sets. */
+ /* -2: FreeRTOS_CreateSocketSet() failed. */
+ }
+ return xReturn;
+}
+
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
+#endif /* 0 */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
index 855c9cbd3..5501da30a 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
@@ -44,9 +44,10 @@
* will be used when TCP data is received while earlier data is still missing.
* If 'pucData' equals NULL, the function is called to advance 'uxHead' only.
*/
-size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )
+size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxByteCount )
{
size_t uxSpace, uxNextHead, uxFirst;
+size_t uxCount = uxByteCount;
uxSpace = uxStreamBufferGetSpace( pxBuffer );
@@ -57,18 +58,18 @@ size_t uxSpace, uxNextHead, uxFirst;
}
else
{
- uxSpace = 0u;
+ uxSpace = 0U;
}
/* The number of bytes that can be written is the minimum of the number of
bytes requested and the number available. */
uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );
- if( uxCount != 0u )
+ if( uxCount != 0U )
{
uxNextHead = pxBuffer->uxHead;
- if( uxOffset != 0u )
+ if( uxOffset != 0U )
{
/* ( uxOffset > 0 ) means: write in front if the uxHead marker */
uxNextHead += uxOffset;
@@ -86,7 +87,7 @@ size_t uxSpace, uxNextHead, uxFirst;
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );
/* Write as many bytes as can be written in the first write. */
- memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );
+ ( void ) memcpy( &( pxBuffer->ucArray[ uxNextHead ] ), pucData, uxFirst );
/* If the number of bytes written was less than the number that
could be written in the first write... */
@@ -94,11 +95,11 @@ size_t uxSpace, uxNextHead, uxFirst;
{
/* ...then write the remaining bytes to the start of the
buffer. */
- memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );
+ ( void ) memcpy( pxBuffer->ucArray, &( pucData[ uxFirst ] ), uxCount - uxFirst );
}
}
- if( uxOffset == 0u )
+ if( uxOffset == 0U )
{
/* ( uxOffset == 0 ) means: write at uxHead position */
uxNextHead += uxCount;
@@ -140,17 +141,17 @@ size_t uxSize, uxCount, uxFirst, uxNextTail;
}
else
{
- uxSize = 0u;
+ uxSize = 0U;
}
/* Use the minimum of the wanted bytes and the available bytes. */
uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );
- if( uxCount > 0u )
+ if( uxCount > 0U )
{
uxNextTail = pxBuffer->uxTail;
- if( uxOffset != 0u )
+ if( uxOffset != 0U )
{
uxNextTail += uxOffset;
if( uxNextTail >= pxBuffer->LENGTH )
@@ -168,14 +169,14 @@ size_t uxSize, uxCount, uxFirst, uxNextTail;
/* Obtain the number of bytes it is possible to obtain in the first
read. */
- memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );
+ ( void ) memcpy( pucData, &( pxBuffer->ucArray[ uxNextTail ] ), uxFirst );
/* If the total number of wanted bytes is greater than the number
that could be read in the first read... */
if( uxCount > uxFirst )
{
/*...then read the remaining bytes from the start of the buffer. */
- memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );
+ ( void ) memcpy( &( pucData[ uxFirst ] ), pxBuffer->ucArray, uxCount - uxFirst );
}
}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
index 70487b9d0..0ce010d42 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
@@ -48,101 +48,94 @@
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h"
-#include "FreeRTOS_TCP_WIN.h"
+
+
+#include "FreeRTOSIPConfigDefaults.h"
/* Just make sure the contents doesn't get compiled if TCP is not enabled. */
#if ipconfigUSE_TCP == 1
-/* This compile-time test was moved to here because some macro's
-were unknown within 'FreeRTOSIPConfigDefaults.h'. It tests whether
-the defined MTU size can contain at least a complete TCP packet. */
-
-#if ( ( ipconfigTCP_MSS + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) > ipconfigNETWORK_MTU )
- #error The ipconfigTCP_MSS setting in FreeRTOSIPConfig.h is too large.
-#endif
+/*lint -e750 local macro not referenced [MISRA 2012 Rule 2.5, advisory] */
/*
* The meaning of the TCP flags:
*/
-#define ipTCP_FLAG_FIN 0x0001u /* No more data from sender */
-#define ipTCP_FLAG_SYN 0x0002u /* Synchronize sequence numbers */
-#define ipTCP_FLAG_RST 0x0004u /* Reset the connection */
-#define ipTCP_FLAG_PSH 0x0008u /* Push function: please push buffered data to the recv application */
-#define ipTCP_FLAG_ACK 0x0010u /* Acknowledgment field is significant */
-#define ipTCP_FLAG_URG 0x0020u /* Urgent pointer field is significant */
-#define ipTCP_FLAG_ECN 0x0040u /* ECN-Echo */
-#define ipTCP_FLAG_CWR 0x0080u /* Congestion Window Reduced */
-#define ipTCP_FLAG_NS 0x0100u /* ECN-nonce concealment protection */
-#define ipTCP_FLAG_RSV 0x0E00u /* Reserved, keep 0 */
+#define tcpTCP_FLAG_FIN ( ( uint8_t ) 0x01U ) /* No more data from sender */
+#define tcpTCP_FLAG_SYN ( ( uint8_t ) 0x02U ) /* Synchronize sequence numbers */
+#define tcpTCP_FLAG_RST ( ( uint8_t ) 0x04U ) /* Reset the connection */
+#define tcpTCP_FLAG_PSH ( ( uint8_t ) 0x08U ) /* Push function: please push buffered data to the recv application */
+#define tcpTCP_FLAG_ACK ( ( uint8_t ) 0x10U ) /* Acknowledgment field is significant */
+#define tcpTCP_FLAG_URG ( ( uint8_t ) 0x20U ) /* Urgent pointer field is significant */
+#define tcpTCP_FLAG_ECN ( ( uint8_t ) 0x40U ) /* ECN-Echo */
+#define tcpTCP_FLAG_CWR ( ( uint8_t ) 0x80U ) /* Congestion Window Reduced */
/* A mask to filter all protocol flags. */
-#define ipTCP_FLAG_CTRL 0x001Fu
+#define tcpTCP_FLAG_CTRL ( ( uint8_t ) 0x1FU )
/*
* A few values of the TCP options:
*/
-#define TCP_OPT_END 0u /* End of TCP options list */
-#define TCP_OPT_NOOP 1u /* "No-operation" TCP option */
-#define TCP_OPT_MSS 2u /* Maximum segment size TCP option */
-#define TCP_OPT_WSOPT 3u /* TCP Window Scale Option (3-byte long) */
-#define TCP_OPT_SACK_P 4u /* Advertize that SACK is permitted */
-#define TCP_OPT_SACK_A 5u /* SACK option with first/last */
-#define TCP_OPT_TIMESTAMP 8u /* Time-stamp option */
+#define tcpTCP_OPT_END 0U /* End of TCP options list */
+#define tcpTCP_OPT_NOOP 1U /* "No-operation" TCP option */
+#define tcpTCP_OPT_MSS 2U /* Maximum segment size TCP option */
+#define tcpTCP_OPT_WSOPT 3U /* TCP Window Scale Option (3-byte long) */
+#define tcpTCP_OPT_SACK_P 4U /* Advertize that SACK is permitted */
+#define tcpTCP_OPT_SACK_A 5U /* SACK option with first/last */
+#define tcpTCP_OPT_TIMESTAMP 8U /* Time-stamp option */
-#define TCP_OPT_MSS_LEN 4u /* Length of TCP MSS option. */
-#define TCP_OPT_WSOPT_LEN 3u /* Length of TCP WSOPT option. */
+#define tcpTCP_OPT_MSS_LEN 4U /* Length of TCP MSS option. */
+#define tcpTCP_OPT_WSOPT_LEN 3U /* Length of TCP WSOPT option. */
-#define TCP_OPT_TIMESTAMP_LEN 10 /* fixed length of the time-stamp option */
+#define tcpTCP_OPT_TIMESTAMP_LEN 10 /* fixed length of the time-stamp option */
#ifndef ipconfigTCP_ACK_EARLIER_PACKET
#define ipconfigTCP_ACK_EARLIER_PACKET 1
#endif
/*
- * The macro NOW_CONNECTED() is use to determine if the connection makes a
+ * The macro tcpNOW_CONNECTED() is use to determine if the connection makes a
* transition from connected to non-connected and vice versa.
- * NOW_CONNECTED() returns true when the status has one of these values:
+ * tcpNOW_CONNECTED() returns true when the status has one of these values:
* eESTABLISHED, eFIN_WAIT_1, eFIN_WAIT_2, eCLOSING, eLAST_ACK, eTIME_WAIT
* Technically the connection status is closed earlier, but the library wants
* to prevent that the socket will be deleted before the last ACK has been
* and thus causing a 'RST' packet on either side.
*/
-#define NOW_CONNECTED( status )\
- ( ( status >= eESTABLISHED ) && ( status != eCLOSE_WAIT ) )
+#define tcpNOW_CONNECTED( status )\
+ ( ( ( ( status ) >= ( BaseType_t ) eESTABLISHED ) && ( ( status ) != ( BaseType_t ) eCLOSE_WAIT ) ) ? 1 : 0 )
/*
* The highest 4 bits in the TCP offset byte indicate the total length of the
* TCP header, divided by 4.
*/
-#define VALID_BITS_IN_TCP_OFFSET_BYTE ( 0xF0u )
+#define tcpVALID_BITS_IN_TCP_OFFSET_BYTE ( 0xF0U )
/*
* Acknowledgements to TCP data packets may be delayed as long as more is being expected.
* A normal delay would be 200ms. Here a much shorter delay of 20 ms is being used to
* gain performance.
*/
-#define DELAYED_ACK_SHORT_DELAY_MS ( 2 )
-#define DELAYED_ACK_LONGER_DELAY_MS ( 20 )
+#define tcpDELAYED_ACK_SHORT_DELAY_MS ( 2 ) /* Should not become smaller than 1. */
+#define tcpDELAYED_ACK_LONGER_DELAY_MS ( 20 )
/*
* The MSS (Maximum Segment Size) will be taken as large as possible. However, packets with
* an MSS of 1460 bytes won't be transported through the internet. The MSS will be reduced
* to 1400 bytes.
*/
-#define REDUCED_MSS_THROUGH_INTERNET ( 1400 )
+#define tcpREDUCED_MSS_THROUGH_INTERNET ( 1400 )
/*
* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as
* the number 5 (words) in the higher niblle of the TCP-offset byte.
*/
-#define TCP_OFFSET_LENGTH_BITS ( 0xf0u )
-#define TCP_OFFSET_STANDARD_LENGTH ( 0x50u )
+#define tcpTCP_OFFSET_LENGTH_BITS ( 0xf0U )
+#define tcpTCP_OFFSET_STANDARD_LENGTH ( 0x50U )
/*
* Each TCP socket is checked regularly to see if it can send data packets.
@@ -158,35 +151,18 @@ the defined MTU size can contain at least a complete TCP packet. */
* When a TCP timer expires, retries and keep-alive messages will be checked.
*/
#ifndef tcpMAXIMUM_TCP_WAKEUP_TIME_MS
- #define tcpMAXIMUM_TCP_WAKEUP_TIME_MS 20000u
+ #define tcpMAXIMUM_TCP_WAKEUP_TIME_MS 20000U
#endif
-/*
- * The names of the different TCP states may be useful in logging.
- */
-#if( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )
- static const char *pcStateNames[] = {
- "eCLOSED",
- "eTCP_LISTEN",
- "eCONNECT_SYN",
- "eSYN_FIRST",
- "eSYN_RECEIVED",
- "eESTABLISHED",
- "eFIN_WAIT_1",
- "eFIN_WAIT_2",
- "eCLOSE_WAIT",
- "eCLOSING",
- "eLAST_ACK",
- "eTIME_WAIT",
- "eUNKNOWN",
-};
-#endif /* ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) */
+/* Two macro's that were introduced to work with both IPv4 and IPv6. */
+#define xIPHeaderSize( pxNetworkBuffer ) ( ipSIZE_OF_IPv4_HEADER )
+#define uxIPHeaderSizeSocket( pxSocket ) ( ipSIZE_OF_IPv4_HEADER )
/*
* Returns true if the socket must be checked. Non-active sockets are waiting
* for user action, either connect() or close().
*/
-static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus );
+static BaseType_t prvTCPSocketIsActive( eIPTCPState_t xStatus );
/*
* Either sends a SYN or calls prvTCPSendRepeated (for regular messages).
@@ -201,7 +177,7 @@ static int32_t prvTCPSendRepeated( FreeRTOS_Socket_t *pxSocket, NetworkBufferDes
/*
* Return or send a packet to the other party.
*/
-static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
+static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxDescriptor,
uint32_t ulLen, BaseType_t xReleaseAfterSend );
/*
@@ -225,27 +201,35 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );
/*
* Parse the TCP option(s) received, if present.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
+_static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
/*
* Identify and deal with a single TCP header option, advancing the pointer to
* the header. This function returns pdTRUE or pdFALSE depending on whether the
* caller should continue to parse more header options or break the loop.
*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow);
+_static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+ size_t uxTotalLength,
+ FreeRTOS_Socket_t * const pxSocket,
+ BaseType_t xHasSYNFlag );
+
+#if( ipconfigUSE_TCP_WIN == 1 )
+ /*
+ * Skip past TCP header options when doing Selective ACK, until there are no
+ * more options left.
+ */
+ _static void prvReadSackOption( const uint8_t * const pucPtr,
+ size_t uxIndex,
+ FreeRTOS_Socket_t * const pxSocket );
+#endif/* ( ipconfigUSE_TCP_WIN == 1 ) */
-/*
- * Skip past TCP header options when doing Selective ACK, until there are no
- * more options left.
- */
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen );
/*
* Set the initial properties in the options fields, like the preferred
* value of MSS and whether SACK allowed. Will be transmitted in the state
* 'eCONNECT_SYN'.
*/
-static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPPacket_t * pxTCPPacket );
+static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader );
/*
* For anti-hang protection and TCP keep-alive messages. Called in two places:
@@ -273,31 +257,31 @@ static void prvTCPAddTxData( FreeRTOS_Socket_t *pxSocket );
/*
* Called to handle the closure of a TCP connection.
*/
-static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
+static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
/*
* Called from prvTCPHandleState(). Find the TCP payload data and check and
* return its length.
*/
-static BaseType_t prvCheckRxData( NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData );
+static BaseType_t prvCheckRxData( const NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData );
/*
* Called from prvTCPHandleState(). Check if the payload data may be accepted.
* If so, it will be added to the socket's reception queue.
*/
-static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, uint8_t *pucRecvData,
+static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, const uint8_t *pucRecvData,
NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulReceiveLength );
/*
* Set the TCP options (if any) for the outgoing packet.
*/
-static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
+static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
/*
* Called from prvTCPHandleState() as long as the TCP status is eSYN_RECEIVED to
* eCONNECT_SYN.
*/
-static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,
+static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer,
uint32_t ulReceiveLength, UBaseType_t uxOptionsLength );
/*
@@ -312,7 +296,7 @@ static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t *pxSocket, NetworkBuff
* be checked if it would better be postponed for efficiency.
*/
static BaseType_t prvSendData( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,
- uint32_t ulReceiveLength, BaseType_t xSendLength );
+ uint32_t ulReceiveLength, BaseType_t xByteCount );
/*
* The heart of all: check incoming packet for valid data and acks and do what
@@ -325,7 +309,7 @@ static BaseType_t prvTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferD
* payload, just flags).
*/
static BaseType_t prvTCPSendSpecialPacketHelper( NetworkBufferDescriptor_t *pxNetworkBuffer,
- uint8_t ucTCPFlags );
+ uint8_t ucTCPFlags );
/*
* A "challenge ACK" is as per https://tools.ietf.org/html/rfc5961#section-3.2,
@@ -365,43 +349,42 @@ static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t *pxNewSocket, FreeRTOS_Soc
static BaseType_t prvTCPStatusAgeCheck( FreeRTOS_Socket_t *pxSocket );
#endif
-static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
+static NetworkBufferDescriptor_t *prvTCPBufferResize( const FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
int32_t lDataLen, UBaseType_t uxOptionsLength );
-#if( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )
- const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState );
-#endif
-
#if( ipconfigUSE_TCP_WIN != 0 )
- static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket );
+ static uint8_t prvWinScaleFactor( const FreeRTOS_Socket_t *pxSocket );
#endif
-/*
- * Generate a randomized TCP Initial Sequence Number per RFC.
- */
-extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
- uint16_t usSourcePort,
- uint32_t ulDestinationAddress,
- uint16_t usDestinationPort );
-
/*-----------------------------------------------------------*/
/* prvTCPSocketIsActive() returns true if the socket must be checked.
* Non-active sockets are waiting for user action, either connect()
* or close(). */
-static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )
+static BaseType_t prvTCPSocketIsActive( eIPTCPState_t xStatus )
{
- switch( uxStatus )
+BaseType_t xResult;
+ switch( xStatus )
{
case eCLOSED:
case eCLOSE_WAIT:
case eFIN_WAIT_2:
case eCLOSING:
case eTIME_WAIT:
- return pdFALSE;
+ xResult = pdFALSE;
+ break;
+ case eTCP_LISTEN:
+ case eCONNECT_SYN:
+ case eSYN_FIRST:
+ case eSYN_RECEIVED:
+ case eESTABLISHED:
+ case eFIN_WAIT_1:
+ case eLAST_ACK:
default:
- return pdTRUE;
+ xResult = pdTRUE;
+ break;
}
+ return xResult;
}
/*-----------------------------------------------------------*/
@@ -410,7 +393,9 @@ static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )
static BaseType_t prvTCPStatusAgeCheck( FreeRTOS_Socket_t *pxSocket )
{
BaseType_t xResult;
- switch( pxSocket->u.xTCP.ucTCPState )
+ eIPTCPState_t eState = ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState );
+
+ switch( eState )
{
case eESTABLISHED:
/* If the 'ipconfigTCP_KEEP_ALIVE' option is enabled, sockets in
@@ -423,6 +408,14 @@ static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )
/* These 3 states may last for ever, up to the owner. */
xResult = pdFALSE;
break;
+ case eCONNECT_SYN:
+ case eSYN_FIRST:
+ case eSYN_RECEIVED:
+ case eFIN_WAIT_1:
+ case eFIN_WAIT_2:
+ case eCLOSING:
+ case eLAST_ACK:
+ case eTIME_WAIT:
default:
/* All other (non-connected) states will get anti-hanging
protection. */
@@ -436,7 +429,7 @@ static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )
TickType_t xAge = xTaskGetTickCount( ) - pxSocket->u.xTCP.xLastActTime;
/* ipconfigTCP_HANG_PROTECTION_TIME is in units of seconds. */
- if( xAge > ( ipconfigTCP_HANG_PROTECTION_TIME * configTICK_RATE_HZ ) )
+ if( xAge > ( ( TickType_t ) ipconfigTCP_HANG_PROTECTION_TIME * ( TickType_t ) configTICK_RATE_HZ ) )
{
#if( ipconfigHAS_DEBUG_PRINTF == 1 )
{
@@ -461,7 +454,7 @@ static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )
accept() it anymore, it will be deleted now. Called from
the IP-task, so it's safe to call the internal Close
function: vSocketClose(). */
- vSocketClose( pxSocket );
+ ( void ) vSocketClose( pxSocket );
}
/* Return a negative value to tell to inform the caller
xTCPTimerCheck()
@@ -494,14 +487,14 @@ BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t *pxSocket )
BaseType_t xResult = 0;
BaseType_t xReady = pdFALSE;
- if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) )
+ if( ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) )
{
/* The API FreeRTOS_send() might have added data to the TX stream. Add
- this data to the windowing system to it can be transmitted. */
+ this data to the windowing system so it can be transmitted. */
prvTCPAddTxData( pxSocket );
}
- #if ipconfigUSE_TCP_WIN == 1
+ #if( ipconfigUSE_TCP_WIN == 1 )
{
if( pxSocket->u.xTCP.pxAckMessage != NULL )
{
@@ -512,16 +505,16 @@ BaseType_t xReady = pdFALSE;
/* Earlier data was received but not yet acknowledged. This
function is called when the TCP timer for the socket expires, the
ACK may be sent now. */
- if( pxSocket->u.xTCP.ucTCPState != eCLOSED )
+ if( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCLOSED )
{
- if( xTCPWindowLoggingLevel > 1 && ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) )
+ if( ( xTCPWindowLoggingLevel > 1 ) && ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) )
{
FreeRTOS_debug_printf( ( "Send[%u->%u] del ACK %lu SEQ %lu (len %u)\n",
pxSocket->usLocalPort,
pxSocket->u.xTCP.usRemotePort,
pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber,
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - pxSocket->u.xTCP.xTCPWindow.tx.ulFirstSequenceNumber,
- ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) );
+ ( unsigned ) ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) );
}
prvTCPReturnPacket( pxSocket, pxSocket->u.xTCP.pxAckMessage, ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER, ipconfigZERO_COPY_TX_DRIVER );
@@ -534,7 +527,7 @@ BaseType_t xReady = pdFALSE;
}
#endif /* ipconfigZERO_COPY_TX_DRIVER */
}
- if( prvTCPNextTimeout( pxSocket ) > 1 )
+ if( prvTCPNextTimeout( pxSocket ) > 1U )
{
/* Tell the code below that this function is ready. */
xReady = pdTRUE;
@@ -559,14 +552,14 @@ BaseType_t xReady = pdFALSE;
if( xReady == pdFALSE )
{
/* The second task of this regular socket check is sending out data. */
- if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) ||
- ( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) )
+ if( ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) ||
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN ) )
{
- prvTCPSendPacket( pxSocket );
+ ( void ) prvTCPSendPacket( pxSocket );
}
/* Set the time-out for the next wakeup for this socket. */
- prvTCPNextTimeout( pxSocket );
+ ( void ) prvTCPNextTimeout( pxSocket );
#if( ipconfigTCP_HANG_PROTECTION == 1 )
{
@@ -589,12 +582,11 @@ static int32_t prvTCPSendPacket( FreeRTOS_Socket_t *pxSocket )
{
int32_t lResult = 0;
UBaseType_t uxOptionsLength;
-TCPPacket_t *pxTCPPacket;
NetworkBufferDescriptor_t *pxNetworkBuffer;
- if( pxSocket->u.xTCP.ucTCPState != eCONNECT_SYN )
+ if( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCONNECT_SYN )
{
- /* The connection is in s state other than SYN. */
+ /* The connection is in a state other than SYN. */
pxNetworkBuffer = NULL;
/* prvTCPSendRepeated() will only create a network buffer if necessary,
@@ -608,7 +600,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
}
else
{
- if( pxSocket->u.xTCP.ucRepCount >= 3u )
+ if( pxSocket->u.xTCP.ucRepCount >= 3U )
{
/* The connection is in the SYN status. The packet will be repeated
to most 3 times. When there is no response, the socket get the
@@ -620,25 +612,27 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
}
else if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) || ( prvTCPPrepareConnect( pxSocket ) == pdTRUE ) )
{
+ ProtocolHeaders_t *pxProtocolHeaders;
+ const UBaseType_t uxHeaderSize = ipSIZE_OF_IPv4_HEADER;
/* Or else, if the connection has been prepared, or can be prepared
now, proceed to send the packet with the SYN flag.
prvTCPPrepareConnect() prepares 'xPacket' and returns pdTRUE if
the Ethernet address of the peer or the gateway is found. */
- pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;
+ pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *, &( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ ipSIZE_OF_ETH_HEADER + uxHeaderSize ] ) );
/* About to send a SYN packet. Call prvSetSynAckOptions() to set
the proper options: The size of MSS and whether SACK's are
allowed. */
- uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPPacket );
+ uxOptionsLength = prvSetSynAckOptions( pxSocket, &( pxProtocolHeaders->xTCPHeader ) );
/* Return the number of bytes to be sent. */
- lResult = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ lResult = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
/* Set the TCP offset field: ipSIZE_OF_TCP_HEADER equals 20 and
uxOptionsLength is always a multiple of 4. The complete expression
would be:
ucTCPOffset = ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) / 4 ) << 4 */
- pxTCPPacket->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
+ pxProtocolHeaders->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
/* Repeat Count is used for a connecting socket, to limit the number
of tries. */
@@ -649,6 +643,10 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
pseudo network buffer descriptor before it will be sent. */
prvTCPReturnPacket( pxSocket, NULL, ( uint32_t ) lResult, pdFALSE );
}
+ else
+ {
+ /* Nothing to do. */
+ }
}
/* Return the total number of bytes sent. */
@@ -664,10 +662,10 @@ static int32_t prvTCPSendRepeated( FreeRTOS_Socket_t *pxSocket, NetworkBufferDes
{
UBaseType_t uxIndex;
int32_t lResult = 0;
-UBaseType_t uxOptionsLength = 0u;
+UBaseType_t uxOptionsLength = 0U;
int32_t xSendLength;
- for( uxIndex = 0u; uxIndex < ( UBaseType_t ) SEND_REPEATED_COUNT; uxIndex++ )
+ for( uxIndex = 0U; uxIndex < ( UBaseType_t ) SEND_REPEATED_COUNT; uxIndex++ )
{
/* prvTCPPrepareSend() might allocate a network buffer if there is data
to be sent. */
@@ -700,13 +698,15 @@ int32_t xSendLength;
* called 'xTCP.xPacket'. A temporary xNetworkBuffer will be used to pass
* the data to the NIC.
*/
-static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulLen, BaseType_t xReleaseAfterSend )
+static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxDescriptor, uint32_t ulLen, BaseType_t xReleaseAfterSend )
{
TCPPacket_t * pxTCPPacket;
IPHeader_t *pxIPHeader;
+BaseType_t xDoRelease = xReleaseAfterSend;
EthernetHeader_t *pxEthernetHeader;
uint32_t ulFrontSpace, ulSpace, ulSourceAddress, ulWinSize;
-TCPWindow_t *pxTCPWindow;
+const TCPWindow_t *pxTCPWindow;
+NetworkBufferDescriptor_t *pxNetworkBuffer = pxDescriptor;
NetworkBufferDescriptor_t xTempBuffer;
/* For sending, a pseudo network buffer will be used, as explained above. */
@@ -716,31 +716,34 @@ NetworkBufferDescriptor_t xTempBuffer;
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
- xTempBuffer.pxNextBuffer = NULL;
+ pxNetworkBuffer->pxNextBuffer = NULL;
}
#endif
- xTempBuffer.pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
- xTempBuffer.xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
- xReleaseAfterSend = pdFALSE;
+ pxNetworkBuffer->pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
+ pxNetworkBuffer->xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
+ xDoRelease = pdFALSE;
}
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
{
- if( xReleaseAfterSend == pdFALSE )
+ if( xDoRelease == pdFALSE )
{
- pxNetworkBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );
+ pxNetworkBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( size_t ) pxNetworkBuffer->xDataLength );
if( pxNetworkBuffer == NULL )
{
FreeRTOS_debug_printf( ( "prvTCPReturnPacket: duplicate failed\n" ) );
}
- xReleaseAfterSend = pdTRUE;
+ xDoRelease = pdTRUE;
}
}
#endif /* ipconfigZERO_COPY_TX_DRIVER */
+ #ifndef __COVERITY__
if( pxNetworkBuffer != NULL )
+ #endif
{
- pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+ /* Map the ethernet buffer onto a TCPPacket_t struct for easy access to the fields. */
+ pxTCPPacket = ipPOINTER_CAST( TCPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
pxIPHeader = &pxTCPPacket->xIPHeader;
pxEthernetHeader = &pxTCPPacket->xEthernetHeader;
@@ -773,7 +776,7 @@ NetworkBufferDescriptor_t xTempBuffer;
space left. The socket will wait until the application has read
or flushed the incoming data, and 'zero-window' will be
advertised. */
- ulSpace = 0u;
+ ulSpace = 0U;
}
/* If possible, advertise an RX window size of at least 1 MSS, otherwise
@@ -801,34 +804,6 @@ NetworkBufferDescriptor_t xTempBuffer;
pxTCPPacket->xTCPHeader.usWindow = FreeRTOS_htons( ( uint16_t ) ulWinSize );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
- {
- if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )
- {
- if( ( xTCPWindowLoggingLevel != 0 ) && ( pxSocket->u.xTCP.bits.bWinChange != pdFALSE_UNSIGNED ) )
- {
- size_t uxFrontSpace;
-
- if(pxSocket->u.xTCP.rxStream != NULL)
- {
- uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream ) ;
- }
- else
- {
- uxFrontSpace = 0u;
- }
-
- FreeRTOS_debug_printf( ( "%s: %lxip:%u: [%lu < %lu] winSize %ld\n",
- pxSocket->u.xTCP.bits.bLowWater ? "STOP" : "GO ",
- pxSocket->u.xTCP.ulRemoteIP,
- pxSocket->u.xTCP.usRemotePort,
- pxSocket->u.xTCP.bits.bLowWater ? pxSocket->u.xTCP.uxLittleSpace : uxFrontSpace, pxSocket->u.xTCP.uxEnoughSpace,
- (int32_t) ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulCurrentSequenceNumber ) ) );
- }
- }
- }
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
-
/* The new window size has been advertised, switch off the flag. */
pxSocket->u.xTCP.bits.bWinChange = pdFALSE_UNSIGNED;
@@ -837,31 +812,31 @@ NetworkBufferDescriptor_t xTempBuffer;
highest sequence number minus 1 that the socket will accept. */
pxSocket->u.xTCP.ulHighestRxAllowed = pxTCPWindow->rx.ulCurrentSequenceNumber + ulSpace;
- #if( ipconfigTCP_KEEP_ALIVE == 1 )
- if( pxSocket->u.xTCP.bits.bSendKeepAlive != pdFALSE_UNSIGNED )
- {
- /* Sending a keep-alive packet, send the current sequence number
- minus 1, which will be recognised as a keep-alive packet an
- responded to by acknowledging the last byte. */
- pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED;
- pxSocket->u.xTCP.bits.bWaitKeepAlive = pdTRUE_UNSIGNED;
-
- pxTCPPacket->xTCPHeader.ulSequenceNumber = pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - 1UL;
- pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
- }
- else
- #endif
+ #if( ipconfigTCP_KEEP_ALIVE == 1 )
+ if( pxSocket->u.xTCP.bits.bSendKeepAlive != pdFALSE_UNSIGNED )
+ {
+ /* Sending a keep-alive packet, send the current sequence number
+ minus 1, which will be recognised as a keep-alive packet an
+ responded to by acknowledging the last byte. */
+ pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED;
+ pxSocket->u.xTCP.bits.bWaitKeepAlive = pdTRUE_UNSIGNED;
+
+ pxTCPPacket->xTCPHeader.ulSequenceNumber = pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - 1UL;
+ pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
+ }
+ else
+ #endif
{
pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber );
- if( ( pxTCPPacket->xTCPHeader.ucTCPFlags & ( uint8_t ) ipTCP_FLAG_FIN ) != 0u )
+ if( ( pxTCPPacket->xTCPHeader.ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_FIN ) != 0U )
{
/* Suppress FIN in case this packet carries earlier data to be
retransmitted. */
uint32_t ulDataLen = ( uint32_t ) ( ulLen - ( ipSIZE_OF_TCP_HEADER + ipSIZE_OF_IPv4_HEADER ) );
if( ( pxTCPWindow->ulOurSequenceNumber + ulDataLen ) != pxTCPWindow->tx.ulFINSequenceNumber )
{
- pxTCPPacket->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~ipTCP_FLAG_FIN );
+ pxTCPPacket->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~tcpTCP_FLAG_FIN );
FreeRTOS_debug_printf( ( "Suppress FIN for %lu + %lu < %lu\n",
pxTCPWindow->ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,
ulDataLen,
@@ -882,12 +857,12 @@ NetworkBufferDescriptor_t xTempBuffer;
pxIPHeader->ucTimeToLive = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;
pxIPHeader->usLength = FreeRTOS_htons( ulLen );
- if( ( pxSocket == NULL ) || ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )
+ if( ( pxSocket == NULL ) || ( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) )
{
/* When pxSocket is NULL, this function is called by prvTCPSendReset()
and the IP-addresses must be swapped.
Also swap the IP-addresses in case the IP-tack doesn't have an
- IP-address yet, i.e. when ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ). */
+ IP-address yet, i.e. when ( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ). */
ulSourceAddress = pxIPHeader->ulDestinationIPAddress;
}
else
@@ -901,41 +876,44 @@ NetworkBufferDescriptor_t xTempBuffer;
/* Just an increasing number. */
pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier );
usPacketIdentifier++;
- pxIPHeader->usFragmentOffset = 0u;
+ pxIPHeader->usFragmentOffset = 0U;
+
+ /* Important: tell NIC driver how many bytes must be sent. */
+ pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
/* calculate the IP header checksum, in case the driver won't do that. */
- pxIPHeader->usHeaderChecksum = 0x00u;
- pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = 0x00U;
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
/* calculate the TCP checksum for an outgoing packet. */
- usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
+ ( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxTCPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
/* A calculated checksum of 0 must be inverted as 0 means the checksum
is disabled. */
- if( pxTCPPacket->xTCPHeader.usChecksum == 0x00u )
+ if( pxTCPPacket->xTCPHeader.usChecksum == 0U )
{
pxTCPPacket->xTCPHeader.usChecksum = 0xffffU;
}
}
#endif
- #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
- pxNetworkBuffer->pxNextBuffer = NULL;
- #endif
-
- /* Important: tell NIC driver how many bytes must be sent. */
- pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
+ {
+ pxNetworkBuffer->pxNextBuffer = NULL;
+ }
+ #endif
/* Fill in the destination MAC addresses. */
- memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ),
- sizeof( pxEthernetHeader->xDestinationAddress ) );
+ ( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ),
+ &( pxEthernetHeader->xSourceAddress ),
+ sizeof( pxEthernetHeader->xDestinationAddress ) );
/* The source MAC addresses is fixed to 'ipLOCAL_MAC_ADDRESS'. */
- memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
-
+ ( void ) memcpy( &( pxEthernetHeader->xSourceAddress ), ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
{
if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
@@ -944,7 +922,7 @@ NetworkBufferDescriptor_t xTempBuffer;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
- pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
+ pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
@@ -952,15 +930,15 @@ NetworkBufferDescriptor_t xTempBuffer;
#endif
/* Send! */
- xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
+ ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, xDoRelease );
- if( xReleaseAfterSend == pdFALSE )
+ if( xDoRelease == pdFALSE )
{
/* Swap-back some fields, as pxBuffer probably points to a socket field
containing the packet header. */
vFlip_16( pxTCPPacket->xTCPHeader.usSourcePort, pxTCPPacket->xTCPHeader.usDestinationPort);
pxTCPPacket->xIPHeader.ulSourceIPAddress = pxTCPPacket->xIPHeader.ulDestinationIPAddress;
- memcpy( pxEthernetHeader->xSourceAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( pxEthernetHeader->xSourceAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
}
else
{
@@ -978,16 +956,18 @@ NetworkBufferDescriptor_t xTempBuffer;
*/
static void prvTCPCreateWindow( FreeRTOS_Socket_t *pxSocket )
{
- if( xTCPWindowLoggingLevel )
- FreeRTOS_debug_printf( ( "Limits (using): TCP Win size %lu Water %lu <= %lu <= %lu\n",
- pxSocket->u.xTCP.uxRxWinSize * ipconfigTCP_MSS,
- pxSocket->u.xTCP.uxLittleSpace ,
- pxSocket->u.xTCP.uxEnoughSpace,
- pxSocket->u.xTCP.uxRxStreamSize ) );
+ if( xTCPWindowLoggingLevel != 0 )
+ {
+ FreeRTOS_debug_printf( ( "Limits (using): TCP Win size %u Water %u <= %u <= %u\n",
+ ( unsigned ) pxSocket->u.xTCP.uxRxWinSize * ipconfigTCP_MSS,
+ ( unsigned ) pxSocket->u.xTCP.uxLittleSpace ,
+ ( unsigned ) pxSocket->u.xTCP.uxEnoughSpace,
+ ( unsigned ) pxSocket->u.xTCP.uxRxStreamSize ) );
+ }
vTCPWindowCreate(
&pxSocket->u.xTCP.xTCPWindow,
- ipconfigTCP_MSS * pxSocket->u.xTCP.uxRxWinSize,
- ipconfigTCP_MSS * pxSocket->u.xTCP.uxTxWinSize,
+ ( ( size_t ) ipconfigTCP_MSS ) * pxSocket->u.xTCP.uxRxWinSize,
+ ( ( size_t ) ipconfigTCP_MSS ) * pxSocket->u.xTCP.uxTxWinSize,
pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber,
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber,
( uint32_t ) pxSocket->u.xTCP.usInitMSS );
@@ -1013,7 +993,7 @@ uint32_t ulInitialSequenceNumber = 0;
#if( ipconfigHAS_PRINTF != 0 )
{
/* Only necessary for nicer logging. */
- memset( xEthAddress.ucBytes, '\0', sizeof( xEthAddress.ucBytes ) );
+ ( void ) memset( xEthAddress.ucBytes, 0, sizeof( xEthAddress.ucBytes ) );
}
#endif /* ipconfigHAS_PRINTF != 0 */
@@ -1045,8 +1025,8 @@ uint32_t ulInitialSequenceNumber = 0;
/* And issue a (new) ARP request */
FreeRTOS_OutputARPRequest( ulRemoteIP );
-
xReturn = pdFALSE;
+ break;
}
if( xReturn != pdFALSE )
@@ -1058,7 +1038,7 @@ uint32_t ulInitialSequenceNumber = 0;
pxSocket->u.xTCP.usRemotePort );
/* Check for a random number generation error. */
- if( 0 == ulInitialSequenceNumber )
+ if( ulInitialSequenceNumber == 0UL )
{
xReturn = pdFALSE;
}
@@ -1066,30 +1046,34 @@ uint32_t ulInitialSequenceNumber = 0;
if( xReturn != pdFALSE )
{
+ uint16_t usLength;
+
/* The MAC-address of the peer (or gateway) has been found,
- now prepare the initial TCP packet and some fields in the socket. */
- pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;
+ * now prepare the initial TCP packet and some fields in the socket. Map
+ * the buffer onto the TCPPacket_t struct to easily access it's field. */
+ pxTCPPacket = ipPOINTER_CAST( TCPPacket_t *, pxSocket->u.xTCP.xPacket.u.ucLastPacket );
pxIPHeader = &pxTCPPacket->xIPHeader;
/* reset the retry counter to zero. */
- pxSocket->u.xTCP.ucRepCount = 0u;
+ pxSocket->u.xTCP.ucRepCount = 0U;
/* And remember that the connect/SYN data are prepared. */
pxSocket->u.xTCP.bits.bConnPrepared = pdTRUE_UNSIGNED;
/* Now that the Ethernet address is known, the initial packet can be
prepared. */
- memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
+ ( void ) memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, 0, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
/* Write the Ethernet address in Source, because it will be swapped by
prvTCPReturnPacket(). */
- memcpy( &pxTCPPacket->xEthernetHeader.xSourceAddress, &xEthAddress, sizeof( xEthAddress ) );
+ ( void ) memcpy( &pxTCPPacket->xEthernetHeader.xSourceAddress, &xEthAddress, sizeof( xEthAddress ) );
/* 'ipIPv4_FRAME_TYPE' is already in network-byte-order. */
pxTCPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE;
- pxIPHeader->ucVersionHeaderLength = 0x45u;
- pxIPHeader->usLength = FreeRTOS_htons( sizeof( TCPPacket_t ) - sizeof( pxTCPPacket->xEthernetHeader ) );
+ pxIPHeader->ucVersionHeaderLength = 0x45U;
+ usLength = ( uint16_t ) ( sizeof( TCPPacket_t ) - sizeof( pxTCPPacket->xEthernetHeader ) );
+ pxIPHeader->usLength = FreeRTOS_htons( usLength );
pxIPHeader->ucTimeToLive = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;
pxIPHeader->ucProtocol = ( uint8_t ) ipPROTOCOL_TCP;
@@ -1104,17 +1088,17 @@ uint32_t ulInitialSequenceNumber = 0;
/* We are actively connecting, so the peer's Initial Sequence Number (ISN)
isn't known yet. */
- pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0ul;
+ pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0UL;
/* Start with ISN (Initial Sequence Number). */
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
/* The TCP header size is 20 bytes, divided by 4 equals 5, which is put in
the high nibble of the TCP offset field. */
- pxTCPPacket->xTCPHeader.ucTCPOffset = 0x50u;
+ pxTCPPacket->xTCPHeader.ucTCPOffset = 0x50U;
/* Only set the SYN flag. */
- pxTCPPacket->xTCPHeader.ucTCPFlags = ipTCP_FLAG_SYN;
+ pxTCPPacket->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_SYN;
/* Set the values of usInitMSS / usCurMSS for this socket. */
prvSocketSetMSS( pxSocket );
@@ -1133,19 +1117,20 @@ uint32_t ulInitialSequenceNumber = 0;
*/
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
- static const char *prvTCPFlagMeaning( UBaseType_t xFlags)
+ static const char *prvTCPFlagMeaning( UBaseType_t xFlags )
{
static char retString[10];
- snprintf(retString, sizeof( retString ), "%c%c%c%c%c%c%c%c%c",
- ( xFlags & ipTCP_FLAG_FIN ) ? 'F' : '.', /* 0x0001: No more data from sender */
- ( xFlags & ipTCP_FLAG_SYN ) ? 'S' : '.', /* 0x0002: Synchronize sequence numbers */
- ( xFlags & ipTCP_FLAG_RST ) ? 'R' : '.', /* 0x0004: Reset the connection */
- ( xFlags & ipTCP_FLAG_PSH ) ? 'P' : '.', /* 0x0008: Push function: please push buffered data to the recv application */
- ( xFlags & ipTCP_FLAG_ACK ) ? 'A' : '.', /* 0x0010: Acknowledgment field is significant */
- ( xFlags & ipTCP_FLAG_URG ) ? 'U' : '.', /* 0x0020: Urgent pointer field is significant */
- ( xFlags & ipTCP_FLAG_ECN ) ? 'E' : '.', /* 0x0040: ECN-Echo */
- ( xFlags & ipTCP_FLAG_CWR ) ? 'C' : '.', /* 0x0080: Congestion Window Reduced */
- ( xFlags & ipTCP_FLAG_NS ) ? 'N' : '.'); /* 0x0100: ECN-nonce concealment protection */
+ size_t uxFlags = ( size_t ) xFlags;
+ ( void ) snprintf(retString,
+ sizeof( retString ), "%c%c%c%c%c%c%c%c",
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_FIN ) != 0 ) ? 'F' : '.', /* 0x0001: No more data from sender */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_SYN ) != 0 ) ? 'S' : '.', /* 0x0002: Synchronize sequence numbers */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_RST ) != 0 ) ? 'R' : '.', /* 0x0004: Reset the connection */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_PSH ) != 0 ) ? 'P' : '.', /* 0x0008: Push function: please push buffered data to the recv application */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_ACK ) != 0 ) ? 'A' : '.', /* 0x0010: Acknowledgment field is significant */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_URG ) != 0 ) ? 'U' : '.', /* 0x0020: Urgent pointer field is significant */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_ECN ) != 0 ) ? 'E' : '.', /* 0x0040: ECN-Echo */
+ ( ( uxFlags & ( size_t ) tcpTCP_FLAG_CWR ) != 0 ) ? 'C' : '.'); /* 0x0080: Congestion Window Reduced */
return retString;
}
/*-----------------------------------------------------------*/
@@ -1157,231 +1142,287 @@ uint32_t ulInitialSequenceNumber = 0;
* that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header
* is longer than the usual 20 (5 x 4) bytes.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
+_static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
{
-TCPPacket_t * pxTCPPacket;
-TCPHeader_t * pxTCPHeader;
-const unsigned char *pucPtr;
-const unsigned char *pucLast;
-TCPWindow_t *pxTCPWindow;
-BaseType_t xShouldContinueLoop;
+size_t uxTCPHeaderOffset = ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer );
+const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ uxTCPHeaderOffset ] ) );
+const TCPHeader_t * pxTCPHeader;
+const uint8_t *pucPtr;
+BaseType_t xHasSYNFlag;
+/* Offset in the network packet where the first option byte is stored. */
+size_t uxOptionOffset = uxTCPHeaderOffset + ( sizeof( TCPHeader_t ) - sizeof( pxTCPHeader->ucOptdata ) );
+size_t uxOptionsLength;
+size_t uxResult;
+uint8_t ucLength;
+
+ pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
- pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
- pxTCPHeader = &pxTCPPacket->xTCPHeader;
/* A character pointer to iterate through the option data */
pucPtr = pxTCPHeader->ucOptdata;
- pucLast = pucPtr + (((pxTCPHeader->ucTCPOffset >> 4) - 5) << 2);
- pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
-
- /* Validate options size calculation. */
- if( pucLast > ( pxNetworkBuffer->pucEthernetBuffer + pxNetworkBuffer->xDataLength ) )
+ if( pxTCPHeader->ucTCPOffset <= ( 5U << 4U ) )
{
- return;
+ /* Avoid integer underflow in computation of ucLength. */
}
-
- /* The comparison with pucLast is only necessary in case the option data are
- corrupted, we don't like to run into invalid memory and crash. */
- xShouldContinueLoop = pdTRUE;
- while( ( pucPtr < pucLast ) && ( xShouldContinueLoop == pdTRUE ) )
+ else
{
- xShouldContinueLoop = prvSingleStepTCPHeaderOptions( &pucPtr, &pucLast, &pxSocket, &pxTCPWindow );
+ ucLength = ( ( ( pxTCPHeader->ucTCPOffset >> 4U ) - 5U ) << 2U );
+ uxOptionsLength = ( size_t ) ucLength;
+ if( pxNetworkBuffer->xDataLength > uxOptionOffset )
+ {
+ /* Validate options size calculation. */
+ if( ( pxNetworkBuffer->xDataLength > uxOptionOffset ) &&
+ ( uxOptionsLength <= ( pxNetworkBuffer->xDataLength - uxOptionOffset ) ) )
+ {
+ if( ( pxTCPHeader->ucTCPFlags & tcpTCP_FLAG_SYN ) != ( uint8_t ) 0U )
+ {
+ xHasSYNFlag = pdTRUE;
+ }
+ else
+ {
+ xHasSYNFlag = pdFALSE;
+ }
+ /* The length check is only necessary in case the option data are
+ corrupted, we don't like to run into invalid memory and crash. */
+ for( ;; )
+ {
+ if( uxOptionsLength == 0U )
+ {
+ /* coverity[break_stmt] : Break statement terminating the loop */
+ break;
+ }
+ uxResult = prvSingleStepTCPHeaderOptions( pucPtr, uxOptionsLength, pxSocket, xHasSYNFlag );
+ if( uxResult == 0UL )
+ {
+ break;
+ }
+ uxOptionsLength -= uxResult;
+ pucPtr = &( pucPtr[ uxResult ] );
+ }
+ }
+ }
}
-}
+ return;
+}
/*-----------------------------------------------------------*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow)
+_static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+ size_t uxTotalLength,
+ FreeRTOS_Socket_t * const pxSocket,
+ BaseType_t xHasSYNFlag )
{
- UBaseType_t uxNewMSS;
- UBaseType_t xRemainingOptionsBytes = ( *ppucLast ) - ( *ppucPtr );
- unsigned char ucLen;
+UBaseType_t uxNewMSS;
+size_t uxRemainingOptionsBytes = uxTotalLength;
+uint8_t ucLen;
+size_t uxIndex;
+TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
+BaseType_t xReturn = pdFALSE;
- if( ( *ppucPtr )[ 0 ] == TCP_OPT_END )
+ if( pucPtr[ 0U ] == tcpTCP_OPT_END )
{
/* End of options. */
- return pdFALSE;
+ uxIndex = 0U;
}
- if( ( *ppucPtr )[ 0 ] == TCP_OPT_NOOP)
+ else if( pucPtr[ 0U ] == tcpTCP_OPT_NOOP )
{
/* NOP option, inserted to make the length a multiple of 4. */
- ( *ppucPtr )++;
- return pdTRUE;
+ uxIndex = 1U;
}
-
- /* Any other well-formed option must be at least two bytes: the option
- type byte followed by a length byte. */
- if( xRemainingOptionsBytes < 2 )
+ else if( uxRemainingOptionsBytes < 2U )
{
- return pdFALSE;
+ /* Any other well-formed option must be at least two bytes: the option
+ type byte followed by a length byte. */
+ uxIndex = 0U;
}
#if( ipconfigUSE_TCP_WIN != 0 )
- else if( ( *ppucPtr )[ 0 ] == TCP_OPT_WSOPT )
+ else if( pucPtr[ 0 ] == tcpTCP_OPT_WSOPT )
{
+ /* The TCP Window Scale Option. */
/* Confirm that the option fits in the remaining buffer space. */
- if( ( xRemainingOptionsBytes < TCP_OPT_WSOPT_LEN ) || ( ( *ppucPtr )[ 1 ] != TCP_OPT_WSOPT_LEN ) )
+ if( ( uxRemainingOptionsBytes < tcpTCP_OPT_WSOPT_LEN ) || ( pucPtr[ 1 ] != tcpTCP_OPT_WSOPT_LEN ) )
{
- return pdFALSE;
+ uxIndex = 0U;
+ }
+ else
+ {
+ /* Option is only valid in SYN phase. */
+ if( xHasSYNFlag != 0 )
+ {
+ pxSocket->u.xTCP.ucPeerWinScaleFactor = pucPtr[ 2 ];
+ pxSocket->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED;
+ }
+ uxIndex = tcpTCP_OPT_WSOPT_LEN;
}
-
- ( *ppxSocket )->u.xTCP.ucPeerWinScaleFactor = ( *ppucPtr )[ 2 ];
- ( *ppxSocket )->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED;
- ( *ppucPtr ) += TCP_OPT_WSOPT_LEN;
}
#endif /* ipconfigUSE_TCP_WIN */
- else if( ( *ppucPtr )[ 0 ] == TCP_OPT_MSS )
+ else if( pucPtr[ 0 ] == tcpTCP_OPT_MSS )
{
/* Confirm that the option fits in the remaining buffer space. */
- if( ( xRemainingOptionsBytes < TCP_OPT_MSS_LEN )|| ( ( *ppucPtr )[ 1 ] != TCP_OPT_MSS_LEN ) )
+ if( ( uxRemainingOptionsBytes < tcpTCP_OPT_MSS_LEN ) || ( pucPtr[ 1 ] != tcpTCP_OPT_MSS_LEN ) )
{
- return pdFALSE;
+ uxIndex = 0U;
}
-
- /* An MSS option with the correct option length. FreeRTOS_htons()
- is not needed here because usChar2u16() already returns a host
- endian number. */
- uxNewMSS = usChar2u16( ( *ppucPtr ) + 2 );
-
- if( ( *ppxSocket )->u.xTCP.usInitMSS != uxNewMSS )
+ else
{
- /* Perform a basic check on the the new MSS. */
- if( uxNewMSS == 0 )
+ /* An MSS option with the correct option length. FreeRTOS_htons()
+ is not needed here because usChar2u16() already returns a host
+ endian number. */
+ uxNewMSS = usChar2u16( &( pucPtr[ 2 ] ) );
+
+ if( pxSocket->u.xTCP.usInitMSS != uxNewMSS )
{
- return pdFALSE;
- }
+ /* Perform a basic check on the the new MSS. */
+ if( uxNewMSS == 0U )
+ {
+ uxIndex = 0U;
- FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", ( *ppxSocket )->u.xTCP.usInitMSS, uxNewMSS ) );
- }
+ /* Return Condition found. */
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", pxSocket->u.xTCP.usInitMSS, uxNewMSS ) );
+ }
+ }
- if( ( *ppxSocket )->u.xTCP.usInitMSS > uxNewMSS )
- {
- /* our MSS was bigger than the MSS of the other party: adapt it. */
- ( *ppxSocket )->u.xTCP.bits.bMssChange = pdTRUE_UNSIGNED;
- if( ( ( *ppxTCPWindow ) != NULL ) && ( ( *ppxSocket )->u.xTCP.usCurMSS > uxNewMSS ) )
+ /* If a 'return' condition has not been found. */
+ if( xReturn == pdFALSE )
{
- /* The peer advertises a smaller MSS than this socket was
- using. Use that as well. */
- FreeRTOS_debug_printf( ( "Change mss %d => %lu\n", ( *ppxSocket )->u.xTCP.usCurMSS, uxNewMSS ) );
- ( *ppxSocket )->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;
+ if( pxSocket->u.xTCP.usInitMSS > uxNewMSS )
+ {
+ /* our MSS was bigger than the MSS of the other party: adapt it. */
+ pxSocket->u.xTCP.bits.bMssChange = pdTRUE_UNSIGNED;
+ if( pxSocket->u.xTCP.usCurMSS > uxNewMSS )
+ {
+ /* The peer advertises a smaller MSS than this socket was
+ using. Use that as well. */
+ FreeRTOS_debug_printf( ( "Change mss %d => %lu\n", pxSocket->u.xTCP.usCurMSS, uxNewMSS ) );
+ pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;
+ }
+ pxTCPWindow->xSize.ulRxWindowLength = ( ( uint32_t ) uxNewMSS ) * ( pxTCPWindow->xSize.ulRxWindowLength / ( ( uint32_t ) uxNewMSS ) );
+ pxTCPWindow->usMSSInit = ( uint16_t ) uxNewMSS;
+ pxTCPWindow->usMSS = ( uint16_t ) uxNewMSS;
+ pxSocket->u.xTCP.usInitMSS = ( uint16_t ) uxNewMSS;
+ pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;
+ }
+
+ uxIndex = tcpTCP_OPT_MSS_LEN;
}
- ( *ppxTCPWindow )->xSize.ulRxWindowLength = ( ( uint32_t ) uxNewMSS ) * ( ( *ppxTCPWindow )->xSize.ulRxWindowLength / ( ( uint32_t ) uxNewMSS ) );
- ( *ppxTCPWindow )->usMSSInit = ( uint16_t ) uxNewMSS;
- ( *ppxTCPWindow )->usMSS = ( uint16_t ) uxNewMSS;
- ( *ppxSocket )->u.xTCP.usInitMSS = ( uint16_t ) uxNewMSS;
- ( *ppxSocket )->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;
}
-
- #if( ipconfigUSE_TCP_WIN != 1 )
- /* Without scaled windows, MSS is the only interesting option. */
- return pdFALSE;
- #else
- /* Or else we continue to check another option: selective ACK. */
- ( *ppucPtr ) += TCP_OPT_MSS_LEN;
- #endif /* ipconfigUSE_TCP_WIN != 1 */
}
else
{
/* All other options have a length field, so that we easily
can skip past them. */
- ucLen = ( *ppucPtr )[ 1 ];
- if( ( ucLen < 2 ) || ( ucLen > xRemainingOptionsBytes ) )
+ ucLen = pucPtr[ 1 ];
+ if( ( ucLen < ( uint8_t ) 2U ) || ( uxRemainingOptionsBytes < ( size_t ) ucLen ) )
{
/* If the length field is too small or too big, the options are
* malformed, don't process them further.
*/
- return pdFALSE;
+ uxIndex = 0U;
}
-
- #if( ipconfigUSE_TCP_WIN == 1 )
+ else
{
- /* Selective ACK: the peer has received a packet but it is missing
- * earlier packets. At least this packet does not need retransmission
- * anymore. ulTCPWindowTxSack( ) takes care of this administration.
- */
- if( ( *ppucPtr )[0] == TCP_OPT_SACK_A )
+ uxIndex = 0U;
+
+ #if( ipconfigUSE_TCP_WIN == 1 )
{
- ucLen -= 2;
- ( *ppucPtr ) += 2;
-
- while( ucLen >= 8 )
+ /* Selective ACK: the peer has received a packet but it is missing
+ * earlier packets. At least this packet does not need retransmission
+ * anymore. ulTCPWindowTxSack( ) takes care of this administration.
+ */
+ if( pucPtr[ 0U ] == tcpTCP_OPT_SACK_A )
{
- prvSkipPastRemainingOptions( ppucPtr, ppxSocket, &ucLen );
+ ucLen -= 2U;
+ uxIndex += 2U;
+
+ while( ucLen >= ( uint8_t ) 8U )
+ {
+ prvReadSackOption( pucPtr, uxIndex, pxSocket );
+ uxIndex += 8U;
+ ucLen -= 8U;
+ }
+ /* ucLen should be 0 by now. */
}
- /* ucLen should be 0 by now. */
}
- }
- #endif /* ipconfigUSE_TCP_WIN == 1 */
+ #endif /* ipconfigUSE_TCP_WIN == 1 */
- ( *ppucPtr ) += ucLen;
+ uxIndex += ( size_t ) ucLen;
+ }
}
- return pdTRUE;
+ return uxIndex;
}
-
/*-----------------------------------------------------------*/
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen )
-{
-uint32_t ulFirst = ulChar2u32( ( *ppucPtr ) );
-uint32_t ulLast = ulChar2u32( ( *ppucPtr ) + 4 );
-uint32_t ulCount = ulTCPWindowTxSack( &( *ppxSocket )->u.xTCP.xTCPWindow, ulFirst, ulLast );
- /* ulTCPWindowTxSack( ) returns the number of bytes which have been acked
- * starting from the head position. Advance the tail pointer in txStream.
- */
- if( ( ( *ppxSocket )->u.xTCP.txStream != NULL ) && ( ulCount > 0 ) )
+#if( ipconfigUSE_TCP_WIN == 1 )
+ _static void prvReadSackOption( const uint8_t * const pucPtr,
+ size_t uxIndex,
+ FreeRTOS_Socket_t * const pxSocket )
{
- /* Just advancing the tail index, 'ulCount' bytes have been confirmed. */
- uxStreamBufferGet( ( *ppxSocket )->u.xTCP.txStream, 0, NULL, ( size_t ) ulCount, pdFALSE );
- ( *ppxSocket )->xEventBits |= eSOCKET_SEND;
+ uint32_t ulFirst = ulChar2u32( &( pucPtr[ uxIndex ] ) );
+ uint32_t ulLast = ulChar2u32( &( pucPtr[ uxIndex + 4U ] ) );
+ uint32_t ulCount = ulTCPWindowTxSack( &( pxSocket->u.xTCP.xTCPWindow ), ulFirst, ulLast );;
- #if ipconfigSUPPORT_SELECT_FUNCTION == 1
+ /* ulTCPWindowTxSack( ) returns the number of bytes which have been acked
+ * starting from the head position. Advance the tail pointer in txStream.
+ */
+ if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0U ) )
{
- if( ( *ppxSocket )->xSelectBits & eSELECT_WRITE )
+ /* Just advancing the tail index, 'ulCount' bytes have been confirmed. */
+ ( void ) uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0, NULL, ( size_t ) ulCount, pdFALSE );
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_SEND;
+
+ #if ipconfigSUPPORT_SELECT_FUNCTION == 1
{
- /* The field 'xEventBits' is used to store regular socket events
- * (at most 8), as well as 'select events', which will be left-shifted.
- */
- ( *ppxSocket )->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_WRITE ) != 0U )
+ {
+ /* The field 'xEventBits' is used to store regular socket events
+ * (at most 8), as well as 'select events', which will be left-shifted.
+ */
+ pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_WRITE ) << SOCKET_EVENT_BIT_COUNT;
+ }
}
- }
- #endif
+ #endif
- /* In case the socket owner has installed an OnSent handler, call it now.
- */
- #if( ipconfigUSE_CALLBACKS == 1 )
- {
- if( ipconfigIS_VALID_PROG_ADDRESS( ( *ppxSocket )->u.xTCP.pxHandleSent ) )
+ /* In case the socket owner has installed an OnSent handler,
+ call it now. */
+ #if( ipconfigUSE_CALLBACKS == 1 )
{
- ( *ppxSocket )->u.xTCP.pxHandleSent( (Socket_t )( *ppxSocket ), ulCount );
+ if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )
+ {
+ pxSocket->u.xTCP.pxHandleSent( pxSocket, ulCount );
+ }
}
+ #endif /* ipconfigUSE_CALLBACKS == 1 */
}
- #endif /* ipconfigUSE_CALLBACKS == 1 */
}
- ( *ppucPtr ) += 8;
- ( *pucLen ) -= 8;
-}
+#endif /* ( ipconfigUSE_TCP_WIN != 0 ) */
/*-----------------------------------------------------------*/
#if( ipconfigUSE_TCP_WIN != 0 )
- static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket )
+ static uint8_t prvWinScaleFactor( const FreeRTOS_Socket_t *pxSocket )
{
size_t uxWinSize;
uint8_t ucFactor;
/* 'xTCP.uxRxWinSize' is the size of the reception window in units of MSS. */
uxWinSize = pxSocket->u.xTCP.uxRxWinSize * ( size_t ) pxSocket->u.xTCP.usInitMSS;
- ucFactor = 0u;
- while( uxWinSize > 0xfffful )
+ ucFactor = 0U;
+ while( uxWinSize > 0xffffUL )
{
/* Divide by two and increase the binary factor by 1. */
uxWinSize >>= 1;
ucFactor++;
}
- FreeRTOS_debug_printf( ( "prvWinScaleFactor: uxRxWinSize %lu MSS %lu Factor %u\n",
- pxSocket->u.xTCP.uxRxWinSize,
- pxSocket->u.xTCP.usInitMSS,
+ FreeRTOS_debug_printf( ( "prvWinScaleFactor: uxRxWinSize %u MSS %u Factor %u\n",
+ ( unsigned ) pxSocket->u.xTCP.uxRxWinSize,
+ ( unsigned ) pxSocket->u.xTCP.usInitMSS,
ucFactor ) );
return ucFactor;
@@ -1395,50 +1436,45 @@ uint32_t ulCount = ulTCPWindowTxSack( &( *ppxSocket )->u.xTCP.xTCPWindow, ulFirs
* communicate what MSS (Maximum Segment Size) they intend to use. MSS is the
* nett size of the payload, always smaller than MTU.
*/
-static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPPacket_t * pxTCPPacket )
+static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPHeader_t * pxTCPHeader )
{
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
uint16_t usMSS = pxSocket->u.xTCP.usInitMSS;
UBaseType_t uxOptionsLength;
/* We send out the TCP Maximum Segment Size option with our SYN[+ACK]. */
- pxTCPHeader->ucOptdata[ 0 ] = ( uint8_t ) TCP_OPT_MSS;
- pxTCPHeader->ucOptdata[ 1 ] = ( uint8_t ) TCP_OPT_MSS_LEN;
+ pxTCPHeader->ucOptdata[ 0 ] = ( uint8_t ) tcpTCP_OPT_MSS;
+ pxTCPHeader->ucOptdata[ 1 ] = ( uint8_t ) tcpTCP_OPT_MSS_LEN;
pxTCPHeader->ucOptdata[ 2 ] = ( uint8_t ) ( usMSS >> 8 );
- pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( usMSS & 0xffu );
+ pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( usMSS & 0xffU );
#if( ipconfigUSE_TCP_WIN != 0 )
{
pxSocket->u.xTCP.ucMyWinScaleFactor = prvWinScaleFactor( pxSocket );
- pxTCPHeader->ucOptdata[ 4 ] = TCP_OPT_NOOP;
- pxTCPHeader->ucOptdata[ 5 ] = ( uint8_t ) ( TCP_OPT_WSOPT );
- pxTCPHeader->ucOptdata[ 6 ] = ( uint8_t ) ( TCP_OPT_WSOPT_LEN );
+ pxTCPHeader->ucOptdata[ 4 ] = tcpTCP_OPT_NOOP;
+ pxTCPHeader->ucOptdata[ 5 ] = ( uint8_t ) ( tcpTCP_OPT_WSOPT );
+ pxTCPHeader->ucOptdata[ 6 ] = ( uint8_t ) ( tcpTCP_OPT_WSOPT_LEN );
pxTCPHeader->ucOptdata[ 7 ] = ( uint8_t ) pxSocket->u.xTCP.ucMyWinScaleFactor;
- uxOptionsLength = 8u;
+ uxOptionsLength = 8U;
}
#else
{
- uxOptionsLength = 4u;
+ uxOptionsLength = 4U;
}
#endif
- #if( ipconfigUSE_TCP_WIN == 0 )
- {
- return uxOptionsLength;
- }
- #else
+ #if( ipconfigUSE_TCP_WIN != 0 )
{
- pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;
- pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;
- pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */
- pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2; /* 2: length of this option. */
- uxOptionsLength += 4u;
+ pxTCPHeader->ucOptdata[ uxOptionsLength ] = tcpTCP_OPT_NOOP;
+ pxTCPHeader->ucOptdata[ uxOptionsLength + 1U ] = tcpTCP_OPT_NOOP;
+ pxTCPHeader->ucOptdata[ uxOptionsLength + 2U ] = tcpTCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */
+ pxTCPHeader->ucOptdata[ uxOptionsLength + 3U ] = 2U; /* 2: length of this option. */
+ uxOptionsLength += 4U;
- return uxOptionsLength; /* bytes, not words. */
}
#endif /* ipconfigUSE_TCP_WIN == 0 */
+ return uxOptionsLength; /* bytes, not words. */
}
/*
@@ -1458,7 +1494,7 @@ static void prvTCPTouchSocket( FreeRTOS_Socket_t *pxSocket )
{
pxSocket->u.xTCP.bits.bWaitKeepAlive = pdFALSE_UNSIGNED;
pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED;
- pxSocket->u.xTCP.ucKeepRepCount = 0u;
+ pxSocket->u.xTCP.ucKeepRepCount = 0U;
pxSocket->u.xTCP.xLastAliveTime = xTaskGetTickCount();
}
#endif
@@ -1476,8 +1512,8 @@ static void prvTCPTouchSocket( FreeRTOS_Socket_t *pxSocket )
void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState )
{
FreeRTOS_Socket_t *xParent = NULL;
-BaseType_t bBefore = ( BaseType_t ) NOW_CONNECTED( pxSocket->u.xTCP.ucTCPState ); /* Was it connected ? */
-BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it connected now ? */
+BaseType_t bBefore = ipNUMERIC_CAST( BaseType_t, tcpNOW_CONNECTED( ( BaseType_t ) pxSocket->u.xTCP.ucTCPState ) ); /* Was it connected ? */
+BaseType_t bAfter = ipNUMERIC_CAST( BaseType_t, tcpNOW_CONNECTED( ( BaseType_t ) eTCPState ) ); /* Is it connected now ? */
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
BaseType_t xPreviousState = ( BaseType_t ) pxSocket->u.xTCP.ucTCPState;
#endif
@@ -1511,22 +1547,22 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
xParent->u.xTCP.pxPeerSocket = pxSocket;
}
- xParent->xEventBits |= eSOCKET_ACCEPT;
+ xParent->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
/* Library support FreeRTOS_select(). Receiving a new
connection is being translated as a READ event. */
- if( ( xParent->xSelectBits & eSELECT_READ ) != 0 )
+ if( ( xParent->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U )
{
- xParent->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );
+ xParent->xEventBits |= ( ( EventBits_t ) eSELECT_READ ) << SOCKET_EVENT_BIT_COUNT;
}
}
#endif
#if( ipconfigUSE_CALLBACKS == 1 )
{
- if( ( ipconfigIS_VALID_PROG_ADDRESS( xParent->u.xTCP.pxHandleConnected ) != pdFALSE ) &&
+ if( ( ipconfigIS_VALID_PROG_ADDRESS( xParent->u.xTCP.pxHandleConnected ) ) &&
( xParent->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) )
{
/* The listening socket does not become connected itself, in stead
@@ -1548,13 +1584,13 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
}
else
{
- pxSocket->xEventBits |= eSOCKET_CONNECT;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_CONNECT;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
- if( pxSocket->xSelectBits & eSELECT_WRITE )
+ if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_WRITE ) ) != 0U )
{
- pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );
+ pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_WRITE ) << SOCKET_EVENT_BIT_COUNT;
}
}
#endif
@@ -1563,20 +1599,20 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
else /* bAfter == pdFALSE, connection is closed. */
{
/* Notify/wake-up the socket-owner by setting a semaphore. */
- pxSocket->xEventBits |= eSOCKET_CLOSED;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_CLOSED;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
- if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )
+ if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_EXCEPT ) != 0U )
{
- pxSocket->xEventBits |= ( eSELECT_EXCEPT << SOCKET_EVENT_BIT_COUNT );
+ pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_EXCEPT ) << SOCKET_EVENT_BIT_COUNT;
}
}
#endif
}
#if( ipconfigUSE_CALLBACKS == 1 )
{
- if( ( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleConnected ) != pdFALSE ) && ( xConnected == NULL ) )
+ if( ( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleConnected ) ) && ( xConnected == NULL ) )
{
/* The 'connected' state has changed, call the user handler. */
xConnected = pxSocket;
@@ -1584,18 +1620,18 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
}
#endif /* ipconfigUSE_CALLBACKS */
- if( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE )
+ if( prvTCPSocketIsActive( ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState ) ) == 0 )
{
/* Now the socket isn't in an active state anymore so it
won't need further attention of the IP-task.
Setting time-out to zero means that the socket won't get checked during
timer events. */
- pxSocket->u.xTCP.usTimeout = 0u;
+ pxSocket->u.xTCP.usTimeout = 0U;
}
}
else
{
- if( eTCPState == eCLOSED )
+ if( ( ( BaseType_t ) eTCPState ) == ( ( BaseType_t ) eCLOSED ) )
{
/* Socket goes to status eCLOSED because of a RST.
When nobody owns the socket yet, delete it. */
@@ -1605,7 +1641,7 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
FreeRTOS_debug_printf( ( "vTCPStateChange: Closing socket\n" ) );
if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
{
- FreeRTOS_closesocket( pxSocket );
+ ( void ) FreeRTOS_closesocket( pxSocket );
}
}
}
@@ -1614,18 +1650,20 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
/* Fill in the new state. */
pxSocket->u.xTCP.ucTCPState = ( uint8_t ) eTCPState;
- /* touch the alive timers because moving to another state. */
+ /* Touch the alive timers because moving to another state. */
prvTCPTouchSocket( pxSocket );
#if( ipconfigHAS_DEBUG_PRINTF == 1 )
{
- if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )
- FreeRTOS_debug_printf( ( "Socket %d -> %lxip:%u State %s->%s\n",
- pxSocket->usLocalPort,
- pxSocket->u.xTCP.ulRemoteIP,
- pxSocket->u.xTCP.usRemotePort,
- FreeRTOS_GetTCPStateName( ( UBaseType_t ) xPreviousState ),
- FreeRTOS_GetTCPStateName( ( UBaseType_t ) eTCPState ) ) );
+ if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) )
+ {
+ FreeRTOS_debug_printf( ( "Socket %d -> %lxip:%u State %s->%s\n",
+ pxSocket->usLocalPort,
+ pxSocket->u.xTCP.ulRemoteIP,
+ pxSocket->u.xTCP.usRemotePort,
+ FreeRTOS_GetTCPStateName( ( UBaseType_t ) xPreviousState ),
+ FreeRTOS_GetTCPStateName( ( UBaseType_t ) eTCPState ) ) );
+ }
}
#endif /* ipconfigHAS_DEBUG_PRINTF */
@@ -1645,31 +1683,50 @@ BaseType_t bAfter = ( BaseType_t ) NOW_CONNECTED( eTCPState ); /* Is it co
}
/*-----------------------------------------------------------*/
-static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
+static NetworkBufferDescriptor_t *prvTCPBufferResize( const FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,
int32_t lDataLen, UBaseType_t uxOptionsLength )
{
NetworkBufferDescriptor_t *pxReturn;
-int32_t lNeeded;
+size_t uxNeeded;
BaseType_t xResize;
if( xBufferAllocFixedSize != pdFALSE )
{
/* Network buffers are created with a fixed size and can hold the largest
MTU. */
- lNeeded = ( int32_t ) ipTOTAL_ETHERNET_FRAME_SIZE;
+ uxNeeded = ( size_t ) ipTOTAL_ETHERNET_FRAME_SIZE;
/* and therefore, the buffer won't be too small.
Only ask for a new network buffer in case none was supplied. */
- xResize = ( pxNetworkBuffer == NULL );
+ if( pxNetworkBuffer == NULL )
+ {
+ xResize = pdTRUE;
+ }
+ else
+ {
+ xResize = pdFALSE;
+ }
}
else
{
/* Network buffers are created with a variable size. See if it must
grow. */
- lNeeded = FreeRTOS_max_int32( ( int32_t ) sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ),
- ( int32_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + lDataLen );
+ uxNeeded = ipNUMERIC_CAST( size_t, ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + lDataLen;
+
+ if( uxNeeded < sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) )
+ {
+ uxNeeded = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
+ }
+
/* In case we were called from a TCP timer event, a buffer must be
created. Otherwise, test 'xDataLength' of the provided buffer. */
- xResize = ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded );
+ if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < uxNeeded ) )
+ {
+ xResize = pdTRUE;
+ }
+ else
+ {
+ xResize = pdFALSE;
+ }
}
if( xResize != pdFALSE )
@@ -1677,18 +1734,18 @@ BaseType_t xResize;
/* The caller didn't provide a network buffer or the provided buffer is
too small. As we must send-out a data packet, a buffer will be created
here. */
- pxReturn = pxGetNetworkBufferWithDescriptor( ( uint32_t ) lNeeded, 0u );
+ pxReturn = pxGetNetworkBufferWithDescriptor( uxNeeded, 0U );
if( pxReturn != NULL )
{
/* Set the actual packet size, in case the returned buffer is larger. */
- pxReturn->xDataLength = lNeeded;
+ pxReturn->xDataLength = uxNeeded;
/* Copy the existing data to the new created buffer. */
- if( pxNetworkBuffer )
+ if( pxNetworkBuffer != NULL )
{
/* Either from the previous buffer... */
- memcpy( pxReturn->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
+ ( void ) memcpy( pxReturn->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
/* ...and release it. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
@@ -1696,18 +1753,19 @@ BaseType_t xResize;
else
{
/* Or from the socket field 'xTCP.xPacket'. */
- memcpy( pxReturn->pucEthernetBuffer, pxSocket->u.xTCP.xPacket.u.ucLastPacket, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
+ ( void ) memcpy( pxReturn->pucEthernetBuffer, pxSocket->u.xTCP.xPacket.u.ucLastPacket, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
}
}
}
else
{
/* xResize is false, the network buffer provided was big enough. */
+ configASSERT( pxNetworkBuffer != NULL ); /* to tell lint: when xResize is false, pxNetworkBuffer is not NULL. */
pxReturn = pxNetworkBuffer;
/* Thanks to Andrey Ivanov from swissEmbedded for reporting that the
xDataLength member must get the correct length too! */
- pxNetworkBuffer->xDataLength = ( size_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + ( size_t ) lDataLen;
+ pxNetworkBuffer->xDataLength = ( size_t ) ( ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + ( size_t ) lDataLen;
}
return pxReturn;
@@ -1721,7 +1779,7 @@ static int32_t prvTCPPrepareSend( FreeRTOS_Socket_t *pxSocket, NetworkBufferDesc
{
int32_t lDataLen;
uint8_t *pucEthernetBuffer, *pucSendData;
-TCPPacket_t *pxTCPPacket;
+ProtocolHeaders_t *pxProtocolHeaders;
size_t uxOffset;
uint32_t ulDataGot, ulDistance;
TCPWindow_t *pxTCPWindow;
@@ -1739,11 +1797,12 @@ int32_t lStreamPos;
pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;
}
- pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );
- pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
+ /* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *, &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
+ pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
lDataLen = 0;
lStreamPos = 0;
- pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_ACK;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags |= tcpTCP_FLAG_ACK;
if( pxSocket->u.xTCP.txStream != NULL )
{
@@ -1751,7 +1810,7 @@ int32_t lStreamPos;
along with the position in the txStream.
Why check for MSS > 1 ?
Because some TCP-stacks (like uIP) use it for flow-control. */
- if( pxSocket->u.xTCP.usCurMSS > 1u )
+ if( pxSocket->u.xTCP.usCurMSS > 1U )
{
lDataLen = ( int32_t ) ulTCPWindowTxGet( pxTCPWindow, pxSocket->u.xTCP.ulWindowSize, &lStreamPos );
}
@@ -1766,9 +1825,12 @@ int32_t lStreamPos;
{
*ppxNetworkBuffer = pxNewBuffer;
pucEthernetBuffer = pxNewBuffer->pucEthernetBuffer;
- pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );
- pucSendData = pucEthernetBuffer + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength;
+ /* Map the byte stream onto ProtocolHeaders_t struct for easy
+ * access to the fields. */
+ pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *, &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
+
+ pucSendData = &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength ] );
/* Translate the position in txStream to an offset from the tail
marker. */
@@ -1782,8 +1844,8 @@ int32_t lStreamPos;
{
if( ulDataGot != ( uint32_t ) lDataLen )
{
- FreeRTOS_debug_printf( ( "uxStreamBufferGet: pos %lu offs %lu only %lu != %lu\n",
- lStreamPos, uxOffset, ulDataGot, lDataLen ) );
+ FreeRTOS_debug_printf( ( "uxStreamBufferGet: pos %d offs %u only %u != %d\n",
+ ( int ) lStreamPos, ( unsigned ) uxOffset, ( unsigned ) ulDataGot, ( int ) lDataLen ) );
}
}
#endif
@@ -1804,14 +1866,15 @@ int32_t lStreamPos;
size_t uxMid = pxSocket->u.xTCP.txStream->uxMid;
size_t uxTail = pxSocket->u.xTCP.txStream->uxTail;
- FreeRTOS_debug_printf( ( "CheckClose %lu <= %lu (%lu <= %lu <= %lu)\n", ulDataGot, ulDistance,
- uxTail, uxMid, uxHead ) );
+ FreeRTOS_debug_printf( ( "CheckClose %u <= %u (%u <= %u <= %u)\n",
+ ( unsigned ) ulDataGot, ( unsigned ) ulDistance,
+ ( unsigned ) uxTail, ( unsigned ) uxMid, ( unsigned ) uxHead ) );
}
#endif
/* Although the socket sends a FIN, it will stay in
ESTABLISHED until all current data has been received or
delivered. */
- pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_FIN;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags |= tcpTCP_FLAG_FIN;
pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->ulOurSequenceNumber + ( uint32_t ) lDataLen;
pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;
}
@@ -1824,14 +1887,14 @@ int32_t lStreamPos;
}
}
- if( ( lDataLen >= 0 ) && ( pxSocket->u.xTCP.ucTCPState == eESTABLISHED ) )
+ if( ( lDataLen >= 0 ) && ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eESTABLISHED ) )
{
/* See if the socket owner wants to shutdown this connection. */
if( ( pxSocket->u.xTCP.bits.bUserShutdown != pdFALSE_UNSIGNED ) &&
( xTCPWindowTxDone( pxTCPWindow ) != pdFALSE ) )
{
pxSocket->u.xTCP.bits.bUserShutdown = pdFALSE_UNSIGNED;
- pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_FIN;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags |= tcpTCP_FLAG_FIN;
pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;
pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
@@ -1840,7 +1903,7 @@ int32_t lStreamPos;
#if( ipconfigTCP_KEEP_ALIVE != 0 )
{
- if( pxSocket->u.xTCP.ucKeepRepCount > 3u )
+ if( pxSocket->u.xTCP.ucKeepRepCount > 3U ) /*_RB_ Magic number. */
{
FreeRTOS_debug_printf( ( "keep-alive: giving up %lxip:%u\n",
pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine. */
@@ -1854,21 +1917,23 @@ int32_t lStreamPos;
we might want to send a keep-alive message. */
TickType_t xAge = xTaskGetTickCount( ) - pxSocket->u.xTCP.xLastAliveTime;
TickType_t xMax;
- xMax = ( ( TickType_t ) ipconfigTCP_KEEP_ALIVE_INTERVAL * configTICK_RATE_HZ );
- if( pxSocket->u.xTCP.ucKeepRepCount )
+ xMax = ( ( TickType_t ) ipconfigTCP_KEEP_ALIVE_INTERVAL * ( TickType_t ) configTICK_RATE_HZ );
+ if( pxSocket->u.xTCP.ucKeepRepCount != ( uint8_t ) 0U )
{
- xMax = ( 3u * configTICK_RATE_HZ );
+ xMax = ( TickType_t ) ( 3U * configTICK_RATE_HZ );
}
if( xAge > xMax )
{
pxSocket->u.xTCP.xLastAliveTime = xTaskGetTickCount( );
- if( xTCPWindowLoggingLevel )
+ if( xTCPWindowLoggingLevel != 0 )
+ {
FreeRTOS_debug_printf( ( "keep-alive: %lxip:%u count %u\n",
pxSocket->u.xTCP.ulRemoteIP,
pxSocket->u.xTCP.usRemotePort,
pxSocket->u.xTCP.ucKeepRepCount ) );
+ }
pxSocket->u.xTCP.bits.bSendKeepAlive = pdTRUE_UNSIGNED;
- pxSocket->u.xTCP.usTimeout = ( ( uint16_t ) pdMS_TO_TICKS( 2500 ) );
+ pxSocket->u.xTCP.usTimeout = ( ( uint16_t ) pdMS_TO_TICKS( 2500U ) );
pxSocket->u.xTCP.ucKeepRepCount++;
}
}
@@ -1882,17 +1947,17 @@ int32_t lStreamPos;
( pxSocket->u.xTCP.bits.bWinChange != pdFALSE_UNSIGNED ) ||
( pxSocket->u.xTCP.bits.bSendKeepAlive != pdFALSE_UNSIGNED ) )
{
- pxTCPPacket->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~ipTCP_FLAG_PSH );
- pxTCPPacket->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~tcpTCP_FLAG_PSH );
+ pxProtocolHeaders->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 ); /*_RB_ "2" needs comment. */
- pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_ACK;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags |= ( uint8_t ) tcpTCP_FLAG_ACK;
- if( lDataLen != 0l )
+ if( lDataLen != 0L )
{
- pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_PSH;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags |= ( uint8_t ) tcpTCP_FLAG_PSH;
}
- lDataLen += ( int32_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ lDataLen += ipNUMERIC_CAST( int32_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
}
return lDataLen;
@@ -1906,16 +1971,16 @@ static TickType_t prvTCPNextTimeout ( FreeRTOS_Socket_t *pxSocket )
{
TickType_t ulDelayMs = ( TickType_t ) tcpMAXIMUM_TCP_WAKEUP_TIME_MS;
- if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN )
{
/* The socket is actively connecting to a peer. */
- if( pxSocket->u.xTCP.bits.bConnPrepared )
+ if( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED )
{
/* Ethernet address has been found, use progressive timeout for
active connect(). */
- if( pxSocket->u.xTCP.ucRepCount < 3u )
+ if( pxSocket->u.xTCP.ucRepCount < 3U )
{
- ulDelayMs = ( 3000UL << ( pxSocket->u.xTCP.ucRepCount - 1u ) );
+ ulDelayMs = ( 3000UL << ( pxSocket->u.xTCP.ucRepCount - 1U ) );
}
else
{
@@ -1931,13 +1996,13 @@ TickType_t ulDelayMs = ( TickType_t ) tcpMAXIMUM_TCP_WAKEUP_TIME_MS;
FreeRTOS_debug_printf( ( "Connect[%lxip:%u]: next timeout %u: %lu ms\n",
pxSocket->u.xTCP.ulRemoteIP, pxSocket->u.xTCP.usRemotePort,
pxSocket->u.xTCP.ucRepCount, ulDelayMs ) );
- pxSocket->u.xTCP.usTimeout = ( uint16_t )pdMS_TO_MIN_TICKS( ulDelayMs );
+ pxSocket->u.xTCP.usTimeout = ( uint16_t )ipMS_TO_MIN_TICKS( ulDelayMs );
}
- else if( pxSocket->u.xTCP.usTimeout == 0u )
+ else if( pxSocket->u.xTCP.usTimeout == 0U )
{
/* Let the sliding window mechanism decide what time-out is appropriate. */
BaseType_t xResult = xTCPWindowTxHasData( &pxSocket->u.xTCP.xTCPWindow, pxSocket->u.xTCP.ulWindowSize, &ulDelayMs );
- if( ulDelayMs == 0u )
+ if( ulDelayMs == 0U )
{
if( xResult != ( BaseType_t )0 )
{
@@ -1952,7 +2017,7 @@ TickType_t ulDelayMs = ( TickType_t ) tcpMAXIMUM_TCP_WAKEUP_TIME_MS;
{
/* ulDelayMs contains the time to wait before a re-transmission. */
}
- pxSocket->u.xTCP.usTimeout = ( uint16_t )pdMS_TO_MIN_TICKS( ulDelayMs );
+ pxSocket->u.xTCP.usTimeout = ( uint16_t ) ipMS_TO_MIN_TICKS( ulDelayMs );
}
else
{
@@ -1972,9 +2037,9 @@ int32_t lCount, lLength;
/* A txStream has been created already, see if the socket has new data for
the sliding window.
- uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It contains new
- Tx data which has not been passed to the sliding window yet. The oldest
- data not-yet-confirmed can be found at rxTail. */
+ uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It
+ contains new Tx data which has not been passed to the sliding window yet.
+ The oldest data not-yet-confirmed can be found at rxTail. */
lLength = ( int32_t ) uxStreamBufferMidSpace( pxSocket->u.xTCP.txStream );
if( lLength > 0 )
@@ -2006,18 +2071,20 @@ int32_t lCount, lLength;
* Before being called, it has been checked that both reception and transmission
* are complete.
*/
-static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
+static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
+/* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
+TCPHeader_t *pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
BaseType_t xSendLength = 0;
uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
- if( ( ucTCPFlags & ipTCP_FLAG_FIN ) != 0u )
+ if( ( ucTCPFlags & tcpTCP_FLAG_FIN ) != 0U )
{
- pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulFINSequenceNumber + 1u;
+ pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulFINSequenceNumber + 1U;
}
if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )
{
@@ -2028,7 +2095,7 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
else
{
/* We did send a FIN already, see if it's ACK'd. */
- if( ulAckNr == pxTCPWindow->tx.ulFINSequenceNumber + 1u )
+ if( ulAckNr == ( pxTCPWindow->tx.ulFINSequenceNumber + 1UL ) )
{
pxSocket->u.xTCP.bits.bFinAcked = pdTRUE_UNSIGNED;
}
@@ -2037,7 +2104,7 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
if( pxSocket->u.xTCP.bits.bFinAcked == pdFALSE_UNSIGNED )
{
pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber;
- pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK | ipTCP_FLAG_FIN;
+ pxTCPHeader->ucTCPFlags = ( uint8_t ) tcpTCP_FLAG_ACK | ( uint8_t ) tcpTCP_FLAG_FIN;
/* And wait for the final ACK. */
vTCPStateChange( pxSocket, eLAST_ACK );
@@ -2045,12 +2112,12 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
else
{
/* Our FIN has been ACK'd, the outgoing sequence number is now fixed. */
- pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber + 1u;
+ pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber + 1U;
if( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED )
{
/* We have sent out a FIN but the peer hasn't replied with a FIN
yet. Do nothing for the moment. */
- pxTCPHeader->ucTCPFlags = 0u;
+ pxTCPHeader->ucTCPFlags = 0U;
}
else
{
@@ -2058,13 +2125,13 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
{
/* This is the third of the three-way hand shake: the last
ACK. */
- pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;
+ pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
}
else
{
/* The other party started the closure, so we just wait for the
last ACK. */
- pxTCPHeader->ucTCPFlags = 0u;
+ pxTCPHeader->ucTCPFlags = 0U;
}
/* And wait for the user to close this socket. */
@@ -2074,9 +2141,9 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
- if( pxTCPHeader->ucTCPFlags != 0u )
+ if( pxTCPHeader->ucTCPFlags != 0U )
{
- xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength );
+ xSendLength = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength );
}
pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength ) << 2 );
@@ -2101,28 +2168,37 @@ uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
* The first thing that will be done is find the TCP payload data
* and check the length of this data.
*/
-static BaseType_t prvCheckRxData( NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData )
+static BaseType_t prvCheckRxData( const NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &( pxTCPPacket->xTCPHeader );
+/* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ( size_t ) ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
+const TCPHeader_t *pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;
+/* Map the buffer onto an IPHeader_t struct for easy access to fields. */
+const IPHeader_t *pxIPHeader = ipPOINTER_CAST( const IPHeader_t *, &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) );
+const size_t xIPHeaderLength = ipSIZE_OF_IPv4_HEADER;
+uint16_t usLength;
+
/* Determine the length and the offset of the user-data sent to this
node.
The size of the TCP header is given in a multiple of 4-byte words (single
byte, needs no ntoh() translation). A shift-right 2: is the same as
(offset >> 4) * 4. */
- lTCPHeaderLength = ( BaseType_t ) ( ( pxTCPHeader->ucTCPOffset & VALID_BITS_IN_TCP_OFFSET_BYTE ) >> 2 );
+ lTCPHeaderLength = ipNUMERIC_CAST( BaseType_t, ( pxTCPHeader->ucTCPOffset & tcpVALID_BITS_IN_TCP_OFFSET_BYTE ) >> 2 );
/* Let pucRecvData point to the first byte received. */
- *ppucRecvData = pxNetworkBuffer->pucEthernetBuffer + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + lTCPHeaderLength;
+ *ppucRecvData = &( pxNetworkBuffer->pucEthernetBuffer[ ( size_t ) ipSIZE_OF_ETH_HEADER + xIPHeaderLength + ( size_t ) lTCPHeaderLength ] );
/* Calculate lReceiveLength - the length of the TCP data received. This is
equal to the total packet length minus:
( LinkLayer length (14) + IP header length (20) + size of TCP header(20 +) ).*/
- lReceiveLength = ( ( int32_t ) pxNetworkBuffer->xDataLength ) - ( int32_t ) ipSIZE_OF_ETH_HEADER;
- lLength = ( int32_t )FreeRTOS_htons( pxTCPPacket->xIPHeader.usLength );
+ lReceiveLength = ipNUMERIC_CAST( int32_t, pxNetworkBuffer->xDataLength ) - ( int32_t ) ipSIZE_OF_ETH_HEADER;
+
+ usLength = FreeRTOS_htons( pxIPHeader->usLength );
+ lLength = ( int32_t ) usLength;
if( lReceiveLength > lLength )
{
@@ -2133,9 +2209,9 @@ int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;
/* Subtract the size of the TCP and IP headers and the actual data size is
known. */
- if( lReceiveLength > ( lTCPHeaderLength + ( int32_t ) ipSIZE_OF_IPv4_HEADER ) )
+ if( lReceiveLength > ( lTCPHeaderLength + ( int32_t ) xIPHeaderLength ) )
{
- lReceiveLength -= ( lTCPHeaderLength + ( int32_t ) ipSIZE_OF_IPv4_HEADER );
+ lReceiveLength -= ( lTCPHeaderLength + ( int32_t ) xIPHeaderLength );
}
else
{
@@ -2148,7 +2224,7 @@ int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;
pointer points to the sequence number of the octet following the urgent
data. This field is only be interpreted in segments with the URG control
bit set. */
- if( ( pxTCPHeader->ucTCPFlags & ipTCP_FLAG_URG ) != 0u )
+ if( ( pxTCPHeader->ucTCPFlags & tcpTCP_FLAG_URG ) != 0U )
{
/* Although we ignore the urgent data, we have to skip it. */
lUrgentLength = ( int32_t ) FreeRTOS_htons( pxTCPHeader->usUrgent );
@@ -2166,11 +2242,13 @@ int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;
* The second thing is to do is check if the payload data may be accepted
* If so, they will be added to the reception queue.
*/
-static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, uint8_t *pucRecvData,
+static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, const uint8_t *pucRecvData,
NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulReceiveLength )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
+/* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( const ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
+const TCPHeader_t *pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
uint32_t ulSequenceNumber, ulSpace;
int32_t lOffset, lStored;
@@ -2178,16 +2256,16 @@ BaseType_t xResult = 0;
ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );
- if( ( ulReceiveLength > 0u ) && ( pxSocket->u.xTCP.ucTCPState >= eSYN_RECEIVED ) )
+ if( ( ulReceiveLength > 0U ) && ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eSYN_RECEIVED ) )
{
/* See if way may accept the data contents and forward it to the socket
owner.
If it can't be "accept"ed it may have to be stored and send a selective
- ack (SACK) option to confirm it. In that case, xTCPWindowRxStore() will be
+ ack (SACK) option to confirm it. In that case, lTCPAddRxdata() will be
called later to store an out-of-order packet (in case lOffset is
negative). */
- if ( pxSocket->u.xTCP.rxStream )
+ if ( pxSocket->u.xTCP.rxStream != NULL )
{
ulSpace = ( uint32_t )uxStreamBufferGetSpace ( pxSocket->u.xTCP.rxStream );
}
@@ -2208,12 +2286,12 @@ BaseType_t xResult = 0;
if( lStored != ( int32_t ) ulReceiveLength )
{
- FreeRTOS_debug_printf( ( "lTCPAddRxdata: stored %ld / %lu bytes??\n", lStored, ulReceiveLength ) );
+ FreeRTOS_debug_printf( ( "lTCPAddRxdata: stored %ld / %lu bytes? ?\n", lStored, ulReceiveLength ) );
/* Received data could not be stored. The socket's flag
bMallocError has been set. The socket now has the status
eCLOSE_WAIT and a RST packet will be sent back. */
- prvTCPSendReset( pxNetworkBuffer );
+ ( void ) prvTCPSendReset( pxNetworkBuffer );
xResult = -1;
}
}
@@ -2225,9 +2303,9 @@ BaseType_t xResult = 0;
/* Now lTCPAddRxdata() will move the rxHead pointer forward
so data becomes available to the user immediately
In case the low-water mark is reached, bLowWater will be set. */
- if( ( xResult == 0 ) && ( pxTCPWindow->ulUserDataLength > 0 ) )
+ if( ( xResult == 0 ) && ( pxTCPWindow->ulUserDataLength > 0UL ) )
{
- lTCPAddRxdata( pxSocket, 0ul, NULL, pxTCPWindow->ulUserDataLength );
+ ( void ) lTCPAddRxdata( pxSocket, 0UL, NULL, pxTCPWindow->ulUserDataLength );
pxTCPWindow->ulUserDataLength = 0;
}
}
@@ -2235,7 +2313,7 @@ BaseType_t xResult = 0;
}
else
{
- pxTCPWindow->ucOptionLength = 0u;
+ pxTCPWindow->ucOptionLength = 0U;
}
return xResult;
@@ -2243,34 +2321,38 @@ BaseType_t xResult = 0;
/*-----------------------------------------------------------*/
/* Set the TCP options (if any) for the outgoing packet. */
-static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
+static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
-TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
+/* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
+TCPHeader_t *pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
+const TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;
- #if( ipconfigUSE_TCP_WIN == 1 )
- if( uxOptionsLength != 0u )
+#if( ipconfigUSE_TCP_WIN == 1 )
+ if( uxOptionsLength != 0U )
+ {
+ /* TCP options must be sent because a packet which is out-of-order
+ was received. */
+ if( xTCPWindowLoggingLevel >= 0 )
{
- /* TCP options must be sent because a packet which is out-of-order
- was received. */
- if( xTCPWindowLoggingLevel >= 0 )
- FreeRTOS_debug_printf( ( "SACK[%d,%d]: optlen %lu sending %lu - %lu\n",
- pxSocket->usLocalPort,
- pxSocket->u.xTCP.usRemotePort,
- uxOptionsLength,
- FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 1 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber,
- FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 2 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber ) );
- memcpy( pxTCPHeader->ucOptdata, pxTCPWindow->ulOptionsData, ( size_t ) uxOptionsLength );
-
- /* The header length divided by 4, goes into the higher nibble,
- effectively a shift-left 2. */
- pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
+ FreeRTOS_debug_printf( ( "SACK[%d,%d]: optlen %lu sending %lu - %lu\n",
+ pxSocket->usLocalPort,
+ pxSocket->u.xTCP.usRemotePort,
+ uxOptionsLength,
+ FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 1 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber,
+ FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 2 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber ) );
}
- else
- #endif /* ipconfigUSE_TCP_WIN */
- if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.bits.bMssChange != pdFALSE_UNSIGNED ) )
+ ( void ) memcpy( pxTCPHeader->ucOptdata, pxTCPWindow->ulOptionsData, ( size_t ) uxOptionsLength );
+
+ /* The header length divided by 4, goes into the higher nibble,
+ effectively a shift-left 2. */
+ pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
+ }
+ else
+#endif /* ipconfigUSE_TCP_WIN */
+ if( ( pxSocket->u.xTCP.ucTCPState >= ( EventBits_t ) eESTABLISHED ) && ( pxSocket->u.xTCP.bits.bMssChange != pdFALSE_UNSIGNED ) )
{
/* TCP options must be sent because the MSS has changed. */
pxSocket->u.xTCP.bits.bMssChange = pdFALSE_UNSIGNED;
@@ -2279,13 +2361,17 @@ UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;
FreeRTOS_debug_printf( ( "MSS: sending %d\n", pxSocket->u.xTCP.usCurMSS ) );
}
- pxTCPHeader->ucOptdata[ 0 ] = TCP_OPT_MSS;
- pxTCPHeader->ucOptdata[ 1 ] = TCP_OPT_MSS_LEN;
+ pxTCPHeader->ucOptdata[ 0 ] = tcpTCP_OPT_MSS;
+ pxTCPHeader->ucOptdata[ 1 ] = tcpTCP_OPT_MSS_LEN;
pxTCPHeader->ucOptdata[ 2 ] = ( uint8_t ) ( ( pxSocket->u.xTCP.usCurMSS ) >> 8 );
- pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( ( pxSocket->u.xTCP.usCurMSS ) & 0xffu );
- uxOptionsLength = 4u;
+ pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( ( pxSocket->u.xTCP.usCurMSS ) & 0xffU );
+ uxOptionsLength = 4U;
pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
}
+ else
+ {
+ /* Nothing. */
+ }
return uxOptionsLength;
}
@@ -2297,33 +2383,42 @@ UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;
* Called from the states: eSYN_RECEIVED and eCONNECT_SYN
* If the flags received are correct, the socket will move to eESTABLISHED.
*/
-static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,
+static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer,
uint32_t ulReceiveLength, UBaseType_t uxOptionsLength )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
+/* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
+TCPHeader_t *pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );
BaseType_t xSendLength = 0;
/* Either expect a ACK or a SYN+ACK. */
- uint16_t usExpect = ( uint16_t ) ipTCP_FLAG_ACK;
- if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )
+ uint8_t ucExpect = tcpTCP_FLAG_ACK;
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN )
{
- usExpect |= ( uint16_t ) ipTCP_FLAG_SYN;
+ ucExpect |= tcpTCP_FLAG_SYN;
}
- if( ( ucTCPFlags & 0x17u ) != usExpect )
+ const uint8_t ucFlagsMask = tcpTCP_FLAG_ACK | tcpTCP_FLAG_RST | tcpTCP_FLAG_SYN | tcpTCP_FLAG_FIN;
+
+ if( ( ucTCPFlags & ucFlagsMask ) != ucExpect )
{
/* eSYN_RECEIVED: flags 0010 expected, not 0002. */
/* eSYN_RECEIVED: flags ACK expected, not SYN. */
FreeRTOS_debug_printf( ( "%s: flags %04X expected, not %04X\n",
- pxSocket->u.xTCP.ucTCPState == eSYN_RECEIVED ? "eSYN_RECEIVED" : "eCONNECT_SYN",
- usExpect, ucTCPFlags ) );
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eSYN_RECEIVED ) ? "eSYN_RECEIVED" : "eCONNECT_SYN",
+ ucExpect, ucTCPFlags ) );
vTCPStateChange( pxSocket, eCLOSE_WAIT );
- pxTCPHeader->ucTCPFlags |= ipTCP_FLAG_RST;
- xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ /* Send RST with the expected sequence and ACK numbers,
+ otherwise the packet will be ignored. */
+ pxTCPWindow->ulOurSequenceNumber = FreeRTOS_htonl( pxTCPHeader->ulAckNr );
+ pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber;
+
+ pxTCPHeader->ucTCPFlags |= tcpTCP_FLAG_RST;
+ xSendLength = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
}
else
@@ -2331,34 +2426,42 @@ BaseType_t xSendLength = 0;
pxTCPWindow->usPeerPortNumber = pxSocket->u.xTCP.usRemotePort;
pxTCPWindow->usOurPortNumber = pxSocket->usLocalPort;
- if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN )
{
- TCPPacket_t *pxLastTCPPacket = ( TCPPacket_t * ) ( pxSocket->u.xTCP.xPacket.u.ucLastPacket );
+ /* Map the Last packet onto the ProtocolHeader_t struct for easy access to the fields. */
+ ProtocolHeaders_t *pxLastHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
/* Clear the SYN flag in lastPacket. */
- pxLastTCPPacket->xTCPHeader.ucTCPFlags = ipTCP_FLAG_ACK;
+ pxLastHeaders->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_ACK;
+ pxProtocolHeaders->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_ACK;
- /* This socket was the one connecting actively so now perofmr the
+ /* This socket was the one connecting actively so now perform the
synchronisation. */
vTCPWindowInit( &pxSocket->u.xTCP.xTCPWindow,
ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber, ( uint32_t ) pxSocket->u.xTCP.usCurMSS );
- pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1u;
+ pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1U;
+ pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber + 1U;
pxTCPWindow->tx.ulCurrentSequenceNumber++; /* because we send a TCP_SYN [ | TCP_ACK ]; */
pxTCPWindow->ulNextTxSequenceNumber++;
}
- else if( ulReceiveLength == 0u )
+ else if( ulReceiveLength == 0U )
{
pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber;
}
+ else
+ {
+ /* Nothing. */
+ }
/* The SYN+ACK has been confirmed, increase the next sequence number by
1. */
- pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1u;
+ pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1U;
#if( ipconfigUSE_TCP_WIN == 1 )
{
FreeRTOS_debug_printf( ( "TCP: %s %d => %lxip:%d set ESTAB (scaling %u)\n",
- pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ? "active" : "passive",
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN ) ? "active" : "passive",
pxSocket->usLocalPort,
pxSocket->u.xTCP.ulRemoteIP,
pxSocket->u.xTCP.usRemotePort,
@@ -2366,10 +2469,10 @@ BaseType_t xSendLength = 0;
}
#endif /* ipconfigUSE_TCP_WIN */
- if( ( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) || ( ulReceiveLength != 0u ) )
+ if( ( pxSocket->u.xTCP.ucTCPState == ( EventBits_t ) eCONNECT_SYN ) || ( ulReceiveLength != 0UL ) )
{
- pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;
- xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
+ xSendLength = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ( size_t ) ipSIZE_OF_TCP_HEADER + uxOptionsLength );
pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
}
#if( ipconfigUSE_TCP_WIN != 0 )
@@ -2403,45 +2506,49 @@ BaseType_t xSendLength = 0;
static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,
uint32_t ulReceiveLength, UBaseType_t uxOptionsLength )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
+/* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( ( *ppxNetworkBuffer )->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
+TCPHeader_t *pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber ), ulCount;
BaseType_t xSendLength = 0, xMayClose = pdFALSE, bRxComplete, bTxDone;
int32_t lDistance, lSendResult;
+uint16_t usWindow;
/* Remember the window size the peer is advertising. */
- pxSocket->u.xTCP.ulWindowSize = FreeRTOS_ntohs( pxTCPHeader->usWindow );
+ usWindow = FreeRTOS_ntohs( pxTCPHeader->usWindow );
+ pxSocket->u.xTCP.ulWindowSize = ( uint32_t ) usWindow;
#if( ipconfigUSE_TCP_WIN != 0 )
{
pxSocket->u.xTCP.ulWindowSize =
( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );
}
- #endif
+ #endif /* ipconfigUSE_TCP_WIN */
- if( ( ucTCPFlags & ( uint8_t ) ipTCP_FLAG_ACK ) != 0u )
+ if( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_ACK ) != 0U )
{
- ulCount = ulTCPWindowTxAck( pxTCPWindow, FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr ) );
+ ulCount = ulTCPWindowTxAck( pxTCPWindow, FreeRTOS_ntohl( pxTCPHeader->ulAckNr ) );
/* ulTCPWindowTxAck() returns the number of bytes which have been acked,
starting at 'tx.ulCurrentSequenceNumber'. Advance the tail pointer in
txStream. */
- if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0u ) )
+ if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0U ) )
{
/* Just advancing the tail index, 'ulCount' bytes have been
confirmed, and because there is new space in the txStream, the
user/owner should be woken up. */
/* _HT_ : only in case the socket's waiting? */
- if( uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0u, NULL, ( size_t ) ulCount, pdFALSE ) != 0u )
+ if( uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0U, NULL, ( size_t ) ulCount, pdFALSE ) != 0U )
{
- pxSocket->xEventBits |= eSOCKET_SEND;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_SEND;
#if ipconfigSUPPORT_SELECT_FUNCTION == 1
{
- if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )
+ if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_WRITE ) ) != 0U )
{
- pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );
+ pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_WRITE ) << SOCKET_EVENT_BIT_COUNT;
}
}
#endif
@@ -2451,7 +2558,7 @@ int32_t lDistance, lSendResult;
{
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )
{
- pxSocket->u.xTCP.pxHandleSent( ( Socket_t )pxSocket, ulCount );
+ pxSocket->u.xTCP.pxHandleSent( ( Socket_t ) pxSocket, ulCount );
}
}
#endif /* ipconfigUSE_CALLBACKS == 1 */
@@ -2468,7 +2575,7 @@ int32_t lDistance, lSendResult;
pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
- if( ( pxSocket->u.xTCP.bits.bFinAccepted != pdFALSE_UNSIGNED ) || ( ( ucTCPFlags & ( uint8_t ) ipTCP_FLAG_FIN ) != 0u ) )
+ if( ( pxSocket->u.xTCP.bits.bFinAccepted != pdFALSE_UNSIGNED ) || ( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_FIN ) != 0U ) )
{
/* Peer is requesting to stop, see if we're really finished. */
xMayClose = pdTRUE;
@@ -2478,7 +2585,7 @@ int32_t lDistance, lSendResult;
{
/* xTCPWindowTxDone returns true when all Tx queues are empty. */
bRxComplete = xTCPWindowRxEmpty( pxTCPWindow );
- bTxDone = xTCPWindowTxDone( pxTCPWindow );
+ bTxDone = xTCPWindowTxDone( pxTCPWindow );
if( ( bRxComplete == 0 ) || ( bTxDone == 0 ) )
{
@@ -2491,7 +2598,7 @@ int32_t lDistance, lSendResult;
}
else
{
- lDistance = ( int32_t ) ( ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber );
+ lDistance = ipNUMERIC_CAST( int32_t, ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber );
if( lDistance > 1 )
{
@@ -2520,11 +2627,11 @@ int32_t lDistance, lSendResult;
if( xMayClose == pdFALSE )
{
- pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;
+ pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
- if( ulReceiveLength != 0u )
+ if( ulReceiveLength != 0U )
{
- xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ xSendLength = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
/* TCP-offsett equals '( ( length / 4 ) << 4 )', resulting in a shift-left 2 */
pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
@@ -2539,7 +2646,7 @@ int32_t lDistance, lSendResult;
can not send-out both TCP options and also a full packet. Sending
options (SACK) is always more urgent than sending data, which can be
sent later. */
- if( uxOptionsLength == 0u )
+ if( uxOptionsLength == 0U )
{
/* prvTCPPrepareSend might allocate a bigger network buffer, if
necessary. */
@@ -2561,13 +2668,16 @@ int32_t lDistance, lSendResult;
* checked if it would better be postponed for efficiency.
*/
static BaseType_t prvSendData( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,
- uint32_t ulReceiveLength, BaseType_t xSendLength )
+ uint32_t ulReceiveLength, BaseType_t xByteCount )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;
-TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
+/* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( ( *ppxNetworkBuffer )->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( *ppxNetworkBuffer ) ] ) );
+const TCPHeader_t *pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
+const TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
/* Find out what window size we may advertised. */
int32_t lRxSpace;
+BaseType_t xSendLength = xByteCount;
#if( ipconfigUSE_TCP_WIN == 1 )
#if( ipconfigTCP_ACK_EARLIER_PACKET == 0 )
const int32_t lMinLength = 0;
@@ -2578,7 +2688,7 @@ int32_t lRxSpace;
/* Set the time-out field, so that we'll be called by the IP-task in case no
next message will be received. */
- lRxSpace = (int32_t)( pxSocket->u.xTCP.ulHighestRxAllowed - pxTCPWindow->rx.ulCurrentSequenceNumber );
+ lRxSpace = ipNUMERIC_CAST( int32_t, pxSocket->u.xTCP.ulHighestRxAllowed - pxTCPWindow->rx.ulCurrentSequenceNumber );
#if ipconfigUSE_TCP_WIN == 1
{
@@ -2590,17 +2700,18 @@ int32_t lRxSpace;
/* In case we're receiving data continuously, we might postpone sending
an ACK to gain performance. */
- if( ( ulReceiveLength > 0 ) && /* Data was sent to this socket. */
+ /* lint e9007 is OK because 'uxIPHeaderSizeSocket()' has no side-effects. */
+ if( ( ulReceiveLength > 0U ) && /* Data was sent to this socket. */
( lRxSpace >= lMinLength ) && /* There is Rx space for more data. */
( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED ) && /* Not in a closure phase. */
- ( xSendLength == ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) ) && /* No Tx data or options to be sent. */
- ( pxSocket->u.xTCP.ucTCPState == eESTABLISHED ) && /* Connection established. */
- ( pxTCPHeader->ucTCPFlags == ipTCP_FLAG_ACK ) ) /* There are no other flags than an ACK. */
+ ( xSendLength == ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER ) ) && /* No Tx data or options to be sent. */
+ ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eESTABLISHED ) && /* Connection established. */
+ ( pxTCPHeader->ucTCPFlags == tcpTCP_FLAG_ACK ) ) /* There are no other flags than an ACK. */
{
if( pxSocket->u.xTCP.pxAckMessage != *ppxNetworkBuffer )
{
/* There was still a delayed in queue, delete it. */
- if( pxSocket->u.xTCP.pxAckMessage != 0 )
+ if( pxSocket->u.xTCP.pxAckMessage != NULL )
{
vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
}
@@ -2608,19 +2719,19 @@ int32_t lRxSpace;
pxSocket->u.xTCP.pxAckMessage = *ppxNetworkBuffer;
}
if( ( ulReceiveLength < ( uint32_t ) pxSocket->u.xTCP.usCurMSS ) || /* Received a small message. */
- ( lRxSpace < ( int32_t ) ( 2U * pxSocket->u.xTCP.usCurMSS ) ) ) /* There are less than 2 x MSS space in the Rx buffer. */
+ ( lRxSpace < ipNUMERIC_CAST( int32_t, 2U * pxSocket->u.xTCP.usCurMSS ) ) ) /* There are less than 2 x MSS space in the Rx buffer. */
{
- pxSocket->u.xTCP.usTimeout = ( uint16_t ) pdMS_TO_MIN_TICKS( DELAYED_ACK_SHORT_DELAY_MS );
+ pxSocket->u.xTCP.usTimeout = ( uint16_t ) tcpDELAYED_ACK_SHORT_DELAY_MS;
}
else
{
/* Normally a delayed ACK should wait 200 ms for a next incoming
packet. Only wait 20 ms here to gain performance. A slow ACK
for full-size message. */
- pxSocket->u.xTCP.usTimeout = ( uint16_t ) pdMS_TO_MIN_TICKS( DELAYED_ACK_LONGER_DELAY_MS );
+ pxSocket->u.xTCP.usTimeout = ( uint16_t ) ipMS_TO_MIN_TICKS( tcpDELAYED_ACK_LONGER_DELAY_MS );
}
- if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )
+ if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) )
{
FreeRTOS_debug_printf( ( "Send[%u->%u] del ACK %lu SEQ %lu (len %lu) tmout %u d %lu\n",
pxSocket->usLocalPort,
@@ -2645,6 +2756,10 @@ int32_t lRxSpace;
pxSocket->u.xTCP.pxAckMessage = NULL;
}
+ else
+ {
+ /* The ack will not be postponed, and there was no stored ack ( in 'pxAckMessage' ). */
+ }
}
#else
{
@@ -2657,7 +2772,7 @@ int32_t lRxSpace;
if( xSendLength != 0 )
{
- if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )
+ if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) )
{
FreeRTOS_debug_printf( ( "Send[%u->%u] imm ACK %lu SEQ %lu (len %lu)\n",
pxSocket->usLocalPort,
@@ -2700,8 +2815,10 @@ int32_t lRxSpace;
*/
static BaseType_t prvTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer )
{
-TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );
-TCPHeader_t *pxTCPHeader = &( pxTCPPacket->xTCPHeader );
+/* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */
+ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
+ &( ( *ppxNetworkBuffer )->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( *ppxNetworkBuffer ) ] ) );
+TCPHeader_t *pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
BaseType_t xSendLength = 0;
uint32_t ulReceiveLength; /* Number of bytes contained in the TCP message. */
uint8_t *pucRecvData;
@@ -2712,7 +2829,7 @@ uint32_t ulSequenceNumber = FreeRTOS_ntohl (pxTCPHeader->ulSequenceNumber);
1. in the SYN phase, we shall communicate the MSS
2. in case of a SACK, Selective ACK, ack a segment which comes in
out-of-order. */
-UBaseType_t uxOptionsLength = 0u;
+UBaseType_t uxOptionsLength = 0U;
uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
@@ -2720,9 +2837,9 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
pucRecvData will point to the first byte of the TCP payload. */
ulReceiveLength = ( uint32_t ) prvCheckRxData( *ppxNetworkBuffer, &pucRecvData );
- if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )
+ if( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED )
{
- if ( pxTCPWindow->rx.ulCurrentSequenceNumber == ulSequenceNumber + 1u )
+ if ( pxTCPWindow->rx.ulCurrentSequenceNumber == ( ulSequenceNumber + 1UL ) )
{
/* This is most probably a keep-alive message from peer. Setting
'bWinChange' doesn't cause a window-size-change, the flag is used
@@ -2733,7 +2850,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
/* Keep track of the highest sequence number that might be expected within
this connection. */
- if( ( ( int32_t ) ( ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulHighestSequenceNumber ) ) > 0 )
+ if( ( ipNUMERIC_CAST( int32_t, ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulHighestSequenceNumber ) ) > 0L )
{
pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + ulReceiveLength;
}
@@ -2747,7 +2864,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
{
uxOptionsLength = prvSetOptions( pxSocket, *ppxNetworkBuffer );
- if( ( pxSocket->u.xTCP.ucTCPState == eSYN_RECEIVED ) && ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) == ipTCP_FLAG_SYN ) )
+ if( ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eSYN_RECEIVED ) && ( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_CTRL ) == ( uint8_t ) tcpTCP_FLAG_SYN ) )
{
FreeRTOS_debug_printf( ( "eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK\n" ) );
@@ -2758,7 +2875,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
vTCPStateChange( pxSocket, eSYN_FIRST );
}
- if( ( ( ucTCPFlags & ipTCP_FLAG_FIN ) != 0u ) && ( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED ) )
+ if( ( ( ucTCPFlags & tcpTCP_FLAG_FIN ) != 0U ) && ( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED ) )
{
/* It's the first time a FIN has been received, remember its
sequence number. */
@@ -2773,7 +2890,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
}
}
- switch (pxSocket->u.xTCP.ucTCPState)
+ switch( ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState ) )
{
case eCLOSED: /* (server + client) no connection state at all. */
/* Nothing to do for a closed socket, except waiting for the
@@ -2792,10 +2909,10 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
/* A new socket has been created, reply with a SYN+ACK.
Acknowledge with seq+1 because the SYN is seen as pseudo data
with len = 1. */
- uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPPacket );
- pxTCPHeader->ucTCPFlags = ipTCP_FLAG_SYN | ipTCP_FLAG_ACK;
+ uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPHeader );
+ pxTCPHeader->ucTCPFlags = ( uint8_t ) tcpTCP_FLAG_SYN | ( uint8_t ) tcpTCP_FLAG_ACK;
- xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
+ xSendLength = ipNUMERIC_CAST( BaseType_t, uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength );
/* Set the TCP offset field: ipSIZE_OF_TCP_HEADER equals 20 and
uxOptionsLength is a multiple of 4. The complete expression is:
@@ -2803,8 +2920,10 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
vTCPStateChange( pxSocket, eSYN_RECEIVED );
- pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1u;
- pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->ulNextTxSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1u; /* because we send a TCP_SYN. */
+ pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1UL;
+ pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber + 1UL;
+ pxTCPWindow->ulNextTxSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1UL;
+ pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1UL; /* because we send a TCP_SYN. */
}
break;
@@ -2813,7 +2932,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
/* Fall through */
case eSYN_RECEIVED: /* (server) we've had a SYN, replied with SYN+SCK
expect a ACK and do nothing. */
- xSendLength = prvHandleSynReceived( pxSocket, ppxNetworkBuffer, ulReceiveLength, uxOptionsLength );
+ xSendLength = prvHandleSynReceived( pxSocket, *( ppxNetworkBuffer ), ulReceiveLength, uxOptionsLength );
break;
case eESTABLISHED: /* (server + client) an open connection, data
@@ -2858,6 +2977,7 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
'bFinSent', 'bFinRecv', and 'bFinAcked'. */
break;
default:
+ /* No more known states. */
break;
}
}
@@ -2872,40 +2992,41 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
/*-----------------------------------------------------------*/
static BaseType_t prvTCPSendSpecialPacketHelper( NetworkBufferDescriptor_t *pxNetworkBuffer,
- uint8_t ucTCPFlags )
+ uint8_t ucTCPFlags )
{
-#if( ipconfigIGNORE_UNKNOWN_PACKETS == 0 )
- {
- TCPPacket_t *pxTCPPacket = ( TCPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer );
- const BaseType_t xSendLength = ( BaseType_t )
- ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 0u ); /* Plus 0 options. */
+#if( ipconfigIGNORE_UNKNOWN_PACKETS == 1 )
+ /* Configured to ignore unknown packets just suppress a compiler warning. */
+ ( void ) pxNetworkBuffer;
+ ( void ) ucTCPFlags;
+#else
+ {
+ /* Map the ethernet buffer onto the TCPPacket_t struct for easy access to the fields. */
+ TCPPacket_t *pxTCPPacket = ipPOINTER_CAST( TCPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ const uint32_t ulSendLength = ( uint32_t )
+ ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ); /* Plus 0 options. */
- pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags;
- pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER + 0u ) << 2;
+ pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags;
+ pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER ) << 2;
- prvTCPReturnPacket( NULL, pxNetworkBuffer, ( uint32_t )xSendLength, pdFALSE );
- }
+ prvTCPReturnPacket( NULL, pxNetworkBuffer, ulSendLength, pdFALSE );
+ }
#endif /* !ipconfigIGNORE_UNKNOWN_PACKETS */
- /* Remove compiler warnings if ipconfigIGNORE_UNKNOWN_PACKETS == 1. */
- ( void )pxNetworkBuffer;
- ( void )ucTCPFlags;
-
- /* The packet was not consumed. */
- return pdFAIL;
+ /* The packet was not consumed. */
+ return pdFAIL;
}
/*-----------------------------------------------------------*/
static BaseType_t prvTCPSendChallengeAck( NetworkBufferDescriptor_t *pxNetworkBuffer )
{
- return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, ipTCP_FLAG_ACK );
+ return prvTCPSendSpecialPacketHelper( pxNetworkBuffer, tcpTCP_FLAG_ACK );
}
/*-----------------------------------------------------------*/
static BaseType_t prvTCPSendReset( NetworkBufferDescriptor_t *pxNetworkBuffer )
{
- return prvTCPSendSpecialPacketHelper( pxNetworkBuffer,
- ipTCP_FLAG_ACK | ipTCP_FLAG_RST );
+ return prvTCPSendSpecialPacketHelper( pxNetworkBuffer,
+ ( uint8_t ) tcpTCP_FLAG_ACK | ( uint8_t ) tcpTCP_FLAG_RST );
}
/*-----------------------------------------------------------*/
@@ -2913,16 +3034,17 @@ static void prvSocketSetMSS( FreeRTOS_Socket_t *pxSocket )
{
uint32_t ulMSS = ipconfigTCP_MSS;
- if( ( ( FreeRTOS_ntohl( pxSocket->u.xTCP.ulRemoteIP ) ^ *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) != 0ul )
+ if( ( ( FreeRTOS_ntohl( pxSocket->u.xTCP.ulRemoteIP ) ^ *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) != 0UL )
{
/* Data for this peer will pass through a router, and maybe through
the internet. Limit the MSS to 1400 bytes or less. */
- ulMSS = FreeRTOS_min_uint32( ( uint32_t ) REDUCED_MSS_THROUGH_INTERNET, ulMSS );
+ ulMSS = FreeRTOS_min_uint32( ( uint32_t ) tcpREDUCED_MSS_THROUGH_INTERNET, ulMSS );
}
FreeRTOS_debug_printf( ( "prvSocketSetMSS: %lu bytes for %lxip:%u\n", ulMSS, pxSocket->u.xTCP.ulRemoteIP, pxSocket->u.xTCP.usRemotePort ) );
- pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ( uint16_t ) ulMSS;
+ pxSocket->u.xTCP.usInitMSS = ( uint16_t ) ulMSS;
+ pxSocket->u.xTCP.usCurMSS = ( uint16_t ) ulMSS;
}
/*-----------------------------------------------------------*/
@@ -2937,215 +3059,235 @@ uint32_t ulMSS = ipconfigTCP_MSS;
* prvTCPReturnPacket() // Prepare for returning
* xNetworkInterfaceOutput() // Sends data to the NIC
*/
-BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer )
+BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxDescriptor )
{
+/* Function might modify the parameter. */
+NetworkBufferDescriptor_t *pxNetworkBuffer = pxDescriptor;
+
+/* Map the buffer onto a ProtocolHeaders_t struct for easy access to the fields. */
+const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( const ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
FreeRTOS_Socket_t *pxSocket;
-TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
-uint16_t ucTCPFlags;
+uint16_t ucTCPFlags = pxProtocolHeaders->xTCPHeader.ucTCPFlags;
uint32_t ulLocalIP;
-uint16_t xLocalPort;
+uint16_t xLocalPort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usDestinationPort );
+uint16_t xRemotePort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usSourcePort );
uint32_t ulRemoteIP;
-uint16_t xRemotePort;
-uint32_t ulSequenceNumber;
-uint32_t ulAckNumber;
+uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulSequenceNumber );
+uint32_t ulAckNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulAckNr );;
BaseType_t xResult = pdPASS;
-configASSERT(pxNetworkBuffer);
-configASSERT(pxNetworkBuffer->pucEthernetBuffer);
+configASSERT( pxNetworkBuffer != NULL );
+configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL );
+const IPHeader_t *pxIPHeader;
/* Check for a minimum packet size. */
- if( pxNetworkBuffer->xDataLength >= ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) )
+ if( pxNetworkBuffer->xDataLength < ( ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) + ipSIZE_OF_TCP_HEADER ) )
{
- ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;
- ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );
- xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );
- ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
- xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
- ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
- ulAckNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr );
-
- /* Find the destination socket, and if not found: return a socket listing to
- the destination PORT. */
- pxSocket = ( FreeRTOS_Socket_t * )pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );
+ xResult = pdFAIL;
}
else
{
- return pdFAIL;
- }
-
- if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE ) )
- {
- /* A TCP messages is received but either there is no socket with the
- given port number or the there is a socket, but it is in one of these
- non-active states: eCLOSED, eCLOSE_WAIT, eFIN_WAIT_2, eCLOSING, or
- eTIME_WAIT. */
+ /* Map the ethernet buffer onto the IPHeader_t struct for easy access to the fields. */
+ pxIPHeader = ipPOINTER_CAST( const IPHeader_t *, &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) );
+ ulLocalIP = FreeRTOS_htonl( pxIPHeader->ulDestinationIPAddress );
+ ulRemoteIP = FreeRTOS_htonl( pxIPHeader->ulSourceIPAddress );
- FreeRTOS_debug_printf( ( "TCP: No active socket on port %d (%lxip:%d)\n", xLocalPort, ulRemoteIP, xRemotePort ) );
+ /* Find the destination socket, and if not found: return a socket listing to
+ the destination PORT. */
+ pxSocket = ( FreeRTOS_Socket_t * ) pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );
- /* Send a RST to all packets that can not be handled. As a result
- the other party will get a ECONN error. There are two exceptions:
- 1) A packet that already has the RST flag set.
- 2) A packet that only has the ACK flag set.
- A packet with only the ACK flag set might be the last ACK in
- a three-way hand-shake that closes a connection. */
- if( ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) != ipTCP_FLAG_ACK ) &&
- ( ( ucTCPFlags & ipTCP_FLAG_RST ) == 0u ) )
+ if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState ) ) == pdFALSE ) )
{
- prvTCPSendReset( pxNetworkBuffer );
- }
+ /* A TCP messages is received but either there is no socket with the
+ given port number or the there is a socket, but it is in one of these
+ non-active states: eCLOSED, eCLOSE_WAIT, eFIN_WAIT_2, eCLOSING, or
+ eTIME_WAIT. */
- /* The packet can't be handled. */
- xResult = pdFAIL;
- }
- else
- {
- pxSocket->u.xTCP.ucRepCount = 0u;
+ FreeRTOS_debug_printf( ( "TCP: No active socket on port %d (%lxip:%d)\n", xLocalPort, ulRemoteIP, xRemotePort ) );
- if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )
+ /* Send a RST to all packets that can not be handled. As a result
+ the other party will get a ECONN error. There are two exceptions:
+ 1) A packet that already has the RST flag set.
+ 2) A packet that only has the ACK flag set.
+ A packet with only the ACK flag set might be the last ACK in
+ a three-way hand-shake that closes a connection. */
+ if( ( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) != tcpTCP_FLAG_ACK ) &&
+ ( ( ucTCPFlags & tcpTCP_FLAG_RST ) == 0U ) )
+ {
+ ( void ) prvTCPSendReset( pxNetworkBuffer );
+ }
+
+ /* The packet can't be handled. */
+ xResult = pdFAIL;
+ }
+ else
{
- /* The matching socket is in a listening state. Test if the peer
- has set the SYN flag. */
- if( ( ucTCPFlags & ipTCP_FLAG_CTRL ) != ipTCP_FLAG_SYN )
+ pxSocket->u.xTCP.ucRepCount = 0U;
+
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
{
- /* What happens: maybe after a reboot, a client doesn't know the
- connection had gone. Send a RST in order to get a new connect
- request. */
- #if( ipconfigHAS_DEBUG_PRINTF == 1 )
+ /* The matching socket is in a listening state. Test if the peer
+ has set the SYN flag. */
+ if( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) != tcpTCP_FLAG_SYN )
{
- FreeRTOS_debug_printf( ( "TCP: Server can't handle flags: %s from %lxip:%u to port %u\n",
- prvTCPFlagMeaning( ( UBaseType_t ) ucTCPFlags ), ulRemoteIP, xRemotePort, xLocalPort ) );
- }
- #endif /* ipconfigHAS_DEBUG_PRINTF */
+ /* What happens: maybe after a reboot, a client doesn't know the
+ connection had gone. Send a RST in order to get a new connect
+ request. */
+ #if( ipconfigHAS_DEBUG_PRINTF == 1 )
+ {
+ FreeRTOS_debug_printf( ( "TCP: Server can't handle flags: %s from %lxip:%u to port %u\n",
+ prvTCPFlagMeaning( ( UBaseType_t ) ucTCPFlags ), ulRemoteIP, xRemotePort, xLocalPort ) );
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF */
- if( ( ucTCPFlags & ipTCP_FLAG_RST ) == 0u )
+ if( ( ucTCPFlags & tcpTCP_FLAG_RST ) == 0U )
+ {
+ ( void ) prvTCPSendReset( pxNetworkBuffer );
+ }
+ xResult = pdFAIL;
+ }
+ else
{
- prvTCPSendReset( pxNetworkBuffer );
+ /* prvHandleListen() will either return a newly created socket
+ (if bReuseSocket is false), otherwise it returns the current
+ socket which will later get connected. */
+ pxSocket = prvHandleListen( pxSocket, pxNetworkBuffer );
+
+ if( pxSocket == NULL )
+ {
+ xResult = pdFAIL;
+ }
}
- xResult = pdFAIL;
- }
+ } /* if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN ). */
else
{
- /* prvHandleListen() will either return a newly created socket
- (if bReuseSocket is false), otherwise it returns the current
- socket which will later get connected. */
- pxSocket = prvHandleListen( pxSocket, pxNetworkBuffer );
+ /* This is not a socket in listening mode. Check for the RST
+ flag. */
+ if( ( ucTCPFlags & tcpTCP_FLAG_RST ) != 0U )
+ {
+ FreeRTOS_debug_printf( ( "TCP: RST received from %lxip:%u for %u\n", ulRemoteIP, xRemotePort, xLocalPort ) );
+
+ /* Implement https://tools.ietf.org/html/rfc5961#section-3.2. */
+ if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCONNECT_SYN )
+ {
+ /* Per the above RFC, "In the SYN-SENT state ... the RST is
+ acceptable if the ACK field acknowledges the SYN." */
+ if( ulAckNumber == ( pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber + 1UL ) )
+ {
+ vTCPStateChange( pxSocket, eCLOSED );
+ }
+ }
+ else
+ {
+ /* Check whether the packet matches the next expected sequence number. */
+ if( ulSequenceNumber == pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber )
+ {
+ vTCPStateChange( pxSocket, eCLOSED );
+ }
+ /* Otherwise, check whether the packet is within the receive window. */
+ else if( ( ulSequenceNumber > pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) &&
+ ( ulSequenceNumber < ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber +
+ pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) ) )
+ {
+ /* Send a challenge ACK. */
+ ( void ) prvTCPSendChallengeAck( pxNetworkBuffer );
+ }
+ else
+ {
+ /* Nothing. */
+ }
+ }
- if( pxSocket == NULL )
+ /* Otherwise, do nothing. In any case, the packet cannot be handled. */
+ xResult = pdFAIL;
+ }
+ else if( ( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) == tcpTCP_FLAG_SYN ) && ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) )
{
+ /* SYN flag while this socket is already connected. */
+ FreeRTOS_debug_printf( ( "TCP: SYN unexpected from %lxip:%u\n", ulRemoteIP, xRemotePort ) );
+
+ /* The packet cannot be handled. */
xResult = pdFAIL;
}
- }
- } /* if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN ). */
- else
- {
- /* This is not a socket in listening mode. Check for the RST
- flag. */
- if( ( ucTCPFlags & ipTCP_FLAG_RST ) != 0u )
- {
- FreeRTOS_debug_printf( ( "TCP: RST received from %lxip:%u for %u\n", ulRemoteIP, xRemotePort, xLocalPort ) );
-
- /* Implement https://tools.ietf.org/html/rfc5961#section-3.2. */
- if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )
- {
- /* Per the above RFC, "In the SYN-SENT state ... the RST is
- acceptable if the ACK field acknowledges the SYN." */
- if( ulAckNumber == pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber + 1 )
- {
- vTCPStateChange( pxSocket, eCLOSED );
- }
- }
- else
- {
- /* Check whether the packet matches the next expected sequence number. */
- if( ulSequenceNumber == pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber )
- {
- vTCPStateChange( pxSocket, eCLOSED );
- }
- /* Otherwise, check whether the packet is within the receive window. */
- else if( ulSequenceNumber > pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber &&
- ulSequenceNumber < ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber +
- pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) )
- {
- /* Send a challenge ACK. */
- prvTCPSendChallengeAck( pxNetworkBuffer );
- }
- }
-
- /* Otherwise, do nothing. In any case, the packet cannot be handled. */
- xResult = pdFAIL;
- }
- else if( ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) == ipTCP_FLAG_SYN ) && ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) )
- {
- /* SYN flag while this socket is already connected. */
- FreeRTOS_debug_printf( ( "TCP: SYN unexpected from %lxip:%u\n", ulRemoteIP, xRemotePort ) );
-
- /* The packet cannot be handled. */
- xResult = pdFAIL;
- }
- else
- {
- /* Update the copy of the TCP header only (skipping eth and IP
- headers). It might be used later on, whenever data must be sent
- to the peer. */
- const BaseType_t lOffset = ( BaseType_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER );
- memcpy( pxSocket->u.xTCP.xPacket.u.ucLastPacket + lOffset, pxNetworkBuffer->pucEthernetBuffer + lOffset, ipSIZE_OF_TCP_HEADER );
+ else
+ {
+ /* Update the copy of the TCP header only (skipping eth and IP
+ headers). It might be used later on, whenever data must be sent
+ to the peer. */
+ const size_t lOffset = ipNUMERIC_CAST( size_t, ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) );
+ ( void ) memcpy( &( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ lOffset ] ),
+ &( pxNetworkBuffer->pucEthernetBuffer[ lOffset ] ),
+ ipSIZE_OF_TCP_HEADER );
+ }
}
}
- }
- if( xResult != pdFAIL )
- {
- /* Touch the alive timers because we received a message for this
- socket. */
- prvTCPTouchSocket( pxSocket );
-
- /* Parse the TCP option(s), if present. */
- /* _HT_ : if we're in the SYN phase, and peer does not send a MSS option,
- then we MUST assume an MSS size of 536 bytes for backward compatibility. */
-
- /* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as
- the number 5 (words) in the higher niblle of the TCP-offset byte. */
- if( ( pxTCPPacket->xTCPHeader.ucTCPOffset & TCP_OFFSET_LENGTH_BITS ) > TCP_OFFSET_STANDARD_LENGTH )
+ if( xResult != pdFAIL )
{
- prvCheckOptions( pxSocket, pxNetworkBuffer );
- }
+ uint16_t usWindow;
+ /* pxSocket is not NULL when xResult != pdFAIL. */
+ configASSERT( pxSocket != NULL );
+ /* Touch the alive timers because we received a message for this
+ socket. */
+ prvTCPTouchSocket( pxSocket );
- #if( ipconfigUSE_TCP_WIN == 1 )
- {
- pxSocket->u.xTCP.ulWindowSize = FreeRTOS_ntohs( pxTCPPacket->xTCPHeader.usWindow );
- pxSocket->u.xTCP.ulWindowSize =
- ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );
- }
- #endif
+ /* Parse the TCP option(s), if present. */
+ /* _HT_ : if we're in the SYN phase, and peer does not send a MSS option,
+ then we MUST assume an MSS size of 536 bytes for backward compatibility. */
- /* In prvTCPHandleState() the incoming messages will be handled
- depending on the current state of the connection. */
- if( prvTCPHandleState( pxSocket, &pxNetworkBuffer ) > 0 )
- {
- /* prvTCPHandleState() has sent a message, see if there are more to
- be transmitted. */
+ /* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as
+ the number 5 (words) in the higher nibble of the TCP-offset byte. */
+ if( ( pxProtocolHeaders->xTCPHeader.ucTCPOffset & tcpTCP_OFFSET_LENGTH_BITS ) > tcpTCP_OFFSET_STANDARD_LENGTH )
+ {
+ prvCheckOptions( pxSocket, pxNetworkBuffer );
+ }
+
+ usWindow = FreeRTOS_ntohs( pxProtocolHeaders->xTCPHeader.usWindow );
+ pxSocket->u.xTCP.ulWindowSize = (uint32_t ) usWindow;
#if( ipconfigUSE_TCP_WIN == 1 )
{
- prvTCPSendRepeated( pxSocket, &pxNetworkBuffer );
+ /* rfc1323 : The Window field in a SYN (i.e., a <SYN> or <SYN,ACK>)
+ segment itself is never scaled. */
+ if( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_SYN ) == 0U )
+ {
+ pxSocket->u.xTCP.ulWindowSize =
+ ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );
+ }
}
#endif /* ipconfigUSE_TCP_WIN */
- }
- if( pxNetworkBuffer != NULL )
- {
- /* We must check if the buffer is unequal to NULL, because the
- socket might keep a reference to it in case a delayed ACK must be
- sent. */
- vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
- pxNetworkBuffer = NULL;
- }
+ /* In prvTCPHandleState() the incoming messages will be handled
+ depending on the current state of the connection. */
+ if( prvTCPHandleState( pxSocket, &pxNetworkBuffer ) > 0 )
+ {
+ /* prvTCPHandleState() has sent a message, see if there are more to
+ be transmitted. */
+ #if( ipconfigUSE_TCP_WIN == 1 )
+ {
+ ( void ) prvTCPSendRepeated( pxSocket, &pxNetworkBuffer );
+ }
+ #endif /* ipconfigUSE_TCP_WIN */
+ }
- /* And finally, calculate when this socket wants to be woken up. */
- prvTCPNextTimeout ( pxSocket );
- /* Return pdPASS to tell that the network buffer is 'consumed'. */
- xResult = pdPASS;
- }
+ if( pxNetworkBuffer != NULL )
+ {
+ /* We must check if the buffer is unequal to NULL, because the
+ socket might keep a reference to it in case a delayed ACK must be
+ sent. */
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ #ifndef _lint
+ /* Clear pointers that are freed. */
+ pxNetworkBuffer = NULL;
+ #endif
+ }
+ /* And finally, calculate when this socket wants to be woken up. */
+ ( void ) prvTCPNextTimeout ( pxSocket );
+ /* Return pdPASS to tell that the network buffer is 'consumed'. */
+ xResult = pdPASS;
+ }
+ }
/* pdPASS being returned means the buffer has been consumed. */
return xResult;
}
@@ -3153,7 +3295,8 @@ configASSERT(pxNetworkBuffer->pucEthernetBuffer);
static FreeRTOS_Socket_t *prvHandleListen( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
{
-TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+/* Map the ethernet buffer onto a TCPPacket_t struct for easy access to the fields. */
+const TCPPacket_t * pxTCPPacket = ipPOINTER_CAST( const TCPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
FreeRTOS_Socket_t *pxReturn = NULL;
uint32_t ulInitialSequenceNumber;
@@ -3166,7 +3309,7 @@ uint32_t ulInitialSequenceNumber;
/* A pure SYN (without ACK) has come in, create a new socket to answer
it. */
- if( 0 != ulInitialSequenceNumber )
+ if( ulInitialSequenceNumber != 0UL )
{
if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
{
@@ -3188,8 +3331,8 @@ uint32_t ulInitialSequenceNumber;
pxSocket->usLocalPort,
pxSocket->u.xTCP.usChildCount,
pxSocket->u.xTCP.usBacklog,
- pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );
- prvTCPSendReset( pxNetworkBuffer );
+ ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
+ ( void ) prvTCPSendReset( pxNetworkBuffer );
}
else
{
@@ -3199,7 +3342,7 @@ uint32_t ulInitialSequenceNumber;
if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )
{
FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );
- prvTCPSendReset( pxNetworkBuffer );
+ ( void ) prvTCPSendReset( pxNetworkBuffer );
}
else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )
{
@@ -3209,18 +3352,26 @@ uint32_t ulInitialSequenceNumber;
lack of resources). */
pxReturn = pxNewSocket;
}
+ else
+ {
+ /* Copying failed somehow. */
+ }
}
}
}
- if( ( 0 != ulInitialSequenceNumber ) && ( pxReturn != NULL ) )
+ if( ( ulInitialSequenceNumber != 0U ) && ( pxReturn != NULL ) )
{
+ /* Map the byte stream onto the ProtocolHeaders_t for easy access to the fields. */
+ const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( const ProtocolHeaders_t *,
+ &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
+
pxReturn->u.xTCP.usRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
pxReturn->u.xTCP.ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
/* Here is the SYN action. */
- pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );
+ pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulSequenceNumber );
prvSocketSetMSS( pxReturn );
prvTCPCreateWindow( pxReturn );
@@ -3229,7 +3380,7 @@ uint32_t ulInitialSequenceNumber;
/* Make a copy of the header up to the TCP header. It is needed later
on, whenever data must be sent to the peer. */
- memcpy( pxReturn->u.xTCP.xPacket.u.ucLastPacket, pxNetworkBuffer->pucEthernetBuffer, sizeof( pxReturn->u.xTCP.xPacket.u.ucLastPacket ) );
+ ( void ) memcpy( pxReturn->u.xTCP.xPacket.u.ucLastPacket, pxNetworkBuffer->pucEthernetBuffer, sizeof( pxReturn->u.xTCP.xPacket.u.ucLastPacket ) );
}
return pxReturn;
}
@@ -3241,6 +3392,7 @@ uint32_t ulInitialSequenceNumber;
static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t *pxNewSocket, FreeRTOS_Socket_t *pxSocket )
{
struct freertos_sockaddr xAddress;
+BaseType_t xResult;
pxNewSocket->xReceiveBlockTime = pxSocket->xReceiveBlockTime;
pxNewSocket->xSendBlockTime = pxSocket->xSendBlockTime;
@@ -3271,10 +3423,10 @@ struct freertos_sockaddr xAddress;
{
/* Child socket of listening sockets will inherit the Socket Set
Otherwise the owner has no chance of including it into the set. */
- if( pxSocket->pxSocketSet )
+ if( pxSocket->pxSocketSet != NULL )
{
pxNewSocket->pxSocketSet = pxSocket->pxSocketSet;
- pxNewSocket->xSelectBits = pxSocket->xSelectBits | eSELECT_READ | eSELECT_EXCEPT;
+ pxNewSocket->xSelectBits = pxSocket->xSelectBits | ( ( EventBits_t ) eSELECT_READ ) | ( ( EventBits_t ) eSELECT_EXCEPT );
}
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
@@ -3299,7 +3451,7 @@ struct freertos_sockaddr xAddress;
/* A reference to the new socket may be stored and the socket is marked
as 'passable'. */
- /* When bPassAccept is pdTRUE_UNSIGNED this socket may be returned in a call to
+ /* When bPassAccept is true, this socket may be returned in a call to
accept(). */
pxNewSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;
if(pxSocket->u.xTCP.pxPeerSocket == NULL )
@@ -3315,17 +3467,21 @@ struct freertos_sockaddr xAddress;
pxSocket->usLocalPort,
pxSocket->u.xTCP.usChildCount,
pxSocket->u.xTCP.usBacklog,
- pxSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );
+ ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
/* Now bind the child socket to the same port as the listening socket. */
if( vSocketBind ( pxNewSocket, &xAddress, sizeof( xAddress ), pdTRUE ) != 0 )
{
FreeRTOS_debug_printf( ( "TCP: Listen: new socket bind error\n" ) );
- vSocketClose( pxNewSocket );
- return pdFALSE;
+ ( void ) vSocketClose( pxNewSocket );
+ xResult = pdFALSE;
+ }
+ else
+ {
+ xResult = pdTRUE;
}
- return pdTRUE;
+ return xResult;
}
/*-----------------------------------------------------------*/
@@ -3333,11 +3489,31 @@ struct freertos_sockaddr xAddress;
const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState )
{
- if( ulState >= ( UBaseType_t ) ARRAY_SIZE( pcStateNames ) )
+ static const char * const pcStateNames[] =
+ {
+ "eCLOSED",
+ "eTCP_LISTEN",
+ "eCONNECT_SYN",
+ "eSYN_FIRST",
+ "eSYN_RECEIVED",
+ "eESTABLISHED",
+ "eFIN_WAIT_1",
+ "eFIN_WAIT_2",
+ "eCLOSE_WAIT",
+ "eCLOSING",
+ "eLAST_ACK",
+ "eTIME_WAIT",
+ "eUNKNOWN",
+ };
+ BaseType_t xIndex = ( BaseType_t ) ulState;
+
+ if( ( xIndex < 0 ) || ( xIndex >= ARRAY_SIZE( pcStateNames ) ) )
{
- ulState = ( UBaseType_t ) ARRAY_SIZE( pcStateNames ) - 1u;
+ /* The last item is called 'eUNKNOWN' */
+ xIndex = ARRAY_SIZE( pcStateNames );
+ xIndex--;
}
- return pcStateNames[ ulState ];
+ return pcStateNames[ xIndex ];
}
#endif /* ( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) ) */
@@ -3349,21 +3525,22 @@ struct freertos_sockaddr xAddress;
*/
BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t *pxSocket )
{
-TickType_t xLocalPort = FreeRTOS_htons( pxSocket->usLocalPort );
-ListItem_t *pxIterator;
+TickType_t uxLocalPort = ( TickType_t ) FreeRTOS_htons( pxSocket->usLocalPort );
+const ListItem_t *pxIterator;
FreeRTOS_Socket_t *pxFound;
BaseType_t xResult = pdFALSE;
+const ListItem_t *pxEndTCP = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &xBoundTCPSocketsList ) );
/* Here xBoundTCPSocketsList can be accessed safely IP-task is the only one
who has access. */
- for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
- pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );
- pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = ( const ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
+ pxIterator != pxEndTCP;
+ pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
{
- if( listGET_LIST_ITEM_VALUE( pxIterator ) == xLocalPort )
+ if( listGET_LIST_ITEM_VALUE( pxIterator ) == ( configLIST_VOLATILE TickType_t ) uxLocalPort )
{
- pxFound = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
- if( ( pxFound->ucProtocol == FREERTOS_IPPROTO_TCP ) && ( pxFound->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
+ pxFound = ipPOINTER_CAST( FreeRTOS_Socket_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
+ if( ( pxFound->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ) && ( pxFound->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
{
pxSocket->u.xTCP.pxPeerSocket = pxFound;
FreeRTOS_debug_printf( ( "xTCPCheckNewClient[0]: client on port %u\n", pxSocket->usLocalPort ) );
@@ -3379,8 +3556,8 @@ BaseType_t xResult = pdFALSE;
#endif /* ipconfigUSE_TCP == 1 */
/* Provide access to private members for testing. */
-#ifdef AMAZON_FREERTOS_ENABLE_UNIT_TESTS
- #include "iot_freertos_tcp_test_access_tcp_define.h"
+#ifdef FREERTOS_ENABLE_UNIT_TESTS
+ #include "freertos_tcp_test_access_tcp_define.h"
#endif
/* Provide access to private members for verification. */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
index 1c8f2246d..5adcc9f31 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
@@ -39,16 +39,14 @@
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
-#include "queue.h"
-#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
-#include "NetworkBufferManagement.h"
-#include "FreeRTOS_TCP_WIN.h"
+
+#include "FreeRTOSIPConfigDefaults.h"
/* Constants used for Smoothed Round Trip Time (SRTT). */
#define winSRTT_INCREMENT_NEW 2
@@ -80,17 +78,17 @@
* by the peer, it is very unlikely a current packet will ever arrive.
* It will be retransmitted far before the RTO.
*/
- #define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ( 3u )
+ #define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ( 3U )
/* If there have been several retransmissions (4), decrease the
* size of the transmission window to at most 2 times MSS.
*/
- #define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ( 4u )
+ #define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ( 4U )
#endif /* configUSE_TCP_WIN */
/*-----------------------------------------------------------*/
-extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
+static void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
/*
* All TCP sockets share a pool of segment descriptors (TCPSegment_t)
@@ -109,7 +107,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* segments: 'pxWindow->xRxSegments'.
*/
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );
+ static TCPSegment_t *xTCPWindowRxFind( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/*
@@ -121,28 +119,18 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
static TCPSegment_t *xTCPWindowNew( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, int32_t lCount, BaseType_t xIsForRx );
#endif /* ipconfigUSE_TCP_WIN == 1 */
-/* When the peer has a close request (FIN flag), the driver will check if
- * there are missing packets in the Rx-queue
- * It will accept the closure of the connection if both conditions are true:
- * - the Rx-queue is empty
- * - we've ACK'd the highest Rx sequence number seen
- */
-#if( ipconfigUSE_TCP_WIN == 1 )
- BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );
-#endif /* ipconfigUSE_TCP_WIN == 1 */
-
/*
* Detaches and returns the head of a queue
*/
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowGetHead( List_t *pxList );
+ static TCPSegment_t *xTCPWindowGetHead( const List_t *pxList );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/*
* Returns the head of a queue but it won't be detached
*/
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList );
+ static TCPSegment_t *xTCPWindowPeekHead( const List_t *pxList );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/*
@@ -162,7 +150,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* segment should have a sequence number equal to '(ulSequenceNumber+xLength)'.
*/
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
+ static TCPSegment_t *xTCPWindowRxConfirm( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/*
@@ -178,7 +166,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* true if there is data to be sent.
*/
#if( ipconfigUSE_TCP_WIN == 1 )
- static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize );
+ static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/*
@@ -206,7 +194,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
/* List of free TCP segments. */
#if( ipconfigUSE_TCP_WIN == 1 )
- static List_t xSegmentList;
+ _static List_t xSegmentList;
#endif
/* Logging verbosity level. */
@@ -217,10 +205,20 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b )
{
+ BaseType_t xResult;
+
/* Test if a <= b
Return true if the unsigned subtraction of (b-a) doesn't generate an
arithmetic overflow. */
- return ( ( b - a ) & 0x80000000UL ) == 0UL;
+ if( ( ( b - a ) & 0x80000000UL ) == 0UL )
+ {
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
}
#endif /* ipconfigUSE_TCP_WIN */
/*-----------------------------------------------------------*/
@@ -229,8 +227,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b )
{
+ BaseType_t xResult;
+
/* Test if a < b */
- return ( ( b - a - 1UL ) & 0x80000000UL ) == 0UL;
+ if( ( ( b - ( a + 1UL ) ) & 0x80000000UL ) == 0UL )
+ {
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
}
#endif /* ipconfigUSE_TCP_WIN */
/*-----------------------------------------------------------*/
@@ -239,8 +247,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b )
{
+ BaseType_t xResult;
+
/* Test if a > b */
- return ( ( a - b - 1UL ) & 0x80000000UL ) == 0UL;
+ if( ( ( a - ( b + 1UL ) ) & 0x80000000UL ) == 0UL )
+ {
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
}
#endif /* ipconfigUSE_TCP_WIN */
@@ -248,8 +266,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b )
{
+BaseType_t xResult;
+
/* Test if a >= b */
- return ( ( a - b ) & 0x80000000UL ) == 0UL;
+ if( ( ( a - b ) & 0x80000000UL ) == 0UL )
+ {
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
}
/*-----------------------------------------------------------*/
@@ -269,30 +297,25 @@ static portINLINE void vTCPTimerSet( TCPTimer_t *pxTimer )
}
/*-----------------------------------------------------------*/
-static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer );
-static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer )
+static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t *pxTimer );
+static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t *pxTimer )
{
- return ( ( xTaskGetTickCount() - pxTimer->ulBorn ) * portTICK_PERIOD_MS );
+ return ( ( xTaskGetTickCount() - ( ( TickType_t ) pxTimer->ulBorn ) ) * portTICK_PERIOD_MS );
}
/*-----------------------------------------------------------*/
-/* _HT_ GCC (using the settings that I'm using) checks for every public function if it is
-preceded by a prototype. Later this prototype will be located in list.h? */
-
-extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
-
-void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere )
+static void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere )
{
/* Insert a new list item into pxList, it does not sort the list,
but it puts the item just before xListEnd, so it will be the last item
returned by listGET_HEAD_ENTRY() */
- pxNewListItem->pxNext = (struct xLIST_ITEM * configLIST_VOLATILE)pxWhere;
+ pxNewListItem->pxNext = ipPOINTER_CAST(struct xLIST_ITEM * configLIST_VOLATILE, pxWhere );
pxNewListItem->pxPrevious = pxWhere->pxPrevious;
pxWhere->pxPrevious->pxNext = pxNewListItem;
pxWhere->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */
- listLIST_ITEM_CONTAINER( pxNewListItem ) = ( void * ) pxList;
+ listLIST_ITEM_CONTAINER( pxNewListItem ) = ( struct xLIST * configLIST_VOLATILE )pxList;
( pxList->uxNumberOfItems )++;
}
@@ -307,29 +330,29 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
/* Allocate space for 'xTCPSegments' and store them in 'xSegmentList'. */
vListInitialise( &xSegmentList );
- xTCPSegments = ( TCPSegment_t * ) pvPortMallocLarge( ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );
+ xTCPSegments = ipPOINTER_CAST( TCPSegment_t *, pvPortMallocLarge( ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
if( xTCPSegments == NULL )
{
- FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %lu failed\n",
- ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
+ FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %u failed\n",
+ ( unsigned ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
xReturn = pdFAIL;
}
else
{
/* Clear the allocated space. */
- memset( xTCPSegments, '\0', ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );
+ ( void ) memset( xTCPSegments, 0, ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );
for( xIndex = 0; xIndex < ipconfigTCP_WIN_SEG_COUNT; xIndex++ )
{
/* Could call vListInitialiseItem here but all data has been
nulled already. Set the owner to a segment descriptor. */
- listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xListItem ), ( void* ) &( xTCPSegments[ xIndex ] ) );
- listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ( void* ) &( xTCPSegments[ xIndex ] ) );
+ listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xSegmentItem ), ipPOINTER_CAST( void *, &( xTCPSegments[ xIndex ] ) ) );
+ listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ipPOINTER_CAST( void *, &( xTCPSegments[ xIndex ] ) ) );
/* And add it to the pool of available segments */
- vListInsertFifo( &xSegmentList, &( xTCPSegments[xIndex].xListItem ) );
+ vListInsertFifo( &xSegmentList, &( xTCPSegments[xIndex].xSegmentItem ) );
}
xReturn = pdPASS;
@@ -343,22 +366,21 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )
+ static TCPSegment_t *xTCPWindowRxFind( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )
{
const ListItem_t *pxIterator;
- const MiniListItem_t* pxEnd;
+ const ListItem_t* pxEnd;
TCPSegment_t *pxSegment, *pxReturn = NULL;
/* Find a segment with a given sequence number in the list of received
segments. */
+ pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xRxSegments ) );
- pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xRxSegments );
-
- for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( const ListItem_t * ) pxEnd;
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
if( pxSegment->ulSequenceNumber == ulSequenceNumber )
{
@@ -386,7 +408,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
{
/* If the TCP-stack runs out of segments, you might consider
increasing 'ipconfigTCP_WIN_SEG_COUNT'. */
- FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", xIsForRx ? 'R' : 'T' ) );
+ FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", ( xIsForRx != 0 ) ? 'R' : 'T' ) );
pxSegment = NULL;
}
else
@@ -394,22 +416,29 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
/* Pop the item at the head of the list. Semaphore protection is
not required as only the IP task will call these functions. */
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( &xSegmentList );
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
configASSERT( pxItem != NULL );
configASSERT( pxSegment != NULL );
/* Remove the item from xSegmentList. */
- uxListRemove( pxItem );
+ ( void ) uxListRemove( pxItem );
/* Add it to either the connections' Rx or Tx queue. */
- vListInsertFifo( xIsForRx ? &pxWindow->xRxSegments : &pxWindow->xTxSegments, pxItem );
+ if( xIsForRx != 0 )
+ {
+ vListInsertFifo( &pxWindow->xRxSegments, pxItem );
+ }
+ else
+ {
+ vListInsertFifo( &pxWindow->xTxSegments, pxItem );
+ }
/* And set the segment's timer to zero */
vTCPTimerSet( &pxSegment->xTransmitTimer );
pxSegment->u.ulFlags = 0;
- pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 );
+ pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 ) ? 1U : 0U;
pxSegment->lMaxLength = lCount;
pxSegment->lDataLength = lCount;
pxSegment->ulSequenceNumber = ulSequenceNumber;
@@ -434,7 +463,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 )
- BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow )
+ BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow )
{
BaseType_t xReturn;
@@ -470,7 +499,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowGetHead( List_t *pxList )
+ static TCPSegment_t *xTCPWindowGetHead( const List_t *pxList )
{
TCPSegment_t *pxSegment;
ListItem_t * pxItem;
@@ -483,9 +512,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
else
{
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
- uxListRemove( pxItem );
+ ( void ) uxListRemove( pxItem );
}
return pxSegment;
@@ -496,9 +525,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList )
+ static TCPSegment_t *xTCPWindowPeekHead( const List_t *pxList )
{
- ListItem_t *pxItem;
+ const ListItem_t *pxItem;
TCPSegment_t *pxReturn;
/* Returns the head of a queue but it won't be detached. */
@@ -509,7 +538,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
else
{
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
- pxReturn = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );
+ pxReturn = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
}
return pxReturn;
@@ -528,21 +557,21 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
Unlink it from one of the queues, if any. */
if( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL )
{
- uxListRemove( &( pxSegment->xQueueItem ) );
+ ( void ) uxListRemove( &( pxSegment->xQueueItem ) );
}
- pxSegment->ulSequenceNumber = 0u;
- pxSegment->lDataLength = 0l;
- pxSegment->u.ulFlags = 0u;
+ pxSegment->ulSequenceNumber = 0UL;
+ pxSegment->lDataLength = 0L;
+ pxSegment->u.ulFlags = 0UL;
/* Take it out of xRxSegments/xTxSegments */
- if( listLIST_ITEM_CONTAINER( &( pxSegment->xListItem ) ) != NULL )
+ if( listLIST_ITEM_CONTAINER( &( pxSegment->xSegmentItem ) ) != NULL )
{
- uxListRemove( &( pxSegment->xListItem ) );
+ ( void ) uxListRemove( &( pxSegment->xSegmentItem ) );
}
/* Return it to xSegmentList */
- vListInsertFifo( &xSegmentList, &( pxSegment->xListItem ) );
+ vListInsertFifo( &xSegmentList, &( pxSegment->xSegmentItem ) );
}
#endif /* ipconfigUSE_TCP_WIN == 1 */
@@ -550,9 +579,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 )
- void vTCPWindowDestroy( TCPWindow_t *pxWindow )
+ void vTCPWindowDestroy( TCPWindow_t const * pxWindow )
{
- List_t * pxSegments;
+ const List_t * pxSegments;
BaseType_t xRound;
TCPSegment_t *pxSegment;
@@ -571,11 +600,11 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
pxSegments = &( pxWindow->xTxSegments );
}
- if( listLIST_IS_INITIALISED( pxSegments ) != pdFALSE )
+ if( listLIST_IS_INITIALISED( pxSegments ) )
{
while( listCURRENT_LIST_LENGTH( pxSegments ) > 0U )
{
- pxSegment = ( TCPSegment_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxSegments );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_OWNER_OF_HEAD_ENTRY( pxSegments ) );
vTCPWindowFree( pxSegment );
}
}
@@ -594,15 +623,15 @@ void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
{
if( xTCPSegments == NULL )
{
- prvCreateSectors();
+ ( void ) prvCreateSectors();
}
- vListInitialise( &pxWindow->xTxSegments );
- vListInitialise( &pxWindow->xRxSegments );
+ vListInitialise( &( pxWindow->xTxSegments ) );
+ vListInitialise( &( pxWindow->xRxSegments ) );
- vListInitialise( &pxWindow->xPriorityQueue ); /* Priority queue: segments which must be sent immediately */
- vListInitialise( &pxWindow->xTxQueue ); /* Transmit queue: segments queued for transmission */
- vListInitialise( &pxWindow->xWaitQueue ); /* Waiting queue: outstanding segments */
+ vListInitialise( &( pxWindow->xPriorityQueue ) ); /* Priority queue: segments which must be sent immediately */
+ vListInitialise( &( pxWindow->xTxQueue ) ); /* Transmit queue: segments queued for transmission */
+ vListInitialise( &( pxWindow->xWaitQueue ) ); /* Waiting queue: outstanding segments */
}
#endif /* ipconfigUSE_TCP_WIN == 1 */
@@ -623,17 +652,17 @@ void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSeq
{
const int32_t l500ms = 500;
- pxWindow->u.ulFlags = 0ul;
+ pxWindow->u.ulFlags = 0UL;
pxWindow->u.bits.bHasInit = pdTRUE_UNSIGNED;
- if( ulMSS != 0ul )
+ if( ulMSS != 0UL )
{
- if( pxWindow->usMSSInit != 0u )
+ if( pxWindow->usMSSInit != 0U )
{
pxWindow->usMSSInit = ( uint16_t ) ulMSS;
}
- if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0u ) )
+ if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0U ) )
{
pxWindow->xSize.ulRxWindowLength = ( pxWindow->xSize.ulRxWindowLength / ulMSS ) * ulMSS;
pxWindow->usMSS = ( uint16_t ) ulMSS;
@@ -707,12 +736,12 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 )
- static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength )
+ static TCPSegment_t *xTCPWindowRxConfirm( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength )
{
TCPSegment_t *pxBest = NULL;
const ListItem_t *pxIterator;
uint32_t ulNextSequenceNumber = ulSequenceNumber + ulLength;
- const MiniListItem_t* pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &pxWindow->xRxSegments );
+ const ListItem_t * pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xRxSegments ) );
TCPSegment_t *pxSegment;
/* A segment has been received with sequence number 'ulSequenceNumber',
@@ -724,11 +753,11 @@ const int32_t l500ms = 500;
'(ulSequenceNumber+ulLength)'. */
/* Iterate through all RX segments that are stored: */
- for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( const ListItem_t * ) pxEnd;
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )
+ for( pxIterator = listGET_NEXT( pxEnd );
+ pxIterator != pxEnd;
+ pxIterator = listGET_NEXT( pxIterator ) )
{
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* And see if there is a segment for which:
'ulSequenceNumber' <= 'pxSegment->ulSequenceNumber' < 'ulNextSequenceNumber'
If there are more matching segments, the one with the lowest sequence number
@@ -746,7 +775,6 @@ const int32_t l500ms = 500;
if( ( pxBest != NULL ) &&
( ( pxBest->ulSequenceNumber != ulSequenceNumber ) || ( pxBest->lDataLength != ( int32_t ) ulLength ) ) )
{
- FreeRTOS_flush_logging();
FreeRTOS_debug_printf( ( "xTCPWindowRxConfirm[%u]: search %lu (+%ld=%lu) found %lu (+%ld=%lu)\n",
pxWindow->usPeerPortNumber,
ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
@@ -783,10 +811,10 @@ const int32_t l500ms = 500;
ulCurrentSequenceNumber = pxWindow->rx.ulCurrentSequenceNumber;
/* For Selective Ack (SACK), used when out-of-sequence data come in. */
- pxWindow->ucOptionLength = 0u;
+ pxWindow->ucOptionLength = 0U;
/* Non-zero if TCP-windows contains data which must be popped. */
- pxWindow->ulUserDataLength = 0ul;
+ pxWindow->ulUserDataLength = 0UL;
if( ulCurrentSequenceNumber == ulSequenceNumber )
{
@@ -801,7 +829,7 @@ const int32_t l500ms = 500;
{
ulCurrentSequenceNumber += ulLength;
- if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0 )
+ if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0U )
{
ulSavedSequenceNumber = ulCurrentSequenceNumber;
@@ -818,12 +846,17 @@ const int32_t l500ms = 500;
/* Remove it because it will be passed to user directly. */
vTCPWindowFree( pxFound );
}
- } while ( pxFound );
+ } while ( pxFound != NULL );
/* Check for following segments that are already in the
queue and increment ulCurrentSequenceNumber. */
- while( ( pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber ) ) != NULL )
+ for( ;; )
{
+ pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber );
+ if( pxFound == NULL )
+ {
+ break;
+ }
ulCurrentSequenceNumber += ( uint32_t ) pxFound->lDataLength;
/* As all packet below this one have been passed to the
@@ -870,7 +903,9 @@ const int32_t l500ms = 500;
/* An "out-of-sequence" segment was received, must have missed one.
Prepare a SACK (Selective ACK). */
ulLast = ulSequenceNumber + ulLength;
- lDistance = ( int32_t ) ( ulLast - ulCurrentSequenceNumber );
+ /* The cast from unsigned long to signed long is on purpose.
+ The macro 'ipNUMERIC_CAST' will prevent PC-lint from complaining. */
+ lDistance = ipNUMERIC_CAST( int32_t, ulLast - ulCurrentSequenceNumber );
if( lDistance <= 0 )
{
@@ -895,19 +930,25 @@ const int32_t l500ms = 500;
* This is useful because subsequent packets will be SACK'd with
* single one message
*/
- while( ( pxFound = xTCPWindowRxFind( pxWindow, ulLast ) ) != NULL )
+ for( ;; )
{
+ pxFound = xTCPWindowRxFind( pxWindow, ulLast );
+ if( pxFound == NULL )
+ {
+ break;
+ }
ulLast += ( uint32_t ) pxFound->lDataLength;
}
if( xTCPWindowLoggingLevel >= 1 )
{
- FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %lu exp %lu (dist %ld) SACK to %lu\n",
- pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,
- ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
- ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
- ( BaseType_t ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */
- ulLast - pxWindow->rx.ulFirstSequenceNumber ) );
+ FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %u exp %u (dist %d) SACK to %u\n",
+ ( int ) pxWindow->usPeerPortNumber,
+ ( int ) pxWindow->usOurPortNumber,
+ ( unsigned ) ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
+ ( unsigned ) ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
+ ( unsigned ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */
+ ( unsigned ) ( ulLast - pxWindow->rx.ulFirstSequenceNumber ) ) );
}
/* Now prepare the SACK message.
@@ -921,7 +962,7 @@ const int32_t l500ms = 500;
pxWindow->ulOptionsData[2] = FreeRTOS_htonl( ulLast );
/* Which make 12 (3*4) option bytes. */
- pxWindow->ucOptionLength = 3 * sizeof( pxWindow->ulOptionsData[ 0 ] );
+ pxWindow->ucOptionLength = ( uint8_t ) ( 3U * sizeof( pxWindow->ulOptionsData[ 0 ] ) );
pxFound = xTCPWindowRxFind( pxWindow, ulSequenceNumber );
@@ -940,7 +981,7 @@ const int32_t l500ms = 500;
{
/* Can not send a SACK, because the segment cannot be
stored. */
- pxWindow->ucOptionLength = 0u;
+ pxWindow->ucOptionLength = 0U;
/* Needs to be stored but there is no segment
available. */
@@ -958,7 +999,7 @@ const int32_t l500ms = 500;
/* Return a positive value. The packet may be accepted
and stored but an earlier packet is still missing. */
- lReturn = ( int32_t ) ( ulSequenceNumber - ulCurrentSequenceNumber );
+ lReturn = ipNUMERIC_CAST( int32_t, ulSequenceNumber - ulCurrentSequenceNumber );
}
}
}
@@ -990,15 +1031,17 @@ const int32_t l500ms = 500;
static int32_t lTCPIncrementTxPosition( int32_t lPosition, int32_t lMax, int32_t lCount )
{
+ int32_t lReturn;
+
/* +TCP stores data in circular buffers. Calculate the next position to
store. */
- lPosition += lCount;
- if( lPosition >= lMax )
+ lReturn = lPosition + lCount;
+ if( lReturn >= lMax )
{
- lPosition -= lMax;
+ lReturn -= lMax;
}
- return lPosition;
+ return lReturn;
}
#endif /* ipconfigUSE_TCP_WIN == 1 */
@@ -1010,6 +1053,7 @@ const int32_t l500ms = 500;
{
int32_t lBytesLeft = ( int32_t ) ulLength, lToWrite;
int32_t lDone = 0;
+ int32_t lBufferIndex = lPosition;
TCPSegment_t *pxSegment = pxWindow->pxHeadSegment;
/* Puts a message in the Tx-window (after buffer size has been
@@ -1042,7 +1086,7 @@ const int32_t l500ms = 500;
lDone += lToWrite;
/* Some detailed logging, for those who're interested. */
- if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) )
+ if( ( xTCPWindowLoggingLevel >= 2 ) && ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
{
FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Add %4lu bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",
ulLength,
@@ -1055,7 +1099,7 @@ const int32_t l500ms = 500;
/* Calculate the next position in the circular data buffer, knowing
its maximum length 'lMax'. */
- lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite );
+ lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
}
}
}
@@ -1064,7 +1108,7 @@ const int32_t l500ms = 500;
{
/* The current transmission segment is full, create new segments as
needed. */
- pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, pxWindow->usMSS );
+ pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, ( int32_t ) pxWindow->usMSS );
if( pxSegment != NULL )
{
@@ -1073,9 +1117,9 @@ const int32_t l500ms = 500;
lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength );
pxSegment->lDataLength = lToWrite;
- pxSegment->lStreamPos = lPosition;
+ pxSegment->lStreamPos = lBufferIndex;
lBytesLeft -= lToWrite;
- lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite );
+ lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;
lDone += lToWrite;
@@ -1093,7 +1137,7 @@ const int32_t l500ms = 500;
pxWindow->pxHeadSegment = NULL;
}
- if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 )
+ if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
{
if( ( xTCPWindowLoggingLevel >= 3 ) ||
( ( xTCPWindowLoggingLevel >= 2 ) && ( pxWindow->pxHeadSegment != NULL ) ) )
@@ -1128,7 +1172,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 )
- BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow )
+ BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow )
{
return listLIST_IS_EMPTY( ( &pxWindow->xTxSegments) );
}
@@ -1138,11 +1182,12 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 )
- static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize )
+ static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize )
{
uint32_t ulTxOutstanding;
BaseType_t xHasSpace;
- TCPSegment_t *pxSegment;
+ const TCPSegment_t *pxSegment;
+ uint32_t ulNettSize;
/* This function will look if there is new transmission data. It will
return true if there is data to be sent. */
@@ -1167,10 +1212,10 @@ const int32_t l500ms = 500;
}
/* Subtract this from the peer's space. */
- ulWindowSize -= FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding );
+ ulNettSize = ulWindowSize - FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding );
/* See if the next segment may be sent. */
- if( ulWindowSize >= ( uint32_t ) pxSegment->lDataLength )
+ if( ulNettSize >= ( uint32_t ) pxSegment->lDataLength )
{
xHasSpace = pdTRUE;
}
@@ -1183,7 +1228,7 @@ const int32_t l500ms = 500;
more new segment of size MSS. xSize.ulTxWindowLength is the self-imposed
limitation of the transmission window (in case of many resends it
may be decreased). */
- if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) )
+ if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ( ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) ) )
{
xHasSpace = pdFALSE;
}
@@ -1197,13 +1242,13 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 )
- BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
+ BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
{
- TCPSegment_t *pxSegment;
+ TCPSegment_t const * pxSegment;
BaseType_t xReturn;
TickType_t ulAge, ulMaxAge;
- *pulDelay = 0u;
+ *pulDelay = 0U;
if( listLIST_IS_EMPTY( &pxWindow->xPriorityQueue ) == pdFALSE )
{
@@ -1225,7 +1270,7 @@ const int32_t l500ms = 500;
/* After a packet has been sent for the first time, it will wait
'1 * lSRTT' ms for an ACK. A second time it will wait '2 * lSRTT' ms,
each time doubling the time-out */
- ulMaxAge = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
+ ulMaxAge = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulMaxAge > ulAge )
{
@@ -1297,17 +1342,17 @@ const int32_t l500ms = 500;
if( pxSegment != NULL )
{
/* Do check the timing. */
- ulMaxTime = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
+ ulMaxTime = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulTimerGetAge( &pxSegment->xTransmitTimer ) > ulMaxTime )
{
/* A normal (non-fast) retransmission. Move it from the
head of the waiting queue. */
pxSegment = xTCPWindowGetHead( &( pxWindow->xWaitQueue ) );
- pxSegment->u.bits.ucDupAckCount = pdFALSE_UNSIGNED;
+ pxSegment->u.bits.ucDupAckCount = ( uint8_t ) pdFALSE_UNSIGNED;
/* Some detailed logging. */
- if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) )
+ if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: WaitQueue %ld bytes for sequence number %lu (%lX)\n",
pxWindow->usPeerPortNumber,
@@ -1363,7 +1408,7 @@ const int32_t l500ms = 500;
pxWindow->tx.ulHighestSequenceNumber = pxSegment->ulSequenceNumber + ( ( uint32_t ) pxSegment->lDataLength );
/* ...and more detailed logging */
- if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
+ if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: XmitQueue %ld bytes for sequence number %lu (ws %lu)\n",
pxWindow->usPeerPortNumber,
@@ -1395,6 +1440,8 @@ const int32_t l500ms = 500;
/* See if it has already been determined to return 0. */
if( ulReturn != 0UL )
{
+ /* pxSegment is not NULL when ulReturn != 0UL. */
+ configASSERT( pxSegment != NULL );
configASSERT( listLIST_ITEM_CONTAINER( &(pxSegment->xQueueItem ) ) == NULL );
/* Now that the segment will be transmitted, add it to the tail of
@@ -1412,11 +1459,13 @@ const int32_t l500ms = 500;
size of the transmission window to at most 2 times MSS. */
if( pxSegment->u.bits.ucTransmitCount == MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW )
{
- if( pxWindow->xSize.ulTxWindowLength > ( 2U * pxWindow->usMSS ) )
+ if( pxWindow->xSize.ulTxWindowLength > ( 2U * ( ( uint32_t ) pxWindow->usMSS ) ) )
{
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u - %d]: Change Tx window: %lu -> %u\n",
- pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,
- pxWindow->xSize.ulTxWindowLength, 2 * pxWindow->usMSS ) );
+ pxWindow->usPeerPortNumber,
+ pxWindow->usOurPortNumber,
+ pxWindow->xSize.ulTxWindowLength,
+ 2U * pxWindow->usMSS ) );
pxWindow->xSize.ulTxWindowLength = ( 2UL * pxWindow->usMSS );
}
}
@@ -1443,10 +1492,10 @@ const int32_t l500ms = 500;
static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )
{
- uint32_t ulBytesConfirmed = 0u;
+ uint32_t ulBytesConfirmed = 0U;
uint32_t ulSequenceNumber = ulFirst, ulDataLength;
const ListItem_t *pxIterator;
- const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xTxSegments );
+ const ListItem_t *pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xTxSegments ) );
BaseType_t xDoUnlink;
TCPSegment_t *pxSegment;
/* An acknowledgement or a selective ACK (SACK) was received. See if some outstanding data
@@ -1470,13 +1519,11 @@ const int32_t l500ms = 500;
A Smoothed RTT will increase quickly, but it is conservative when
becoming smaller. */
- for(
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- ( pxIterator != ( const ListItem_t * ) pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 );
- )
+ pxIterator = listGET_NEXT( pxEnd );
+ while( ( pxIterator != pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 ) )
{
xDoUnlink = pdFALSE;
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* Move to the next item because the current item might get
removed. */
@@ -1491,6 +1538,7 @@ const int32_t l500ms = 500;
/* Is it ready? */
if( ulSequenceNumber != pxSegment->ulSequenceNumber )
{
+ /* coverity[break_stmt] : Break statement terminating the loop */
break;
}
@@ -1515,16 +1563,16 @@ const int32_t l500ms = 500;
ulLast - pxWindow->tx.ulFirstSequenceNumber,
ulFirstSeq, ulFirstSeq + ulDataLength ) );
}
- #endif /* ipconfigHAS_DEBUG_PRINTF */
+ #endif /* ipconfigHAS_DEBUG_PRINTF */
break;
}
/* This segment is fully ACK'd, set the flag. */
- pxSegment->u.bits.bAcked = pdTRUE_UNSIGNED;
+ pxSegment->u.bits.bAcked = pdTRUE;
/* Calculate the RTT only if the segment was sent-out for the
first time and if this is the last ACK'd segment in a range. */
- if( ( pxSegment->u.bits.ucTransmitCount == 1 ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) )
+ if( ( pxSegment->u.bits.ucTransmitCount == 1U ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) )
{
int32_t mS = ( int32_t ) ulTimerGetAge( &( pxSegment->xTransmitTimer ) );
@@ -1554,7 +1602,7 @@ const int32_t l500ms = 500;
side of the transmission queue? If so, it may be freed. */
if( ulSequenceNumber == pxWindow->tx.ulCurrentSequenceNumber )
{
- if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
+ if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{
FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck: %lu - %lu Ready sequence number %lu\n",
ulFirst - pxWindow->tx.ulFirstSequenceNumber,
@@ -1579,7 +1627,7 @@ const int32_t l500ms = 500;
if( ( xDoUnlink != pdFALSE ) && ( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) )
{
/* Remove item from its queues. */
- uxListRemove( &pxSegment->xQueueItem );
+ ( void ) uxListRemove( &pxSegment->xQueueItem );
}
ulSequenceNumber += ulDataLength;
@@ -1594,52 +1642,57 @@ const int32_t l500ms = 500;
static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t *pxWindow, uint32_t ulFirst )
{
- const ListItem_t *pxIterator;
- const MiniListItem_t* pxEnd;
+ const ListItem_t * pxIterator;
+ const ListItem_t * pxEnd;
TCPSegment_t *pxSegment;
uint32_t ulCount = 0UL;
/* A higher Tx block has been acknowledged. Now iterate through the
xWaitQueue to find a possible condition for a FAST retransmission. */
- pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &( pxWindow->xWaitQueue ) );
+ pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &( pxWindow->xWaitQueue ) ) );
+
+ pxIterator = listGET_NEXT( pxEnd );
- for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
- pxIterator != ( const ListItem_t * ) pxEnd; )
+ while( pxIterator != pxEnd )
{
/* Get the owner, which is a TCP segment. */
- pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
+ pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* Hop to the next item before the current gets unlinked. */
- pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
+ pxIterator = listGET_NEXT( pxIterator );
/* Fast retransmission:
When 3 packets with a higher sequence number have been acknowledged
by the peer, it is very unlikely a current packet will ever arrive.
It will be retransmitted far before the RTO. */
- if( ( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED ) &&
- ( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE ) &&
- ( ++( pxSegment->u.bits.ucDupAckCount ) == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ) )
+ if( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED )
{
- pxSegment->u.bits.ucTransmitCount = pdFALSE_UNSIGNED;
-
- /* Not clearing 'ucDupAckCount' yet as more SACK's might come in
- which might lead to a second fast rexmit. */
- if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
+ if( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE )
{
- FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n",
- pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
- ulFirst - pxWindow->tx.ulFirstSequenceNumber ) );
- FreeRTOS_flush_logging( );
- }
+ pxSegment->u.bits.ucDupAckCount++;
+ if( pxSegment->u.bits.ucDupAckCount == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT )
+ {
+ pxSegment->u.bits.ucTransmitCount = ( uint8_t ) pdFALSE;
- /* Remove it from xWaitQueue. */
- uxListRemove( &pxSegment->xQueueItem );
+ /* Not clearing 'ucDupAckCount' yet as more SACK's might come in
+ which might lead to a second fast rexmit. */
+ if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
+ {
+ FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n",
+ pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
+ ulFirst - pxWindow->tx.ulFirstSequenceNumber ) );
+ FreeRTOS_flush_logging( );
+ }
- /* Add this segment to the priority queue so it gets
- retransmitted immediately. */
- vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) );
- ulCount++;
+ /* Remove it from xWaitQueue. */
+ ( void ) uxListRemove( &pxSegment->xQueueItem );
+ /* Add this segment to the priority queue so it gets
+ retransmitted immediately. */
+ vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) );
+ ulCount++;
+ }
+ }
}
}
@@ -1677,12 +1730,12 @@ const int32_t l500ms = 500;
uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )
{
- uint32_t ulAckCount = 0UL;
+ uint32_t ulAckCount;
uint32_t ulCurrentSequenceNumber = pxWindow->tx.ulCurrentSequenceNumber;
/* Receive a SACK option. */
ulAckCount = prvTCPWindowTxCheckAck( pxWindow, ulFirst, ulLast );
- prvTCPWindowFastRetransmit( pxWindow, ulFirst );
+ ( void ) prvTCPWindowFastRetransmit( pxWindow, ulFirst );
if( ( xTCPWindowLoggingLevel >= 1 ) && ( xSequenceGreaterThan( ulFirst, ulCurrentSequenceNumber ) != pdFALSE ) )
{
@@ -1810,15 +1863,15 @@ const int32_t l500ms = 500;
if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
{
/* As 'ucTransmitCount' has a minimum of 1, take 2 * RTT */
- ulMaxTime = ( ( uint32_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
+ ulMaxTime = ( ( uint32_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulTimerGetAge( &( pxSegment->xTransmitTimer ) ) < ulMaxTime )
{
- ulLength = 0ul;
+ ulLength = 0UL;
}
}
- if( ulLength != 0ul )
+ if( ulLength != 0UL )
{
pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;
pxSegment->u.bits.ucTransmitCount++;
@@ -1836,7 +1889,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
- BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow )
+ BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow )
{
BaseType_t xReturn;
@@ -1858,8 +1911,8 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
- static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize );
- static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize )
+ static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize );
+ static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize )
{
BaseType_t xReturn;
@@ -1880,9 +1933,9 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
- BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
+ BaseType_t xTCPWindowTxHasData( TCPWindow_t const *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
{
- TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );
+ TCPSegment_t const *pxSegment = &( pxWindow->xTxSegment );
BaseType_t xReturn;
TickType_t ulAge, ulMaxAge;
@@ -1898,7 +1951,7 @@ const int32_t l500ms = 500;
if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
{
ulAge = ulTimerGetAge ( &pxSegment->xTransmitTimer );
- ulMaxAge = ( ( TickType_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
+ ulMaxAge = ( ( TickType_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulMaxAge > ulAge )
{
@@ -1933,7 +1986,7 @@ const int32_t l500ms = 500;
/* Receive a normal ACK */
- if( ulDataLength != 0ul )
+ if( ulDataLength != 0UL )
{
if( ulSequenceNumber < ( pxWindow->tx.ulCurrentSequenceNumber + ulDataLength ) )
{
@@ -1946,7 +1999,7 @@ const int32_t l500ms = 500;
}
/* Nothing to send right now. */
- ulDataLength = 0ul;
+ ulDataLength = 0UL;
}
else
{
@@ -1971,7 +2024,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
- BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow )
+ BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow )
{
/* Return true if 'ulCurrentSequenceNumber >= ulHighestSequenceNumber'
'ulCurrentSequenceNumber' is the highest sequence number stored,
@@ -1985,7 +2038,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
/* Destroy a window (always returns NULL) */
- void vTCPWindowDestroy( TCPWindow_t *pxWindow )
+ void vTCPWindowDestroy( const TCPWindow_t *pxWindow )
{
/* As in tiny TCP there are no shared segments descriptors, there is
nothing to release. */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
index 6d67c113a..715a2b1c6 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
@@ -53,6 +53,7 @@
/* Part of the Ethernet and IP headers are always constant when sending an IPv4
UDP packet. This array defines the constant parts, allowing this part of the
packet to be filled in using a simple memcpy() instead of individual writes. */
+/*lint -e708 (Info -- union initialization). */
UDPPacketHeader_t xDefaultPartUDPPacketHeader =
{
/* .ucBytes : */
@@ -81,10 +82,10 @@ uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;
size_t uxPayloadSize;
/* Map the UDP packet onto the start of the frame. */
- pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
+ pxUDPPacket = ipPOINTER_CAST( UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
- if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )
+ if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{
uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( ICMPPacket_t );
}
@@ -112,7 +113,7 @@ size_t uxPayloadSize;
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/* Is it possible that the packet is not actually a UDP packet
after all, but an ICMP packet. */
- if( pxNetworkBuffer->usPort != ipPACKET_CONTAINS_ICMP_DATA )
+ if( pxNetworkBuffer->usPort != ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */
{
UDPHeader_t *pxUDPHeader;
@@ -123,7 +124,7 @@ size_t uxPayloadSize;
pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort;
pxUDPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( UDPHeader_t ) );
pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength );
- pxUDPHeader->usChecksum = 0u;
+ pxUDPHeader->usChecksum = 0U;
}
/* memcpy() the constant parts of the header information into
@@ -140,19 +141,23 @@ size_t uxPayloadSize;
and
xIPHeader.usHeaderChecksum
*/
+
/* Save options now, as they will be overwritten by memcpy */
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
+ {
ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];
+ }
#endif
/*
* Offset the memcpy by the size of a MAC address to start at the packet's
* Ethernet header 'source' MAC address; the preceding 'destination' should not be altered.
*/
- char *pxUdpSrcAddrOffset = ( char *) pxUDPPacket + sizeof( MACAddress_t );
- memcpy( pxUdpSrcAddrOffset, xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
+ /* The Ethernet source address is at offset 6. */
+ char *pxUdpSrcAddrOffset = ( char *) ( &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( MACAddress_t ) ] ) );
+ ( void ) memcpy( pxUdpSrcAddrOffset, xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1
- if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )
+ if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{
pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;
pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) );
@@ -164,7 +169,6 @@ size_t uxPayloadSize;
}
pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength );
- /* HT:endian: changed back to network endian */
pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress;
#if( ipconfigUSE_LLMNR == 1 )
@@ -180,17 +184,17 @@ size_t uxPayloadSize;
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
- pxIPHeader->usHeaderChecksum = 0u;
- pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = 0U;
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
- if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0u )
+ if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0U )
{
- usGenerateProtocolChecksum( (uint8_t*)pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
+ ( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
}
else
{
- pxUDPPacket->xUDPHeader.usChecksum = 0u;
+ pxUDPPacket->xUDPHeader.usChecksum = 0U;
}
}
#endif
@@ -228,14 +232,14 @@ size_t uxPayloadSize;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
- pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
+ pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
}
#endif
- xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
+ ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
}
else
{
@@ -250,16 +254,16 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
{
BaseType_t xReturn = pdPASS;
FreeRTOS_Socket_t *pxSocket;
-configASSERT(pxNetworkBuffer);
-configASSERT(pxNetworkBuffer->pucEthernetBuffer);
+configASSERT( pxNetworkBuffer != NULL );
+configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL );
-
-UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
+/* Map the ethernet buffer to the UDPPacket_t struct for easy access to the fields. */
+const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
/* Caller must check for minimum packet size. */
pxSocket = pxUDPSocketLookup( usPort );
- if( pxSocket )
+ if( pxSocket != NULL )
{
/* When refreshing the ARP cache with received UDP packets we must be
@@ -273,7 +277,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )
{
struct freertos_sockaddr xSourceAddress, destinationAddress;
- void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
+ void *pcData = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;
xSourceAddress.sin_port = pxNetworkBuffer->usPort;
xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;
@@ -281,16 +285,19 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;
/* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */
- if( xHandler( ( Socket_t ) pxSocket, ( void* ) pcData, ( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ),
- &xSourceAddress, &destinationAddress ) )
+ if( xHandler( ( Socket_t ) pxSocket,
+ ( void* ) pcData,
+ ( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ),
+ &( xSourceAddress ),
+ &( destinationAddress ) ) != 0 )
{
- xReturn = pdFAIL; /* FAIL means that we did not consume or release the buffer */
+ xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */
}
}
}
#endif /* ipconfigUSE_CALLBACKS */
- #if( ipconfigUDP_MAX_RX_PACKETS > 0 )
+ #if( ipconfigUDP_MAX_RX_PACKETS > 0U )
{
if( xReturn == pdPASS )
{
@@ -305,34 +312,35 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
}
#endif
- if( xReturn == pdPASS )
+ #if( ipconfigUSE_CALLBACKS == 1 ) || ( ipconfigUDP_MAX_RX_PACKETS > 0U )
+ if( xReturn == pdPASS ) /*lint !e774: Boolean within 'if' always evaluates to True, depending on configuration. [MISRA 2012 Rule 14.3, required. */
+ #else
+ /* xReturn is still pdPASS. */
+ #endif
{
vTaskSuspendAll();
{
- if( xReturn == pdPASS )
+ taskENTER_CRITICAL();
{
- taskENTER_CRITICAL();
- {
- /* Add the network packet to the list of packets to be
- processed by the socket. */
- vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );
- }
- taskEXIT_CRITICAL();
+ /* Add the network packet to the list of packets to be
+ processed by the socket. */
+ vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );
}
+ taskEXIT_CRITICAL();
}
- xTaskResumeAll();
+ ( void ) xTaskResumeAll();
/* Set the socket's receive event */
if( pxSocket->xEventGroup != NULL )
{
- xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );
+ ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
}
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
- if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) )
+ if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U ) )
{
- xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ );
+ ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_READ );
}
}
#endif
@@ -341,16 +349,16 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
{
if( pxSocket->pxUserSemaphore != NULL )
{
- xSemaphoreGive( pxSocket->pxUserSemaphore );
+ ( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
}
}
#endif
#if( ipconfigUSE_DHCP == 1 )
{
- if( xIsDHCPSocket( pxSocket ) )
+ if( xIsDHCPSocket( pxSocket ) != 0 )
{
- xSendEventToIPTask( eDHCPEvent );
+ ( void ) xSendEventToIPTask( eDHCPEvent );
}
}
#endif
@@ -366,7 +374,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
does open a UDP socket to send a messages, this socket will be
closed after a short timeout. Messages that come late (after the
socket is closed) will be treated here. */
- if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT )
+ if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ( uint16_t ) ipDNS_PORT )
{
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );
@@ -375,7 +383,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
#endif
#if( ipconfigUSE_LLMNR == 1 )
- /* a LLMNR request, check for the destination port. */
+ /* A LLMNR request, check for the destination port. */
if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )
{
@@ -395,9 +403,9 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
}
else
#endif /* ipconfigUSE_NBNS */
- {
- xReturn = pdFAIL;
- }
+ {
+ xReturn = pdFAIL;
+ }
}
return xReturn;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h
index d23410f5f..7194df3ee 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -36,6 +36,10 @@ will be removed. */
/* This file provides default values for configuration options that are missing
from the FreeRTOSIPConfig.h configuration header file. */
+/* These macros are used to define away static keyword for CBMC proofs */
+#ifndef _static
+ #define _static static
+#endif
/* Ensure defined configuration constants are using the most up to date naming. */
#ifdef tcpconfigIP_TIME_TO_LIVE
@@ -157,7 +161,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* This macro will only be used if FreeRTOS_debug_printf() is defined for logging
*/
#ifndef ipconfigTCP_MAY_LOG_PORT
- #define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23u )
+ #define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23U )
#endif
@@ -171,11 +175,11 @@ from the FreeRTOSIPConfig.h configuration header file. */
#ifndef ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS
- #define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u )
+ #define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 5000U )
#endif
#ifndef ipconfigDNS_SEND_BLOCK_TIME_TICKS
- #define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u )
+ #define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500U )
#endif
/*
* FreeRTOS debug logging routine (proposal)
@@ -196,7 +200,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif /* ifdef ipconfigHAS_DEBUG_PRINTF */
#ifndef FreeRTOS_debug_printf
- #define FreeRTOS_debug_printf( MSG ) do{} while(0)
+ #define FreeRTOS_debug_printf( MSG ) do{} while( ipFALSE_BOOL )
#define ipconfigHAS_DEBUG_PRINTF 0
#endif
@@ -217,7 +221,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif /* ifdef ipconfigHAS_PRINTF */
#ifndef FreeRTOS_printf
- #define FreeRTOS_printf( MSG ) do{} while(0)
+ #define FreeRTOS_printf( MSG ) do{} while( ipFALSE_BOOL )
#define ipconfigHAS_PRINTF 0
#endif
@@ -227,7 +231,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* An example of this is the netstat command, which produces many lines of logging
*/
#ifndef FreeRTOS_flush_logging
- #define FreeRTOS_flush_logging( ) do{} while(0)
+ #define FreeRTOS_flush_logging( ) do{} while( ipFALSE_BOOL )
#endif
/* Malloc functions. Within most applications of FreeRTOS, the couple
@@ -274,7 +278,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
- #define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20 ) )
+ #define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20U ) )
#endif
#ifndef ipconfigARP_CACHE_ENTRIES
@@ -282,11 +286,11 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigMAX_ARP_RETRANSMISSIONS
- #define ipconfigMAX_ARP_RETRANSMISSIONS ( 5u )
+ #define ipconfigMAX_ARP_RETRANSMISSIONS ( 5U )
#endif
#ifndef ipconfigMAX_ARP_AGE
- #define ipconfigMAX_ARP_AGE 150u
+ #define ipconfigMAX_ARP_AGE 150U
#endif
#ifndef ipconfigUSE_ARP_REVERSED_LOOKUP
@@ -301,6 +305,10 @@ from the FreeRTOSIPConfig.h configuration header file. */
#define ipconfigINCLUDE_FULL_INET_ADDR 1
#endif
+#ifndef ipconfigUSE_LINKED_RX_MESSAGES
+ #define ipconfigUSE_LINKED_RX_MESSAGES 0
+#endif
+
#ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 45
#endif
@@ -310,7 +318,30 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
- #define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
+ #define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
+#endif
+
+/* Configuration to control whether packets with IP options,
+ * received over the network, should be passed up to the
+ * software stack OR should be dropped.
+ * If set to 1, the stack accepts IP packets that contain IP options, but does
+ * not process the options (IP options are not supported).
+ * If set to 0, the stack will drop IP packets that contain IP options.
+ */
+#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
+ #define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
+#endif
+
+/* Configuration to control whether UDP packets with
+ * checksum value of zero should be passed up the software
+ * stack OR should be dropped.
+ * If set to 1, the stack will accept UDP packets that have their checksum
+ * value set to 0.
+ * If set to 0, the stack will drop UDP packets that have their checksum value
+ * set to 0.
+ */
+#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
+ #define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
#endif
#ifndef ipconfigUDP_TIME_TO_LIVE
@@ -326,7 +357,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* for each UDP socket.
* Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS
*/
- #define ipconfigUDP_MAX_RX_PACKETS 0u
+ #define ipconfigUDP_MAX_RX_PACKETS 0U
#endif
#ifndef ipconfigUSE_DHCP
@@ -359,7 +390,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif
#ifndef ipconfigTCP_MSS
- #define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER )
+ #define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) )
#endif
/* Each TCP socket has circular stream buffers for Rx and Tx, which
@@ -367,19 +398,19 @@ from the FreeRTOSIPConfig.h configuration header file. */
* The defaults for these size are defined here, although
* they can be overridden at runtime by using the setsockopt() call */
#ifndef ipconfigTCP_RX_BUFFER_LENGTH
- #define ipconfigTCP_RX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
+ #define ipconfigTCP_RX_BUFFER_LENGTH ( 4U * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif
/* Define the size of Tx stream buffer for TCP sockets */
#ifndef ipconfigTCP_TX_BUFFER_LENGTH
-# define ipconfigTCP_TX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
+# define ipconfigTCP_TX_BUFFER_LENGTH ( 4U * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif
#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD
#ifdef _WINDOWS_
- #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999 ) )
+ #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999U ) )
#else
- #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000 ) )
+ #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000U ) )
#endif /* _WINDOWS_ */
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
@@ -407,14 +438,22 @@ from the FreeRTOSIPConfig.h configuration header file. */
#ifndef ipconfigDNS_CACHE_NAME_LENGTH
/* Per https://tools.ietf.org/html/rfc1035, 253 is the maximum string length
of a DNS name. The following default accounts for a null terminator. */
- #define ipconfigDNS_CACHE_NAME_LENGTH 254
+ #define ipconfigDNS_CACHE_NAME_LENGTH 254U
#endif
#ifndef ipconfigDNS_CACHE_ENTRIES
#define ipconfigDNS_CACHE_ENTRIES 1
#endif
+
#endif /* ipconfigUSE_DNS_CACHE != 0 */
+/* When accessing services which have multiple IP addresses, setting this
+greater than 1 can improve reliability by returning different IP address
+answers on successive calls to FreeRTOS_gethostbyname(). */
+#ifndef ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY
+ #define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY 1
+#endif
+
#ifndef ipconfigCHECK_IP_QUEUE_SPACE
#define ipconfigCHECK_IP_QUEUE_SPACE 0
#endif
@@ -544,7 +583,7 @@ connections, hang protection can help reduce the impact of SYN floods. */
/* Non-activity timeout is expressed in seconds. */
#ifndef ipconfigTCP_HANG_PROTECTION_TIME
- #define ipconfigTCP_HANG_PROTECTION_TIME 30
+ #define ipconfigTCP_HANG_PROTECTION_TIME 30U
#endif
#ifndef ipconfigTCP_IP_SANITY
@@ -559,11 +598,15 @@ connections, hang protection can help reduce the impact of SYN floods. */
/* Expert option: define a value for 'ipBUFFER_PADDING'.
When 'ipconfigBUFFER_PADDING' equals 0,
'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */
- #define ipconfigBUFFER_PADDING 0
+ #define ipconfigBUFFER_PADDING 0U
#endif
#ifndef ipconfigPACKET_FILLER_SIZE
- #define ipconfigPACKET_FILLER_SIZE 2
+ #define ipconfigPACKET_FILLER_SIZE 2U
+#endif
+
+#ifndef ipconfigSELECT_USES_NOTIFY
+ #define ipconfigSELECT_USES_NOTIFY 0
#endif
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
index 363fca425..3615b68b5 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -42,7 +42,7 @@ extern "C" {
typedef struct xARP_CACHE_TABLE_ROW
{
uint32_t ulIPAddress; /* The IP address of an ARP cache entry. */
- MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */
+ MACAddress_t xMACAddress; /* The MAC address of an ARP cache entry. */
uint8_t ucAge; /* A value that is periodically decremented but can also be refreshed by active communication. The ARP cache entry is removed if the value reaches zero. */
uint8_t ucValid; /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */
} ARPCacheRow_t;
@@ -54,13 +54,6 @@ typedef enum
eCantSendPacket /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */
} eARPLookupResult_t;
-typedef enum
-{
- eNotFragment = 0, /* The IP packet being sent is not part of a fragment. */
- eFirstFragment, /* The IP packet being sent is the first in a set of fragmented packets. */
- eFollowingFragment /* The IP packet being sent is part of a set of fragmented packets. */
-} eIPFragmentStatus_t;
-
/*
* If ulIPAddress is already in the ARP cache table then reset the age of the
* entry back to its maximum value. If ulIPAddress is not already in the ARP
@@ -121,6 +114,23 @@ void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffe
*/
void vARPSendGratuitous( void );
+/* This function will check if the target IP-address belongs to this device.
+If so, the packet will be passed to the IP-stack, who will answer it.
+The function is to be called within the function xNetworkInterfaceOutput()
+in NetworkInterface.c as follows:
+
+ if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
+ {
+ / * The packet has been sent back to the IP-task.
+ * The IP-task will further handle it.
+ * Do not release the descriptor.
+ * /
+ return pdTRUE;
+ }
+ / * Send the packet as usual. * /
+*/
+BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend );
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
index a49909eb2..d70327d56 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -34,23 +34,53 @@ extern "C" {
#include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h"
-/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
-typedef enum eDHCP_PHASE
+#if( ipconfigUSE_DHCP_HOOK != 0 )
+ /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
+ typedef enum eDHCP_PHASE
+ {
+ eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */
+ eDHCPPhasePreRequest /* Driver is about to request DHCP an IP address. */
+ } eDHCPCallbackPhase_t;
+
+ /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
+ typedef enum eDHCP_ANSWERS
+ {
+ eDHCPContinue, /* Continue the DHCP process */
+ eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */
+ eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */
+ } eDHCPCallbackAnswer_t;
+#endif /* #if( ipconfigUSE_DHCP_HOOK != 0 ) */
+
+/* DHCP state machine states. */
+typedef enum
{
- eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */
- eDHCPPhasePreRequest, /* Driver is about to request DHCP an IP address. */
-#if( ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP != 0 )
- eDHCPPhasePreLLA, /* Driver is about to try get an LLA address */
-#endif /* ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP */
-} eDHCPCallbackPhase_t;
-
-/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
-typedef enum eDHCP_ANSWERS
+ eWaitingSendFirstDiscover = 0, /* Initial state. Send a discover the first time it is called, and reset all timers. */
+ eWaitingOffer, /* Either resend the discover, or, if the offer is forthcoming, send a request. */
+ eWaitingAcknowledge, /* Either resend the request. */
+ #if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
+ eGetLinkLayerAddress, /* When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */
+ #endif
+ eLeasedAddress, /* Resend the request at the appropriate time to renew the lease. */
+ eNotUsingLeasedAddress /* DHCP failed, and a default IP address is being used. */
+} eDHCPState_t;
+
+/* Hold information in between steps in the DHCP state machine. */
+struct xDHCP_DATA
{
- eDHCPContinue, /* Continue the DHCP process */
- eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */
- eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */
-} eDHCPCallbackAnswer_t;
+ uint32_t ulTransactionId;
+ uint32_t ulOfferedIPAddress;
+ uint32_t ulDHCPServerAddress;
+ uint32_t ulLeaseTime;
+ /* Hold information on the current timer state. */
+ TickType_t xDHCPTxTime;
+ TickType_t xDHCPTxPeriod;
+ /* Try both without and with the broadcast flag */
+ BaseType_t xUseBroadcast;
+ /* Maintains the DHCP state machine state. */
+ eDHCPState_t eDHCPState;
+};
+
+typedef struct xDHCP_DATA DHCPData_t;
/*
* NOT A PUBLIC API FUNCTION.
@@ -60,12 +90,14 @@ void vDHCPProcess( BaseType_t xReset );
/* Internal call: returns true if socket is the current DHCP socket */
BaseType_t xIsDHCPSocket( Socket_t xSocket );
-/* Prototype of the hook (or callback) function that must be provided by the
-application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for
-usage information:
-http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
-*/
-eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );
+#if( ipconfigUSE_DHCP_HOOK != 0 )
+ /* Prototype of the hook (or callback) function that must be provided by the
+ application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for
+ usage information:
+ http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
+ */
+ eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );
+#endif /* ( ipconfigUSE_DHCP_HOOK != 0 ) */
#ifdef __cplusplus
} /* extern "C" */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
index 0458d7621..0168d3477 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -43,9 +43,9 @@ extern "C" {
* The target IP address will be 224.0.0.252
*/
#if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
- #define ipLLMNR_IP_ADDR 0xE00000FC
+ #define ipLLMNR_IP_ADDR 0xE00000FCUL
#else
- #define ipLLMNR_IP_ADDR 0xFC0000E0
+ #define ipLLMNR_IP_ADDR 0xFC0000E0UL
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */
#define ipLLMNR_PORT 5355 /* Standard LLMNR port. */
@@ -55,18 +55,21 @@ extern "C" {
#define ipNBNS_PORT 137 /* NetBIOS Name Service. */
#define ipNBDGM_PORT 138 /* Datagram Service, not included. */
-/*
- * The following function should be provided by the user and return true if it
- * matches the domain name.
- */
-extern BaseType_t xApplicationDNSQueryHook( const char *pcName );
+#if( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 )
+ /*
+ * The following function should be provided by the user and return true if it
+ * matches the domain name.
+ */
+ extern BaseType_t xApplicationDNSQueryHook( const char *pcName );
+#endif /* ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) */
/*
* LLMNR is very similar to DNS, so is handled by the DNS routines.
*/
-uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
+uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t *pxNetworkBuffer );
#if( ipconfigUSE_LLMNR == 1 )
+ /* The LLMNR MAC address is 01:00:5e:00:00:fc */
extern const MACAddress_t xLLMNR_MacAdress;
#endif /* ipconfigUSE_LLMNR */
@@ -84,12 +87,13 @@ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
#if( ipconfigUSE_DNS_CACHE != 0 )
- /* Look for the indicated host name in the DNS cache. Returns the IPv4
- address if present, or 0x0 otherwise. */
+ /* Look for the indicated host name in the DNS cache. Returns the IPv4
+ address if present, or 0x0 otherwise. */
uint32_t FreeRTOS_dnslookup( const char *pcHostName );
- /* Remove all entries from the DNS cache. */
- void FreeRTOS_dnsclear();
+ /* Remove all entries from the DNS cache. */
+ void FreeRTOS_dnsclear( void );
+
#endif /* ipconfigUSE_DNS_CACHE != 0 */
#if( ipconfigDNS_USE_CALLBACKS != 0 )
@@ -104,18 +108,33 @@ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
* Asynchronous version of gethostbyname()
* xTimeout is in units of ms.
*/
- uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout );
+ uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t uxTimeout );
void FreeRTOS_gethostbyname_cancel( void *pvSearchID );
#endif
/*
- * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
- * FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:
- * _TBD_ Add URL
+ * Lookup a IPv4 node in a blocking-way.
+ * It returns a 32-bit IP-address, 0 when not found.
+ * gethostbyname() is already deprecated.
*/
uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
+#if( ipconfigDNS_USE_CALLBACKS == 1 )
+ /*
+ * The function vDNSInitialise() initialises the DNS module.
+ * It will be called "internally", by the IP-task.
+ */
+ void vDNSInitialise( void );
+#endif /* ( ipconfigDNS_USE_CALLBACKS == 1 ) */
+
+#if( ipconfigDNS_USE_CALLBACKS == 1 )
+ /*
+ * A function local to the library.
+ */
+ extern void vDNSCheckCallBack( void *pvSearchID );
+#endif
+
#ifdef __cplusplus
} /* extern "C" */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
index 46a215777..7b37f955e 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -30,36 +30,71 @@
extern "C" {
#endif
+#include "FreeRTOS.h"
+#include "task.h"
+
/* Application level configuration options. */
#include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h"
-/* Some constants defining the sizes of several parts of a packet */
-#define ipSIZE_OF_ETH_HEADER 14u
-#define ipSIZE_OF_IPv4_HEADER 20u
-#define ipSIZE_OF_IGMP_HEADER 8u
-#define ipSIZE_OF_ICMP_HEADER 8u
-#define ipSIZE_OF_UDP_HEADER 8u
-#define ipSIZE_OF_TCP_HEADER 20u
+#ifdef __COVERITY__
+ /* Coverity static checks don't like inlined functions.
+ As it is up to the users to allow inlining, don't let
+ let Coverity know about it. */
+
+ #ifdef portINLINE
+ /* The usage of #undef violates the rule. */
+ #undef portINLINE
+
+ #endif
+
+ #define portINLINE
+#endif
+
+/* Some constants defining the sizes of several parts of a packet.
+These defines come before inlucding the configuration header files. */
+/* The size of the Ethernet header is 14, meaning that 802.1Q VLAN tags
+are not ( yet ) supported. */
+#define ipSIZE_OF_ETH_HEADER 14U
+#define ipSIZE_OF_IPv4_HEADER 20U
+#define ipSIZE_OF_IGMP_HEADER 8U
+#define ipSIZE_OF_ICMP_HEADER 8U
+#define ipSIZE_OF_UDP_HEADER 8U
+#define ipSIZE_OF_TCP_HEADER 20U
+#define ipSIZE_OF_IPv4_ADDRESS 4U
+
+/*
+ * Generate a randomized TCP Initial Sequence Number per RFC.
+ * This function must be provided by the application builder.
+ */
+/* This function is defined generally by the application. */
+extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
+ uint16_t usSourcePort,
+ uint32_t ulDestinationAddress,
+ uint16_t usDestinationPort );
/* The number of octets in the MAC and IP addresses respectively. */
#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )
#define ipIP_ADDRESS_LENGTH_BYTES ( 4 )
/* IP protocol definitions. */
-#define ipPROTOCOL_ICMP ( 1 )
-#define ipPROTOCOL_IGMP ( 2 )
-#define ipPROTOCOL_TCP ( 6 )
-#define ipPROTOCOL_UDP ( 17 )
+#define ipPROTOCOL_ICMP ( 1U )
+#define ipPROTOCOL_IGMP ( 2U )
+#define ipPROTOCOL_TCP ( 6U )
+#define ipPROTOCOL_UDP ( 17U )
+
+/* The character used to fill ICMP echo requests, and therefore also the
+character expected to fill ICMP echo replies. */
+#define ipECHO_DATA_FILL_BYTE 'x'
/* Dimensions the buffers that are filled by received Ethernet frames. */
#define ipSIZE_OF_ETH_CRC_BYTES ( 4UL )
#define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ( 4UL )
#define ipTOTAL_ETHERNET_FRAME_SIZE ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )
-/*_RB_ Comment may need updating. */
+
/* Space left at the beginning of a network buffer storage area to store a
pointer back to the network buffer. Should be a multiple of 8 to ensure 8 byte
alignment is maintained on architectures that require it.
@@ -77,10 +112,11 @@ buffer will have the following contents:
uint8_t ucVersionHeaderLength;
etc
*/
+
#if( ipconfigBUFFER_PADDING != 0 )
#define ipBUFFER_PADDING ipconfigBUFFER_PADDING
#else
- #define ipBUFFER_PADDING ( 8u + ipconfigPACKET_FILLER_SIZE )
+ #define ipBUFFER_PADDING ( 8U + ipconfigPACKET_FILLER_SIZE )
#endif
/* The structure used to store buffers and pass them around the network stack.
@@ -114,6 +150,8 @@ typedef enum eNETWORK_EVENTS
eNetworkDown /* The network connection has been lost. */
} eIPCallbackEvent_t;
+/* MISRA check: some modules refer to this typedef even though
+ipconfigSUPPORT_OUTGOING_PINGS is not enabled. */
typedef enum ePING_REPLY_STATUS
{
eSuccess = 0, /* A correct reply has been received for an outgoing ping. */
@@ -121,12 +159,15 @@ typedef enum ePING_REPLY_STATUS
eInvalidData /* A reply was received to an outgoing ping but the payload of the reply was not correct. */
} ePingReplyStatus_t;
-typedef enum eNETWORK_ADDRESS_TYPE
+typedef struct xIP_TIMER
{
- eNetWorkAddressTypeIPV4,
- eNetWorkAddressTypeIPV6,
- eNetWorkAddressTypeHostName
-} eNetWorkAddressType_t;
+ uint32_t
+ bActive : 1, /* This timer is running and must be processed. */
+ bExpired : 1; /* Timer has expired and a task must be processed. */
+ TimeOut_t xTimeOut;
+ TickType_t ulRemainingTime;
+ TickType_t ulReloadTime;
+} IPTimer_t;
/* Endian related definitions. */
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
@@ -169,52 +210,45 @@ typedef enum eNETWORK_ADDRESS_TYPE
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d);
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d);
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b);
- static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b);
- static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b);
- static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b);
-
- static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return a >= b ? a : b; }
- static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return a >= b ? a : b; }
- static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return a <= b ? a : b; }
- static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return a <= b ? a : b; }
- static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1u ) / d ); }
+ static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return ( a >= b ) ? a : b; }
+ static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return ( a >= b ) ? a : b; }
+ static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return ( a <= b ) ? a : b; }
+ static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return ( a <= b ) ? a : b; }
+ static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1U ) / d ); }
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); }
- static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b) { return a >= b ? a : b; }
- static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b) { return a >= b ? a : b; }
- static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return a <= b ? a : b; }
- static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b) { return a <= b ? a : b; }
+ static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return ( a <= b ) ? a : b; }
#else
- #define FreeRTOS_max_int32(a,b) ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) )
- #define FreeRTOS_max_uint32(a,b) ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )
+ #define FreeRTOS_max_int32(a,b) ( ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) )
+ #define FreeRTOS_max_uint32(a,b) ( ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )
- #define FreeRTOS_min_int32(a,b) ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) )
- #define FreeRTOS_min_uint32(a,b) ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )
+ #define FreeRTOS_min_int32(a,b) ( ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) )
+ #define FreeRTOS_min_uint32(a,b) ( ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )
- /* Round-up: a = d * ( ( a + d - 1 ) / d ) */
+ /* Round-up: divide a by d and round=up the result. */
#define FreeRTOS_round_up(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) )
#define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) )
- #define FreeRTOS_ms_to_tick(ms) ( ( ms * configTICK_RATE_HZ + 500 ) / 1000 )
-
- #define FreeRTOS_max_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) >= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
- #define FreeRTOS_max_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) >= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#define FreeRTOS_min_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
- #define FreeRTOS_min_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) <= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#endif /* ipconfigHAS_INLINE_FUNCTIONS */
-#define pdMS_TO_MIN_TICKS( xTimeInMs ) ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1 ) ? ( ( TickType_t ) 1 ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
+#define ipMS_TO_MIN_TICKS( xTimeInMs ) ( ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1U ) ) ? ( ( TickType_t ) 1U ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
+
+/* For backward compatibility. */
+#define pdMS_TO_MIN_TICKS( xTimeInMs ) ipMS_TO_MIN_TICKS( xTimeInMs )
#ifndef pdTRUE_SIGNED
/* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */
#define pdTRUE_SIGNED pdTRUE
#define pdFALSE_SIGNED pdFALSE
- #define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1u )
- #define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0u )
+ #define pdTRUE_UNSIGNED ( 1U )
+ #define pdFALSE_UNSIGNED ( 0U )
+ #define ipTRUE_BOOL ( 1 == 1 )
+ #define ipFALSE_BOOL ( 1 == 2 )
#endif
/*
@@ -228,15 +262,31 @@ BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
-void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );
-void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress );
-void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress );
-BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks );
-void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer );
+void * FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes, TickType_t uxBlockTimeTicks );
+void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress,
+ uint32_t *pulNetMask,
+ uint32_t *pulGatewayAddress,
+ uint32_t *pulDNSServerAddress );
+
+void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress,
+ const uint32_t *pulNetMask,
+ const uint32_t *pulGatewayAddress,
+ const uint32_t *pulDNSServerAddress );
+
+/* MISRA defining 'FreeRTOS_SendPingRequest' should be dependent on 'ipconfigSUPPORT_OUTGOING_PINGS'.
+In order not to break some existing project, define it unconditionally. */
+BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t uxNumberOfBytesToSend, TickType_t uxBlockTimeTicks );
+
+void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer );
const uint8_t * FreeRTOS_GetMACAddress( void );
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] );
-void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
-void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
+#if( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
+ /* This function shall be defined by the application. */
+ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
+#endif
+#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
+ void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
+#endif
uint32_t FreeRTOS_GetIPAddress( void );
void FreeRTOS_SetIPAddress( uint32_t ulIPAddress );
void FreeRTOS_SetNetmask( uint32_t ulNetmask );
@@ -251,6 +301,12 @@ BaseType_t FreeRTOS_IsNetworkUp( void );
UBaseType_t uxGetMinimumIPQueueSpace( void );
#endif
+#if ( ipconfigHAS_PRINTF != 0 )
+ extern void vPrintResourceStats( void );
+#else
+ #define vPrintResourceStats() do {} while( ipFALSE_BOOL )
+#endif
+
/*
* Defined in FreeRTOS_Sockets.c
* //_RB_ Don't think this comment is correct. If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.
@@ -264,12 +320,19 @@ const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState);
void FreeRTOS_PrintARPCache( void );
void FreeRTOS_ClearARP( void );
+/* Return pdTRUE if the IPv4 address is a multicast address. */
+BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress );
+
+/* Set the MAC-address that belongs to a given IPv4 multi-cast address. */
+void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress, MACAddress_t *pxMACAddress );
+
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
/* DHCP has an option for clients to register their hostname. It doesn't
have much use, except that a device can be found in a router along with its
name. If this option is used the callback below must be provided by the
application writer to return a const string, denoting the device's name. */
+ /* Typically this function is defined in a user module. */
const char *pcApplicationHostnameHook( void );
#endif /* ipconfigDHCP_REGISTER_HOSTNAME */
@@ -282,7 +345,9 @@ The function is defined in 'iot_secure_sockets.c'.
If that module is not included in the project, the application must provide an
implementation of it.
The macro's ipconfigRAND32() and configRAND32() are not in use anymore. */
-BaseType_t xApplicationGetRandomNumber( uint32_t *pulNumber );
+/* "xApplicationGetRandomNumber" is declared but never defined, because it may
+be defined in a user module. */
+extern BaseType_t xApplicationGetRandomNumber( uint32_t *pulNumber );
/* For backward compatibility define old structure names to the newer equivalent
structure name. */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h
index 0d8c03872..e59ee63da 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -41,6 +41,8 @@ extern "C" {
#include "FreeRTOS_TCP_IP.h"
#endif
+#include "semphr.h"
+
#include "event_groups.h"
typedef struct xNetworkAddressingParameters
@@ -53,6 +55,7 @@ typedef struct xNetworkAddressingParameters
} NetworkAddressingParameters_t;
extern BaseType_t xTCPWindowLoggingLevel;
+extern QueueHandle_t xNetworkEventQueue;
/*-----------------------------------------------------------*/
/* Protocol headers. */
@@ -102,17 +105,6 @@ struct xIP_HEADER
typedef struct xIP_HEADER IPHeader_t;
#include "pack_struct_start.h"
-struct xIGMP_HEADER
-{
- uint8_t ucVersionType; /* 0 + 1 = 1 */
- uint8_t ucMaxResponseTime; /* 1 + 1 = 2 */
- uint16_t usChecksum; /* 2 + 2 = 4 */
- uint32_t usGroupAddress; /* 4 + 4 = 8 */
-}
-#include "pack_struct_end.h"
-typedef struct xIGMP_HEADER IGMPHeader_t;
-
-#include "pack_struct_start.h"
struct xICMP_HEADER
{
uint8_t ucTypeOfMessage; /* 0 + 1 = 1 */
@@ -155,18 +147,6 @@ struct xTCP_HEADER
#include "pack_struct_end.h"
typedef struct xTCP_HEADER TCPHeader_t;
-#include "pack_struct_start.h"
-struct xPSEUDO_HEADER
-{
- uint32_t ulSourceAddress;
- uint32_t ulDestinationAddress;
- uint8_t ucZeros;
- uint8_t ucProtocol;
- uint16_t usUDPLength;
-}
-#include "pack_struct_end.h"
-typedef struct xPSEUDO_HEADER PseudoHeader_t;
-
/*-----------------------------------------------------------*/
/* Nested protocol packets. */
/*-----------------------------------------------------------*/
@@ -227,6 +207,13 @@ typedef union XPROT_PACKET
ICMPPacket_t xICMPPacket;
} ProtocolPacket_t;
+typedef union xPROT_HEADERS
+{
+ ICMPHeader_t xICMPHeader;
+ UDPHeader_t xUDPHeader;
+ TCPHeader_t xTCPHeader;
+} ProtocolHeaders_t;
+
/* The maximum UDP payload length. */
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )
@@ -281,18 +268,6 @@ setting. */
/* The offset into an IP packet into which the IP data (payload) starts. */
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
-#include "pack_struct_start.h"
-struct xUDP_IP_FRAGMENT_PARAMETERS
-{
- uint8_t ucSocketOptions;
- uint8_t ucPadFor16BitAlignment;
- uint16_t usFragmentedPacketOffset;
- uint16_t usFragmentLength;
- uint16_t usPayloadChecksum;
-}
-#include "pack_struct_end.h"
-typedef struct xUDP_IP_FRAGMENT_PARAMETERS IPFragmentParameters_t;
-
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
/* Ethernet frame types. */
@@ -339,7 +314,8 @@ extern NetworkAddressingParameters_t xNetworkAddressing;
/* Structure that stores the defaults for netmask, gateway address and DNS.
These values will be copied to 'xNetworkAddressing' in case DHCP is not used,
and also in case DHCP does not lead to a confirmed request. */
-extern NetworkAddressingParameters_t xDefaultAddressing;
+/*lint -e9003*/
+extern NetworkAddressingParameters_t xDefaultAddressing; /*lint !e9003 could define variable 'xDefaultAddressing' at block scope [MISRA 2012 Rule 8.9, advisory]. */
/* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */
extern const BaseType_t xBufferAllocFixedSize;
@@ -351,11 +327,43 @@ extern const BaseType_t xBufferAllocFixedSize;
/* The local IP address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */
-#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20u / sizeof(uint32_t) ] ) )
+#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20U / sizeof(uint32_t) ] ) )
/* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */
-#define ipLOCAL_MAC_ADDRESS ( &xDefaultPartUDPPacketHeader.ucBytes[0] )
+#define ipLOCAL_MAC_ADDRESS ( xDefaultPartUDPPacketHeader.ucBytes )
+
+/* In this library, there is often a cast from a character pointer
+ * to a pointer to a struct.
+ * In order to suppress MISRA warnings, do the cast within a macro,
+ * which can be exempt from warnings:
+ *
+ * 3 required by MISRA:
+ * -emacro(740,ipPOINTER_CAST) // 750: Unusual pointer cast (incompatible indirect types) [MISRA 2012 Rule 1.3, required])
+ * -emacro(9005,ipPOINTER_CAST) // 9005: attempt to cast away const/volatile from a pointer or reference [MISRA 2012 Rule 11.8, required]
+ * -emacro(9087,ipPOINTER_CAST) // 9087: cast performed between a pointer to object type and a pointer to a different object type [MISRA 2012 Rule 11.3, required]
+ *
+ * 2 advisory by MISRA:
+ * -emacro(9079,ipPOINTER_CAST) // 9079: conversion from pointer to void to pointer to other type [MISRA 2012 Rule 11.5, advisory])
+ * --emacro((826),ipPOINTER_CAST) // 826: Suspicious pointer-to-pointer conversion (area too small)
+ *
+ * The MISRA warnings can safely be suppressed because all casts are planned with care.
+ */
+
+#define ipPOINTER_CAST( TYPE, pointer ) ( ( TYPE ) ( pointer ) )
+
+/* Sequence and ACK numbers are essentially unsigned (uint32_t). But when
+ * a distance is calculated, it is useful to use signed numbers:
+ * int32_t lDistance = ( int32_t ) ( ulSeq1 - ulSeq2 );
+ *
+ * 1 required by MISRA:
+ * -emacro(9033,ipNUMERIC_CAST) // 9033: Impermissible cast of composite expression (different essential type categories) [MISRA 2012 Rule 10.8, required])
+ *
+ * 1 advisory by MISRA:
+ * -emacro(9030,ipNUMERIC_CAST) // 9030: Impermissible cast; cannot cast from 'essentially Boolean' to 'essentially signed' [MISRA 2012 Rule 10.5, advisory])
+ */
+
+#define ipNUMERIC_CAST( TYPE, expression ) ( ( TYPE ) ( expression ) )
/* ICMP packets are sent using the same function as UDP packets. The port
number is used to distinguish between the two, as 0 is an invalid UDP port. */
@@ -368,15 +376,15 @@ socket events. */
#define vSetField16( pxBase, xType, xField, usValue ) \
{ \
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \
- ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xff ); \
+ ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xffU ); \
}
#define vSetField32( pxBase, xType, xField, ulValue ) \
{ \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 ); \
- ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xff ); \
- ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xff ); \
- ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xff ); \
+ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xffU ); \
+ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xffU ); \
+ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xffU ); \
}
#define vFlip_16( left, right ) \
@@ -384,17 +392,18 @@ socket events. */
uint16_t tmp = (left); \
(left) = (right); \
(right) = tmp; \
- } while (0)
+ } while ( ipFALSE_BOOL )
#define vFlip_32( left, right ) \
do { \
uint32_t tmp = (left); \
(left) = (right); \
(right) = tmp; \
- } while (0)
+ } while ( ipFALSE_BOOL )
+/* WARNING: Do NOT use this macro when the array was received as a parameter. */
#ifndef ARRAY_SIZE
- #define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
+ #define ARRAY_SIZE(x) ( ( BaseType_t ) ( sizeof( x ) / sizeof( ( x )[ 0 ] ) ) )
#endif
/*
@@ -434,11 +443,11 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
/*
* Return the checksum generated over xDataLengthBytes from pucNextData.
*/
-uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes );
+uint16_t usGenerateChecksum( uint16_t usSum, const uint8_t * pucNextData, size_t uxByteCount );
/* Socket related private functions. */
-/*
+/*
* The caller must ensure that pxNetworkBuffer->xDataLength is the UDP packet
* payload size (excluding packet headers) and that the packet in pucEthernetBuffer
* is at least the size of UDPPacket_t.
@@ -448,7 +457,7 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
/*
* Initialize the socket list data structures for TCP and UDP.
*/
-BaseType_t vNetworkSocketsInit( void );
+void vNetworkSocketsInit( void );
/*
* Returns pdTRUE if the IP task has been created and is initialised. Otherwise
@@ -601,7 +610,8 @@ typedef struct UDPSOCKET
#endif /* ipconfigUSE_CALLBACKS */
} IPUDPSocket_t;
-typedef enum eSOCKET_EVENT {
+/* Formally typedef'd as eSocketEvent_t. */
+enum eSOCKET_EVENT {
eSOCKET_RECEIVE = 0x0001,
eSOCKET_SEND = 0x0002,
eSOCKET_ACCEPT = 0x0004,
@@ -610,7 +620,7 @@ typedef enum eSOCKET_EVENT {
eSOCKET_CLOSED = 0x0020,
eSOCKET_INTR = 0x0040,
eSOCKET_ALL = 0x007F,
-} eSocketEvent_t;
+};
typedef struct xSOCKET
{
@@ -695,7 +705,7 @@ void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType
* The TCP driver needs to bind a socket at the moment a listening socket
* creates a new connected socket
*/
-BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal );
+BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxBindAddress, size_t uxAddressLength, BaseType_t xInternal );
/*
* Internal function to add streaming data to a TCP socket. If ulIn == true,
@@ -712,7 +722,10 @@ int32_t lTCPAddRxdata(FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_
void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket );
/*
- * Some helping function, their meaning should be clear
+ * Some helping function, their meaning should be clear.
+ * Going by MISRA rules, these utility functions should not be defined
+ * if they are not being used anywhwere. But their use depends on the
+ * application and hence these functions are defined unconditionally.
*/
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr);
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr)
@@ -753,13 +766,13 @@ BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );
* eIPEvent_t eEventType;
* void *pvData;
*/
-BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout );
+BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t uxTimeout );
/*
* Returns a pointer to the original NetworkBuffer from a pointer to a UDP
* payload buffer.
*/
-NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer );
+NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( const void * pvBuffer );
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
/*
@@ -778,9 +791,6 @@ NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )
void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState );
#endif /* ipconfigUSE_TCP */
-/*_RB_ Should this be part of the public API? */
-void FreeRTOS_netstat( void );
-
/* Returns pdTRUE is this function is called from the IP-task */
BaseType_t xIsCallingFromIPTask( void );
@@ -789,11 +799,16 @@ BaseType_t xIsCallingFromIPTask( void );
typedef struct xSOCKET_SET
{
EventGroupHandle_t xSelectGroup;
- BaseType_t bApiCalled; /* True if the API was calling the private vSocketSelect */
- FreeRTOS_Socket_t *pxSocket;
} SocketSelect_t;
-extern void vSocketSelect( SocketSelect_t *pxSocketSelect );
+extern void vSocketSelect( SocketSelect_t *pxSocketSet );
+
+/* Define the data that must be passed for a 'eSocketSelectEvent'. */
+typedef struct xSocketSelectMessage
+{
+ TaskHandle_t xTaskhandle;
+ SocketSelect_t *pxSocketSet;
+} SocketSelectMessage_t;
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h
index 926ccebbd..a6329ebc3 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -180,6 +180,8 @@ struct freertos_sockaddr
uint32_t sin_addr;
};
+extern const char *FreeRTOS_inet_ntoa( uint32_t ulIPAddress, char *pcBuffer );
+
#if ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
@@ -188,13 +190,6 @@ struct freertos_sockaddr
( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet0 ) ) )
- #define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
- sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
- ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \
- ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
- ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
- ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) )
-
#else /* ipconfigBYTE_ORDER */
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
@@ -203,23 +198,19 @@ struct freertos_sockaddr
( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet3 ) ) )
- #define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
- sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
- ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \
- ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
- ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
- ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) )
-
#endif /* ipconfigBYTE_ORDER */
/* The socket type itself. */
struct xSOCKET;
typedef struct xSOCKET *Socket_t;
+typedef struct xSOCKET const * ConstSocket_t;
-/* The SocketSet_t type is the equivalent to the fd_set type used by the
-Berkeley API. */
-struct xSOCKET_SET;
-typedef struct xSOCKET_SET *SocketSet_t;
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
+ /* The SocketSet_t type is the equivalent to the fd_set type used by the
+ Berkeley API. */
+ struct xSOCKET_SET;
+ typedef struct xSOCKET_SET *SocketSet_t;
+#endif /* ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) */
/**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
@@ -227,21 +218,23 @@ typedef struct xSOCKET_SET *SocketSet_t;
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html
*/
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );
-int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
-int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
-BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
+int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
+int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t uxTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
+BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr const * pxAddress, socklen_t xAddressLength );
/* function to get the local address and IP port */
-size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
+size_t FreeRTOS_GetLocalAddress( ConstSocket_t xSocket, struct freertos_sockaddr *pxAddress );
-/* Made available when ipconfigETHERNET_DRIVER_FILTERS_PACKETS is set to 1. */
-BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
+#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
+ /* Returns true if an UDP socket exists bound to mentioned port number. */
+ BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
+#endif
#if ipconfigUSE_TCP == 1
BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog );
-BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags );
+BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags );
BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags );
Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength );
BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
@@ -256,28 +249,34 @@ BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
#endif /* ipconfigSUPPORT_SIGNALS */
/* Return the remote address and IP port. */
-BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
+BaseType_t FreeRTOS_GetRemoteAddress( ConstSocket_t xSocket, struct freertos_sockaddr *pxAddress );
+
+#if( ipconfigUSE_TCP == 1 )
+
+ /* Returns pdTRUE if TCP socket is connected. */
+ BaseType_t FreeRTOS_issocketconnected( ConstSocket_t xSocket );
-/* returns pdTRUE if TCP socket is connected */
-BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket );
+ /* Returns the actual size of MSS being used. */
+ BaseType_t FreeRTOS_mss( ConstSocket_t xSocket );
-/* returns the actual size of MSS being used */
-BaseType_t FreeRTOS_mss( Socket_t xSocket );
+#endif
-/* for internal use only: return the connection status */
-BaseType_t FreeRTOS_connstatus( Socket_t xSocket );
+/* For internal use only: return the connection status. */
+BaseType_t FreeRTOS_connstatus( ConstSocket_t xSocket );
/* Returns the number of bytes that may be added to txStream */
-BaseType_t FreeRTOS_maywrite( Socket_t xSocket );
+BaseType_t FreeRTOS_maywrite( ConstSocket_t xSocket );
/*
* Two helper functions, mostly for testing
* rx_size returns the number of bytes available in the Rx buffer
* tx_space returns the free space in the Tx buffer
*/
-BaseType_t FreeRTOS_rx_size( Socket_t xSocket );
-BaseType_t FreeRTOS_tx_space( Socket_t xSocket );
-BaseType_t FreeRTOS_tx_size( Socket_t xSocket );
+#if( ipconfigUSE_TCP == 1 )
+ BaseType_t FreeRTOS_rx_size( ConstSocket_t xSocket );
+ BaseType_t FreeRTOS_tx_space( ConstSocket_t xSocket );
+ BaseType_t FreeRTOS_tx_size( ConstSocket_t xSocket );
+#endif
/* Returns the number of outstanding bytes in txStream. */
/* The function FreeRTOS_outstanding() was already implemented
@@ -294,67 +293,97 @@ FreeRTOS_rx_size(). */
* Get a direct pointer to the circular transmit buffer.
* '*pxLength' will contain the number of bytes that may be written.
*/
-uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );
+uint8_t *FreeRTOS_get_tx_head( ConstSocket_t xSocket, BaseType_t *pxLength );
#endif /* ipconfigUSE_TCP */
-/*
- * Connect / disconnect handler for a TCP socket
- * For example:
- * static void vMyConnectHandler (Socket_t xSocket, BaseType_t ulConnected)
- * {
- * }
- * F_TCP_UDP_Handler_t xHnd = { vMyConnectHandler };
- * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );
- */
+#if( ipconfigUSE_CALLBACKS != 0 )
+ /*
+ * Connect / disconnect handler for a TCP socket
+ * For example:
+ * static void vMyConnectHandler (Socket_t xSocket, BaseType_t ulConnected)
+ * {
+ * }
+ * F_TCP_UDP_Handler_t xHnd = { vMyConnectHandler };
+ * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );
+ */
+
+ #ifdef __COVERITY__
+ typedef void (* FOnConnected_t )( Socket_t xSocket, BaseType_t ulConnected );
+ #else
+ typedef void (* FOnConnected_t )( Socket_t, BaseType_t );
+ #endif
-typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnected */ );
+ /*
+ * Reception handler for a TCP socket
+ * A user-proved function will be called on reception of a message
+ * If the handler returns a positive number, the messages will not be stored
+ * For example:
+ * static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t uxLength )
+ * {
+ * // handle the message
+ * return 1;
+ * }
+ * F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };
+ * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );
+ */
+ #ifdef __COVERITY__
+ typedef BaseType_t (* FOnTCPReceive_t )( Socket_t xSocket, void * pData, size_t xLength );
+ typedef void (* FOnTCPSent_t )( Socket_t xSocket, size_t xLength );
+ #else
+ typedef BaseType_t (* FOnTCPReceive_t )( Socket_t, void *, size_t );
+ typedef void (* FOnTCPSent_t )( Socket_t, size_t );
+ #endif
+
+ /*
+ * Reception handler for a UDP socket
+ * A user-proved function will be called on reception of a message
+ * If the handler returns a positive number, the messages will not be stored
+ */
+ #ifdef __COVERITY__
+ typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t xSocket, void * pData, size_t xLength,
+ const struct freertos_sockaddr * pxFrom, const struct freertos_sockaddr * pxDest );
+ typedef void (* FOnUDPSent_t )( Socket_t xSocket, size_t xLength );
+ #else
+ typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t, void *, size_t,
+ const struct freertos_sockaddr *, const struct freertos_sockaddr *);
+ typedef void (* FOnUDPSent_t )( Socket_t, size_t);
+ #endif
-/*
- * Reception handler for a TCP socket
- * A user-proved function will be called on reception of a message
- * If the handler returns a positive number, the messages will not be stored
- * For example:
- * static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t xLength )
- * {
- * // handle the message
- * return 1;
- * }
- * F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };
- * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );
- */
-typedef BaseType_t (* FOnTCPReceive_t )( Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */ );
-typedef void (* FOnTCPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
+ typedef union xTCP_UDP_HANDLER
+ {
+ FOnConnected_t pxOnTCPConnected; /* FREERTOS_SO_TCP_CONN_HANDLER */
+ FOnTCPReceive_t pxOnTCPReceive; /* FREERTOS_SO_TCP_RECV_HANDLER */
+ FOnTCPSent_t pxOnTCPSent; /* FREERTOS_SO_TCP_SENT_HANDLER */
+ FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */
+ FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */
+ } F_TCP_UDP_Handler_t;
+#endif /* ( ipconfigUSE_CALLBACKS != 0 ) */
+
+BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t uxOptionLength );
+BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
-/*
- * Reception handler for a UDP socket
- * A user-proved function will be called on reception of a message
- * If the handler returns a positive number, the messages will not be stored
- */
-typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */,
- const struct freertos_sockaddr * /* pxFrom */, const struct freertos_sockaddr * /* pxDest */ );
-typedef void (* FOnUDPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );
+/* The following function header should be placed in FreeRTOS_DNS.h.
+It is kept here because some applications expect it in FreeRTOS_Sockets.h.*/
+#ifndef __COVERITY__
+ uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
+#endif
+BaseType_t FreeRTOS_inet_pton( BaseType_t xAddressFamily, const char *pcSource, void *pvDestination );
+const char *FreeRTOS_inet_ntop( BaseType_t xAddressFamily, const void *pvSource, char *pcDestination, socklen_t uxSize );
-typedef union xTCP_UDP_HANDLER
-{
- FOnConnected_t pxOnTCPConnected; /* FREERTOS_SO_TCP_CONN_HANDLER */
- FOnTCPReceive_t pxOnTCPReceive; /* FREERTOS_SO_TCP_RECV_HANDLER */
- FOnTCPSent_t pxOnTCPSent; /* FREERTOS_SO_TCP_SENT_HANDLER */
- FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */
- FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */
-} F_TCP_UDP_Handler_t;
-
-BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );
-BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
-uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
+/* Convert a null-terminated string in dot-decimal-notation (d.d.d.d) to a 32-bit unsigned integer. */
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );
+BaseType_t FreeRTOS_inet_pton4( const char *pcSource, void *pvDestination );
+const char *FreeRTOS_inet_ntop4( const void *pvSource, char *pcDestination, socklen_t uxSize );
+
+
/*
* For the web server: borrow the circular Rx buffer for inspection
* HTML driver wants to see if a sequence of 13/10/13/10 is available
*/
-const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket );
+const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( ConstSocket_t xSocket );
void FreeRTOS_netstat( void );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h
index 9698227c6..b56ecdbeb 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -52,10 +52,10 @@ static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )
{
/* Make the circular buffer empty */
- pxBuffer->uxHead = 0u;
- pxBuffer->uxTail = 0u;
- pxBuffer->uxFront = 0u;
- pxBuffer->uxMid = 0u;
+ pxBuffer->uxHead = 0U;
+ pxBuffer->uxTail = 0U;
+ pxBuffer->uxFront = 0U;
+ pxBuffer->uxMid = 0U;
}
/*-----------------------------------------------------------*/
@@ -65,7 +65,7 @@ static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, co
/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
size_t uxCount;
- uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;
+ uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1U;
if( uxCount >= pxBuffer->LENGTH )
{
uxCount -= pxBuffer->LENGTH;
@@ -145,12 +145,13 @@ static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t ux
{
/* Increment uxMid, but no further than uxHead */
size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
+size_t uxMoveCount = uxCount;
- if( uxCount > uxSize )
+ if( uxMoveCount > uxSize )
{
- uxCount = uxSize;
+ uxMoveCount = uxSize;
}
- pxBuffer->uxMid += uxCount;
+ pxBuffer->uxMid += uxMoveCount;
if( pxBuffer->uxMid >= pxBuffer->LENGTH )
{
pxBuffer->uxMid -= pxBuffer->LENGTH;
@@ -165,7 +166,7 @@ BaseType_t xReturn;
size_t uxTail = pxBuffer->uxTail;
/* Returns true if ( uxLeft < uxRight ) */
- if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )
+ if( ( ( ( uxLeft < uxTail ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U )
{
if( uxRight < uxTail )
{
@@ -211,7 +212,7 @@ size_t uxSize = uxStreamBufferGetSize( pxBuffer );
* pucData - A pointer to the data to be added.
* uxCount - The number of bytes to add.
*/
-size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );
+size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxByteCount );
/*
* Read bytes from a stream buffer.
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
index e26edf653..5e64e9743 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -30,13 +30,13 @@
extern "C" {
#endif
-BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
+BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxDescriptor );
typedef enum eTCP_STATE {
/* Comments about the TCP states are borrowed from the very useful
* Wiki page:
* http://en.wikipedia.org/wiki/Transmission_Control_Protocol */
- eCLOSED = 0u, /* 0 (server + client) no connection state at all. */
+ eCLOSED = 0U, /* 0 (server + client) no connection state at all. */
eTCP_LISTEN, /* 1 (server) waiting for a connection request
from any remote TCP and port. */
eCONNECT_SYN, /* 2 (client) internal state: socket wants to send
@@ -50,11 +50,11 @@ typedef enum eTCP_STATE {
or an acknowledgement of the connection termination request previously sent. */
eFIN_WAIT_2, /* 7 (server + client) waiting for a connection termination request from the remote TCP. */
eCLOSE_WAIT, /* 8 (server + client) waiting for a connection termination request from the local user. */
- eCLOSING, /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
- eLAST_ACK, /* 9 (server + client) waiting for an acknowledgement of the connection termination request
+ eCLOSING, /* 9 (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
+ eLAST_ACK, /*10 (server + client) waiting for an acknowledgement of the connection termination request
previously sent to the remote TCP
(which includes an acknowledgement of its connection termination request). */
- eTIME_WAIT, /* 10 (either server or client) waiting for enough time to pass to be sure the remote TCP received the
+ eTIME_WAIT, /*11 (either server or client) waiting for enough time to pass to be sure the remote TCP received the
acknowledgement of its connection termination request. [According to RFC 793 a connection can
stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */
} eIPTCPState_t;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h
index 1cb7eebc0..9368e0801 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -35,9 +35,8 @@
extern "C" {
#endif
-extern BaseType_t xTCPWindowLoggingLevel;
-
-typedef struct xTCPTimer
+/* The name xTCPTimer was already use as the name of an IP-timer. */
+typedef struct xTCPTimerStruct
{
uint32_t ulBorn;
} TCPTimer_t;
@@ -64,7 +63,7 @@ typedef struct xTCP_SEGMENT
} u;
#if( ipconfigUSE_TCP_WIN != 0 )
struct xLIST_ITEM xQueueItem; /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */
- struct xLIST_ITEM xListItem; /* With this item the segment can be connected to a list, depending on who is owning it */
+ struct xLIST_ITEM xSegmentItem; /* With this item the segment can be connected to a list, depending on who is owning it */
#endif
} TCPSegment_t;
@@ -80,9 +79,9 @@ typedef struct xTCP_WINSIZE
*/
/* Keep this as a multiple of 4 */
#if( ipconfigUSE_TCP_WIN == 1 )
- #define ipSIZE_TCP_OPTIONS 16u
+ #define ipSIZE_TCP_OPTIONS 16U
#else
- #define ipSIZE_TCP_OPTIONS 12u
+ #define ipSIZE_TCP_OPTIONS 12U
#endif
/*
@@ -149,7 +148,7 @@ void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
/* Destroy a window (always returns NULL)
* It will free some resources: a collection of segments */
-void vTCPWindowDestroy( TCPWindow_t *pxWindow );
+void vTCPWindowDestroy( TCPWindow_t const * pxWindow );
/* Initialize a window */
void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
@@ -167,16 +166,9 @@ void vTCPSegmentCleanup( void );
* But pxWindow->ackno should always be used to set "BUF->ackno" */
int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace );
-/* When lTCPWindowRxCheck returned false, please call store for this unexpected data */
-BaseType_t xTCPWindowRxStore( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
-
/* This function will be called as soon as a FIN is received. It will return true
* if there are no 'open' reception segments */
-BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );
-
-/* _HT_ Temporary function for testing/debugging
- * Not used at this moment */
-void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
+BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow );
/*=============================================================================
*
@@ -188,12 +180,12 @@ void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax );
/* Check data to be sent and calculate the time period we may sleep */
-BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );
+BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );
/* See if anything is left to be sent
* Function will be called when a FIN has been received. Only when the TX window is clean,
* it will return pdTRUE */
-BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow );
+BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow );
/* Fetches data to be sent.
* apPos will point to a location with the circular data buffer: txStream */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h
index cb3dd3556..0da86a7df 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h
index 0253a200d..9105b0f81 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -64,6 +64,7 @@ already been made. */
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+ #define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
@@ -81,9 +82,15 @@ already been made. */
itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
-
+#else
+ #ifndef pdFREERTOS_ERRNO_EAFNOSUPPORT
+ #define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
+ #endif /* pdFREERTOS_ERRNO_EAFNOSUPPORT */
#endif /* pdFREERTOS_ERRNO_NONE */
+/* Translate a pdFREERTOS_ERRNO code to a human readable string. */
+const char *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength );
+
#endif /* FREERTOS_ERRNO_TCP */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h
index 0af7189dd..fc100c9fd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -190,4 +190,44 @@ http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Trace.html */
#define iptraceSENDTO_DATA_TOO_LONG()
#endif
+#ifndef ipconfigUSE_TCP_MEM_STATS
+ #define ipconfigUSE_TCP_MEM_STATS 0
+#endif
+
+#if( ipconfigUSE_TCP_MEM_STATS == 0 )
+
+ /* See tools/tcp_mem_stat.c */
+
+ #ifndef iptraceMEM_STATS_CREATE
+ #define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize )
+ #endif
+
+ #ifndef iptraceMEM_STATS_DELETE
+ #define iptraceMEM_STATS_DELETE( pxObject )
+ #endif
+
+ #ifndef iptraceMEM_STATS_CLOSE
+ #define iptraceMEM_STATS_CLOSE()
+ #endif
+
+#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
+
+#ifndef ipconfigUSE_DUMP_PACKETS
+ #define ipconfigUSE_DUMP_PACKETS 0
+#endif
+
+#if( ipconfigUSE_DUMP_PACKETS == 0 )
+
+ /* See tools/tcp_dump_packets.c */
+
+ #ifndef iptraceDUMP_INIT
+ #define iptraceDUMP_INIT( pcFileName, pxEntries )
+ #endif
+
+ #ifndef iptraceDUMP_PACKET
+ #define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming )
+ #endif
+
+#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */
+
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h
index d57e607ac..7d8d574a6 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -46,7 +46,7 @@ UBaseType_t uxGetNumberOfFreeNetworkBuffers( void );
UBaseType_t uxGetMinimumFreeNetworkBuffers( void );
/* Copy a network buffer into a bigger buffer. */
-NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
+NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer,
size_t uxNewLength);
/* Increase the size of a Network Buffer.
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h
index 8f1fb3219..51e9a2942 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.2.0
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -30,10 +30,16 @@
extern "C" {
#endif
-/* NOTE PUBLIC API FUNCTIONS. */
+/* INTERNAL API FUNCTIONS. */
BaseType_t xNetworkInterfaceInitialise( void );
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend );
+/* coverity[misra_c_2012_rule_8_6_violation] */
+/* "vNetworkInterfaceAllocateRAMToBuffers" is declared but never defined.
+The following function is only used when BufferAllocation_1.c is linked in the project. */
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );
+
+/* "xGetPhyLinkStatus" is provided by the network driver. */
+/* coverity[misra_c_2012_rule_8_6_violation] */
BaseType_t xGetPhyLinkStatus( void );
#ifdef __cplusplus
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h
new file mode 100644
index 000000000..7dd369023
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h
@@ -0,0 +1,89 @@
+/*
+ * FreeRTOS+TCP V2.2.1
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.
+ *
+ * http://aws.amazon.com/freertos
+ * http://www.FreeRTOS.org
+ */
+
+/*
+ * dump_packets.c
+ * Used in the PC/Win project to dump Ethernet packets, along with some description.
+ */
+
+#ifndef DUMP_PACKETS_H
+
+
+#define DUMP_PACKETS_H
+
+#ifndef dumpMAX_DUMP_ENTRIES
+ #define dumpMAX_DUMP_ENTRIES 16
+#endif
+
+#define flag_ICMP4 0x00000001UL
+#define flag_ICMP6 0x00000002UL
+#define flag_UDP 0x00000004UL
+#define flag_TCP 0x00000008UL
+#define flag_DNS 0x00000010UL
+#define flag_REPLY 0x00000020UL
+#define flag_REQUEST 0x00000040UL
+#define flag_SYN 0x00000080UL
+#define flag_FIN 0x00000100UL
+#define flag_RST 0x00000200UL
+#define flag_ACK 0x00000400UL
+#define flag_IN 0x00000800UL
+#define flag_OUT 0x00001000UL
+#define flag_FRAME_ARP 0x00002000UL
+#define flag_ARP 0x00004000UL
+#define flag_UNKNOWN 0x00008000UL
+#define flag_FRAME_4 0x00010000UL
+#define flag_FRAME_6 0x00020000UL
+#define flag_Unknown_FRAME 0x00040000UL
+
+typedef struct xDumpEntry
+{
+ uint32_t ulMask;
+ size_t uxMax;
+ size_t uxCount;
+} DumpEntry_t;
+
+typedef struct xDumpEntries
+{
+ size_t uxEntryCount;
+ DumpEntry_t xEntries[ dumpMAX_DUMP_ENTRIES ];
+} DumpEntries_t;
+
+/*
+
+ */
+
+#if( ipconfigUSE_DUMP_PACKETS != 0 )
+
+ extern void dump_packet_init( const char *pcFileName, DumpEntries_t *pxEntries );
+ #define iptraceDUMP_INIT( pcFileName, pxEntries ) \
+ dump_packet_init( pcFileName, pxEntries )
+
+ extern void dump_packet( const uint8_t *pucBuffer, size_t uxLength, BaseType_t xIncoming );
+ #define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming ) \
+ dump_packet( pucBuffer, uxLength, xIncoming )
+
+#endif
+
+#endif
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h
new file mode 100644
index 000000000..d07956f4a
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h
@@ -0,0 +1,77 @@
+/*
+ * FreeRTOS+TCP V2.2.1
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.
+ *
+ * http://aws.amazon.com/freertos
+ * http://www.FreeRTOS.org
+ */
+
+/*
+ * tcp_mem_stats.h
+ */
+
+
+#ifndef TCP_MEM_STATS_H
+
+#define TCP_MEM_STATS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum xTCP_MEMORY
+{
+ tcpSOCKET_TCP,
+ tcpSOCKET_UDP,
+ tcpSOCKET_SET,
+ tcpSEMAPHORE,
+ tcpRX_STREAM_BUFFER,
+ tcpTX_STREAM_BUFFER,
+ tcpNETWORK_BUFFER,
+} TCP_MEMORY_t;
+
+#if( ipconfigUSE_TCP_MEM_STATS != 0 )
+
+ void vTCPMemStatCreate( TCP_MEMORY_t xMemType, void *pxObject, size_t uxSize );
+
+ void vTCPMemStatDelete( void *pxObject );
+
+ void vTCPMemStatClose( void );
+
+ #define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize ) \
+ vTCPMemStatCreate( xMemType, pxObject, uxSize )
+
+ #define iptraceMEM_STATS_DELETE( pxObject ) \
+ vTCPMemStatDelete( pxObject )
+
+ #define iptraceMEM_STATS_CLOSE() \
+ vTCPMemStatClose()
+#else
+
+ /* The header file 'IPTraceMacroDefaults.h' will define the default empty macro's. */
+
+#endif /* ipconfigUSE_TCP_MEM_STATS != 0 */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* TCP_MEM_STATS_H */
+
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c
index e70eb80eb..cf0fa1105 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -54,7 +54,7 @@ be at least this number of buffers available. */
static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */
-static UBaseType_t uxMinimumFreeNetworkBuffers = 0u;
+static UBaseType_t uxMinimumFreeNetworkBuffers = 0U;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist
@@ -86,7 +86,7 @@ are not defined then default them to call the normal enter/exit critical
section macros. */
#if !defined( ipconfigBUFFER_ALLOC_LOCK )
- #define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0)
+ #define ipconfigBUFFER_ALLOC_INIT( ) do {} while ( ipFALSE_BOOL )
#define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \
UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
{
@@ -172,7 +172,7 @@ BaseType_t xReturn, x;
ipconfigBUFFER_ALLOC_INIT();
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
- configASSERT( xNetworkBufferSemaphore );
+ configASSERT( xNetworkBufferSemaphore != NULL );
if( xNetworkBufferSemaphore != NULL )
{
@@ -225,7 +225,7 @@ UBaseType_t uxCount;
available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
- /* Protect the structure as they are accessed from tasks and
+ /* Protect the structure as it is accessed from tasks and
interrupts. */
ipconfigBUFFER_ALLOC_LOCK();
{
@@ -234,7 +234,7 @@ UBaseType_t uxCount;
if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&
listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )
{
- uxListRemove( &( pxReturn->xBufferListItem ) );
+ ( void ) uxListRemove( &( pxReturn->xBufferListItem ) );
}
else
{
@@ -285,6 +285,7 @@ UBaseType_t uxCount;
}
else
{
+ /* lint wants to see at least a comment. */
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
}
@@ -343,7 +344,7 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
}
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
- xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
+ ( void ) xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
return xHigherPriorityTaskWoken;
@@ -357,34 +358,36 @@ BaseType_t xListItemAlreadyInFreeList;
if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )
{
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );
- return ;
}
- /* Ensure the buffer is returned to the list of free buffers before the
- counting semaphore is 'given' to say a buffer is available. */
- ipconfigBUFFER_ALLOC_LOCK();
+ else
{
+ /* Ensure the buffer is returned to the list of free buffers before the
+ counting semaphore is 'given' to say a buffer is available. */
+ ipconfigBUFFER_ALLOC_LOCK();
{
- xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
-
- if( xListItemAlreadyInFreeList == pdFALSE )
{
- vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
+ xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
+
+ if( xListItemAlreadyInFreeList == pdFALSE )
+ {
+ vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
+ }
}
}
- }
- ipconfigBUFFER_ALLOC_UNLOCK();
+ ipconfigBUFFER_ALLOC_UNLOCK();
- if( xListItemAlreadyInFreeList )
- {
- FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
- pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
- }
- if( xListItemAlreadyInFreeList == pdFALSE )
- {
- xSemaphoreGive( xNetworkBufferSemaphore );
- prvShowWarnings();
+ if( xListItemAlreadyInFreeList )
+ {
+ FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
+ pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
+ }
+ else
+ {
+ ( void ) xSemaphoreGive( xNetworkBufferSemaphore );
+ prvShowWarnings();
+ }
+ iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
- iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
/*-----------------------------------------------------------*/
@@ -404,7 +407,7 @@ NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDes
/* In BufferAllocation_1.c all network buffer are allocated with a
maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the
network buffer. */
- ( void ) xNewSizeBytes;
+ pxNetworkBuffer->xDataLength = xNewSizeBytes;
return pxNetworkBuffer;
}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c
index 51f5410a4..d8d95e64f 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c
@@ -1,5 +1,5 @@
/*
- * FreeRTOS+TCP V2.0.11
+ * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -102,7 +102,7 @@ BaseType_t xReturn, x;
if( xNetworkBufferSemaphore == NULL )
{
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
- configASSERT( xNetworkBufferSemaphore );
+ configASSERT( xNetworkBufferSemaphore != NULL );
if( xNetworkBufferSemaphore != NULL )
{
@@ -168,9 +168,9 @@ size_t xSize = *pxRequestedSizeBytes;
/* Round up xSize to the nearest multiple of N bytes,
where N equals 'sizeof( size_t )'. */
- if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
+ if( ( xSize & ( sizeof( size_t ) - 1U ) ) != 0U )
{
- xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
+ xSize = ( xSize | ( sizeof( size_t ) - 1U ) ) + 1U;
}
*pxRequestedSizeBytes = xSize;
@@ -178,7 +178,7 @@ size_t xSize = *pxRequestedSizeBytes;
and a pointer to a network buffer structure (hence the addition of
ipBUFFER_PADDING bytes). */
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
- configASSERT( pucEthernetBuffer );
+ configASSERT( pucEthernetBuffer != NULL );
if( pucEthernetBuffer != NULL )
{
@@ -212,7 +212,7 @@ size_t uxCount;
if( xNetworkBufferSemaphore != NULL )
{
- if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
+ if( ( xRequestedSizeBytes != 0U ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
{
/* ARP packets can replace application packets, so the storage must be
at least large enough to hold an ARP. */
@@ -221,10 +221,10 @@ size_t uxCount;
/* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes
to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
- xRequestedSizeBytes += 2u;
- if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
+ xRequestedSizeBytes += 2U;
+ if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1U ) ) != 0U )
{
- xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
+ xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1U ) ) + 1U;
}
/* If there is a semaphore available, there is a network buffer available. */
@@ -234,7 +234,7 @@ size_t uxCount;
taskENTER_CRITICAL();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
- uxListRemove( &( pxReturn->xBufferListItem ) );
+ ( void ) uxListRemove( &( pxReturn->xBufferListItem ) );
}
taskEXIT_CRITICAL();
@@ -297,6 +297,7 @@ size_t uxCount;
}
else
{
+ /* No action. */
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
@@ -340,6 +341,7 @@ BaseType_t xListItemAlreadyInFreeList;
}
else
{
+ /* No action. */
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h
index cdbad17c4..5128b7a43 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h
index 7fe533a06..dedf3d245 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/CompilerName/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h
index 73455f910..fa9dacae7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h
index 658cc4a5e..c928843bd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h
index f0a73881d..0ce830b0a 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h
index 95cc089b2..a2f7067bd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h
index 48a8ef963..4038d6d6c 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h
index 32c98e859..58b94dc25 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Keil/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h
index e486c1c30..9ff11b17f 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h
index 52b90803b..f20565e0c 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h
index 49e276960..eab452ba0 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h
index 88c4c1f38..1044e53d1 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
index 83c96a07c..dc70ed993 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -219,19 +219,19 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
}
if( xTxBufferQueue == NULL )
{
xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
- configASSERT( xTxBufferQueue );
+ configASSERT( xTxBufferQueue != NULL );
}
if( xTXDescriptorSemaphore == NULL )
{
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
- configASSERT( xTXDescriptorSemaphore );
+ configASSERT( xTXDescriptorSemaphore != NULL );
}
/* When returning non-zero, the stack will become active and
start DHCP (in configured) */
@@ -296,7 +296,7 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
#endif /* ipconfigZERO_COPY_TX_DRIVER */
/* Not interested in a call-back after TX. */
iptraceNETWORK_INTERFACE_TRANSMIT();
- } while( 0 );
+ } while( ipFALSE_BOOL );
if( bReleaseAfterSend != pdFALSE )
{
@@ -417,7 +417,7 @@ const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
/* Calculate the IP header checksum. */
pxIPHeader->usHeaderChecksum = 0x00;
- pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
/* Calculate the TCP checksum for an outgoing packet. */
@@ -519,7 +519,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
index 948f9a661..87b837702 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
@@ -141,7 +141,7 @@ typedef struct gmac_dev_mem {
/** Circular buffer is empty ? */
#define CIRC_EMPTY( head, tail ) ( head == tail )
/** Clear circular buffer */
-#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )
+#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( ipFALSE_BOOL )
/** Increment head or tail */
static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
index fa7695942..5d77b8bbe 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Common/phyHandling.c
@@ -34,60 +34,60 @@
#ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still high after 15 seconds of not
receiving packets. */
- #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000uL
+ #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000UL
#endif
#ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still low every second. */
- #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000uL
+ #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000UL
#endif
/* As the following 3 macro's are OK in most situations, and so they're not
included in 'FreeRTOSIPConfigDefaults.h'.
Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
#ifndef phyPHY_MAX_RESET_TIME_MS
- #define phyPHY_MAX_RESET_TIME_MS 1000uL
+ #define phyPHY_MAX_RESET_TIME_MS 1000UL
#endif
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
- #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000uL
+ #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000UL
#endif
#ifndef phySHORT_DELAY_MS
- #define phySHORT_DELAY_MS 50uL
+ #define phySHORT_DELAY_MS 50UL
#endif
/* Naming and numbering of basic PHY registers. */
-#define phyREG_00_BMCR 0x00u /* Basic Mode Control Register. */
-#define phyREG_01_BMSR 0x01u /* Basic Mode Status Register. */
-#define phyREG_02_PHYSID1 0x02u /* PHYS ID 1 */
-#define phyREG_03_PHYSID2 0x03u /* PHYS ID 2 */
-#define phyREG_04_ADVERTISE 0x04u /* Advertisement control reg */
+#define phyREG_00_BMCR 0x00U /* Basic Mode Control Register. */
+#define phyREG_01_BMSR 0x01U /* Basic Mode Status Register. */
+#define phyREG_02_PHYSID1 0x02U /* PHYS ID 1 */
+#define phyREG_03_PHYSID2 0x03U /* PHYS ID 2 */
+#define phyREG_04_ADVERTISE 0x04U /* Advertisement control reg */
/* Naming and numbering of extended PHY registers. */
-#define PHYREG_10_PHYSTS 0x10u /* 16 PHY status register Offset */
-#define phyREG_19_PHYCR 0x19u /* 25 RW PHY Control Register */
-#define phyREG_1F_PHYSPCS 0x1Fu /* 31 RW PHY Special Control Status */
+#define PHYREG_10_PHYSTS 0x10U /* 16 PHY status register Offset */
+#define phyREG_19_PHYCR 0x19U /* 25 RW PHY Control Register */
+#define phyREG_1F_PHYSPCS 0x1FU /* 31 RW PHY Special Control Status */
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
-#define phyBMCR_FULL_DUPLEX 0x0100u /* Full duplex. */
-#define phyBMCR_AN_RESTART 0x0200u /* Auto negotiation restart. */
-#define phyBMCR_ISOLATE 0x0400u /* 1 = Isolates 0 = Normal operation. */
-#define phyBMCR_AN_ENABLE 0x1000u /* Enable auto negotiation. */
-#define phyBMCR_SPEED_100 0x2000u /* Select 100Mbps. */
-#define phyBMCR_RESET 0x8000u /* Reset the PHY. */
+#define phyBMCR_FULL_DUPLEX 0x0100U /* Full duplex. */
+#define phyBMCR_AN_RESTART 0x0200U /* Auto negotiation restart. */
+#define phyBMCR_ISOLATE 0x0400U /* 1 = Isolates 0 = Normal operation. */
+#define phyBMCR_AN_ENABLE 0x1000U /* Enable auto negotiation. */
+#define phyBMCR_SPEED_100 0x2000U /* Select 100Mbps. */
+#define phyBMCR_RESET 0x8000U /* Reset the PHY. */
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
-#define PHYCR_MDIX_EN 0x8000u /* Enable Auto MDIX. */
-#define PHYCR_MDIX_FORCE 0x4000u /* Force MDIX crossed. */
+#define PHYCR_MDIX_EN 0x8000U /* Enable Auto MDIX. */
+#define PHYCR_MDIX_FORCE 0x4000U /* Force MDIX crossed. */
-#define phyBMSR_AN_COMPLETE 0x0020u /* Auto-Negotiation process completed */
+#define phyBMSR_AN_COMPLETE 0x0020U /* Auto-Negotiation process completed */
-#define phyBMSR_LINK_STATUS 0x0004u
+#define phyBMSR_LINK_STATUS 0x0004U
-#define phyPHYSTS_LINK_STATUS 0x0001u /* PHY Link mask */
-#define phyPHYSTS_SPEED_STATUS 0x0002u /* PHY Speed mask */
-#define phyPHYSTS_DUPLEX_STATUS 0x0004u /* PHY Duplex mask */
+#define phyPHYSTS_LINK_STATUS 0x0001U /* PHY Link mask */
+#define phyPHYSTS_SPEED_STATUS 0x0002U /* PHY Speed mask */
+#define phyPHYSTS_DUPLEX_STATUS 0x0004U /* PHY Duplex mask */
/* Bit fields for 'phyREG_1F_PHYSPCS
001 = 10BASE-T half-duplex
@@ -95,20 +95,20 @@ Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
010 = 100BASE-TX half-duplex
110 = 100BASE-TX full-duplex
*/
-#define phyPHYSPCS_SPEED_MASK 0x000Cu
-#define phyPHYSPCS_SPEED_10 0x0004u
-#define phyPHYSPCS_FULL_DUPLEX 0x0010u
+#define phyPHYSPCS_SPEED_MASK 0x000CU
+#define phyPHYSPCS_SPEED_10 0x0004U
+#define phyPHYSPCS_FULL_DUPLEX 0x0010U
/*
* Description of all capabilities that can be advertised to
* the peer (usually a switch or router).
*/
-#define phyADVERTISE_CSMA 0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
-#define phyADVERTISE_10HALF 0x0020u /* Try for 10mbps half-duplex. */
-#define phyADVERTISE_10FULL 0x0040u /* Try for 10mbps full-duplex. */
-#define phyADVERTISE_100HALF 0x0080u /* Try for 100mbps half-duplex. */
-#define phyADVERTISE_100FULL 0x0100u /* Try for 100mbps full-duplex. */
+#define phyADVERTISE_CSMA 0x0001U /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
+#define phyADVERTISE_10HALF 0x0020U /* Try for 10mbps half-duplex. */
+#define phyADVERTISE_10FULL 0x0040U /* Try for 10mbps full-duplex. */
+#define phyADVERTISE_100HALF 0x0080U /* Try for 100mbps half-duplex. */
+#define phyADVERTISE_100FULL 0x0100U /* Try for 100mbps full-duplex. */
#define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
@@ -167,7 +167,7 @@ BaseType_t xResult;
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite )
{
- memset( ( void * )pxPhyObject, '\0', sizeof( *pxPhyObject ) );
+ memset( ( void * )pxPhyObject, 0, sizeof( *pxPhyObject ) );
pxPhyObject->fnPhyRead = fnPhyRead;
pxPhyObject->fnPhyWrite = fnPhyWrite;
@@ -187,7 +187,7 @@ BaseType_t xPhyAddress;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
/* A valid PHY id can not be all zeros or all ones. */
- if( ( ulLowerID != ( uint16_t )~0u ) && ( ulLowerID != ( uint16_t )0u ) )
+ if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
{
uint32_t ulUpperID;
uint32_t ulPhyID;
@@ -225,7 +225,7 @@ TimeOut_t xTimer;
BaseType_t xPhyIndex;
/* A bit-mask of PHY ports that are ready. */
- ulDoneMask = 0ul;
+ ulDoneMask = 0UL;
/* Set the RESET bits high. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
@@ -251,7 +251,7 @@ BaseType_t xPhyIndex;
if( ( ulConfig & phyBMCR_RESET ) == 0 )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) );
- ulDoneMask |= ( 1ul << xPhyIndex );
+ ulDoneMask |= ( 1UL << xPhyIndex );
}
}
if( ulDoneMask == ulPhyMask )
@@ -270,7 +270,7 @@ BaseType_t xPhyIndex;
/* Clear the reset bits. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
- if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL )
+ if( ( ulDoneMask & ( 1UL << xPhyIndex ) ) == 0UL )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
@@ -454,9 +454,9 @@ with ulPhyMask. */
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{
BaseType_t xPhyIndex;
-uint32_t ulValue, ulBitMask = ( uint32_t )1u;
+uint32_t ulValue, ulBitMask = ( uint32_t )1U;
- ulValue = ( uint32_t )0u;
+ ulValue = ( uint32_t ) 0U;
if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
{
@@ -491,7 +491,7 @@ uint32_t ulPHYLinkStatus, ulRegValue;
TickType_t xRemainingTime;
TimeOut_t xTimer;
- if( ulPhyMask == ( uint32_t )0u )
+ if( ulPhyMask == ( uint32_t ) 0U )
{
return 0;
}
@@ -512,7 +512,7 @@ TimeOut_t xTimer;
/* Wait until the auto-negotiation will be completed */
for( ;; )
{
- ulBitMask = ( uint32_t )1u;
+ ulBitMask = ( uint32_t ) 1U;
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
@@ -541,16 +541,16 @@ TimeOut_t xTimer;
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
- if( ulDoneMask != ( uint32_t)0u )
+ if( ulDoneMask != ( uint32_t) 0U )
{
- ulBitMask = ( uint32_t )1u;
+ ulBitMask = ( uint32_t ) 1U;
pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
- if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u )
+ if( ( ulDoneMask & ulBitMask ) == ( uint32_t ) 0U )
{
continue;
}
@@ -632,7 +632,7 @@ TimeOut_t xTimer;
( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) );
- if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u )
+ if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t ) 0U )
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
}
@@ -650,7 +650,7 @@ TimeOut_t xTimer;
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
}
}
- } /* if( ulDoneMask != ( uint32_t)0u ) */
+ } /* if( ulDoneMask != ( uint32_t) 0U ) */
return 0;
}
@@ -658,7 +658,7 @@ TimeOut_t xTimer;
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
{
-uint32_t ulStatus, ulBitMask = 1u;
+uint32_t ulStatus, ulBitMask = 1U;
BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE;
@@ -670,7 +670,7 @@ BaseType_t xNeedCheck = pdFALSE;
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
- if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul )
+ if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0UL )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
@@ -705,7 +705,7 @@ BaseType_t xNeedCheck = pdFALSE;
}
}
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
- if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
+ if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )
{
/* The link status is high, so don't poll the PHY too often. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c
new file mode 100644
index 000000000..543cc1d62
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/NetworkInterface.c
@@ -0,0 +1,928 @@
+/*
+FreeRTOS+TCP V2.2.1
+Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+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.
+
+ http://aws.amazon.com/freertos
+ http://www.FreeRTOS.org
+*/
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "FreeRTOS_ARP.h"
+#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
+
+/* Some files from the Atmel Software Framework */
+/* gmac_SAM.[ch] is a combination of the gmac.[ch] for both SAM4E and SAME70. */
+#include "gmac_SAM.h"
+#include <sysclk.h>
+#include "phyhandling.h"
+
+/* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */
+#include "conf_board.h"
+
+
+/* Interrupt events to process. Currently only the Rx event is processed
+although code for other events is included to allow for possible future
+expansion. */
+#define EMAC_IF_RX_EVENT 1UL
+#define EMAC_IF_TX_EVENT 2UL
+#define EMAC_IF_ERR_EVENT 4UL
+#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )
+
+/* 1536 bytes is more than needed, 1524 would be enough.
+But 1536 is a multiple of 32, which gives a great alignment for
+cached memories. */
+
+#define NETWORK_BUFFER_SIZE 1536
+
+#ifndef EMAC_MAX_BLOCK_TIME_MS
+ /* The task 'prvEMACHandlerTask()' will wake-up every 100 ms, to see
+ if something has to be done, mostly checking if the PHY has a
+ change in Link Status. */
+ #define EMAC_MAX_BLOCK_TIME_MS 100ul
+#endif
+
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ #error This driver works optimal if ipconfigZERO_COPY_RX_DRIVER is defined as 1
+#endif
+
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ #error This driver works optimal if ipconfigZERO_COPY_TX_DRIVER is defined as 1
+#endif
+
+/* Default the size of the stack used by the EMAC deferred handler task to 4x
+the size of the stack used by the idle task - but allow this to be overridden in
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
+#ifndef configEMAC_TASK_STACK_SIZE
+ #define configEMAC_TASK_STACK_SIZE ( 4 * configMINIMAL_STACK_SIZE )
+#endif
+
+#ifndef niEMAC_HANDLER_TASK_PRIORITY
+ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
+#endif
+
+#if( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
+ #include "core_cm7.h"
+ #warning This driver assumes the presence of DCACHE
+ #define NETWORK_BUFFERS_CACHED 1
+ #define CACHE_LINE_SIZE 32
+ #define NETWORK_BUFFER_HEADER_SIZE ( ipconfigPACKET_FILLER_SIZE + 8 )
+
+ static void cache_clean_invalidate()
+ {
+ /* If you application crashes here, make sure that SCB_EnableDCache() has been called. */
+ SCB_CleanInvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+ static void cache_clean_invalidate_by_addr(uint32_t addr, uint32_t size)
+ {
+ /* SAME70 does not have clean/invalidate per area. */
+ /* SCB_CleanInvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
+ SCB_CleanInvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+ static void cache_invalidate_by_addr(addr, size) \
+ {
+ /* SAME70 does not have clean/invalidate per area. */
+ /* SCB_InvalidateDCache_by_Addr( ( uint32_t * )addr, size); */
+ SCB_InvalidateDCache();
+ }
+ /*-----------------------------------------------------------*/
+
+#else
+ #warning Sure there is no caching?
+ #define cache_clean_invalidate() do {} while( 0 )
+ #define cache_clean_invalidate_by_addr(addr, size) do {} while( 0 )
+ #define cache_invalidate_by_addr(addr, size) do {} while( 0 )
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Update settings in GMAC for speed and duplex.
+ */
+static void prvEthernetUpdateConfig( BaseType_t xForce );
+
+/*
+ * Access functions to the PHY's: read() and write() to be used by
+ * phyHandling.c.
+ */
+static BaseType_t xPHY_Read( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue );
+static BaseType_t xPHY_Write( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue );
+
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )
+ void vGMACGenerateChecksum( uint8_t *apBuffer, size_t uxLength );
+#endif
+
+/*
+ * Called from the ASF GMAC driver.
+ */
+void xRxCallback( uint32_t ulStatus );
+void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
+
+/*
+ * A deferred interrupt handler task that processes GMAC interrupts.
+ */
+static void prvEMACHandlerTask( void *pvParameters );
+
+/*
+ * Initialise the ASF GMAC driver.
+ */
+static BaseType_t prvGMACInit( void );
+
+/*
+ * Try to obtain an Rx packet from the hardware.
+ */
+static uint32_t prvEMACRxPoll( void );
+
+/*
+ * Handle transmission errors.
+ */
+static void hand_tx_errors( void );
+
+/*-----------------------------------------------------------*/
+
+/* Bit map of outstanding ETH interrupt events for processing. Currently only
+the Rx interrupt is handled, although code is included for other events to
+enable future expansion. */
+static volatile uint32_t ulISREvents;
+
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
+static volatile BaseType_t xGMACSwitchRequired;
+
+/* LLMNR multicast address. */
+static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
+
+/* The GMAC object as defined by the ASF drivers. */
+static gmac_device_t gs_gmac_dev;
+
+/* MAC address to use. */
+extern const uint8_t ucMACAddress[ 6 ];
+
+/* Holds the handle of the task used as a deferred interrupt processor. The
+handle is used so direct notifications can be sent to the task for all EMAC/DMA
+related interrupts. */
+TaskHandle_t xEMACTaskHandle = NULL;
+
+static QueueHandle_t xTxBufferQueue;
+int tx_release_count[ 4 ];
+
+/* xTXDescriptorSemaphore is a counting semaphore with
+a maximum count of GMAC_TX_BUFFERS, which is the number of
+DMA TX descriptors. */
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
+
+/* For local use only: describe the PHY's properties: */
+const PhyProperties_t xPHYProperties =
+{
+ #if( ipconfigETHERNET_AN_ENABLE != 0 )
+ .ucSpeed = PHY_SPEED_AUTO,
+ .ucDuplex = PHY_DUPLEX_AUTO,
+ #else
+ #if( ipconfigETHERNET_USE_100MB != 0 )
+ .ucSpeed = PHY_SPEED_100,
+ #else
+ .ucSpeed = PHY_SPEED_10,
+ #endif
+
+ #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
+ .ucDuplex = PHY_DUPLEX_FULL,
+ #else
+ .ucDuplex = PHY_DUPLEX_HALF,
+ #endif
+ #endif
+
+ #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
+ .ucMDI_X = PHY_MDIX_AUTO,
+ #elif( ipconfigETHERNET_CROSSED_LINK != 0 )
+ .ucMDI_X = PHY_MDIX_CROSSED,
+ #else
+ .ucMDI_X = PHY_MDIX_DIRECT,
+ #endif
+};
+
+/* All PHY handling code has now been separated from the NetworkInterface.c,
+see "../Common/phyHandling.c". */
+static EthernetPhy_t xPhyObject;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * GMAC interrupt handler.
+ */
+void GMAC_Handler(void)
+{
+ xGMACSwitchRequired = pdFALSE;
+
+ /* gmac_handler() may call xRxCallback() which may change
+ the value of xGMACSwitchRequired. */
+ gmac_handler( &gs_gmac_dev );
+
+ if( xGMACSwitchRequired != pdFALSE )
+ {
+ portEND_SWITCHING_ISR( xGMACSwitchRequired );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void xRxCallback( uint32_t ulStatus )
+{
+ if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )
+ {
+ /* let the prvEMACHandlerTask know that there was an RX event. */
+ ulISREvents |= EMAC_IF_RX_EVENT;
+ /* Only an RX interrupt can wakeup prvEMACHandlerTask. */
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void returnTxBuffer(uint8_t *puc_buffer)
+{
+ /* Called from a non-ISR context. */
+ if( xTxBufferQueue != NULL )
+ {
+ xQueueSend( xTxBufferQueue, &puc_buffer, 0 );
+ xTaskNotifyGive( xEMACTaskHandle );
+ ulISREvents |= EMAC_IF_TX_EVENT;
+ }
+}
+
+void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )
+{
+ if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )
+ {
+ /* let the prvEMACHandlerTask know that there was an TX event. */
+ ulISREvents |= EMAC_IF_TX_EVENT;
+ /* Wakeup prvEMACHandlerTask. */
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );
+ xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );
+ tx_release_count[ 2 ]++;
+ }
+}
+/*-----------------------------------------------------------*/
+
+
+/*
+ The two standard defines 'GMAC_MAN_RW_TYPE' and 'GMAC_MAN_READ_ONLY'
+ are incorrect.
+ Therefore, use the following:
+*/
+
+#define GMAC_MAINTENANCE_READ_ACCESS (2)
+#define GMAC_MAINTENANCE_WRITE_ACCESS (1)
+
+static BaseType_t xPHY_Read( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
+{
+BaseType_t xReturn;
+UBaseType_t uxWasEnabled;
+
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ /*
+ * OP: Operation: 10 is read. 01 is write.
+ */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ GMAC->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(xAddress)
+ | GMAC_MAN_REGA(xRegister)
+ | GMAC_MAN_OP(GMAC_MAINTENANCE_READ_ACCESS)
+ | GMAC_MAN_DATA( (uint16_t)0u );
+
+ if (gmac_wait_phy(GMAC, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT)
+ {
+ *pulValue = (uint32_t)0xffffu;
+ xReturn = -1;
+ }
+ else
+ {
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+
+ /* Return data */
+ *pulValue = (uint32_t)(GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk);
+
+ xReturn = 0;
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t xPHY_Write( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
+{
+BaseType_t xReturn;
+UBaseType_t uxWasEnabled;
+
+ /* Wait until bus idle */
+ while ((GMAC->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ GMAC->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(xAddress)
+ | GMAC_MAN_REGA(xRegister)
+ | GMAC_MAN_OP(GMAC_MAINTENANCE_WRITE_ACCESS)
+ | GMAC_MAN_DATA( (uint16_t)ulValue );
+
+ if (gmac_wait_phy(GMAC, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT )
+ {
+ xReturn = -1;
+ }
+ else
+ {
+ xReturn = 0;
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xNetworkInterfaceInitialise( void )
+{
+const TickType_t x5_Seconds = 5000UL;
+
+ if( xEMACTaskHandle == NULL )
+ {
+ prvGMACInit();
+
+ cache_clean_invalidate();
+
+ /* The handler task is created at the highest possible priority to
+ ensure the interrupt handler can return directly to it. */
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle );
+ }
+
+ if( xTxBufferQueue == NULL )
+ {
+ xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
+ configASSERT( xTxBufferQueue );
+ }
+
+ if( xTXDescriptorSemaphore == NULL )
+ {
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
+ configASSERT( xTXDescriptorSemaphore );
+ }
+ /* When returning non-zero, the stack will become active and
+ start DHCP (in configured) */
+ return xGetPhyLinkStatus();
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xGetPhyLinkStatus( void )
+{
+BaseType_t xReturn;
+
+ if( xPhyObject.ulLinkStatusMask != 0 )
+ {
+ xReturn = pdPASS;
+ }
+ else
+ {
+ xReturn = pdFAIL;
+ }
+
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+/** The GMAC TX errors to handle */
+#define GMAC_TX_ERRORS (GMAC_TSR_TFC | GMAC_TSR_HRESP)
+
+static void hand_tx_errors( void )
+{
+/* Handle GMAC underrun or AHB errors. */
+ if (gmac_get_tx_status(GMAC) & GMAC_TX_ERRORS) {
+
+ gmac_enable_transmit(GMAC, false);
+
+ /* Reinit TX descriptors. */
+// gmac_tx_init(ps_gmac_dev);
+ gmac_reset_tx_mem(&gs_gmac_dev);
+ /* Clear error status. */
+ gmac_clear_tx_status(GMAC, GMAC_TX_ERRORS);
+
+ gmac_enable_transmit(GMAC, true);
+ }
+}
+
+volatile IPPacket_t *pxSendPacket;
+
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
+{
+/* Do not wait too long for a free TX DMA buffer. */
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
+uint32_t ulTransmitSize;
+
+ ulTransmitSize = pxDescriptor->xDataLength;
+
+ pxSendPacket = (IPPacket_t *)pxDescriptor->pucEthernetBuffer;
+
+ if( ulTransmitSize > NETWORK_BUFFER_SIZE )
+ {
+ ulTransmitSize = NETWORK_BUFFER_SIZE;
+ }
+ /* A do{}while(0) loop is introduced to allow the use of multiple break
+ statement. */
+ do {
+ if( xPhyObject.ulLinkStatusMask == 0ul )
+ {
+ /* Do not attempt to send packets as long as the Link Status is low. */
+ break;
+ }
+ if( xTXDescriptorSemaphore == NULL )
+ {
+ /* Semaphore has not been created yet? */
+ break;
+ }
+ hand_tx_errors();
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
+ {
+ /* Time-out waiting for a free TX descriptor. */
+ tx_release_count[ 3 ]++;
+ break;
+ }
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Confirm that the pxDescriptor may be kept by the driver. */
+ configASSERT( bReleaseAfterSend != pdFALSE );
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+ #if( NETWORK_BUFFERS_CACHED != 0 )
+ {
+ uint32_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );
+ uint32_t xAddress = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );
+ cache_clean_invalidate_by_addr( xAddress, xlength );
+ }
+ #endif
+
+ gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );
+
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Confirm that the pxDescriptor may be kept by the driver. */
+ bReleaseAfterSend = pdFALSE;
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ /* Not interested in a call-back after TX. */
+ iptraceNETWORK_INTERFACE_TRANSMIT();
+ } while( ipFALSE_BOOL );
+
+ if( bReleaseAfterSend != pdFALSE )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+ }
+ return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvGMACInit( void )
+{
+uint32_t ncfgr;
+
+ gmac_options_t gmac_option;
+
+ gmac_enable_management(GMAC, true);
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+
+ memset( &gmac_option, '\0', sizeof( gmac_option ) );
+ gmac_option.uc_copy_all_frame = 0;
+ gmac_option.uc_no_boardcast = 0;
+ memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );
+
+ gs_gmac_dev.p_hw = GMAC;
+ gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );
+
+ NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
+ NVIC_EnableIRQ( GMAC_IRQn );
+
+ {
+ /* Set MDC clock divider. */
+ gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() );
+
+ vPhyInitialise( &xPhyObject, xPHY_Read, xPHY_Write );
+ xPhyDiscover( &xPhyObject );
+ xPhyConfigure( &xPhyObject, &xPHYProperties );
+
+ /* For a reset / reconfigure of the EMAC. */
+ prvEthernetUpdateConfig( pdTRUE );
+
+ /* Select Media Independent Interface type */
+ #if( SAME70 != 0 )
+ {
+ /* Selecting RMII mode. */
+ GMAC->GMAC_UR &= ~GMAC_UR_RMII;
+ }
+ #else
+ {
+ gmac_select_mii_mode(GMAC, ETH_PHY_MODE);
+ }
+ #endif
+
+ gmac_enable_transmit(GMAC, true);
+ gmac_enable_receive(GMAC, true);
+
+ }
+
+ gmac_enable_management(GMAC, true);
+
+ gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );
+
+ gmac_enable_management(GMAC, false);
+ /* Disable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+
+ return 1;
+}
+/*-----------------------------------------------------------*/
+
+static void prvEthernetUpdateConfig( BaseType_t xForce )
+{
+ FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
+ xPhyObject.ulLinkStatusMask,
+ ( int )xForce ) );
+
+ if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
+ {
+ #if( ipconfigETHERNET_AN_ENABLE != 0 )
+ {
+ UBaseType_t uxWasEnabled;
+
+ /* Restart the auto-negotiation. */
+ uxWasEnabled = ( GMAC->GMAC_NCR & GMAC_NCR_MPE ) != 0u;
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR |= GMAC_NCR_MPE;
+ }
+ xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
+
+ /* Configure the MAC with the Duplex Mode fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
+ {
+ gmac_enable_full_duplex(GMAC, pdTRUE);
+ }
+ else
+ {
+ gmac_enable_full_duplex(GMAC, pdFALSE);
+ }
+
+ /* Configure the MAC with the speed fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
+ {
+ gmac_set_speed(GMAC, pdFALSE);
+ }
+ else
+ {
+ gmac_set_speed(GMAC, pdTRUE);
+ }
+ if( uxWasEnabled == 0u )
+ {
+ /* Enable further GMAC maintenance. */
+ GMAC->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+ }
+ #else
+ {
+ if( xPHYProperties.ucDuplex == PHY_DUPLEX_FULL )
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
+ gmac_enable_full_duplex(GMAC, pdTRUE);
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
+ gmac_enable_full_duplex(GMAC, pdFALSE);
+ }
+
+ if( xPHYProperties.ucSpeed == PHY_SPEED_100 )
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
+ gmac_set_speed(GMAC, pdTRUE);
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
+ gmac_set_speed(GMAC, pdFALSE);
+ }
+
+ xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
+
+ /* Use predefined (fixed) configuration. */
+ xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
+ }
+ #endif
+
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vGMACGenerateChecksum( uint8_t *pucBuffer, size_t uxLength )
+{
+ProtocolPacket_t *xProtPacket = ( ProtocolPacket_t * ) pucBuffer;
+
+ if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
+ {
+ IPHeader_t *pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader );
+
+ /* Calculate the IP header checksum. */
+ pxIPHeader->usHeaderChecksum = 0x00;
+ pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
+ pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
+
+ /* Calculate the TCP checksum for an outgoing packet. */
+ usGenerateProtocolChecksum( pucBuffer, uxLength, pdTRUE );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static uint32_t prvEMACRxPoll( void )
+{
+unsigned char *pucUseBuffer;
+uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;
+static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;
+const UBaseType_t xMinDescriptorsToLeave = 2UL;
+const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );
+static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
+uint8_t *pucDMABuffer = NULL;
+
+ for( ;; )
+ {
+ /* If pxNextNetworkBufferDescriptor was not left pointing at a valid
+ descriptor then allocate one now. */
+ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )
+ {
+ pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );
+ }
+
+ if( pxNextNetworkBufferDescriptor != NULL )
+ {
+ /* Point pucUseBuffer to the buffer pointed to by the descriptor. */
+ pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );
+ }
+ else
+ {
+ /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming
+ messages will be flushed and ignored. */
+ pucUseBuffer = NULL;
+ }
+
+ /* Read the next packet from the hardware into pucUseBuffer. */
+ ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount, &pucDMABuffer );
+
+ if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )
+ {
+ /* No data from the hardware. */
+ break;
+ }
+
+ if( pxNextNetworkBufferDescriptor == NULL )
+ {
+ /* Data was read from the hardware, but no descriptor was available
+ for it, so it will be dropped. */
+ iptraceETHERNET_RX_EVENT_LOST();
+ continue;
+ }
+
+ iptraceNETWORK_INTERFACE_RECEIVE();
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+ {
+ pxNextNetworkBufferDescriptor = pxPacketBuffer_to_NetworkBuffer( pucDMABuffer );
+ if( pxNextNetworkBufferDescriptor == NULL )
+ {
+ /* STrange: can not translate from a DMA buffer to a Network Buffer. */
+ break;
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+ pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
+ xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;
+
+ /* Send the descriptor to the IP task for processing. */
+ if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )
+ {
+ /* The buffer could not be sent to the stack so must be released
+ again. */
+ vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );
+ iptraceETHERNET_RX_EVENT_LOST();
+ FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
+ }
+
+ /* Now the buffer has either been passed to the IP-task,
+ or it has been released in the code above. */
+ pxNextNetworkBufferDescriptor = NULL;
+ ulReturnValue++;
+ }
+
+ return ulReturnValue;
+}
+/*-----------------------------------------------------------*/
+
+volatile UBaseType_t uxLastMinBufferCount = 0;
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ volatile UBaseType_t uxLastMinQueueSpace;
+#endif
+volatile UBaseType_t uxCurrentSemCount;
+volatile UBaseType_t uxLowestSemCount;
+
+void vCheckBuffersAndQueue( void )
+{
+static UBaseType_t uxCurrentCount;
+
+ #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ {
+ uxCurrentCount = uxGetMinimumIPQueueSpace();
+ if( uxLastMinQueueSpace != uxCurrentCount )
+ {
+ /* The logging produced below may be helpful
+ while tuning +TCP: see how many buffers are in use. */
+ uxLastMinQueueSpace = uxCurrentCount;
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
+ }
+ }
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
+ uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
+ if( uxLastMinBufferCount != uxCurrentCount )
+ {
+ /* The logging produced below may be helpful
+ while tuning +TCP: see how many buffers are in use. */
+ uxLastMinBufferCount = uxCurrentCount;
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
+ }
+ if( xTXDescriptorSemaphore != NULL )
+ {
+ uxCurrentSemCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );
+ if( uxLowestSemCount > uxCurrentSemCount )
+ {
+ uxLowestSemCount = uxCurrentSemCount;
+ FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
+ }
+
+ }
+
+}
+/*-----------------------------------------------------------*/
+
+extern uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
+{
+uint8_t *ucRAMBuffer = ucNetworkPackets;
+uint32_t ulIndex;
+
+ for( ulIndex = 0; ulIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ulIndex++ )
+ {
+ pxNetworkBuffers[ ulIndex ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
+ *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ulIndex ] ) );
+ ucRAMBuffer += NETWORK_BUFFER_SIZE;
+ }
+ cache_clean_invalidate();
+}
+/*-----------------------------------------------------------*/
+
+static void prvEMACHandlerTask( void *pvParameters )
+{
+UBaseType_t uxCount;
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ NetworkBufferDescriptor_t *pxBuffer;
+#endif
+uint8_t *pucBuffer;
+BaseType_t xResult = 0;
+uint32_t xStatus;
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
+
+ /* Remove compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ configASSERT( xEMACTaskHandle );
+
+ for( ;; )
+ {
+ xResult = 0;
+ vCheckBuffersAndQueue();
+
+ if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
+ {
+ /* No events to process now, wait for the next. */
+ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
+ }
+
+ if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )
+ {
+ ulISREvents &= ~EMAC_IF_RX_EVENT;
+
+ /* Wait for the EMAC interrupt to indicate that another packet has been
+ received. */
+ xResult = prvEMACRxPoll();
+ }
+
+ if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
+ {
+ /* Future extension: code to release TX buffers if zero-copy is used. */
+ ulISREvents &= ~EMAC_IF_TX_EVENT;
+ while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )
+ {
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );
+ if( pxBuffer != NULL )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxBuffer );
+ tx_release_count[ 0 ]++;
+ }
+ else
+ {
+ tx_release_count[ 1 ]++;
+ }
+ }
+ #else
+ {
+ tx_release_count[ 0 ]++;
+ }
+ #endif
+ uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );
+ if( uxCount < GMAC_TX_BUFFERS )
+ {
+ /* Tell the counting semaphore that one more TX descriptor is available. */
+ xSemaphoreGive( xTXDescriptorSemaphore );
+ }
+ }
+ }
+
+ if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
+ {
+ /* Future extension: logging about errors that occurred. */
+ ulISREvents &= ~EMAC_IF_ERR_EVENT;
+ }
+ gmac_enable_management(GMAC, true);
+ if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )
+ {
+ /* Something has changed to a Link Status, need re-check. */
+ prvEthernetUpdateConfig( pdFALSE );
+ }
+ gmac_enable_management(GMAC, false);
+ }
+}
+/*-----------------------------------------------------------*/
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c
new file mode 100644
index 000000000..6732ec51b
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.c
@@ -0,0 +1,924 @@
+/**
+ * \file
+ *
+ * \brief GMAC (Ethernet MAC) driver for SAM.
+ *
+ * Copyright (c) 2015-2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+#include "FreeRTOSIPConfig.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_IP_Private.h"
+#include "FreeRTOS_ARP.h"
+#include "NetworkBufferManagement.h"
+#include "NetworkInterface.h"
+
+#include "compiler.h"
+#include "gmac_SAM.h"
+
+#if( SAME70 != 0 )
+ /* This file is included to see if 'CONF_BOARD_ENABLE_CACHE' is defined. */
+ #include "conf_board.h"
+ #include "core_cm7.h"
+#endif
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+#ifndef ARRAY_SIZE
+ #define ARRAY_SIZE(x) (int)( sizeof(x) / sizeof(x)[0] )
+#endif
+
+#if( GMAC_RX_BUFFERS <= 1 )
+ #error Configuration error
+#endif
+
+#if( GMAC_TX_BUFFERS <= 1 )
+ #error Configuration error
+#endif
+
+/**
+ * \defgroup gmac_group Ethernet Media Access Controller
+ *
+ * See \ref gmac_quickstart.
+ *
+ * Driver for the GMAC (Ethernet Media Access Controller).
+ * This file contains basic functions for the GMAC, with support for all modes, settings
+ * and clock speeds.
+ *
+ * \section dependencies Dependencies
+ * This driver does not depend on other modules.
+ *
+ * @{
+ */
+
+#define NETWORK_BUFFER_SIZE 1536
+
+__attribute__ ( ( aligned( 32 ) ) )
+__attribute__ ( ( section( ".first_data" ) ) )
+ uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];
+
+/** TX descriptor lists */
+__attribute__ ((section(".first_data")))
+COMPILER_ALIGNED(8)
+static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];
+
+#if( SAME70 != 0 )
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static gmac_tx_descriptor_t gs_tx_desc_null;
+#endif
+
+/** RX descriptors lists */
+__attribute__ ((section(".first_data")))
+COMPILER_ALIGNED(8)
+static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];
+
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the
+ * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits
+ * of the address shall be set to 0.
+ */
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];
+#endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ /** Receive Buffer */
+ __attribute__ ((section(".first_data")))
+ COMPILER_ALIGNED(8)
+ static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];
+#endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+/** Return count in buffer */
+#define CIRC_CNT( head, tail, size ) ( ( ( head ) - ( tail ) ) % ( size ) )
+
+/*
+ * Return space available, from 0 to size-1.
+ * Always leave one free char as a completely full buffer that has (head == tail),
+ * which is the same as empty.
+ */
+#define CIRC_SPACE( head, tail, size ) CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )
+
+/** Circular buffer is empty ? */
+#define CIRC_EMPTY( head, tail ) ( ( head ) == ( tail ) )
+/** Clear circular buffer */
+#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 )
+
+/* Two call-back functions that should be defined in NetworkInterface.c */
+extern void xRxCallback( uint32_t ulStatus );
+extern void xTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );
+extern void returnTxBuffer(uint8_t *puc_buffer);
+
+
+/** Increment head or tail */
+static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )
+{
+ ( *lHeadOrTail ) ++;
+ if( ( *lHeadOrTail ) >= ( int32_t )ulSize )
+ {
+ ( *lHeadOrTail ) = 0;
+ }
+}
+
+/**
+ * \brief Wait PHY operation to be completed.
+ *
+ * \param p_gmac HW controller address.
+ * \param ul_retry The retry times, 0 to wait forever until completeness.
+ *
+ * Return GMAC_OK if the operation is completed successfully.
+ */
+uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)
+{
+ volatile uint32_t ul_retry_count = 0;
+ const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );
+
+ while (!gmac_is_phy_idle(p_gmac)) {
+ if (ul_retry == 0) {
+ continue;
+ }
+
+ ul_retry_count++;
+
+ if (ul_retry_count >= ul_retry) {
+ return GMAC_TIMEOUT;
+ }
+
+ /* Block the task to allow other tasks to execute while the PHY
+ is not connected. */
+ vTaskDelay( xPHYPollDelay );
+ }
+ return GMAC_OK;
+}
+
+/**
+ * \brief Disable transfer, reset registers and descriptor lists.
+ *
+ * \param p_dev Pointer to GMAC driver instance.
+ *
+ */
+void gmac_reset_tx_mem(gmac_device_t* p_dev)
+{
+ Gmac *p_hw = p_dev->p_hw;
+
+ uint32_t ul_index;
+ uint32_t ul_address;
+
+ /* Disable TX */
+ gmac_enable_transmit(p_hw, 0);
+
+ {
+ for( ul_index = 0; ul_index < ARRAY_SIZE(gs_tx_desc); ul_index++ )
+ {
+ uint32_t ulAddr = gs_tx_desc[ul_index].addr;
+ if (ulAddr) {
+ returnTxBuffer ((uint8_t *)ulAddr);
+ }
+ }
+ }
+ /* Set up the TX descriptors */
+ CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);
+ for( ul_index = 0; ul_index < GMAC_TX_BUFFERS; ul_index++ )
+ {
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ ul_address = (uint32_t) 0u;
+ }
+ #else
+ {
+ ul_address = (uint32_t) (&(gs_uc_tx_buffer[ul_index * GMAC_TX_UNITSIZE]));
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ gs_tx_desc[ul_index].addr = ul_address;
+ gs_tx_desc[ul_index].status.val = GMAC_TXD_USED;
+ }
+ /* Set the WRAP bit in the last descriptor. */
+ gs_tx_desc[GMAC_TX_BUFFERS - 1].status.val = GMAC_TXD_USED | GMAC_TXD_WRAP;
+
+ /* Set transmit buffer queue */
+ gmac_set_tx_queue(p_hw, (uint32_t) gs_tx_desc);
+ #if( SAME70 != 0 )
+ {
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_1);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_2);
+ /* Note that SAME70 REV B had 6 priority queues. */
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_3);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_4);
+ gmac_set_tx_priority_queue(p_hw, (uint32_t)&gs_tx_desc_null, GMAC_QUE_5);
+ }
+ #endif
+}
+
+/**
+ * \brief Disable receiver, reset registers and descriptor list.
+ *
+ * \param p_dev Pointer to GMAC Driver instance.
+ */
+static void gmac_reset_rx_mem(gmac_device_t* p_dev)
+{
+ Gmac *p_hw = p_dev->p_hw;
+
+ uint32_t ul_index;
+ uint32_t ul_address;
+
+ /* Disable RX */
+ gmac_enable_receive(p_hw, 0);
+
+ /* Set up the RX descriptors */
+ p_dev->ul_rx_idx = 0;
+ for( ul_index = 0; ul_index < GMAC_RX_BUFFERS; ul_index++ )
+ {
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )
+ {
+ NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor;
+
+ pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( GMAC_RX_UNITSIZE, 0ul );
+ configASSERT( pxNextNetworkBufferDescriptor != NULL );
+ ul_address = ( uint32_t )( pxNextNetworkBufferDescriptor->pucEthernetBuffer );
+ }
+ #else
+ {
+ ul_address = ( uint32_t ) ( &( gs_uc_rx_buffer[ ul_index * GMAC_RX_UNITSIZE ] ) );
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+ gs_rx_desc[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;
+ gs_rx_desc[ul_index].status.val = 0;
+ }
+ /* Set the WRAP bit in the last descriptor. */
+ gs_rx_desc[GMAC_RX_BUFFERS - 1].addr.bm.b_wrap = 1;
+
+ /* Set receive buffer queue */
+ gmac_set_rx_queue(p_hw, (uint32_t)gs_rx_desc);
+}
+
+
+/**
+ * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.
+ * Must be invoked after gmac_dev_init() but before RX/TX starts.
+ *
+ * \note If input address is not 8-byte aligned, the address is automatically
+ * adjusted and the list size is reduced by one.
+ *
+ * \param p_gmac Pointer to GMAC instance.
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ * \param p_dev_mm Pointer to the GMAC memory management control block.
+ *
+ * \return GMAC_OK or GMAC_PARAM.
+ */
+static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev)
+{
+ /* Assign TX buffers */
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ if ((((uint32_t) gs_uc_tx_buffer) & 0x7)
+ || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
+ p_dev_mm->ul_tx_size--;
+ }
+ p_gmac_dev->p_tx_buffer =
+ (uint8_t *) (((uint32_t) gs_uc_tx_buffer) & 0xFFFFFFF8);
+#endif
+
+ /* Reset TX & RX Memory */
+ gmac_reset_rx_mem(p_gmac_dev);
+ gmac_reset_tx_mem(p_gmac_dev);
+
+ /* Enable Rx and Tx, plus the statistics register */
+ gmac_enable_transmit(p_gmac, true);
+ gmac_enable_receive(p_gmac, true);
+ gmac_enable_statistics_write(p_gmac, true);
+
+ /* Set up the interrupts for transmission and errors */
+ gmac_enable_interrupt(p_gmac,
+ GMAC_IER_RLEX | /* Enable retry limit exceeded interrupt. */
+ GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
+ GMAC_IER_ROVR | /* Enable receive overrun interrupt. */
+ GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
+ GMAC_IER_TUR | /* Enable transmit underrun interrupt. */
+ GMAC_IER_TFC | /* Enable transmit buffers exhausted in mid-frame interrupt. */
+ GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
+ GMAC_IER_PFNZ | /* Enable pause frame received interrupt. */
+ GMAC_IER_PTZ | /* Enable pause time zero interrupt. */
+ GMAC_IER_RCOMP); /* Enable receive complete interrupt. */
+
+ return GMAC_OK;
+}
+
+/**
+ * \brief Initialize the GMAC driver.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_opt GMAC configure options.
+ */
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
+ gmac_options_t* p_opt)
+{
+ /* Disable TX & RX and more */
+ gmac_network_control(p_gmac, 0);
+ gmac_disable_interrupt(p_gmac, ~0u);
+
+ gmac_clear_statistics(p_gmac);
+
+ /* Clear all status bits in the receive status register. */
+ gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA
+ | GMAC_RSR_HNO);
+
+#ifndef GMAC_TSR_UND
+ /* GMAC_TSR_UND is only defined by SAM4E. */
+ #define GMAC_TSR_UND 0ul
+#endif
+ /* Clear all status bits in the transmit status register */
+ gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE
+ | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);
+
+ /* Clear interrupts */
+ gmac_get_interrupt_status(p_gmac);
+#if !defined(ETHERNET_CONF_DATA_OFFSET)
+ /* Receive Buffer Offset
+ * Indicates the number of bytes by which the received data
+ * is offset from the start of the receive buffer
+ * which can be handy for alignment reasons */
+ /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */
+ #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0
+#endif
+ /* Enable the copy of data into the buffers
+ ignore broadcasts, and not copy FCS. */
+
+ gmac_set_config(p_gmac,
+ ( gmac_get_config(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |
+ GMAC_NCFGR_RFCS | /* Remove FCS, frame check sequence (last 4 bytes) */
+ GMAC_NCFGR_PEN | /* Pause Enable */
+ GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) | /* Set Ethernet Offset */
+ GMAC_RXD_RXCOEN ); /* RXCOEN related function */
+
+ /*
+ * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.
+ * Note: SAM4E/SAME70 do have RX checksum offloading
+ * but TX checksum offloading has NOT been implemented,
+ * at least on a SAM4E.
+ * http://community.atmel.com/forum/sam4e-gmac-transmit-checksum-offload-enablesolved
+ */
+
+ {
+ uint32_t ulValue = gmac_get_dma(p_gmac);
+
+ /* Let the GMAC set TX checksum's. */
+ ulValue |= GMAC_DCFGR_TXCOEN;
+ #if( SAME70 != 0 )
+ {
+ /* Transmitter Packet Buffer Memory Size Select:
+ Use full configured addressable space (4 Kbytes). */
+ ulValue |= GMAC_DCFGR_TXPBMS;
+ }
+ #endif
+
+ /* Clear the DMA Receive Buffer Size (DRBS) field: */
+ ulValue &= ~( GMAC_DCFGR_DRBS_Msk );
+ /* And set it: */
+ ulValue |= ( GMAC_RX_UNITSIZE / 64 ) << GMAC_DCFGR_DRBS_Pos;
+
+ gmac_set_dma(p_gmac, ulValue);
+ }
+
+ /* Enable/Disable Copy(Receive) All Valid Frames. */
+ gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);
+
+ /* Disable/Enable broadcast receiving */
+ gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);
+
+
+ /* Initialize memory */
+ gmac_init_mem(p_gmac, p_gmac_dev);
+
+ /* Set Mac Address */
+ gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);
+}
+
+/**
+ * \brief Frames can be read from the GMAC in multiple sections.
+ *
+ * Returns > 0 if a complete frame is available
+ * It also it cleans up incomplete older frames
+ */
+
+static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)
+{
+ uint32_t ulReturn = 0;
+ int32_t ulIndex = p_gmac_dev->ul_rx_idx;
+ gmac_rx_descriptor_t *pxHead = &gs_rx_desc[ulIndex];
+
+// #warning Just for debugging
+// if((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0)
+// {
+// NVIC_DisableIRQ( GMAC_IRQn );
+// }
+
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+ /* Discard any incomplete frames */
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&
+ (pxHead->status.val & GMAC_RXD_SOF) == 0)
+ {
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ #if( GMAC_STATS != 0 )
+ {
+ gmacStats.incompCount++;
+ }
+ #endif
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER == 0 */
+
+ while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0)
+ {
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+ if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {
+ /* Here a complete frame has been seen with SOF and EOF */
+ ulReturn = pxHead->status.bm.b_len;
+ break;
+ }
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {
+ /* CPU is not the owner (yet) */
+ break;
+ }
+ if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {
+ /* Strange, we found a new Start Of Frame
+ * discard previous segments */
+ int32_t ulPrev = p_gmac_dev->ul_rx_idx;
+ pxHead = &gs_rx_desc[ulPrev];
+ do {
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&ulPrev, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulPrev];
+ #if( GMAC_STATS != 0 )
+ {
+ gmacStats.truncCount++;
+ }
+ #endif
+ } while (ulPrev != ulIndex);
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ }
+ }
+ #else /* ipconfigZERO_COPY_RX_DRIVER */
+ {
+ if ((pxHead->status.val & (GMAC_RXD_SOF|GMAC_RXD_EOF)) == (GMAC_RXD_SOF|GMAC_RXD_EOF)) {
+ /* Here a complete frame in a single segment. */
+ ulReturn = pxHead->status.bm.b_len;
+ break;
+ }
+ /* Return the buffer to DMA. */
+ pxHead->addr.bm.b_ownership = 0;
+
+ /* Let ulIndex/pxHead point to the next buffer. */
+ circ_inc32 (&ulIndex, GMAC_RX_BUFFERS);
+ pxHead = &gs_rx_desc[ulIndex];
+ /* And remember this index. */
+ p_gmac_dev->ul_rx_idx = ulIndex;
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+ }
+ return ulReturn;
+}
+
+/**
+ * \brief Frames can be read from the GMAC in multiple sections.
+ * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.
+ * p_rcv_size is the size of the entire frame. Generally gmac_read
+ * will be repeatedly called until the sum of all the ul_frame_size equals
+ * the value of p_rcv_size.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_frame Address of the frame buffer.
+ * \param ul_frame_size Length of the frame.
+ * \param p_rcv_size Received frame size.
+ *
+ * \return GMAC_OK if receiving frame successfully, otherwise failed.
+ */
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
+ uint32_t ul_frame_size, uint32_t* p_rcv_size,
+ uint8_t** pp_recv_frame)
+{
+ int32_t nextIdx; /* A copy of the Rx-index 'ul_rx_idx' */
+ int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);
+ gmac_rx_descriptor_t *pxHead;
+
+ if (bytesLeft == 0 )
+ {
+ return GMAC_RX_NO_DATA;
+ }
+
+ /* gmac_dev_poll has confirmed that there is a complete frame at
+ * the current position 'ul_rx_idx'
+ */
+ nextIdx = p_gmac_dev->ul_rx_idx;
+
+ /* Read +2 bytes because buffers are aligned at -2 bytes */
+ bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );
+
+#if( __DCACHE_PRESENT != 0 ) && defined( CONF_BOARD_ENABLE_CACHE )
+ SCB_InvalidateDCache();
+#endif
+
+ #if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ {
+
+ /* The frame will be copied in 1 or 2 memcpy's */
+ if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )
+ {
+ const uint8_t *source;
+ int32_t left;
+ int32_t toCopy;
+
+ source = gs_uc_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;
+ left = bytesLeft;
+ toCopy = ( GMAC_RX_BUFFERS - nextIdx ) * GMAC_RX_UNITSIZE;
+ if(toCopy > left )
+ {
+ toCopy = left;
+ }
+ memcpy (p_frame, source, toCopy);
+ left -= toCopy;
+
+ if( left != 0ul )
+ {
+ memcpy (p_frame + toCopy, (void*)gs_uc_rx_buffer, left);
+ }
+ }
+ }
+ #else /* ipconfigZERO_COPY_RX_DRIVER */
+ {
+ if( p_frame != NULL )
+ {
+ /* Return a pointer to the earlier DMA buffer. */
+ *( pp_recv_frame ) = ( uint8_t * )
+ ( ( ( gs_rx_desc[nextIdx].addr.val ) & ~( 0x03ul ) ) + 2 );
+ /* Set the new DMA-buffer. */
+ gs_rx_desc[nextIdx].addr.bm.addr_dw = ( ( uint32_t )p_frame ) / 4;
+ }
+ else
+ {
+ /* The driver couldn't not allocate a buffer to receive a packet.
+ Leave the current DMA buffer in place. */
+ }
+ }
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */
+
+ do
+ {
+ pxHead = &gs_rx_desc[nextIdx];
+ pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);
+ circ_inc32 (&nextIdx, GMAC_RX_BUFFERS);
+ } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);
+
+ p_gmac_dev->ul_rx_idx = nextIdx;
+
+ *p_rcv_size = bytesLeft;
+
+// #warning Just for debugging
+// NVIC_EnableIRQ( GMAC_IRQn );
+
+ return GMAC_OK;
+}
+
+extern void vGMACGenerateChecksum( uint8_t *apBuffer, size_t uxLength );
+
+/**
+ * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
+ * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.
+ * If lEndOfFrame is true then the data being copied is the end of the frame
+ * and the frame can be transmitted.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ * \param p_buffer Pointer to the data buffer.
+ * \param ul_size Length of the frame.
+ *
+ * \return Length sent.
+ */
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
+ uint32_t ul_size)
+{
+ volatile gmac_tx_descriptor_t *p_tx_td;
+
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+
+ /* Check parameter */
+ if (ul_size > GMAC_TX_UNITSIZE) {
+ return GMAC_PARAM;
+ }
+
+ /* Pointers to the current transmit descriptor */
+ p_tx_td = &gs_tx_desc[p_gmac_dev->l_tx_head];
+
+ /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)
+ {
+ return GMAC_TX_BUSY;
+ }
+
+ /* Set up/copy data to transmission buffer */
+ if (p_buffer && ul_size) {
+ /* Driver manages the ring buffer */
+ /* Calculating the checksum here is faster than calculating it from the GMAC buffer
+ * because withing p_buffer, it is well aligned */
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ /* Zero-copy... */
+ p_tx_td->addr = ( uint32_t ) p_buffer;
+ }
+ #else
+ {
+ /* Or memcopy... */
+ memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr, ( size_t ) ul_size );
+ }
+
+ //#warning Trying out
+ gmac_start_transmission(p_hw);
+
+ /* Update transmit descriptor status */
+
+ /* The buffer size defined is the length of ethernet frame,
+ so it's always the last buffer of the frame. */
+ if( p_gmac_dev->l_tx_head == ( int32_t )( GMAC_TX_BUFFERS - 1 ) )
+ {
+ /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked
+ GMAC_TXD_USED will now be cleared. */
+ p_tx_td->status.val =
+ ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;
+ } else {
+ /* GMAC_TXD_USED will now be cleared. */
+ p_tx_td->status.val =
+ ul_size | GMAC_TXD_LAST;
+ }
+
+ circ_inc32( &p_gmac_dev->l_tx_head, GMAC_TX_BUFFERS );
+
+ /* Now start to transmit if it is still not done */
+ gmac_start_transmission(p_hw);
+
+ return GMAC_OK;
+}
+
+/**
+ * \brief Get current load of transmit.
+ *
+ * \param p_gmac_dev Pointer to the GMAC device instance.
+ *
+ * \return Current load of transmit.
+ */
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)
+{
+ uint16_t us_head = p_gmac_dev->l_tx_head;
+ uint16_t us_tail = p_gmac_dev->l_tx_tail;
+ return CIRC_CNT(us_head, us_tail, GMAC_TX_BUFFERS);
+}
+
+/**
+ * \brief Register/Clear TX wakeup callback.
+ *
+ * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application
+ * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and
+ * enters suspend state. The callback is in charge to resume the task once
+ * several transmit descriptors have been released. The next time gmac_dev_write() will be called,
+ * it shall be successful.
+ *
+ * This function is usually invoked with NULL callback from the TX wakeup
+ * callback itself, to unregister. Once the callback has resumed the
+ * application task, there is no need to invoke the callback again.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ * \param func_wakeup Pointer to wakeup callback function.
+ * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.
+ *
+ * \return GMAC_OK, GMAC_PARAM on parameter error.
+ */
+#if( GMAC_USES_WAKEUP_CALLBACK )
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)
+{
+ if (func_wakeup_cb == NULL) {
+ p_gmac_dev->func_wakeup_cb = NULL;
+ } else {
+ if (uc_threshold <= GMAC_TX_BUFFERS) {
+ p_gmac_dev->func_wakeup_cb = func_wakeup_cb;
+ p_gmac_dev->ul_wakeup_threshold = ( uint32_t )uc_threshold;
+ } else {
+ return GMAC_PARAM;
+ }
+ }
+
+ return GMAC_OK;
+}
+#endif /* GMAC_USES_WAKEUP_CALLBACK */
+
+/**
+ * \brief Reset TX & RX queue & statistics.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ */
+void gmac_dev_reset(gmac_device_t* p_gmac_dev)
+{
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+ gmac_reset_rx_mem(p_gmac_dev);
+ gmac_reset_tx_mem(p_gmac_dev);
+ gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN
+ | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
+}
+
+void gmac_dev_halt(Gmac* p_gmac);
+
+void gmac_dev_halt(Gmac* p_gmac)
+{
+ gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
+ gmac_disable_interrupt(p_gmac, ~0u);
+}
+
+
+/**
+ * \brief GMAC Interrupt handler.
+ *
+ * \param p_gmac_dev Pointer to GMAC device instance.
+ */
+
+#if( GMAC_STATS != 0 )
+ extern int logPrintf( const char *pcFormat, ... );
+
+ void gmac_show_irq_counts ()
+ {
+ int index;
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
+ if (gmacStats.intStatus[intPairs[index].index]) {
+ logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);
+ }
+ }
+ }
+#endif
+
+void gmac_handler(gmac_device_t* p_gmac_dev)
+{
+ Gmac *p_hw = p_gmac_dev->p_hw;
+
+ gmac_tx_descriptor_t *p_tx_td;
+ uint32_t ul_tx_status_flag;
+#if( GMAC_STATS != 0 )
+ int index;
+#endif
+
+ uint32_t ul_isr = gmac_get_interrupt_status(p_hw);
+ uint32_t ul_rsr = gmac_get_rx_status(p_hw);
+ uint32_t ul_tsr = gmac_get_tx_status(p_hw);
+
+ #if( GMAC_STATS != 0 )
+ {
+ for (index = 0; index < ARRAY_SIZE(intPairs); index++) {
+ if (ul_isr & intPairs[index].mask)
+ gmacStats.intStatus[intPairs[index].index]++;
+ }
+ }
+ #endif /* GMAC_STATS != 0 */
+
+ /* RX packet */
+ if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {
+ /* Clear status */
+ gmac_clear_rx_status(p_hw, ul_rsr);
+
+ if (ul_isr & GMAC_ISR_RCOMP)
+ ul_rsr |= GMAC_RSR_REC;
+ /* Invoke callbacks which can be useful to wake op a task */
+ xRxCallback( ul_rsr );
+ }
+
+ /* TX packet */
+ if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {
+
+ ul_tx_status_flag = GMAC_TSR_TXCOMP;
+ /* A frame transmitted */
+
+ /* Check RLE */
+ if (ul_tsr & GMAC_TSR_RLE) {
+ /* Status RLE & Number of discarded buffers */
+ ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,
+ p_gmac_dev->l_tx_tail, GMAC_TX_BUFFERS);
+ gmac_reset_tx_mem(p_gmac_dev);
+ gmac_enable_transmit(p_hw, 1);
+ }
+ /* Clear status */
+ gmac_clear_tx_status(p_hw, ul_tsr);
+
+ if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {
+ /* Check the buffers */
+ do {
+ p_tx_td = &gs_tx_desc[p_gmac_dev->l_tx_tail];
+ /* Any error? Exit if buffer has not been sent yet */
+ if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {
+ break;
+ }
+
+ /* Notify upper layer that a packet has been sent */
+ xTxCallback(ul_tx_status_flag, (void*)p_tx_td->addr); // Function call prvTxCallback
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ {
+ p_tx_td->addr = 0ul;
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
+
+ circ_inc32(&p_gmac_dev->l_tx_tail, GMAC_TX_BUFFERS);
+ } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
+ GMAC_TX_BUFFERS));
+ }
+
+ if (ul_tsr & GMAC_TSR_RLE) {
+ /* Notify upper layer RLE */
+ xTxCallback(ul_tx_status_flag, NULL);
+ }
+
+#if( GMAC_USES_WAKEUP_CALLBACK )
+ /* If a wakeup has been scheduled, notify upper layer that it can
+ send other packets, and the sending will be successful. */
+ if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,
+ GMAC_TX_BUFFERS) >= p_gmac_dev->ul_wakeup_threshold)
+ && p_gmac_dev->func_wakeup_cb) {
+ p_gmac_dev->func_wakeup_cb();
+ }
+#endif
+ }
+}
+
+//@}
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h
new file mode 100644
index 000000000..1965889b1
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/DriverSAM/gmac_SAM.h
@@ -0,0 +1,1418 @@
+ /**
+ * \file
+ *
+ * \brief GMAC (Ethernet MAC) driver for SAM.
+ *
+ * Copyright (c) 2013-2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef GMAC_H_INCLUDED
+#define GMAC_H_INCLUDED
+
+#include "compiler.h"
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+/** The buffer addresses written into the descriptors must be aligned, so the
+ last few bits are zero. These bits have special meaning for the GMAC
+ peripheral and cannot be used as part of the address. */
+#define GMAC_RXD_ADDR_MASK 0xFFFFFFFC
+#define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */
+#define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */
+
+#define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */
+#define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */
+#define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */
+#define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */
+#define GMAC_RXD_ADDR (3ul << 25) /**< Address match */
+#define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */
+#define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */
+#define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */
+#define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */
+#define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */
+#define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
+#define GMAC_RXD_EOF (1ul << 15) /**< End of frame */
+#define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */
+#define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */
+#define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */
+#define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */
+#define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */
+
+#define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */
+#define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */
+#define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */
+#define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */
+#define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */
+#define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */
+#define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */
+#define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */
+#define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */
+#define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */
+
+/** The MAC can support frame lengths up to 1536 bytes */
+#define GMAC_FRAME_LENTGH_MAX 1536
+
+//#define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */
+#define GMAC_RX_UNITSIZE 1536 /**< Fixed size for RX buffer */
+
+//#define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */
+#define GMAC_TX_UNITSIZE 1536 /**< Size for ETH frame length */
+
+/** GMAC clock speed */
+#define GMAC_MCK_SPEED_240MHZ (240*1000*1000)
+#define GMAC_MCK_SPEED_160MHZ (160*1000*1000)
+#define GMAC_MCK_SPEED_120MHZ (120*1000*1000)
+#define GMAC_MCK_SPEED_80MHZ (80*1000*1000)
+#define GMAC_MCK_SPEED_40MHZ (40*1000*1000)
+#define GMAC_MCK_SPEED_20MHZ (20*1000*1000)
+
+/** GMAC maintain code default value*/
+#define GMAC_MAN_CODE_VALUE (10)
+
+/** GMAC maintain start of frame default value*/
+#define GMAC_MAN_SOF_VALUE (1)
+
+/** GMAC maintain read/write*/
+#define GMAC_MAN_RW_TYPE (2)
+
+/** GMAC maintain read only*/
+#define GMAC_MAN_READ_ONLY (1)
+
+/** GMAC address length */
+#define GMAC_ADDR_LENGTH (6)
+
+
+#define GMAC_DUPLEX_HALF 0
+#define GMAC_DUPLEX_FULL 1
+
+#define GMAC_SPEED_10M 0
+#define GMAC_SPEED_100M 1
+
+/**
+ * \brief Return codes for GMAC APIs.
+ */
+typedef enum {
+ GMAC_OK = 0, /** 0 Operation OK */
+ GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */
+ GMAC_TX_BUSY, /** 2 TX in progress */
+ GMAC_RX_NO_DATA, /** 3 No data received */
+ GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */
+ GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */
+ GMAC_RX_ERROR, /** 6 RX error */
+ GMAC_INVALID = 0xFF, /* Invalid */
+} gmac_status_t;
+
+/**
+ * \brief Media Independent Interface (MII) type.
+ */
+typedef enum {
+ GMAC_PHY_MII = 0, /** MII mode */
+ GMAC_PHY_RMII = 1, /** Reduced MII mode */
+ GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/
+} gmac_mii_mode_t;
+
+/* This is the list of GMAC priority queue */
+typedef enum {
+ GMAC_QUE_0 = 0,
+#if !(SAM4E)
+ GMAC_QUE_1 = 1,
+ GMAC_QUE_2 = 2,
+ /* Only SAM E70 Rev-B. */
+ GMAC_QUE_3 = 3,
+ GMAC_QUE_4 = 4,
+ GMAC_QUE_5 = 5,
+#endif
+# if !defined(__DOXYGEN__)
+ GMAC_QUE_N,
+# endif
+
+}gmac_quelist_t;
+
+/** Receive buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_rx_descriptor {
+ union gmac_rx_addr {
+ uint32_t val;
+ struct gmac_rx_addr_bm {
+ uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */
+ b_wrap:1, /**< Marks last descriptor in receive buffer */
+ addr_dw:30; /**< Address in number of DW */
+ } bm;
+ } addr; /**< Address, Wrap & Ownership */
+ union gmac_rx_status {
+ uint32_t val;
+ struct gmac_rx_status_bm {
+ uint32_t b_len:13, /** 0..12 Length of frame including FCS */
+ b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */
+ b_sof:1, /** 14 Start of frame */
+ b_eof:1, /** 15 End of frame */
+ b_cfi:1, /** 16 Concatenation Format Indicator */
+ b_vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */
+ b_priority_detected:1, /** 20 Priority tag detected */
+ b_vlan_detected:1, /** 21 VLAN tag detected */
+ b_type_id_match:2, /** 22..23 Type ID match */
+ b_checksumoffload:1, /** 24 Checksum offload specific function */
+ b_addrmatch:2, /** 25..26 Address register match */
+ b_ext_addr_match:1, /** 27 External address match found */
+ reserved:1, /** 28 */
+ b_uni_hash_match:1, /** 29 Unicast hash match */
+ b_multi_hash_match:1, /** 30 Multicast hash match */
+ b_boardcast_detect:1; /** 31 Global broadcast address detected */
+ } bm;
+ } status;
+} gmac_rx_descriptor_t;
+
+/** Transmit buffer descriptor struct */
+COMPILER_PACK_SET(8)
+typedef struct gmac_tx_descriptor {
+ uint32_t addr;
+ union gmac_tx_status {
+ uint32_t val;
+ struct gmac_tx_status_bm {
+ uint32_t b_len:14, /** 0..13 Length of buffer */
+ reserved:1, /** 14 */
+ b_last_buffer:1, /** 15 Last buffer (in the current frame) */
+ b_no_crc:1, /** 16 No CRC */
+ reserved1:3, /** 17..19 */
+ b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */
+ reserved2:3, /** 23..25 */
+ b_lco:1, /** 26 Late collision, transmit error detected */
+ b_exhausted:1, /** 27 Buffer exhausted in mid frame */
+ b_underrun:1, /** 28 Transmit underrun */
+ b_error:1, /** 29 Retry limit exceeded, error detected */
+ b_wrap:1, /** 30 Marks last descriptor in TD list */
+ b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */
+ } bm;
+ } status;
+} gmac_tx_descriptor_t;
+
+COMPILER_PACK_RESET()
+
+/**
+ * \brief Input parameters when initializing the gmac module mode.
+ */
+typedef struct gmac_options {
+ /* Enable/Disable CopyAllFrame */
+ uint8_t uc_copy_all_frame;
+ /* Enable/Disable NoBroadCast */
+ uint8_t uc_no_boardcast;
+ /* MAC address */
+ uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];
+} gmac_options_t;
+
+/** Wakeup callback */
+typedef void (*gmac_dev_wakeup_cb_t) (void);
+
+/**
+ * GMAC driver structure.
+ */
+typedef struct gmac_device {
+
+ /** Pointer to HW register base */
+ Gmac *p_hw;
+ /**
+ * Pointer to allocated TX buffer.
+ * Section 3.6 of AMBA 2.0 spec states that burst should not cross
+ * 1K Boundaries.
+ * Receive buffer manager writes are burst of 2 words => 3 lsb bits
+ * of the address shall be set to 0.
+ */
+#if( GMAC_USES_WAKEUP_CALLBACK != 0 )
+ /** Optional callback to be invoked once several TDs have been released */
+ gmac_dev_wakeup_cb_t func_wakeup_cb;
+#endif
+ /** RX index for current processing TD */
+ uint32_t ul_rx_idx;
+ /** Circular buffer head pointer by upper layer (buffer to be sent) */
+ int32_t l_tx_head;
+ /** Circular buffer tail pointer incremented by handlers (buffer sent) */
+ int32_t l_tx_tail;
+
+ /** Number of free TD before wakeup callback is invoked */
+ uint32_t ul_wakeup_threshold;
+} gmac_device_t;
+
+uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry);
+
+/**
+ * \brief Write network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_ncr Network control value.
+ */
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)
+{
+ p_gmac->GMAC_NCR = ul_ncr;
+}
+
+/**
+ * \brief Get network control value.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCR;
+}
+
+/**
+ * \brief Enable/Disable GMAC receive.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC transmit.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC transmit, else to enable it.
+ */
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable GMAC management.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable GMAC management, else to enable it.
+ */
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_MPE;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
+ }
+}
+
+/**
+ * \brief Clear all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_clear_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
+}
+
+/**
+ * \brief Increase all statistics registers.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_increase_statistics(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
+}
+
+/**
+ * \brief Enable/Disable statistics registers writing.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the statistics registers writing, else to enable it.
+ */
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,
+ uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
+ }
+}
+
+/**
+ * \brief In half-duplex mode, forces collisions on all received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the back pressure, else to enable it.
+ */
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_BP;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;
+ }
+}
+
+/**
+ * \brief Start transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_start_transmission(Gmac* p_gmac)
+{
+ __DSB();
+ p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;
+}
+
+/**
+ * \brief Halt transmission.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_halt_transmission(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_THALT;
+}
+
+/**
+ * \brief Transmit pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;
+}
+
+/**
+ * \brief Transmit zero quantum pause frame.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;
+}
+
+/**
+ * \brief Store receivetime stamp to memory.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to normal operation, else to enable the store.
+ */
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;
+ }
+}
+
+/**
+ * \brief Enable PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to set the reception, 0 to disable.
+ */
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;
+ } else {
+ p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;
+ }
+}
+
+/**
+ * \brief Transmit PFC priority-based pause reception.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;
+}
+
+/**
+ * \brief Flush next packet.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_flush_next_packet(Gmac* p_gmac)
+{
+ p_gmac->GMAC_NCR |= GMAC_NCR_FNP;
+}
+
+/**
+ * \brief Set up network configuration register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_cfg Network configuration value.
+ */
+static inline void gmac_set_config(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_NCFGR = ul_cfg;
+}
+
+/* Get and set DMA Configuration Register */
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)
+{
+ p_gmac->GMAC_DCFGR = ul_cfg;
+}
+
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_DCFGR;
+}
+
+/**
+ * \brief Get network configuration.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network configuration.
+ */
+static inline uint32_t gmac_get_config(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NCFGR;
+}
+
+/**
+ * \brief Set speed.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
+ */
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)
+{
+ if (uc_speed) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Full-Duplex mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.
+ */
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
+ }
+}
+
+/**
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable copying all valid frames, else to enable it.
+ */
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
+ }
+}
+
+/**
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the jumbo frames, else to enable it.
+ */
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;
+ }
+}
+
+/**
+ * \brief Disable/Enable broadcast receiving.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 1 to disable the broadcast, else to enable it.
+ */
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;
+ }
+}
+
+/**
+ * \brief Enable/Disable multicast hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the multicast hash, else to enable it.
+ */
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;
+ }
+}
+
+/**
+ * \brief Enable/Disable big frames (over 1518, up to 1536).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable big frames else to enable it.
+ */
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;
+ }
+}
+
+/**
+ * \brief Set MDC clock divider.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_mck GMAC MCK.
+ *
+ * \return GMAC_OK if successfully.
+ */
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)
+{
+ uint32_t ul_clk, ul_value;
+
+ if (ul_mck > GMAC_MCK_SPEED_240MHZ) {
+ return GMAC_INVALID;
+ } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_96;
+ } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_64;
+ } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_48;
+ } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_32;
+ } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {
+ ul_clk = GMAC_NCFGR_CLK_MCK_16;
+ } else {
+ ul_clk = GMAC_NCFGR_CLK_MCK_8;
+ }
+ ul_value = p_gmac->GMAC_NCFGR;
+ ul_value &= ~GMAC_NCFGR_CLK_Msk;
+ ul_value |= ul_clk;
+ p_gmac->GMAC_NCFGR = ul_value;
+ return GMAC_OK;
+}
+
+/**
+ * \brief Enable/Disable retry test.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the GMAC receiver, else to enable it.
+ */
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;
+ }
+}
+
+/**
+ * \brief Enable/Disable pause (when a valid pause frame is received).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable pause frame, else to enable it.
+ */
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;
+ }
+}
+
+/**
+ * \brief Set receive buffer offset to 0 ~ 3.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)
+{
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);
+}
+
+/**
+ * \brief Enable/Disable receive length field checking.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable receive length field checking, else to enable it.
+ */
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;
+ }
+}
+
+/**
+ * \brief Enable/Disable discarding FCS field of received frames.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.
+ */
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;
+ }
+}
+
+
+/**
+ * \brief Enable/Disable frames to be received in half-duplex mode
+ * while transmitting.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.
+ */
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;
+ }
+}
+
+/**
+ * \brief Enable/Disable ignore RX FCS.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable ignore RX FCS, else to enable it.
+ */
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;
+ } else {
+ p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;
+ }
+}
+
+/**
+ * \brief Get Network Status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Network status.
+ */
+static inline uint32_t gmac_get_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_NSR;
+}
+
+/**
+ * \brief Get MDIO IN pin status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return MDIO IN pin status.
+ */
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);
+}
+
+/**
+ * \brief Check if PHY is idle.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return 1 if PHY is idle.
+ */
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)
+{
+ return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
+}
+
+/**
+ * \brief Return transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Transmit status.
+ */
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TSR;
+}
+
+/**
+ * \brief Clear transmit status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Transmit status.
+ */
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_TSR = ul_status;
+}
+
+/**
+ * \brief Return receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ */
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RSR;
+}
+
+/**
+ * \brief Clear receive status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_status Receive status.
+ */
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)
+{
+ p_gmac->GMAC_RSR = ul_status;
+}
+
+/**
+ * \brief Set Rx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Rx queue address.
+ */
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Set Rx buffer size.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Rx buffer.
+ */
+static inline void gmac_set_rx_bufsize(Gmac* p_gmac, uint32_t ul_code)
+{
+ p_gmac->GMAC_DCFGR = (p_gmac->GMAC_DCFGR & ~GMAC_DCFGR_DRBS_Msk)
+ | GMAC_DCFGR_DRBS(ul_code);
+}
+
+/**
+ * \brief Get Rx Queue Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_RBQB;
+}
+
+/**
+ * \brief Set Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_addr Tx queue address.
+ */
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)
+{
+ p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get Tx Queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Rx queue address.
+ */
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_TBQB;
+}
+
+/**
+ * \brief Enable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be enabled.
+ */
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IER = ul_source;
+}
+
+/**
+ * \brief Disable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be disabled.
+ */
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)
+{
+ p_gmac->GMAC_IDR = ul_source;
+}
+
+/**
+ * \brief Return interrupt status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt status.
+ */
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_ISR;
+}
+
+/**
+ * \brief Return interrupt mask.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Interrupt mask.
+ */
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)
+{
+ return p_gmac->GMAC_IMR;
+}
+
+/**
+ * \brief Execute PHY maintenance command.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_phy_addr PHY address.
+ * \param uc_reg_addr Register address.
+ * \param uc_rw 1 to Read, 0 to write.
+ * \param us_data Data to be performed, write only.
+ */
+static inline void gmac_maintain_phy(Gmac* p_gmac,
+ uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
+ uint16_t us_data)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Write maintain register */
+ p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)
+ | GMAC_MAN_CLTTO
+ | GMAC_MAN_PHYA(uc_phy_addr)
+ | GMAC_MAN_REGA(uc_reg_addr)
+ | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))
+ | GMAC_MAN_DATA(us_data);
+}
+
+/**
+ * \brief Get PHY maintenance data returned.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ *
+ * \return Get PHY data.
+ */
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)
+{
+ /* Wait until bus idle */
+ while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
+ /* Return data */
+ return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
+}
+
+/**
+ * \brief Set Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_hash_top Hash top.
+ * \param ul_hash_bottom Hash bottom.
+ */
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,
+ uint32_t ul_hash_bottom)
+{
+ p_gmac->GMAC_HRB = ul_hash_bottom;
+ p_gmac->GMAC_HRT = ul_hash_top;
+}
+
+/**
+ * \brief Set 64 bits Hash.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ull_hash 64 bits hash value.
+ */
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)
+{
+ p_gmac->GMAC_HRB = (uint32_t) ull_hash;
+ p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);
+}
+
+/**
+ * \brief Set MAC Address.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param p_mac_addr GMAC address.
+ */
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,
+ const uint8_t* p_mac_addr)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)
+ | (p_mac_addr[2] << 16)
+ | (p_mac_addr[1] << 8)
+ | (p_mac_addr[0]);
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)
+ | (p_mac_addr[4]);
+}
+
+/**
+ * \brief Set MAC Address via 2 dword.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ul_mac_top GMAC top address.
+ * \param ul_mac_bottom GMAC bottom address.
+ */
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,
+ uint32_t ul_mac_top, uint32_t ul_mac_bottom)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;
+}
+
+/**
+ * \brief Set MAC Address via int64.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_index GMAC specific address register index.
+ * \param ull_mac 64-bit GMAC address.
+ */
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,
+ uint64_t ull_mac)
+{
+ p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;
+ p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);
+}
+
+/**
+ * \brief Select media independent interface mode.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param mode Media independent interface mode.
+ */
+#if (SAM4E)
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
+{
+ switch (mode) {
+ case GMAC_PHY_MII:
+ case GMAC_PHY_RMII:
+ p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;
+ break;
+
+ default:
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
+ break;
+ }
+}
+#else
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)
+{
+ switch (mode) {
+ case GMAC_PHY_MII:
+ p_gmac->GMAC_UR |= GMAC_UR_RMII;
+ break;
+
+ case GMAC_PHY_RMII:
+ default:
+ p_gmac->GMAC_UR &= ~GMAC_UR_RMII;
+ break;
+ }
+}
+#endif
+
+#if !(SAM4E)
+/**
+ * \brief Set 1588 timer comparison.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param seconds47 Second comparison high
+ * \param seconds31 Second comparison low
+ * \param nanosec Nanosecond Comparison
+ */
+static inline void gmac_set_tsu_compare(Gmac *p_gmac, uint32_t seconds47, uint32_t seconds31, uint32_t nanosec)
+{
+ p_gmac->GMAC_SCH = seconds47;
+ p_gmac->GMAC_SCL = seconds31;
+ p_gmac->GMAC_NSC = nanosec;
+}
+
+/**
+ * \brief Get interrupt status.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Interrupt status.
+ */
+static inline uint32_t gmac_get_priority_interrupt_status(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_ISRPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set base address of TX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_tx_priority_queue(Gmac* p_gmac, uint32_t ul_addr, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_TBQBAPQ[queue_idx - 1] = GMAC_TBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get base address of TX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Base address.
+ */
+static inline uint32_t gmac_get_tx_priority_queue(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_TBQBAPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set base address of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_rx_priority_queue(Gmac* p_gmac, uint32_t ul_addr, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_RBQBAPQ[queue_idx - 1] = GMAC_RBQB_ADDR_Msk & ul_addr;
+}
+
+/**
+ * \brief Get base address of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Base address.
+ */
+static inline uint32_t gmac_get_rx_priority_queue(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_RBQBAPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set size of RX buffer.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_set_rx_priority_bufsize(Gmac* p_gmac, uint32_t ul_size, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_RBSRPQ[queue_idx - 1] = ul_size;
+}
+
+/**
+ * \brief Enable or disable credit-based shaping on the second highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable, 1 to enable it
+ */
+static inline void gmac_enable_cbsque_a(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_CBSCR |= GMAC_CBSCR_QAE;
+ } else {
+ p_gmac->GMAC_CBSCR &= ~GMAC_CBSCR_QAE;
+ }
+}
+
+/**
+ * \brief Enable or disable credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param uc_enable 0 to disable, 1 to enable it
+ */
+static inline void gmac_enable_cbsque_b(Gmac* p_gmac, uint8_t uc_enable)
+{
+ if (uc_enable) {
+ p_gmac->GMAC_CBSCR |= GMAC_CBSCR_QBE;
+ } else {
+ p_gmac->GMAC_CBSCR &= ~GMAC_CBSCR_QBE;
+ }
+}
+
+/**
+ * \brief Set credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param idleslope_a Value for queue A in bytes/second
+ */
+static inline void gmac_config_idleslope_a(Gmac* p_gmac, uint32_t idleslope_a)
+{
+ p_gmac->GMAC_CBSISQA = idleslope_a;
+}
+
+/**
+ * \brief Set credit-based shaping on the highest priority queue.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param idleslope_b Value for queue B in bytes/second
+ */
+static inline void gmac_config_idleslope_b(Gmac* p_gmac, uint32_t idleslope_b)
+{
+ p_gmac->GMAC_CBSISQB = idleslope_b;
+}
+
+/**
+ * \brief Set screening type 1 register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param reg_val Value for screening type 1
+ * \param index Index of register
+ */
+static inline void gmac_write_screener_reg_1(Gmac* p_gmac, uint32_t reg_val, uint32_t index)
+{
+ p_gmac->GMAC_ST1RPQ[index] = reg_val;
+}
+
+/**
+ * \brief Set screening type 2 register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param reg_val Value for screening type 2
+ * \param index Index of register
+ */
+static inline void gmac_write_screener_reg_2 (Gmac* p_gmac, uint32_t reg_val, uint32_t index)
+{
+ p_gmac->GMAC_ST2RPQ[index] = reg_val;
+}
+
+/**
+ * \brief Enable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be enabled.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_enable_priority_interrupt(Gmac* p_gmac, uint32_t ul_source, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_IERPQ[queue_idx - 1] = ul_source;
+}
+
+/**
+ * \brief Disable interrupt(s).
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ul_source Interrupt source(s) to be disabled.
+ * \param queue_idx Index of queue, start from 1
+ */
+static inline void gmac_disable_priority_interrupt(Gmac* p_gmac, uint32_t ul_source, gmac_quelist_t queue_idx)
+{
+ p_gmac->GMAC_IDRPQ[queue_idx - 1] = ul_source;
+}
+
+/**
+ * \brief Get interrupt mask.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param queue_idx Index of queue, start from 1
+ *
+ * \return Interrupt mask.
+ */
+static inline uint32_t gmac_get_priority_interrupt_mask(Gmac* p_gmac, gmac_quelist_t queue_idx)
+{
+ return p_gmac->GMAC_IMRPQ[queue_idx - 1];
+}
+
+/**
+ * \brief Set screening type 2 eherType register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param ethertype Ethertype compare value
+ * \param index Index of register
+ */
+static inline void gmac_write_ethtype_reg(Gmac* p_gmac, uint16_t ethertype, uint32_t index)
+{
+ p_gmac->GMAC_ST2ER[index] = (uint32_t)ethertype;
+}
+
+/**
+ * \brief Set screening type 2 compare word register.
+ *
+ * \param p_gmac Pointer to the GMAC instance.
+ * \param c0reg Compare value 0
+ * \param c1reg Compare value 1
+ * \param index Index of register
+ */
+static inline void gmac_write_screen_compare_reg(Gmac* p_gmac, uint32_t c0reg, uint16_t c1reg, uint32_t index)
+{
+ volatile uint32_t *p_PRAS;
+ uint32_t ul_dlt;
+
+ ul_dlt = (uint32_t)&(p_gmac->GMAC_ST2CW01);
+ ul_dlt = ul_dlt - (uint32_t)&(p_gmac->GMAC_ST2CW00);
+
+ p_PRAS = (volatile uint32_t *)((uint32_t)&(p_gmac->GMAC_ST2CW00) +
+ index * ul_dlt);
+ *p_PRAS = c0reg;
+ p_PRAS = (volatile uint32_t *)((uint32_t)&(p_gmac->GMAC_ST2CW10) +
+ index * ul_dlt);
+ *p_PRAS = (uint32_t)c1reg;
+}
+
+#endif /* !(SAM4E) */
+
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,
+ uint32_t* p_value);
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,
+ uint8_t uc_address, uint32_t ul_value);
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,
+ gmac_options_t* p_opt);
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,
+ uint32_t ul_frame_size, uint32_t* p_rcv_size, uint8_t** pp_recv_frame);
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,
+ uint32_t ul_size);
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,
+ gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);
+void gmac_handler(gmac_device_t* p_gmac_dev);
+
+void gmac_reset_tx_mem(gmac_device_t* p_dev);
+
+/// @cond 0
+/**INDENT-OFF**/
+#ifdef __cplusplus
+}
+#endif
+/**INDENT-ON**/
+/// @endcond
+
+
+# define GMAC_STATS 0
+
+#if( GMAC_STATS != 0 )
+
+ /* Here below some code to study the types and
+ frequencies of GMAC interrupts. */
+ #define GMAC_IDX_RXUBR 0
+ #define GMAC_IDX_TUR 1
+ #define GMAC_IDX_RLEX 2
+ #define GMAC_IDX_TFC 3
+ #define GMAC_IDX_RCOMP 4
+ #define GMAC_IDX_TCOMP 5
+ #define GMAC_IDX_ROVR 6
+ #define GMAC_IDX_HRESP 7
+ #define GMAC_IDX_PFNZ 8
+ #define GMAC_IDX_PTZ 9
+
+ struct SGmacStats {
+ unsigned recvCount;
+ unsigned rovrCount;
+ unsigned bnaCount;
+ unsigned sendCount;
+ unsigned sovrCount;
+ unsigned incompCount;
+ unsigned truncCount;
+
+ unsigned intStatus[10];
+ };
+ extern struct SGmacStats gmacStats;
+
+ struct SIntPair {
+ const char *name;
+ unsigned mask;
+ int index;
+ };
+
+ #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME
+ static const struct SIntPair intPairs[] = {
+ { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */
+ { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */
+ { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */
+ { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */
+ { MK_PAIR( RCOMP ) }, /* Receive complete */
+ { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */
+ { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */
+ { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */
+ { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */
+ { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */
+ };
+
+ void gmac_show_irq_counts ();
+
+#endif
+
+#endif /* GMAC_H_INCLUDED */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
index e0d04e454..8bd539614 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -100,7 +100,7 @@ extern uint8_t ucMACAddress[ 6 ];
if( xStatus != ERROR )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
- configASSERT( xEMACRxEventSemaphore );
+ configASSERT( xEMACRxEventSemaphore != NULL );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
@@ -212,7 +212,7 @@ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters;
- configASSERT( xEMACRxEventSemaphore );
+ configASSERT( xEMACRxEventSemaphore != NULL );
for( ;; )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
index ac01d41af..e01602b9d 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -81,7 +81,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#ifndef iptraceEMAC_TASK_STARTING
- #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
+ #define iptraceEMAC_TASK_STARTING() do { } while( ipFALSE_BOOL )
#endif
/* Define the bits of .STATUS that indicate a reception error. */
@@ -284,7 +284,7 @@ BaseType_t xReturn = pdPASS;
if( xRxHanderTask == NULL )
{
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
- configASSERT( xReturn );
+ configASSERT( xReturn != NULL );
}
if( xTXDescriptorSemaphore == NULL )
@@ -292,7 +292,7 @@ BaseType_t xReturn = pdPASS;
/* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'
and a maximum of 'configNUM_TX_DESCRIPTORS'. */
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );
- configASSERT( xTXDescriptorSemaphore );
+ configASSERT( xTXDescriptorSemaphore != NULL );
}
/* Enable MAC interrupts. */
@@ -526,7 +526,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will
often not use a malloc() failed hook as the TCP stack will recover
from allocation failures. */
- configASSERT( xDMATxDescriptors[ x ].B1ADD );
+ configASSERT( xDMATxDescriptors[ x ].B1ADD != 0U );
}
#endif
@@ -592,7 +592,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will often
not use a malloc failed hook as the TCP stack will recover from
allocation failures. */
- configASSERT( xDMARxDescriptors[ x ].B1ADD );
+ configASSERT( xDMARxDescriptors[ x ].B1ADD != 0U );
xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );
xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
index e759141cc..2149a7bdd 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/M487/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
index 44d19f3a9..92b1573f7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
index 84019d637..aa3a1f58e 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
@@ -4,7 +4,7 @@
*/
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -828,7 +828,7 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
#endif
) {
/* Drop this packet, not for this device. */
- FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) );
+ /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */
return pdFALSE;
}
}
@@ -1178,9 +1178,9 @@ BaseType_t xReturn;
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
static
-#if defined(STM32F7xx)
- __attribute__ ((section(".first_data")))
-#endif
+ #if defined(STM32F7xx)
+ __attribute__ ((section(".first_data")))
+ #endif
uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
index 474629e46..511b27859 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -445,6 +445,11 @@ void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_
if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
{
+ /* The received packets will be written to a C source file,
+ only if 'ipconfigUSE_DUMP_PACKETS' is defined.
+ Otherwise, there is no action. */
+ iptraceDUMP_PACKET( ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen, pdTRUE );
+
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );
}
@@ -489,6 +494,10 @@ const DWORD xMaxMSToWait = 1000;
{
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
+ /* The packets sent will be written to a C source file,
+ only if 'ipconfigUSE_DUMP_PACKETS' is defined.
+ Otherwise, there is no action. */
+ iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE );
if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
{
ulWinPCAPSendFailures++;
@@ -498,6 +507,31 @@ const DWORD xMaxMSToWait = 1000;
}
/*-----------------------------------------------------------*/
+static BaseType_t xPacketBouncedBack( const uint8_t *pucBuffer )
+{
+EthernetHeader_t *pxEtherHeader;
+BaseType_t xResult;
+
+ pxEtherHeader = ( EthernetHeader_t * ) pucBuffer;
+ if( memcmp( ucMACAddress, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
+ {
+ FreeRTOS_printf( ( "Bounced back: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pxEtherHeader->xSourceAddress.ucBytes[ 0 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 1 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 2 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 3 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 4 ],
+ pxEtherHeader->xSourceAddress.ucBytes[ 5 ] ) );
+ xResult = pdTRUE;
+ }
+ else
+ {
+ xResult = pdFALSE;
+ }
+ return xResult;
+}
+/*-----------------------------------------------------------*/
+
static void prvInterruptSimulatorTask( void *pvParameters )
{
struct pcap_pkthdr xHeader;
@@ -545,7 +579,14 @@ eFrameProcessingResult_t eResult;
is ok to call the task level function here, but note that
some buffer implementations cannot be called from a real
interrupt. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+ if( xPacketBouncedBack( pucPacketData ) == pdFALSE )
+ {
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+ }
+ else
+ {
+ pxNetworkBuffer = NULL;
+ }
if( pxNetworkBuffer != NULL )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
index 4a6af81f9..dab007ba8 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
@@ -238,7 +238,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer,
}
}
#endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
- if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL )
+ if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0UL )
{
iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
index 10a72b464..a1185c104 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
@@ -10,6 +10,11 @@ Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
+The file uncached_memory.c can also be found in:
+
+ vendors\xilinx\boards\microzed\aws_demos\application_code\xilinx_code
+ vendors\xilinx\boards\microzed\aws_tests\application_code\xilinx_code
+
And include the following source files from the Xilinx library:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
index aa0a646b4..251640d7e 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/board_family/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -41,23 +41,23 @@ considers need processing. */
BaseType_t xNetworkInterfaceInitialise( void )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
- /* FIX ME. */
+ /* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
- /* FIX ME. */
- return pdFALSE;
+ /* FIX ME. */
+ return pdFALSE;
} \ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
index 544e5ba09..4df3ac370 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -351,7 +351,7 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
}
/* When returning non-zero, the stack will become active and
@@ -1059,7 +1059,7 @@ static void ksz8851snl_low_level_init( void )
if( ksz8851snl_init() < 0 )
{
FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );
- configASSERT(0 == 1);
+ configASSERT( ipFALSE_BOOL );
}
memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );
ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );
@@ -1166,7 +1166,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
- configASSERT( xEMACTaskHandle );
+ configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c
new file mode 100644
index 000000000..41f28a0d2
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/linux/NetworkInterface.c
@@ -0,0 +1,889 @@
+/*
+FreeRTOS+TCP V2.0.11
+Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+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.
+
+ http://aws.amazon.com/freertos
+ http://www.FreeRTOS.org
+*/
+
+/* ========================= FreeRTOS includes ============================== */
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#include "semphr.h"
+
+/* ========================= FreeRTOS+TCP includes ========================== */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_IP_Private.h"
+#include "NetworkBufferManagement.h"
+#include "FreeRTOS_Stream_Buffer.h"
+
+/* ======================== Standard Library inludes ======================== */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/sysinfo.h>
+#include <signal.h>
+#include <pcap.h>
+
+/* ========================== Local includes =================================*/
+#include "utils/wait_for_event.h"
+
+/* ======================== Macro Definitions =============================== */
+#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
+#else
+ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) \
+ eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
+#endif
+
+/* ============================== Definitions =============================== */
+#define xSEND_BUFFER_SIZE 32768
+#define xRECV_BUFFER_SIZE 32768
+#define MAX_CAPTURE_LEN 65535
+#define IP_SIZE 100
+
+/* ================== Static Function Prototypes ============================ */
+static int prvConfigureCaptureBehaviour( void );
+static int prvCreateThreadSafeBuffers( void );
+static void * prvLinuxPcapSendThread( void *pvParam );
+static void * prvLinuxPcapRecvThread( void *pvParam );
+static void prvInterruptSimulatorTask( void *pvParameters );
+static void prvPrintAvailableNetworkInterfaces( pcap_if_t * pxAllNetworkInterfaces );
+static pcap_if_t * prvGetAvailableNetworkInterfaces( void );
+static const char * prvRemoveSpaces( char *pcBuffer,
+ int aBuflen,
+ const char *pcMessage );
+static int prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );
+static int prvCreateWorkerThreads( void );
+static int prvSetDeviceModes( void );
+static void print_hex( unsigned const char * const bin_data,
+ size_t len );
+
+/* ======================== Static Global Variables ========================= */
+static StreamBuffer_t *xSendBuffer = NULL;
+static StreamBuffer_t *xRecvBuffer = NULL;
+extern uint8_t ucMACAddress[ 6 ];
+static char errbuf[ PCAP_ERRBUF_SIZE ];
+static pcap_t *pxOpenedInterfaceHandle = NULL;
+static struct event *pvSendEvent = NULL;
+static uint32_t ulPCAPSendFailures = 0;
+static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;
+static BaseType_t xInvalidInterfaceDetected = pdFALSE;
+
+/* ======================= API Function definitions ========================= */
+
+/*!
+ * @brief API call, called from reeRTOS_IP.c to initialize the capture device
+ * to be able to send and receive packets
+ * @return pdPASS if successful else pdFAIL
+ */
+BaseType_t xNetworkInterfaceInitialise( void )
+{
+BaseType_t ret = pdFAIL;
+pcap_if_t *pxAllNetworkInterfaces;
+
+ /* Query the computer the simulation is being executed on to find the
+ network interfaces it has installed. */
+ pxAllNetworkInterfaces = prvGetAvailableNetworkInterfaces();
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ prvPrintAvailableNetworkInterfaces( pxAllNetworkInterfaces );
+ ret = prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );
+
+ if( ret == pdPASS )
+ {
+ ret = prvCreateThreadSafeBuffers();
+
+ if( ret == pdPASS )
+ {
+ ret = prvCreateWorkerThreads();
+ }
+ }
+
+ /* The device list is no longer required. */
+ pcap_freealldevs( pxAllNetworkInterfaces );
+ }
+
+ if( ( pxOpenedInterfaceHandle != NULL ) && ( ret == pdPASS ) )
+ {
+ ret = pdPASS;
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief API call, called from reeRTOS_IP.c to send a network packet over the
+ * selected interface
+ * @return pdTRUE if successful else pdFALSE
+ */
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
+ BaseType_t bReleaseAfterSend )
+{
+size_t xSpace;
+
+ iptraceNETWORK_INTERFACE_TRANSMIT();
+ configASSERT( xIsCallingFromIPTask() == pdTRUE );
+
+ /* Both the length of the data being sent and the actual data being sent
+ are placed in the thread safe buffer used to pass data between the FreeRTOS
+ tasks and the pthread that sends data via the pcap library. Drop
+ the packet if there is insufficient space in the buffer to hold both. */
+ xSpace = uxStreamBufferGetSpace( xSendBuffer );
+
+ if( ( pxNetworkBuffer->xDataLength <=
+ ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
+ ( xSpace >= ( pxNetworkBuffer->xDataLength +
+ sizeof( pxNetworkBuffer->xDataLength ) ) ) )
+ {
+ /* First write in the length of the data, then write in the data
+ itself. */
+ uxStreamBufferAdd( xSendBuffer,
+ 0,
+ ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ),
+ sizeof( pxNetworkBuffer->xDataLength ) );
+ uxStreamBufferAdd( xSendBuffer,
+ 0,
+ ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer,
+ pxNetworkBuffer->xDataLength );
+ }
+ else
+ {
+ FreeRTOS_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n",
+ pxNetworkBuffer->xDataLength ) );
+ }
+
+ /* Kick the Tx task in either case in case it doesn't know the buffer is
+ full. */
+ event_signal( pvSendEvent );
+
+ /* The buffer has been sent so can be released. */
+ if( bReleaseAfterSend != pdFALSE )
+ {
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ }
+
+ return pdPASS;
+}
+
+/* ====================== Static Function definitions ======================= */
+
+/*!
+ * @brief create thread safe buffers to send/receive packets between threads
+ * @returns
+ */
+static int prvCreateThreadSafeBuffers( void )
+{
+int ret = pdFAIL;
+
+ /* The buffer used to pass data to be transmitted from a FreeRTOS task to
+ the linux thread that sends via the pcap library. */
+ do
+ {
+ if( xSendBuffer == NULL )
+ {
+ xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );
+
+ if( xSendBuffer == NULL )
+ {
+ break;
+ }
+
+ configASSERT( xSendBuffer );
+ memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );
+ xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;
+ }
+
+ /* The buffer used to pass received data from the pthread that receives
+ via the pcap library to the FreeRTOS task. */
+ if( xRecvBuffer == NULL )
+ {
+ xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );
+
+ if( xRecvBuffer == NULL )
+ {
+ break;
+ }
+
+ configASSERT( xRecvBuffer );
+ memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );
+ xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ return ret;
+}
+
+/*!
+ * @brief print network interfaces available on the system
+ * @param[in] pxAllNetworkInterfaces interface structure list to print
+ */
+static void prvPrintAvailableNetworkInterfaces( pcap_if_t * pxAllNetworkInterfaces )
+{
+pcap_if_t *xInterface;
+int32_t lInterfaceNumber = 1;
+char cBuffer[ 512 ];
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ /* Print out the list of network interfaces. The first in the list
+ is interface '1', not interface '0'. */
+ for( xInterface = pxAllNetworkInterfaces;
+ xInterface != NULL; xInterface = xInterface->next )
+ {
+ /* The descriptions of the devices can be full of spaces, clean them
+ a little. printf() can only be used here because the network is not
+ up yet - so no other network tasks will be running. */
+ printf( "Interface %d - %s\n",
+ lInterfaceNumber,
+ prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );
+ printf( " (%s)\n",
+ prvRemoveSpaces( cBuffer,
+ sizeof( cBuffer ),
+ xInterface->description ? xInterface->description :
+ "No description" ) );
+ printf( "\n" );
+ lInterfaceNumber++;
+ }
+ }
+
+ if( lInterfaceNumber == 1 )
+ {
+ /* The interface number was never incremented, so the above for() loop
+ did not execute meaning no interfaces were found. */
+ printf( " \nNo network interfaces were found.\n" );
+ pxAllNetworkInterfaces = NULL;
+ }
+
+ printf( "\r\nThe interface that will be opened is set by " );
+ printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );
+
+ if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) )
+ {
+ printf( "\r\nERROR: configNETWORK_INTERFACE_TO_USE is set to %ld, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse );
+ printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );
+ printf( "then re-compile and re-start the application. Only Ethernet (as opposed to WiFi)\r\n" );
+ printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );
+ xInvalidInterfaceDetected = pdTRUE;
+
+ if( pxAllNetworkInterfaces != NULL )
+ {
+ /* Free the device list, as no devices are going to be opened. */
+ pcap_freealldevs( pxAllNetworkInterfaces );
+ pxAllNetworkInterfaces = NULL;
+ }
+ }
+ else
+ {
+ printf( "Attempting to open interface number %ld.\n", xConfigNetworkInterfaceToUse );
+ }
+}
+
+/*!
+ * @brief get network interfaces from the system
+ * @returns the structure list containing all found devices
+ */
+static pcap_if_t * prvGetAvailableNetworkInterfaces( void )
+{
+pcap_if_t * pxAllNetworkInterfaces = NULL;
+
+ if( xInvalidInterfaceDetected == pdFALSE )
+ {
+ int ret;
+ ret = pcap_findalldevs( &pxAllNetworkInterfaces, errbuf );
+
+ if( ret == PCAP_ERROR )
+ {
+ FreeRTOS_printf( ( "Could not obtain a list of network interfaces\n%s\n",
+ errbuf ) );
+ pxAllNetworkInterfaces = NULL;
+ }
+ else
+ {
+ printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );
+ }
+ }
+
+ return pxAllNetworkInterfaces;
+}
+
+/*!
+ * @brief set device operation modes
+ * @returns pdPASS on success pdFAIL on failure
+ */
+static int prvSetDeviceModes()
+{
+int ret = pdFAIL;
+
+ /*
+ Open in promiscuous mode as the MAC and
+ IP address is going to be "simulated", and
+ not be the real MAC and IP address. This allows
+ traffic to the simulated IP address to be routed
+ to uIP, and traffic to the real IP address to be
+ routed to the Linux TCP/IP stack.
+ */
+ FreeRTOS_debug_printf( ( "setting device modes of operation...\n" ) );
+
+ do
+ {
+ ret = pcap_set_promisc( pxOpenedInterfaceHandle, 1 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not activate promisuous mode\n" ) );
+ break;
+ }
+
+ ret = pcap_set_snaplen( pxOpenedInterfaceHandle,
+ ipTOTAL_ETHERNET_FRAME_SIZE );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set snaplen\n" ) );
+ break;
+ }
+
+ ret = pcap_set_timeout( pxOpenedInterfaceHandle, 200 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set timeout\n" ) );
+ break;
+ }
+
+ ret = pcap_set_buffer_size( pxOpenedInterfaceHandle,
+ ipTOTAL_ETHERNET_FRAME_SIZE * 1100 );
+
+ if( ( ret != 0 ) && ( ret != PCAP_ERROR_ACTIVATED ) )
+ {
+ FreeRTOS_printf( ( "coult not set buffer size\n" ) );
+ break;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ return ret;
+}
+
+/*!
+ * @brief open selected interface given its name
+ * @param [in] pucName interface name to pen
+ * @returns pdPASS on success pdFAIL on failure
+ */
+static int prvOpenInterface( const char *pucName )
+{
+static char pucInterfaceName[ 256 ];
+int ret = pdFAIL;
+
+ if( pucName != NULL )
+ {
+ ( void ) strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );
+ pucInterfaceName[ sizeof( pucInterfaceName ) - ( size_t ) 1 ] = '\0';
+
+ FreeRTOS_debug_printf( ( "opening interface %s\n", pucInterfaceName ) );
+
+ pxOpenedInterfaceHandle = pcap_create( pucInterfaceName, errbuf );
+
+ if( pxOpenedInterfaceHandle != NULL )
+ {
+ ret = prvSetDeviceModes();
+
+ if( ret == pdPASS )
+ {
+ if( pcap_activate( pxOpenedInterfaceHandle ) == 0 )
+ {
+ /* Configure the capture filter to allow blocking reads, and to filter
+ out packets that are not of interest to this demo. */
+ ret = prvConfigureCaptureBehaviour();
+ }
+ else
+ {
+ FreeRTOS_debug_printf( ( "pcap activate error %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) ) );
+ ret = pdFAIL;
+ }
+ }
+ }
+ else
+ {
+ FreeRTOS_printf( ( "\n%s is not supported by pcap and cannot be opened %s\n",
+ pucInterfaceName, errbuf ) );
+ }
+ }
+ else
+ {
+ FreeRTOS_printf( ( "could not open interface: name is null\n" ) );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief Open the network interface. The number of the interface to be opened is
+ * set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h
+ * Calling this function will set the pxOpenedInterfaceHandle variable
+ * If, after calling this function, pxOpenedInterfaceHandle
+ * is equal to NULL, then the interface could not be opened.
+ * @param [in] pxAllNetworkInterfaces network interface list to choose from
+ * @returns pdPASS on success or pdFAIL when something goes wrong
+ */
+static int prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )
+{
+pcap_if_t *pxInterface;
+int32_t x;
+int ret = pdFAIL;
+
+ /* Walk the list of devices until the selected device is located. */
+ pxInterface = pxAllNetworkInterfaces;
+
+ for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ )
+ {
+ pxInterface = pxInterface->next;
+ }
+
+ /* Open the selected interface. */
+ if( prvOpenInterface( pxInterface->name ) == pdPASS )
+ {
+ FreeRTOS_debug_printf( ( "Successfully opened interface number %d.\n", x + 1 ) );
+ ret = pdPASS;
+ }
+ else
+ {
+ FreeRTOS_printf( ( "Failed to open interface number %d.\n", x + 1 ) );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief launch 2 linux threads, one for Tx and one for Rx
+ * and one FreeRTOS thread that will simulate an interrupt
+ * and notify the tcp/ip stack of new data
+ * @return pdPASS on success otherwise pdFAIL
+ */
+static int prvCreateWorkerThreads( void )
+{
+pthread_t vPcapRecvThreadHandle;
+pthread_t vPcapSendThreadHandle;
+int ret = pdPASS;
+
+ if( pvSendEvent == NULL )
+ {
+ FreeRTOS_debug_printf( ( "Creating Threads ..\n" ) );
+ ret = pdFAIL;
+ /* Create event used to signal the pcap Tx thread. */
+ pvSendEvent = event_create();
+
+ do
+ {
+ /* Create the thread that handles pcap Rx. */
+ ret = pthread_create( &vPcapRecvThreadHandle,
+ NULL,
+ prvLinuxPcapRecvThread,
+ NULL );
+
+ if( ret != 0 )
+ {
+ FreeRTOS_printf( ( "pthread error %d", ret ) );
+ break;
+ }
+
+ /* Create the thread that handles pcap Tx. */
+ ret = pthread_create( &vPcapSendThreadHandle,
+ NULL,
+ prvLinuxPcapSendThread,
+ NULL );
+
+ if( ret != 0 )
+ {
+ FreeRTOS_printf( ( "pthread error %d", ret ) );
+ break;
+ }
+
+ ret = pdPASS;
+ } while( 0 );
+
+ /* Create a task that simulates an interrupt in a real system. This will
+ block waiting for packets, then send a message to the IP task when data
+ is available. */
+ if( xTaskCreate( prvInterruptSimulatorTask,
+ "MAC_ISR",
+ configMINIMAL_STACK_SIZE,
+ NULL,
+ configMAC_ISR_SIMULATOR_PRIORITY,
+ NULL ) != pdPASS )
+ {
+ ret = pdFAIL;
+ FreeRTOS_printf( ( "xTaskCreate could not create a new task\n" ) );
+ }
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief Create the buffers used to pass packets between the FreeRTOS simulator
+ * and the pthreads that are handling pcap as well as the FreeRTOS task
+ * responsible of simulating an interrupt.
+ * @returns pdPASS when successful and pdFAIL when there is a failure
+ */
+static int prvConfigureCaptureBehaviour( void )
+{
+ struct bpf_program xFilterCode;
+ uint32_t ulNetMask;
+ char pcap_filter[ 500 ];
+ int ret = pdFAIL;
+
+ FreeRTOS_debug_printf( ( "Configuring Capture behaviour\n" ) );
+
+ /* Set up a filter so only the packets of interest are passed to the IP
+ stack. errbuf is used for convenience to create the string. Don't
+ confuse this with an error message. */
+ sprintf( pcap_filter, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",
+ ucMACAddress[ 0 ],
+ ucMACAddress[ 1 ],
+ ucMACAddress[ 2 ],
+ ucMACAddress[ 3 ],
+ ucMACAddress[ 4 ],
+ ucMACAddress[ 5 ] );
+ FreeRTOS_debug_printf( ( "pcap filter to compile: %s\n", pcap_filter ) );
+
+ ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;
+
+ ret = pcap_compile( pxOpenedInterfaceHandle,
+ &xFilterCode,
+ pcap_filter,
+ 1,
+ ulNetMask );
+
+ if( ret < 0 )
+ {
+ ( void ) printf( "\nThe packet filter string is invalid %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) );
+ }
+ else
+ {
+ ret = pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode );
+
+ if( ret < 0 )
+ {
+ ( void ) printf( "\nAn error occurred setting the packet filter. %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) );
+ }
+ else
+ {
+ ret = pdPASS;
+ }
+
+ /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct
+ parameter.pcap_freecode() will free that memory. */
+ pcap_freecode( &xFilterCode );
+ }
+
+ return ret;
+}
+
+/*!
+ * @brief callback function called from pcap_dispatch function when new
+ * data arrives on the interface
+ * @param [in] user data sent to pcap_dispatch
+ * @param [in] pkt_header received packet header
+ * @param [in] pkt_data received packet data
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ */
+static void pcap_callback( unsigned char *user,
+ const struct pcap_pkthdr *pkt_header,
+ const u_char *pkt_data )
+{
+ FreeRTOS_debug_printf( ( "Receiving < =========== network callback user: %s len: %d caplen: %d\n",
+ user,
+ pkt_header->len,
+ pkt_header->caplen ) );
+ print_hex( pkt_data, pkt_header->len );
+
+ /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */
+ if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
+ ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
+ {
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_header, sizeof( *pkt_header ) );
+ uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t * ) pkt_data, ( size_t ) pkt_header->caplen );
+ }
+}
+
+/*!
+ * @brief infinite loop pthread to read from pcap
+ * @param [in] pvParam not used
+ * @returns NULL
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ * @remarks This function disables signal, to prevent it from being put into
+ * sleep byt the posix port
+ */
+static void * prvLinuxPcapRecvThread( void *pvParam )
+{
+int ret;
+
+ ( void ) pvParam;
+
+ /* Disable signals to this thread since this is a Linux pthread to be able to
+ * printf and other blocking operations without being interruped and put in
+ * suspension mode by the linux port signals
+ */
+ sigset_t set;
+ sigfillset( &set );
+ pthread_sigmask( SIG_SETMASK, &set, NULL );
+
+ for( ; ; )
+ {
+ ret = pcap_dispatch( pxOpenedInterfaceHandle, 1,
+ pcap_callback, ( u_char * ) "mydata" );
+
+ if( ret == -1 )
+ {
+ FreeRTOS_printf( ( "pcap_dispatch error received: %s\n",
+ pcap_geterr( pxOpenedInterfaceHandle ) ) );
+ }
+ }
+
+ return NULL;
+}
+
+/*!
+ * @brief Infinite loop thread that waits for events when there is data
+ * available then sends the data on the interface
+ * @param [in] pvParam not used
+ * @returns NULL
+ * @warning this is called from a Linux thread, do not attempt any FreeRTOS calls
+ */
+static void * prvLinuxPcapSendThread( void *pvParam )
+{
+size_t xLength;
+uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
+const time_t xMaxMSToWait = 1000;
+
+ ( void ) pvParam;
+
+ /* disable signals to avoid treating this thread as a FreeRTOS task and puting
+ * it to sleep by the scheduler */
+ sigset_t set;
+ sigfillset( &set );
+ pthread_sigmask( SIG_SETMASK, &set, NULL );
+
+ for( ; ; )
+ {
+ /* Wait until notified of something to send. */
+ event_wait_timed( pvSendEvent, xMaxMSToWait );
+
+ /* Is there more than the length value stored in the circular buffer
+ used to pass data from the FreeRTOS simulator into this pthread?*/
+ while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )
+ {
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
+ uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) ucBuffer, xLength, pdFALSE );
+ FreeRTOS_debug_printf( ( "Sending ========== > data pcap_sendpadcket %lu\n", xLength ) );
+ print_hex( ucBuffer, xLength );
+
+ if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
+ {
+ FreeRTOS_printf( ( "pcap_sendpackeet: send failed %d\n", ulPCAPSendFailures ) );
+ ulPCAPSendFailures++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*!
+ * @brief FreeRTOS infinite loop thread that simulates a network interrupt to notify the
+ * network stack of the presence of new data
+ * @param [in] pvParameters not used
+ */
+static void prvInterruptSimulatorTask( void *pvParameters )
+{
+ struct pcap_pkthdr xHeader;
+ static struct pcap_pkthdr *pxHeader;
+ const uint8_t *pucPacketData;
+ uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];
+ NetworkBufferDescriptor_t *pxNetworkBuffer;
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
+ eFrameProcessingResult_t eResult;
+
+ /* Remove compiler warnings about unused parameters. */
+ ( void ) pvParameters;
+
+ for( ; ; )
+ {
+ /* Does the circular buffer used to pass data from the pthread thread that
+ handles pacap Rx into the FreeRTOS simulator contain another packet? */
+ if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )
+ {
+ /* Get the next packet. */
+ uxStreamBufferGet( xRecvBuffer, 0, ( uint8_t * ) &xHeader, sizeof( xHeader ), pdFALSE );
+ uxStreamBufferGet( xRecvBuffer, 0, ( uint8_t * ) ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );
+ pucPacketData = ucRecvBuffer;
+ pxHeader = &xHeader;
+
+ iptraceNETWORK_INTERFACE_RECEIVE();
+
+ /* Check for minimal size. */
+ if( pxHeader->len >= sizeof( EthernetHeader_t ) )
+ {
+ eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );
+ }
+ else
+ {
+ eResult = eReleaseBuffer;
+ }
+
+ if( eResult == eProcessBuffer )
+ {
+ /* Will the data fit into the frame buffer? */
+ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )
+ {
+ /* Obtain a buffer into which the data can be placed. This
+ is only an interrupt simulator, not a real interrupt, so it
+ is ok to call the task level function here, but note that
+ some buffer implementations cannot be called from a real
+ interrupt. */
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
+
+ if( pxNetworkBuffer != NULL )
+ {
+ memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );
+ pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;
+
+ #if ( niDISRUPT_PACKETS == 1 )
+ {
+ pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );
+ }
+ #endif /* niDISRUPT_PACKETS */
+
+ if( pxNetworkBuffer != NULL )
+ {
+ xRxEvent.pvData = ( void * ) pxNetworkBuffer;
+
+ /* Data was received and stored. Send a message to
+ the IP task to let it know. */
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
+ {
+ /* The buffer could not be sent to the stack so
+ must be released again. This is only an
+ interrupt simulator, not a real interrupt, so it
+ is ok to use the task level function here, but
+ note no all buffer implementations will allow
+ this function to be executed from a real
+ interrupt. */
+ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
+ iptraceETHERNET_RX_EVENT_LOST();
+ }
+ }
+ else
+ {
+ /* The packet was already released or stored inside
+ vRxFaultInjection(). Don't release it here. */
+ }
+ }
+ else
+ {
+ iptraceETHERNET_RX_EVENT_LOST();
+ }
+ }
+ else
+ {
+ /* Log that a packet was dropped because it would have
+ overflowed the buffer, but there may be more buffers to
+ process. */
+ }
+ }
+ }
+ else
+ {
+ /* There is no real way of simulating an interrupt. Make sure
+ other tasks can run. */
+ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );
+ }
+ }
+}
+
+/*!
+ * @brief remove spacces from pcMessage into pcBuffer
+ * @param [out] pcBuffer buffer to fill up
+ * @param [in] aBuflen length of pcBuffer
+ * @param [in] pcMessage original message
+ * @returns
+ */
+static const char * prvRemoveSpaces( char *pcBuffer,
+ int aBuflen,
+ const char *pcMessage )
+{
+char *pcTarget = pcBuffer;
+
+ /* Utility function used to formap messages being printed only. */
+ while( ( *pcMessage != 0 ) && ( pcTarget < ( &pcBuffer[ aBuflen - 1 ] ) ) )
+ {
+ *( pcTarget++ ) = *pcMessage;
+
+ if( isspace( *pcMessage ) != pdFALSE )
+ {
+ while( isspace( *pcMessage ) != pdFALSE )
+ {
+ pcMessage++;
+ }
+ }
+ else
+ {
+ pcMessage++;
+ }
+ }
+
+ *pcTarget = '\0';
+
+ return pcBuffer;
+}
+
+/*!
+ * @brief print binary packet in hex
+ * @param [in] bin_daa data to print
+ * @param [in] len length of the data
+ */
+static void print_hex( unsigned const char * const bin_data,
+ size_t len )
+/*static void print_hex(unsigned char *bin_data, size_t len) */
+{
+size_t i;
+
+ for( i = 0; i < len; ++i )
+ {
+ FreeRTOS_debug_printf( ( "%.2X ", bin_data[ i ] ) );
+ }
+
+ FreeRTOS_debug_printf( ( "\n" ) );
+}
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
index 87161fd39..f6d152a8c 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/mw300_rd/NetworkInterface.c
@@ -1,5 +1,5 @@
/*
-FreeRTOS+TCP V2.0.11
+FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.c
new file mode 100644
index 000000000..8ac6cdb1f
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.c
@@ -0,0 +1,658 @@
+/*
+ * FreeRTOS+TCP V2.2.1
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.
+ *
+ * http://aws.amazon.com/freertos
+ * http://www.FreeRTOS.org
+ */
+
+/*
+ * tcp_dump_packets.c
+ * Used in the PC/Win project to dump Ethernet packets, along with some description.
+ * See tools/tcp_dump_packets.md for further description.
+ */
+
+/* Standard includes. */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+/* FreeRTOS includes. */
+#include <FreeRTOS.h>
+#include "task.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_Stream_Buffer.h"
+#include "FreeRTOS_IP_Private.h"
+
+#if( ipconfigUSE_DUMP_PACKETS != 0 )
+
+#include "tcp_dump_packets.h"
+
+/* The priority of the windows thread. */
+#define dumpPROCESS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL
+
+/* There is a stream buffer between the FreeRTOS tasks sending network packets,
+and the Windows thread that writes these packets to disk. The macro 'dumpITEM_COUNT'
+determines the number of full-size packets that can be stored in this stream buffer. */
+#ifndef dumpITEM_COUNT
+ #define dumpITEM_COUNT 32
+#endif
+
+/* Packets are written in hex notation, no more than 16 bytes on a row. */
+#ifndef dumpBYTES_PER_ROW
+ #define dumpBYTES_PER_ROW 16
+#endif
+
+/* The TCP port number reserved for a DNS server. */
+#define dnsDNS_PORT 0x0035u
+
+/* Some const values describing the 'flags' in a TCP packet. */
+#define tcpTCP_FLAG_FIN 0x0001u /* No more data from sender */
+#define tcpTCP_FLAG_SYN 0x0002u /* Synchronize sequence numbers */
+#define tcpTCP_FLAG_RST 0x0004u /* Reset the connection */
+#define tcpTCP_FLAG_PSH 0x0008u /* Push function: please push buffered data to the recv application */
+#define tcpTCP_FLAG_ACK 0x0010u /* Acknowledgment field is significant */
+
+/* A macro to add a type, both as a numeric value, as well as a string. */
+#define ADD_TYPE( FLAGS ) \
+ vAddType( flag_##FLAGS, #FLAGS )
+
+/*-----------------------------------------------------------*/
+
+static char pcTypeString[ 255 ];
+static uint32_t ulTypeMask;
+
+/* The name of the C source file to be written. */
+static char pcCodeFileName[ MAX_PATH ];
+
+/* The name of the header file to be written. */
+static char pcHeaderFileName[ MAX_PATH ];
+
+/* A stream buffer between the FreeRTOS tasks and the Windows thread. */
+static StreamBuffer_t *xPacketBuffer;
+
+/* A process handle of the Windows thread. */
+static HANDLE pvProcessHandle;
+
+static UBaseType_t uxNextPacketNumber;
+static BaseType_t xFirstPacket = 1;
+
+/* Bollean 'xDumpingReady' becomes true once all desired packet have been collected.
+Further packets will be dropped (ignored). */
+static volatile BaseType_t xDumpingReady = pdFALSE;
+
+static DumpEntries_t *pxCurrentEntries;
+
+static uint16_t usSourcePort;
+static uint16_t usDestinationPort;
+
+typedef struct xBufferheader
+{
+ size_t uxLength;
+ UBaseType_t bIncoming : 1;
+} Bufferheader_t;
+
+static DumpEntries_t xExampleEntries = {
+ .uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
+ .xEntries = {
+ { .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
+ { .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
+ { .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
+ { .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
+ }
+};
+
+const char pcHeaderCode[] =
+ "/*\n"
+ " * This file was created automatically by 'dump_packets.c'\n"
+ " */\n"
+ "\n"
+ "/* Standard includes. */\n"
+ "#include <stdio.h>\n"
+ "#include <stdint.h>\n"
+ "#include <stdarg.h>\n"
+ "#include <io.h>\n"
+ "#include <ctype.h>\n"
+ "\n"
+ "/* FreeRTOS includes. */\n"
+ "#include <FreeRTOS.h>\n"
+ "#include <task.h>\n\n"
+ "#include \"%s\"\n\n";
+
+const char pcHeaderHeader[] =
+ "/*\n"
+ " * This file was created automatically by 'dump_packets.c'\n"
+ " */\n"
+ "\n"
+ "#ifndef PACKET_LIST_H\n\n"
+ "#define PACKET_LIST_H\n\n"
+ "typedef struct xDumpPacket\n"
+ "{\n"
+ " const uint8_t *pucData;\n"
+ " size_t uxLength;\n"
+ " uint32_t ulType;\n"
+ " uint16_t usSource;\n"
+ " uint16_t usDestination;\n"
+ "} DumpPacket_t;\n\n";
+
+/*-----------------------------------------------------------*/
+
+/* The Windows thread that actually writes the network packets to a C source and header file. */
+static DWORD WINAPI prvWritePackets( LPVOID lpParameter );
+
+static void vAddProtocolTags( uint8_t *pucEthernetBuffer, BaseType_t xIPType );
+static void vDetermineMessageType( uint8_t *pucBuffer, BaseType_t xIncoming );
+static void vActualDump( uint8_t *pucBuffer, size_t uxLength, BaseType_t xIncoming );
+static void vAddType( uint32_t ulFlags, const char *pcFlagName );
+static void vWriteHeaderFile( void );
+
+/*-----------------------------------------------------------*/
+
+void dump_packet_init( const char *pcFileName, DumpEntries_t *pxEntries )
+{
+size_t uxIndex;
+
+ snprintf( pcCodeFileName, sizeof pcCodeFileName, "%s.c", pcFileName );
+ snprintf( pcHeaderFileName, sizeof pcHeaderFileName, "%s.h", pcFileName );
+
+ if( pxEntries == NULL )
+ {
+ pxEntries = &( xExampleEntries );
+ }
+ configASSERT( pxEntries->uxEntryCount > 0 );
+ configASSERT( pxEntries->uxEntryCount <= dumpMAX_DUMP_ENTRIES );
+
+ for( uxIndex = 0; uxIndex < pxEntries->uxEntryCount; uxIndex++ )
+ {
+ pxEntries->xEntries[ uxIndex ].uxCount = 0;
+ }
+
+ pxCurrentEntries = pxEntries;
+
+ if( xPacketBuffer == NULL )
+ {
+ size_t uxLength, uxSize;
+
+ /* Enough space for e.g. 32 buffers and length words. */
+ uxLength = dumpITEM_COUNT * ( sizeof( void * ) + ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER );
+ uxSize = ( sizeof( *xPacketBuffer ) + uxLength ) - sizeof( xPacketBuffer->ucArray );
+ xPacketBuffer = ( StreamBuffer_t * ) pvPortMalloc( uxSize );
+ configASSERT( xPacketBuffer != NULL );
+ vStreamBufferClear( xPacketBuffer );
+ xPacketBuffer->LENGTH = uxLength;
+ }
+
+ if( pvProcessHandle == NULL )
+ {
+ pvProcessHandle = CreateThread( NULL, 0, prvWritePackets, NULL, CREATE_SUSPENDED, NULL );
+ if( pvProcessHandle != NULL )
+ {
+ SetThreadPriority( pvProcessHandle, dumpPROCESS_THREAD_PRIORITY );
+ SetThreadPriorityBoost( pvProcessHandle, TRUE );
+ SetThreadAffinityMask( pvProcessHandle, 0x0E );
+ ResumeThread( pvProcessHandle );
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+void dump_packet( const uint8_t *pucBuffer, size_t uxLength, BaseType_t xIncoming )
+{
+ /* This function shall be called from a normal FreeRTOS task only. */
+ if( xPacketBuffer != NULL )
+ {
+ if( xDumpingReady == pdFALSE )
+ {
+ size_t uxSpace = uxStreamBufferGetSpace( xPacketBuffer );
+ size_t uxNeeded = uxLength + sizeof( size_t );
+
+ if( uxNeeded < uxSpace )
+ {
+ Bufferheader_t xheader;
+
+ xheader.uxLength = uxLength;
+ xheader.bIncoming = xIncoming;
+ uxStreamBufferAdd( xPacketBuffer, 0u, ( const uint8_t * ) &( xheader ), sizeof( xheader ) );
+ uxStreamBufferAdd( xPacketBuffer, 0u, pucBuffer, uxLength );
+ }
+ else
+ {
+ /* Drop this packet. */
+ }
+ }
+ else
+ {
+ /* The Windows thread 'prvWritePackets()' had received enough packets.
+ The packet buffer may be freed. */
+ vPortFree( xPacketBuffer );
+ xPacketBuffer = NULL;
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static DWORD WINAPI prvWritePackets( LPVOID lpParameter )
+{
+ /* This is a Windows thread, not a FreeRTOS task. FreeRTOS API's may not be called. */
+ for( ;; )
+ {
+ Sleep( 100 );
+
+ while( ( xPacketBuffer != NULL ) && ( xDumpingReady == pdFALSE ) )
+ {
+ Bufferheader_t xHeader;
+ size_t uxBytes = uxStreamBufferGetSize( xPacketBuffer );
+
+ if( uxBytes <= sizeof( xHeader ) )
+ break;
+
+ /* Peek the number of bytes available. */
+ uxStreamBufferGet( xPacketBuffer, 0u, ( uint8_t * ) &( xHeader ), sizeof( xHeader ), pdTRUE );
+ if( uxBytes >= sizeof( xHeader ) + xHeader.uxLength );
+ {
+ size_t xBytesRead;
+ uint8_t pcBuffer[ ipconfigNETWORK_MTU ];
+ size_t xActualCount;
+
+ uxStreamBufferGet( xPacketBuffer, 0u, NULL, sizeof( xHeader ), pdFALSE );
+ xActualCount = uxStreamBufferGet( xPacketBuffer, 0u, pcBuffer, xHeader.uxLength, pdFALSE );
+ vActualDump( pcBuffer, xActualCount, xHeader.bIncoming );
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static int _fprintf( FILE *pxHandle, const char* pcFormat, ... )
+{
+char pcString[ 255 ];
+BaseType_t iCount;
+
+ va_list args;
+ va_start (args, pcFormat);
+ iCount = vsnprintf( pcString, sizeof pcString, pcFormat, args);
+ va_end (args);
+ fwrite( pcString, 1u, iCount, pxHandle );
+
+ return iCount;
+}
+/*-----------------------------------------------------------*/
+
+static void vWriteHeaderFile( void )
+{
+FILE *outfile;
+
+ outfile = fopen( pcHeaderFileName, "w" );
+ if( outfile != NULL )
+ {
+ fwrite( pcHeaderHeader, 1u, sizeof( pcHeaderHeader ) - 1u, outfile );
+ _fprintf( outfile, "#define dumpPACKET_COUNT %lu\n\n",
+ ( uxNextPacketNumber < 1u ) ? 1u : uxNextPacketNumber );
+ _fprintf( outfile, "extern DumpPacket_t *xPacketList[ dumpPACKET_COUNT ];\n\n" );
+ _fprintf( outfile, "#endif PACKET_LIST_H\n" );
+
+ fclose ( outfile );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vAddType( uint32_t ulFlags, const char *pcFlagName )
+{
+size_t uxLength = strlen( pcTypeString );
+char pcString[ 64 ];
+BaseType_t iCount;
+
+ ulTypeMask |= ulFlags;
+
+ if( uxLength == 0 )
+ {
+ snprintf( pcTypeString, sizeof pcTypeString, "%s", pcFlagName );
+ }
+ else
+ {
+ snprintf( pcTypeString + uxLength, sizeof pcTypeString - 1, " | %s", pcFlagName );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vAddProtocolTags( uint8_t *pucEthernetBuffer, BaseType_t xIPType )
+{
+ProtocolHeaders_t *pxProtocolHeaders;
+#if( ipconfigUSE_IPv6 != 0 )
+ const IPHeader_IPv6_t * pxIPHeader_IPv6;
+#endif
+UBaseType_t uxHeaderLength;
+uint8_t ucProtocol;
+IPPacket_t * pxIPPacket;
+IPHeader_t * pxIPHeader;
+
+ pxIPPacket = ( IPPacket_t * ) pucEthernetBuffer;
+ pxIPHeader = &( pxIPPacket->xIPHeader );
+ #if( ipconfigUSE_IPv6 != 0 )
+ pxIPHeader_IPv6 = ipPOINTER_CAST( const IPHeader_IPv6_t *, &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) );
+ if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE )
+ {
+ uxHeaderLength = ipSIZE_OF_IPv6_HEADER;
+ ucProtocol = pxIPHeader_IPv6->ucNextHeader;
+ pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *, &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER ] ) );
+ }
+ else
+ #endif
+ {
+ size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
+
+ /* Check if the IP headers are acceptable and if it has our destination.
+ The lowest four bits of 'ucVersionHeaderLength' indicate the IP-header
+ length in multiples of 4. */
+ uxHeaderLength = ( size_t ) ( ( uxLength & 0x0Fu ) << 2 );
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+ pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *, &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxHeaderLength ] ) );
+ }
+
+ switch( ucProtocol )
+ {
+ case ipPROTOCOL_ICMP :
+ ADD_TYPE( ICMP4 );
+ break;
+
+#if( ipconfigUSE_IPv6 != 0 )
+ case ipPROTOCOL_ICMP_IPv6:
+ ADD_TYPE( ICMP6 );
+ break;
+#endif
+
+ case ipPROTOCOL_UDP :
+ {
+ ADD_TYPE( UDP );
+ usSourcePort = pxProtocolHeaders->xUDPHeader.usSourcePort;
+ usDestinationPort = pxProtocolHeaders->xUDPHeader.usDestinationPort;
+ if( usSourcePort == FreeRTOS_htons( dnsDNS_PORT) )
+ {
+ ADD_TYPE( DNS );
+ ADD_TYPE( REPLY );
+ }
+ else if( usDestinationPort == FreeRTOS_htons( dnsDNS_PORT) )
+ {
+ ADD_TYPE( DNS );
+ ADD_TYPE( REQUEST );
+ }
+ }
+ break;
+#if ipconfigUSE_TCP == 1
+ case ipPROTOCOL_TCP :
+ {
+ ADD_TYPE( TCP );
+ usSourcePort = pxProtocolHeaders->xTCPHeader.usSourcePort;
+ usDestinationPort = pxProtocolHeaders->xTCPHeader.usDestinationPort;
+ if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_SYN ) != 0u )
+ {
+ ADD_TYPE( SYN );
+ }
+ if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_FIN ) != 0u )
+ {
+ ADD_TYPE( FIN );
+ }
+ if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_RST ) != 0u )
+ {
+ ADD_TYPE( RST );
+ }
+ if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_ACK ) != 0u )
+ {
+ ADD_TYPE( ACK );
+ }
+ }
+ break;
+#endif
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vDetermineMessageType( uint8_t *pucBuffer, BaseType_t xIncoming )
+{
+EthernetHeader_t *pxEthernetHeader;
+
+ if( xIncoming != 0 )
+ {
+ ADD_TYPE( IN );
+ }
+ else
+ {
+ ADD_TYPE( OUT );
+ }
+ pxEthernetHeader = ( EthernetHeader_t * ) pucBuffer;
+
+ /* Interpret the received Ethernet packet. */
+ switch( pxEthernetHeader->usFrameType )
+ {
+ case ipARP_FRAME_TYPE :
+ {
+ ARPPacket_t * pxARPFrame;
+ ARPHeader_t *pxARPHeader;
+
+ /* The Ethernet frame contains an ARP packet. */
+ ADD_TYPE( FRAME_ARP );
+ pxARPFrame = ( ARPPacket_t * ) pucBuffer;
+ pxARPHeader = &( pxARPFrame->xARPHeader );
+ ADD_TYPE( ARP );
+ switch( pxARPHeader->usOperation )
+ {
+ case ipARP_REQUEST:
+ ADD_TYPE( REQUEST );
+ break;
+ case ipARP_REPLY:
+ ADD_TYPE( REPLY );
+ break;
+ default:
+ ADD_TYPE( UNKNOWN );
+ break;
+ }
+ }
+ break;
+
+ case ipIPv4_FRAME_TYPE :
+ {
+ ADD_TYPE( FRAME_4 );
+ vAddProtocolTags( pucBuffer, 4 );
+ }
+ break;
+
+ #if( ipconfigUSE_IPv6 != 0 )
+ case ipIPv6_FRAME_TYPE :
+ {
+ ADD_TYPE( FRAME_6 );
+ vAddProtocolTags( pucBuffer, 6 );
+ }
+ break;
+ #endif
+ default :
+ /* No other packet types are handled. Nothing to do. */
+ ADD_TYPE( Unknown_FRAME );
+ break;
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void vActualDump( uint8_t *pucBuffer, size_t uxLength, BaseType_t xIncoming )
+{
+char pcString[ 513 ];
+size_t uxOffset;
+size_t uxIndex;
+size_t uxCompleteCount = 0;
+BaseType_t xUseIt = pdFALSE;
+
+ usSourcePort = 0u;
+ usDestinationPort = 0u;
+ pcTypeString[ 0 ] = 0;
+ ulTypeMask = 0uL;
+
+ if( pxCurrentEntries == NULL )
+ {
+ return;
+ }
+
+ vDetermineMessageType( pucBuffer, xIncoming );
+
+ for( uxIndex = 0; uxIndex < pxCurrentEntries->uxEntryCount; uxIndex++ )
+ {
+ if( pxCurrentEntries->xEntries[ uxIndex ].uxCount < pxCurrentEntries->xEntries[ uxIndex ].uxMax )
+ {
+ uint32_t ulMask = pxCurrentEntries->xEntries[ uxIndex ].ulMask;
+
+ if( ( ulMask & ulTypeMask ) == ulMask )
+ {
+ pxCurrentEntries->xEntries[ uxIndex ].uxCount++;
+ xUseIt = pdTRUE;
+ }
+ }
+ else
+ {
+ uxCompleteCount++;
+ }
+ }
+ FreeRTOS_printf( ( "prvWritePackets: done %d/%d : (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
+ uxCompleteCount,
+ pxCurrentEntries->uxEntryCount,
+ pxCurrentEntries->xEntries[ 0 ].uxCount, pxCurrentEntries->xEntries[ 0 ].uxMax,
+ pxCurrentEntries->xEntries[ 1 ].uxCount, pxCurrentEntries->xEntries[ 1 ].uxMax,
+ pxCurrentEntries->xEntries[ 2 ].uxCount, pxCurrentEntries->xEntries[ 2 ].uxMax,
+ pxCurrentEntries->xEntries[ 3 ].uxCount, pxCurrentEntries->xEntries[ 3 ].uxMax ) );
+ if( uxCompleteCount >= pxCurrentEntries->uxEntryCount )
+ {
+ FreeRTOS_printf( ( "prvWritePackets: all %lu packets have been collected\n", pxCurrentEntries->uxEntryCount ) );
+ if( pxCurrentEntries != NULL )
+ {
+ FILE *outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
+ if ( outfile == NULL )
+ {
+ FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
+ }
+ else
+ {
+ /*
+ Create a list with pointers to each network packet.
+ DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
+ {
+ &xPacket_0000,
+ &xPacket_0001,
+ &xPacket_0002,
+ &xPacket_0003,
+ }
+ */
+ _fprintf( outfile, "\nDumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =\n{\n" );
+ for( uxIndex = 0; uxIndex < uxNextPacketNumber; uxIndex++ )
+ {
+ _fprintf( outfile, "\t&xPacket_%04lu,\n", uxIndex );
+ }
+ _fprintf( outfile, "};\n" );
+ fclose( outfile );
+ vWriteHeaderFile();
+ }
+ pxCurrentEntries = NULL;
+ /* Tell the thread and the function dump_packet() that packet
+ dumping is ready. */
+ xDumpingReady = pdTRUE;
+ }
+ return;
+ }
+ if( xUseIt == pdFALSE )
+ {
+ return;
+ }
+
+ printf("prvWritePackets: Read %lu bytes, type %s\n", uxLength, pcTypeString );
+
+ FILE *outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
+ if ( outfile == NULL )
+ {
+ FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
+ return;
+ }
+ if( xFirstPacket != 0 )
+ {
+ char *pcPtr;
+ size_t xLength;
+
+ vWriteHeaderFile( pcHeaderFileName );
+ xLength = snprintf( pcString, sizeof pcString, pcHeaderCode, pcHeaderFileName );
+ fwrite( pcString, 1u, xLength, outfile );
+ xFirstPacket = pdFALSE;
+ }
+
+ _fprintf( outfile, "\n/* Packet_%04d */\n", uxNextPacketNumber );
+ _fprintf( outfile, "uint8_t ucPacket_%04lx[ %lu ] =\n{\n", uxNextPacketNumber, uxLength );
+
+ for( uxOffset = 0u; uxOffset < uxLength; )
+ {
+ size_t uxCurLength = 0u;
+ size_t uxLast = uxOffset + dumpBYTES_PER_ROW;
+ BaseType_t xFirst = pdTRUE;
+
+ if( uxLast > uxLength )
+ {
+ uxLast = uxLength;
+ }
+ while( uxOffset < uxLast )
+ {
+ uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s0x%02x",
+ ( uxCurLength == 0 ) ? "\t" : ", ", pucBuffer[ uxOffset ] );
+ uxOffset++;
+ }
+ if( uxCurLength != 0u )
+ {
+ uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s\n",
+ ( uxOffset == uxLength ) ? "\n};" : "," );
+ fwrite( pcString, 1u, uxCurLength, outfile );
+ }
+ }
+
+ _fprintf( outfile, "\n");
+
+ _fprintf( outfile,
+ "DumpPacket_t xPacket_%04lx =\n{\n"
+ "\t.pucData = ucPacket_%04lx,\n"
+ "\t.uxLength = %lu,\n"
+ "\t.ulType = 0x%lX, /* %s */\n",
+ uxNextPacketNumber, uxNextPacketNumber, uxLength, ulTypeMask, pcTypeString );
+
+ if( usSourcePort != 0u )
+ {
+ _fprintf( outfile,
+ "\t.usSource = %u,\n", FreeRTOS_ntohs( usSourcePort ) );
+ }
+ if( usSourcePort != 0u )
+ {
+ _fprintf( outfile,
+ "\t.usDestination = %u,\n", FreeRTOS_ntohs( usDestinationPort ) );
+ }
+
+ _fprintf( outfile,
+ "};\n"
+ "/*-----------------------------------------------------------*/\n\n" );
+ fclose( outfile );
+ uxNextPacketNumber++;
+}
+/*-----------------------------------------------------------*/
+
+#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */
+
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.md b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.md
new file mode 100644
index 000000000..e2b56f705
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_dump_packets.md
@@ -0,0 +1,72 @@
+tcp_dump_packets.c dumps network packets in a C source file.
+
+It is written to be added to the "pc" project ( Windows simulator ). It uses the file system to write 2 C source files:
+
+ PacketList.c
+ PacketList.h
+
+How to include 'tcp_dump_packets' into a project:
+
+● Make sure that tools/tcp_dump_packets.c is added to the source files
+● See if Network Interface has been adapted to call:
+ `iptraceDUMP_PACKET( ucBuffer, xLength, pdTRUE ); /* Incoming packet. */`
+ `iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE ); /* Outgoing packet. */`
+● Once the network is up, call `dump_packet_init()` with a file name and a pointer to
+ `DumpEntries_t`, which contains the requirements. For instance like this:
+ static DumpEntries_t xExampleEntries = {
+ .uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
+ .xEntries = {
+ { .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
+ { .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
+ { .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
+ { .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
+ }
+ };
+● Add the following lines to FreeRTOSIPConfig.h :
+ #define ipconfigUSE_DUMP_PACKETS ( 1 )
+ #include "../tools/tcp_dump_packets.h"
+
+Later on, the module can disabled by simply setting `ipconfigUSE_DUMP_PACKETS` to `0`.
+
+Here is some contents of the output file:
+
+ /* Packet_0001 */
+ uint8_t ucPacket_0001[ 60 ] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0x08, 0x06, 0x00, 0x01,
+ 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0xc0, 0xa8, 0x02, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ DumpPacket_t xPacket_0001 =
+ {
+ .pucData = ucPacket_0001,
+ .uxLength = 60,
+ .ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
+ };
+ /*-----------------------------------------------------------*/
+
+tcp_dump_packets has an enum of all possible properties of network packets:
+ ICMP4, ICMP6, UDP, TCP, DNS, REPLY, REQUEST, SYN,
+ FIN, RST, ACK, IN, OUT, ARP, FRAME_ARP, FRAME_4, and FRAME_6
+
+Each property is defined as a bit so they can be combined as in:
+ .ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
+
+Finishing: when there are enough packets of all required types, an array is added to the C-source output:
+
+ DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
+ {
+ &xPacket_0000,
+ &xPacket_0001,
+ &xPacket_0002,
+ &xPacket_0003,
+ &xPacket_0004,
+ &xPacket_0005,
+ &xPacket_0006,
+ &xPacket_0007,
+ &xPacket_0008,
+ };
+
+The new source file PacketList.{c, h} can be used in testing software as sample packets.
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.c
new file mode 100644
index 000000000..d4929b3fa
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.c
@@ -0,0 +1,425 @@
+/*
+ * FreeRTOS+TCP V2.2.1
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.
+ *
+ * http://aws.amazon.com/freertos
+ * http://www.FreeRTOS.org
+ */
+/*
+ * tcp_mem_stats.c
+ * Used to create a CSV file with detaild information about the memory usage of FreeRTOS+TCP.
+ * See tools/tcp_mem_stats.md for further description.
+ */
+
+/* Standard includes. */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+/* FreeRTOS includes. */
+#include <FreeRTOS.h>
+#include "task.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_Stream_Buffer.h"
+#include "FreeRTOS_ARP.h"
+#include "FreeRTOS_IP_Private.h"
+
+#include "tcp_mem_stats.h"
+
+#ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION
+ #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u
+ #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?"
+#endif
+
+#if( ipconfigUSE_TCP_MEM_STATS != 0 )
+
+/* When a streambuffer is allocated, 4 extra bytes will be reserved. */
+
+#define STREAM_BUFFER_ROUNDUP_BYTES 4
+
+#define STATS_PRINTF( MSG ) \
+ xCurrentLine++; \
+ configPRINTF( MSG )
+
+#define ETH_MAX_PACKET_SIZE ( ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL )
+/*-----------------------------------------------------------*/
+
+/* Objects are allocated and deleted. This structure stores the type
+and the size of the object. */
+typedef struct xTCP_ALLOCATION
+{
+ TCP_MEMORY_t xMemType;
+ void *pxObject;
+ UBaseType_t uxNumber;
+ size_t uxSize;
+} TCP_ALLOCATION_t;
+/*-----------------------------------------------------------*/
+
+
+static void vWriteHeader( void );
+
+static size_t uxCurrentMallocSize;
+static TCP_ALLOCATION_t xAllocations[ ipconfigTCP_MEM_STATS_MAX_ALLOCATION ];
+static size_t uxAllocationCount;
+static BaseType_t xFirstItem = pdTRUE;
+UBaseType_t uxNextObjectNumber;
+static BaseType_t xCurrentLine = 0;
+static BaseType_t xFirstDumpLine = 0;
+static BaseType_t xLastHeaderLineNr = 0;
+static BaseType_t xLoggingStopped = 0;
+/*-----------------------------------------------------------*/
+
+static void vAddAllocation( TCP_MEMORY_t xMemType, void *pxObject, size_t uxSize )
+{
+size_t uxIndex;
+
+ vTaskSuspendAll();
+ {
+ for( uxIndex = 0; uxIndex < uxAllocationCount; uxIndex++ )
+ {
+ if( xAllocations[ uxIndex ].pxObject == pxObject )
+ {
+ /* Already added, strange. */
+ FreeRTOS_printf( ( "vAddAllocation: Pointer %p already added\n", pxObject ) );
+ return;
+ }
+ }
+ if( uxAllocationCount >= ipconfigTCP_MEM_STATS_MAX_ALLOCATION )
+ {
+ /* The table is full. */
+ return;
+ }
+ xAllocations[ uxIndex ].pxObject = pxObject;
+ xAllocations[ uxIndex ].xMemType = xMemType;
+ xAllocations[ uxIndex ].uxSize = uxSize;
+ xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++;
+ uxAllocationCount++;
+ }
+ xTaskResumeAll();
+}
+/*-----------------------------------------------------------*/
+
+static TCP_ALLOCATION_t *pxRemoveAllocation( void *pxObject )
+{
+size_t uxSource = 0, uxTarget = 0;
+static TCP_ALLOCATION_t xAllocation = { 0 };
+BaseType_t xFound = pdFALSE;
+TCP_ALLOCATION_t *pxReturn;
+
+ vTaskSuspendAll();
+ {
+ for( ; uxSource < uxAllocationCount; uxSource++ )
+ {
+ if( xAllocations[ uxSource ].pxObject == pxObject )
+ {
+ /* This is entry will be removed. */
+ ( void ) memcpy( &( xAllocation ), &( xAllocations[ uxSource ] ), sizeof xAllocation );
+ xFound = pdTRUE;
+ }
+ else
+ {
+ xAllocations[ uxTarget ] = xAllocations[ uxSource ];
+ uxTarget++;
+ }
+ }
+ if( xFound != pdFALSE )
+ {
+ uxAllocationCount--;
+ pxReturn = &( xAllocation );
+ }
+ else
+ {
+ pxReturn = NULL;
+ }
+ }
+ xTaskResumeAll();
+ return pxReturn;
+}
+/*-----------------------------------------------------------*/
+
+static const char *pcTypeName( TCP_MEMORY_t xMemType )
+{
+ switch( xMemType )
+ {
+ case tcpSOCKET_TCP: return "TCP-Socket";
+ case tcpSOCKET_UDP: return "UDP-Socket";
+ case tcpSOCKET_SET: return "SocketSet";
+ case tcpSEMAPHORE: return "Semaphore";
+ case tcpRX_STREAM_BUFFER: return "RX-Buffer";
+ case tcpTX_STREAM_BUFFER: return "TX-Buffer";
+ case tcpNETWORK_BUFFER: return "networkBuffer";
+ }
+ return "Unknown object";
+}
+/*-----------------------------------------------------------*/
+
+static void vWriteHeader()
+{
+size_t uxPacketSize;
+size_t uxTXSize;
+size_t uxStaticSize = 0;
+BaseType_t xFirstLineNr = 0;
+
+char pucComment[ 64 ] = "";
+StreamBuffer_t *pxBuffer = NULL;
+size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
+
+ /* The approximate size of a buffer for a Network Packet. */
+ STATS_PRINTF( ( "TCPMemStat,Some important ipconfig items:\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,Comment\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,NETWORK_MTU,%u\n", ipconfigNETWORK_MTU ) );
+ STATS_PRINTF( ( "TCPMemStat,TCP_MSS,%u\n", ipconfigTCP_MSS ) );
+ STATS_PRINTF( ( "TCPMemStat,USE_TCP,%u\n", ipconfigUSE_TCP ) );
+ STATS_PRINTF( ( "TCPMemStat,USE_TCP_WIN,%u\n", ipconfigUSE_TCP_WIN ) );
+
+ uxTXSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
+
+ STATS_PRINTF( ( "TCPMemStat,TCP_RX_BUFFER_LENGTH,%u,Plus %u bytes\n", ipconfigTCP_RX_BUFFER_LENGTH, uxTara + STREAM_BUFFER_ROUNDUP_BYTES ) );
+ if( uxTXSize > ipconfigTCP_TX_BUFFER_LENGTH )
+ {
+ snprintf( pucComment, sizeof pucComment, ",Rounded up to %u x MSS (plus %u bytes)", uxTXSize / ipconfigTCP_MSS, uxTara + STREAM_BUFFER_ROUNDUP_BYTES );
+ }
+ STATS_PRINTF( ( "TCPMemStat,TCP_TX_BUFFER_LENGTH,%u%s\n", ipconfigTCP_TX_BUFFER_LENGTH, pucComment ) );
+ STATS_PRINTF( ( "TCPMemStat,USE_DHCP,%u\n", ipconfigUSE_DHCP ) );
+
+ /*
+ * Start of fixed RAM allocations.
+ */
+
+ STATS_PRINTF( ( "TCPMemStat,\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,RAM that is always allocated either statically or on the heap:\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,PerUnit,Total\n" ) );
+ xFirstLineNr = xCurrentLine;
+ if( xBufferAllocFixedSize != 0 )
+ {
+ size_t uxBytes;
+
+ /* Using BufferAllocation_1.c */
+ uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL;
+ uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ( uxPacketSize + sizeof( NetworkBufferDescriptor_t ) );
+
+ STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors + buffers\n",
+ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
+ uxPacketSize + sizeof( NetworkBufferDescriptor_t ),
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+ }
+ else
+ {
+ size_t uxBytes;
+
+ /* Using BufferAllocation_2.c */
+ uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * sizeof( NetworkBufferDescriptor_t );
+ STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors only\n",
+ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
+ sizeof( NetworkBufferDescriptor_t ),
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+ }
+ {
+ #if( ipconfigUSE_TCP_WIN != 0 )
+ {
+ STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u,=B%d*C%d\n",
+ ipconfigTCP_WIN_SEG_COUNT, sizeof( TCPSegment_t ), xCurrentLine, xCurrentLine ) );
+ }
+ #else
+ {
+ STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u\n", 0, 0 ) );
+ }
+ #endif
+ }
+ {
+ size_t uxBytes;
+ size_t uxEntrySize;
+
+ uxBytes = ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t );
+ STATS_PRINTF( ( "TCPMemStat,EVENT_QUEUE_LENGTH,%u,%u,=B%d*C%d\n",
+ ipconfigEVENT_QUEUE_LENGTH,
+ sizeof( IPStackEvent_t ),
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+
+ uxBytes = ipconfigIP_TASK_STACK_SIZE_WORDS * sizeof( void *);
+ STATS_PRINTF( ( "TCPMemStat,IP_TASK_STACK_SIZE_WORDS,%u,%u,=B%d*C%d\n",
+ ipconfigIP_TASK_STACK_SIZE_WORDS,
+ sizeof( void *),
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+
+ uxBytes = ipconfigARP_CACHE_ENTRIES * sizeof( ARPCacheRow_t );
+ STATS_PRINTF( ( "TCPMemStat,ARP_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
+ ipconfigARP_CACHE_ENTRIES,
+ sizeof( ARPCacheRow_t ),
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+
+ #if( ipconfigUSE_DNS_CACHE == 1 )
+ {
+ uxEntrySize = 3u * sizeof( uint32_t ) + ( ( ipconfigDNS_CACHE_NAME_LENGTH + 3 ) & ~0x3u );
+ STATS_PRINTF( ( "TCPMemStat,DNS_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
+ ipconfigDNS_CACHE_ENTRIES,
+ uxEntrySize,
+ xCurrentLine,
+ xCurrentLine ) );
+ }
+ #endif
+ }
+ /*
+ * End of fixed RAM allocations.
+ */
+ if( xBufferAllocFixedSize != 0 )
+ {
+ pucComment[0] = 0;
+ }
+ else
+ {
+ size_t uxBytes;
+
+ /* BufferAllocation_2.c uses HEAP to store network packets. */
+ uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 3 ) & ~0x03uL;
+ uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * uxPacketSize;
+ STATS_PRINTF( ( "TCPMemStat,Network buffers in HEAP,%u,%u,=B%d*C%d\n",
+ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
+ uxPacketSize,
+ xCurrentLine,
+ xCurrentLine ) );
+ uxStaticSize += uxBytes;
+ snprintf( pucComment, sizeof pucComment, "Actual size fluctuates because BufferAllocation_2.c is used" );
+ }
+ xLastHeaderLineNr = xCurrentLine;
+
+ STATS_PRINTF( ( "TCPMemStat,Total,,,=SUM(D%d:D%d),%s\n", xFirstLineNr + 1, xLastHeaderLineNr, pucComment ) );
+
+ STATS_PRINTF( ( "TCPMemStat,\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,The following allocations are done on the heap while running:\n" ) );
+ STATS_PRINTF( ( "TCPMemStat,Create/Remove,Object,Size,Heap use,Pointer,Heap-min,Heap-Cur,comment\n" ) );
+}
+/*-----------------------------------------------------------*/
+
+void vTCPMemStatCreate( TCP_MEMORY_t xMemType, void *pxObject, size_t uxSize )
+{
+ if( xLoggingStopped == pdFALSE )
+ {
+ StreamBuffer_t *pxBuffer = NULL;
+ char pcExtra[ 81 ] = "";
+
+ if( xFirstItem != pdFALSE )
+ {
+ xFirstItem = pdFALSE;
+ vWriteHeader();
+ }
+ if( ( xMemType == tcpRX_STREAM_BUFFER ) || ( xMemType == tcpTX_STREAM_BUFFER ) )
+ {
+ size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
+ size_t uxNett = uxSize - uxTara;
+
+ snprintf( pcExtra, sizeof pcExtra, ",%u nett", uxNett );
+ }
+
+ if( xFirstDumpLine == 0 )
+ {
+ xFirstDumpLine = xCurrentLine + 1;
+ }
+
+ xCurrentLine++;
+ configPRINTF( ( "TCPMemStat,CREATE,%s,%lu,%lu,%u,%u,%u%s\n",
+ pcTypeName( xMemType ),
+ uxSize,
+ uxCurrentMallocSize + uxSize,
+ uxNextObjectNumber,
+ xPortGetMinimumEverFreeHeapSize(),
+ xPortGetFreeHeapSize(),
+ pcExtra ) );
+ uxCurrentMallocSize += uxSize;
+ vAddAllocation( xMemType, pxObject, uxSize );
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTCPMemStatDelete( void *pxObject )
+{
+ if( xLoggingStopped == pdFALSE )
+ {
+ TCP_ALLOCATION_t *pxFound = pxRemoveAllocation( pxObject );
+
+ if( xFirstDumpLine == 0 )
+ {
+ xFirstDumpLine = xCurrentLine + 1;
+ }
+ if( pxFound == NULL )
+ {
+ FreeRTOS_printf( ( "TCPMemStat: can not find pointer %p\n", pxObject ) );
+ }
+ else
+ {
+ xCurrentLine++;
+ configPRINTF( ( "TCPMemStat,REMOVE,%s,-%lu,%lu,%x,%u,%u\n",
+ pcTypeName( pxFound->xMemType ),
+ pxFound->uxSize,
+ uxCurrentMallocSize - pxFound->uxSize,
+ pxFound->uxNumber,
+ xPortGetMinimumEverFreeHeapSize(),
+ xPortGetFreeHeapSize() ) );
+ if( uxCurrentMallocSize < pxFound->uxSize )
+ {
+ uxCurrentMallocSize = 0uL;
+ }
+ else
+ {
+ uxCurrentMallocSize -= pxFound->uxSize;
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+void vTCPMemStatClose()
+{
+ if( xLoggingStopped == pdFALSE )
+ {
+ // name;object;size;Heap;Ppointer;HeapMin;HeapDur;Comment
+ BaseType_t xLastLineNr = xCurrentLine;
+
+ xLoggingStopped = pdTRUE;
+
+ STATS_PRINTF( ( "TCPMemStat,Totals,,,=MAX(D%d:D%d),,=MIN(F%d:F%d),=MAX(G%d:G%d)\n",
+ xFirstDumpLine,
+ xLastLineNr,
+ xFirstDumpLine,
+ xLastLineNr,
+ xFirstDumpLine,
+ xLastLineNr ) );
+ STATS_PRINTF( ( "TCPMemStat,Maximum RAM usage:,,,=SUM(D%d;D%d)\n",
+ xLastHeaderLineNr + 1,
+ xLastLineNr + 1 ) );
+ }
+}
+/*-----------------------------------------------------------*/
+
+#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.md b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.md
new file mode 100644
index 000000000..5b638ef4e
--- /dev/null
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/tools/tcp_mem_stats.md
@@ -0,0 +1,45 @@
+tcp_mem_stats.c : FreeRTOS+TCP Memory Statistics
+
+This module can be used in any project on any platform that uses FreeRTOS+TCP.
+
+It creates an overview of the memory usage of FreeRTOS+TCP.
+It reports the static use of RAM, and also the dynamic usage ( heap ).
+It relates these numbers to the macro's defined `FreeRTOSIPConfig.h`.
+
+It writes CSV records to the logging with configPRINTF().
+
+The resulting log can be filtered by e.g.:
+
+ cat logging.txt | grep ".*TCPMemStat," | sed "s/.*TCPMemStat,//"
+
+The resulting text can be imported into any spreadsheet at cell "A1" ( top-left ):
+
+ ipconfig item,Value,PerUnit,Total
+ NUM_NETWORK_BUFFER_DESCRIPTORS,12,60,=B13*C13,Descriptors only
+ TCP_WIN_SEG_COUNT,32,64,=B14*C14
+ EVENT_QUEUE_LENGTH,17,8,=B15*C15
+ IP_TASK_STACK_SIZE_WORDS,300,4,=B16*C16
+
+When the CSV-records are imported at another row or column than "A1", the formulas will be incorrect.
+
+How to include 'tcp_mem_stats' into a project:
+
+● Add tools/tcp_mem_stats.c to the sources
+● Add the following lines to FreeRTOSIPConfig.h :
+ #define ipconfigUSE_TCP_MEM_STATS ( 1 )
+ #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION ( 128 )
+ #include "../tools/tcp_mem_stats.h"
+
+Later on, the module can disabled by setting `#define ipconfigUSE_TCP_MEM_STATS 0`.
+
+`ipconfigTCP_MEM_STATS_MAX_ALLOCATION` is the maximum number of objects that can be followed at any time.
+A socket that has 2 stream buffers counts as 3 objects ( needing 3 x 16 = 48 bytes to store their properties ).
+
+The **summary** at the bottom will only be written when `iptraceMEM_STATS_CLOSE()` is called.
+The application is responsible for calling `iptraceMEM_STATS_CLOSE()`.
+The summary at the bottom looks like this:
+
+ Totals,,,=MAX(D25:D31),,=MIN(F25:F31),=MAX(G25:G31)
+ Maximum RAM usage:,,,=SUM(D20;D32)
+
+The spreadsheet can be edited further to make estimations with different macro values.