FreeRTOS_TCP_WIN.c 100 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515
  1. /*
  2. * FreeRTOS+TCP V2.3.2 LTS Patch 1
  3. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. * this software and associated documentation files (the "Software"), to deal in
  7. * the Software without restriction, including without limitation the rights to
  8. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. * the Software, and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  18. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * http://aws.amazon.com/freertos
  23. * http://www.FreeRTOS.org
  24. */
  25. /**
  26. * @file FreeRTOS_TCP_WIN.c
  27. * @brief Module which handles the TCP windowing schemes for FreeRTOS+TCP. Many
  28. * functions have two versions - one for FreeRTOS+TCP (full) and one for
  29. * FreeRTOS+TCP (lite).
  30. *
  31. * In this module all ports and IP addresses and sequence numbers are
  32. * being stored in host byte-order.
  33. */
  34. /* Standard includes. */
  35. #include <stdint.h>
  36. /* FreeRTOS includes. */
  37. #include "FreeRTOS.h"
  38. #include "task.h"
  39. /* FreeRTOS+TCP includes. */
  40. #include "FreeRTOS_UDP_IP.h"
  41. #include "FreeRTOS_IP.h"
  42. #include "FreeRTOS_Sockets.h"
  43. #include "FreeRTOS_IP_Private.h"
  44. #ifndef FREERTOS_DEFAULT_IP_CONFIG_H
  45. #error "FreeRTOSIPConfigDefaults.h not included."
  46. #endif
  47. #if ( ipconfigUSE_TCP == 1 )
  48. /* Constants used for Smoothed Round Trip Time (SRTT). */
  49. #define winSRTT_INCREMENT_NEW 2 /**< New increment for the smoothed RTT. */
  50. #define winSRTT_INCREMENT_CURRENT 6 /**< Current increment for the smoothed RTT. */
  51. #define winSRTT_DECREMENT_NEW 1 /**< New decrement for the smoothed RTT. */
  52. #define winSRTT_DECREMENT_CURRENT 7 /**< Current decrement for the smoothed RTT. */
  53. #define winSRTT_CAP_mS 50 /**< Cap in milliseconds. */
  54. /**
  55. * @brief Utility function to cast pointer of a type to pointer of type TCPSegment_t.
  56. *
  57. * @return The casted pointer.
  58. */
  59. static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( TCPSegment_t )
  60. {
  61. return ( TCPSegment_t * ) pvArgument;
  62. }
  63. #if ( ipconfigUSE_TCP_WIN == 1 )
  64. /** @brief Create a new Rx window. */
  65. #define xTCPWindowRxNew( pxWindow, ulSequenceNumber, lCount ) xTCPWindowNew( pxWindow, ulSequenceNumber, lCount, pdTRUE )
  66. /** @brief Create a new Tx window. */
  67. #define xTCPWindowTxNew( pxWindow, ulSequenceNumber, lCount ) xTCPWindowNew( pxWindow, ulSequenceNumber, lCount, pdFALSE )
  68. /** @brief The code to send a single Selective ACK (SACK):
  69. * NOP (0x01), NOP (0x01), SACK (0x05), LEN (0x0a),
  70. * followed by a lower and a higher sequence number,
  71. * where LEN is 2 + 2*4 = 10 bytes. */
  72. #if ( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
  73. #define OPTION_CODE_SINGLE_SACK ( 0x0101050aUL )
  74. #else
  75. #define OPTION_CODE_SINGLE_SACK ( 0x0a050101UL )
  76. #endif
  77. /** @brief Normal retransmission:
  78. * A packet will be retransmitted after a Retransmit Time-Out (RTO).
  79. * Fast retransmission:
  80. * When 3 packets with a higher sequence number have been acknowledged
  81. * by the peer, it is very unlikely a current packet will ever arrive.
  82. * It will be retransmitted far before the RTO.
  83. */
  84. #define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ( 3U )
  85. /** @brief If there have been several retransmissions (4), decrease the
  86. * size of the transmission window to at most 2 times MSS.
  87. */
  88. #define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ( 4U )
  89. #endif /* configUSE_TCP_WIN */
  90. /*-----------------------------------------------------------*/
  91. void vListInsertGeneric( List_t * const pxList,
  92. ListItem_t * const pxNewListItem,
  93. MiniListItem_t * const pxWhere );
  94. /*
  95. * All TCP sockets share a pool of segment descriptors (TCPSegment_t)
  96. * Available descriptors are stored in the 'xSegmentList'
  97. * When a socket owns a descriptor, it will either be stored in
  98. * 'xTxSegments' or 'xRxSegments'
  99. * As soon as a package has been confirmed, the descriptor will be returned
  100. * to the segment pool
  101. */
  102. #if ( ipconfigUSE_TCP_WIN == 1 )
  103. static BaseType_t prvCreateSectors( void );
  104. #endif /* ipconfigUSE_TCP_WIN == 1 */
  105. /*
  106. * Find a segment with a given sequence number in the list of received
  107. * segments: 'pxWindow->xRxSegments'.
  108. */
  109. #if ( ipconfigUSE_TCP_WIN == 1 )
  110. static TCPSegment_t * xTCPWindowRxFind( const TCPWindow_t * pxWindow,
  111. uint32_t ulSequenceNumber );
  112. #endif /* ipconfigUSE_TCP_WIN == 1 */
  113. /*
  114. * Allocate a new segment
  115. * The socket will borrow all segments from a common pool: 'xSegmentList',
  116. * which is a list of 'TCPSegment_t'
  117. */
  118. #if ( ipconfigUSE_TCP_WIN == 1 )
  119. static TCPSegment_t * xTCPWindowNew( TCPWindow_t * pxWindow,
  120. uint32_t ulSequenceNumber,
  121. int32_t lCount,
  122. BaseType_t xIsForRx );
  123. #endif /* ipconfigUSE_TCP_WIN == 1 */
  124. /*
  125. * Detaches and returns the head of a queue
  126. */
  127. #if ( ipconfigUSE_TCP_WIN == 1 )
  128. static TCPSegment_t * xTCPWindowGetHead( const List_t * pxList );
  129. #endif /* ipconfigUSE_TCP_WIN == 1 */
  130. /*
  131. * Returns the head of a queue but it won't be detached
  132. */
  133. #if ( ipconfigUSE_TCP_WIN == 1 )
  134. static TCPSegment_t * xTCPWindowPeekHead( const List_t * pxList );
  135. #endif /* ipconfigUSE_TCP_WIN == 1 */
  136. /*
  137. * Free entry pxSegment because it's not used anymore
  138. * The ownership will be passed back to the segment pool
  139. */
  140. #if ( ipconfigUSE_TCP_WIN == 1 )
  141. static void vTCPWindowFree( TCPSegment_t * pxSegment );
  142. #endif /* ipconfigUSE_TCP_WIN == 1 */
  143. /*
  144. * A segment has been received with sequence number 'ulSequenceNumber', where
  145. * 'ulCurrentSequenceNumber == ulSequenceNumber', which means that exactly this
  146. * segment was expected. xTCPWindowRxConfirm() will check if there is already
  147. * another segment with a sequence number between (ulSequenceNumber) and
  148. * (ulSequenceNumber+xLength). Normally none will be found, because the next Rx
  149. * segment should have a sequence number equal to '(ulSequenceNumber+xLength)'.
  150. */
  151. #if ( ipconfigUSE_TCP_WIN == 1 )
  152. static TCPSegment_t * xTCPWindowRxConfirm( const TCPWindow_t * pxWindow,
  153. uint32_t ulSequenceNumber,
  154. uint32_t ulLength );
  155. #endif /* ipconfigUSE_TCP_WIN == 1 */
  156. /*
  157. * FreeRTOS+TCP stores data in circular buffers. Calculate the next position to
  158. * store.
  159. */
  160. #if ( ipconfigUSE_TCP_WIN == 1 )
  161. static int32_t lTCPIncrementTxPosition( int32_t lPosition,
  162. int32_t lMax,
  163. int32_t lCount );
  164. #endif /* ipconfigUSE_TCP_WIN == 1 */
  165. /*
  166. * This function will look if there is new transmission data. It will return
  167. * true if there is data to be sent.
  168. */
  169. #if ( ipconfigUSE_TCP_WIN == 1 )
  170. static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow,
  171. uint32_t ulWindowSize );
  172. #endif /* ipconfigUSE_TCP_WIN == 1 */
  173. /*
  174. * An acknowledge was received. See if some outstanding data may be removed
  175. * from the transmission queue(s).
  176. */
  177. #if ( ipconfigUSE_TCP_WIN == 1 )
  178. static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t * pxWindow,
  179. uint32_t ulFirst,
  180. uint32_t ulLast );
  181. #endif /* ipconfigUSE_TCP_WIN == 1 */
  182. /*
  183. * A higher Tx block has been acknowledged. Now iterate through the xWaitQueue
  184. * to find a possible condition for a FAST retransmission.
  185. */
  186. #if ( ipconfigUSE_TCP_WIN == 1 )
  187. static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t * pxWindow,
  188. uint32_t ulFirst );
  189. #endif /* ipconfigUSE_TCP_WIN == 1 */
  190. /*-----------------------------------------------------------*/
  191. /**< TCP segment pool. */
  192. #if ( ipconfigUSE_TCP_WIN == 1 )
  193. static TCPSegment_t * xTCPSegments = NULL;
  194. #endif /* ipconfigUSE_TCP_WIN == 1 */
  195. /**< List of free TCP segments. */
  196. #if ( ipconfigUSE_TCP_WIN == 1 )
  197. _static List_t xSegmentList;
  198. #endif
  199. /** @brief Logging verbosity level. */
  200. BaseType_t xTCPWindowLoggingLevel = 0;
  201. #if ( ipconfigUSE_TCP_WIN == 1 )
  202. /* Some 32-bit arithmetic: comparing sequence numbers */
  203. static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a,
  204. uint32_t b );
  205. /**
  206. * @brief Check if a <= b.
  207. *
  208. * @param[in] a: The value on the left-hand side.
  209. * @param[in] b: The value on the right-hand side.
  210. *
  211. * @return pdTRUE when "( b - a ) < 0x80000000". Else, pdFALSE.
  212. */
  213. static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a,
  214. uint32_t b )
  215. {
  216. BaseType_t xResult;
  217. /* Test if a <= b
  218. * Return true if the unsigned subtraction of (b-a) doesn't generate an
  219. * arithmetic overflow. */
  220. if( ( ( b - a ) & 0x80000000UL ) == 0UL )
  221. {
  222. xResult = pdTRUE;
  223. }
  224. else
  225. {
  226. xResult = pdFALSE;
  227. }
  228. return xResult;
  229. }
  230. #endif /* ipconfigUSE_TCP_WIN */
  231. /*-----------------------------------------------------------*/
  232. #if ( ipconfigUSE_TCP_WIN == 1 )
  233. static portINLINE BaseType_t xSequenceLessThan( uint32_t a,
  234. uint32_t b );
  235. /**
  236. * @brief Check if a < b.
  237. *
  238. * @param[in] a: The value on the left-hand side.
  239. * @param[in] b: The value on the right-hand side.
  240. *
  241. * @return pdTRUE when "( b - ( a + 1 ) ) < 0x80000000", else pdFALSE.
  242. */
  243. static portINLINE BaseType_t xSequenceLessThan( uint32_t a,
  244. uint32_t b )
  245. {
  246. BaseType_t xResult;
  247. /* Test if a < b */
  248. if( ( ( b - ( a + 1UL ) ) & 0x80000000UL ) == 0UL )
  249. {
  250. xResult = pdTRUE;
  251. }
  252. else
  253. {
  254. xResult = pdFALSE;
  255. }
  256. return xResult;
  257. }
  258. #endif /* ipconfigUSE_TCP_WIN */
  259. /*-----------------------------------------------------------*/
  260. #if ( ipconfigUSE_TCP_WIN == 1 )
  261. static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a,
  262. uint32_t b );
  263. /**
  264. * @brief Check if a > b.
  265. *
  266. * @param[in] a: The value on the left-hand side.
  267. * @param[in] b: The value on the right-hand side.
  268. *
  269. * @return pdTRUE when "( a - b ) < 0x80000000", else pdFALSE.
  270. */
  271. static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a,
  272. uint32_t b )
  273. {
  274. BaseType_t xResult;
  275. /* Test if a > b */
  276. if( ( ( a - ( b + 1UL ) ) & 0x80000000UL ) == 0UL )
  277. {
  278. xResult = pdTRUE;
  279. }
  280. else
  281. {
  282. xResult = pdFALSE;
  283. }
  284. return xResult;
  285. }
  286. #endif /* ipconfigUSE_TCP_WIN */
  287. /*-----------------------------------------------------------*/
  288. static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a,
  289. uint32_t b );
  290. /**
  291. * @brief Test if a>=b. This function is required since the sequence numbers can roll over.
  292. *
  293. * @param[in] a: The first sequence number.
  294. * @param[in] b: The second sequence number.
  295. *
  296. * @return pdTRUE if a>=b, else pdFALSE.
  297. */
  298. static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a,
  299. uint32_t b )
  300. {
  301. BaseType_t xResult;
  302. /* Test if a >= b */
  303. if( ( ( a - b ) & 0x80000000UL ) == 0UL )
  304. {
  305. xResult = pdTRUE;
  306. }
  307. else
  308. {
  309. xResult = pdFALSE;
  310. }
  311. return xResult;
  312. }
  313. /*-----------------------------------------------------------*/
  314. #if ( ipconfigUSE_TCP_WIN == 1 )
  315. static portINLINE void vListInsertFifo( List_t * const pxList,
  316. ListItem_t * const pxNewListItem );
  317. /**
  318. * @brief Insert the given item in the list in FIFO manner.
  319. *
  320. * @param[in] pxList: The list in which the item is to inserted.
  321. * @param[in] pxNewListItem: The item to be inserted.
  322. */
  323. static portINLINE void vListInsertFifo( List_t * const pxList,
  324. ListItem_t * const pxNewListItem )
  325. {
  326. vListInsertGeneric( pxList, pxNewListItem, &pxList->xListEnd );
  327. }
  328. #endif
  329. /*-----------------------------------------------------------*/
  330. static portINLINE void vTCPTimerSet( TCPTimer_t * pxTimer );
  331. /**
  332. * @brief Set the timer's "born" time.
  333. *
  334. * @param[in] pxTimer: The TCP timer.
  335. */
  336. static portINLINE void vTCPTimerSet( TCPTimer_t * pxTimer )
  337. {
  338. pxTimer->ulBorn = xTaskGetTickCount();
  339. }
  340. /*-----------------------------------------------------------*/
  341. static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t * pxTimer );
  342. /**
  343. * @brief Get the timer age in milliseconds.
  344. *
  345. * @param[in] pxTimer: The timer whose age is to be fetched.
  346. *
  347. * @return The time in milliseconds since the timer was born.
  348. */
  349. static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t * pxTimer )
  350. {
  351. return( ( xTaskGetTickCount() - ( ( TickType_t ) pxTimer->ulBorn ) ) * portTICK_PERIOD_MS );
  352. }
  353. /*-----------------------------------------------------------*/
  354. /**
  355. * @brief Insert a new list item into a list.
  356. *
  357. * @param[in] pxList: The list in which the item is to be inserted.
  358. * @param[in] pxNewListItem: The item to be inserted.
  359. * @param[in] pxWhere: Where should the item be inserted.
  360. */
  361. void vListInsertGeneric( List_t * const pxList,
  362. ListItem_t * const pxNewListItem,
  363. MiniListItem_t * const pxWhere )
  364. {
  365. /* Insert a new list item into pxList, it does not sort the list,
  366. * but it puts the item just before xListEnd, so it will be the last item
  367. * returned by listGET_HEAD_ENTRY() */
  368. pxNewListItem->pxNext = ( struct xLIST_ITEM * configLIST_VOLATILE ) pxWhere;
  369. pxNewListItem->pxPrevious = pxWhere->pxPrevious;
  370. pxWhere->pxPrevious->pxNext = pxNewListItem;
  371. pxWhere->pxPrevious = pxNewListItem;
  372. /* Remember which list the item is in. */
  373. listLIST_ITEM_CONTAINER( pxNewListItem ) = ( struct xLIST * configLIST_VOLATILE ) pxList;
  374. ( pxList->uxNumberOfItems )++;
  375. }
  376. /*-----------------------------------------------------------*/
  377. #if ( ipconfigUSE_TCP_WIN == 1 )
  378. /**
  379. * @brief Creates a pool of 'ipconfigTCP_WIN_SEG_COUNT' sector buffers. Should be called once only.
  380. *
  381. * @return When the allocation was successful: pdPASS, otherwise pdFAIL.
  382. */
  383. static BaseType_t prvCreateSectors( void )
  384. {
  385. BaseType_t xIndex, xReturn;
  386. /* Allocate space for 'xTCPSegments' and store them in 'xSegmentList'. */
  387. vListInitialise( &xSegmentList );
  388. xTCPSegments = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, pvPortMallocLarge( ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
  389. if( xTCPSegments == NULL )
  390. {
  391. FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %u failed\n",
  392. ( unsigned ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
  393. xReturn = pdFAIL;
  394. }
  395. else
  396. {
  397. /* Clear the allocated space. */
  398. ( void ) memset( xTCPSegments, 0, ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );
  399. for( xIndex = 0; xIndex < ipconfigTCP_WIN_SEG_COUNT; xIndex++ )
  400. {
  401. /* Could call vListInitialiseItem here but all data has been
  402. * nulled already. Set the owner to a segment descriptor. */
  403. listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xSegmentItem ), ( void * ) &( xTCPSegments[ xIndex ] ) );
  404. listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ( void * ) &( xTCPSegments[ xIndex ] ) );
  405. /* And add it to the pool of available segments */
  406. vListInsertFifo( &xSegmentList, &( xTCPSegments[ xIndex ].xSegmentItem ) );
  407. }
  408. xReturn = pdPASS;
  409. }
  410. return xReturn;
  411. }
  412. #endif /* ipconfigUSE_TCP_WIN == 1 */
  413. /*-----------------------------------------------------------*/
  414. #if ( ipconfigUSE_TCP_WIN == 1 )
  415. /**
  416. * @brief Find a segment with a given sequence number in the list of received segments.
  417. *
  418. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  419. * @param[in] ulSequenceNumber: the sequence number to look-up
  420. *
  421. * @return The address of the segment descriptor found, or NULL when not found.
  422. */
  423. static TCPSegment_t * xTCPWindowRxFind( const TCPWindow_t * pxWindow,
  424. uint32_t ulSequenceNumber )
  425. {
  426. const ListItem_t * pxIterator;
  427. const ListItem_t * pxEnd;
  428. TCPSegment_t * pxSegment, * pxReturn = NULL;
  429. /* Find a segment with a given sequence number in the list of received
  430. * segments. */
  431. pxEnd = listGET_END_MARKER( &pxWindow->xRxSegments );
  432. for( pxIterator = listGET_NEXT( pxEnd );
  433. pxIterator != pxEnd;
  434. pxIterator = listGET_NEXT( pxIterator ) )
  435. {
  436. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  437. if( pxSegment->ulSequenceNumber == ulSequenceNumber )
  438. {
  439. pxReturn = pxSegment;
  440. break;
  441. }
  442. }
  443. return pxReturn;
  444. }
  445. #endif /* ipconfigUSE_TCP_WIN == 1 */
  446. /*-----------------------------------------------------------*/
  447. #if ( ipconfigUSE_TCP_WIN == 1 )
  448. /**
  449. * @brief Allocate a new segment object, either for transmission or reception.
  450. *
  451. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  452. * @param[in] ulSequenceNumber: The sequence number.
  453. * @param[in] lCount: The number of bytes stored in this segment.
  454. * @param[in] xIsForRx: True when this is a reception segment.
  455. *
  456. * @return Allocate and initialise a segment descriptor, or NULL when none was available.
  457. */
  458. static TCPSegment_t * xTCPWindowNew( TCPWindow_t * pxWindow,
  459. uint32_t ulSequenceNumber,
  460. int32_t lCount,
  461. BaseType_t xIsForRx )
  462. {
  463. TCPSegment_t * pxSegment;
  464. ListItem_t * pxItem;
  465. /* Allocate a new segment. The socket will borrow all segments from a
  466. * common pool: 'xSegmentList', which is a list of 'TCPSegment_t' */
  467. if( listLIST_IS_EMPTY( &xSegmentList ) != pdFALSE )
  468. {
  469. /* If the TCP-stack runs out of segments, you might consider
  470. * increasing 'ipconfigTCP_WIN_SEG_COUNT'. */
  471. FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", ( xIsForRx != 0 ) ? 'R' : 'T' ) );
  472. pxSegment = NULL;
  473. }
  474. else
  475. {
  476. /* Pop the item at the head of the list. Semaphore protection is
  477. * not required as only the IP task will call these functions. */
  478. pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( &xSegmentList );
  479. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxItem ) );
  480. configASSERT( pxItem != NULL );
  481. configASSERT( pxSegment != NULL );
  482. /* Remove the item from xSegmentList. */
  483. ( void ) uxListRemove( pxItem );
  484. /* Add it to either the connections' Rx or Tx queue. */
  485. if( xIsForRx != 0 )
  486. {
  487. vListInsertFifo( &pxWindow->xRxSegments, pxItem );
  488. }
  489. else
  490. {
  491. vListInsertFifo( &pxWindow->xTxSegments, pxItem );
  492. }
  493. /* And set the segment's timer to zero */
  494. vTCPTimerSet( &pxSegment->xTransmitTimer );
  495. pxSegment->u.ulFlags = 0;
  496. pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 ) ? 1U : 0U;
  497. pxSegment->lMaxLength = lCount;
  498. pxSegment->lDataLength = lCount;
  499. pxSegment->ulSequenceNumber = ulSequenceNumber;
  500. #if ( ipconfigHAS_DEBUG_PRINTF != 0 )
  501. {
  502. static UBaseType_t xLowestLength = ipconfigTCP_WIN_SEG_COUNT;
  503. UBaseType_t xLength = listCURRENT_LIST_LENGTH( &xSegmentList );
  504. if( xLowestLength > xLength )
  505. {
  506. xLowestLength = xLength;
  507. }
  508. }
  509. #endif /* ipconfigHAS_DEBUG_PRINTF */
  510. }
  511. return pxSegment;
  512. }
  513. #endif /* ipconfigUSE_TCP_WIN == 1 */
  514. /*-----------------------------------------------------------*/
  515. #if ( ipconfigUSE_TCP_WIN == 1 )
  516. /**
  517. * @brief See if the peer has more packets for this node, before allowing to shut down the connection.
  518. *
  519. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  520. *
  521. * @return pdTRUE if the connection can be closed. Else, pdFALSE.
  522. */
  523. BaseType_t xTCPWindowRxEmpty( const TCPWindow_t * pxWindow )
  524. {
  525. BaseType_t xReturn;
  526. /* When the peer has a close request (FIN flag), the driver will check
  527. * if there are missing packets in the Rx-queue. It will accept the
  528. * closure of the connection if both conditions are true:
  529. * - the Rx-queue is empty
  530. * - the highest Rx sequence number has been ACK'ed */
  531. if( listLIST_IS_EMPTY( ( &pxWindow->xRxSegments ) ) == pdFALSE )
  532. {
  533. /* Rx data has been stored while earlier packets were missing. */
  534. xReturn = pdFALSE;
  535. }
  536. else if( xSequenceGreaterThanOrEqual( pxWindow->rx.ulCurrentSequenceNumber, pxWindow->rx.ulHighestSequenceNumber ) != pdFALSE )
  537. {
  538. /* No Rx packets are being stored and the highest sequence number
  539. * that has been received has been ACKed. */
  540. xReturn = pdTRUE;
  541. }
  542. else
  543. {
  544. FreeRTOS_debug_printf( ( "xTCPWindowRxEmpty: cur %lu highest %lu (empty)\n",
  545. ( pxWindow->rx.ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ),
  546. ( pxWindow->rx.ulHighestSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ) ) );
  547. xReturn = pdFALSE;
  548. }
  549. return xReturn;
  550. }
  551. #endif /* ipconfigUSE_TCP_WIN == 1 */
  552. /*-----------------------------------------------------------*/
  553. #if ( ipconfigUSE_TCP_WIN == 1 )
  554. /**
  555. * @brief Remove the head item of a list (generic function).
  556. *
  557. * @param[in] pxList: The list of segment descriptors.
  558. *
  559. * @return The address of the segment descriptor, or NULL when not found.
  560. */
  561. static TCPSegment_t * xTCPWindowGetHead( const List_t * pxList )
  562. {
  563. TCPSegment_t * pxSegment;
  564. ListItem_t * pxItem;
  565. /* Detaches and returns the head of a queue. */
  566. if( listLIST_IS_EMPTY( pxList ) != pdFALSE )
  567. {
  568. pxSegment = NULL;
  569. }
  570. else
  571. {
  572. pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
  573. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxItem ) );
  574. ( void ) uxListRemove( pxItem );
  575. }
  576. return pxSegment;
  577. }
  578. #endif /* ipconfigUSE_TCP_WIN == 1 */
  579. /*-----------------------------------------------------------*/
  580. #if ( ipconfigUSE_TCP_WIN == 1 )
  581. /**
  582. * @brief Return the head item of a list (generic function).
  583. *
  584. * @param[in] pxList: The list of segment descriptors.
  585. *
  586. * @return The address of the segment descriptor, or NULL when the list is empty.
  587. */
  588. static TCPSegment_t * xTCPWindowPeekHead( const List_t * pxList )
  589. {
  590. const ListItem_t * pxItem;
  591. TCPSegment_t * pxReturn;
  592. /* Returns the head of a queue but it won't be detached. */
  593. if( listLIST_IS_EMPTY( pxList ) != pdFALSE )
  594. {
  595. pxReturn = NULL;
  596. }
  597. else
  598. {
  599. pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
  600. pxReturn = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxItem ) );
  601. }
  602. return pxReturn;
  603. }
  604. #endif /* ipconfigUSE_TCP_WIN == 1 */
  605. /*-----------------------------------------------------------*/
  606. #if ( ipconfigUSE_TCP_WIN == 1 )
  607. /**
  608. * @brief Release a segment object, return it to the list of available segment holders.
  609. *
  610. * @param[in] pxSegment: The segment descriptor that must be freed.
  611. */
  612. static void vTCPWindowFree( TCPSegment_t * pxSegment )
  613. {
  614. /* Free entry pxSegment because it's not used any more. The ownership
  615. * will be passed back to the segment pool.
  616. *
  617. * Unlink it from one of the queues, if any. */
  618. if( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL )
  619. {
  620. ( void ) uxListRemove( &( pxSegment->xQueueItem ) );
  621. }
  622. pxSegment->ulSequenceNumber = 0UL;
  623. pxSegment->lDataLength = 0L;
  624. pxSegment->u.ulFlags = 0UL;
  625. /* Take it out of xRxSegments/xTxSegments */
  626. if( listLIST_ITEM_CONTAINER( &( pxSegment->xSegmentItem ) ) != NULL )
  627. {
  628. ( void ) uxListRemove( &( pxSegment->xSegmentItem ) );
  629. }
  630. /* Return it to xSegmentList */
  631. vListInsertFifo( &xSegmentList, &( pxSegment->xSegmentItem ) );
  632. }
  633. #endif /* ipconfigUSE_TCP_WIN == 1 */
  634. /*-----------------------------------------------------------*/
  635. #if ( ipconfigUSE_TCP_WIN == 1 )
  636. /**
  637. * @brief Return all segment descriptor to the poll of descriptors, before deleting a socket.
  638. *
  639. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  640. */
  641. void vTCPWindowDestroy( TCPWindow_t const * pxWindow )
  642. {
  643. const List_t * pxSegments;
  644. BaseType_t xRound;
  645. TCPSegment_t * pxSegment;
  646. /* Destroy a window. A TCP window doesn't serve any more. Return all
  647. * owned segments to the pool. In order to save code, it will make 2 rounds,
  648. * one to remove the segments from xRxSegments, and a second round to clear
  649. * xTxSegments*/
  650. for( xRound = 0; xRound < 2; xRound++ )
  651. {
  652. if( xRound != 0 )
  653. {
  654. pxSegments = &( pxWindow->xRxSegments );
  655. }
  656. else
  657. {
  658. pxSegments = &( pxWindow->xTxSegments );
  659. }
  660. if( listLIST_IS_INITIALISED( pxSegments ) )
  661. {
  662. while( listCURRENT_LIST_LENGTH( pxSegments ) > 0U )
  663. {
  664. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_OWNER_OF_HEAD_ENTRY( pxSegments ) );
  665. vTCPWindowFree( pxSegment );
  666. }
  667. }
  668. }
  669. }
  670. #endif /* ipconfigUSE_TCP_WIN == 1 */
  671. /*-----------------------------------------------------------*/
  672. /**
  673. * @brief Create a window for TCP.
  674. *
  675. * @param[in] pxWindow: The window to be created.
  676. * @param[in] ulRxWindowLength: The length of the receive window.
  677. * @param[in] ulTxWindowLength: The length of the transmit window.
  678. * @param[in] ulAckNumber: The first ACK number.
  679. * @param[in] ulSequenceNumber: The first sequence number.
  680. * @param[in] ulMSS: The MSS of the connection.
  681. */
  682. void vTCPWindowCreate( TCPWindow_t * pxWindow,
  683. uint32_t ulRxWindowLength,
  684. uint32_t ulTxWindowLength,
  685. uint32_t ulAckNumber,
  686. uint32_t ulSequenceNumber,
  687. uint32_t ulMSS )
  688. {
  689. /* Create and initialize a window. */
  690. #if ( ipconfigUSE_TCP_WIN == 1 )
  691. {
  692. if( xTCPSegments == NULL )
  693. {
  694. ( void ) prvCreateSectors();
  695. }
  696. vListInitialise( &( pxWindow->xTxSegments ) );
  697. vListInitialise( &( pxWindow->xRxSegments ) );
  698. vListInitialise( &( pxWindow->xPriorityQueue ) ); /* Priority queue: segments which must be sent immediately */
  699. vListInitialise( &( pxWindow->xTxQueue ) ); /* Transmit queue: segments queued for transmission */
  700. vListInitialise( &( pxWindow->xWaitQueue ) ); /* Waiting queue: outstanding segments */
  701. }
  702. #endif /* ipconfigUSE_TCP_WIN == 1 */
  703. if( xTCPWindowLoggingLevel != 0 )
  704. {
  705. FreeRTOS_debug_printf( ( "vTCPWindowCreate: for WinLen = Rx/Tx: %lu/%lu\n",
  706. ulRxWindowLength, ulTxWindowLength ) );
  707. }
  708. pxWindow->xSize.ulRxWindowLength = ulRxWindowLength;
  709. pxWindow->xSize.ulTxWindowLength = ulTxWindowLength;
  710. vTCPWindowInit( pxWindow, ulAckNumber, ulSequenceNumber, ulMSS );
  711. }
  712. /*-----------------------------------------------------------*/
  713. /**
  714. * @brief Initialise a TCP window.
  715. *
  716. * @param[in] pxWindow: The window to be initialised.
  717. * @param[in] ulAckNumber: The number of the first ACK.
  718. * @param[in] ulSequenceNumber: The first sequence number.
  719. * @param[in] ulMSS: The MSS of the connection.
  720. */
  721. void vTCPWindowInit( TCPWindow_t * pxWindow,
  722. uint32_t ulAckNumber,
  723. uint32_t ulSequenceNumber,
  724. uint32_t ulMSS )
  725. {
  726. const int32_t l500ms = 500;
  727. pxWindow->u.ulFlags = 0UL;
  728. pxWindow->u.bits.bHasInit = pdTRUE_UNSIGNED;
  729. if( ulMSS != 0UL )
  730. {
  731. if( pxWindow->usMSSInit != 0U )
  732. {
  733. pxWindow->usMSSInit = ( uint16_t ) ulMSS;
  734. }
  735. if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0U ) )
  736. {
  737. pxWindow->xSize.ulRxWindowLength = ( pxWindow->xSize.ulRxWindowLength / ulMSS ) * ulMSS;
  738. pxWindow->usMSS = ( uint16_t ) ulMSS;
  739. }
  740. }
  741. #if ( ipconfigUSE_TCP_WIN == 0 )
  742. {
  743. pxWindow->xTxSegment.lMaxLength = ( int32_t ) pxWindow->usMSS;
  744. }
  745. #endif /* ipconfigUSE_TCP_WIN == 1 */
  746. /*Start with a timeout of 2 * 500 ms (1 sec). */
  747. pxWindow->lSRTT = l500ms;
  748. /* Just for logging, to print relative sequence numbers. */
  749. pxWindow->rx.ulFirstSequenceNumber = ulAckNumber;
  750. /* The segment asked for in the next transmission. */
  751. pxWindow->rx.ulCurrentSequenceNumber = ulAckNumber;
  752. /* The right-hand side of the receive window. */
  753. pxWindow->rx.ulHighestSequenceNumber = ulAckNumber;
  754. pxWindow->tx.ulFirstSequenceNumber = ulSequenceNumber;
  755. /* The segment asked for in next transmission. */
  756. pxWindow->tx.ulCurrentSequenceNumber = ulSequenceNumber;
  757. /* The sequence number given to the next outgoing byte to be added is
  758. * maintained by lTCPWindowTxAdd(). */
  759. pxWindow->ulNextTxSequenceNumber = ulSequenceNumber;
  760. /* The right-hand side of the transmit window. */
  761. pxWindow->tx.ulHighestSequenceNumber = ulSequenceNumber;
  762. pxWindow->ulOurSequenceNumber = ulSequenceNumber;
  763. }
  764. /*-----------------------------------------------------------*/
  765. #if ( ipconfigUSE_TCP_WIN == 1 )
  766. /**
  767. * @brief Free the space occupied by the pool of segment descriptors, normally never used
  768. */
  769. void vTCPSegmentCleanup( void )
  770. {
  771. /* Free and clear the TCP segments pointer. This function should only be called
  772. * once FreeRTOS+TCP will no longer be used. No thread-safety is provided for this
  773. * function. */
  774. if( xTCPSegments != NULL )
  775. {
  776. vPortFreeLarge( xTCPSegments );
  777. xTCPSegments = NULL;
  778. }
  779. }
  780. #endif /* ipconfgiUSE_TCP_WIN == 1 */
  781. /*-----------------------------------------------------------*/
  782. /*=============================================================================
  783. *
  784. * ###### # #
  785. * # # # #
  786. * # # # #
  787. * # # ####
  788. * ###### ##
  789. * # ## ####
  790. * # # # #
  791. * # # # #
  792. * ### ## # #
  793. * Rx functions
  794. *
  795. *=============================================================================*/
  796. #if ( ipconfigUSE_TCP_WIN == 1 )
  797. /**
  798. * @brief A expected segment has been received, see if there is overlap with earlier segments.
  799. *
  800. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  801. * @param[in] ulSequenceNumber: The sequence number of the segment that was received.
  802. * @param[in] ulLength: The number of bytes that were received.
  803. *
  804. * @return The first segment descriptor involved, or NULL when no matching descriptor was found.
  805. */
  806. static TCPSegment_t * xTCPWindowRxConfirm( const TCPWindow_t * pxWindow,
  807. uint32_t ulSequenceNumber,
  808. uint32_t ulLength )
  809. {
  810. TCPSegment_t * pxBest = NULL;
  811. const ListItem_t * pxIterator;
  812. uint32_t ulNextSequenceNumber = ulSequenceNumber + ulLength;
  813. const ListItem_t * pxEnd = listGET_END_MARKER( &pxWindow->xRxSegments );
  814. TCPSegment_t * pxSegment;
  815. /* A segment has been received with sequence number 'ulSequenceNumber',
  816. * where 'ulCurrentSequenceNumber == ulSequenceNumber', which means that
  817. * exactly this segment was expected. xTCPWindowRxConfirm() will check if
  818. * there is already another segment with a sequence number between (ulSequenceNumber)
  819. * and (ulSequenceNumber+ulLength). Normally none will be found, because
  820. * the next RX segment should have a sequence number equal to
  821. * '(ulSequenceNumber+ulLength)'. */
  822. /* Iterate through all RX segments that are stored: */
  823. for( pxIterator = listGET_NEXT( pxEnd );
  824. pxIterator != pxEnd;
  825. pxIterator = listGET_NEXT( pxIterator ) )
  826. {
  827. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  828. /* And see if there is a segment for which:
  829. * 'ulSequenceNumber' <= 'pxSegment->ulSequenceNumber' < 'ulNextSequenceNumber'
  830. * If there are more matching segments, the one with the lowest sequence number
  831. * shall be taken */
  832. if( ( xSequenceGreaterThanOrEqual( pxSegment->ulSequenceNumber, ulSequenceNumber ) != 0 ) &&
  833. ( xSequenceLessThan( pxSegment->ulSequenceNumber, ulNextSequenceNumber ) != 0 ) )
  834. {
  835. if( ( pxBest == NULL ) || ( xSequenceLessThan( pxSegment->ulSequenceNumber, pxBest->ulSequenceNumber ) != 0 ) )
  836. {
  837. pxBest = pxSegment;
  838. }
  839. }
  840. }
  841. if( ( pxBest != NULL ) &&
  842. ( ( pxBest->ulSequenceNumber != ulSequenceNumber ) || ( pxBest->lDataLength != ( int32_t ) ulLength ) ) )
  843. {
  844. FreeRTOS_debug_printf( ( "xTCPWindowRxConfirm[%u]: search %lu (+%ld=%lu) found %lu (+%ld=%lu)\n",
  845. pxWindow->usPeerPortNumber,
  846. ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  847. ulLength,
  848. ulSequenceNumber + ulLength - pxWindow->rx.ulFirstSequenceNumber,
  849. pxBest->ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  850. pxBest->lDataLength,
  851. pxBest->ulSequenceNumber + ( ( uint32_t ) pxBest->lDataLength ) - pxWindow->rx.ulFirstSequenceNumber ) );
  852. }
  853. return pxBest;
  854. }
  855. #endif /* ipconfgiUSE_TCP_WIN == 1 */
  856. /*-----------------------------------------------------------*/
  857. #if ( ipconfigUSE_TCP_WIN == 1 )
  858. /**
  859. * @brief Check what to do with a new incoming packet: store or ignore.
  860. *
  861. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  862. * @param[in] ulSequenceNumber: The sequence number of the packet received.
  863. * @param[in] ulLength: The number of bytes received.
  864. * @param[in] ulSpace: The available space in the RX stream buffer.
  865. *
  866. * @return 0 or positive value indicating the offset at which the packet is to
  867. * be stored, -1 if the packet is to be ignored.
  868. */
  869. int32_t lTCPWindowRxCheck( TCPWindow_t * pxWindow,
  870. uint32_t ulSequenceNumber,
  871. uint32_t ulLength,
  872. uint32_t ulSpace )
  873. {
  874. uint32_t ulCurrentSequenceNumber, ulLast, ulSavedSequenceNumber, ulIntermediateResult = 0;
  875. int32_t lReturn, lDistance;
  876. TCPSegment_t * pxFound;
  877. /* If lTCPWindowRxCheck( ) returns == 0, the packet will be passed
  878. * directly to user (segment is expected). If it returns a positive
  879. * number, an earlier packet is missing, but this packet may be stored.
  880. * If negative, the packet has already been stored, or it is out-of-order,
  881. * or there is not enough space.
  882. *
  883. * As a side-effect, pxWindow->ulUserDataLength will get set to non-zero,
  884. * if more Rx data may be passed to the user after this packet. */
  885. ulCurrentSequenceNumber = pxWindow->rx.ulCurrentSequenceNumber;
  886. /* For Selective Ack (SACK), used when out-of-sequence data come in. */
  887. pxWindow->ucOptionLength = 0U;
  888. /* Non-zero if TCP-windows contains data which must be popped. */
  889. pxWindow->ulUserDataLength = 0UL;
  890. if( ulCurrentSequenceNumber == ulSequenceNumber )
  891. {
  892. /* This is the packet with the lowest sequence number we're waiting
  893. * for. It can be passed directly to the rx stream. */
  894. if( ulLength > ulSpace )
  895. {
  896. FreeRTOS_debug_printf( ( "lTCPWindowRxCheck: Refuse %lu bytes, due to lack of space (%lu)\n", ulLength, ulSpace ) );
  897. lReturn = -1;
  898. }
  899. else
  900. {
  901. ulCurrentSequenceNumber += ulLength;
  902. if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0U )
  903. {
  904. ulSavedSequenceNumber = ulCurrentSequenceNumber;
  905. /* Clean up all sequence received between ulSequenceNumber and ulSequenceNumber + ulLength since they are duplicated.
  906. * If the server is forced to retransmit packets several time in a row it might send a batch of concatenated packet for speed.
  907. * So we cannot rely on the packets between ulSequenceNumber and ulSequenceNumber + ulLength to be sequential and it is better to just
  908. * clean them out. */
  909. do
  910. {
  911. pxFound = xTCPWindowRxConfirm( pxWindow, ulSequenceNumber, ulLength );
  912. if( pxFound != NULL )
  913. {
  914. /* Remove it because it will be passed to user directly. */
  915. vTCPWindowFree( pxFound );
  916. }
  917. } while( pxFound != NULL );
  918. /* Check for following segments that are already in the
  919. * queue and increment ulCurrentSequenceNumber. */
  920. for( ; ; )
  921. {
  922. pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber );
  923. if( pxFound == NULL )
  924. {
  925. break;
  926. }
  927. ulCurrentSequenceNumber += ( uint32_t ) pxFound->lDataLength;
  928. /* As all packet below this one have been passed to the
  929. * user it can be discarded. */
  930. vTCPWindowFree( pxFound );
  931. }
  932. if( ulSavedSequenceNumber != ulCurrentSequenceNumber )
  933. {
  934. /* After the current data-package, there is more data
  935. * to be popped. */
  936. pxWindow->ulUserDataLength = ulCurrentSequenceNumber - ulSavedSequenceNumber;
  937. if( xTCPWindowLoggingLevel >= 1 )
  938. {
  939. FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: retran %lu (Found %lu bytes at %lu cnt %ld)\n",
  940. pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,
  941. ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  942. pxWindow->ulUserDataLength,
  943. ulSavedSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  944. listCURRENT_LIST_LENGTH( &pxWindow->xRxSegments ) ) );
  945. }
  946. }
  947. }
  948. pxWindow->rx.ulCurrentSequenceNumber = ulCurrentSequenceNumber;
  949. /* Packet was expected, may be passed directly to the socket
  950. * buffer or application. Store the packet at offset 0. */
  951. lReturn = 0;
  952. }
  953. }
  954. else if( ulCurrentSequenceNumber == ( ulSequenceNumber + 1UL ) )
  955. {
  956. /* Looks like a TCP keep-alive message. Do not accept/store Rx data
  957. * ulUserDataLength = 0. Not packet out-of-sync. Just reply to it. */
  958. lReturn = -1;
  959. }
  960. else
  961. {
  962. /* The packet is not the one expected. See if it falls within the Rx
  963. * window so it can be stored. */
  964. /* An "out-of-sequence" segment was received, must have missed one.
  965. * Prepare a SACK (Selective ACK). */
  966. ulLast = ulSequenceNumber + ulLength;
  967. ulIntermediateResult = ulLast - ulCurrentSequenceNumber;
  968. /* The cast from unsigned long to signed long is on purpose. */
  969. lDistance = ( int32_t ) ulIntermediateResult;
  970. if( lDistance <= 0 )
  971. {
  972. /* An earlier has been received, must be a retransmission of a
  973. * packet that has been accepted already. No need to send out a
  974. * Selective ACK (SACK). */
  975. lReturn = -1;
  976. }
  977. else if( lDistance > ( int32_t ) ulSpace )
  978. {
  979. /* The new segment is ahead of rx.ulCurrentSequenceNumber. The
  980. * sequence number of this packet is too far ahead, ignore it. */
  981. FreeRTOS_debug_printf( ( "lTCPWindowRxCheck: Refuse %lu+%lu bytes, due to lack of space (%lu)\n", lDistance, ulLength, ulSpace ) );
  982. lReturn = -1;
  983. }
  984. else
  985. {
  986. /* See if there is more data in a contiguous block to make the
  987. * SACK describe a longer range of data. */
  988. /* TODO: SACK's may also be delayed for a short period
  989. * This is useful because subsequent packets will be SACK'd with
  990. * single one message
  991. */
  992. for( ; ; )
  993. {
  994. pxFound = xTCPWindowRxFind( pxWindow, ulLast );
  995. if( pxFound == NULL )
  996. {
  997. break;
  998. }
  999. ulLast += ( uint32_t ) pxFound->lDataLength;
  1000. }
  1001. if( xTCPWindowLoggingLevel >= 1 )
  1002. {
  1003. FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %u exp %u (dist %d) SACK to %u\n",
  1004. ( int ) pxWindow->usPeerPortNumber,
  1005. ( int ) pxWindow->usOurPortNumber,
  1006. ( unsigned ) ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  1007. ( unsigned ) ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  1008. ( unsigned ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */
  1009. ( unsigned ) ( ulLast - pxWindow->rx.ulFirstSequenceNumber ) ) );
  1010. }
  1011. /* Now prepare the SACK message.
  1012. * Code OPTION_CODE_SINGLE_SACK already in network byte order. */
  1013. pxWindow->ulOptionsData[ 0 ] = OPTION_CODE_SINGLE_SACK;
  1014. /* First sequence number that we received. */
  1015. pxWindow->ulOptionsData[ 1 ] = FreeRTOS_htonl( ulSequenceNumber );
  1016. /* Last + 1 */
  1017. pxWindow->ulOptionsData[ 2 ] = FreeRTOS_htonl( ulLast );
  1018. /* Which make 12 (3*4) option bytes. */
  1019. pxWindow->ucOptionLength = ( uint8_t ) ( 3U * sizeof( pxWindow->ulOptionsData[ 0 ] ) );
  1020. pxFound = xTCPWindowRxFind( pxWindow, ulSequenceNumber );
  1021. if( pxFound != NULL )
  1022. {
  1023. /* This out-of-sequence packet has been received for a
  1024. * second time. It is already stored but do send a SACK
  1025. * again. */
  1026. lReturn = -1;
  1027. }
  1028. else
  1029. {
  1030. pxFound = xTCPWindowRxNew( pxWindow, ulSequenceNumber, ( int32_t ) ulLength );
  1031. if( pxFound == NULL )
  1032. {
  1033. /* Can not send a SACK, because the segment cannot be
  1034. * stored. */
  1035. pxWindow->ucOptionLength = 0U;
  1036. /* Needs to be stored but there is no segment
  1037. * available. */
  1038. lReturn = -1;
  1039. }
  1040. else
  1041. {
  1042. if( xTCPWindowLoggingLevel != 0 )
  1043. {
  1044. FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%u,%u]: seqnr %lu (cnt %lu)\n",
  1045. pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber, ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
  1046. listCURRENT_LIST_LENGTH( &pxWindow->xRxSegments ) ) );
  1047. FreeRTOS_flush_logging();
  1048. }
  1049. /* Return a positive value. The packet may be accepted
  1050. * and stored but an earlier packet is still missing. */
  1051. ulIntermediateResult = ulSequenceNumber - ulCurrentSequenceNumber;
  1052. lReturn = ( int32_t ) ulIntermediateResult;
  1053. }
  1054. }
  1055. }
  1056. }
  1057. return lReturn;
  1058. }
  1059. #endif /* ipconfgiUSE_TCP_WIN == 1 */
  1060. /*-----------------------------------------------------------*/
  1061. /*=============================================================================
  1062. *
  1063. * ######### # #
  1064. * # # # # #
  1065. * # # #
  1066. * # ####
  1067. * # ##
  1068. * # ####
  1069. * # # #
  1070. * # # #
  1071. * ##### # #
  1072. *
  1073. * Tx functions
  1074. *
  1075. *=============================================================================*/
  1076. #if ( ipconfigUSE_TCP_WIN == 1 )
  1077. /**
  1078. * @brief Increment the position in a circular buffer of size 'lMax'.
  1079. *
  1080. * @param[in] lPosition: The current index in the buffer.
  1081. * @param[in] lMax: The total number of items in this buffer.
  1082. * @param[in] lCount: The number of bytes that must be advanced.
  1083. *
  1084. * @return The new incremented position, or "( lPosition + lCount ) % lMax".
  1085. */
  1086. static int32_t lTCPIncrementTxPosition( int32_t lPosition,
  1087. int32_t lMax,
  1088. int32_t lCount )
  1089. {
  1090. int32_t lReturn;
  1091. /* +TCP stores data in circular buffers. Calculate the next position to
  1092. * store. */
  1093. lReturn = lPosition + lCount;
  1094. if( lReturn >= lMax )
  1095. {
  1096. lReturn -= lMax;
  1097. }
  1098. return lReturn;
  1099. }
  1100. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1101. /*-----------------------------------------------------------*/
  1102. #if ( ipconfigUSE_TCP_WIN == 1 )
  1103. /**
  1104. * @brief Will add data to be transmitted to the front of the segment fifo.
  1105. *
  1106. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1107. * @param[in] ulLength: The number of bytes that will be sent.
  1108. * @param[in] lPosition: The index in the TX stream buffer.
  1109. * @param[in] lMax: The size of the ( circular ) TX stream buffer.
  1110. *
  1111. * @return The number of bytes added to the sliding window for transmission.
  1112. *
  1113. */
  1114. int32_t lTCPWindowTxAdd( TCPWindow_t * pxWindow,
  1115. uint32_t ulLength,
  1116. int32_t lPosition,
  1117. int32_t lMax )
  1118. {
  1119. int32_t lBytesLeft = ( int32_t ) ulLength, lToWrite;
  1120. int32_t lDone = 0;
  1121. int32_t lBufferIndex = lPosition;
  1122. TCPSegment_t * pxSegment = pxWindow->pxHeadSegment;
  1123. /* Puts a message in the Tx-window (after buffer size has been
  1124. * verified). */
  1125. if( pxSegment != NULL )
  1126. {
  1127. if( pxSegment->lDataLength < pxSegment->lMaxLength )
  1128. {
  1129. if( ( pxSegment->u.bits.bOutstanding == pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength != 0 ) )
  1130. {
  1131. /* Adding data to a segment that was already in the TX queue. It
  1132. * will be filled-up to a maximum of MSS (maximum segment size). */
  1133. lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength - pxSegment->lDataLength );
  1134. pxSegment->lDataLength += lToWrite;
  1135. if( pxSegment->lDataLength >= pxSegment->lMaxLength )
  1136. {
  1137. /* This segment is full, don't add more bytes. */
  1138. pxWindow->pxHeadSegment = NULL;
  1139. }
  1140. lBytesLeft -= lToWrite;
  1141. /* ulNextTxSequenceNumber is the sequence number of the next byte to
  1142. * be stored for transmission. */
  1143. pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;
  1144. /* Increased the return value. */
  1145. lDone += lToWrite;
  1146. /* Some detailed logging, for those who're interested. */
  1147. if( ( xTCPWindowLoggingLevel >= 2 ) && ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
  1148. {
  1149. FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Add %4lu bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",
  1150. ulLength,
  1151. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1152. pxSegment->lDataLength,
  1153. pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1154. pxSegment->lStreamPos ) );
  1155. FreeRTOS_flush_logging();
  1156. }
  1157. /* Calculate the next position in the circular data buffer, knowing
  1158. * its maximum length 'lMax'. */
  1159. lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
  1160. }
  1161. }
  1162. }
  1163. while( lBytesLeft > 0 )
  1164. {
  1165. /* The current transmission segment is full, create new segments as
  1166. * needed. */
  1167. pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, ( int32_t ) pxWindow->usMSS );
  1168. if( pxSegment != NULL )
  1169. {
  1170. /* Store as many as needed, but no more than the maximum
  1171. * (MSS). */
  1172. lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength );
  1173. pxSegment->lDataLength = lToWrite;
  1174. pxSegment->lStreamPos = lBufferIndex;
  1175. lBytesLeft -= lToWrite;
  1176. lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
  1177. pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;
  1178. lDone += lToWrite;
  1179. /* Link this segment in the Tx-Queue. */
  1180. vListInsertFifo( &( pxWindow->xTxQueue ), &( pxSegment->xQueueItem ) );
  1181. /* Let 'pxHeadSegment' point to this segment if there is still
  1182. * space. */
  1183. if( pxSegment->lDataLength < pxSegment->lMaxLength )
  1184. {
  1185. pxWindow->pxHeadSegment = pxSegment;
  1186. }
  1187. else
  1188. {
  1189. pxWindow->pxHeadSegment = NULL;
  1190. }
  1191. if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
  1192. {
  1193. if( ( xTCPWindowLoggingLevel >= 3 ) ||
  1194. ( ( xTCPWindowLoggingLevel >= 2 ) && ( pxWindow->pxHeadSegment != NULL ) ) )
  1195. {
  1196. FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: New %4ld bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",
  1197. ulLength,
  1198. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1199. pxSegment->lDataLength,
  1200. pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1201. pxSegment->lStreamPos ) );
  1202. FreeRTOS_flush_logging();
  1203. }
  1204. }
  1205. }
  1206. else
  1207. {
  1208. /* A sever situation: running out of segments for transmission.
  1209. * No more data can be sent at the moment. */
  1210. if( lDone != 0 )
  1211. {
  1212. FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Sorry all buffers full (cancel %ld bytes)\n", lBytesLeft ) );
  1213. }
  1214. break;
  1215. }
  1216. }
  1217. return lDone;
  1218. }
  1219. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1220. /*-----------------------------------------------------------*/
  1221. #if ( ipconfigUSE_TCP_WIN == 1 )
  1222. /**
  1223. * @brief Returns true if there are no more outstanding TX segments.
  1224. *
  1225. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1226. *
  1227. * @return pdTRUE if there are no more outstanding Tx segments, else pdFALSE.
  1228. */
  1229. BaseType_t xTCPWindowTxDone( const TCPWindow_t * pxWindow )
  1230. {
  1231. return listLIST_IS_EMPTY( ( &pxWindow->xTxSegments ) );
  1232. }
  1233. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1234. /*-----------------------------------------------------------*/
  1235. #if ( ipconfigUSE_TCP_WIN == 1 )
  1236. /**
  1237. * @brief Find out if the peer is able to receive more data.
  1238. *
  1239. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1240. * @param[in] ulWindowSize: The number of bytes in this segment.
  1241. *
  1242. * @return True if the peer has space in it window to receive more data.
  1243. */
  1244. static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow,
  1245. uint32_t ulWindowSize )
  1246. {
  1247. uint32_t ulTxOutstanding;
  1248. BaseType_t xHasSpace;
  1249. const TCPSegment_t * pxSegment;
  1250. uint32_t ulNettSize;
  1251. /* This function will look if there is new transmission data. It will
  1252. * return true if there is data to be sent. */
  1253. pxSegment = xTCPWindowPeekHead( &( pxWindow->xTxQueue ) );
  1254. if( pxSegment == NULL )
  1255. {
  1256. xHasSpace = pdFALSE;
  1257. }
  1258. else
  1259. {
  1260. /* How much data is outstanding, i.e. how much data has been sent
  1261. * but not yet acknowledged ? */
  1262. if( pxWindow->tx.ulHighestSequenceNumber >= pxWindow->tx.ulCurrentSequenceNumber )
  1263. {
  1264. ulTxOutstanding = pxWindow->tx.ulHighestSequenceNumber - pxWindow->tx.ulCurrentSequenceNumber;
  1265. }
  1266. else
  1267. {
  1268. ulTxOutstanding = 0UL;
  1269. }
  1270. /* Subtract this from the peer's space. */
  1271. ulNettSize = ulWindowSize - FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding );
  1272. /* See if the next segment may be sent. */
  1273. if( ulNettSize >= ( uint32_t ) pxSegment->lDataLength )
  1274. {
  1275. xHasSpace = pdTRUE;
  1276. }
  1277. else
  1278. {
  1279. xHasSpace = pdFALSE;
  1280. }
  1281. /* If 'xHasSpace', it looks like the peer has at least space for 1
  1282. * more new segment of size MSS. xSize.ulTxWindowLength is the self-imposed
  1283. * limitation of the transmission window (in case of many resends it
  1284. * may be decreased). */
  1285. if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ( ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) ) )
  1286. {
  1287. xHasSpace = pdFALSE;
  1288. }
  1289. }
  1290. return xHasSpace;
  1291. }
  1292. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1293. /*-----------------------------------------------------------*/
  1294. #if ( ipconfigUSE_TCP_WIN == 1 )
  1295. /**
  1296. * @brief Returns true if there is TX data that can be sent right now.
  1297. *
  1298. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1299. * @param[in] ulWindowSize: The current size of the sliding RX window of the peer.
  1300. * @param[out] pulDelay: The delay before the packet may be sent.
  1301. *
  1302. * @return pdTRUE if there is Tx data that can be sent, else pdFALSE.
  1303. */
  1304. BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow,
  1305. uint32_t ulWindowSize,
  1306. TickType_t * pulDelay )
  1307. {
  1308. TCPSegment_t const * pxSegment;
  1309. BaseType_t xReturn;
  1310. TickType_t ulAge, ulMaxAge;
  1311. *pulDelay = 0U;
  1312. if( listLIST_IS_EMPTY( &pxWindow->xPriorityQueue ) == pdFALSE )
  1313. {
  1314. /* No need to look at retransmissions or new transmission as long as
  1315. * there are priority segments. *pulDelay equals zero, meaning it must
  1316. * be sent out immediately. */
  1317. xReturn = pdTRUE;
  1318. }
  1319. else
  1320. {
  1321. pxSegment = xTCPWindowPeekHead( &( pxWindow->xWaitQueue ) );
  1322. if( pxSegment != NULL )
  1323. {
  1324. /* There is an outstanding segment, see if it is time to resend
  1325. * it. */
  1326. ulAge = ulTimerGetAge( &pxSegment->xTransmitTimer );
  1327. /* After a packet has been sent for the first time, it will wait
  1328. * '1 * lSRTT' ms for an ACK. A second time it will wait '2 * lSRTT' ms,
  1329. * each time doubling the time-out */
  1330. ulMaxAge = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
  1331. if( ulMaxAge > ulAge )
  1332. {
  1333. /* A segment must be sent after this amount of msecs */
  1334. *pulDelay = ulMaxAge - ulAge;
  1335. }
  1336. xReturn = pdTRUE;
  1337. }
  1338. else
  1339. {
  1340. /* No priority segment, no outstanding data, see if there is new
  1341. * transmission data. */
  1342. pxSegment = xTCPWindowPeekHead( &pxWindow->xTxQueue );
  1343. /* See if it fits in the peer's reception window. */
  1344. if( pxSegment == NULL )
  1345. {
  1346. xReturn = pdFALSE;
  1347. }
  1348. else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )
  1349. {
  1350. /* Too many outstanding messages. */
  1351. xReturn = pdFALSE;
  1352. }
  1353. else if( ( pxWindow->u.bits.bSendFullSize != pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength < pxSegment->lMaxLength ) )
  1354. {
  1355. /* 'bSendFullSize' is a special optimisation. If true, the
  1356. * driver will only sent completely filled packets (of MSS
  1357. * bytes). */
  1358. xReturn = pdFALSE;
  1359. }
  1360. else
  1361. {
  1362. xReturn = pdTRUE;
  1363. }
  1364. }
  1365. }
  1366. return xReturn;
  1367. }
  1368. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1369. /*-----------------------------------------------------------*/
  1370. #if ( ipconfigUSE_TCP_WIN == 1 )
  1371. /**
  1372. * @brief Get data that can be transmitted right now.
  1373. *
  1374. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1375. * @param[in] ulWindowSize: The current size of the sliding RX window of the peer.
  1376. * @param[out] plPosition: The index within the TX stream buffer of the first byte to be sent.
  1377. *
  1378. * @return The amount of data in bytes that can be transmitted right now.
  1379. */
  1380. uint32_t ulTCPWindowTxGet( TCPWindow_t * pxWindow,
  1381. uint32_t ulWindowSize,
  1382. int32_t * plPosition )
  1383. {
  1384. TCPSegment_t * pxSegment;
  1385. uint32_t ulMaxTime;
  1386. uint32_t ulReturn = ~0UL;
  1387. /* Fetches data to be sent-out now.
  1388. *
  1389. * Priority messages: segments with a resend need no check current sliding
  1390. * window size. */
  1391. pxSegment = xTCPWindowGetHead( &( pxWindow->xPriorityQueue ) );
  1392. pxWindow->ulOurSequenceNumber = pxWindow->tx.ulHighestSequenceNumber;
  1393. if( pxSegment == NULL )
  1394. {
  1395. /* Waiting messages: outstanding messages with a running timer
  1396. * neither check peer's reception window size because these packets
  1397. * have been sent earlier. */
  1398. pxSegment = xTCPWindowPeekHead( &( pxWindow->xWaitQueue ) );
  1399. if( pxSegment != NULL )
  1400. {
  1401. /* Do check the timing. */
  1402. ulMaxTime = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
  1403. if( ulTimerGetAge( &pxSegment->xTransmitTimer ) > ulMaxTime )
  1404. {
  1405. /* A normal (non-fast) retransmission. Move it from the
  1406. * head of the waiting queue. */
  1407. pxSegment = xTCPWindowGetHead( &( pxWindow->xWaitQueue ) );
  1408. pxSegment->u.bits.ucDupAckCount = ( uint8_t ) pdFALSE_UNSIGNED;
  1409. /* Some detailed logging. */
  1410. if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
  1411. {
  1412. FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: WaitQueue %ld bytes for sequence number %lu (%lX)\n",
  1413. pxWindow->usPeerPortNumber,
  1414. pxWindow->usOurPortNumber,
  1415. pxSegment->lDataLength,
  1416. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1417. pxSegment->ulSequenceNumber ) );
  1418. FreeRTOS_flush_logging();
  1419. }
  1420. }
  1421. else
  1422. {
  1423. pxSegment = NULL;
  1424. }
  1425. }
  1426. if( pxSegment == NULL )
  1427. {
  1428. /* New messages: sent-out for the first time. Check current
  1429. * sliding window size of peer. */
  1430. pxSegment = xTCPWindowPeekHead( &( pxWindow->xTxQueue ) );
  1431. if( pxSegment == NULL )
  1432. {
  1433. /* No segments queued. */
  1434. ulReturn = 0UL;
  1435. }
  1436. else if( ( pxWindow->u.bits.bSendFullSize != pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength < pxSegment->lMaxLength ) )
  1437. {
  1438. /* A segment has been queued but the driver waits until it
  1439. * has a full size of MSS. */
  1440. ulReturn = 0;
  1441. }
  1442. else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )
  1443. {
  1444. /* Peer has no more space at this moment. */
  1445. ulReturn = 0;
  1446. }
  1447. else
  1448. {
  1449. /* Move it out of the Tx queue. */
  1450. pxSegment = xTCPWindowGetHead( &( pxWindow->xTxQueue ) );
  1451. /* Don't let pxHeadSegment point to this segment any more,
  1452. * so no more data will be added. */
  1453. if( pxWindow->pxHeadSegment == pxSegment )
  1454. {
  1455. pxWindow->pxHeadSegment = NULL;
  1456. }
  1457. /* pxWindow->tx.highest registers the highest sequence
  1458. * number in our transmission window. */
  1459. pxWindow->tx.ulHighestSequenceNumber = pxSegment->ulSequenceNumber + ( ( uint32_t ) pxSegment->lDataLength );
  1460. /* ...and more detailed logging */
  1461. if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
  1462. {
  1463. FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: XmitQueue %ld bytes for sequence number %lu (ws %lu)\n",
  1464. pxWindow->usPeerPortNumber,
  1465. pxWindow->usOurPortNumber,
  1466. pxSegment->lDataLength,
  1467. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1468. ulWindowSize ) );
  1469. FreeRTOS_flush_logging();
  1470. }
  1471. }
  1472. }
  1473. }
  1474. else
  1475. {
  1476. /* There is a priority segment. It doesn't need any checking for
  1477. * space or timeouts. */
  1478. if( xTCPWindowLoggingLevel != 0 )
  1479. {
  1480. FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: PrioQueue %ld bytes for sequence number %lu (ws %lu)\n",
  1481. pxWindow->usPeerPortNumber,
  1482. pxWindow->usOurPortNumber,
  1483. pxSegment->lDataLength,
  1484. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1485. ulWindowSize ) );
  1486. FreeRTOS_flush_logging();
  1487. }
  1488. }
  1489. /* See if it has already been determined to return 0. */
  1490. if( ulReturn != 0UL )
  1491. {
  1492. /* pxSegment is not NULL when ulReturn != 0UL. */
  1493. configASSERT( pxSegment != NULL );
  1494. configASSERT( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) == NULL );
  1495. /* Now that the segment will be transmitted, add it to the tail of
  1496. * the waiting queue. */
  1497. vListInsertFifo( &pxWindow->xWaitQueue, &pxSegment->xQueueItem );
  1498. /* And mark it as outstanding. */
  1499. pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;
  1500. /* Administer the transmit count, needed for fast
  1501. * retransmissions. */
  1502. ( pxSegment->u.bits.ucTransmitCount )++;
  1503. /* If there have been several retransmissions (4), decrease the
  1504. * size of the transmission window to at most 2 times MSS. */
  1505. if( pxSegment->u.bits.ucTransmitCount == MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW )
  1506. {
  1507. if( pxWindow->xSize.ulTxWindowLength > ( 2U * ( ( uint32_t ) pxWindow->usMSS ) ) )
  1508. {
  1509. FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u - %d]: Change Tx window: %lu -> %u\n",
  1510. pxWindow->usPeerPortNumber,
  1511. pxWindow->usOurPortNumber,
  1512. pxWindow->xSize.ulTxWindowLength,
  1513. 2U * pxWindow->usMSS ) );
  1514. pxWindow->xSize.ulTxWindowLength = ( 2UL * pxWindow->usMSS );
  1515. }
  1516. }
  1517. /* Clear the transmit timer. */
  1518. vTCPTimerSet( &( pxSegment->xTransmitTimer ) );
  1519. pxWindow->ulOurSequenceNumber = pxSegment->ulSequenceNumber;
  1520. /* Inform the caller where to find the data within the queue. */
  1521. *plPosition = pxSegment->lStreamPos;
  1522. /* And return the length of the data segment */
  1523. ulReturn = ( uint32_t ) pxSegment->lDataLength;
  1524. }
  1525. return ulReturn;
  1526. }
  1527. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1528. /*-----------------------------------------------------------*/
  1529. #if ( ipconfigUSE_TCP_WIN == 1 )
  1530. /**
  1531. * @brief An acknowledgement or a selective ACK (SACK) was received. See if some outstanding data
  1532. * may be removed from the transmission queue(s). All TX segments for which
  1533. * ( ( ulSequenceNumber >= ulFirst ) && ( ulSequenceNumber < ulLast ) in a contiguous block.
  1534. * Note that the segments are stored in xTxSegments in a strict sequential order.
  1535. *
  1536. * @param[in] pxWindow: The TCP-window object of the current connection.
  1537. * @param[in] ulFirst: The sequence number of the first byte that was acknowledged.
  1538. * @param[in] ulLast: The sequence number of the last byte ( minus one ) that was acknowledged.
  1539. *
  1540. * @return number of bytes that the tail of txStream may be advanced.
  1541. */
  1542. static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t * pxWindow,
  1543. uint32_t ulFirst,
  1544. uint32_t ulLast )
  1545. {
  1546. uint32_t ulBytesConfirmed = 0U;
  1547. uint32_t ulSequenceNumber = ulFirst, ulDataLength;
  1548. const ListItem_t * pxIterator;
  1549. const ListItem_t * pxEnd = listGET_END_MARKER( &pxWindow->xTxSegments );
  1550. BaseType_t xDoUnlink;
  1551. TCPSegment_t * pxSegment;
  1552. /* An acknowledgement or a selective ACK (SACK) was received. See if some outstanding data
  1553. * may be removed from the transmission queue(s).
  1554. * All TX segments for which
  1555. * ( ( ulSequenceNumber >= ulFirst ) && ( ulSequenceNumber < ulLast ) in a
  1556. * contiguous block. Note that the segments are stored in xTxSegments in a
  1557. * strict sequential order. */
  1558. /* SRTT[i] = (1-a) * SRTT[i-1] + a * RTT
  1559. *
  1560. * 0 < a < 1; usually a = 1/8
  1561. *
  1562. * RTO = 2 * SRTT
  1563. *
  1564. * where:
  1565. * RTT is Round Trip Time
  1566. * SRTT is Smoothed RTT
  1567. * RTO is Retransmit timeout
  1568. *
  1569. * A Smoothed RTT will increase quickly, but it is conservative when
  1570. * becoming smaller. */
  1571. pxIterator = listGET_NEXT( pxEnd );
  1572. while( ( pxIterator != pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 ) )
  1573. {
  1574. xDoUnlink = pdFALSE;
  1575. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  1576. /* Move to the next item because the current item might get
  1577. * removed. */
  1578. pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
  1579. /* Continue if this segment does not fall within the ACK'd range. */
  1580. if( xSequenceGreaterThan( ulSequenceNumber, pxSegment->ulSequenceNumber ) != pdFALSE )
  1581. {
  1582. continue;
  1583. }
  1584. /* Is it ready? */
  1585. if( ulSequenceNumber != pxSegment->ulSequenceNumber )
  1586. {
  1587. /* coverity[break_stmt] : Break statement terminating the loop */
  1588. break;
  1589. }
  1590. ulDataLength = ( uint32_t ) pxSegment->lDataLength;
  1591. if( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED )
  1592. {
  1593. if( xSequenceGreaterThan( pxSegment->ulSequenceNumber + ( uint32_t ) ulDataLength, ulLast ) != pdFALSE )
  1594. {
  1595. /* What happens? Only part of this segment was accepted,
  1596. * probably due to WND limits
  1597. *
  1598. * AAAAAAA BBBBBBB << acked
  1599. * aaaaaaa aaaa << sent */
  1600. #if ( ipconfigHAS_DEBUG_PRINTF != 0 )
  1601. {
  1602. uint32_t ulFirstSeq = pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber;
  1603. FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck[%u.%u]: %lu - %lu Partial sequence number %lu - %lu\n",
  1604. pxWindow->usPeerPortNumber,
  1605. pxWindow->usOurPortNumber,
  1606. ulFirstSeq - pxWindow->tx.ulFirstSequenceNumber,
  1607. ulLast - pxWindow->tx.ulFirstSequenceNumber,
  1608. ulFirstSeq, ulFirstSeq + ulDataLength ) );
  1609. }
  1610. #endif /* ipconfigHAS_DEBUG_PRINTF */
  1611. break;
  1612. }
  1613. /* This segment is fully ACK'd, set the flag. */
  1614. pxSegment->u.bits.bAcked = pdTRUE;
  1615. /* Calculate the RTT only if the segment was sent-out for the
  1616. * first time and if this is the last ACK'd segment in a range. */
  1617. if( ( pxSegment->u.bits.ucTransmitCount == 1U ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) )
  1618. {
  1619. int32_t mS = ( int32_t ) ulTimerGetAge( &( pxSegment->xTransmitTimer ) );
  1620. if( pxWindow->lSRTT >= mS )
  1621. {
  1622. /* RTT becomes smaller: adapt slowly. */
  1623. pxWindow->lSRTT = ( ( winSRTT_DECREMENT_NEW * mS ) + ( winSRTT_DECREMENT_CURRENT * pxWindow->lSRTT ) ) / ( winSRTT_DECREMENT_NEW + winSRTT_DECREMENT_CURRENT );
  1624. }
  1625. else
  1626. {
  1627. /* RTT becomes larger: adapt quicker */
  1628. pxWindow->lSRTT = ( ( winSRTT_INCREMENT_NEW * mS ) + ( winSRTT_INCREMENT_CURRENT * pxWindow->lSRTT ) ) / ( winSRTT_INCREMENT_NEW + winSRTT_INCREMENT_CURRENT );
  1629. }
  1630. /* Cap to the minimum of 50ms. */
  1631. if( pxWindow->lSRTT < winSRTT_CAP_mS )
  1632. {
  1633. pxWindow->lSRTT = winSRTT_CAP_mS;
  1634. }
  1635. }
  1636. /* Unlink it from the 3 queues, but do not destroy it (yet). */
  1637. xDoUnlink = pdTRUE;
  1638. }
  1639. /* pxSegment->u.bits.bAcked is now true. Is it located at the left
  1640. * side of the transmission queue? If so, it may be freed. */
  1641. if( ulSequenceNumber == pxWindow->tx.ulCurrentSequenceNumber )
  1642. {
  1643. if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
  1644. {
  1645. FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck: %lu - %lu Ready sequence number %lu\n",
  1646. ulFirst - pxWindow->tx.ulFirstSequenceNumber,
  1647. ulLast - pxWindow->tx.ulFirstSequenceNumber,
  1648. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber ) );
  1649. }
  1650. /* Increase the left-hand value of the transmission window. */
  1651. pxWindow->tx.ulCurrentSequenceNumber += ulDataLength;
  1652. /* This function will return the number of bytes that the tail
  1653. * of txStream may be advanced. */
  1654. ulBytesConfirmed += ulDataLength;
  1655. /* All segments below tx.ulCurrentSequenceNumber may be freed. */
  1656. vTCPWindowFree( pxSegment );
  1657. /* No need to unlink it any more. */
  1658. xDoUnlink = pdFALSE;
  1659. }
  1660. if( ( xDoUnlink != pdFALSE ) && ( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) )
  1661. {
  1662. /* Remove item from its queues. */
  1663. ( void ) uxListRemove( &pxSegment->xQueueItem );
  1664. }
  1665. ulSequenceNumber += ulDataLength;
  1666. }
  1667. return ulBytesConfirmed;
  1668. }
  1669. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1670. /*-----------------------------------------------------------*/
  1671. #if ( ipconfigUSE_TCP_WIN == 1 )
  1672. /**
  1673. * @brief See if there are segments that need a fast retransmission.
  1674. *
  1675. * @param[in] pxWindow: The descriptor of the TCP sliding windows.
  1676. * @param[in] ulFirst: The sequence number of the first segment that must be checked.
  1677. *
  1678. * @return The number of segments that need a fast retransmission.
  1679. */
  1680. static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t * pxWindow,
  1681. uint32_t ulFirst )
  1682. {
  1683. const ListItem_t * pxIterator;
  1684. const ListItem_t * pxEnd;
  1685. TCPSegment_t * pxSegment;
  1686. uint32_t ulCount = 0UL;
  1687. /* A higher Tx block has been acknowledged. Now iterate through the
  1688. * xWaitQueue to find a possible condition for a FAST retransmission. */
  1689. pxEnd = listGET_END_MARKER( &( pxWindow->xWaitQueue ) );
  1690. pxIterator = listGET_NEXT( pxEnd );
  1691. while( pxIterator != pxEnd )
  1692. {
  1693. /* Get the owner, which is a TCP segment. */
  1694. pxSegment = ipCAST_PTR_TO_TYPE_PTR( TCPSegment_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  1695. /* Hop to the next item before the current gets unlinked. */
  1696. pxIterator = listGET_NEXT( pxIterator );
  1697. /* Fast retransmission:
  1698. * When 3 packets with a higher sequence number have been acknowledged
  1699. * by the peer, it is very unlikely a current packet will ever arrive.
  1700. * It will be retransmitted far before the RTO. */
  1701. if( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED )
  1702. {
  1703. if( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE )
  1704. {
  1705. pxSegment->u.bits.ucDupAckCount++;
  1706. if( pxSegment->u.bits.ucDupAckCount == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT )
  1707. {
  1708. pxSegment->u.bits.ucTransmitCount = ( uint8_t ) pdFALSE;
  1709. /* Not clearing 'ucDupAckCount' yet as more SACK's might come in
  1710. * which might lead to a second fast rexmit. */
  1711. if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
  1712. {
  1713. FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n",
  1714. pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1715. ulFirst - pxWindow->tx.ulFirstSequenceNumber ) );
  1716. FreeRTOS_flush_logging();
  1717. }
  1718. /* Remove it from xWaitQueue. */
  1719. ( void ) uxListRemove( &pxSegment->xQueueItem );
  1720. /* Add this segment to the priority queue so it gets
  1721. * retransmitted immediately. */
  1722. vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) );
  1723. ulCount++;
  1724. }
  1725. }
  1726. }
  1727. }
  1728. return ulCount;
  1729. }
  1730. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1731. /*-----------------------------------------------------------*/
  1732. #if ( ipconfigUSE_TCP_WIN == 1 )
  1733. /**
  1734. * @brief Receive a normal ACK.
  1735. *
  1736. * @param[in] pxWindow: Window in which a data is receive.
  1737. * @param[in] ulSequenceNumber: The sequence number of the ACK.
  1738. *
  1739. * @return The location where the packet should be added.
  1740. */
  1741. uint32_t ulTCPWindowTxAck( TCPWindow_t * pxWindow,
  1742. uint32_t ulSequenceNumber )
  1743. {
  1744. uint32_t ulFirstSequence, ulReturn;
  1745. /* Receive a normal ACK. */
  1746. ulFirstSequence = pxWindow->tx.ulCurrentSequenceNumber;
  1747. if( xSequenceLessThanOrEqual( ulSequenceNumber, ulFirstSequence ) != pdFALSE )
  1748. {
  1749. ulReturn = 0UL;
  1750. }
  1751. else
  1752. {
  1753. ulReturn = prvTCPWindowTxCheckAck( pxWindow, ulFirstSequence, ulSequenceNumber );
  1754. }
  1755. return ulReturn;
  1756. }
  1757. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1758. /*-----------------------------------------------------------*/
  1759. #if ( ipconfigUSE_TCP_WIN == 1 )
  1760. /**
  1761. * @brief Receive a SACK option.
  1762. *
  1763. * @param[in] pxWindow: Window in which the data is received.
  1764. * @param[in] ulFirst: Index of starting position of options.
  1765. * @param[in] ulLast: Index of end position of the options.
  1766. *
  1767. * @return returns the number of bytes which have been acked starting from
  1768. * the head position.
  1769. */
  1770. uint32_t ulTCPWindowTxSack( TCPWindow_t * pxWindow,
  1771. uint32_t ulFirst,
  1772. uint32_t ulLast )
  1773. {
  1774. uint32_t ulAckCount;
  1775. uint32_t ulCurrentSequenceNumber = pxWindow->tx.ulCurrentSequenceNumber;
  1776. /* Receive a SACK option. */
  1777. ulAckCount = prvTCPWindowTxCheckAck( pxWindow, ulFirst, ulLast );
  1778. ( void ) prvTCPWindowFastRetransmit( pxWindow, ulFirst );
  1779. if( ( xTCPWindowLoggingLevel >= 1 ) && ( xSequenceGreaterThan( ulFirst, ulCurrentSequenceNumber ) != pdFALSE ) )
  1780. {
  1781. FreeRTOS_debug_printf( ( "ulTCPWindowTxSack[%u,%u]: from %lu to %lu (ack = %lu)\n",
  1782. pxWindow->usPeerPortNumber,
  1783. pxWindow->usOurPortNumber,
  1784. ulFirst - pxWindow->tx.ulFirstSequenceNumber,
  1785. ulLast - pxWindow->tx.ulFirstSequenceNumber,
  1786. pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber ) );
  1787. FreeRTOS_flush_logging();
  1788. }
  1789. return ulAckCount;
  1790. }
  1791. #endif /* ipconfigUSE_TCP_WIN == 1 */
  1792. /*-----------------------------------------------------------*/
  1793. /*
  1794. ##### # ##### #### ######
  1795. # # # # # # # # # # #
  1796. # # # # # #
  1797. # ### ##### # # # # # #
  1798. # # # # # # # # #####
  1799. # # # # # # #### # # #
  1800. # # # # # # # # # #
  1801. # # # # #### # # # #
  1802. #### ##### # # # #### #### ####
  1803. #
  1804. ###
  1805. */
  1806. #if ( ipconfigUSE_TCP_WIN == 0 )
  1807. /**
  1808. * @brief Data was received at 'ulSequenceNumber'. See if it was expected
  1809. * and if there is enough space to store the new data.
  1810. *
  1811. * @param[in] pxWindow: The window to be checked.
  1812. * @param[in] ulSequenceNumber: Sequence number of the data received.
  1813. * @param[in] ulLength: Length of the data received.
  1814. * @param[in] ulSpace: Space in the buffer.
  1815. *
  1816. * @return A 0 is returned if there is enough space and the sequence number is correct,
  1817. * if not then a -1 is returned.
  1818. *
  1819. * @note if true may be passed directly to user (segment expected and window is empty).
  1820. * But pxWindow->ackno should always be used to set "BUF->ackno".
  1821. */
  1822. int32_t lTCPWindowRxCheck( TCPWindow_t * pxWindow,
  1823. uint32_t ulSequenceNumber,
  1824. uint32_t ulLength,
  1825. uint32_t ulSpace )
  1826. {
  1827. int32_t iReturn;
  1828. /* Data was received at 'ulSequenceNumber'. See if it was expected
  1829. * and if there is enough space to store the new data. */
  1830. if( ( pxWindow->rx.ulCurrentSequenceNumber != ulSequenceNumber ) || ( ulSpace < ulLength ) )
  1831. {
  1832. iReturn = -1;
  1833. }
  1834. else
  1835. {
  1836. pxWindow->rx.ulCurrentSequenceNumber += ( uint32_t ) ulLength;
  1837. iReturn = 0;
  1838. }
  1839. return iReturn;
  1840. }
  1841. #endif /* ipconfigUSE_TCP_WIN == 0 */
  1842. /*-----------------------------------------------------------*/
  1843. #if ( ipconfigUSE_TCP_WIN == 0 )
  1844. /**
  1845. * @brief Add data to the Tx Window.
  1846. *
  1847. * @param[in] pxWindow: The window to which the data is to be added.
  1848. * @param[in] ulLength: The length of the data to be added.
  1849. * @param[in] lPosition: Position in the stream.
  1850. * @param[in] lMax: Size of the Tx stream.
  1851. *
  1852. * @return The data actually added.
  1853. */
  1854. int32_t lTCPWindowTxAdd( TCPWindow_t * pxWindow,
  1855. uint32_t ulLength,
  1856. int32_t lPosition,
  1857. int32_t lMax )
  1858. {
  1859. TCPSegment_t * pxSegment = &( pxWindow->xTxSegment );
  1860. int32_t lResult;
  1861. /* Data is being scheduled for transmission. */
  1862. /* lMax would indicate the size of the txStream. */
  1863. ( void ) lMax;
  1864. /* This is tiny TCP: there is only 1 segment for outgoing data.
  1865. * As long as 'lDataLength' is unequal to zero, the segment is still occupied. */
  1866. if( pxSegment->lDataLength > 0 )
  1867. {
  1868. lResult = 0L;
  1869. }
  1870. else
  1871. {
  1872. if( ulLength > ( uint32_t ) pxSegment->lMaxLength )
  1873. {
  1874. if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
  1875. {
  1876. FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: can only store %ld / %ld bytes\n", ulLength, pxSegment->lMaxLength ) );
  1877. }
  1878. ulLength = ( uint32_t ) pxSegment->lMaxLength;
  1879. }
  1880. if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
  1881. {
  1882. FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: SeqNr %ld (%ld) Len %ld\n",
  1883. pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1884. pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  1885. ulLength ) );
  1886. }
  1887. /* The sequence number of the first byte in this packet. */
  1888. pxSegment->ulSequenceNumber = pxWindow->ulNextTxSequenceNumber;
  1889. pxSegment->lDataLength = ( int32_t ) ulLength;
  1890. pxSegment->lStreamPos = lPosition;
  1891. pxSegment->u.ulFlags = 0UL;
  1892. vTCPTimerSet( &( pxSegment->xTransmitTimer ) );
  1893. /* Increase the sequence number of the next data to be stored for
  1894. * transmission. */
  1895. pxWindow->ulNextTxSequenceNumber += ulLength;
  1896. lResult = ( int32_t ) ulLength;
  1897. }
  1898. return lResult;
  1899. }
  1900. #endif /* ipconfigUSE_TCP_WIN == 0 */
  1901. /*-----------------------------------------------------------*/
  1902. #if ( ipconfigUSE_TCP_WIN == 0 )
  1903. /**
  1904. * @brief Fetches data to be sent.
  1905. *
  1906. * @param[in] pxWindow: The window for the connection.
  1907. * @param[in] ulWindowSize: The size of the window.
  1908. * @param[out] plPosition: plPosition will point to a location with the circular data buffer: txStream.
  1909. *
  1910. * @return return the amount of data which may be sent along with the position in the txStream.
  1911. */
  1912. uint32_t ulTCPWindowTxGet( TCPWindow_t * pxWindow,
  1913. uint32_t ulWindowSize,
  1914. int32_t * plPosition )
  1915. {
  1916. TCPSegment_t * pxSegment = &( pxWindow->xTxSegment );
  1917. uint32_t ulLength = ( uint32_t ) pxSegment->lDataLength;
  1918. uint32_t ulMaxTime;
  1919. if( ulLength != 0UL )
  1920. {
  1921. /* _HT_ Still under investigation */
  1922. ( void ) ulWindowSize;
  1923. if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
  1924. {
  1925. /* As 'ucTransmitCount' has a minimum of 1, take 2 * RTT */
  1926. ulMaxTime = ( ( uint32_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
  1927. if( ulTimerGetAge( &( pxSegment->xTransmitTimer ) ) < ulMaxTime )
  1928. {
  1929. ulLength = 0UL;
  1930. }
  1931. }
  1932. if( ulLength != 0UL )
  1933. {
  1934. pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;
  1935. pxSegment->u.bits.ucTransmitCount++;
  1936. vTCPTimerSet( &pxSegment->xTransmitTimer );
  1937. pxWindow->ulOurSequenceNumber = pxSegment->ulSequenceNumber;
  1938. *plPosition = pxSegment->lStreamPos;
  1939. }
  1940. }
  1941. return ulLength;
  1942. }
  1943. #endif /* ipconfigUSE_TCP_WIN == 0 */
  1944. /*-----------------------------------------------------------*/
  1945. #if ( ipconfigUSE_TCP_WIN == 0 )
  1946. /**
  1947. * @brief Has the transmission completed.
  1948. *
  1949. * @param[in] pxWindow: The window whose transmission window is to be checked.
  1950. *
  1951. * @return If there is no outstanding data then pdTRUE is returned,
  1952. * else pdFALSE.
  1953. */
  1954. BaseType_t xTCPWindowTxDone( const TCPWindow_t * pxWindow )
  1955. {
  1956. BaseType_t xReturn;
  1957. /* Has the outstanding data been sent because user wants to shutdown? */
  1958. if( pxWindow->xTxSegment.lDataLength == 0 )
  1959. {
  1960. xReturn = pdTRUE;
  1961. }
  1962. else
  1963. {
  1964. xReturn = pdFALSE;
  1965. }
  1966. return xReturn;
  1967. }
  1968. #endif /* ipconfigUSE_TCP_WIN == 0 */
  1969. /*-----------------------------------------------------------*/
  1970. #if ( ipconfigUSE_TCP_WIN == 0 )
  1971. static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow,
  1972. uint32_t ulWindowSize );
  1973. /**
  1974. * @brief Check if the window has space for one message.
  1975. *
  1976. * @param[in] pxWindow: The window to be checked.
  1977. * @param[in] ulWindowSize: Size of the window.
  1978. *
  1979. * @return pdTRUE if the window has space, pdFALSE otherwise.
  1980. */
  1981. static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow,
  1982. uint32_t ulWindowSize )
  1983. {
  1984. BaseType_t xReturn;
  1985. if( ulWindowSize >= pxWindow->usMSSInit )
  1986. {
  1987. xReturn = pdTRUE;
  1988. }
  1989. else
  1990. {
  1991. xReturn = pdFALSE;
  1992. }
  1993. return xReturn;
  1994. }
  1995. #endif /* ipconfigUSE_TCP_WIN == 0 */
  1996. /*-----------------------------------------------------------*/
  1997. #if ( ipconfigUSE_TCP_WIN == 0 )
  1998. /**
  1999. * @brief Check data to be sent and calculate the time period the process may sleep.
  2000. *
  2001. * @param[in] pxWindow: The window to be checked.
  2002. * @param[in] ulWindowSize: Size of the window.
  2003. * @param[out] pulDelay: The time period (in ticks) that the process may sleep.
  2004. *
  2005. * @return pdTRUE if the process should sleep or pdFALSE.
  2006. */
  2007. BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow,
  2008. uint32_t ulWindowSize,
  2009. TickType_t * pulDelay )
  2010. {
  2011. TCPSegment_t const * pxSegment = &( pxWindow->xTxSegment );
  2012. BaseType_t xReturn;
  2013. TickType_t ulAge, ulMaxAge;
  2014. /* Check data to be sent. */
  2015. *pulDelay = ( TickType_t ) 0;
  2016. if( pxSegment->lDataLength == 0 )
  2017. {
  2018. /* Got nothing to send right now. */
  2019. xReturn = pdFALSE;
  2020. }
  2021. else
  2022. {
  2023. if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
  2024. {
  2025. ulAge = ulTimerGetAge( &pxSegment->xTransmitTimer );
  2026. ulMaxAge = ( ( TickType_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
  2027. if( ulMaxAge > ulAge )
  2028. {
  2029. *pulDelay = ulMaxAge - ulAge;
  2030. }
  2031. xReturn = pdTRUE;
  2032. }
  2033. else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )
  2034. {
  2035. /* Too many outstanding messages. */
  2036. xReturn = pdFALSE;
  2037. }
  2038. else
  2039. {
  2040. xReturn = pdTRUE;
  2041. }
  2042. }
  2043. return xReturn;
  2044. }
  2045. #endif /* ipconfigUSE_TCP_WIN == 0 */
  2046. /*-----------------------------------------------------------*/
  2047. #if ( ipconfigUSE_TCP_WIN == 0 )
  2048. /**
  2049. * @brief Receive a normal ACK.
  2050. *
  2051. * @param[in] pxWindow: The window for this particular connection.
  2052. * @param[in] ulSequenceNumber: The sequence number of the packet.
  2053. *
  2054. * @return Number of bytes to send.
  2055. */
  2056. uint32_t ulTCPWindowTxAck( TCPWindow_t * pxWindow,
  2057. uint32_t ulSequenceNumber )
  2058. {
  2059. TCPSegment_t * pxSegment = &( pxWindow->xTxSegment );
  2060. uint32_t ulDataLength = ( uint32_t ) pxSegment->lDataLength;
  2061. /* Receive a normal ACK */
  2062. if( ulDataLength != 0UL )
  2063. {
  2064. if( ulSequenceNumber < ( pxWindow->tx.ulCurrentSequenceNumber + ulDataLength ) )
  2065. {
  2066. if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE )
  2067. {
  2068. FreeRTOS_debug_printf( ( "win_tx_ack: acked %ld expc %ld len %ld\n",
  2069. ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  2070. pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  2071. ulDataLength ) );
  2072. }
  2073. /* Nothing to send right now. */
  2074. ulDataLength = 0UL;
  2075. }
  2076. else
  2077. {
  2078. pxWindow->tx.ulCurrentSequenceNumber += ulDataLength;
  2079. if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )
  2080. {
  2081. FreeRTOS_debug_printf( ( "win_tx_ack: acked seqnr %ld len %ld\n",
  2082. ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
  2083. ulDataLength ) );
  2084. }
  2085. pxSegment->lDataLength = 0;
  2086. }
  2087. }
  2088. return ulDataLength;
  2089. }
  2090. #endif /* ipconfigUSE_TCP_WIN == 0 */
  2091. /*-----------------------------------------------------------*/
  2092. #if ( ipconfigUSE_TCP_WIN == 0 )
  2093. /**
  2094. * @brief This function will be called as soon as a FIN is received to check
  2095. * whether all transmit queues are empty or not.
  2096. *
  2097. * @param[in] pxWindow: The window to be checked.
  2098. *
  2099. * @return It will return true if there are no 'open' reception segments.
  2100. */
  2101. BaseType_t xTCPWindowRxEmpty( const TCPWindow_t * pxWindow )
  2102. {
  2103. /* Return true if 'ulCurrentSequenceNumber >= ulHighestSequenceNumber'
  2104. * 'ulCurrentSequenceNumber' is the highest sequence number stored,
  2105. * 'ulHighestSequenceNumber' is the highest sequence number seen. */
  2106. return xSequenceGreaterThanOrEqual( pxWindow->rx.ulCurrentSequenceNumber, pxWindow->rx.ulHighestSequenceNumber );
  2107. }
  2108. #endif /* ipconfigUSE_TCP_WIN == 0 */
  2109. /*-----------------------------------------------------------*/
  2110. #if ( ipconfigUSE_TCP_WIN == 0 )
  2111. /**
  2112. * @brief Destroy a window.
  2113. *
  2114. * @param[in] pxWindow: Pointer to the window to be destroyed.
  2115. *
  2116. * @return Always returns a NULL.
  2117. */
  2118. void vTCPWindowDestroy( const TCPWindow_t * pxWindow )
  2119. {
  2120. /* As in tiny TCP there are no shared segments descriptors, there is
  2121. * nothing to release. */
  2122. ( void ) pxWindow;
  2123. }
  2124. #endif /* ipconfigUSE_TCP_WIN == 0 */
  2125. /*-----------------------------------------------------------*/
  2126. #endif /* ipconfigUSE_TCP == 1 */