FreeRTOS_Sockets.c 181 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870
  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_Sockets.c
  27. * @brief Implements the Sockets API based on Berkeley sockets for the FreeRTOS+TCP network stack.
  28. * Sockets are used by the application processes to interact with the IP-task which in turn
  29. * interacts with the hardware.
  30. */
  31. /* Standard includes. */
  32. #include <stdint.h>
  33. #include <stdio.h>
  34. /* FreeRTOS includes. */
  35. #include "FreeRTOS.h"
  36. #include "task.h"
  37. #include "queue.h"
  38. #include "semphr.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. #include "FreeRTOS_DNS.h"
  45. #include "NetworkBufferManagement.h"
  46. /* The ItemValue of the sockets xBoundSocketListItem member holds the socket's
  47. * port number. */
  48. /** @brief Set the port number for the socket in the xBoundSocketListItem. */
  49. #define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )
  50. /** @brief Get the port number for the socket in the xBoundSocketListItem. */
  51. #define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )
  52. /** @brief Test if a socket it bound which means it is either included in
  53. * xBoundUDPSocketsList or xBoundTCPSocketsList
  54. */
  55. #define socketSOCKET_IS_BOUND( pxSocket ) ( listLIST_ITEM_CONTAINER( &( pxSocket )->xBoundSocketListItem ) != NULL )
  56. /** @brief If FreeRTOS_sendto() is called on a socket that is not bound to a port
  57. * number then, depending on the FreeRTOSIPConfig.h settings, it might be
  58. * that a port number is automatically generated for the socket.
  59. * Automatically generated port numbers will be between
  60. * socketAUTO_PORT_ALLOCATION_START_NUMBER and 0xffff.
  61. *
  62. * @note Per https://tools.ietf.org/html/rfc6056, "the dynamic ports consist of
  63. * the range 49152-65535. However, ephemeral port selection algorithms should
  64. * use the whole range 1024-65535" excluding those already in use (inbound
  65. * or outbound).
  66. */
  67. #if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )
  68. #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0x0400 )
  69. #endif
  70. /** @brief Maximum value of port number which can be auto assigned. */
  71. #define socketAUTO_PORT_ALLOCATION_MAX_NUMBER ( ( uint16_t ) 0xffff )
  72. /** @brief The number of octets that make up an IP address. */
  73. #define socketMAX_IP_ADDRESS_OCTETS 4U
  74. /** @brief A block time of 0 simply means "don't block". */
  75. #define socketDONT_BLOCK ( ( TickType_t ) 0 )
  76. /** @brief TCP timer period in milliseconds. */
  77. #if ( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
  78. #define ipTCP_TIMER_PERIOD_MS ( 1000U )
  79. #endif
  80. /* Some helper macro's for defining the 20/80 % limits of uxLittleSpace / uxEnoughSpace. */
  81. #define sock20_PERCENT 20U /**< 20% of the defined limit. */
  82. #define sock80_PERCENT 80U /**< 80% of the defined limit. */
  83. #define sock100_PERCENT 100U /**< 100% of the defined limit. */
  84. #if ( ipconfigUSE_CALLBACKS != 0 )
  85. static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( F_TCP_UDP_Handler_t )
  86. {
  87. return ( F_TCP_UDP_Handler_t * ) pvArgument;
  88. }
  89. static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( F_TCP_UDP_Handler_t )
  90. {
  91. return ( const F_TCP_UDP_Handler_t * ) pvArgument;
  92. }
  93. #endif
  94. /**
  95. * @brief Utility function to cast pointer of a type to pointer of type NetworkBufferDescriptor_t.
  96. *
  97. * @return The casted pointer.
  98. */
  99. static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( NetworkBufferDescriptor_t )
  100. {
  101. return ( NetworkBufferDescriptor_t * ) pvArgument;
  102. }
  103. /**
  104. * @brief Utility function to cast pointer of a type to pointer of type StreamBuffer_t.
  105. *
  106. * @return The casted pointer.
  107. */
  108. static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( StreamBuffer_t )
  109. {
  110. return ( StreamBuffer_t * ) pvArgument;
  111. }
  112. /*-----------------------------------------------------------*/
  113. /*
  114. * Allocate the next port number from the private allocation range.
  115. * TCP and UDP each have their own series of port numbers
  116. * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP
  117. */
  118. static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );
  119. /*
  120. * Return the list item from within pxList that has an item value of
  121. * xWantedItemValue. If there is no such list item return NULL.
  122. */
  123. static const ListItem_t * pxListFindListItemWithValue( const List_t * pxList,
  124. TickType_t xWantedItemValue );
  125. /*
  126. * Return pdTRUE only if pxSocket is valid and bound, as far as can be
  127. * determined.
  128. */
  129. static BaseType_t prvValidSocket( const FreeRTOS_Socket_t * pxSocket,
  130. BaseType_t xProtocol,
  131. BaseType_t xIsBound );
  132. #if ( ipconfigUSE_TCP == 1 )
  133. /*
  134. * Internal function prvSockopt_so_buffer(): sets FREERTOS_SO_SNDBUF or
  135. * FREERTOS_SO_RCVBUF properties of a socket.
  136. */
  137. static BaseType_t prvSockopt_so_buffer( FreeRTOS_Socket_t * pxSocket,
  138. int32_t lOptionName,
  139. const void * pvOptionValue );
  140. #endif /* ipconfigUSE_TCP == 1 */
  141. /*
  142. * Before creating a socket, check the validity of the parameters used
  143. * and find the size of the socket space, which is different for UDP and TCP
  144. */
  145. static BaseType_t prvDetermineSocketSize( BaseType_t xDomain,
  146. BaseType_t xType,
  147. BaseType_t xProtocol,
  148. size_t * pxSocketSize );
  149. #if ( ipconfigUSE_TCP == 1 )
  150. /*
  151. * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'
  152. */
  153. static StreamBuffer_t * prvTCPCreateStream( FreeRTOS_Socket_t * pxSocket,
  154. BaseType_t xIsInputStream );
  155. #endif /* ipconfigUSE_TCP == 1 */
  156. #if ( ipconfigUSE_TCP == 1 )
  157. /*
  158. * Called from FreeRTOS_send(): some checks which will be done before
  159. * sending a TCP packed.
  160. */
  161. static int32_t prvTCPSendCheck( FreeRTOS_Socket_t * pxSocket,
  162. size_t uxDataLength );
  163. #endif /* ipconfigUSE_TCP */
  164. #if ( ipconfigUSE_TCP == 1 )
  165. /*
  166. * When a child socket gets closed, make sure to update the child-count of the parent
  167. */
  168. static void prvTCPSetSocketCount( FreeRTOS_Socket_t const * pxSocketToDelete );
  169. #endif /* ipconfigUSE_TCP == 1 */
  170. #if ( ipconfigUSE_TCP == 1 )
  171. /*
  172. * Called from FreeRTOS_connect(): make some checks and if allowed, send a
  173. * message to the IP-task to start connecting to a remote socket
  174. */
  175. static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t * pxSocket,
  176. struct freertos_sockaddr const * pxAddress );
  177. #endif /* ipconfigUSE_TCP */
  178. #if ( ipconfigUSE_TCP == 1 )
  179. /*
  180. * Check if it makes any sense to wait for a connect event.
  181. * It may return: -EINPROGRESS, -EAGAIN, or 0 for OK.
  182. */
  183. static BaseType_t bMayConnect( FreeRTOS_Socket_t const * pxSocket );
  184. #endif /* ipconfigUSE_TCP */
  185. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  186. /* Executed by the IP-task, it will check all sockets belonging to a set */
  187. static void prvFindSelectedSocket( SocketSelect_t * pxSocketSet );
  188. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  189. /*-----------------------------------------------------------*/
  190. /** @brief The list that contains mappings between sockets and port numbers.
  191. * Accesses to this list must be protected by critical sections of
  192. * some kind.
  193. */
  194. List_t xBoundUDPSocketsList;
  195. #if ipconfigUSE_TCP == 1
  196. /** @brief The list that contains mappings between sockets and port numbers.
  197. * Accesses to this list must be protected by critical sections of
  198. * some kind.
  199. */
  200. List_t xBoundTCPSocketsList;
  201. #endif /* ipconfigUSE_TCP == 1 */
  202. /*-----------------------------------------------------------*/
  203. /**
  204. * @brief Check whether the socket is valid or not.
  205. *
  206. * @param[in] pxSocket: The socket being checked.
  207. * @param[in] xProtocol: The protocol for which the socket was created.
  208. * @param[in] xIsBound: pdTRUE when the socket should be bound, otherwise pdFALSE.
  209. *
  210. * @return If the socket is valid, then pdPASS is returned or else, pdFAIL
  211. * is returned.
  212. */
  213. static BaseType_t prvValidSocket( const FreeRTOS_Socket_t * pxSocket,
  214. BaseType_t xProtocol,
  215. BaseType_t xIsBound )
  216. {
  217. BaseType_t xReturn;
  218. if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
  219. {
  220. xReturn = pdFALSE;
  221. }
  222. else if( ( xIsBound != pdFALSE ) && !socketSOCKET_IS_BOUND( pxSocket ) )
  223. {
  224. /* The caller expects the socket to be bound, but it isn't. */
  225. xReturn = pdFALSE;
  226. }
  227. else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )
  228. {
  229. /* Socket has a wrong type (UDP != TCP). */
  230. xReturn = pdFALSE;
  231. }
  232. else
  233. {
  234. xReturn = pdTRUE;
  235. }
  236. return xReturn;
  237. }
  238. /*-----------------------------------------------------------*/
  239. /**
  240. * @brief Initialise the bound TCP/UDP socket lists.
  241. */
  242. void vNetworkSocketsInit( void )
  243. {
  244. vListInitialise( &xBoundUDPSocketsList );
  245. #if ( ipconfigUSE_TCP == 1 )
  246. {
  247. vListInitialise( &xBoundTCPSocketsList );
  248. }
  249. #endif /* ipconfigUSE_TCP == 1 */
  250. }
  251. /*-----------------------------------------------------------*/
  252. /**
  253. * @brief Determine the socket size for the given protocol.
  254. *
  255. * @param[in] xDomain: The domain for which the size of socket is being determined.
  256. * @param[in] xType: Is this a datagram socket or a stream socket.
  257. * @param[in] xProtocol: The protocol being used.
  258. * @param[out] pxSocketSize: Pointer to a variable in which the size shall be returned
  259. * if all checks pass.
  260. *
  261. * @return pdPASS if socket size was determined and put in the parameter pxSocketSize
  262. * correctly, else pdFAIL.
  263. */
  264. static BaseType_t prvDetermineSocketSize( BaseType_t xDomain,
  265. BaseType_t xType,
  266. BaseType_t xProtocol,
  267. size_t * pxSocketSize )
  268. {
  269. BaseType_t xReturn = pdPASS;
  270. FreeRTOS_Socket_t const * pxSocket = NULL;
  271. /* Asserts must not appear before it has been determined that the network
  272. * task is ready - otherwise the asserts will fail. */
  273. if( xIPIsNetworkTaskReady() == pdFALSE )
  274. {
  275. xReturn = pdFAIL;
  276. }
  277. else
  278. {
  279. /* Only Ethernet is currently supported. */
  280. configASSERT( xDomain == FREERTOS_AF_INET );
  281. /* Check if the UDP socket-list has been initialised. */
  282. configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );
  283. #if ( ipconfigUSE_TCP == 1 )
  284. {
  285. /* Check if the TCP socket-list has been initialised. */
  286. configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );
  287. }
  288. #endif /* ipconfigUSE_TCP == 1 */
  289. if( xProtocol == FREERTOS_IPPROTO_UDP )
  290. {
  291. if( xType != FREERTOS_SOCK_DGRAM )
  292. {
  293. xReturn = pdFAIL;
  294. configASSERT( xReturn == pdPASS );
  295. }
  296. /* In case a UDP socket is created, do not allocate space for TCP data. */
  297. *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );
  298. }
  299. #if ( ipconfigUSE_TCP == 1 )
  300. else if( xProtocol == FREERTOS_IPPROTO_TCP )
  301. {
  302. if( xType != FREERTOS_SOCK_STREAM )
  303. {
  304. xReturn = pdFAIL;
  305. configASSERT( xReturn == pdPASS );
  306. }
  307. *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );
  308. }
  309. #endif /* ipconfigUSE_TCP == 1 */
  310. else
  311. {
  312. xReturn = pdFAIL;
  313. configASSERT( xReturn == pdPASS );
  314. }
  315. }
  316. /* In case configASSERT() is not used */
  317. ( void ) xDomain;
  318. ( void ) pxSocket; /* Was only used for sizeof. */
  319. return xReturn;
  320. }
  321. /*-----------------------------------------------------------*/
  322. /**
  323. * @brief allocate and initialise a socket.
  324. *
  325. * @param[in] xDomain: The domain in which the socket should be created.
  326. * @param[in] xType: The type of the socket.
  327. * @param[in] xProtocol: The protocol of the socket.
  328. *
  329. * @return FREERTOS_INVALID_SOCKET if the allocation failed, or if there was
  330. * a parameter error, otherwise a valid socket.
  331. */
  332. Socket_t FreeRTOS_socket( BaseType_t xDomain,
  333. BaseType_t xType,
  334. BaseType_t xProtocol )
  335. {
  336. FreeRTOS_Socket_t * pxSocket;
  337. /* Note that this value will be over-written by the call to prvDetermineSocketSize. */
  338. size_t uxSocketSize = 1;
  339. EventGroupHandle_t xEventGroup;
  340. Socket_t xReturn;
  341. if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )
  342. {
  343. xReturn = FREERTOS_INVALID_SOCKET;
  344. }
  345. else
  346. {
  347. /* Allocate the structure that will hold the socket information. The
  348. * size depends on the type of socket: UDP sockets need less space. A
  349. * define 'pvPortMallocSocket' will used to allocate the necessary space.
  350. * By default it points to the FreeRTOS function 'pvPortMalloc()'. */
  351. pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, pvPortMallocSocket( uxSocketSize ) );
  352. if( pxSocket == NULL )
  353. {
  354. xReturn = FREERTOS_INVALID_SOCKET;
  355. iptraceFAILED_TO_CREATE_SOCKET();
  356. }
  357. else
  358. {
  359. xEventGroup = xEventGroupCreate();
  360. if( xEventGroup == NULL )
  361. {
  362. vPortFreeSocket( pxSocket );
  363. xReturn = FREERTOS_INVALID_SOCKET;
  364. iptraceFAILED_TO_CREATE_EVENT_GROUP();
  365. }
  366. else
  367. {
  368. if( xProtocol == FREERTOS_IPPROTO_UDP )
  369. {
  370. iptraceMEM_STATS_CREATE( tcpSOCKET_UDP, pxSocket, uxSocketSize + sizeof( StaticEventGroup_t ) );
  371. }
  372. else
  373. {
  374. /* Lint wants at least a comment, in case the macro is empty. */
  375. iptraceMEM_STATS_CREATE( tcpSOCKET_TCP, pxSocket, uxSocketSize + sizeof( StaticEventGroup_t ) );
  376. }
  377. /* Clear the entire space to avoid nulling individual entries. */
  378. ( void ) memset( pxSocket, 0, uxSocketSize );
  379. pxSocket->xEventGroup = xEventGroup;
  380. /* Initialise the socket's members. The semaphore will be created
  381. * if the socket is bound to an address, for now the pointer to the
  382. * semaphore is just set to NULL to show it has not been created. */
  383. if( xProtocol == FREERTOS_IPPROTO_UDP )
  384. {
  385. vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
  386. #if ( ipconfigUDP_MAX_RX_PACKETS > 0U )
  387. {
  388. pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;
  389. }
  390. #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */
  391. }
  392. vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );
  393. listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ipPOINTER_CAST( void *, pxSocket ) );
  394. pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;
  395. pxSocket->xSendBlockTime = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;
  396. pxSocket->ucSocketOptions = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
  397. pxSocket->ucProtocol = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */
  398. #if ( ipconfigUSE_TCP == 1 )
  399. {
  400. if( xProtocol == FREERTOS_IPPROTO_TCP )
  401. {
  402. /* StreamSize is expressed in number of bytes */
  403. /* Round up buffer sizes to nearest multiple of MSS */
  404. pxSocket->u.xTCP.usCurMSS = ( uint16_t ) ipconfigTCP_MSS;
  405. pxSocket->u.xTCP.usInitMSS = ( uint16_t ) ipconfigTCP_MSS;
  406. pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;
  407. pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
  408. /* Use half of the buffer size of the TCP windows */
  409. #if ( ipconfigUSE_TCP_WIN == 1 )
  410. {
  411. pxSocket->u.xTCP.uxRxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2U ) / ipconfigTCP_MSS );
  412. pxSocket->u.xTCP.uxTxWinSize = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2U ) / ipconfigTCP_MSS );
  413. }
  414. #else
  415. {
  416. pxSocket->u.xTCP.uxRxWinSize = 1U;
  417. pxSocket->u.xTCP.uxTxWinSize = 1U;
  418. }
  419. #endif
  420. /* The above values are just defaults, and can be overridden by
  421. * calling FreeRTOS_setsockopt(). No buffers will be allocated until a
  422. * socket is connected and data is exchanged. */
  423. }
  424. }
  425. #endif /* ipconfigUSE_TCP == 1 */
  426. xReturn = pxSocket;
  427. }
  428. }
  429. }
  430. /* Remove compiler warnings in the case the configASSERT() is not defined. */
  431. ( void ) xDomain;
  432. return xReturn;
  433. }
  434. /*-----------------------------------------------------------*/
  435. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  436. /**
  437. * @brief Create a socket set.
  438. *
  439. * @return The new socket set which was created, or NULL when allocation has failed.
  440. */
  441. SocketSet_t FreeRTOS_CreateSocketSet( void )
  442. {
  443. SocketSelect_t * pxSocketSet;
  444. pxSocketSet = ipCAST_PTR_TO_TYPE_PTR( SocketSelect_t, pvPortMalloc( sizeof( *pxSocketSet ) ) );
  445. if( pxSocketSet != NULL )
  446. {
  447. ( void ) memset( pxSocketSet, 0, sizeof( *pxSocketSet ) );
  448. pxSocketSet->xSelectGroup = xEventGroupCreate();
  449. if( pxSocketSet->xSelectGroup == NULL )
  450. {
  451. vPortFree( pxSocketSet );
  452. pxSocketSet = NULL;
  453. }
  454. else
  455. {
  456. /* Lint wants at least a comment, in case the macro is empty. */
  457. iptraceMEM_STATS_CREATE( tcpSOCKET_SET, pxSocketSet, sizeof( *pxSocketSet ) + sizeof( StaticEventGroup_t ) );
  458. }
  459. }
  460. return ( SocketSet_t ) pxSocketSet;
  461. }
  462. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  463. /*-----------------------------------------------------------*/
  464. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  465. /**
  466. * @brief Delete a given socket set.
  467. *
  468. * @param[in] xSocketSet: The socket set being deleted.
  469. */
  470. void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )
  471. {
  472. SocketSelect_t * pxSocketSet = ( SocketSelect_t * ) xSocketSet;
  473. iptraceMEM_STATS_DELETE( pxSocketSet );
  474. vEventGroupDelete( pxSocketSet->xSelectGroup );
  475. vPortFree( pxSocketSet );
  476. }
  477. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  478. /*-----------------------------------------------------------*/
  479. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  480. /**
  481. * @brief Add a socket to a set.
  482. *
  483. * @param[in] xSocket: The socket being added.
  484. * @param[in] xSocketSet: The socket set being added to.
  485. * @param[in] xBitsToSet: The event bits to set, a combination of the values defined
  486. * in 'eSelectEvent_t', for read, write, exception, etc.
  487. */
  488. void FreeRTOS_FD_SET( Socket_t xSocket,
  489. SocketSet_t xSocketSet,
  490. EventBits_t xBitsToSet )
  491. {
  492. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  493. SocketSelect_t * pxSocketSet = ( SocketSelect_t * ) xSocketSet;
  494. configASSERT( pxSocket != NULL );
  495. configASSERT( xSocketSet != NULL );
  496. /* Make sure we're not adding bits which are reserved for internal use,
  497. * such as eSELECT_CALL_IP */
  498. pxSocket->xSelectBits |= xBitsToSet & ( ( EventBits_t ) eSELECT_ALL );
  499. if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_ALL ) ) != ( EventBits_t ) 0U )
  500. {
  501. /* Adding a socket to a socket set. */
  502. pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
  503. /* Now have the IP-task call vSocketSelect() to see if the set contains
  504. * any sockets which are 'ready' and set the proper bits. */
  505. prvFindSelectedSocket( pxSocketSet );
  506. }
  507. }
  508. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  509. /*-----------------------------------------------------------*/
  510. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  511. /**
  512. * @brief Clear select bits for a socket. If the mask becomes 0,
  513. * remove the socket from the set.
  514. *
  515. * @param[in] xSocket: The socket whose select bits are being cleared.
  516. * @param[in] xSocketSet: The socket set of the socket.
  517. * @param[in] xBitsToClear: The bits to be cleared. Every '1' means that the
  518. * corresponding bit will be cleared. See 'eSelectEvent_t' for
  519. * the possible values.
  520. */
  521. void FreeRTOS_FD_CLR( Socket_t xSocket,
  522. SocketSet_t xSocketSet,
  523. EventBits_t xBitsToClear )
  524. {
  525. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  526. configASSERT( pxSocket != NULL );
  527. configASSERT( xSocketSet != NULL );
  528. pxSocket->xSelectBits &= ~( xBitsToClear & ( ( EventBits_t ) eSELECT_ALL ) );
  529. if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_ALL ) ) != ( EventBits_t ) 0U )
  530. {
  531. pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;
  532. }
  533. else
  534. {
  535. /* disconnect it from the socket set */
  536. pxSocket->pxSocketSet = NULL;
  537. }
  538. }
  539. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  540. /*-----------------------------------------------------------*/
  541. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  542. /**
  543. * @brief Test if a socket belongs to a socket-set and if so, which event bit(s)
  544. * are set.
  545. *
  546. * @param[in] xSocket: The socket of interest.
  547. * @param[in] xSocketSet: The socket set to which the socket belongs.
  548. *
  549. * @return If the socket belongs to the socket set: the event bits, otherwise zero.
  550. */
  551. EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket,
  552. SocketSet_t xSocketSet )
  553. {
  554. EventBits_t xReturn;
  555. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  556. configASSERT( pxSocket != NULL );
  557. configASSERT( xSocketSet != NULL );
  558. if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )
  559. {
  560. /* Make sure we're not adding bits which are reserved for internal
  561. * use. */
  562. xReturn = pxSocket->xSocketBits & ( ( EventBits_t ) eSELECT_ALL );
  563. }
  564. else
  565. {
  566. xReturn = 0;
  567. }
  568. return xReturn;
  569. }
  570. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  571. /*-----------------------------------------------------------*/
  572. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  573. /**
  574. * @brief The select() statement: wait for an event to occur on any of the sockets
  575. * included in a socket set.
  576. *
  577. * @param[in] xSocketSet: The socket set including the sockets on which we are
  578. * waiting for an event to occur.
  579. * @param[in] xBlockTimeTicks: Maximum time ticks to wait for an event to occur.
  580. * If the value is 'portMAX_DELAY' then the function will wait
  581. * indefinitely for an event to occur.
  582. *
  583. * @return The socket which might have triggered the event bit.
  584. */
  585. BaseType_t FreeRTOS_select( SocketSet_t xSocketSet,
  586. TickType_t xBlockTimeTicks )
  587. {
  588. TimeOut_t xTimeOut;
  589. TickType_t xRemainingTime;
  590. SocketSelect_t * pxSocketSet = ( SocketSelect_t * ) xSocketSet;
  591. EventBits_t uxResult;
  592. configASSERT( xSocketSet != NULL );
  593. /* Only in the first round, check for non-blocking */
  594. xRemainingTime = xBlockTimeTicks;
  595. /* Fetch the current time */
  596. vTaskSetTimeOutState( &xTimeOut );
  597. for( ; ; )
  598. {
  599. /* Find a socket which might have triggered the bit
  600. * This function might return immediately or block for a limited time */
  601. uxResult = xEventGroupWaitBits( pxSocketSet->xSelectGroup, ( ( EventBits_t ) eSELECT_ALL ), pdFALSE, pdFALSE, xRemainingTime );
  602. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  603. {
  604. if( ( uxResult & ( ( EventBits_t ) eSELECT_INTR ) ) != 0U )
  605. {
  606. ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_INTR );
  607. FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );
  608. break;
  609. }
  610. }
  611. #endif /* ipconfigSUPPORT_SIGNALS */
  612. /* Have the IP-task find the socket which had an event */
  613. prvFindSelectedSocket( pxSocketSet );
  614. uxResult = xEventGroupGetBits( pxSocketSet->xSelectGroup );
  615. if( uxResult != 0U )
  616. {
  617. break;
  618. }
  619. /* Has the timeout been reached? */
  620. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  621. {
  622. break;
  623. }
  624. }
  625. return ( BaseType_t ) uxResult;
  626. }
  627. #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
  628. /*-----------------------------------------------------------*/
  629. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  630. /**
  631. * @brief Send a message to the IP-task to have it check all sockets belonging to
  632. * 'pxSocketSet'
  633. *
  634. * @param[in] pxSocketSet: The socket set being asked to check.
  635. */
  636. static void prvFindSelectedSocket( SocketSelect_t * pxSocketSet )
  637. {
  638. IPStackEvent_t xSelectEvent;
  639. #if ( ipconfigSELECT_USES_NOTIFY != 0 )
  640. SocketSelectMessage_t xSelectMessage;
  641. #endif
  642. xSelectEvent.eEventType = eSocketSelectEvent;
  643. #if ( ipconfigSELECT_USES_NOTIFY != 0 )
  644. {
  645. xSelectMessage.pxSocketSet = pxSocketSet;
  646. xSelectMessage.xTaskhandle = xTaskGetCurrentTaskHandle();
  647. xSelectEvent.pvData = &( xSelectMessage );
  648. }
  649. #else
  650. {
  651. xSelectEvent.pvData = pxSocketSet;
  652. /* while the IP-task works on the request, the API will block on
  653. * 'eSELECT_CALL_IP'. So clear it first. */
  654. ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, ( BaseType_t ) eSELECT_CALL_IP );
  655. }
  656. #endif /* if ( ipconfigSELECT_USES_NOTIFY != 0 ) */
  657. /* Now send the socket select event */
  658. if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
  659. {
  660. /* Oops, we failed to wake-up the IP task. No use to wait for it. */
  661. FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );
  662. }
  663. else
  664. {
  665. /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to
  666. * wakeup the calling API */
  667. #if ( ipconfigSELECT_USES_NOTIFY != 0 )
  668. {
  669. ( void ) ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
  670. }
  671. #else
  672. {
  673. ( void ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, ( BaseType_t ) eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );
  674. }
  675. #endif
  676. }
  677. }
  678. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  679. /*-----------------------------------------------------------*/
  680. /**
  681. * @brief Receive data from a bound socket. In this library, the function
  682. * can only be used with connection-less sockets (UDP). For TCP sockets,
  683. * please use FreeRTOS_recv().
  684. *
  685. * @param[in] xSocket: The socket to which the data is sent i.e. the
  686. * listening socket.
  687. * @param[out] pvBuffer: The buffer in which the data being received is to
  688. * be stored.
  689. * @param[in] uxBufferLength: The length of the buffer.
  690. * @param[in] xFlags: The flags to indicate preferences while calling this function.
  691. * @param[out] pxSourceAddress: The source address from which the data is being sent.
  692. * @param[out] pxSourceAddressLength: This parameter is used only to adhere to Berkeley
  693. * sockets standard. It is not used internally.
  694. *
  695. * @return The number of bytes received. Or else, an error code is returned. When it
  696. * returns a negative value, the cause can be looked-up in
  697. * 'FreeRTOS_errno_TCP.h'.
  698. */
  699. int32_t FreeRTOS_recvfrom( Socket_t xSocket,
  700. void * pvBuffer,
  701. size_t uxBufferLength,
  702. BaseType_t xFlags,
  703. struct freertos_sockaddr * pxSourceAddress,
  704. socklen_t * pxSourceAddressLength )
  705. {
  706. BaseType_t lPacketCount;
  707. NetworkBufferDescriptor_t * pxNetworkBuffer;
  708. const void * pvCopySource;
  709. FreeRTOS_Socket_t const * pxSocket = xSocket;
  710. TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */
  711. BaseType_t xTimed = pdFALSE;
  712. TimeOut_t xTimeOut;
  713. int32_t lReturn;
  714. EventBits_t xEventBits = ( EventBits_t ) 0;
  715. size_t uxPayloadLength;
  716. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )
  717. {
  718. lReturn = -pdFREERTOS_ERRNO_EINVAL;
  719. }
  720. else
  721. {
  722. lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
  723. /* The function prototype is designed to maintain the expected Berkeley
  724. * sockets standard, but this implementation does not use all the parameters. */
  725. ( void ) pxSourceAddressLength;
  726. while( lPacketCount == 0 )
  727. {
  728. if( xTimed == pdFALSE )
  729. {
  730. /* Check to see if the socket is non blocking on the first
  731. * iteration. */
  732. xRemainingTime = pxSocket->xReceiveBlockTime;
  733. if( xRemainingTime == ( TickType_t ) 0 )
  734. {
  735. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  736. {
  737. /* Just check for the interrupt flag. */
  738. xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR,
  739. pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
  740. }
  741. #endif /* ipconfigSUPPORT_SIGNALS */
  742. break;
  743. }
  744. if( ( ( ( UBaseType_t ) xFlags ) & ( ( UBaseType_t ) FREERTOS_MSG_DONTWAIT ) ) != 0U )
  745. {
  746. break;
  747. }
  748. /* To ensure this part only executes once. */
  749. xTimed = pdTRUE;
  750. /* Fetch the current time. */
  751. vTaskSetTimeOutState( &xTimeOut );
  752. }
  753. /* Wait for arrival of data. While waiting, the IP-task may set the
  754. * 'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this
  755. * socket, thus unblocking this API call. */
  756. xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( ( EventBits_t ) eSOCKET_RECEIVE ) | ( ( EventBits_t ) eSOCKET_INTR ),
  757. pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
  758. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  759. {
  760. if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
  761. {
  762. if( ( xEventBits & ( EventBits_t ) eSOCKET_RECEIVE ) != 0U )
  763. {
  764. /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */
  765. ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
  766. }
  767. break;
  768. }
  769. }
  770. #else /* if ( ipconfigSUPPORT_SIGNALS != 0 ) */
  771. {
  772. ( void ) xEventBits;
  773. }
  774. #endif /* ipconfigSUPPORT_SIGNALS */
  775. lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
  776. if( lPacketCount != 0 )
  777. {
  778. break;
  779. }
  780. /* Has the timeout been reached ? */
  781. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  782. {
  783. break;
  784. }
  785. } /* while( lPacketCount == 0 ) */
  786. if( lPacketCount != 0 )
  787. {
  788. taskENTER_CRITICAL();
  789. {
  790. /* The owner of the list item is the network buffer. */
  791. pxNetworkBuffer = ipCAST_PTR_TO_TYPE_PTR( NetworkBufferDescriptor_t, listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) );
  792. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_PEEK ) == 0U )
  793. {
  794. /* Remove the network buffer from the list of buffers waiting to
  795. * be processed by the socket. */
  796. ( void ) uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
  797. }
  798. }
  799. taskEXIT_CRITICAL();
  800. /* The returned value is the length of the payload data, which is
  801. * calculated at the total packet size minus the headers.
  802. * The validity of `xDataLength` prvProcessIPPacket has been confirmed
  803. * in 'prvProcessIPPacket()'. */
  804. uxPayloadLength = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
  805. lReturn = ( int32_t ) uxPayloadLength;
  806. if( pxSourceAddress != NULL )
  807. {
  808. pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
  809. pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
  810. }
  811. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
  812. {
  813. /* The zero copy flag is not set. Truncate the length if it won't
  814. * fit in the provided buffer. */
  815. if( lReturn > ( int32_t ) uxBufferLength )
  816. {
  817. iptraceRECVFROM_DISCARDING_BYTES( ( uxBufferLength - lReturn ) );
  818. lReturn = ( int32_t ) uxBufferLength;
  819. }
  820. /* Copy the received data into the provided buffer, then release the
  821. * network buffer. */
  822. pvCopySource = ( const void * ) &pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ];
  823. ( void ) memcpy( pvBuffer, pvCopySource, ( size_t ) lReturn );
  824. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_PEEK ) == 0U )
  825. {
  826. vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
  827. }
  828. }
  829. else
  830. {
  831. /* The zero copy flag was set. pvBuffer is not a buffer into which
  832. * the received data can be copied, but a pointer that must be set to
  833. * point to the buffer in which the received data has already been
  834. * placed. */
  835. *( ( void ** ) pvBuffer ) = ipPOINTER_CAST( void *, &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );
  836. }
  837. }
  838. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  839. else if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
  840. {
  841. lReturn = -pdFREERTOS_ERRNO_EINTR;
  842. iptraceRECVFROM_INTERRUPTED();
  843. }
  844. #endif /* ipconfigSUPPORT_SIGNALS */
  845. else
  846. {
  847. lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;
  848. iptraceRECVFROM_TIMEOUT();
  849. }
  850. }
  851. return lReturn;
  852. }
  853. /*-----------------------------------------------------------*/
  854. /**
  855. * @brief Send data to a socket. The socket must have already been created by a
  856. * successful call to FreeRTOS_socket(). It works for UDP-sockets only.
  857. *
  858. * @param[in] xSocket: The socket being sent to.
  859. * @param[in] pvBuffer: Pointer to the data being sent.
  860. * @param[in] uxTotalDataLength: Length (in bytes) of the data being sent.
  861. * @param[in] xFlags: Flags used to communicate preferences to the function.
  862. * Possibly FREERTOS_MSG_DONTWAIT and/or FREERTOS_ZERO_COPY.
  863. * @param[in] pxDestinationAddress: The address to which the data is to be sent.
  864. * @param[in] xDestinationAddressLength: This parameter is present to adhere to the
  865. * Berkeley sockets standard. Else, it is not used.
  866. *
  867. * @return When positive: the total number of bytes sent, when negative an error
  868. * has occurred: it can be looked-up in 'FreeRTOS_errno_TCP.h'.
  869. */
  870. int32_t FreeRTOS_sendto( Socket_t xSocket,
  871. const void * pvBuffer,
  872. size_t uxTotalDataLength,
  873. BaseType_t xFlags,
  874. const struct freertos_sockaddr * pxDestinationAddress,
  875. socklen_t xDestinationAddressLength )
  876. {
  877. NetworkBufferDescriptor_t * pxNetworkBuffer;
  878. void * pvCopyDest;
  879. IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
  880. TimeOut_t xTimeOut;
  881. TickType_t xTicksToWait;
  882. int32_t lReturn = 0;
  883. FreeRTOS_Socket_t const * pxSocket;
  884. const size_t uxMaxPayloadLength = ipMAX_UDP_PAYLOAD_LENGTH;
  885. const size_t uxPayloadOffset = ipUDP_PAYLOAD_OFFSET_IPv4;
  886. pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  887. /* The function prototype is designed to maintain the expected Berkeley
  888. * sockets standard, but this implementation does not use all the
  889. * parameters. */
  890. ( void ) xDestinationAddressLength;
  891. configASSERT( pvBuffer != NULL );
  892. if( uxTotalDataLength <= ( size_t ) uxMaxPayloadLength )
  893. {
  894. /* If the socket is not already bound to an address, bind it now.
  895. * Passing NULL as the address parameter tells FreeRTOS_bind() to select
  896. * the address to bind to. */
  897. if( socketSOCKET_IS_BOUND( pxSocket ) ||
  898. ( FreeRTOS_bind( xSocket, NULL, 0U ) == 0 ) )
  899. {
  900. xTicksToWait = pxSocket->xSendBlockTime;
  901. #if ( ipconfigUSE_CALLBACKS != 0 )
  902. {
  903. if( xIsCallingFromIPTask() != pdFALSE )
  904. {
  905. /* If this send function is called from within a call-back
  906. * handler it may not block, otherwise chances would be big to
  907. * get a deadlock: the IP-task waiting for itself. */
  908. xTicksToWait = ( TickType_t ) 0;
  909. }
  910. }
  911. #endif /* ipconfigUSE_CALLBACKS */
  912. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
  913. {
  914. xTicksToWait = ( TickType_t ) 0;
  915. }
  916. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
  917. {
  918. /* Zero copy is not set, so obtain a network buffer into
  919. * which the payload will be copied. */
  920. vTaskSetTimeOutState( &xTimeOut );
  921. /* Block until a buffer becomes available, or until a
  922. * timeout has been reached */
  923. pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxPayloadOffset + uxTotalDataLength, xTicksToWait );
  924. if( pxNetworkBuffer != NULL )
  925. {
  926. pvCopyDest = ( void * ) &pxNetworkBuffer->pucEthernetBuffer[ uxPayloadOffset ];
  927. ( void ) memcpy( pvCopyDest, pvBuffer, uxTotalDataLength );
  928. if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )
  929. {
  930. /* The entire block time has been used up. */
  931. xTicksToWait = ( TickType_t ) 0;
  932. }
  933. }
  934. }
  935. else
  936. {
  937. /* When zero copy is used, pvBuffer is a pointer to the
  938. * payload of a buffer that has already been obtained from the
  939. * stack. Obtain the network buffer pointer from the buffer. */
  940. pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer );
  941. }
  942. if( pxNetworkBuffer != NULL )
  943. {
  944. /* xDataLength is the size of the total packet, including the Ethernet header. */
  945. pxNetworkBuffer->xDataLength = uxTotalDataLength + sizeof( UDPPacket_t );
  946. pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;
  947. pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );
  948. pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;
  949. /* The socket options are passed to the IP layer in the
  950. * space that will eventually get used by the Ethernet header. */
  951. pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;
  952. /* Tell the networking task that the packet needs sending. */
  953. xStackTxEvent.pvData = pxNetworkBuffer;
  954. /* Ask the IP-task to send this packet */
  955. if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )
  956. {
  957. /* The packet was successfully sent to the IP task. */
  958. lReturn = ( int32_t ) uxTotalDataLength;
  959. #if ( ipconfigUSE_CALLBACKS == 1 )
  960. {
  961. if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )
  962. {
  963. pxSocket->u.xUDP.pxHandleSent( xSocket, uxTotalDataLength );
  964. }
  965. }
  966. #endif /* ipconfigUSE_CALLBACKS */
  967. }
  968. else
  969. {
  970. /* If the buffer was allocated in this function, release
  971. * it. */
  972. if( ( ( UBaseType_t ) xFlags & ( UBaseType_t ) FREERTOS_ZERO_COPY ) == 0U )
  973. {
  974. vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
  975. }
  976. iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
  977. }
  978. }
  979. else
  980. {
  981. /* If errno was available, errno would be set to
  982. * FREERTOS_ENOPKTS. As it is, the function must return the
  983. * number of transmitted bytes, so the calling function knows
  984. * how much data was actually sent. */
  985. iptraceNO_BUFFER_FOR_SENDTO();
  986. }
  987. }
  988. else
  989. {
  990. /* No comment. */
  991. iptraceSENDTO_SOCKET_NOT_BOUND();
  992. }
  993. }
  994. else
  995. {
  996. /* The data is longer than the available buffer space. */
  997. iptraceSENDTO_DATA_TOO_LONG();
  998. }
  999. return lReturn;
  1000. } /* Tested */
  1001. /*-----------------------------------------------------------*/
  1002. /**
  1003. * @brief binds a socket to a local port number. If port 0 is provided,
  1004. * a system provided port number will be assigned. This function
  1005. * can be used for both UDP and TCP sockets. The actual binding
  1006. * will be performed by the IP-task to avoid mutual access to the
  1007. * bound-socket-lists (xBoundUDPSocketsList or xBoundTCPSocketsList).
  1008. *
  1009. * @param[in] xSocket: The socket being bound.
  1010. * @param[in] pxAddress: The address struct carrying the port number to which
  1011. * this socket is to be bound.
  1012. * @param[in] xAddressLength: This parameter is not used internally. The
  1013. * function signature is used to adhere to standard
  1014. * Berkeley sockets API.
  1015. *
  1016. * @return The return value is 0 if the bind is successful.
  1017. * If some error occurred, then a negative value is returned.
  1018. */
  1019. BaseType_t FreeRTOS_bind( Socket_t xSocket,
  1020. struct freertos_sockaddr const * pxAddress,
  1021. socklen_t xAddressLength )
  1022. {
  1023. IPStackEvent_t xBindEvent;
  1024. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  1025. BaseType_t xReturn = 0;
  1026. ( void ) xAddressLength;
  1027. configASSERT( xIsCallingFromIPTask() == pdFALSE );
  1028. if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
  1029. {
  1030. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1031. }
  1032. /* Once a socket is bound to a port, it can not be bound to a different
  1033. * port number */
  1034. else if( socketSOCKET_IS_BOUND( pxSocket ) )
  1035. {
  1036. /* The socket is already bound. */
  1037. FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );
  1038. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1039. }
  1040. else
  1041. {
  1042. /* Prepare a messages to the IP-task in order to perform the binding.
  1043. * The desired port number will be passed in usLocalPort. */
  1044. xBindEvent.eEventType = eSocketBindEvent;
  1045. xBindEvent.pvData = xSocket;
  1046. if( pxAddress != NULL )
  1047. {
  1048. pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
  1049. }
  1050. else
  1051. {
  1052. /* Caller wants to bind to a random port number. */
  1053. pxSocket->usLocalPort = 0U;
  1054. }
  1055. /* portMAX_DELAY is used as a the time-out parameter, as binding *must*
  1056. * succeed before the socket can be used. _RB_ The use of an infinite
  1057. * block time needs be changed as it could result in the task hanging. */
  1058. if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
  1059. {
  1060. /* Failed to wake-up the IP-task, no use to wait for it */
  1061. FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );
  1062. xReturn = -pdFREERTOS_ERRNO_ECANCELED;
  1063. }
  1064. else
  1065. {
  1066. /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its
  1067. * job. */
  1068. ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );
  1069. if( !socketSOCKET_IS_BOUND( pxSocket ) )
  1070. {
  1071. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1072. }
  1073. }
  1074. }
  1075. return xReturn;
  1076. }
  1077. /*-----------------------------------------------------------*/
  1078. /**
  1079. * @brief Internal version of bind() that should not be called directly.
  1080. * 'xInternal' is used for TCP sockets only: it allows to have several
  1081. * (connected) child sockets bound to the same server port.
  1082. *
  1083. * @param[in] pxSocket: The socket is to be bound.
  1084. * @param[in] pxBindAddress: The port to which this socket should be bound.
  1085. * @param[in] uxAddressLength: The address length.
  1086. * @param[in] xInternal: pdTRUE is calling internally, else pdFALSE.
  1087. *
  1088. * @return If the socket was bound to a port successfully, then a 0 is returned.
  1089. * Or else, an error code is returned.
  1090. */
  1091. BaseType_t vSocketBind( FreeRTOS_Socket_t * pxSocket,
  1092. struct freertos_sockaddr * pxBindAddress,
  1093. size_t uxAddressLength,
  1094. BaseType_t xInternal )
  1095. {
  1096. BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */
  1097. List_t * pxSocketList;
  1098. struct freertos_sockaddr * pxAddress = pxBindAddress;
  1099. #if ( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
  1100. struct freertos_sockaddr xAddress;
  1101. #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */
  1102. #if ( ipconfigUSE_TCP == 1 )
  1103. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1104. {
  1105. pxSocketList = &xBoundTCPSocketsList;
  1106. }
  1107. else
  1108. #endif /* ipconfigUSE_TCP == 1 */
  1109. {
  1110. pxSocketList = &xBoundUDPSocketsList;
  1111. }
  1112. /* The function prototype is designed to maintain the expected Berkeley
  1113. * sockets standard, but this implementation does not use all the parameters. */
  1114. ( void ) uxAddressLength;
  1115. configASSERT( pxSocket != NULL );
  1116. configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );
  1117. #if ( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
  1118. {
  1119. /* pxAddress will be NULL if sendto() was called on a socket without the
  1120. * socket being bound to an address. In this case, automatically allocate
  1121. * an address to the socket. There is a small chance that the allocated
  1122. * port will already be in use - if that is the case, then the check below
  1123. * [pxListFindListItemWithValue()] will result in an error being returned. */
  1124. if( pxAddress == NULL )
  1125. {
  1126. pxAddress = &xAddress;
  1127. /* Put the port to zero to be assigned later. */
  1128. pxAddress->sin_port = 0U;
  1129. }
  1130. }
  1131. #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */
  1132. /* Sockets must be bound before calling FreeRTOS_sendto() if
  1133. * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */
  1134. configASSERT( pxAddress != NULL );
  1135. #if ( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )
  1136. /* pxAddress is not NULL, no testing needed. */
  1137. #else
  1138. if( pxAddress != NULL )
  1139. #endif
  1140. {
  1141. /* Add a do-while loop to facilitate use of 'break' statements. */
  1142. do
  1143. {
  1144. if( pxAddress->sin_port == 0U )
  1145. {
  1146. pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );
  1147. if( pxAddress->sin_port == ( uint16_t ) 0U )
  1148. {
  1149. xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
  1150. break;
  1151. }
  1152. }
  1153. /* If vSocketBind() is called from the API FreeRTOS_bind() it has been
  1154. * confirmed that the socket was not yet bound to a port. If it is called
  1155. * from the IP-task, no such check is necessary. */
  1156. /* Check to ensure the port is not already in use. If the bind is
  1157. * called internally, a port MAY be used by more than one socket. */
  1158. if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
  1159. ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )
  1160. {
  1161. FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
  1162. ( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ) ? "TC" : "UD",
  1163. FreeRTOS_ntohs( pxAddress->sin_port ) ) );
  1164. xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
  1165. }
  1166. else
  1167. {
  1168. /* Allocate the port number to the socket.
  1169. * This macro will set 'xBoundSocketListItem->xItemValue' */
  1170. socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );
  1171. /* And also store it in a socket field 'usLocalPort' in host-byte-order,
  1172. * mostly used for logging and debugging purposes */
  1173. pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );
  1174. /* Add the socket to the list of bound ports. */
  1175. {
  1176. /* If the network driver can iterate through 'xBoundUDPSocketsList',
  1177. * by calling xPortHasUDPSocket() then the IP-task must temporarily
  1178. * suspend the scheduler to keep the list in a consistent state. */
  1179. #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
  1180. {
  1181. vTaskSuspendAll();
  1182. }
  1183. #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
  1184. /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */
  1185. vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );
  1186. #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
  1187. {
  1188. ( void ) xTaskResumeAll();
  1189. }
  1190. #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
  1191. }
  1192. }
  1193. } while( ipFALSE_BOOL );
  1194. }
  1195. #if ( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 0 )
  1196. else
  1197. {
  1198. xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;
  1199. FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );
  1200. }
  1201. #endif
  1202. if( xReturn != 0 )
  1203. {
  1204. iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );
  1205. }
  1206. return xReturn;
  1207. } /* Tested */
  1208. /*-----------------------------------------------------------*/
  1209. /**
  1210. * @brief Close a socket and free the allocated space. In case of a TCP socket:
  1211. * the connection will not be closed automatically. Subsequent messages
  1212. * for the closed socket will be responded to with a RST. The IP-task
  1213. * will actually close the socket, after receiving a 'eSocketCloseEvent'
  1214. * message.
  1215. *
  1216. * @param[in] xSocket: the socket being closed.
  1217. *
  1218. * @return There are three distinct values which can be returned:
  1219. * 0: If the xSocket is NULL/invalid.
  1220. * 1: If the socket was successfully closed (read the brief above).
  1221. * -1: If the socket was valid but could not be closed because the message
  1222. * could not be delivered to the IP-task. Try again later.
  1223. */
  1224. BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
  1225. {
  1226. BaseType_t xResult;
  1227. #if ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )
  1228. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  1229. #endif
  1230. IPStackEvent_t xCloseEvent;
  1231. xCloseEvent.eEventType = eSocketCloseEvent;
  1232. xCloseEvent.pvData = xSocket;
  1233. if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )
  1234. {
  1235. xResult = 0;
  1236. }
  1237. else
  1238. {
  1239. #if ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )
  1240. {
  1241. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1242. {
  1243. /* Make sure that IP-task won't call the user callback's anymore */
  1244. pxSocket->u.xTCP.pxHandleConnected = NULL;
  1245. pxSocket->u.xTCP.pxHandleReceive = NULL;
  1246. pxSocket->u.xTCP.pxHandleSent = NULL;
  1247. }
  1248. }
  1249. #endif /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */
  1250. /* Let the IP task close the socket to keep it synchronised with the
  1251. * packet handling. */
  1252. /* Note when changing the time-out value below, it must be checked who is calling
  1253. * this function. If it is called by the IP-task, a deadlock could occur.
  1254. * The IP-task would only call it in case of a user call-back */
  1255. if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )
  1256. {
  1257. FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );
  1258. xResult = -1;
  1259. }
  1260. else
  1261. {
  1262. xResult = 1;
  1263. }
  1264. }
  1265. return xResult;
  1266. }
  1267. /**
  1268. * @brief This is the internal version of FreeRTOS_closesocket(). It will
  1269. * be called by the IPtask only to avoid problems with synchronicity.
  1270. *
  1271. * @param[in] pxSocket: The socket descriptor of the socket being closed.
  1272. *
  1273. * @return Returns NULL, always.
  1274. */
  1275. void * vSocketClose( FreeRTOS_Socket_t * pxSocket )
  1276. {
  1277. NetworkBufferDescriptor_t * pxNetworkBuffer;
  1278. #if ( ipconfigUSE_TCP == 1 )
  1279. {
  1280. /* For TCP: clean up a little more. */
  1281. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1282. {
  1283. #if ( ipconfigUSE_TCP_WIN == 1 )
  1284. {
  1285. if( pxSocket->u.xTCP.pxAckMessage != NULL )
  1286. {
  1287. vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );
  1288. }
  1289. /* Free the resources which were claimed by the tcpWin member */
  1290. vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );
  1291. }
  1292. #endif /* ipconfigUSE_TCP_WIN */
  1293. /* Free the input and output streams */
  1294. if( pxSocket->u.xTCP.rxStream != NULL )
  1295. {
  1296. iptraceMEM_STATS_DELETE( pxSocket->u.xTCP.rxStream );
  1297. vPortFreeLarge( pxSocket->u.xTCP.rxStream );
  1298. }
  1299. if( pxSocket->u.xTCP.txStream != NULL )
  1300. {
  1301. iptraceMEM_STATS_DELETE( pxSocket->u.xTCP.txStream );
  1302. vPortFreeLarge( pxSocket->u.xTCP.txStream );
  1303. }
  1304. /* In case this is a child socket, make sure the child-count of the
  1305. * parent socket is decreased. */
  1306. prvTCPSetSocketCount( pxSocket );
  1307. }
  1308. }
  1309. #endif /* ipconfigUSE_TCP == 1 */
  1310. /* Socket must be unbound first, to ensure no more packets are queued on
  1311. * it. */
  1312. if( socketSOCKET_IS_BOUND( pxSocket ) )
  1313. {
  1314. /* If the network driver can iterate through 'xBoundUDPSocketsList',
  1315. * by calling xPortHasUDPSocket(), then the IP-task must temporarily
  1316. * suspend the scheduler to keep the list in a consistent state. */
  1317. #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
  1318. {
  1319. vTaskSuspendAll();
  1320. }
  1321. #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
  1322. ( void ) uxListRemove( &( pxSocket->xBoundSocketListItem ) );
  1323. #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
  1324. {
  1325. ( void ) xTaskResumeAll();
  1326. }
  1327. #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
  1328. }
  1329. /* Now the socket is not bound the list of waiting packets can be
  1330. * drained. */
  1331. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
  1332. {
  1333. while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )
  1334. {
  1335. pxNetworkBuffer = ipCAST_PTR_TO_TYPE_PTR( NetworkBufferDescriptor_t, listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) );
  1336. ( void ) uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );
  1337. vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
  1338. }
  1339. }
  1340. if( pxSocket->xEventGroup != NULL )
  1341. {
  1342. vEventGroupDelete( pxSocket->xEventGroup );
  1343. }
  1344. #if ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )
  1345. {
  1346. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1347. {
  1348. FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",
  1349. pxSocket->usLocalPort,
  1350. pxSocket->u.xTCP.ulRemoteIP,
  1351. pxSocket->u.xTCP.usRemotePort,
  1352. uxGetNumberOfFreeNetworkBuffers(),
  1353. listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );
  1354. }
  1355. }
  1356. #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
  1357. /* And finally, after all resources have been freed, free the socket space */
  1358. iptraceMEM_STATS_DELETE( pxSocket );
  1359. vPortFreeSocket( pxSocket );
  1360. return NULL;
  1361. } /* Tested */
  1362. /*-----------------------------------------------------------*/
  1363. #if ipconfigUSE_TCP == 1
  1364. /**
  1365. * @brief When a child socket gets closed, make sure to update the child-count of the
  1366. * parent. When a listening parent socket is closed, make sure no child-sockets
  1367. * keep a pointer to it.
  1368. *
  1369. * @param[in] pxSocketToDelete: The socket being closed.
  1370. */
  1371. static void prvTCPSetSocketCount( FreeRTOS_Socket_t const * pxSocketToDelete )
  1372. {
  1373. const ListItem_t * pxIterator;
  1374. const ListItem_t * pxEnd = listGET_END_MARKER( &xBoundTCPSocketsList );
  1375. FreeRTOS_Socket_t * pxOtherSocket;
  1376. uint16_t usLocalPort = pxSocketToDelete->usLocalPort;
  1377. for( pxIterator = listGET_NEXT( pxEnd );
  1378. pxIterator != pxEnd;
  1379. pxIterator = listGET_NEXT( pxIterator ) )
  1380. {
  1381. pxOtherSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  1382. if( ( pxOtherSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN ) &&
  1383. ( pxOtherSocket->usLocalPort == usLocalPort ) &&
  1384. ( pxOtherSocket->u.xTCP.usChildCount != 0U ) )
  1385. {
  1386. pxOtherSocket->u.xTCP.usChildCount--;
  1387. FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",
  1388. pxOtherSocket->usLocalPort,
  1389. pxOtherSocket->u.xTCP.usChildCount,
  1390. pxOtherSocket->u.xTCP.usBacklog,
  1391. ( pxOtherSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
  1392. break;
  1393. }
  1394. }
  1395. }
  1396. #endif /* ipconfigUSE_TCP == 1 */
  1397. /*-----------------------------------------------------------*/
  1398. #if ( ipconfigUSE_TCP == 1 )
  1399. /**
  1400. * @brief Set the value of receive/send buffer after some preliminary checks.
  1401. *
  1402. * @param[in] pxSocket: The socket whose options are being set.
  1403. * @param[in] lOptionName: The option name: either FREERTOS_SO_SNDBUF or
  1404. * FREERTOS_SO_SNDBUF.
  1405. * @param[in] pvOptionValue: The value of the option being set.
  1406. *
  1407. * @return If there is no error, then 0 is returned. Or a negative errno
  1408. * value is returned.
  1409. */
  1410. static BaseType_t prvSockopt_so_buffer( FreeRTOS_Socket_t * pxSocket,
  1411. int32_t lOptionName,
  1412. const void * pvOptionValue )
  1413. {
  1414. uint32_t ulNewValue;
  1415. BaseType_t xReturn;
  1416. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1417. {
  1418. FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
  1419. ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
  1420. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1421. }
  1422. else if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
  1423. ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
  1424. {
  1425. FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
  1426. ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
  1427. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1428. }
  1429. else
  1430. {
  1431. ulNewValue = *( ipPOINTER_CAST( const uint32_t *, pvOptionValue ) );
  1432. if( lOptionName == FREERTOS_SO_SNDBUF )
  1433. {
  1434. /* Round up to nearest MSS size */
  1435. ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
  1436. pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
  1437. }
  1438. else
  1439. {
  1440. pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
  1441. }
  1442. xReturn = 0;
  1443. }
  1444. return xReturn;
  1445. }
  1446. #endif /* ipconfigUSE_TCP == 1 */
  1447. /*-----------------------------------------------------------*/
  1448. /* FreeRTOS_setsockopt calls itself, but in a very limited way,
  1449. * only when FREERTOS_SO_WIN_PROPERTIES is being set. */
  1450. /**
  1451. * @brief Set the socket options for the given socket.
  1452. *
  1453. * @param[in] xSocket: The socket for which the options are to be set.
  1454. * @param[in] lLevel: Not used. Parameter is used to maintain the Berkeley sockets
  1455. * standard.
  1456. * @param[in] lOptionName: The name of the option to be set.
  1457. * @param[in] pvOptionValue: The value of the option to be set.
  1458. * @param[in] uxOptionLength: Not used. Parameter is used to maintain the Berkeley
  1459. * sockets standard.
  1460. *
  1461. * @return If the option can be set with the given value, then 0 is returned. Else,
  1462. * an error code is returned.
  1463. */
  1464. BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
  1465. int32_t lLevel,
  1466. int32_t lOptionName,
  1467. const void * pvOptionValue,
  1468. size_t uxOptionLength )
  1469. {
  1470. /* The standard Berkeley function returns 0 for success. */
  1471. BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1472. FreeRTOS_Socket_t * pxSocket;
  1473. pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  1474. /* The function prototype is designed to maintain the expected Berkeley
  1475. * sockets standard, but this implementation does not use all the parameters. */
  1476. ( void ) lLevel;
  1477. ( void ) uxOptionLength;
  1478. if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )
  1479. {
  1480. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  1481. return xReturn;
  1482. }
  1483. switch( lOptionName )
  1484. {
  1485. case FREERTOS_SO_RCVTIMEO:
  1486. /* Receive time out. */
  1487. pxSocket->xReceiveBlockTime = *( ( const TickType_t * ) pvOptionValue );
  1488. xReturn = 0;
  1489. break;
  1490. case FREERTOS_SO_SNDTIMEO:
  1491. pxSocket->xSendBlockTime = *( ( const TickType_t * ) pvOptionValue );
  1492. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
  1493. {
  1494. /* The send time out is capped for the reason stated in the
  1495. * comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
  1496. * in FreeRTOSIPConfig.h (assuming an official configuration file
  1497. * is being used. */
  1498. if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
  1499. {
  1500. pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
  1501. }
  1502. }
  1503. else
  1504. {
  1505. /* For TCP socket, it isn't necessary to limit the blocking time
  1506. * because the FreeRTOS_send() function does not wait for a network
  1507. * buffer to become available. */
  1508. }
  1509. xReturn = 0;
  1510. break;
  1511. #if ( ipconfigUDP_MAX_RX_PACKETS > 0U )
  1512. case FREERTOS_SO_UDP_MAX_RX_PACKETS:
  1513. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
  1514. {
  1515. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1516. }
  1517. pxSocket->u.xUDP.uxMaxPackets = *( ( const UBaseType_t * ) pvOptionValue );
  1518. xReturn = 0;
  1519. break;
  1520. #endif /* ipconfigUDP_MAX_RX_PACKETS */
  1521. case FREERTOS_SO_UDPCKSUM_OUT:
  1522. /* Turn calculating of the UDP checksum on/off for this socket. If pvOptionValue
  1523. * is anything else than NULL, the checksum generation will be turned on. */
  1524. if( pvOptionValue == NULL )
  1525. {
  1526. pxSocket->ucSocketOptions &= ~( ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT );
  1527. }
  1528. else
  1529. {
  1530. pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
  1531. }
  1532. xReturn = 0;
  1533. break;
  1534. #if ( ipconfigUSE_CALLBACKS == 1 )
  1535. #if ( ipconfigUSE_TCP == 1 )
  1536. case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
  1537. case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
  1538. case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
  1539. #endif /* ipconfigUSE_TCP */
  1540. case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
  1541. case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
  1542. {
  1543. #if ( ipconfigUSE_TCP == 1 )
  1544. {
  1545. UBaseType_t uxProtocol;
  1546. if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
  1547. ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
  1548. {
  1549. uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
  1550. }
  1551. else
  1552. {
  1553. uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
  1554. }
  1555. if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
  1556. {
  1557. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1558. }
  1559. }
  1560. #else /* if ( ipconfigUSE_TCP == 1 ) */
  1561. {
  1562. /* No need to check if the socket has the right
  1563. * protocol, because only UDP socket can be created. */
  1564. }
  1565. #endif /* ipconfigUSE_TCP */
  1566. switch( lOptionName )
  1567. {
  1568. #if ipconfigUSE_TCP == 1
  1569. case FREERTOS_SO_TCP_CONN_HANDLER:
  1570. pxSocket->u.xTCP.pxHandleConnected = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( F_TCP_UDP_Handler_t, pvOptionValue )->pxOnTCPConnected;
  1571. break;
  1572. case FREERTOS_SO_TCP_RECV_HANDLER:
  1573. pxSocket->u.xTCP.pxHandleReceive = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( F_TCP_UDP_Handler_t, pvOptionValue )->pxOnTCPReceive;
  1574. break;
  1575. case FREERTOS_SO_TCP_SENT_HANDLER:
  1576. pxSocket->u.xTCP.pxHandleSent = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( F_TCP_UDP_Handler_t, pvOptionValue )->pxOnTCPSent;
  1577. break;
  1578. #endif /* ipconfigUSE_TCP */
  1579. case FREERTOS_SO_UDP_RECV_HANDLER:
  1580. pxSocket->u.xUDP.pxHandleReceive = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( F_TCP_UDP_Handler_t, pvOptionValue )->pxOnUDPReceive;
  1581. break;
  1582. case FREERTOS_SO_UDP_SENT_HANDLER:
  1583. pxSocket->u.xUDP.pxHandleSent = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( F_TCP_UDP_Handler_t, pvOptionValue )->pxOnUDPSent;
  1584. break;
  1585. default:
  1586. /* Should it throw an error here? */
  1587. break;
  1588. }
  1589. }
  1590. xReturn = 0;
  1591. break;
  1592. #endif /* ipconfigUSE_CALLBACKS */
  1593. #if ( ipconfigUSE_TCP != 0 )
  1594. #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
  1595. /* Each socket has a semaphore on which the using task normally
  1596. * sleeps. */
  1597. case FREERTOS_SO_SET_SEMAPHORE:
  1598. {
  1599. pxSocket->pxUserSemaphore = *( ipPOINTER_CAST( SemaphoreHandle_t *, pvOptionValue ) );
  1600. }
  1601. xReturn = 0;
  1602. break;
  1603. #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
  1604. #if ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
  1605. case FREERTOS_SO_WAKEUP_CALLBACK:
  1606. /* Each socket can have a callback function that is executed
  1607. * when there is an event the socket's owner might want to
  1608. * process. */
  1609. /* The type cast of the pointer expression "A" to type "B" removes const qualifier from the pointed to type. */
  1610. pxSocket->pxUserWakeCallback = ( const SocketWakeupCallback_t ) pvOptionValue;
  1611. xReturn = 0;
  1612. break;
  1613. #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
  1614. case FREERTOS_SO_SET_LOW_HIGH_WATER:
  1615. {
  1616. const LowHighWater_t * pxLowHighWater = ipPOINTER_CAST( const LowHighWater_t *, pvOptionValue );
  1617. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1618. {
  1619. /* It is not allowed to access 'pxSocket->u.xTCP'. */
  1620. FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
  1621. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1622. }
  1623. if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
  1624. ( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
  1625. {
  1626. /* Impossible values. */
  1627. FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
  1628. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1629. }
  1630. /* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
  1631. pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
  1632. /* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
  1633. pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
  1634. xReturn = 0;
  1635. }
  1636. break;
  1637. case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
  1638. case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
  1639. xReturn = prvSockopt_so_buffer( pxSocket, lOptionName, pvOptionValue );
  1640. break;
  1641. case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
  1642. {
  1643. const WinProperties_t * pxProps;
  1644. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1645. {
  1646. FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
  1647. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1648. }
  1649. if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
  1650. {
  1651. FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
  1652. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1653. }
  1654. pxProps = ipPOINTER_CAST( const WinProperties_t *, pvOptionValue );
  1655. xReturn = prvSockopt_so_buffer( pxSocket, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ) );
  1656. if( xReturn != 0 )
  1657. {
  1658. break; /* will return an error. */
  1659. }
  1660. xReturn = prvSockopt_so_buffer( pxSocket, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ) );
  1661. if( xReturn != 0 )
  1662. {
  1663. break; /* will return an error. */
  1664. }
  1665. #if ( ipconfigUSE_TCP_WIN == 1 )
  1666. {
  1667. pxSocket->u.xTCP.uxRxWinSize = ( uint32_t ) pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
  1668. pxSocket->u.xTCP.uxTxWinSize = ( uint32_t ) pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
  1669. }
  1670. #else
  1671. {
  1672. pxSocket->u.xTCP.uxRxWinSize = 1U;
  1673. pxSocket->u.xTCP.uxTxWinSize = 1U;
  1674. }
  1675. #endif
  1676. /* In case the socket has already initialised its tcpWin,
  1677. * adapt the window size parameters */
  1678. if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
  1679. {
  1680. pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
  1681. pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
  1682. }
  1683. }
  1684. xReturn = 0;
  1685. break;
  1686. case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
  1687. {
  1688. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1689. {
  1690. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1691. }
  1692. if( *( ( const BaseType_t * ) pvOptionValue ) != 0 )
  1693. {
  1694. pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE;
  1695. }
  1696. else
  1697. {
  1698. pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE;
  1699. }
  1700. }
  1701. xReturn = 0;
  1702. break;
  1703. case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
  1704. {
  1705. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1706. {
  1707. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1708. }
  1709. if( *( ( const BaseType_t * ) pvOptionValue ) != 0 )
  1710. {
  1711. pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE;
  1712. }
  1713. else
  1714. {
  1715. pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE;
  1716. }
  1717. }
  1718. xReturn = 0;
  1719. break;
  1720. case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
  1721. {
  1722. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1723. {
  1724. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1725. }
  1726. if( *( ( const BaseType_t * ) pvOptionValue ) != 0 )
  1727. {
  1728. pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE;
  1729. }
  1730. else
  1731. {
  1732. pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE;
  1733. }
  1734. if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
  1735. ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) &&
  1736. ( FreeRTOS_outstanding( pxSocket ) != 0 ) )
  1737. {
  1738. pxSocket->u.xTCP.usTimeout = 1U; /* to set/clear bSendFullSize */
  1739. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  1740. }
  1741. }
  1742. xReturn = 0;
  1743. break;
  1744. case FREERTOS_SO_STOP_RX: /* Refuse to receive more packets. */
  1745. {
  1746. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  1747. {
  1748. break; /* will return -pdFREERTOS_ERRNO_EINVAL */
  1749. }
  1750. if( *( ( const BaseType_t * ) pvOptionValue ) != 0 )
  1751. {
  1752. pxSocket->u.xTCP.bits.bRxStopped = pdTRUE;
  1753. }
  1754. else
  1755. {
  1756. pxSocket->u.xTCP.bits.bRxStopped = pdFALSE;
  1757. }
  1758. pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
  1759. pxSocket->u.xTCP.usTimeout = 1U; /* to set/clear bRxStopped */
  1760. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  1761. }
  1762. xReturn = 0;
  1763. break;
  1764. #endif /* ipconfigUSE_TCP == 1 */
  1765. default:
  1766. /* No other options are handled. */
  1767. xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
  1768. break;
  1769. }
  1770. return xReturn;
  1771. } /* Tested */
  1772. /*-----------------------------------------------------------*/
  1773. /**
  1774. * @brief Find an available port number per https://tools.ietf.org/html/rfc6056.
  1775. *
  1776. * @param[in] xProtocol: FREERTOS_IPPROTO_TCP/FREERTOS_IPPROTO_UDP.
  1777. *
  1778. * @return If an available protocol port is found then that port number is returned.
  1779. * Or else, 0 is returned.
  1780. */
  1781. static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )
  1782. {
  1783. const uint16_t usEphemeralPortCount =
  1784. socketAUTO_PORT_ALLOCATION_MAX_NUMBER - ( socketAUTO_PORT_ALLOCATION_START_NUMBER - 1U );
  1785. uint16_t usIterations = usEphemeralPortCount;
  1786. uint32_t ulRandomSeed = 0;
  1787. uint16_t usResult = 0;
  1788. const List_t * pxList;
  1789. #if ipconfigUSE_TCP == 1
  1790. if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )
  1791. {
  1792. pxList = &xBoundTCPSocketsList;
  1793. }
  1794. else
  1795. #endif
  1796. {
  1797. pxList = &xBoundUDPSocketsList;
  1798. }
  1799. /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */
  1800. ( void ) xProtocol;
  1801. /* Find the next available port using the random seed as a starting
  1802. * point. */
  1803. do
  1804. {
  1805. /* Only proceed if the random number generator succeeded. */
  1806. if( xApplicationGetRandomNumber( &( ulRandomSeed ) ) == pdFALSE )
  1807. {
  1808. break;
  1809. }
  1810. /* Map the random to a candidate port. */
  1811. usResult =
  1812. socketAUTO_PORT_ALLOCATION_START_NUMBER +
  1813. ( ( ( uint16_t ) ulRandomSeed ) % usEphemeralPortCount );
  1814. /* Check if there's already an open socket with the same protocol
  1815. * and port. */
  1816. if( NULL == pxListFindListItemWithValue(
  1817. pxList,
  1818. ( TickType_t ) FreeRTOS_htons( usResult ) ) )
  1819. {
  1820. usResult = FreeRTOS_htons( usResult );
  1821. break;
  1822. }
  1823. else
  1824. {
  1825. usResult = 0;
  1826. }
  1827. usIterations--;
  1828. }
  1829. while( usIterations > 0U );
  1830. return usResult;
  1831. }
  1832. /*-----------------------------------------------------------*/
  1833. /**
  1834. * @brief Find a list item associated with the wanted-item.
  1835. *
  1836. * @param[in] pxList: The list through which the search is to be conducted.
  1837. * @param[in] xWantedItemValue: The wanted item whose association is to be found.
  1838. *
  1839. * @return The list item holding the value being searched for. If nothing is found,
  1840. * then a NULL is returned.
  1841. */
  1842. static const ListItem_t * pxListFindListItemWithValue( const List_t * pxList,
  1843. TickType_t xWantedItemValue )
  1844. {
  1845. const ListItem_t * pxResult = NULL;
  1846. if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )
  1847. {
  1848. const ListItem_t * pxIterator;
  1849. const ListItem_t * pxEnd = listGET_END_MARKER( pxList );
  1850. for( pxIterator = listGET_NEXT( pxEnd );
  1851. pxIterator != pxEnd;
  1852. pxIterator = listGET_NEXT( pxIterator ) )
  1853. {
  1854. if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )
  1855. {
  1856. pxResult = pxIterator;
  1857. break;
  1858. }
  1859. }
  1860. }
  1861. return pxResult;
  1862. } /* Tested */
  1863. /*-----------------------------------------------------------*/
  1864. /**
  1865. * @brief Find the UDP socket corresponding to the port number.
  1866. *
  1867. * @param[in] uxLocalPort: The port whose corresponding bound UDP socket
  1868. * is to be found.
  1869. *
  1870. * @return The socket owning the port if found or else NULL.
  1871. */
  1872. FreeRTOS_Socket_t * pxUDPSocketLookup( UBaseType_t uxLocalPort )
  1873. {
  1874. const ListItem_t * pxListItem;
  1875. FreeRTOS_Socket_t * pxSocket = NULL;
  1876. /* Looking up a socket is quite simple, find a match with the local port.
  1877. *
  1878. * See if there is a list item associated with the port number on the
  1879. * list of bound sockets. */
  1880. pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );
  1881. if( pxListItem != NULL )
  1882. {
  1883. /* The owner of the list item is the socket itself. */
  1884. pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxListItem ) );
  1885. configASSERT( pxSocket != NULL );
  1886. }
  1887. return pxSocket;
  1888. }
  1889. /*-----------------------------------------------------------*/
  1890. #define sockDIGIT_COUNT ( 3U ) /**< Each nibble is expressed in at most 3 digits such as "192". */
  1891. /**
  1892. * @brief Convert the 32-bit representation of the IP-address to the dotted decimal
  1893. * notation after some checks.
  1894. * A safe alternative is FreeRTOS_inet_ntop4().
  1895. *
  1896. * @param[in] ulIPAddress: 32-bit representation of the IP-address.
  1897. * @param[out] pcBuffer: The buffer where the dotted decimal representation will be
  1898. * stored if all checks pass. The buffer must be at least 16
  1899. * bytes long.
  1900. *
  1901. * @return If all checks pass, then the pointer returned will be same as pcBuffer
  1902. * and will have the address stored in the location. Else, NULL is returned.
  1903. */
  1904. const char * FreeRTOS_inet_ntoa( uint32_t ulIPAddress,
  1905. char * pcBuffer )
  1906. {
  1907. socklen_t uxNibble;
  1908. socklen_t uxIndex = 0;
  1909. const uint8_t * pucAddress = ( const uint8_t * ) &( ulIPAddress );
  1910. const char * pcResult = pcBuffer;
  1911. const socklen_t uxSize = 16;
  1912. for( uxNibble = 0; uxNibble < ipSIZE_OF_IPv4_ADDRESS; uxNibble++ )
  1913. {
  1914. uint8_t pucDigits[ sockDIGIT_COUNT ];
  1915. uint8_t ucValue = pucAddress[ uxNibble ];
  1916. socklen_t uxSource = ( socklen_t ) sockDIGIT_COUNT - ( socklen_t ) 1U;
  1917. socklen_t uxNeeded;
  1918. for( ; ; )
  1919. {
  1920. pucDigits[ uxSource ] = ucValue % ( uint8_t ) 10U;
  1921. ucValue /= ( uint8_t ) 10U;
  1922. if( uxSource == 1U )
  1923. {
  1924. break;
  1925. }
  1926. uxSource--;
  1927. }
  1928. pucDigits[ 0 ] = ucValue;
  1929. /* Skip leading zeros. */
  1930. for( uxSource = 0; uxSource < ( ( socklen_t ) sockDIGIT_COUNT - ( socklen_t ) 1U ); uxSource++ )
  1931. {
  1932. if( pucDigits[ uxSource ] != 0U )
  1933. {
  1934. break;
  1935. }
  1936. }
  1937. /* Write e.g. "192.", which is 3 digits and a dot. */
  1938. uxNeeded = ( ( socklen_t ) sockDIGIT_COUNT - uxSource ) + 1U;
  1939. if( ( uxIndex + uxNeeded ) > uxSize )
  1940. {
  1941. /* The result won't fit. */
  1942. pcResult = NULL;
  1943. break;
  1944. }
  1945. for( ; uxSource < ( socklen_t ) sockDIGIT_COUNT; uxSource++ )
  1946. {
  1947. pcBuffer[ uxIndex ] = ( char ) ( pucDigits[ uxSource ] + ( char ) '0' );
  1948. uxIndex++;
  1949. }
  1950. if( uxNibble < ( ipSIZE_OF_IPv4_ADDRESS - 1U ) )
  1951. {
  1952. pcBuffer[ uxIndex ] = '.';
  1953. }
  1954. else
  1955. {
  1956. pcBuffer[ uxIndex ] = '\0';
  1957. }
  1958. uxIndex++;
  1959. }
  1960. return pcResult;
  1961. }
  1962. /*-----------------------------------------------------------*/
  1963. /**
  1964. * @brief Convert the dotted decimal format of the IP-address to the 32-bit representation.
  1965. *
  1966. * @param[in] xAddressFamily: The Address family to which the IP-address belongs to. Only
  1967. * FREERTOS_AF_INET (IPv4) is supported.
  1968. * @param[in] pcSource: Pointer to the string holding the dotted decimal representation of
  1969. * the IP-address.
  1970. * @param[out] pvDestination: The pointer to the address struct/variable where the converted
  1971. * IP-address will be stored. The buffer must be 4 bytes long
  1972. * in case of a IPv4 address.
  1973. *
  1974. * @return If all checks pass, then pdPASS is returned or else pdFAIL is returned.
  1975. */
  1976. BaseType_t FreeRTOS_inet_pton( BaseType_t xAddressFamily,
  1977. const char * pcSource,
  1978. void * pvDestination )
  1979. {
  1980. BaseType_t xResult;
  1981. /* Printable string to struct sockaddr. */
  1982. switch( xAddressFamily )
  1983. {
  1984. case FREERTOS_AF_INET:
  1985. xResult = FreeRTOS_inet_pton4( pcSource, pvDestination );
  1986. break;
  1987. default:
  1988. xResult = -pdFREERTOS_ERRNO_EAFNOSUPPORT;
  1989. break;
  1990. }
  1991. return xResult;
  1992. }
  1993. /*-----------------------------------------------------------*/
  1994. /**
  1995. * @brief Convert the 32-bit representation of the IP-address to the dotted
  1996. * decimal format based on the Address Family. (Only FREERTOS_AF_INET
  1997. * is allowed).
  1998. *
  1999. * @param[in] xAddressFamily: The address family of the IP-address.
  2000. * @param[in] pvSource: Pointer to the 32-bit representation of IP-address.
  2001. * @param[out] pcDestination: The pointer to the character array where the dotted
  2002. * decimal address will be stored if every check does pass.
  2003. * @param[in] uxSize: Size of the character array. This value makes sure that the code
  2004. * doesn't write beyond it's bounds.
  2005. *
  2006. * @return If every check does pass, then the pointer to the pcDestination is returned
  2007. * holding the dotted decimal format of IP-address. Else, a NULL is returned.
  2008. */
  2009. const char * FreeRTOS_inet_ntop( BaseType_t xAddressFamily,
  2010. const void * pvSource,
  2011. char * pcDestination,
  2012. socklen_t uxSize )
  2013. {
  2014. const char * pcResult;
  2015. /* Printable struct sockaddr to string. */
  2016. switch( xAddressFamily )
  2017. {
  2018. case FREERTOS_AF_INET:
  2019. pcResult = FreeRTOS_inet_ntop4( pvSource, pcDestination, uxSize );
  2020. break;
  2021. default:
  2022. /* errno should be set to pdFREERTOS_ERRNO_EAFNOSUPPORT. */
  2023. pcResult = NULL;
  2024. break;
  2025. }
  2026. return pcResult;
  2027. }
  2028. /*-----------------------------------------------------------*/
  2029. /**
  2030. * @brief Convert the 32-bit representation of the IP-address to the dotted decimal format.
  2031. *
  2032. * @param[in] pvSource: The pointer to the 32-bit representation of the IP-address.
  2033. * @param[out] pcDestination: The pointer to a character array where the string of the
  2034. * dotted decimal IP format.
  2035. * @param[in] uxSize: Size of the character array. This value makes sure that the code
  2036. * doesn't write beyond it's bounds.
  2037. *
  2038. * @return The pointer to the string holding the dotted decimal format of the IP-address. If
  2039. * everything passes correctly, then the pointer being returned is the same as
  2040. * pcDestination, else a NULL is returned.
  2041. */
  2042. const char * FreeRTOS_inet_ntop4( const void * pvSource,
  2043. char * pcDestination,
  2044. socklen_t uxSize )
  2045. {
  2046. uint32_t ulIPAddress;
  2047. void * pvCopyDest;
  2048. const char * pcReturn;
  2049. if( uxSize < 16U )
  2050. {
  2051. /* There must be space for "255.255.255.255". */
  2052. pcReturn = NULL;
  2053. }
  2054. else
  2055. {
  2056. pvCopyDest = ( void * ) &ulIPAddress;
  2057. ( void ) memcpy( pvCopyDest, pvSource, sizeof( ulIPAddress ) );
  2058. ( void ) FreeRTOS_inet_ntoa( ulIPAddress, pcDestination );
  2059. pcReturn = pcDestination;
  2060. }
  2061. return pcReturn;
  2062. }
  2063. /*-----------------------------------------------------------*/
  2064. /**
  2065. * @brief This function converts the character string pcSource into a network address
  2066. * structure, then copies the network address structure to pvDestination.
  2067. * pvDestination is written in network byte order.
  2068. *
  2069. * @param[in] pcSource: The character string in holding the IP address.
  2070. * @param[out] pvDestination: The returned network address in 32-bit network-endian format.
  2071. *
  2072. * @return pdPASS if the translation was successful or else pdFAIL.
  2073. */
  2074. BaseType_t FreeRTOS_inet_pton4( const char * pcSource,
  2075. void * pvDestination )
  2076. {
  2077. const uint32_t ulDecimalBase = 10U;
  2078. uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];
  2079. uint32_t ulReturn = 0UL, ulValue;
  2080. UBaseType_t uxOctetNumber;
  2081. BaseType_t xResult = pdPASS;
  2082. const char * pcIPAddress = pcSource;
  2083. const void * pvCopySource;
  2084. ( void ) memset( pvDestination, 0, sizeof( ulReturn ) );
  2085. /* Translate "192.168.2.100" to a 32-bit number, network-endian. */
  2086. for( uxOctetNumber = 0U; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )
  2087. {
  2088. ulValue = 0UL;
  2089. if( pcIPAddress[ 0 ] == '0' )
  2090. {
  2091. /* Test for the sequence "0[0-9]", which would make it an octal representation. */
  2092. if( ( pcIPAddress[ 1 ] >= '0' ) && ( pcIPAddress[ 1 ] <= '9' ) )
  2093. {
  2094. FreeRTOS_printf( ( "Octal representation of IP-addresses is not supported." ) );
  2095. /* Don't support octal numbers. */
  2096. xResult = pdFAIL;
  2097. break;
  2098. }
  2099. }
  2100. while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )
  2101. {
  2102. BaseType_t xChar;
  2103. /* Move previous read characters into the next decimal
  2104. * position. */
  2105. ulValue *= ulDecimalBase;
  2106. /* Add the binary value of the ascii character. */
  2107. xChar = ( BaseType_t ) pcIPAddress[ 0 ];
  2108. xChar = xChar - ( BaseType_t ) '0';
  2109. ulValue += ( uint32_t ) xChar;
  2110. /* Move to next character in the string. */
  2111. pcIPAddress++;
  2112. }
  2113. /* Check characters were read. */
  2114. if( pcIPAddress == pcSource )
  2115. {
  2116. xResult = pdFAIL;
  2117. }
  2118. /* Check the value fits in an 8-bit number. */
  2119. if( ulValue > 0xffUL )
  2120. {
  2121. xResult = pdFAIL;
  2122. }
  2123. else
  2124. {
  2125. ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;
  2126. /* Check the next character is as expected. */
  2127. if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1U ) )
  2128. {
  2129. if( *pcIPAddress != '.' )
  2130. {
  2131. xResult = pdFAIL;
  2132. }
  2133. else
  2134. {
  2135. /* Move past the dot. */
  2136. pcIPAddress++;
  2137. }
  2138. }
  2139. }
  2140. if( xResult == pdFAIL )
  2141. {
  2142. /* No point going on. */
  2143. break;
  2144. }
  2145. }
  2146. if( *pcIPAddress != ( char ) 0 )
  2147. {
  2148. /* Expected the end of the string. */
  2149. xResult = pdFAIL;
  2150. }
  2151. if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )
  2152. {
  2153. /* Didn't read enough octets. */
  2154. xResult = pdFAIL;
  2155. }
  2156. if( xResult == pdPASS )
  2157. {
  2158. /* lint: ucOctet has been set because xResult == pdPASS. */
  2159. ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );
  2160. }
  2161. else
  2162. {
  2163. ulReturn = 0UL;
  2164. }
  2165. if( xResult == pdPASS )
  2166. {
  2167. pvCopySource = ( const void * ) &ulReturn;
  2168. ( void ) memcpy( pvDestination, pvCopySource, sizeof( ulReturn ) );
  2169. }
  2170. return xResult;
  2171. }
  2172. /*-----------------------------------------------------------*/
  2173. /**
  2174. * @brief Convert the IP address from "w.x.y.z" (dotted decimal) format to the 32-bit format.
  2175. *
  2176. * @param[in] pcIPAddress: The character string pointer holding the IP-address in the "W.X.Y.Z"
  2177. * (dotted decimal) format.
  2178. *
  2179. * @return The 32-bit representation of IP(v4) address.
  2180. */
  2181. uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
  2182. {
  2183. uint32_t ulReturn = 0UL;
  2184. /* inet_pton AF_INET target is a 4-byte 'struct in_addr'. */
  2185. ( void ) FreeRTOS_inet_pton4( pcIPAddress, &( ulReturn ) );
  2186. return ulReturn;
  2187. }
  2188. /*-----------------------------------------------------------*/
  2189. /**
  2190. * @brief Function to get the local address and IP port of the given socket.
  2191. *
  2192. * @param[in] xSocket: Socket whose port is to be added to the pxAddress.
  2193. * @param[out] pxAddress: Structure in which the IP address and the port number
  2194. * is returned.
  2195. *
  2196. * @return Size of the freertos_sockaddr structure.
  2197. */
  2198. size_t FreeRTOS_GetLocalAddress( ConstSocket_t xSocket,
  2199. struct freertos_sockaddr * pxAddress )
  2200. {
  2201. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  2202. /* IP address of local machine. */
  2203. pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
  2204. /* Local port on this machine. */
  2205. pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
  2206. return sizeof( *pxAddress );
  2207. }
  2208. /*-----------------------------------------------------------*/
  2209. /**
  2210. * @brief Wake up the user of the given socket through event-groups.
  2211. *
  2212. * @param[in] pxSocket: The socket whose user is to be woken up.
  2213. */
  2214. void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket )
  2215. {
  2216. /* _HT_ must work this out, now vSocketWakeUpUser will be called for any important
  2217. * event or transition */
  2218. #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
  2219. {
  2220. if( pxSocket->pxUserSemaphore != NULL )
  2221. {
  2222. ( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
  2223. }
  2224. }
  2225. #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
  2226. #if ( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK == 1 )
  2227. {
  2228. if( pxSocket->pxUserWakeCallback != NULL )
  2229. {
  2230. pxSocket->pxUserWakeCallback( pxSocket );
  2231. }
  2232. }
  2233. #endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
  2234. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  2235. {
  2236. if( pxSocket->pxSocketSet != NULL )
  2237. {
  2238. EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & ( ( EventBits_t ) eSELECT_ALL );
  2239. if( xSelectBits != 0UL )
  2240. {
  2241. pxSocket->xSocketBits |= xSelectBits;
  2242. ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );
  2243. }
  2244. }
  2245. pxSocket->xEventBits &= ( EventBits_t ) eSOCKET_ALL;
  2246. }
  2247. #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
  2248. if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0U ) )
  2249. {
  2250. ( void ) xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );
  2251. }
  2252. pxSocket->xEventBits = 0UL;
  2253. }
  2254. /*-----------------------------------------------------------*/
  2255. #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
  2256. /**
  2257. * @brief This define makes it possible for network interfaces to inspect
  2258. * UDP messages and see if there is any UDP socket bound to a given port
  2259. * number. This is probably only useful in systems with a minimum of
  2260. * RAM and when lots of anonymous broadcast messages come in.
  2261. *
  2262. * @param[in] usPortNr: the port number to look for.
  2263. *
  2264. * @return xFound if a socket with the port number is found.
  2265. */
  2266. BaseType_t xPortHasUDPSocket( uint16_t usPortNr )
  2267. {
  2268. BaseType_t xFound = pdFALSE;
  2269. vTaskSuspendAll();
  2270. {
  2271. if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )
  2272. {
  2273. xFound = pdTRUE;
  2274. }
  2275. }
  2276. ( void ) xTaskResumeAll();
  2277. return xFound;
  2278. }
  2279. #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
  2280. /*-----------------------------------------------------------*/
  2281. #if ( ipconfigUSE_TCP == 1 )
  2282. /**
  2283. * @brief Check if it makes any sense to wait for a connect event.
  2284. *
  2285. * @param[in] pxSocket: The socket trying to connect.
  2286. *
  2287. * @return It may return: -EINPROGRESS, -EAGAIN, or 0 for OK.
  2288. */
  2289. static BaseType_t bMayConnect( FreeRTOS_Socket_t const * pxSocket )
  2290. {
  2291. BaseType_t xResult;
  2292. eIPTCPState_t eState = ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState );
  2293. switch( eState )
  2294. {
  2295. case eCLOSED:
  2296. case eCLOSE_WAIT:
  2297. xResult = 0;
  2298. break;
  2299. case eCONNECT_SYN:
  2300. xResult = -pdFREERTOS_ERRNO_EINPROGRESS;
  2301. break;
  2302. case eTCP_LISTEN:
  2303. case eSYN_FIRST:
  2304. case eSYN_RECEIVED:
  2305. case eESTABLISHED:
  2306. case eFIN_WAIT_1:
  2307. case eFIN_WAIT_2:
  2308. case eCLOSING:
  2309. case eLAST_ACK:
  2310. case eTIME_WAIT:
  2311. default:
  2312. xResult = -pdFREERTOS_ERRNO_EAGAIN;
  2313. break;
  2314. }
  2315. return xResult;
  2316. }
  2317. #endif /* ipconfigUSE_TCP */
  2318. /*-----------------------------------------------------------*/
  2319. #if ( ipconfigUSE_TCP == 1 )
  2320. /**
  2321. * @brief Called from #FreeRTOS_connect(): make some checks and if allowed,
  2322. * send a message to the IP-task to start connecting to a remote socket.
  2323. *
  2324. * @param[in] pxSocket: The socket attempting to connect to a remote port.
  2325. * @param[in] pxAddress: The address the socket is trying to connect to.
  2326. *
  2327. * @return 0 on successful checks or a negative error code.
  2328. */
  2329. static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t * pxSocket,
  2330. struct freertos_sockaddr const * pxAddress )
  2331. {
  2332. BaseType_t xResult = 0;
  2333. if( pxAddress == NULL )
  2334. {
  2335. /* NULL address passed to the function. Invalid value. */
  2336. xResult = -pdFREERTOS_ERRNO_EINVAL;
  2337. }
  2338. else if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )
  2339. {
  2340. /* Not a valid socket or wrong type */
  2341. xResult = -pdFREERTOS_ERRNO_EBADF;
  2342. }
  2343. else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )
  2344. {
  2345. /* The socket is already connected. */
  2346. xResult = -pdFREERTOS_ERRNO_EISCONN;
  2347. }
  2348. else if( !socketSOCKET_IS_BOUND( pxSocket ) )
  2349. {
  2350. /* Bind the socket to the port that the client task will send from.
  2351. * Non-standard, so the error returned is that returned by bind(). */
  2352. xResult = FreeRTOS_bind( pxSocket, NULL, 0U );
  2353. }
  2354. else
  2355. {
  2356. /* The socket is valid, not yet connected, and already bound to a port number. */
  2357. }
  2358. if( xResult == 0 )
  2359. {
  2360. /* Check if it makes any sense to wait for a connect event, this condition
  2361. * might change while sleeping, so it must be checked within each loop */
  2362. xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */
  2363. /* Start the connect procedure, kernel will start working on it */
  2364. if( xResult == 0 )
  2365. {
  2366. pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE;
  2367. pxSocket->u.xTCP.ucRepCount = 0U;
  2368. FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",
  2369. pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );
  2370. /* Port on remote machine. */
  2371. pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );
  2372. /* IP address of remote machine. */
  2373. pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );
  2374. /* (client) internal state: socket wants to send a connect. */
  2375. vTCPStateChange( pxSocket, eCONNECT_SYN );
  2376. /* To start an active connect. */
  2377. pxSocket->u.xTCP.usTimeout = 1U;
  2378. if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )
  2379. {
  2380. xResult = -pdFREERTOS_ERRNO_ECANCELED;
  2381. }
  2382. }
  2383. }
  2384. return xResult;
  2385. }
  2386. #endif /* ipconfigUSE_TCP */
  2387. /*-----------------------------------------------------------*/
  2388. #if ( ipconfigUSE_TCP == 1 )
  2389. /**
  2390. * @brief Connect to a remote port.
  2391. *
  2392. * @param[in] xClientSocket: The socket initiating the connection.
  2393. * @param[in] pxAddress: The address of the remote socket.
  2394. * @param[in] xAddressLength: This parameter is not used. It is kept in
  2395. * the function signature to adhere to the Berkeley
  2396. * sockets standard.
  2397. *
  2398. * @return 0 is returned on a successful connection, else a negative
  2399. * error code is returned.
  2400. */
  2401. BaseType_t FreeRTOS_connect( Socket_t xClientSocket,
  2402. struct freertos_sockaddr * pxAddress,
  2403. socklen_t xAddressLength )
  2404. {
  2405. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xClientSocket;
  2406. TickType_t xRemainingTime;
  2407. BaseType_t xTimed = pdFALSE;
  2408. BaseType_t xResult = -pdFREERTOS_ERRNO_EINVAL;
  2409. TimeOut_t xTimeOut;
  2410. ( void ) xAddressLength;
  2411. xResult = prvTCPConnectStart( pxSocket, pxAddress );
  2412. if( xResult == 0 )
  2413. {
  2414. /* And wait for the result */
  2415. for( ; ; )
  2416. {
  2417. if( xTimed == pdFALSE )
  2418. {
  2419. /* Only in the first round, check for non-blocking */
  2420. xRemainingTime = pxSocket->xReceiveBlockTime;
  2421. if( xRemainingTime == ( TickType_t ) 0 )
  2422. {
  2423. /* Not yet connected, correct state, non-blocking. */
  2424. xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;
  2425. break;
  2426. }
  2427. /* Don't get here a second time. */
  2428. xTimed = pdTRUE;
  2429. /* Fetch the current time */
  2430. vTaskSetTimeOutState( &xTimeOut );
  2431. }
  2432. /* Did it get connected while sleeping ? */
  2433. xResult = FreeRTOS_issocketconnected( pxSocket );
  2434. /* Returns positive when connected, negative means an error */
  2435. if( xResult < 0 )
  2436. {
  2437. /* Return the error */
  2438. break;
  2439. }
  2440. if( xResult > 0 )
  2441. {
  2442. /* Socket now connected, return a zero */
  2443. xResult = 0;
  2444. break;
  2445. }
  2446. /* Is it allowed to sleep more? */
  2447. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  2448. {
  2449. xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;
  2450. break;
  2451. }
  2452. /* Go sleeping until we get any down-stream event */
  2453. ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
  2454. }
  2455. }
  2456. return xResult;
  2457. }
  2458. #endif /* ipconfigUSE_TCP */
  2459. /*-----------------------------------------------------------*/
  2460. #if ( ipconfigUSE_TCP == 1 )
  2461. /**
  2462. * @brief Accept a connection on an listening socket.
  2463. *
  2464. * @param[in] xServerSocket: The socket in listening mode.
  2465. * @param[out] pxAddress: The address of the machine trying to connect to this node
  2466. * is returned in this pointer.
  2467. * @param[out] pxAddressLength: The length of the address of the remote machine.
  2468. *
  2469. * @return FreeRTOS_accept: can return a new connected socket if the server socket
  2470. * is in listen mode and receives a connection request. The new socket will
  2471. * be bound already to the same port number as the listening socket.
  2472. */
  2473. Socket_t FreeRTOS_accept( Socket_t xServerSocket,
  2474. struct freertos_sockaddr * pxAddress,
  2475. socklen_t * pxAddressLength )
  2476. {
  2477. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;
  2478. FreeRTOS_Socket_t * pxClientSocket = NULL;
  2479. TickType_t xRemainingTime;
  2480. BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;
  2481. TimeOut_t xTimeOut;
  2482. IPStackEvent_t xAskEvent;
  2483. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
  2484. {
  2485. /* Not a valid socket or wrong type */
  2486. pxClientSocket = FREERTOS_INVALID_SOCKET;
  2487. }
  2488. else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&
  2489. ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eTCP_LISTEN ) )
  2490. {
  2491. /* Parent socket is not in listening mode */
  2492. pxClientSocket = FREERTOS_INVALID_SOCKET;
  2493. }
  2494. else
  2495. {
  2496. /* Loop will stop with breaks. */
  2497. for( ; ; )
  2498. {
  2499. /* Is there a new client? */
  2500. vTaskSuspendAll();
  2501. {
  2502. if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
  2503. {
  2504. pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;
  2505. }
  2506. else
  2507. {
  2508. pxClientSocket = pxSocket;
  2509. }
  2510. if( pxClientSocket != NULL )
  2511. {
  2512. pxSocket->u.xTCP.pxPeerSocket = NULL;
  2513. /* Is it still not taken ? */
  2514. if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )
  2515. {
  2516. pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE;
  2517. }
  2518. else
  2519. {
  2520. pxClientSocket = NULL;
  2521. }
  2522. }
  2523. }
  2524. ( void ) xTaskResumeAll();
  2525. if( pxClientSocket != NULL )
  2526. {
  2527. if( pxAddress != NULL )
  2528. {
  2529. /* IP address of remote machine. */
  2530. pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );
  2531. /* Port on remote machine. */
  2532. pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );
  2533. }
  2534. if( pxAddressLength != NULL )
  2535. {
  2536. *pxAddressLength = sizeof( *pxAddress );
  2537. }
  2538. if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )
  2539. {
  2540. xAsk = pdTRUE;
  2541. }
  2542. }
  2543. if( xAsk != pdFALSE )
  2544. {
  2545. /* Ask to set an event in 'xEventGroup' as soon as a new
  2546. * client gets connected for this listening socket. */
  2547. xAskEvent.eEventType = eTCPAcceptEvent;
  2548. xAskEvent.pvData = pxSocket;
  2549. ( void ) xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );
  2550. }
  2551. if( pxClientSocket != NULL )
  2552. {
  2553. break;
  2554. }
  2555. if( xTimed == pdFALSE )
  2556. {
  2557. /* Only in the first round, check for non-blocking */
  2558. xRemainingTime = pxSocket->xReceiveBlockTime;
  2559. if( xRemainingTime == ( TickType_t ) 0 )
  2560. {
  2561. break;
  2562. }
  2563. /* Don't get here a second time */
  2564. xTimed = pdTRUE;
  2565. /* Fetch the current time */
  2566. vTaskSetTimeOutState( &xTimeOut );
  2567. }
  2568. /* Has the timeout been reached? */
  2569. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  2570. {
  2571. break;
  2572. }
  2573. /* Go sleeping until we get any down-stream event */
  2574. ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
  2575. }
  2576. }
  2577. return pxClientSocket;
  2578. }
  2579. #endif /* ipconfigUSE_TCP */
  2580. /*-----------------------------------------------------------*/
  2581. #if ( ipconfigUSE_TCP == 1 )
  2582. /**
  2583. * @brief Read incoming data from a TCP socket. Only after the last
  2584. * byte has been read, a close error might be returned.
  2585. *
  2586. * @param[in] xSocket: The socket owning the connection.
  2587. * @param[out] pvBuffer: The buffer to store the incoming data in.
  2588. * @param[in] uxBufferLength: The length of the buffer so that the function
  2589. * does not do out of bound access.
  2590. * @param[in] xFlags: The flags for conveying preference. The values
  2591. * FREERTOS_MSG_DONTWAIT, FREERTOS_ZERO_COPY and/or
  2592. * FREERTOS_MSG_PEEK can be used.
  2593. *
  2594. * @return The number of bytes actually received and stored in the pvBuffer.
  2595. */
  2596. BaseType_t FreeRTOS_recv( Socket_t xSocket,
  2597. void * pvBuffer,
  2598. size_t uxBufferLength,
  2599. BaseType_t xFlags )
  2600. {
  2601. BaseType_t xByteCount;
  2602. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  2603. TickType_t xRemainingTime;
  2604. BaseType_t xTimed = pdFALSE;
  2605. TimeOut_t xTimeOut;
  2606. EventBits_t xEventBits = ( EventBits_t ) 0;
  2607. /* Check if the socket is valid, has type TCP and if it is bound to a
  2608. * port. */
  2609. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
  2610. {
  2611. xByteCount = -pdFREERTOS_ERRNO_EINVAL;
  2612. }
  2613. else if( ( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_ZERO_COPY ) != 0U ) &&
  2614. ( pvBuffer == NULL ) )
  2615. {
  2616. /* In zero-copy mode, pvBuffer is a pointer to a pointer ( not NULL ). */
  2617. xByteCount = -pdFREERTOS_ERRNO_EINVAL;
  2618. }
  2619. else
  2620. {
  2621. if( pxSocket->u.xTCP.rxStream != NULL )
  2622. {
  2623. xByteCount = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
  2624. }
  2625. else
  2626. {
  2627. xByteCount = 0;
  2628. }
  2629. while( xByteCount == 0 )
  2630. {
  2631. switch( ipNUMERIC_CAST( eIPTCPState_t, pxSocket->u.xTCP.ucTCPState ) )
  2632. {
  2633. case eCLOSED:
  2634. case eCLOSE_WAIT: /* (server + client) waiting for a connection termination request from the local user. */
  2635. case eCLOSING: /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
  2636. if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
  2637. {
  2638. /* The no-memory error has priority above the non-connected error.
  2639. * Both are fatal and will lead to closing the socket. */
  2640. xByteCount = -pdFREERTOS_ERRNO_ENOMEM;
  2641. }
  2642. else
  2643. {
  2644. xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;
  2645. }
  2646. break;
  2647. case eTCP_LISTEN:
  2648. case eCONNECT_SYN:
  2649. case eSYN_FIRST:
  2650. case eSYN_RECEIVED:
  2651. case eESTABLISHED:
  2652. case eFIN_WAIT_1:
  2653. case eFIN_WAIT_2:
  2654. case eLAST_ACK:
  2655. case eTIME_WAIT:
  2656. default:
  2657. /* Nothing. */
  2658. break;
  2659. }
  2660. if( xByteCount < 0 )
  2661. {
  2662. break;
  2663. }
  2664. if( xTimed == pdFALSE )
  2665. {
  2666. /* Only in the first round, check for non-blocking. */
  2667. xRemainingTime = pxSocket->xReceiveBlockTime;
  2668. if( xRemainingTime == ( TickType_t ) 0 )
  2669. {
  2670. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  2671. {
  2672. /* Just check for the interrupt flag. */
  2673. xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR,
  2674. pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );
  2675. }
  2676. #endif /* ipconfigSUPPORT_SIGNALS */
  2677. break;
  2678. }
  2679. if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
  2680. {
  2681. break;
  2682. }
  2683. /* Don't get here a second time. */
  2684. xTimed = pdTRUE;
  2685. /* Fetch the current time. */
  2686. vTaskSetTimeOutState( &xTimeOut );
  2687. }
  2688. /* Has the timeout been reached? */
  2689. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  2690. {
  2691. break;
  2692. }
  2693. /* Block until there is a down-stream event. */
  2694. xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,
  2695. ( EventBits_t ) eSOCKET_RECEIVE | ( EventBits_t ) eSOCKET_CLOSED | ( EventBits_t ) eSOCKET_INTR,
  2696. pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
  2697. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  2698. {
  2699. if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
  2700. {
  2701. break;
  2702. }
  2703. }
  2704. #else
  2705. {
  2706. ( void ) xEventBits;
  2707. }
  2708. #endif /* ipconfigSUPPORT_SIGNALS */
  2709. if( pxSocket->u.xTCP.rxStream != NULL )
  2710. {
  2711. xByteCount = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
  2712. }
  2713. else
  2714. {
  2715. xByteCount = 0;
  2716. }
  2717. }
  2718. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  2719. if( ( xEventBits & ( EventBits_t ) eSOCKET_INTR ) != 0U )
  2720. {
  2721. if( ( xEventBits & ( ( EventBits_t ) eSOCKET_RECEIVE | ( EventBits_t ) eSOCKET_CLOSED ) ) != 0U )
  2722. {
  2723. /* Shouldn't have cleared other flags. */
  2724. xEventBits &= ~( ( EventBits_t ) eSOCKET_INTR );
  2725. ( void ) xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );
  2726. }
  2727. xByteCount = -pdFREERTOS_ERRNO_EINTR;
  2728. }
  2729. else
  2730. #endif /* ipconfigSUPPORT_SIGNALS */
  2731. if( xByteCount > 0 )
  2732. {
  2733. if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_ZERO_COPY ) == 0U )
  2734. {
  2735. BaseType_t xIsPeek = ( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_PEEK ) != 0U ) ? 1L : 0L;
  2736. xByteCount = ( BaseType_t )
  2737. uxStreamBufferGet( pxSocket->u.xTCP.rxStream,
  2738. 0UL,
  2739. ipPOINTER_CAST( uint8_t *, pvBuffer ),
  2740. ( size_t ) uxBufferLength,
  2741. xIsPeek );
  2742. if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )
  2743. {
  2744. /* We had reached the low-water mark, now see if the flag
  2745. * can be cleared */
  2746. size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
  2747. if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )
  2748. {
  2749. pxSocket->u.xTCP.bits.bLowWater = pdFALSE;
  2750. pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
  2751. pxSocket->u.xTCP.usTimeout = 1U; /* because bLowWater is cleared. */
  2752. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  2753. }
  2754. }
  2755. }
  2756. else
  2757. {
  2758. /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */
  2759. xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, ipPOINTER_CAST( uint8_t * *, pvBuffer ) );
  2760. }
  2761. }
  2762. else
  2763. {
  2764. /* Nothing. */
  2765. }
  2766. } /* prvValidSocket() */
  2767. return xByteCount;
  2768. }
  2769. #endif /* ipconfigUSE_TCP */
  2770. /*-----------------------------------------------------------*/
  2771. #if ( ipconfigUSE_TCP == 1 )
  2772. /**
  2773. * @brief Called from FreeRTOS_send(): some checks which will be done before
  2774. * sending a TCP packed.
  2775. *
  2776. * @param[in] pxSocket: The socket owning the connection.
  2777. * @param[in] uxDataLength: The length of the data to be sent.
  2778. *
  2779. * @return 0: representing OK, else a negative error code will be returned.
  2780. */
  2781. static int32_t prvTCPSendCheck( FreeRTOS_Socket_t * pxSocket,
  2782. size_t uxDataLength )
  2783. {
  2784. int32_t xResult = 1;
  2785. /* Is this a socket of type TCP and is it already bound to a port number ? */
  2786. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
  2787. {
  2788. xResult = -pdFREERTOS_ERRNO_EINVAL;
  2789. }
  2790. else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )
  2791. {
  2792. xResult = -pdFREERTOS_ERRNO_ENOMEM;
  2793. }
  2794. else if( ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSED ) ||
  2795. ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSE_WAIT ) ||
  2796. ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSING ) )
  2797. {
  2798. xResult = -pdFREERTOS_ERRNO_ENOTCONN;
  2799. }
  2800. else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
  2801. {
  2802. /* This TCP connection is closing already, the FIN flag has been sent.
  2803. * Maybe it is still delivering or receiving data.
  2804. * Return OK in order not to get closed/deleted too quickly */
  2805. xResult = 0;
  2806. }
  2807. else if( uxDataLength == 0UL )
  2808. {
  2809. /* send() is being called to send zero bytes */
  2810. xResult = 0;
  2811. }
  2812. else if( pxSocket->u.xTCP.txStream == NULL )
  2813. {
  2814. /* Create the outgoing stream only when it is needed */
  2815. ( void ) prvTCPCreateStream( pxSocket, pdFALSE );
  2816. if( pxSocket->u.xTCP.txStream == NULL )
  2817. {
  2818. xResult = -pdFREERTOS_ERRNO_ENOMEM;
  2819. }
  2820. }
  2821. else
  2822. {
  2823. /* Nothing. */
  2824. }
  2825. return xResult;
  2826. }
  2827. #endif /* ipconfigUSE_TCP */
  2828. /*-----------------------------------------------------------*/
  2829. #if ( ipconfigUSE_TCP == 1 )
  2830. /**
  2831. * @brief Get a direct pointer to the circular transmit buffer.
  2832. *
  2833. * @param[in] xSocket: The socket owning the buffer.
  2834. * @param[in] pxLength: This will contain the number of bytes that may be written.
  2835. *
  2836. * @return Head of the circular transmit buffer if all checks pass. Or else, NULL
  2837. * is returned.
  2838. */
  2839. uint8_t * FreeRTOS_get_tx_head( ConstSocket_t xSocket,
  2840. BaseType_t * pxLength )
  2841. {
  2842. uint8_t * pucReturn = NULL;
  2843. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  2844. StreamBuffer_t * pxBuffer = NULL;
  2845. *pxLength = 0;
  2846. /* Confirm that this is a TCP socket before dereferencing structure
  2847. * member pointers. */
  2848. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
  2849. {
  2850. pxBuffer = pxSocket->u.xTCP.txStream;
  2851. if( pxBuffer != NULL )
  2852. {
  2853. BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );
  2854. BaseType_t xRemain = ( BaseType_t ) pxBuffer->LENGTH - ( BaseType_t ) pxBuffer->uxHead;
  2855. *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );
  2856. pucReturn = &( pxBuffer->ucArray[ pxBuffer->uxHead ] );
  2857. }
  2858. }
  2859. return pucReturn;
  2860. }
  2861. #endif /* ipconfigUSE_TCP */
  2862. /*-----------------------------------------------------------*/
  2863. #if ( ipconfigUSE_TCP == 1 )
  2864. /**
  2865. * @brief Send data using a TCP socket. It is not necessary to have the socket
  2866. * connected already. Outgoing data will be stored and delivered as soon as
  2867. * the socket gets connected.
  2868. *
  2869. * @param[in] xSocket: The socket owning the connection.
  2870. * @param[in] pvBuffer: The buffer containing the data.
  2871. * @param[in] uxDataLength: The length of the data to be added.
  2872. * @param[in] xFlags: This parameter is not used. (zero or FREERTOS_MSG_DONTWAIT).
  2873. *
  2874. * @return The number of bytes actually sent. Zero when nothing could be sent
  2875. * or a negative error code in case an error occurred.
  2876. */
  2877. BaseType_t FreeRTOS_send( Socket_t xSocket,
  2878. const void * pvBuffer,
  2879. size_t uxDataLength,
  2880. BaseType_t xFlags )
  2881. {
  2882. BaseType_t xByteCount = -pdFREERTOS_ERRNO_EINVAL;
  2883. BaseType_t xBytesLeft;
  2884. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  2885. TickType_t xRemainingTime;
  2886. BaseType_t xTimed = pdFALSE;
  2887. TimeOut_t xTimeOut;
  2888. BaseType_t xCloseAfterSend;
  2889. const uint8_t * pucSource = ipPOINTER_CAST( const uint8_t *, pvBuffer );
  2890. /* Prevent compiler warnings about unused parameters. The parameter
  2891. * may be used in future versions. */
  2892. ( void ) xFlags;
  2893. if( pvBuffer != NULL )
  2894. {
  2895. xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );
  2896. }
  2897. if( xByteCount > 0 )
  2898. {
  2899. /* xBytesLeft is number of bytes to send, will count to zero. */
  2900. xBytesLeft = ( BaseType_t ) uxDataLength;
  2901. /* xByteCount is number of bytes that can be sent now. */
  2902. xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
  2903. /* While there are still bytes to be sent. */
  2904. while( xBytesLeft > 0 )
  2905. {
  2906. /* If txStream has space. */
  2907. if( xByteCount > 0 )
  2908. {
  2909. /* Don't send more than necessary. */
  2910. if( xByteCount > xBytesLeft )
  2911. {
  2912. xByteCount = xBytesLeft;
  2913. }
  2914. /* Is the close-after-send flag set and is this really the
  2915. * last transmission? */
  2916. if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )
  2917. {
  2918. xCloseAfterSend = pdTRUE;
  2919. }
  2920. else
  2921. {
  2922. xCloseAfterSend = pdFALSE;
  2923. }
  2924. /* The flag 'bCloseAfterSend' can be set before sending data
  2925. * using setsockopt()
  2926. *
  2927. * When the last data packet is being sent out, a FIN flag will
  2928. * be included to let the peer know that no more data is to be
  2929. * expected. The use of 'bCloseAfterSend' is not mandatory, it
  2930. * is just a faster way of transferring files (e.g. when using
  2931. * FTP). */
  2932. if( xCloseAfterSend != pdFALSE )
  2933. {
  2934. /* Now suspend the scheduler: sending the last data and
  2935. * setting bCloseRequested must be done together */
  2936. vTaskSuspendAll();
  2937. pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE;
  2938. }
  2939. xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0UL, pucSource, ( size_t ) xByteCount );
  2940. if( xCloseAfterSend != pdFALSE )
  2941. {
  2942. /* Now when the IP-task transmits the data, it will also
  2943. * see that bCloseRequested is true and include the FIN
  2944. * flag to start closure of the connection. */
  2945. ( void ) xTaskResumeAll();
  2946. }
  2947. /* Send a message to the IP-task so it can work on this
  2948. * socket. Data is sent, let the IP-task work on it. */
  2949. pxSocket->u.xTCP.usTimeout = 1U;
  2950. if( xIsCallingFromIPTask() == pdFALSE )
  2951. {
  2952. /* Only send a TCP timer event when not called from the
  2953. * IP-task. */
  2954. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  2955. }
  2956. xBytesLeft -= xByteCount;
  2957. if( xBytesLeft == 0 )
  2958. {
  2959. break;
  2960. }
  2961. /* As there are still bytes left to be sent, increase the
  2962. * data pointer. */
  2963. pucSource = &( pucSource[ xByteCount ] );
  2964. }
  2965. /* Not all bytes have been sent. In case the socket is marked as
  2966. * blocking sleep for a while. */
  2967. if( xTimed == pdFALSE )
  2968. {
  2969. /* Only in the first round, check for non-blocking. */
  2970. xRemainingTime = pxSocket->xSendBlockTime;
  2971. #if ( ipconfigUSE_CALLBACKS != 0 )
  2972. {
  2973. if( xIsCallingFromIPTask() != pdFALSE )
  2974. {
  2975. /* If this send function is called from within a
  2976. * call-back handler it may not block, otherwise
  2977. * chances would be big to get a deadlock: the IP-task
  2978. * waiting for itself. */
  2979. xRemainingTime = ( TickType_t ) 0;
  2980. }
  2981. }
  2982. #endif /* ipconfigUSE_CALLBACKS */
  2983. if( xRemainingTime == ( TickType_t ) 0 )
  2984. {
  2985. break;
  2986. }
  2987. if( ( ( uint32_t ) xFlags & ( uint32_t ) FREERTOS_MSG_DONTWAIT ) != 0U )
  2988. {
  2989. break;
  2990. }
  2991. /* Don't get here a second time. */
  2992. xTimed = pdTRUE;
  2993. /* Fetch the current time. */
  2994. vTaskSetTimeOutState( &xTimeOut );
  2995. }
  2996. else
  2997. {
  2998. /* Has the timeout been reached? */
  2999. if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )
  3000. {
  3001. break;
  3002. }
  3003. }
  3004. /* Go sleeping until down-stream events are received. */
  3005. ( void ) xEventGroupWaitBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_SEND | ( EventBits_t ) eSOCKET_CLOSED,
  3006. pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );
  3007. xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
  3008. }
  3009. /* How much was actually sent? */
  3010. xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;
  3011. if( xByteCount == 0 )
  3012. {
  3013. if( pxSocket->u.xTCP.ucTCPState > ( uint8_t ) eESTABLISHED )
  3014. {
  3015. xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;
  3016. }
  3017. else
  3018. {
  3019. if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) )
  3020. {
  3021. FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",
  3022. pxSocket->usLocalPort,
  3023. pxSocket->u.xTCP.ulRemoteIP,
  3024. pxSocket->u.xTCP.usRemotePort ) );
  3025. }
  3026. xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;
  3027. }
  3028. }
  3029. }
  3030. return xByteCount;
  3031. }
  3032. #endif /* ipconfigUSE_TCP */
  3033. /*-----------------------------------------------------------*/
  3034. #if ( ipconfigUSE_TCP == 1 )
  3035. /**
  3036. * @brief Request to put a socket in listen mode.
  3037. *
  3038. * @param[in] xSocket: the socket to be put in listening mode.
  3039. * @param[in] xBacklog: Maximum number of child sockets.
  3040. *
  3041. * @return 0 in case of success, or else a negative error code is
  3042. * returned.
  3043. */
  3044. BaseType_t FreeRTOS_listen( Socket_t xSocket,
  3045. BaseType_t xBacklog )
  3046. {
  3047. FreeRTOS_Socket_t * pxSocket;
  3048. BaseType_t xResult = 0;
  3049. pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  3050. /* listen() is allowed for a valid TCP socket in Closed state and already
  3051. * bound. */
  3052. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
  3053. {
  3054. xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
  3055. }
  3056. else if( ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eCLOSE_WAIT ) )
  3057. {
  3058. /* Socket is in a wrong state. */
  3059. xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
  3060. }
  3061. else
  3062. {
  3063. /* Backlog is interpreted here as "the maximum number of child
  3064. * sockets. */
  3065. pxSocket->u.xTCP.usBacklog = ( uint16_t ) FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );
  3066. /* This cleaning is necessary only if a listening socket is being
  3067. * reused as it might have had a previous connection. */
  3068. if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
  3069. {
  3070. if( pxSocket->u.xTCP.rxStream != NULL )
  3071. {
  3072. vStreamBufferClear( pxSocket->u.xTCP.rxStream );
  3073. }
  3074. if( pxSocket->u.xTCP.txStream != NULL )
  3075. {
  3076. vStreamBufferClear( pxSocket->u.xTCP.txStream );
  3077. }
  3078. ( void ) memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, 0, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );
  3079. ( void ) memset( &pxSocket->u.xTCP.xTCPWindow, 0, sizeof( pxSocket->u.xTCP.xTCPWindow ) );
  3080. ( void ) memset( &pxSocket->u.xTCP.bits, 0, sizeof( pxSocket->u.xTCP.bits ) );
  3081. /* Now set the bReuseSocket flag again, because the bits have
  3082. * just been cleared. */
  3083. pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE;
  3084. }
  3085. vTCPStateChange( pxSocket, eTCP_LISTEN );
  3086. }
  3087. return xResult;
  3088. }
  3089. #endif /* ipconfigUSE_TCP */
  3090. /*-----------------------------------------------------------*/
  3091. #if ( ipconfigUSE_TCP == 1 )
  3092. /**
  3093. * @brief Shutdown - This function will shut down the connection in both
  3094. * directions. However, it will first deliver all data queued for
  3095. * transmission, and also it will first wait to receive any missing
  3096. * packets from the peer.
  3097. *
  3098. * @param[in] xSocket: The socket owning the connection.
  3099. * @param[in] xHow: Not used. Just present to stick to Berkeley standard.
  3100. *
  3101. * @return 0 on successful shutdown or else a negative error code.
  3102. */
  3103. BaseType_t FreeRTOS_shutdown( Socket_t xSocket,
  3104. BaseType_t xHow )
  3105. {
  3106. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  3107. BaseType_t xResult;
  3108. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )
  3109. {
  3110. /*_RB_ Is this comment correct? The socket is not of a type that
  3111. * supports the listen() operation. */
  3112. xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
  3113. }
  3114. else if( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eESTABLISHED )
  3115. {
  3116. /*_RB_ Is this comment correct? The socket is not of a type that
  3117. * supports the listen() operation. */
  3118. xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;
  3119. }
  3120. else
  3121. {
  3122. pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;
  3123. /* Let the IP-task perform the shutdown of the connection. */
  3124. pxSocket->u.xTCP.usTimeout = 1U;
  3125. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  3126. xResult = 0;
  3127. }
  3128. ( void ) xHow;
  3129. return xResult;
  3130. }
  3131. #endif /* ipconfigUSE_TCP */
  3132. /*-----------------------------------------------------------*/
  3133. #if ( ipconfigUSE_TCP == 1 )
  3134. /**
  3135. * @brief A TCP timer has expired, now check all TCP sockets for:
  3136. * - Active connect
  3137. * - Send a delayed ACK
  3138. * - Send new data
  3139. * - Send a keep-alive packet
  3140. * - Check for timeout (in non-connected states only)
  3141. *
  3142. * @param[in] xWillSleep: Whether the calling task is going to sleep.
  3143. *
  3144. * @return Minimum amount of time before the timer shall expire.
  3145. */
  3146. TickType_t xTCPTimerCheck( BaseType_t xWillSleep )
  3147. {
  3148. FreeRTOS_Socket_t * pxSocket;
  3149. TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );
  3150. TickType_t xNow = xTaskGetTickCount();
  3151. static TickType_t xLastTime = 0U;
  3152. TickType_t xDelta = xNow - xLastTime;
  3153. const ListItem_t * pxEnd = listGET_END_MARKER( &xBoundTCPSocketsList );
  3154. const ListItem_t * pxIterator = ( const ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
  3155. xLastTime = xNow;
  3156. if( xDelta == 0U )
  3157. {
  3158. xDelta = 1U;
  3159. }
  3160. while( pxIterator != pxEnd )
  3161. {
  3162. pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  3163. pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );
  3164. /* Sockets with 'timeout == 0' do not need any regular attention. */
  3165. if( pxSocket->u.xTCP.usTimeout == 0U )
  3166. {
  3167. continue;
  3168. }
  3169. if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )
  3170. {
  3171. pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );
  3172. }
  3173. else
  3174. {
  3175. BaseType_t xRc;
  3176. pxSocket->u.xTCP.usTimeout = 0U;
  3177. xRc = xTCPSocketCheck( pxSocket );
  3178. /* Within this function, the socket might want to send a delayed
  3179. * ack or send out data or whatever it needs to do. */
  3180. if( xRc < 0 )
  3181. {
  3182. /* Continue because the socket was deleted. */
  3183. continue;
  3184. }
  3185. }
  3186. /* In xEventBits the driver may indicate that the socket has
  3187. * important events for the user. These are only done just before the
  3188. * IP-task goes to sleep. */
  3189. if( pxSocket->xEventBits != 0U )
  3190. {
  3191. if( xWillSleep != pdFALSE )
  3192. {
  3193. /* The IP-task is about to go to sleep, so messages can be
  3194. * sent to the socket owners. */
  3195. vSocketWakeUpUser( pxSocket );
  3196. }
  3197. else
  3198. {
  3199. /* Or else make sure this will be called again to wake-up
  3200. * the sockets' owner. */
  3201. xShortest = ( TickType_t ) 0;
  3202. }
  3203. }
  3204. if( ( pxSocket->u.xTCP.usTimeout != 0U ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )
  3205. {
  3206. xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;
  3207. }
  3208. }
  3209. return xShortest;
  3210. }
  3211. #endif /* ipconfigUSE_TCP */
  3212. /*-----------------------------------------------------------*/
  3213. #if ( ipconfigUSE_TCP == 1 )
  3214. /**
  3215. * @brief As multiple sockets may be bound to the same local port number
  3216. * looking up a socket is a little more complex: Both a local port,
  3217. * and a remote port and IP address are being used to find a match.
  3218. * For a socket in listening mode, the remote port and IP address
  3219. * are both 0.
  3220. *
  3221. * @param[in] ulLocalIP: Local IP address. Ignored for now.
  3222. * @param[in] uxLocalPort: Local port number.
  3223. * @param[in] ulRemoteIP: Remote (peer) IP address.
  3224. * @param[in] uxRemotePort: Remote (peer) port.
  3225. *
  3226. * @return The socket which was found.
  3227. */
  3228. FreeRTOS_Socket_t * pxTCPSocketLookup( uint32_t ulLocalIP,
  3229. UBaseType_t uxLocalPort,
  3230. uint32_t ulRemoteIP,
  3231. UBaseType_t uxRemotePort )
  3232. {
  3233. const ListItem_t * pxIterator;
  3234. FreeRTOS_Socket_t * pxResult = NULL, * pxListenSocket = NULL;
  3235. const ListItem_t * pxEnd = listGET_END_MARKER( &xBoundTCPSocketsList );
  3236. /* Parameter not yet supported. */
  3237. ( void ) ulLocalIP;
  3238. for( pxIterator = listGET_NEXT( pxEnd );
  3239. pxIterator != pxEnd;
  3240. pxIterator = listGET_NEXT( pxIterator ) )
  3241. {
  3242. FreeRTOS_Socket_t * pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  3243. if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )
  3244. {
  3245. if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
  3246. {
  3247. /* If this is a socket listening to uxLocalPort, remember it
  3248. * in case there is no perfect match. */
  3249. pxListenSocket = pxSocket;
  3250. }
  3251. else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )
  3252. {
  3253. /* For sockets not in listening mode, find a match with
  3254. * xLocalPort, ulRemoteIP AND xRemotePort. */
  3255. pxResult = pxSocket;
  3256. break;
  3257. }
  3258. else
  3259. {
  3260. /* This 'pxSocket' doesn't match. */
  3261. }
  3262. }
  3263. }
  3264. if( pxResult == NULL )
  3265. {
  3266. /* An exact match was not found, maybe a listening socket was
  3267. * found. */
  3268. pxResult = pxListenSocket;
  3269. }
  3270. return pxResult;
  3271. }
  3272. #endif /* ipconfigUSE_TCP */
  3273. /*-----------------------------------------------------------*/
  3274. #if ( ipconfigUSE_TCP == 1 )
  3275. /**
  3276. * @brief For the web server: borrow the circular Rx buffer for inspection.
  3277. * HTML driver wants to see if a sequence of 13/10/13/10 is available.
  3278. *
  3279. * @param[in] xSocket: The socket whose Rx stream is to be returned.
  3280. *
  3281. * @return The Rx stream of the socket if all checks pass, else NULL.
  3282. */
  3283. const struct xSTREAM_BUFFER * FreeRTOS_get_rx_buf( ConstSocket_t xSocket )
  3284. {
  3285. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3286. const struct xSTREAM_BUFFER * pxReturn = NULL;
  3287. /* Confirm that this is a TCP socket before dereferencing structure
  3288. * member pointers. */
  3289. if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdTRUE )
  3290. {
  3291. pxReturn = pxSocket->u.xTCP.rxStream;
  3292. }
  3293. return pxReturn;
  3294. }
  3295. #endif /* ipconfigUSE_TCP */
  3296. /*-----------------------------------------------------------*/
  3297. #if ( ipconfigUSE_TCP == 1 )
  3298. /**
  3299. * @brief Create the stream buffer for the given socket.
  3300. *
  3301. * @param[in] pxSocket: the socket to create the stream for.
  3302. * @param[in] xIsInputStream: Is this input stream? pdTRUE/pdFALSE?
  3303. *
  3304. * @return The stream buffer.
  3305. */
  3306. static StreamBuffer_t * prvTCPCreateStream( FreeRTOS_Socket_t * pxSocket,
  3307. BaseType_t xIsInputStream )
  3308. {
  3309. StreamBuffer_t * pxBuffer;
  3310. size_t uxLength;
  3311. size_t uxSize;
  3312. /* Now that a stream is created, the maximum size is fixed before
  3313. * creation, it could still be changed with setsockopt(). */
  3314. if( xIsInputStream != pdFALSE )
  3315. {
  3316. uxLength = pxSocket->u.xTCP.uxRxStreamSize;
  3317. if( pxSocket->u.xTCP.uxLittleSpace == 0UL )
  3318. {
  3319. pxSocket->u.xTCP.uxLittleSpace = ( sock20_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
  3320. }
  3321. if( pxSocket->u.xTCP.uxEnoughSpace == 0UL )
  3322. {
  3323. pxSocket->u.xTCP.uxEnoughSpace = ( sock80_PERCENT * pxSocket->u.xTCP.uxRxStreamSize ) / sock100_PERCENT;
  3324. }
  3325. }
  3326. else
  3327. {
  3328. uxLength = pxSocket->u.xTCP.uxTxStreamSize;
  3329. }
  3330. /* Add an extra 4 (or 8) bytes. */
  3331. uxLength += sizeof( size_t );
  3332. /* And make the length a multiple of sizeof( size_t ). */
  3333. uxLength &= ~( sizeof( size_t ) - 1U );
  3334. uxSize = ( sizeof( *pxBuffer ) + uxLength ) - sizeof( pxBuffer->ucArray );
  3335. pxBuffer = ipCAST_PTR_TO_TYPE_PTR( StreamBuffer_t, pvPortMallocLarge( uxSize ) );
  3336. if( pxBuffer == NULL )
  3337. {
  3338. FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );
  3339. pxSocket->u.xTCP.bits.bMallocError = pdTRUE;
  3340. vTCPStateChange( pxSocket, eCLOSE_WAIT );
  3341. }
  3342. else
  3343. {
  3344. /* Clear the markers of the stream */
  3345. ( void ) memset( pxBuffer, 0, sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );
  3346. pxBuffer->LENGTH = ( size_t ) uxLength;
  3347. if( xTCPWindowLoggingLevel != 0 )
  3348. {
  3349. FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %u bytes (total %u)\n", ( xIsInputStream != 0 ) ? 'R' : 'T', uxLength, uxSize ) );
  3350. }
  3351. if( xIsInputStream != 0 )
  3352. {
  3353. iptraceMEM_STATS_CREATE( tcpRX_STREAM_BUFFER, pxBuffer, uxSize );
  3354. pxSocket->u.xTCP.rxStream = pxBuffer;
  3355. }
  3356. else
  3357. {
  3358. iptraceMEM_STATS_CREATE( tcpTX_STREAM_BUFFER, pxBuffer, uxSize );
  3359. pxSocket->u.xTCP.txStream = pxBuffer;
  3360. }
  3361. }
  3362. return pxBuffer;
  3363. }
  3364. #endif /* ipconfigUSE_TCP */
  3365. /*-----------------------------------------------------------*/
  3366. #if ( ipconfigUSE_TCP == 1 )
  3367. /**
  3368. * @brief Add data to the RxStream. When uxOffset > 0, data has come in out-of-order
  3369. * and will be put in front of the head so it can not be popped by the user.
  3370. *
  3371. * @param[in] pxSocket: The socket to whose RxStream data is to be added.
  3372. * @param[in] uxOffset: Offset of the packet.
  3373. * @param[in] pcData: The data to be added to the RxStream.
  3374. * @param[in] ulByteCount: Number of bytes in the data.
  3375. *
  3376. * @return The number of bytes actually added to the RxStream. Or else, a negative
  3377. * error code is returned.
  3378. */
  3379. int32_t lTCPAddRxdata( FreeRTOS_Socket_t * pxSocket,
  3380. size_t uxOffset,
  3381. const uint8_t * pcData,
  3382. uint32_t ulByteCount )
  3383. {
  3384. StreamBuffer_t * pxStream = pxSocket->u.xTCP.rxStream;
  3385. int32_t xResult = 0;
  3386. #if ( ipconfigUSE_CALLBACKS == 1 )
  3387. BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive ) ? pdTRUE : pdFALSE;
  3388. const uint8_t * pucBuffer = NULL;
  3389. #endif /* ipconfigUSE_CALLBACKS */
  3390. /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )
  3391. * if( pucData != NULL ) copy data the the buffer
  3392. * if( pucData == NULL ) no copying, just advance rxHead
  3393. * if( uxOffset != 0 ) Just store data which has come out-of-order
  3394. * if( uxOffset == 0 ) Also advance rxHead */
  3395. if( pxStream == NULL )
  3396. {
  3397. pxStream = prvTCPCreateStream( pxSocket, pdTRUE );
  3398. if( pxStream == NULL )
  3399. {
  3400. xResult = -1;
  3401. }
  3402. }
  3403. if( xResult >= 0 )
  3404. {
  3405. #if ( ipconfigUSE_CALLBACKS == 1 )
  3406. {
  3407. if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0U ) && ( uxOffset == 0UL ) && ( pcData != NULL ) )
  3408. {
  3409. /* Data can be passed directly to the user */
  3410. pucBuffer = pcData;
  3411. pcData = NULL;
  3412. }
  3413. }
  3414. #endif /* ipconfigUSE_CALLBACKS */
  3415. xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );
  3416. #if ( ipconfigHAS_DEBUG_PRINTF != 0 )
  3417. {
  3418. if( xResult != ( int32_t ) ulByteCount )
  3419. {
  3420. FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %u: %d/%u bytes (tail %u head %u space %u front %u)\n",
  3421. ( UBaseType_t ) uxOffset,
  3422. ( BaseType_t ) xResult,
  3423. ( UBaseType_t ) ulByteCount,
  3424. ( UBaseType_t ) pxStream->uxTail,
  3425. ( UBaseType_t ) pxStream->uxHead,
  3426. ( UBaseType_t ) uxStreamBufferFrontSpace( pxStream ),
  3427. ( UBaseType_t ) pxStream->uxFront ) );
  3428. }
  3429. }
  3430. #endif /* ipconfigHAS_DEBUG_PRINTF */
  3431. if( uxOffset == 0U )
  3432. {
  3433. /* Data is being added to rxStream at the head (offs = 0) */
  3434. #if ( ipconfigUSE_CALLBACKS == 1 )
  3435. if( bHasHandler != pdFALSE )
  3436. {
  3437. /* The socket owner has installed an OnReceive handler. Pass the
  3438. * Rx data, without copying from the rxStream, to the user. */
  3439. for( ; ; )
  3440. {
  3441. uint8_t * ucReadPtr = NULL;
  3442. uint32_t ulCount;
  3443. if( pucBuffer != NULL )
  3444. {
  3445. ucReadPtr = ipPOINTER_CAST( uint8_t *, pucBuffer );
  3446. ulCount = ulByteCount;
  3447. pucBuffer = NULL;
  3448. }
  3449. else
  3450. {
  3451. ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );
  3452. }
  3453. if( ulCount == 0UL )
  3454. {
  3455. break;
  3456. }
  3457. ( void ) pxSocket->u.xTCP.pxHandleReceive( pxSocket, ucReadPtr, ( size_t ) ulCount );
  3458. ( void ) uxStreamBufferGet( pxStream, 0UL, NULL, ( size_t ) ulCount, pdFALSE );
  3459. }
  3460. }
  3461. else
  3462. #endif /* ipconfigUSE_CALLBACKS */
  3463. {
  3464. /* See if running out of space. */
  3465. if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )
  3466. {
  3467. size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );
  3468. if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace )
  3469. {
  3470. pxSocket->u.xTCP.bits.bLowWater = pdTRUE;
  3471. pxSocket->u.xTCP.bits.bWinChange = pdTRUE;
  3472. /* bLowWater was reached, send the changed window size. */
  3473. pxSocket->u.xTCP.usTimeout = 1U;
  3474. ( void ) xSendEventToIPTask( eTCPTimerEvent );
  3475. }
  3476. }
  3477. /* New incoming data is available, wake up the user. User's
  3478. * semaphores will be set just before the IP-task goes asleep. */
  3479. pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_RECEIVE;
  3480. #if ipconfigSUPPORT_SELECT_FUNCTION == 1
  3481. {
  3482. if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != 0U )
  3483. {
  3484. pxSocket->xEventBits |= ( ( ( EventBits_t ) eSELECT_READ ) << SOCKET_EVENT_BIT_COUNT );
  3485. }
  3486. }
  3487. #endif
  3488. }
  3489. }
  3490. }
  3491. return xResult;
  3492. }
  3493. #endif /* ipconfigUSE_TCP */
  3494. /*-----------------------------------------------------------*/
  3495. #if ( ipconfigUSE_TCP == 1 )
  3496. /**
  3497. * @brief Function to get the remote IP-address and port number.
  3498. *
  3499. * @param[in] xSocket: Socket owning the connection.
  3500. * @param[out] pxAddress: The address pointer to which the address
  3501. * is to be added.
  3502. *
  3503. * @return The size of the address being returned. Or else a negative
  3504. * error code will be returned.
  3505. */
  3506. BaseType_t FreeRTOS_GetRemoteAddress( ConstSocket_t xSocket,
  3507. struct freertos_sockaddr * pxAddress )
  3508. {
  3509. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3510. BaseType_t xResult;
  3511. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3512. {
  3513. xResult = -pdFREERTOS_ERRNO_EINVAL;
  3514. }
  3515. else
  3516. {
  3517. /* BSD style sockets communicate IP and port addresses in network
  3518. * byte order.
  3519. * IP address of remote machine. */
  3520. pxAddress->sin_addr = FreeRTOS_htonl( pxSocket->u.xTCP.ulRemoteIP );
  3521. /* Port on remote machine. */
  3522. pxAddress->sin_port = FreeRTOS_htons( pxSocket->u.xTCP.usRemotePort );
  3523. xResult = ( BaseType_t ) sizeof( *pxAddress );
  3524. }
  3525. return xResult;
  3526. }
  3527. #endif /* ipconfigUSE_TCP */
  3528. /*-----------------------------------------------------------*/
  3529. #if ( ipconfigUSE_TCP == 1 )
  3530. /**
  3531. * @brief Check the number of bytes that may be added to txStream.
  3532. *
  3533. * @param[in] xSocket: The socket to be checked.
  3534. *
  3535. * @return the number of bytes that may be added to txStream or
  3536. * else a negative error code.
  3537. */
  3538. BaseType_t FreeRTOS_maywrite( ConstSocket_t xSocket )
  3539. {
  3540. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3541. BaseType_t xResult;
  3542. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3543. {
  3544. xResult = -pdFREERTOS_ERRNO_EINVAL;
  3545. }
  3546. else if( pxSocket->u.xTCP.ucTCPState != ( uint8_t ) eESTABLISHED )
  3547. {
  3548. if( ( pxSocket->u.xTCP.ucTCPState < ( uint8_t ) eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > ( EventBits_t ) eESTABLISHED ) )
  3549. {
  3550. xResult = -1;
  3551. }
  3552. else
  3553. {
  3554. xResult = 0;
  3555. }
  3556. }
  3557. else if( pxSocket->u.xTCP.txStream == NULL )
  3558. {
  3559. xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
  3560. }
  3561. else
  3562. {
  3563. xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
  3564. }
  3565. return xResult;
  3566. }
  3567. #endif /* ipconfigUSE_TCP */
  3568. /*-----------------------------------------------------------*/
  3569. #if ( ipconfigUSE_TCP == 1 )
  3570. /**
  3571. * @brief Get the number of bytes that can be written in the Tx buffer
  3572. * of the given socket.
  3573. *
  3574. * @param[in] xSocket: the socket to be checked.
  3575. *
  3576. * @return The bytes that can be written. Or else an error code.
  3577. */
  3578. BaseType_t FreeRTOS_tx_space( ConstSocket_t xSocket )
  3579. {
  3580. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3581. BaseType_t xReturn;
  3582. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3583. {
  3584. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3585. }
  3586. else
  3587. {
  3588. if( pxSocket->u.xTCP.txStream != NULL )
  3589. {
  3590. xReturn = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );
  3591. }
  3592. else
  3593. {
  3594. xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;
  3595. }
  3596. }
  3597. return xReturn;
  3598. }
  3599. #endif /* ipconfigUSE_TCP */
  3600. /*-----------------------------------------------------------*/
  3601. #if ( ipconfigUSE_TCP == 1 )
  3602. /**
  3603. * @brief Returns the number of bytes stored in the Tx buffer.
  3604. *
  3605. * @param[in] xSocket: The socket to be checked.
  3606. *
  3607. * @return The number of bytes stored in the Tx buffer of the socket.
  3608. * Or an error code.
  3609. */
  3610. BaseType_t FreeRTOS_tx_size( ConstSocket_t xSocket )
  3611. {
  3612. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3613. BaseType_t xReturn;
  3614. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3615. {
  3616. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3617. }
  3618. else
  3619. {
  3620. if( pxSocket->u.xTCP.txStream != NULL )
  3621. {
  3622. xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.txStream );
  3623. }
  3624. else
  3625. {
  3626. xReturn = 0;
  3627. }
  3628. }
  3629. return xReturn;
  3630. }
  3631. #endif /* ipconfigUSE_TCP */
  3632. /*-----------------------------------------------------------*/
  3633. #if ( ipconfigUSE_TCP == 1 )
  3634. /**
  3635. * @brief Is the socket connected.
  3636. *
  3637. * @param[in] xSocket: The socket being checked.
  3638. *
  3639. * @return pdTRUE if TCP socket is connected.
  3640. */
  3641. BaseType_t FreeRTOS_issocketconnected( ConstSocket_t xSocket )
  3642. {
  3643. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3644. BaseType_t xReturn = pdFALSE;
  3645. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3646. {
  3647. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3648. }
  3649. else
  3650. {
  3651. if( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED )
  3652. {
  3653. if( pxSocket->u.xTCP.ucTCPState < ( uint8_t ) eCLOSE_WAIT )
  3654. {
  3655. xReturn = pdTRUE;
  3656. }
  3657. }
  3658. }
  3659. return xReturn;
  3660. }
  3661. #endif /* ipconfigUSE_TCP */
  3662. /*-----------------------------------------------------------*/
  3663. #if ( ipconfigUSE_TCP == 1 )
  3664. /**
  3665. * @brief Get the actual value of Maximum Segment Size ( MSS ) being used.
  3666. *
  3667. * @param[in] xSocket: The socket whose MSS is to be returned.
  3668. *
  3669. * @return the actual size of MSS being used or an error code.
  3670. */
  3671. BaseType_t FreeRTOS_mss( ConstSocket_t xSocket )
  3672. {
  3673. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3674. BaseType_t xReturn;
  3675. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3676. {
  3677. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3678. }
  3679. else
  3680. {
  3681. /* usCurMSS is declared as uint16_t to save space. FreeRTOS_mss()
  3682. * will often be used in signed native-size expressions cast it to
  3683. * BaseType_t. */
  3684. xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );
  3685. }
  3686. return xReturn;
  3687. }
  3688. #endif /* ipconfigUSE_TCP */
  3689. /*-----------------------------------------------------------*/
  3690. #if ( ipconfigUSE_TCP == 1 )
  3691. /**
  3692. * @brief Get the connection status. The values correspond to the members
  3693. * of the enum 'eIPTCPState_t'.
  3694. *
  3695. * @param[in] xSocket: Socket to get the connection status from.
  3696. *
  3697. * @return The connection status or an error code.
  3698. *
  3699. * @note For internal use only.
  3700. */
  3701. BaseType_t FreeRTOS_connstatus( ConstSocket_t xSocket )
  3702. {
  3703. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3704. BaseType_t xReturn;
  3705. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3706. {
  3707. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3708. }
  3709. else
  3710. {
  3711. /* Cast it to BaseType_t. */
  3712. xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );
  3713. }
  3714. return xReturn;
  3715. }
  3716. #endif /* ipconfigUSE_TCP */
  3717. /*-----------------------------------------------------------*/
  3718. #if ( ipconfigUSE_TCP == 1 )
  3719. /**
  3720. * @brief Returns the number of bytes which can be read from the RX stream buffer.
  3721. *
  3722. * @param[in] xSocket: the socket to get the number of bytes from.
  3723. *
  3724. * @return Returns the number of bytes which can be read. Or an error
  3725. * code is returned.
  3726. */
  3727. BaseType_t FreeRTOS_rx_size( ConstSocket_t xSocket )
  3728. {
  3729. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3730. BaseType_t xReturn;
  3731. if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3732. {
  3733. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3734. }
  3735. else if( pxSocket->u.xTCP.rxStream != NULL )
  3736. {
  3737. xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );
  3738. }
  3739. else
  3740. {
  3741. xReturn = 0;
  3742. }
  3743. return xReturn;
  3744. }
  3745. #endif /* ipconfigUSE_TCP */
  3746. /*-----------------------------------------------------------*/
  3747. #if 0
  3748. /**
  3749. * @brief Returns the number of packets that are stored in a UDP socket.
  3750. *
  3751. * @param[in] xSocket: the socket to get the number of bytes from.
  3752. *
  3753. * @return Returns the number of packets that are stored. Use FreeRTOS_recvfrom()
  3754. * to retrieve those packets.
  3755. */
  3756. BaseType_t FreeRTOS_udp_rx_size( Socket_t xSocket )
  3757. {
  3758. BaseType_t xReturn = 0;
  3759. const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
  3760. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
  3761. {
  3762. xReturn = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );
  3763. }
  3764. else
  3765. {
  3766. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  3767. }
  3768. return xReturn;
  3769. }
  3770. #endif /* 0 */
  3771. #if ( ipconfigUSE_TCP == 1 )
  3772. /**
  3773. * @brief Get the net status. The IP-task will print a summary of all sockets and
  3774. * their connections.
  3775. */
  3776. void FreeRTOS_netstat( void )
  3777. {
  3778. IPStackEvent_t xAskEvent;
  3779. /* Ask the IP-task to call vTCPNetStat()
  3780. * to avoid accessing xBoundTCPSocketsList
  3781. */
  3782. xAskEvent.eEventType = eTCPNetStat;
  3783. xAskEvent.pvData = ( void * ) NULL;
  3784. ( void ) xSendEventStructToIPTask( &xAskEvent, pdMS_TO_TICKS( 1000U ) );
  3785. }
  3786. #endif /* ipconfigUSE_TCP */
  3787. /*-----------------------------------------------------------*/
  3788. #if ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )
  3789. /**
  3790. * @brief Print a summary of all sockets and their connections.
  3791. */
  3792. void vTCPNetStat( void )
  3793. {
  3794. /* Show a simple listing of all created sockets and their connections */
  3795. const ListItem_t * pxIterator;
  3796. BaseType_t count = 0;
  3797. size_t uxMinimum = uxGetMinimumFreeNetworkBuffers();
  3798. size_t uxCurrent = uxGetNumberOfFreeNetworkBuffers();
  3799. if( !listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) )
  3800. {
  3801. FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
  3802. }
  3803. else
  3804. {
  3805. const ListItem_t * pxEndTCP = listGET_END_MARKER( &xBoundTCPSocketsList );
  3806. const ListItem_t * pxEndUDP = listGET_END_MARKER( &xBoundUDPSocketsList );
  3807. FreeRTOS_printf( ( "Prot Port IP-Remote : Port R/T Status Alive tmout Child\n" ) );
  3808. for( pxIterator = listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
  3809. pxIterator != pxEndTCP;
  3810. pxIterator = listGET_NEXT( pxIterator ) )
  3811. {
  3812. const FreeRTOS_Socket_t * pxSocket = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  3813. #if ( ipconfigTCP_KEEP_ALIVE == 1 )
  3814. TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;
  3815. #else
  3816. TickType_t age = 0U;
  3817. #endif
  3818. char ucChildText[ 16 ] = "";
  3819. if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
  3820. {
  3821. /* Using function "snprintf". */
  3822. const int32_t copied_len = snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",
  3823. ( int32_t ) pxSocket->u.xTCP.usChildCount,
  3824. ( int32_t ) pxSocket->u.xTCP.usBacklog );
  3825. ( void ) copied_len;
  3826. /* These should never evaluate to false since the buffers are both shorter than 5-6 characters (<=65535) */
  3827. configASSERT( copied_len >= 0 );
  3828. configASSERT( copied_len < ( int32_t ) sizeof( ucChildText ) );
  3829. }
  3830. FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",
  3831. pxSocket->usLocalPort, /* Local port on this machine */
  3832. pxSocket->u.xTCP.ulRemoteIP, /* IP address of remote machine */
  3833. pxSocket->u.xTCP.usRemotePort, /* Port on remote machine */
  3834. ( pxSocket->u.xTCP.rxStream != NULL ) ? 1 : 0,
  3835. ( pxSocket->u.xTCP.txStream != NULL ) ? 1 : 0,
  3836. FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),
  3837. ( age > 999999u ) ? 999999u : age, /* Format 'age' for printing */
  3838. pxSocket->u.xTCP.usTimeout,
  3839. ucChildText ) );
  3840. count++;
  3841. }
  3842. for( pxIterator = listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
  3843. pxIterator != pxEndUDP;
  3844. pxIterator = listGET_NEXT( pxIterator ) )
  3845. {
  3846. /* Local port on this machine */
  3847. FreeRTOS_printf( ( "UDP Port %5u\n",
  3848. FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );
  3849. count++;
  3850. }
  3851. FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %ld buffers free\n",
  3852. ( UBaseType_t ) count,
  3853. ( UBaseType_t ) uxMinimum,
  3854. ( UBaseType_t ) uxCurrent,
  3855. ( BaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );
  3856. }
  3857. }
  3858. #endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */
  3859. /*-----------------------------------------------------------*/
  3860. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  3861. /**
  3862. * @brief This internal non-blocking function will check all sockets that belong
  3863. * to a select set. The events bits of each socket will be updated, and it
  3864. * will check if an ongoing select() call must be interrupted because of an
  3865. * event has occurred.
  3866. *
  3867. * @param[in] pxSocketSet: The socket-set which is to be waited on for change.
  3868. */
  3869. void vSocketSelect( SocketSelect_t * pxSocketSet )
  3870. {
  3871. BaseType_t xRound;
  3872. EventBits_t xSocketBits, xBitsToClear;
  3873. #if ipconfigUSE_TCP == 1
  3874. BaseType_t xLastRound = 1;
  3875. #else
  3876. BaseType_t xLastRound = 0;
  3877. #endif
  3878. /* These flags will be switched on after checking the socket status. */
  3879. EventBits_t xGroupBits = 0;
  3880. for( xRound = 0; xRound <= xLastRound; xRound++ )
  3881. {
  3882. const ListItem_t * pxIterator;
  3883. const ListItem_t * pxEnd;
  3884. if( xRound == 0 )
  3885. {
  3886. pxEnd = listGET_END_MARKER( &xBoundUDPSocketsList );
  3887. }
  3888. #if ipconfigUSE_TCP == 1
  3889. else
  3890. {
  3891. pxEnd = listGET_END_MARKER( &xBoundTCPSocketsList );
  3892. }
  3893. #endif /* ipconfigUSE_TCP == 1 */
  3894. for( pxIterator = listGET_NEXT( pxEnd );
  3895. pxIterator != pxEnd;
  3896. pxIterator = listGET_NEXT( pxIterator ) )
  3897. {
  3898. FreeRTOS_Socket_t * pxSocket = ipCAST_PTR_TO_TYPE_PTR( FreeRTOS_Socket_t, listGET_LIST_ITEM_OWNER( pxIterator ) );
  3899. if( pxSocket->pxSocketSet != pxSocketSet )
  3900. {
  3901. /* Socket does not belong to this select group. */
  3902. continue;
  3903. }
  3904. xSocketBits = 0;
  3905. #if ( ipconfigUSE_TCP == 1 )
  3906. if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )
  3907. {
  3908. /* Check if the socket has already been accepted by the
  3909. * owner. If not, it is useless to return it from a
  3910. * select(). */
  3911. BaseType_t bAccepted = pdFALSE;
  3912. if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )
  3913. {
  3914. if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )
  3915. {
  3916. bAccepted = pdTRUE;
  3917. }
  3918. }
  3919. /* Is the set owner interested in READ events? */
  3920. if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != ( EventBits_t ) 0U )
  3921. {
  3922. if( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eTCP_LISTEN )
  3923. {
  3924. if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
  3925. {
  3926. xSocketBits |= ( EventBits_t ) eSELECT_READ;
  3927. }
  3928. }
  3929. else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )
  3930. {
  3931. /* This socket has the re-use flag. After connecting it turns into
  3932. * a connected socket. Set the READ event, so that accept() will be called. */
  3933. xSocketBits |= ( EventBits_t ) eSELECT_READ;
  3934. }
  3935. else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )
  3936. {
  3937. xSocketBits |= ( EventBits_t ) eSELECT_READ;
  3938. }
  3939. else
  3940. {
  3941. /* Nothing. */
  3942. }
  3943. }
  3944. /* Is the set owner interested in EXCEPTION events? */
  3945. if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_EXCEPT ) != 0U )
  3946. {
  3947. if( ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == ( uint8_t ) eCLOSED ) )
  3948. {
  3949. xSocketBits |= ( EventBits_t ) eSELECT_EXCEPT;
  3950. }
  3951. }
  3952. /* Is the set owner interested in WRITE events? */
  3953. if( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_WRITE ) != 0U )
  3954. {
  3955. BaseType_t bMatch = pdFALSE;
  3956. if( bAccepted != 0 )
  3957. {
  3958. if( FreeRTOS_tx_space( pxSocket ) > 0 )
  3959. {
  3960. bMatch = pdTRUE;
  3961. }
  3962. }
  3963. if( bMatch == pdFALSE )
  3964. {
  3965. if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&
  3966. ( pxSocket->u.xTCP.ucTCPState >= ( uint8_t ) eESTABLISHED ) &&
  3967. ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )
  3968. {
  3969. pxSocket->u.xTCP.bits.bConnPassed = pdTRUE;
  3970. bMatch = pdTRUE;
  3971. }
  3972. }
  3973. if( bMatch != pdFALSE )
  3974. {
  3975. xSocketBits |= ( EventBits_t ) eSELECT_WRITE;
  3976. }
  3977. }
  3978. }
  3979. else
  3980. #endif /* ipconfigUSE_TCP == 1 */
  3981. {
  3982. /* Select events for UDP are simpler. */
  3983. if( ( ( pxSocket->xSelectBits & ( EventBits_t ) eSELECT_READ ) != 0U ) &&
  3984. ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )
  3985. {
  3986. xSocketBits |= ( EventBits_t ) eSELECT_READ;
  3987. }
  3988. /* The WRITE and EXCEPT bits are not used for UDP */
  3989. } /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */
  3990. /* Each socket keeps its own event flags, which are looked-up
  3991. * by FreeRTOS_FD_ISSSET() */
  3992. pxSocket->xSocketBits = xSocketBits;
  3993. /* The ORed value will be used to set the bits in the event
  3994. * group. */
  3995. xGroupBits |= xSocketBits;
  3996. } /* for( pxIterator ... ) */
  3997. } /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */
  3998. xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );
  3999. /* Now set the necessary bits. */
  4000. xBitsToClear = ( xBitsToClear & ~xGroupBits ) & ( ( EventBits_t ) eSELECT_ALL );
  4001. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  4002. {
  4003. /* Maybe the socketset was signalled, but don't
  4004. * clear the 'eSELECT_INTR' bit here, as it will be used
  4005. * and cleared in FreeRTOS_select(). */
  4006. xBitsToClear &= ~( ( EventBits_t ) eSELECT_INTR );
  4007. }
  4008. #endif /* ipconfigSUPPORT_SIGNALS */
  4009. if( xBitsToClear != 0U )
  4010. {
  4011. ( void ) xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );
  4012. }
  4013. /* Now include eSELECT_CALL_IP to wakeup the caller. */
  4014. ( void ) xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | ( EventBits_t ) eSELECT_CALL_IP );
  4015. }
  4016. #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
  4017. /*-----------------------------------------------------------*/
  4018. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  4019. /**
  4020. * @brief Send a signal to the task which reads from this socket.
  4021. * The socket will receive an event of the type 'eSOCKET_INTR'.
  4022. * Any ongoing blocking API ( e.g. FreeRTOS_recv() ) will be terminated
  4023. * and return the value -pdFREERTOS_ERRNO_EINTR ( -4 ).
  4024. *
  4025. * @param[in] xSocket: The socket that will be signalled.
  4026. */
  4027. BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )
  4028. {
  4029. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  4030. BaseType_t xReturn;
  4031. if( pxSocket == NULL )
  4032. {
  4033. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  4034. }
  4035. else
  4036. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  4037. if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )
  4038. {
  4039. ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_INTR );
  4040. xReturn = 0;
  4041. }
  4042. else
  4043. #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
  4044. if( pxSocket->xEventGroup != NULL )
  4045. {
  4046. ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_INTR );
  4047. xReturn = 0;
  4048. }
  4049. else
  4050. {
  4051. xReturn = -pdFREERTOS_ERRNO_EINVAL;
  4052. }
  4053. return xReturn;
  4054. }
  4055. #endif /* ipconfigSUPPORT_SIGNALS */
  4056. /*-----------------------------------------------------------*/
  4057. #if ( ipconfigSUPPORT_SIGNALS != 0 )
  4058. /**
  4059. * @brief The same as 'FreeRTOS_SignalSocket()', except that this function should
  4060. * be called from an ISR context.
  4061. *
  4062. * @param[in] xSocket: The socket that will be signalled.
  4063. * @param[in,out] pxHigherPriorityTaskWoken: will be set to non-zero in case a higher-
  4064. * priority task has become runnable.
  4065. */
  4066. BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket,
  4067. BaseType_t * pxHigherPriorityTaskWoken )
  4068. {
  4069. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
  4070. BaseType_t xReturn;
  4071. IPStackEvent_t xEvent;
  4072. configASSERT( pxSocket != NULL );
  4073. configASSERT( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP );
  4074. configASSERT( pxSocket->xEventGroup != NULL );
  4075. xEvent.eEventType = eSocketSignalEvent;
  4076. xEvent.pvData = pxSocket;
  4077. /* The IP-task will call FreeRTOS_SignalSocket for this socket. */
  4078. xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );
  4079. return xReturn;
  4080. }
  4081. #endif /* ipconfigSUPPORT_SIGNALS */
  4082. /*-----------------------------------------------------------*/
  4083. #if 0
  4084. #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
  4085. struct pollfd
  4086. {
  4087. Socket_t fd; /* file descriptor */
  4088. EventBits_t events; /* requested events */
  4089. EventBits_t revents; /* returned events */
  4090. };
  4091. typedef BaseType_t nfds_t;
  4092. BaseType_t poll( struct pollfd * fds,
  4093. nfds_t nfds,
  4094. BaseType_t timeout );
  4095. BaseType_t poll( struct pollfd * fds,
  4096. nfds_t nfds,
  4097. BaseType_t timeout )
  4098. {
  4099. BaseType_t index;
  4100. SocketSelect_t * pxSocketSet = NULL;
  4101. BaseType_t xReturn = 0;
  4102. /* See which socket-sets have been created and bound to the sockets involved. */
  4103. for( index = 0; index < nfds; index++ )
  4104. {
  4105. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) fds[ index ].fd;
  4106. if( pxSocket->pxSocketSet != NULL )
  4107. {
  4108. if( pxSocketSet == NULL )
  4109. {
  4110. /* Use this socket-set. */
  4111. pxSocketSet = pxSocket->pxSocketSet;
  4112. xReturn = 1;
  4113. }
  4114. else if( pxSocketSet == pxSocket->pxSocketSet )
  4115. {
  4116. /* Good: associated with the same socket-set. */
  4117. }
  4118. else
  4119. {
  4120. /* More than one socket-set is found: can not do a select on 2 sets. */
  4121. xReturn = -1;
  4122. break;
  4123. }
  4124. }
  4125. }
  4126. if( xReturn == 0 )
  4127. {
  4128. /* Create a new socket-set, and attach all sockets to it. */
  4129. pxSocketSet = FreeRTOS_CreateSocketSet();
  4130. if( pxSocketSet != NULL )
  4131. {
  4132. xReturn = 1;
  4133. }
  4134. else
  4135. {
  4136. xReturn = -2;
  4137. }
  4138. /* Memory leak: when the last socket closes, there is no more reference to
  4139. * this socket-set. It should be marked as an automatic or anonymous socket-set,
  4140. * so when closing the last member, its memory will be freed. */
  4141. }
  4142. if( xReturn > 0 )
  4143. {
  4144. /* Only one socket-set is found. Connect all sockets to this socket-set. */
  4145. for( index = 0; index < nfds; index++ )
  4146. {
  4147. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) fds[ index ].fd;
  4148. EventBits_t xEventBits = fds[ index ].events;
  4149. FreeRTOS_FD_SET( pxSocket, pxSocketSet, xEventBits );
  4150. FreeRTOS_FD_CLR( pxSocket, pxSocketSet, ( EventBits_t ) ~xEventBits );
  4151. }
  4152. /* And sleep until an event happens or a time-out. */
  4153. xReturn = FreeRTOS_select( pxSocketSet, timeout );
  4154. /* Now set the return events, copying from the socked field 'xSocketBits'. */
  4155. for( index = 0; index < nfds; index++ )
  4156. {
  4157. FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) fds[ index ].fd;
  4158. fds[ index ].revents = pxSocket->xSocketBits & ( ( EventBits_t ) eSELECT_ALL );
  4159. }
  4160. }
  4161. else
  4162. {
  4163. /* -1: Sockets are connected to different socket sets. */
  4164. /* -2: FreeRTOS_CreateSocketSet() failed. */
  4165. }
  4166. return xReturn;
  4167. }
  4168. #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
  4169. #endif /* 0 */